blob: 4784c200f032b3bd64d666c3a8a38e7ae04f1bd8 [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());
40 for (uptr j = 0; j < addr_frames_num; j++) {
41 AddressInfo &info = addr_frames[j];
42 frame_desc.clear();
43 PrintStackFramePrefix(&frame_desc, frame_num, pc);
44 if (info.function) {
45 frame_desc.append(" in %s", info.function);
46 // Print offset in function if we don't know the source file.
47 if (!info.file && info.function_offset != AddressInfo::kUnknown)
48 frame_desc.append("+0x%zx", info.function_offset);
49 }
50 if (info.file) {
51 frame_desc.append(" ");
52 PrintSourceLocation(&frame_desc, info.file, info.line, info.column);
53 } else if (info.module) {
54 frame_desc.append(" ");
55 PrintModuleAndOffset(&frame_desc, info.module, info.module_offset);
56 }
57 Printf("%s\n", frame_desc.data());
58 frame_num++;
59 info.Clear();
60 }
61 }
62 // Always print a trailing empty line after stack trace.
63 Printf("\n");
64}
65
Evgeniy Stepanov769d46f2014-02-11 13:38:57 +000066void StackTrace::Unwind(uptr max_depth, uptr pc, uptr bp, void *context,
67 uptr stack_top, uptr stack_bottom,
68 bool request_fast_unwind) {
69 if (!WillUseFastUnwind(request_fast_unwind)) {
70 if (context)
71 SlowUnwindStackWithContext(pc, context, max_depth);
72 else
73 SlowUnwindStack(pc, max_depth);
Evgeniy Stepanov2629e572014-02-11 13:45:01 +000074 } else {
Alexey Samsonove13f7752013-11-07 06:33:06 +000075 FastUnwindStack(pc, bp, stack_top, stack_bottom, max_depth);
Evgeniy Stepanov769d46f2014-02-11 13:38:57 +000076 }
Alexey Samsonov9ff45982013-11-13 14:46:58 +000077
78 top_frame_bp = size ? bp : 0;
Alexey Samsonove13f7752013-11-07 06:33:06 +000079}
80
81} // namespace __sanitizer