1 //===-- sanitizer_common.cc -----------------------------------------------===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 // 10 // This file is shared between sanitizers' run-time libraries. 11 // 12 //===----------------------------------------------------------------------===// 13 14 #include "sanitizer_stacktrace_printer.h" 15 16 namespace __sanitizer { 17 18 static const char *StripFunctionName(const char *function, const char *prefix) { 19 if (!function) return nullptr; 20 if (!prefix) return function; 21 uptr prefix_len = internal_strlen(prefix); 22 if (0 == internal_strncmp(function, prefix, prefix_len)) 23 return function + prefix_len; 24 return function; 25 } 26 27 static const char kDefaultFormat[] = " #%n %p %F %L"; 28 29 void RenderFrame(InternalScopedString *buffer, const char *format, int frame_no, 30 const AddressInfo &info, bool vs_style, 31 const char *strip_path_prefix, const char *strip_func_prefix) { 32 if (0 == internal_strcmp(format, "DEFAULT")) 33 format = kDefaultFormat; 34 for (const char *p = format; *p != '\0'; p++) { 35 if (*p != '%') { 36 buffer->append("%c", *p); 37 continue; 38 } 39 p++; 40 switch (*p) { 41 case '%': 42 buffer->append("%%"); 43 break; 44 // Frame number and all fields of AddressInfo structure. 45 case 'n': 46 buffer->append("%zu", frame_no); 47 break; 48 case 'p': 49 buffer->append("0x%zx", info.address); 50 break; 51 case 'm': 52 buffer->append("%s", StripPathPrefix(info.module, strip_path_prefix)); 53 break; 54 case 'o': 55 buffer->append("0x%zx", info.module_offset); 56 break; 57 case 'f': 58 buffer->append("%s", StripFunctionName(info.function, strip_func_prefix)); 59 break; 60 case 'q': 61 buffer->append("0x%zx", info.function_offset != AddressInfo::kUnknown 62 ? info.function_offset 63 : 0x0); 64 break; 65 case 's': 66 buffer->append("%s", StripPathPrefix(info.file, strip_path_prefix)); 67 break; 68 case 'l': 69 buffer->append("%d", info.line); 70 break; 71 case 'c': 72 buffer->append("%d", info.column); 73 break; 74 // Smarter special cases. 75 case 'F': 76 // Function name and offset, if file is unknown. 77 if (info.function) { 78 buffer->append("in %s", 79 StripFunctionName(info.function, strip_func_prefix)); 80 if (!info.file && info.function_offset != AddressInfo::kUnknown) 81 buffer->append("+0x%zx", info.function_offset); 82 } 83 break; 84 case 'S': 85 // File/line information. 86 RenderSourceLocation(buffer, info.file, info.line, info.column, vs_style, 87 strip_path_prefix); 88 break; 89 case 'L': 90 // Source location, or module location. 91 if (info.file) { 92 RenderSourceLocation(buffer, info.file, info.line, info.column, 93 vs_style, strip_path_prefix); 94 } else if (info.module) { 95 RenderModuleLocation(buffer, info.module, info.module_offset, 96 strip_path_prefix); 97 } else { 98 buffer->append("(<unknown module>)"); 99 } 100 break; 101 case 'M': 102 // Module basename and offset, or PC. 103 if (info.address & kExternalPCBit) 104 {} // There PCs are not meaningful. 105 else if (info.module) 106 buffer->append("(%s+%p)", StripModuleName(info.module), 107 (void *)info.module_offset); 108 else 109 buffer->append("(%p)", (void *)info.address); 110 break; 111 default: 112 Report("Unsupported specifier in stack frame format: %c (0x%zx)!\n", *p, 113 *p); 114 Die(); 115 } 116 } 117 } 118 119 void RenderSourceLocation(InternalScopedString *buffer, const char *file, 120 int line, int column, bool vs_style, 121 const char *strip_path_prefix) { 122 if (vs_style && line > 0) { 123 buffer->append("%s(%d", StripPathPrefix(file, strip_path_prefix), line); 124 if (column > 0) 125 buffer->append(",%d", column); 126 buffer->append(")"); 127 return; 128 } 129 130 buffer->append("%s", StripPathPrefix(file, strip_path_prefix)); 131 if (line > 0) { 132 buffer->append(":%d", line); 133 if (column > 0) 134 buffer->append(":%d", column); 135 } 136 } 137 138 void RenderModuleLocation(InternalScopedString *buffer, const char *module, 139 uptr offset, const char *strip_path_prefix) { 140 buffer->append("(%s+0x%zx)", StripPathPrefix(module, strip_path_prefix), 141 offset); 142 } 143 144 } // namespace __sanitizer 145