forked from OSchip/llvm-project
				
			
		
			
				
	
	
		
			133 lines
		
	
	
		
			4.3 KiB
		
	
	
	
		
			C++
		
	
	
	
			
		
		
	
	
			133 lines
		
	
	
		
			4.3 KiB
		
	
	
	
		
			C++
		
	
	
	
| //===-- sanitizer_common.cc -----------------------------------------------===//
 | |
| //
 | |
| //                     The LLVM Compiler Infrastructure
 | |
| //
 | |
| // This file is distributed under the University of Illinois Open Source
 | |
| // License. See LICENSE.TXT for details.
 | |
| //
 | |
| //===----------------------------------------------------------------------===//
 | |
| //
 | |
| // This file is shared between sanitizers' run-time libraries.
 | |
| //
 | |
| //===----------------------------------------------------------------------===//
 | |
| #include "sanitizer_stacktrace_printer.h"
 | |
| 
 | |
| namespace __sanitizer {
 | |
| 
 | |
| static const char *StripFunctionName(const char *function, const char *prefix) {
 | |
|   if (function == 0) return 0;
 | |
|   if (prefix == 0) return function;
 | |
|   uptr prefix_len = internal_strlen(prefix);
 | |
|   if (0 == internal_strncmp(function, prefix, prefix_len))
 | |
|     return function + prefix_len;
 | |
|   return function;
 | |
| }
 | |
| 
 | |
| static const char kDefaultFormat[] = "    #%n %p %F %L";
 | |
| 
 | |
| void RenderFrame(InternalScopedString *buffer, const char *format, int frame_no,
 | |
|                  const AddressInfo &info, const char *strip_path_prefix,
 | |
|                  const char *strip_func_prefix) {
 | |
|   if (0 == internal_strcmp(format, "DEFAULT"))
 | |
|     format = kDefaultFormat;
 | |
|   for (const char *p = format; *p != '\0'; p++) {
 | |
|     if (*p != '%') {
 | |
|       buffer->append("%c", *p);
 | |
|       continue;
 | |
|     }
 | |
|     p++;
 | |
|     switch (*p) {
 | |
|     case '%':
 | |
|       buffer->append("%%");
 | |
|       break;
 | |
|     // Frame number and all fields of AddressInfo structure.
 | |
|     case 'n':
 | |
|       buffer->append("%zu", frame_no);
 | |
|       break;
 | |
|     case 'p':
 | |
|       buffer->append("0x%zx", info.address);
 | |
|       break;
 | |
|     case 'm':
 | |
|       buffer->append("%s", StripPathPrefix(info.module, strip_path_prefix));
 | |
|       break;
 | |
|     case 'o':
 | |
|       buffer->append("0x%zx", info.module_offset);
 | |
|       break;
 | |
|     case 'f':
 | |
|       buffer->append("%s", StripFunctionName(info.function, strip_func_prefix));
 | |
|       break;
 | |
|     case 'q':
 | |
|       buffer->append("0x%zx", info.function_offset != AddressInfo::kUnknown
 | |
|                                   ? info.function_offset
 | |
|                                   : 0x0);
 | |
|       break;
 | |
|     case 's':
 | |
|       buffer->append("%s", StripPathPrefix(info.file, strip_path_prefix));
 | |
|       break;
 | |
|     case 'l':
 | |
|       buffer->append("%d", info.line);
 | |
|       break;
 | |
|     case 'c':
 | |
|       buffer->append("%d", info.column);
 | |
|       break;
 | |
|     // Smarter special cases.
 | |
|     case 'F':
 | |
|       // Function name and offset, if file is unknown.
 | |
|       if (info.function) {
 | |
|         buffer->append("in %s",
 | |
|                        StripFunctionName(info.function, strip_func_prefix));
 | |
|         if (!info.file && info.function_offset != AddressInfo::kUnknown)
 | |
|           buffer->append("+0x%zx", info.function_offset);
 | |
|       }
 | |
|       break;
 | |
|     case 'S':
 | |
|       // File/line information.
 | |
|       RenderSourceLocation(buffer, info.file, info.line, info.column,
 | |
|                            strip_path_prefix);
 | |
|       break;
 | |
|     case 'L':
 | |
|       // Source location, or module location.
 | |
|       if (info.file) {
 | |
|         RenderSourceLocation(buffer, info.file, info.line, info.column,
 | |
|                              strip_path_prefix);
 | |
|       } else if (info.module) {
 | |
|         RenderModuleLocation(buffer, info.module, info.module_offset,
 | |
|                              strip_path_prefix);
 | |
|       } else {
 | |
|         buffer->append("(<unknown module>)");
 | |
|       }
 | |
|       break;
 | |
|     case 'M':
 | |
|       // Module basename and offset, or PC.
 | |
|       if (info.module)
 | |
|         buffer->append("(%s+%p)", StripModuleName(info.module),
 | |
|                        (void *)info.module_offset);
 | |
|       else
 | |
|         buffer->append("(%p)", (void *)info.address);
 | |
|       break;
 | |
|     default:
 | |
|       Report("Unsupported specifier in stack frame format: %c (0x%zx)!\n",
 | |
|              *p, *p);
 | |
|       Die();
 | |
|     }
 | |
|   }
 | |
| }
 | |
| 
 | |
| void RenderSourceLocation(InternalScopedString *buffer, const char *file,
 | |
|                           int line, int column, const char *strip_path_prefix) {
 | |
|   buffer->append("%s", StripPathPrefix(file, strip_path_prefix));
 | |
|   if (line > 0) {
 | |
|     buffer->append(":%d", line);
 | |
|     if (column > 0)
 | |
|       buffer->append(":%d", column);
 | |
|   }
 | |
| }
 | |
| 
 | |
| void RenderModuleLocation(InternalScopedString *buffer, const char *module,
 | |
|                           uptr offset, const char *strip_path_prefix) {
 | |
|   buffer->append("(%s+0x%zx)", StripPathPrefix(module, strip_path_prefix),
 | |
|                  offset);
 | |
| }
 | |
| 
 | |
| }  // namespace __sanitizer
 |