sanitizer_stacktrace.cc revision 24861607cb3c606ad46e724456eb851558c85330
1a11af531ec48ad84f790b9511f003ac5c934a999Daniel Dunbar//===-- sanitizer_stacktrace.cc -------------------------------------------===//
2a11af531ec48ad84f790b9511f003ac5c934a999Daniel Dunbar//
3a11af531ec48ad84f790b9511f003ac5c934a999Daniel Dunbar//                     The LLVM Compiler Infrastructure
4a11af531ec48ad84f790b9511f003ac5c934a999Daniel Dunbar//
5a11af531ec48ad84f790b9511f003ac5c934a999Daniel Dunbar// This file is distributed under the University of Illinois Open Source
6a11af531ec48ad84f790b9511f003ac5c934a999Daniel Dunbar// License. See LICENSE.TXT for details.
7a11af531ec48ad84f790b9511f003ac5c934a999Daniel Dunbar//
8a11af531ec48ad84f790b9511f003ac5c934a999Daniel Dunbar//===----------------------------------------------------------------------===//
9a11af531ec48ad84f790b9511f003ac5c934a999Daniel Dunbar//
10a11af531ec48ad84f790b9511f003ac5c934a999Daniel Dunbar// This file is shared between AddressSanitizer and ThreadSanitizer
11d04a8d4b33ff316ca4cf961e06c9e312eff8e64fChandler Carruth// run-time libraries.
12dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines//===----------------------------------------------------------------------===//
13d04a8d4b33ff316ca4cf961e06c9e312eff8e64fChandler Carruth
14d04a8d4b33ff316ca4cf961e06c9e312eff8e64fChandler Carruth#include "sanitizer_common.h"
15d04a8d4b33ff316ca4cf961e06c9e312eff8e64fChandler Carruth#include "sanitizer_flags.h"
168c2eebe4074ef218b30d94358f6b2e45c079605cDaniel Dunbar#include "sanitizer_procmaps.h"
174a0abd80f18f9c2a10bf5b14cd6731d51972a426Daniel Dunbar#include "sanitizer_stacktrace.h"
18a11af531ec48ad84f790b9511f003ac5c934a999Daniel Dunbar#include "sanitizer_symbolizer.h"
198c2eebe4074ef218b30d94358f6b2e45c079605cDaniel Dunbar
202761fc427082215c2affcc9d8db8491400bc9e5dDaniel Dunbarnamespace __sanitizer {
21abde2982e3c660398ff5a8e5f7ac3d1467b83062Daniel Dunbar
2290edac0e8b35f766599362b6301863229f0ddcdbChris Lattneruptr StackTrace::GetPreviousInstructionPc(uptr pc) {
23bfe3686aee881cb7599c42fc96afc44ff9bcf356Evan Cheng#ifdef __arm__
240e6a052331f674dd70e28af41f654a7874405eabEvan Cheng  // Cancel Thumb bit.
25e76a33b9567d78a5744dc52fcec3a6056d6fb576Evan Cheng  pc = pc & (~1);
26f9bdeddb96043559c61f176f8077e3b91a0c544fChris Lattner#endif
27a11af531ec48ad84f790b9511f003ac5c934a999Daniel Dunbar#if defined(__sparc__)
285e195a4c8d8cd4498ab7e0aa16a3b6f273daf457Rafael Espindola  return pc - 8;
29c25e7581b9b8088910da31702d4ca21c4734c6d7Torok Edwin#else
304a0abd80f18f9c2a10bf5b14cd6731d51972a426Daniel Dunbar  return pc - 1;
3186e2211d0a496f470ea1d320161c8dc43593c5c6Chris Lattner#endif
32d04a8d4b33ff316ca4cf961e06c9e312eff8e64fChandler Carruth}
33a11c3e25015a62c817e60ec4f955a7f3f3bb6c67Rafael Espindola
34476b242fe7a61e5f9ac6214b0bc5c680d24f152eNick Lewyckystatic void PrintStackFramePrefix(InternalScopedString *buffer, uptr frame_num,
35dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines                                  uptr pc) {
36a11af531ec48ad84f790b9511f003ac5c934a999Daniel Dunbar  buffer->append("    #%zu 0x%zx", frame_num, pc);
37a11af531ec48ad84f790b9511f003ac5c934a999Daniel Dunbar}
38a11af531ec48ad84f790b9511f003ac5c934a999Daniel Dunbar
39a11af531ec48ad84f790b9511f003ac5c934a999Daniel Dunbarvoid StackTrace::PrintStack(const uptr *addr, uptr size,
4046a947d8c191e5c218e736330c9d4d59ac4bcab3Chris Lattner                            SymbolizeCallback symbolize_callback) {
41916a94b870042772568fca7995cf45aef7a6e333Bill Wendling  if (addr == 0) {
4286e2211d0a496f470ea1d320161c8dc43593c5c6Chris Lattner    Printf("<empty stack>\n\n");
4399cb622041a0839c7dfcf0263c5102a305a0fdb5Bill Wendling    return;
44916a94b870042772568fca7995cf45aef7a6e333Bill Wendling  }
4536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  MemoryMappingLayout proc_maps(/*cache_enabled*/true);
4636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  InternalScopedBuffer<char> buff(GetPageSizeCached() * 2);
4736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  InternalScopedBuffer<AddressInfo> addr_frames(64);
4800545e1cd50073ed8a3af98070a16b50f3c3401cJim Grosbach  InternalScopedString frame_desc(GetPageSizeCached() * 2);
4986e2211d0a496f470ea1d320161c8dc43593c5c6Chris Lattner  uptr frame_num = 0;
50d79d9dce47d505369662ae5111dba24f9ccdef68Chris Lattner  for (uptr i = 0; i < size && addr[i]; i++) {
519dee8e3009408fd08c656558397a8ac8604139baDaniel Dunbar    // PCs in stack traces are actually the return addresses, that is,
529dee8e3009408fd08c656558397a8ac8604139baDaniel Dunbar    // addresses of the next instructions after the call.
539dee8e3009408fd08c656558397a8ac8604139baDaniel Dunbar    uptr pc = GetPreviousInstructionPc(addr[i]);
5444d798d9763bc32aaf49fe7c10d604845f4b6685Nick Lewycky    uptr addr_frames_num = 0;  // The number of stack frames for current
559dee8e3009408fd08c656558397a8ac8604139baDaniel Dunbar                               // instruction address.
566e032942cf58d1c41f88609a1cec74eb74940ecdRafael Espindola    if (symbolize_callback) {
5736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines      if (symbolize_callback((void*)pc, buff.data(), buff.size())) {
5836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines        addr_frames_num = 1;
596e032942cf58d1c41f88609a1cec74eb74940ecdRafael Espindola        frame_desc.clear();
6046a947d8c191e5c218e736330c9d4d59ac4bcab3Chris Lattner        PrintStackFramePrefix(&frame_desc, frame_num, pc);
6136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines        // We can't know anything about the string returned by external
62dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines        // symbolizer, but if it starts with filename, try to strip path prefix
6336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines        // from it.
6436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines        frame_desc.append(
6536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines            " %s",
66320296a4cfe414ce59f406b8a5ce15272f563103Rafael Espindola            StripPathPrefix(buff.data(), common_flags()->strip_path_prefix));
67320296a4cfe414ce59f406b8a5ce15272f563103Rafael Espindola        Printf("%s\n", frame_desc.data());
68dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines        frame_num++;
695d672cfab096390690a1a5f33b0057c4cf252c55Chris Lattner      }
705d672cfab096390690a1a5f33b0057c4cf252c55Chris Lattner    }
715d672cfab096390690a1a5f33b0057c4cf252c55Chris Lattner    if (common_flags()->symbolize && addr_frames_num == 0) {
72a11af531ec48ad84f790b9511f003ac5c934a999Daniel Dunbar      // Use our own (online) symbolizer, if necessary.
7386e2211d0a496f470ea1d320161c8dc43593c5c6Chris Lattner      if (Symbolizer *sym = Symbolizer::GetOrNull())
74d79d9dce47d505369662ae5111dba24f9ccdef68Chris Lattner        addr_frames_num =
75d79d9dce47d505369662ae5111dba24f9ccdef68Chris Lattner            sym->SymbolizeCode(pc, addr_frames.data(), addr_frames.size());
7686e2211d0a496f470ea1d320161c8dc43593c5c6Chris Lattner      for (uptr j = 0; j < addr_frames_num; j++) {
7786e2211d0a496f470ea1d320161c8dc43593c5c6Chris Lattner        AddressInfo &info = addr_frames[j];
7886e2211d0a496f470ea1d320161c8dc43593c5c6Chris Lattner        frame_desc.clear();
7986e2211d0a496f470ea1d320161c8dc43593c5c6Chris Lattner        PrintStackFramePrefix(&frame_desc, frame_num, pc);
8086e2211d0a496f470ea1d320161c8dc43593c5c6Chris Lattner        if (info.function) {
8186e2211d0a496f470ea1d320161c8dc43593c5c6Chris Lattner          frame_desc.append(" in %s", info.function);
8256591ab218639d8a6e4c756ca37adaf20215c3b6Chris Lattner        }
8356591ab218639d8a6e4c756ca37adaf20215c3b6Chris Lattner        if (info.file) {
8456591ab218639d8a6e4c756ca37adaf20215c3b6Chris Lattner          frame_desc.append(" ");
8536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines          PrintSourceLocation(&frame_desc, info.file, info.line, info.column);
8600545e1cd50073ed8a3af98070a16b50f3c3401cJim Grosbach        } else if (info.module) {
8791bead790518fcf5cb26019fb1ebf2372e8a5b3fChris Lattner          frame_desc.append(" ");
8836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines          PrintModuleAndOffset(&frame_desc, info.module, info.module_offset);
896b71653c82f86626f64356c308d7356a17b05834Daniel Dunbar        }
90d32c7cfa248f685e6e3064c0958dc2f0c31a4df6Chris Lattner        Printf("%s\n", frame_desc.data());
9186e2211d0a496f470ea1d320161c8dc43593c5c6Chris Lattner        frame_num++;
9286e2211d0a496f470ea1d320161c8dc43593c5c6Chris Lattner        info.Clear();
9386e2211d0a496f470ea1d320161c8dc43593c5c6Chris Lattner      }
9436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    }
956b71653c82f86626f64356c308d7356a17b05834Daniel Dunbar    if (addr_frames_num == 0) {
966b71653c82f86626f64356c308d7356a17b05834Daniel Dunbar      // If online symbolization failed, try to output at least module and
9736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines      // offset for instruction.
986b71653c82f86626f64356c308d7356a17b05834Daniel Dunbar      frame_desc.clear();
99d79d9dce47d505369662ae5111dba24f9ccdef68Chris Lattner      PrintStackFramePrefix(&frame_desc, frame_num, pc);
100d79d9dce47d505369662ae5111dba24f9ccdef68Chris Lattner      uptr offset;
101d79d9dce47d505369662ae5111dba24f9ccdef68Chris Lattner      if (proc_maps.GetObjectNameAndOffset(pc, &offset,
10236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines                                           buff.data(), buff.size(),
103d79d9dce47d505369662ae5111dba24f9ccdef68Chris Lattner                                           /* protection */0)) {
104d79d9dce47d505369662ae5111dba24f9ccdef68Chris Lattner        frame_desc.append(" ");
105d79d9dce47d505369662ae5111dba24f9ccdef68Chris Lattner        PrintModuleAndOffset(&frame_desc, buff.data(), offset);
106d79d9dce47d505369662ae5111dba24f9ccdef68Chris Lattner      }
1076b71653c82f86626f64356c308d7356a17b05834Daniel Dunbar      Printf("%s\n", frame_desc.data());
10836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines      frame_num++;
10936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    }
1100fd90fd8d1c2143a763dee509c66a5b3c74088b1Chris Lattner  }
11136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  // Always print a trailing empty line after stack trace.
1120fd90fd8d1c2143a763dee509c66a5b3c74088b1Chris Lattner  Printf("\n");
1130fd90fd8d1c2143a763dee509c66a5b3c74088b1Chris Lattner}
1146b71653c82f86626f64356c308d7356a17b05834Daniel Dunbar
11546a947d8c191e5c218e736330c9d4d59ac4bcab3Chris Lattneruptr StackTrace::GetCurrentPc() {
11646a947d8c191e5c218e736330c9d4d59ac4bcab3Chris Lattner  return GET_CALLER_PC();
117a11af531ec48ad84f790b9511f003ac5c934a999Daniel Dunbar}
11836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines
11936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hinesvoid StackTrace::FastUnwindStack(uptr pc, uptr bp,
12036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines                                 uptr stack_top, uptr stack_bottom,
12136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines                                 uptr max_depth) {
12236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  if (max_depth == 0) {
12336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    size = 0;
12436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    return;
12536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  }
12636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  trace[0] = pc;
12736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  size = 1;
12836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  uptr *frame = (uptr *)bp;
12936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  uptr *prev_frame = frame - 1;
13036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  if (stack_top < 4096) return;  // Sanity check for stack top.
13136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  // Avoid infinite loop when frame == frame[0] by using frame > prev_frame.
13236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  while (frame > prev_frame &&
13336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines         frame < (uptr *)stack_top - 2 &&
13436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines         frame > (uptr *)stack_bottom &&
13536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines         IsAligned((uptr)frame, sizeof(*frame)) &&
13636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines         size < max_depth) {
13736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    uptr pc1 = frame[1];
13836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    if (pc1 != pc) {
13936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines      trace[size++] = pc1;
14036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    }
14136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    prev_frame = frame;
14236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    frame = (uptr*)frame[0];
14336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  }
14436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines}
14595cf30c444707634bbd950f13405b6c8bcfe496bKevin Enderby
1469eb158d5b4cd4f6fc80912e2dd77bdf13c3ca0e7Chris Lattnerstatic bool MatchPc(uptr cur_pc, uptr trace_pc, uptr threshold) {
1479eb158d5b4cd4f6fc80912e2dd77bdf13c3ca0e7Chris Lattner  return cur_pc - trace_pc <= threshold || trace_pc - cur_pc <= threshold;
1489eb158d5b4cd4f6fc80912e2dd77bdf13c3ca0e7Chris Lattner}
1499eb158d5b4cd4f6fc80912e2dd77bdf13c3ca0e7Chris Lattner
150a00b80b04c5edb08639c1c6b32e9231fd8b066f7Dmitri Gribenkovoid StackTrace::PopStackFrames(uptr count) {
15136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  CHECK(count < size);
15236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  size -= count;
15336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  for (uptr i = 0; i < size; ++i) {
154dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    trace[i] = trace[i + count];
15536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  }
15636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines}
15736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines
15836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hinesuptr StackTrace::LocatePcInTrace(uptr pc) {
15936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  // Use threshold to find PC in stack trace, as PC we want to unwind from may
16036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  // slightly differ from return address in the actual unwinded stack trace.
16136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  const int kPcThreshold = 96;
162dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines  for (uptr i = 0; i < size; ++i) {
163dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    if (MatchPc(pc, trace[i], kPcThreshold))
16436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines      return i;
16536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  }
16636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  return 0;
16736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines}
16836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines
16936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines}  // namespace __sanitizer
17036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines