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