gcc/
[official-gcc.git] / libsanitizer / sanitizer_common / sanitizer_stacktrace_printer.cc
blob300b4904c54bee33402e9df8ca7d4daff53648de
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 //===----------------------------------------------------------------------===//
11 #include "sanitizer_stacktrace_printer.h"
13 namespace __sanitizer {
15 static const char *StripFunctionName(const char *function, const char *prefix) {
16 if (function == 0) return 0;
17 if (prefix == 0) return function;
18 uptr prefix_len = internal_strlen(prefix);
19 if (0 == internal_strncmp(function, prefix, prefix_len))
20 return function + prefix_len;
21 return function;
24 static const char kDefaultFormat[] = " #%n %p %F %L";
26 void RenderFrame(InternalScopedString *buffer, const char *format, int frame_no,
27 const AddressInfo &info, const char *strip_path_prefix,
28 const char *strip_func_prefix) {
29 if (0 == internal_strcmp(format, "DEFAULT"))
30 format = kDefaultFormat;
31 for (const char *p = format; *p != '\0'; p++) {
32 if (*p != '%') {
33 buffer->append("%c", *p);
34 continue;
36 p++;
37 switch (*p) {
38 case '%':
39 buffer->append("%%");
40 break;
41 // Frame number and all fields of AddressInfo structure.
42 case 'n':
43 buffer->append("%zu", frame_no);
44 break;
45 case 'p':
46 buffer->append("0x%zx", info.address);
47 break;
48 case 'm':
49 buffer->append("%s", StripPathPrefix(info.module, strip_path_prefix));
50 break;
51 case 'o':
52 buffer->append("0x%zx", info.module_offset);
53 break;
54 case 'f':
55 buffer->append("%s", StripFunctionName(info.function, strip_func_prefix));
56 break;
57 case 'q':
58 buffer->append("0x%zx", info.function_offset != AddressInfo::kUnknown
59 ? info.function_offset
60 : 0x0);
61 break;
62 case 's':
63 buffer->append("%s", StripPathPrefix(info.file, strip_path_prefix));
64 break;
65 case 'l':
66 buffer->append("%d", info.line);
67 break;
68 case 'c':
69 buffer->append("%d", info.column);
70 break;
71 // Smarter special cases.
72 case 'F':
73 // Function name and offset, if file is unknown.
74 if (info.function) {
75 buffer->append("in %s",
76 StripFunctionName(info.function, strip_func_prefix));
77 if (!info.file && info.function_offset != AddressInfo::kUnknown)
78 buffer->append("+0x%zx", info.function_offset);
80 break;
81 case 'S':
82 // File/line information.
83 RenderSourceLocation(buffer, info.file, info.line, info.column,
84 strip_path_prefix);
85 break;
86 case 'L':
87 // Source location, or module location.
88 if (info.file) {
89 RenderSourceLocation(buffer, info.file, info.line, info.column,
90 strip_path_prefix);
91 } else if (info.module) {
92 RenderModuleLocation(buffer, info.module, info.module_offset,
93 strip_path_prefix);
94 } else {
95 buffer->append("(<unknown module>)");
97 break;
98 case 'M':
99 // Module basename and offset, or PC.
100 if (info.module)
101 buffer->append("(%s+%p)", StripModuleName(info.module),
102 (void *)info.module_offset);
103 else
104 buffer->append("(%p)", (void *)info.address);
105 break;
106 default:
107 Report("Unsupported specifier in stack frame format: %c (0x%zx)!\n",
108 *p, *p);
109 Die();
114 void RenderSourceLocation(InternalScopedString *buffer, const char *file,
115 int line, int column, const char *strip_path_prefix) {
116 buffer->append("%s", StripPathPrefix(file, strip_path_prefix));
117 if (line > 0) {
118 buffer->append(":%d", line);
119 if (column > 0)
120 buffer->append(":%d", column);
124 void RenderModuleLocation(InternalScopedString *buffer, const char *module,
125 uptr offset, const char *strip_path_prefix) {
126 buffer->append("(%s+0x%zx)", StripPathPrefix(module, strip_path_prefix),
127 offset);
130 } // namespace __sanitizer