1 //===-- sanitizer_common.cc -----------------------------------------------===//
3 // This file is distributed under the University of Illinois Open Source
4 // License. See LICENSE.TXT for details.
6 //===----------------------------------------------------------------------===//
8 // This file is shared between sanitizers' run-time libraries.
10 //===----------------------------------------------------------------------===//
12 #include "sanitizer_stacktrace_printer.h"
14 namespace __sanitizer
{
16 static const char *StripFunctionName(const char *function
, const char *prefix
) {
17 if (!function
) return nullptr;
18 if (!prefix
) return function
;
19 uptr prefix_len
= internal_strlen(prefix
);
20 if (0 == internal_strncmp(function
, prefix
, prefix_len
))
21 return function
+ prefix_len
;
25 static const char kDefaultFormat
[] = " #%n %p %F %L";
27 void RenderFrame(InternalScopedString
*buffer
, const char *format
, int frame_no
,
28 const AddressInfo
&info
, bool vs_style
,
29 const char *strip_path_prefix
, const char *strip_func_prefix
) {
30 if (0 == internal_strcmp(format
, "DEFAULT"))
31 format
= kDefaultFormat
;
32 for (const char *p
= format
; *p
!= '\0'; p
++) {
34 buffer
->append("%c", *p
);
42 // Frame number and all fields of AddressInfo structure.
44 buffer
->append("%zu", frame_no
);
47 buffer
->append("0x%zx", info
.address
);
50 buffer
->append("%s", StripPathPrefix(info
.module
, strip_path_prefix
));
53 buffer
->append("0x%zx", info
.module_offset
);
56 buffer
->append("%s", StripFunctionName(info
.function
, strip_func_prefix
));
59 buffer
->append("0x%zx", info
.function_offset
!= AddressInfo::kUnknown
60 ? info
.function_offset
64 buffer
->append("%s", StripPathPrefix(info
.file
, strip_path_prefix
));
67 buffer
->append("%d", info
.line
);
70 buffer
->append("%d", info
.column
);
72 // Smarter special cases.
74 // Function name and offset, if file is unknown.
76 buffer
->append("in %s",
77 StripFunctionName(info
.function
, strip_func_prefix
));
78 if (!info
.file
&& info
.function_offset
!= AddressInfo::kUnknown
)
79 buffer
->append("+0x%zx", info
.function_offset
);
83 // File/line information.
84 RenderSourceLocation(buffer
, info
.file
, info
.line
, info
.column
, vs_style
,
88 // Source location, or module location.
90 RenderSourceLocation(buffer
, info
.file
, info
.line
, info
.column
,
91 vs_style
, strip_path_prefix
);
92 } else if (info
.module
) {
93 RenderModuleLocation(buffer
, info
.module
, info
.module_offset
,
96 buffer
->append("(<unknown module>)");
100 // Module basename and offset, or PC.
101 if (info
.address
& kExternalPCBit
)
102 {} // There PCs are not meaningful.
103 else if (info
.module
)
104 buffer
->append("(%s+%p)", StripModuleName(info
.module
),
105 (void *)info
.module_offset
);
107 buffer
->append("(%p)", (void *)info
.address
);
110 Report("Unsupported specifier in stack frame format: %c (0x%zx)!\n", *p
,
117 void RenderData(InternalScopedString
*buffer
, const char *format
,
118 const DataInfo
*DI
, const char *strip_path_prefix
) {
119 for (const char *p
= format
; *p
!= '\0'; p
++) {
121 buffer
->append("%c", *p
);
127 buffer
->append("%%");
130 buffer
->append("%s", StripPathPrefix(DI
->file
, strip_path_prefix
));
133 buffer
->append("%d", DI
->line
);
136 buffer
->append("%s", DI
->name
);
139 Report("Unsupported specifier in stack frame format: %c (0x%zx)!\n", *p
,
146 void RenderSourceLocation(InternalScopedString
*buffer
, const char *file
,
147 int line
, int column
, bool vs_style
,
148 const char *strip_path_prefix
) {
149 if (vs_style
&& line
> 0) {
150 buffer
->append("%s(%d", StripPathPrefix(file
, strip_path_prefix
), line
);
152 buffer
->append(",%d", column
);
157 buffer
->append("%s", StripPathPrefix(file
, strip_path_prefix
));
159 buffer
->append(":%d", line
);
161 buffer
->append(":%d", column
);
165 void RenderModuleLocation(InternalScopedString
*buffer
, const char *module
,
166 uptr offset
, const char *strip_path_prefix
) {
167 buffer
->append("(%s+0x%zx)", StripPathPrefix(module
, strip_path_prefix
),
171 } // namespace __sanitizer