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());
116 // Reserve one byte for the final 0.
117 char *out_end
= out_buf
+ out_buf_size
- 1;
118 for (SymbolizedStack
*cur
= frame
; cur
&& out_buf
< out_end
;
121 RenderFrame(&frame_desc
, fmt
, frame_num
++, cur
->info
,
122 common_flags()->symbolize_vs_style
,
123 common_flags()->strip_path_prefix
);
124 if (!frame_desc
.length())
126 // Reserve one byte for the terminating 0.
127 uptr n
= out_end
- out_buf
- 1;
128 internal_strncpy(out_buf
, frame_desc
.data(), n
);
129 out_buf
+= __sanitizer::Min
<uptr
>(n
, frame_desc
.length());
132 CHECK(out_buf
<= out_end
);
136 SANITIZER_INTERFACE_ATTRIBUTE
137 void __sanitizer_symbolize_global(uptr data_addr
, const char *fmt
,
138 char *out_buf
, uptr out_buf_size
) {
139 if (!out_buf_size
) return;
142 if (!Symbolizer::GetOrInit()->SymbolizeData(data_addr
, &DI
)) return;
143 InternalScopedString
data_desc(GetPageSizeCached());
144 RenderData(&data_desc
, fmt
, &DI
, common_flags()->strip_path_prefix
);
145 internal_strncpy(out_buf
, data_desc
.data(), out_buf_size
);
146 out_buf
[out_buf_size
- 1] = 0;
149 SANITIZER_INTERFACE_ATTRIBUTE
150 int __sanitizer_get_module_and_offset_for_pc( // NOLINT
151 uptr pc
, char *module_name
, uptr module_name_len
, uptr
*pc_offset
) {
152 return __sanitizer::GetModuleAndOffsetForPc(pc
, module_name
, module_name_len
,