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