* c-parser.c (c_parser_omp_requires): Call sorry_at on requires
[official-gcc.git] / libsanitizer / sanitizer_common / sanitizer_stacktrace_printer.cc
blob7e21c4b883fac367f332f800690e456975a14c39
1 //===-- sanitizer_common.cc -----------------------------------------------===//
2 //
3 // This file is distributed under the University of Illinois Open Source
4 // License. See LICENSE.TXT for details.
5 //
6 //===----------------------------------------------------------------------===//
7 //
8 // This file is shared between sanitizers' run-time libraries.
9 //
10 //===----------------------------------------------------------------------===//
12 #include "sanitizer_stacktrace_printer.h"
13 #include "sanitizer_file.h"
14 #include "sanitizer_fuchsia.h"
16 namespace __sanitizer {
18 // sanitizer_symbolizer_markup.cc implements these differently.
19 #if !SANITIZER_SYMBOLIZER_MARKUP
21 static const char *StripFunctionName(const char *function, const char *prefix) {
22 if (!function) return nullptr;
23 if (!prefix) return function;
24 uptr prefix_len = internal_strlen(prefix);
25 if (0 == internal_strncmp(function, prefix, prefix_len))
26 return function + prefix_len;
27 return function;
30 static const char *DemangleFunctionName(const char *function) {
31 if (!function) return nullptr;
33 // NetBSD uses indirection for old threading functions for historical reasons
34 // The mangled names are internal implementation detail and should not be
35 // exposed even in backtraces.
36 #if SANITIZER_NETBSD
37 if (!internal_strcmp(function, "__libc_mutex_init"))
38 return "pthread_mutex_init";
39 if (!internal_strcmp(function, "__libc_mutex_lock"))
40 return "pthread_mutex_lock";
41 if (!internal_strcmp(function, "__libc_mutex_trylock"))
42 return "pthread_mutex_trylock";
43 if (!internal_strcmp(function, "__libc_mutex_unlock"))
44 return "pthread_mutex_unlock";
45 if (!internal_strcmp(function, "__libc_mutex_destroy"))
46 return "pthread_mutex_destroy";
47 if (!internal_strcmp(function, "__libc_mutexattr_init"))
48 return "pthread_mutexattr_init";
49 if (!internal_strcmp(function, "__libc_mutexattr_settype"))
50 return "pthread_mutexattr_settype";
51 if (!internal_strcmp(function, "__libc_mutexattr_destroy"))
52 return "pthread_mutexattr_destroy";
53 if (!internal_strcmp(function, "__libc_cond_init"))
54 return "pthread_cond_init";
55 if (!internal_strcmp(function, "__libc_cond_signal"))
56 return "pthread_cond_signal";
57 if (!internal_strcmp(function, "__libc_cond_broadcast"))
58 return "pthread_cond_broadcast";
59 if (!internal_strcmp(function, "__libc_cond_wait"))
60 return "pthread_cond_wait";
61 if (!internal_strcmp(function, "__libc_cond_timedwait"))
62 return "pthread_cond_timedwait";
63 if (!internal_strcmp(function, "__libc_cond_destroy"))
64 return "pthread_cond_destroy";
65 if (!internal_strcmp(function, "__libc_rwlock_init"))
66 return "pthread_rwlock_init";
67 if (!internal_strcmp(function, "__libc_rwlock_rdlock"))
68 return "pthread_rwlock_rdlock";
69 if (!internal_strcmp(function, "__libc_rwlock_wrlock"))
70 return "pthread_rwlock_wrlock";
71 if (!internal_strcmp(function, "__libc_rwlock_tryrdlock"))
72 return "pthread_rwlock_tryrdlock";
73 if (!internal_strcmp(function, "__libc_rwlock_trywrlock"))
74 return "pthread_rwlock_trywrlock";
75 if (!internal_strcmp(function, "__libc_rwlock_unlock"))
76 return "pthread_rwlock_unlock";
77 if (!internal_strcmp(function, "__libc_rwlock_destroy"))
78 return "pthread_rwlock_destroy";
79 if (!internal_strcmp(function, "__libc_thr_keycreate"))
80 return "pthread_key_create";
81 if (!internal_strcmp(function, "__libc_thr_setspecific"))
82 return "pthread_setspecific";
83 if (!internal_strcmp(function, "__libc_thr_getspecific"))
84 return "pthread_getspecific";
85 if (!internal_strcmp(function, "__libc_thr_keydelete"))
86 return "pthread_key_delete";
87 if (!internal_strcmp(function, "__libc_thr_once"))
88 return "pthread_once";
89 if (!internal_strcmp(function, "__libc_thr_self"))
90 return "pthread_self";
91 if (!internal_strcmp(function, "__libc_thr_exit"))
92 return "pthread_exit";
93 if (!internal_strcmp(function, "__libc_thr_setcancelstate"))
94 return "pthread_setcancelstate";
95 if (!internal_strcmp(function, "__libc_thr_equal"))
96 return "pthread_equal";
97 if (!internal_strcmp(function, "__libc_thr_curcpu"))
98 return "pthread_curcpu_np";
99 #endif
101 return function;
104 static const char kDefaultFormat[] = " #%n %p %F %L";
106 void RenderFrame(InternalScopedString *buffer, const char *format, int frame_no,
107 const AddressInfo &info, bool vs_style,
108 const char *strip_path_prefix, const char *strip_func_prefix) {
109 if (0 == internal_strcmp(format, "DEFAULT"))
110 format = kDefaultFormat;
111 for (const char *p = format; *p != '\0'; p++) {
112 if (*p != '%') {
113 buffer->append("%c", *p);
114 continue;
116 p++;
117 switch (*p) {
118 case '%':
119 buffer->append("%%");
120 break;
121 // Frame number and all fields of AddressInfo structure.
122 case 'n':
123 buffer->append("%zu", frame_no);
124 break;
125 case 'p':
126 buffer->append("0x%zx", info.address);
127 break;
128 case 'm':
129 buffer->append("%s", StripPathPrefix(info.module, strip_path_prefix));
130 break;
131 case 'o':
132 buffer->append("0x%zx", info.module_offset);
133 break;
134 case 'f':
135 buffer->append("%s",
136 DemangleFunctionName(
137 StripFunctionName(info.function, strip_func_prefix)));
138 break;
139 case 'q':
140 buffer->append("0x%zx", info.function_offset != AddressInfo::kUnknown
141 ? info.function_offset
142 : 0x0);
143 break;
144 case 's':
145 buffer->append("%s", StripPathPrefix(info.file, strip_path_prefix));
146 break;
147 case 'l':
148 buffer->append("%d", info.line);
149 break;
150 case 'c':
151 buffer->append("%d", info.column);
152 break;
153 // Smarter special cases.
154 case 'F':
155 // Function name and offset, if file is unknown.
156 if (info.function) {
157 buffer->append("in %s",
158 DemangleFunctionName(
159 StripFunctionName(info.function, strip_func_prefix)));
160 if (!info.file && info.function_offset != AddressInfo::kUnknown)
161 buffer->append("+0x%zx", info.function_offset);
163 break;
164 case 'S':
165 // File/line information.
166 RenderSourceLocation(buffer, info.file, info.line, info.column, vs_style,
167 strip_path_prefix);
168 break;
169 case 'L':
170 // Source location, or module location.
171 if (info.file) {
172 RenderSourceLocation(buffer, info.file, info.line, info.column,
173 vs_style, strip_path_prefix);
174 } else if (info.module) {
175 RenderModuleLocation(buffer, info.module, info.module_offset,
176 info.module_arch, strip_path_prefix);
177 } else {
178 buffer->append("(<unknown module>)");
180 break;
181 case 'M':
182 // Module basename and offset, or PC.
183 if (info.address & kExternalPCBit)
184 {} // There PCs are not meaningful.
185 else if (info.module)
186 // Always strip the module name for %M.
187 RenderModuleLocation(buffer, StripModuleName(info.module),
188 info.module_offset, info.module_arch, "");
189 else
190 buffer->append("(%p)", (void *)info.address);
191 break;
192 default:
193 Report("Unsupported specifier in stack frame format: %c (0x%zx)!\n", *p,
194 *p);
195 Die();
200 void RenderData(InternalScopedString *buffer, const char *format,
201 const DataInfo *DI, const char *strip_path_prefix) {
202 for (const char *p = format; *p != '\0'; p++) {
203 if (*p != '%') {
204 buffer->append("%c", *p);
205 continue;
207 p++;
208 switch (*p) {
209 case '%':
210 buffer->append("%%");
211 break;
212 case 's':
213 buffer->append("%s", StripPathPrefix(DI->file, strip_path_prefix));
214 break;
215 case 'l':
216 buffer->append("%d", DI->line);
217 break;
218 case 'g':
219 buffer->append("%s", DI->name);
220 break;
221 default:
222 Report("Unsupported specifier in stack frame format: %c (0x%zx)!\n", *p,
223 *p);
224 Die();
229 #endif // !SANITIZER_SYMBOLIZER_MARKUP
231 void RenderSourceLocation(InternalScopedString *buffer, const char *file,
232 int line, int column, bool vs_style,
233 const char *strip_path_prefix) {
234 if (vs_style && line > 0) {
235 buffer->append("%s(%d", StripPathPrefix(file, strip_path_prefix), line);
236 if (column > 0)
237 buffer->append(",%d", column);
238 buffer->append(")");
239 return;
242 buffer->append("%s", StripPathPrefix(file, strip_path_prefix));
243 if (line > 0) {
244 buffer->append(":%d", line);
245 if (column > 0)
246 buffer->append(":%d", column);
250 void RenderModuleLocation(InternalScopedString *buffer, const char *module,
251 uptr offset, ModuleArch arch,
252 const char *strip_path_prefix) {
253 buffer->append("(%s", StripPathPrefix(module, strip_path_prefix));
254 if (arch != kModuleArchUnknown) {
255 buffer->append(":%s", ModuleArchToString(arch));
257 buffer->append("+0x%zx)", offset);
260 } // namespace __sanitizer