blob: 669b0ba282658af197de8b6cc37af4f900df656a [file] [log] [blame]
Stephen Hines6d186232014-11-26 17:56:19 -08001//===-- 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 Nainar799172d2016-03-03 15:50:30 -080013
Stephen Hines6d186232014-11-26 17:56:19 -080014#include "sanitizer_stacktrace_printer.h"
15
16namespace __sanitizer {
17
18static const char *StripFunctionName(const char *function, const char *prefix) {
Pirama Arumuga Nainar799172d2016-03-03 15:50:30 -080019 if (!function) return nullptr;
20 if (!prefix) return function;
Stephen Hines6d186232014-11-26 17:56:19 -080021 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
27static const char kDefaultFormat[] = " #%n %p %F %L";
28
29void RenderFrame(InternalScopedString *buffer, const char *format, int frame_no,
Pirama Arumuga Nainarcdce50b2015-07-01 12:26:56 -070030 const AddressInfo &info, bool vs_style,
31 const char *strip_path_prefix, const char *strip_func_prefix) {
Stephen Hines6d186232014-11-26 17:56:19 -080032 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 Nainarcdce50b2015-07-01 12:26:56 -070086 RenderSourceLocation(buffer, info.file, info.line, info.column, vs_style,
Stephen Hines6d186232014-11-26 17:56:19 -080087 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 Nainarcdce50b2015-07-01 12:26:56 -070093 vs_style, strip_path_prefix);
Stephen Hines6d186232014-11-26 17:56:19 -080094 } 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 Nainar799172d2016-03-03 15:50:30 -0800103 if (info.address & kExternalPCBit)
104 {} // There PCs are not meaningful.
105 else if (info.module)
Stephen Hines6d186232014-11-26 17:56:19 -0800106 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 Nainarcdce50b2015-07-01 12:26:56 -0700112 Report("Unsupported specifier in stack frame format: %c (0x%zx)!\n", *p,
113 *p);
Stephen Hines6d186232014-11-26 17:56:19 -0800114 Die();
115 }
116 }
117}
118
119void RenderSourceLocation(InternalScopedString *buffer, const char *file,
Pirama Arumuga Nainarcdce50b2015-07-01 12:26:56 -0700120 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 Hines6d186232014-11-26 17:56:19 -0800130 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
138void 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 Nainar799172d2016-03-03 15:50:30 -0800144} // namespace __sanitizer