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_stacktrace.h"
14 #include "sanitizer_symbolizer.h"
16 namespace __sanitizer
{
18 static void PrintStackFramePrefix(InternalScopedString
*buffer
, uptr frame_num
,
20 buffer
->append(" #%zu 0x%zx", frame_num
, pc
);
23 void StackTrace::PrintStack(const uptr
*addr
, uptr size
) {
24 if (addr
== 0 || size
== 0) {
25 Printf(" <empty stack>\n\n");
28 InternalScopedBuffer
<char> buff(GetPageSizeCached() * 2);
29 InternalScopedBuffer
<AddressInfo
> addr_frames(64);
30 InternalScopedString
frame_desc(GetPageSizeCached() * 2);
32 for (uptr i
= 0; i
< size
&& addr
[i
]; i
++) {
33 // PCs in stack traces are actually the return addresses, that is,
34 // addresses of the next instructions after the call.
35 uptr pc
= GetPreviousInstructionPc(addr
[i
]);
36 uptr addr_frames_num
= Symbolizer::GetOrInit()->SymbolizePC(
37 pc
, addr_frames
.data(), addr_frames
.size());
38 if (addr_frames_num
== 0) {
40 PrintStackFramePrefix(&frame_desc
, frame_num
, pc
);
41 frame_desc
.append(" (<unknown module>)");
42 Printf("%s\n", frame_desc
.data());
46 for (uptr j
= 0; j
< addr_frames_num
; j
++) {
47 AddressInfo
&info
= addr_frames
[j
];
49 PrintStackFramePrefix(&frame_desc
, frame_num
, pc
);
51 frame_desc
.append(" in %s", info
.function
);
52 // Print offset in function if we don't know the source file.
53 if (!info
.file
&& info
.function_offset
!= AddressInfo::kUnknown
)
54 frame_desc
.append("+0x%zx", info
.function_offset
);
57 frame_desc
.append(" ");
58 PrintSourceLocation(&frame_desc
, info
.file
, info
.line
, info
.column
);
59 } else if (info
.module
) {
60 frame_desc
.append(" ");
61 PrintModuleAndOffset(&frame_desc
, info
.module
, info
.module_offset
);
63 Printf("%s\n", frame_desc
.data());
68 // Always print a trailing empty line after stack trace.
72 void StackTrace::Unwind(uptr max_depth
, uptr pc
, uptr bp
, void *context
,
73 uptr stack_top
, uptr stack_bottom
,
74 bool request_fast_unwind
) {
75 top_frame_bp
= (max_depth
> 0) ? bp
: 0;
76 // Avoid doing any work for small max_depth.
86 if (!WillUseFastUnwind(request_fast_unwind
)) {
88 SlowUnwindStackWithContext(pc
, context
, max_depth
);
90 SlowUnwindStack(pc
, max_depth
);
92 FastUnwindStack(pc
, bp
, stack_top
, stack_bottom
, max_depth
);
96 } // namespace __sanitizer