Stephen Hines | 6d18623 | 2014-11-26 17:56:19 -0800 | [diff] [blame] | 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 | //===----------------------------------------------------------------------===// |
Pirama Arumuga Nainar | 799172d | 2016-03-03 15:50:30 -0800 | [diff] [blame^] | 13 | |
Stephen Hines | 6d18623 | 2014-11-26 17:56:19 -0800 | [diff] [blame] | 14 | #include "sanitizer_stacktrace_printer.h" |
| 15 | |
| 16 | namespace __sanitizer { |
| 17 | |
| 18 | static const char *StripFunctionName(const char *function, const char *prefix) { |
Pirama Arumuga Nainar | 799172d | 2016-03-03 15:50:30 -0800 | [diff] [blame^] | 19 | if (!function) return nullptr; |
| 20 | if (!prefix) return function; |
Stephen Hines | 6d18623 | 2014-11-26 17:56:19 -0800 | [diff] [blame] | 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, |
Pirama Arumuga Nainar | cdce50b | 2015-07-01 12:26:56 -0700 | [diff] [blame] | 30 | const AddressInfo &info, bool vs_style, |
| 31 | const char *strip_path_prefix, const char *strip_func_prefix) { |
Stephen Hines | 6d18623 | 2014-11-26 17:56:19 -0800 | [diff] [blame] | 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. |
Pirama Arumuga Nainar | cdce50b | 2015-07-01 12:26:56 -0700 | [diff] [blame] | 86 | RenderSourceLocation(buffer, info.file, info.line, info.column, vs_style, |
Stephen Hines | 6d18623 | 2014-11-26 17:56:19 -0800 | [diff] [blame] | 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, |
Pirama Arumuga Nainar | cdce50b | 2015-07-01 12:26:56 -0700 | [diff] [blame] | 93 | vs_style, strip_path_prefix); |
Stephen Hines | 6d18623 | 2014-11-26 17:56:19 -0800 | [diff] [blame] | 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. |
Pirama Arumuga Nainar | 799172d | 2016-03-03 15:50:30 -0800 | [diff] [blame^] | 103 | if (info.address & kExternalPCBit) |
| 104 | {} // There PCs are not meaningful. |
| 105 | else if (info.module) |
Stephen Hines | 6d18623 | 2014-11-26 17:56:19 -0800 | [diff] [blame] | 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: |
Pirama Arumuga Nainar | cdce50b | 2015-07-01 12:26:56 -0700 | [diff] [blame] | 112 | Report("Unsupported specifier in stack frame format: %c (0x%zx)!\n", *p, |
| 113 | *p); |
Stephen Hines | 6d18623 | 2014-11-26 17:56:19 -0800 | [diff] [blame] | 114 | Die(); |
| 115 | } |
| 116 | } |
| 117 | } |
| 118 | |
| 119 | void RenderSourceLocation(InternalScopedString *buffer, const char *file, |
Pirama Arumuga Nainar | cdce50b | 2015-07-01 12:26:56 -0700 | [diff] [blame] | 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 | |
Stephen Hines | 6d18623 | 2014-11-26 17:56:19 -0800 | [diff] [blame] | 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 | |
Pirama Arumuga Nainar | 799172d | 2016-03-03 15:50:30 -0800 | [diff] [blame^] | 144 | } // namespace __sanitizer |