xref: /netbsd-src/external/gpl3/gcc.old/dist/libsanitizer/sanitizer_common/sanitizer_stacktrace_printer.cc (revision 796c32c94f6e154afc9de0f63da35c91bb739b45)
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"
12 
13 namespace __sanitizer {
14 
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;
22 }
23 
24 static const char kDefaultFormat[] = "    #%n %p %F %L";
25 
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;
35     }
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);
79       }
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>)");
96       }
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();
110     }
111   }
112 }
113 
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);
121   }
122 }
123 
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);
128 }
129 
130 }  // namespace __sanitizer
131