1 //===-- sanitizer_stacktrace_libcdep.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 AddressSanitizer and ThreadSanitizer
10 //===----------------------------------------------------------------------===//
12 #include "sanitizer_common.h"
13 #include "sanitizer_placement_new.h"
14 #include "sanitizer_stacktrace.h"
15 #include "sanitizer_stacktrace_printer.h"
16 #include "sanitizer_symbolizer.h"
18 namespace __sanitizer
{
20 void StackTrace::Print() const {
21 if (trace
== nullptr || size
== 0) {
22 Printf(" <empty stack>\n\n");
25 InternalScopedString
frame_desc(GetPageSizeCached() * 2);
26 InternalScopedString
dedup_token(GetPageSizeCached());
27 int dedup_frames
= common_flags()->dedup_token_length
;
29 for (uptr i
= 0; i
< size
&& trace
[i
]; i
++) {
30 // PCs in stack traces are actually the return addresses, that is,
31 // addresses of the next instructions after the call.
32 uptr pc
= GetPreviousInstructionPc(trace
[i
]);
33 SymbolizedStack
*frames
= Symbolizer::GetOrInit()->SymbolizePC(pc
);
35 for (SymbolizedStack
*cur
= frames
; cur
; cur
= cur
->next
) {
37 RenderFrame(&frame_desc
, common_flags()->stack_trace_format
, frame_num
++,
38 cur
->info
, common_flags()->symbolize_vs_style
,
39 common_flags()->strip_path_prefix
);
40 Printf("%s\n", frame_desc
.data());
41 if (dedup_frames
-- > 0) {
42 if (dedup_token
.length())
43 dedup_token
.append("--");
44 if (cur
->info
.function
!= nullptr)
45 dedup_token
.append(cur
->info
.function
);
50 // Always print a trailing empty line after stack trace.
52 if (dedup_token
.length())
53 Printf("DEDUP_TOKEN: %s\n", dedup_token
.data());
56 void BufferedStackTrace::Unwind(u32 max_depth
, uptr pc
, uptr bp
, void *context
,
57 uptr stack_top
, uptr stack_bottom
,
58 bool request_fast_unwind
) {
59 top_frame_bp
= (max_depth
> 0) ? bp
: 0;
60 // Avoid doing any work for small max_depth.
70 if (!WillUseFastUnwind(request_fast_unwind
)) {
71 #if SANITIZER_CAN_SLOW_UNWIND
73 SlowUnwindStackWithContext(pc
, context
, max_depth
);
75 SlowUnwindStack(pc
, max_depth
);
77 UNREACHABLE("slow unwind requested but not available");
80 FastUnwindStack(pc
, bp
, stack_top
, stack_bottom
, max_depth
);
84 static int GetModuleAndOffsetForPc(uptr pc
, char *module_name
,
85 uptr module_name_len
, uptr
*pc_offset
) {
86 const char *found_module_name
= nullptr;
87 bool ok
= Symbolizer::GetOrInit()->GetModuleNameAndOffsetForPC(
88 pc
, &found_module_name
, pc_offset
);
90 if (!ok
) return false;
92 if (module_name
&& module_name_len
) {
93 internal_strncpy(module_name
, found_module_name
, module_name_len
);
94 module_name
[module_name_len
- 1] = '\x00';
99 } // namespace __sanitizer
100 using namespace __sanitizer
;
103 SANITIZER_INTERFACE_ATTRIBUTE
104 void __sanitizer_symbolize_pc(uptr pc
, const char *fmt
, char *out_buf
,
106 if (!out_buf_size
) return;
107 pc
= StackTrace::GetPreviousInstructionPc(pc
);
108 SymbolizedStack
*frame
= Symbolizer::GetOrInit()->SymbolizePC(pc
);
110 internal_strncpy(out_buf
, "<can't symbolize>", out_buf_size
);
111 out_buf
[out_buf_size
- 1] = 0;
114 InternalScopedString
frame_desc(GetPageSizeCached());
115 RenderFrame(&frame_desc
, fmt
, 0, frame
->info
,
116 common_flags()->symbolize_vs_style
,
117 common_flags()->strip_path_prefix
);
118 internal_strncpy(out_buf
, frame_desc
.data(), out_buf_size
);
119 out_buf
[out_buf_size
- 1] = 0;
122 SANITIZER_INTERFACE_ATTRIBUTE
123 void __sanitizer_symbolize_global(uptr data_addr
, const char *fmt
,
124 char *out_buf
, uptr out_buf_size
) {
125 if (!out_buf_size
) return;
128 if (!Symbolizer::GetOrInit()->SymbolizeData(data_addr
, &DI
)) return;
129 InternalScopedString
data_desc(GetPageSizeCached());
130 RenderData(&data_desc
, fmt
, &DI
, common_flags()->strip_path_prefix
);
131 internal_strncpy(out_buf
, data_desc
.data(), out_buf_size
);
132 out_buf
[out_buf_size
- 1] = 0;
135 SANITIZER_INTERFACE_ATTRIBUTE
136 int __sanitizer_get_module_and_offset_for_pc( // NOLINT
137 uptr pc
, char *module_name
, uptr module_name_len
, uptr
*pc_offset
) {
138 return __sanitizer::GetModuleAndOffsetForPc(pc
, module_name
, module_name_len
,