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 dedup_token
.append(cur
->info
.function
);
49 // Always print a trailing empty line after stack trace.
51 if (dedup_token
.length())
52 Printf("DEDUP_TOKEN: %s\n", dedup_token
.data());
55 void BufferedStackTrace::Unwind(u32 max_depth
, uptr pc
, uptr bp
, void *context
,
56 uptr stack_top
, uptr stack_bottom
,
57 bool request_fast_unwind
) {
58 top_frame_bp
= (max_depth
> 0) ? bp
: 0;
59 // Avoid doing any work for small max_depth.
69 if (!WillUseFastUnwind(request_fast_unwind
)) {
70 #if SANITIZER_CAN_SLOW_UNWIND
72 SlowUnwindStackWithContext(pc
, context
, max_depth
);
74 SlowUnwindStack(pc
, max_depth
);
76 UNREACHABLE("slow unwind requested but not available");
79 FastUnwindStack(pc
, bp
, stack_top
, stack_bottom
, max_depth
);
83 } // namespace __sanitizer
84 using namespace __sanitizer
;
87 SANITIZER_INTERFACE_ATTRIBUTE
88 void __sanitizer_symbolize_pc(uptr pc
, const char *fmt
, char *out_buf
,
90 if (!out_buf_size
) return;
91 pc
= StackTrace::GetPreviousInstructionPc(pc
);
92 SymbolizedStack
*frame
= Symbolizer::GetOrInit()->SymbolizePC(pc
);
94 internal_strncpy(out_buf
, "<can't symbolize>", out_buf_size
);
95 out_buf
[out_buf_size
- 1] = 0;
98 InternalScopedString
frame_desc(GetPageSizeCached());
99 RenderFrame(&frame_desc
, fmt
, 0, frame
->info
,
100 common_flags()->symbolize_vs_style
,
101 common_flags()->strip_path_prefix
);
102 internal_strncpy(out_buf
, frame_desc
.data(), out_buf_size
);
103 out_buf
[out_buf_size
- 1] = 0;
106 SANITIZER_INTERFACE_ATTRIBUTE
107 void __sanitizer_symbolize_global(uptr data_addr
, const char *fmt
,
108 char *out_buf
, uptr out_buf_size
) {
109 if (!out_buf_size
) return;
112 if (!Symbolizer::GetOrInit()->SymbolizeData(data_addr
, &DI
)) return;
113 InternalScopedString
data_desc(GetPageSizeCached());
114 RenderData(&data_desc
, fmt
, &DI
, common_flags()->strip_path_prefix
);
115 internal_strncpy(out_buf
, data_desc
.data(), out_buf_size
);
116 out_buf
[out_buf_size
- 1] = 0;