blob: d56e47e0727662f2863d821729ebc7bd6e02ea25 [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//===----------------------------------------------------------------------===//
13#include "sanitizer_stacktrace_printer.h"
14
15namespace __sanitizer {
16
17static const char *StripFunctionName(const char *function, const char *prefix) {
18 if (function == 0) return 0;
19 if (prefix == 0) return function;
20 uptr prefix_len = internal_strlen(prefix);
21 if (0 == internal_strncmp(function, prefix, prefix_len))
22 return function + prefix_len;
23 return function;
24}
25
26static const char kDefaultFormat[] = " #%n %p %F %L";
27
28void RenderFrame(InternalScopedString *buffer, const char *format, int frame_no,
Pirama Arumuga Nainarcdce50b2015-07-01 12:26:56 -070029 const AddressInfo &info, bool vs_style,
30 const char *strip_path_prefix, const char *strip_func_prefix) {
Stephen Hines6d186232014-11-26 17:56:19 -080031 if (0 == internal_strcmp(format, "DEFAULT"))
32 format = kDefaultFormat;
33 for (const char *p = format; *p != '\0'; p++) {
34 if (*p != '%') {
35 buffer->append("%c", *p);
36 continue;
37 }
38 p++;
39 switch (*p) {
40 case '%':
41 buffer->append("%%");
42 break;
43 // Frame number and all fields of AddressInfo structure.
44 case 'n':
45 buffer->append("%zu", frame_no);
46 break;
47 case 'p':
48 buffer->append("0x%zx", info.address);
49 break;
50 case 'm':
51 buffer->append("%s", StripPathPrefix(info.module, strip_path_prefix));
52 break;
53 case 'o':
54 buffer->append("0x%zx", info.module_offset);
55 break;
56 case 'f':
57 buffer->append("%s", StripFunctionName(info.function, strip_func_prefix));
58 break;
59 case 'q':
60 buffer->append("0x%zx", info.function_offset != AddressInfo::kUnknown
61 ? info.function_offset
62 : 0x0);
63 break;
64 case 's':
65 buffer->append("%s", StripPathPrefix(info.file, strip_path_prefix));
66 break;
67 case 'l':
68 buffer->append("%d", info.line);
69 break;
70 case 'c':
71 buffer->append("%d", info.column);
72 break;
73 // Smarter special cases.
74 case 'F':
75 // Function name and offset, if file is unknown.
76 if (info.function) {
77 buffer->append("in %s",
78 StripFunctionName(info.function, strip_func_prefix));
79 if (!info.file && info.function_offset != AddressInfo::kUnknown)
80 buffer->append("+0x%zx", info.function_offset);
81 }
82 break;
83 case 'S':
84 // File/line information.
Pirama Arumuga Nainarcdce50b2015-07-01 12:26:56 -070085 RenderSourceLocation(buffer, info.file, info.line, info.column, vs_style,
Stephen Hines6d186232014-11-26 17:56:19 -080086 strip_path_prefix);
87 break;
88 case 'L':
89 // Source location, or module location.
90 if (info.file) {
91 RenderSourceLocation(buffer, info.file, info.line, info.column,
Pirama Arumuga Nainarcdce50b2015-07-01 12:26:56 -070092 vs_style, strip_path_prefix);
Stephen Hines6d186232014-11-26 17:56:19 -080093 } else if (info.module) {
94 RenderModuleLocation(buffer, info.module, info.module_offset,
95 strip_path_prefix);
96 } else {
97 buffer->append("(<unknown module>)");
98 }
99 break;
100 case 'M':
101 // Module basename and offset, or PC.
102 if (info.module)
103 buffer->append("(%s+%p)", StripModuleName(info.module),
104 (void *)info.module_offset);
105 else
106 buffer->append("(%p)", (void *)info.address);
107 break;
108 default:
Pirama Arumuga Nainarcdce50b2015-07-01 12:26:56 -0700109 Report("Unsupported specifier in stack frame format: %c (0x%zx)!\n", *p,
110 *p);
Stephen Hines6d186232014-11-26 17:56:19 -0800111 Die();
112 }
113 }
114}
115
116void RenderSourceLocation(InternalScopedString *buffer, const char *file,
Pirama Arumuga Nainarcdce50b2015-07-01 12:26:56 -0700117 int line, int column, bool vs_style,
118 const char *strip_path_prefix) {
119 if (vs_style && line > 0) {
120 buffer->append("%s(%d", StripPathPrefix(file, strip_path_prefix), line);
121 if (column > 0)
122 buffer->append(",%d", column);
123 buffer->append(")");
124 return;
125 }
126
Stephen Hines6d186232014-11-26 17:56:19 -0800127 buffer->append("%s", StripPathPrefix(file, strip_path_prefix));
128 if (line > 0) {
129 buffer->append(":%d", line);
130 if (column > 0)
131 buffer->append(":%d", column);
132 }
133}
134
135void RenderModuleLocation(InternalScopedString *buffer, const char *module,
136 uptr offset, const char *strip_path_prefix) {
137 buffer->append("(%s+0x%zx)", StripPathPrefix(module, strip_path_prefix),
138 offset);
139}
140
141} // namespace __sanitizer