1//===-- tsan_symbolize.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 a part of ThreadSanitizer (TSan), a race detector. 11// 12//===----------------------------------------------------------------------===// 13 14#include "tsan_symbolize.h" 15 16#include "sanitizer_common/sanitizer_common.h" 17#include "sanitizer_common/sanitizer_placement_new.h" 18#include "sanitizer_common/sanitizer_symbolizer.h" 19#include "tsan_flags.h" 20#include "tsan_report.h" 21#include "tsan_rtl.h" 22 23namespace __tsan { 24 25struct ScopedInSymbolizer { 26 ScopedInSymbolizer() { 27 ThreadState *thr = cur_thread(); 28 CHECK(!thr->in_symbolizer); 29 thr->in_symbolizer = true; 30 } 31 32 ~ScopedInSymbolizer() { 33 ThreadState *thr = cur_thread(); 34 CHECK(thr->in_symbolizer); 35 thr->in_symbolizer = false; 36 } 37}; 38 39ReportStack *NewReportStackEntry(uptr addr) { 40 ReportStack *ent = (ReportStack*)internal_alloc(MBlockReportStack, 41 sizeof(ReportStack)); 42 internal_memset(ent, 0, sizeof(*ent)); 43 ent->pc = addr; 44 return ent; 45} 46 47// Strip module path to make output shorter. 48static char *StripModuleName(const char *module) { 49 if (module == 0) 50 return 0; 51 const char *short_module_name = internal_strrchr(module, '/'); 52 if (short_module_name) 53 short_module_name += 1; 54 else 55 short_module_name = module; 56 return internal_strdup(short_module_name); 57} 58 59static ReportStack *NewReportStackEntry(const AddressInfo &info) { 60 ReportStack *ent = NewReportStackEntry(info.address); 61 ent->module = StripModuleName(info.module); 62 ent->offset = info.module_offset; 63 if (info.function) 64 ent->func = internal_strdup(info.function); 65 if (info.file) 66 ent->file = internal_strdup(info.file); 67 ent->line = info.line; 68 ent->col = info.column; 69 return ent; 70} 71 72ReportStack *SymbolizeCode(uptr addr) { 73 if (!IsSymbolizerAvailable()) 74 return SymbolizeCodeAddr2Line(addr); 75 ScopedInSymbolizer in_symbolizer; 76 static const uptr kMaxAddrFrames = 16; 77 InternalScopedBuffer<AddressInfo> addr_frames(kMaxAddrFrames); 78 for (uptr i = 0; i < kMaxAddrFrames; i++) 79 new(&addr_frames[i]) AddressInfo(); 80 uptr addr_frames_num = __sanitizer::SymbolizeCode(addr, addr_frames.data(), 81 kMaxAddrFrames); 82 if (addr_frames_num == 0) 83 return NewReportStackEntry(addr); 84 ReportStack *top = 0; 85 ReportStack *bottom = 0; 86 for (uptr i = 0; i < addr_frames_num; i++) { 87 ReportStack *cur_entry = NewReportStackEntry(addr_frames[i]); 88 CHECK(cur_entry); 89 addr_frames[i].Clear(); 90 if (i == 0) 91 top = cur_entry; 92 else 93 bottom->next = cur_entry; 94 bottom = cur_entry; 95 } 96 return top; 97} 98 99ReportLocation *SymbolizeData(uptr addr) { 100 if (!IsSymbolizerAvailable()) 101 return 0; 102 ScopedInSymbolizer in_symbolizer; 103 DataInfo info; 104 if (!__sanitizer::SymbolizeData(addr, &info)) 105 return 0; 106 ReportLocation *ent = (ReportLocation*)internal_alloc(MBlockReportStack, 107 sizeof(ReportLocation)); 108 internal_memset(ent, 0, sizeof(*ent)); 109 ent->type = ReportLocationGlobal; 110 ent->module = StripModuleName(info.module); 111 ent->offset = info.module_offset; 112 if (info.name) 113 ent->name = internal_strdup(info.name); 114 ent->addr = info.start; 115 ent->size = info.size; 116 return ent; 117} 118 119} // namespace __tsan 120