blob: c68149daa81de6fa38ad4724f0645da6e31a45ae [file] [log] [blame]
Alexey Samsonove13f7752013-11-07 06:33:06 +00001//===-- sanitizer_stacktrace_libcdep.cc -----------------------------------===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// This file is shared between AddressSanitizer and ThreadSanitizer
11// run-time libraries.
12//===----------------------------------------------------------------------===//
13
Alexey Samsonovca7a2132013-12-25 09:29:54 +000014#include "sanitizer_common.h"
Alexey Samsonove13f7752013-11-07 06:33:06 +000015#include "sanitizer_stacktrace.h"
Alexey Samsonovca7a2132013-12-25 09:29:54 +000016#include "sanitizer_symbolizer.h"
Alexey Samsonove13f7752013-11-07 06:33:06 +000017
18namespace __sanitizer {
19
Alexey Samsonovca7a2132013-12-25 09:29:54 +000020static void PrintStackFramePrefix(InternalScopedString *buffer, uptr frame_num,
21 uptr pc) {
22 buffer->append(" #%zu 0x%zx", frame_num, pc);
23}
24
25void StackTrace::PrintStack(const uptr *addr, uptr size) {
26 if (addr == 0 || size == 0) {
27 Printf(" <empty stack>\n\n");
28 return;
29 }
30 InternalScopedBuffer<char> buff(GetPageSizeCached() * 2);
31 InternalScopedBuffer<AddressInfo> addr_frames(64);
32 InternalScopedString frame_desc(GetPageSizeCached() * 2);
33 uptr frame_num = 0;
34 for (uptr i = 0; i < size && addr[i]; i++) {
35 // PCs in stack traces are actually the return addresses, that is,
36 // addresses of the next instructions after the call.
37 uptr pc = GetPreviousInstructionPc(addr[i]);
38 uptr addr_frames_num = Symbolizer::GetOrInit()->SymbolizePC(
39 pc, addr_frames.data(), addr_frames.size());
Sergey Matveev2be4a282014-05-23 16:04:41 +000040 if (addr_frames_num == 0) {
41 frame_desc.clear();
42 PrintStackFramePrefix(&frame_desc, frame_num, pc);
43 frame_desc.append(" (<unknown module>)");
44 Printf("%s\n", frame_desc.data());
45 frame_num++;
46 continue;
47 }
Alexey Samsonovca7a2132013-12-25 09:29:54 +000048 for (uptr j = 0; j < addr_frames_num; j++) {
49 AddressInfo &info = addr_frames[j];
50 frame_desc.clear();
51 PrintStackFramePrefix(&frame_desc, frame_num, pc);
52 if (info.function) {
53 frame_desc.append(" in %s", info.function);
54 // Print offset in function if we don't know the source file.
55 if (!info.file && info.function_offset != AddressInfo::kUnknown)
56 frame_desc.append("+0x%zx", info.function_offset);
57 }
58 if (info.file) {
59 frame_desc.append(" ");
60 PrintSourceLocation(&frame_desc, info.file, info.line, info.column);
61 } else if (info.module) {
62 frame_desc.append(" ");
63 PrintModuleAndOffset(&frame_desc, info.module, info.module_offset);
64 }
65 Printf("%s\n", frame_desc.data());
66 frame_num++;
67 info.Clear();
68 }
69 }
70 // Always print a trailing empty line after stack trace.
71 Printf("\n");
72}
73
Evgeniy Stepanov769d46f2014-02-11 13:38:57 +000074void StackTrace::Unwind(uptr max_depth, uptr pc, uptr bp, void *context,
75 uptr stack_top, uptr stack_bottom,
76 bool request_fast_unwind) {
Alexey Samsonov3e8467b2014-03-04 12:21:28 +000077 top_frame_bp = (max_depth > 0) ? bp : 0;
78 // Avoid doing any work for small max_depth.
79 if (max_depth == 0) {
80 size = 0;
81 return;
82 }
83 if (max_depth == 1) {
84 size = 1;
85 trace[0] = pc;
86 return;
87 }
Evgeniy Stepanov769d46f2014-02-11 13:38:57 +000088 if (!WillUseFastUnwind(request_fast_unwind)) {
89 if (context)
90 SlowUnwindStackWithContext(pc, context, max_depth);
91 else
92 SlowUnwindStack(pc, max_depth);
Evgeniy Stepanov2629e572014-02-11 13:45:01 +000093 } else {
Alexey Samsonove13f7752013-11-07 06:33:06 +000094 FastUnwindStack(pc, bp, stack_top, stack_bottom, max_depth);
Evgeniy Stepanov769d46f2014-02-11 13:38:57 +000095 }
Alexey Samsonove13f7752013-11-07 06:33:06 +000096}
97
98} // namespace __sanitizer