tsan_symbolize.cc revision 68e16eb59c7f654cdb98a2811b3a42612b58a735
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 25void EnterSymbolizer() { 26 ThreadState *thr = cur_thread(); 27 CHECK(!thr->in_symbolizer); 28 thr->in_symbolizer = true; 29} 30 31void ExitSymbolizer() { 32 ThreadState *thr = cur_thread(); 33 CHECK(thr->in_symbolizer); 34 thr->in_symbolizer = false; 35} 36 37ReportStack *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 45static ReportStack *NewReportStackEntry(const AddressInfo &info) { 46 ReportStack *ent = NewReportStackEntry(info.address); 47 ent->module = StripModuleName(info.module); 48 ent->offset = info.module_offset; 49 if (info.function) 50 ent->func = internal_strdup(info.function); 51 if (info.file) 52 ent->file = internal_strdup(info.file); 53 ent->line = info.line; 54 ent->col = info.column; 55 return ent; 56} 57 58 59 ReportStack *next; 60 char *module; 61 uptr offset; 62 uptr pc; 63 char *func; 64 char *file; 65 int line; 66 int col; 67 68 69// Denotes fake PC values that come from JIT/JAVA/etc. 70// For such PC values __tsan_symbolize_external() will be called. 71const uptr kExternalPCBit = 1ULL << 60; 72 73// May be overriden by JIT/JAVA/etc, 74// whatever produces PCs marked with kExternalPCBit. 75extern "C" bool __tsan_symbolize_external(uptr pc, 76 char *func_buf, uptr func_siz, 77 char *file_buf, uptr file_siz, 78 int *line, int *col) 79 SANITIZER_WEAK_ATTRIBUTE; 80 81bool __tsan_symbolize_external(uptr pc, 82 char *func_buf, uptr func_siz, 83 char *file_buf, uptr file_siz, 84 int *line, int *col) { 85 return false; 86} 87 88ReportStack *SymbolizeCode(uptr addr) { 89 // Check if PC comes from non-native land. 90 if (addr & kExternalPCBit) { 91 // Declare static to not consume too much stack space. 92 // We symbolize reports in a single thread, so this is fine. 93 static char func_buf[1024]; 94 static char file_buf[1024]; 95 int line, col; 96 if (!__tsan_symbolize_external(addr, func_buf, sizeof(func_buf), 97 file_buf, sizeof(file_buf), &line, &col)) 98 return NewReportStackEntry(addr); 99 ReportStack *ent = NewReportStackEntry(addr); 100 ent->module = 0; 101 ent->offset = 0; 102 ent->func = internal_strdup(func_buf); 103 ent->file = internal_strdup(file_buf); 104 ent->line = line; 105 ent->col = col; 106 return ent; 107 } 108 if (!Symbolizer::Get()->IsAvailable()) 109 return SymbolizeCodeAddr2Line(addr); 110 static const uptr kMaxAddrFrames = 16; 111 InternalScopedBuffer<AddressInfo> addr_frames(kMaxAddrFrames); 112 for (uptr i = 0; i < kMaxAddrFrames; i++) 113 new(&addr_frames[i]) AddressInfo(); 114 uptr addr_frames_num = Symbolizer::Get()->SymbolizeCode( 115 addr, addr_frames.data(), kMaxAddrFrames); 116 if (addr_frames_num == 0) 117 return NewReportStackEntry(addr); 118 ReportStack *top = 0; 119 ReportStack *bottom = 0; 120 for (uptr i = 0; i < addr_frames_num; i++) { 121 ReportStack *cur_entry = NewReportStackEntry(addr_frames[i]); 122 CHECK(cur_entry); 123 addr_frames[i].Clear(); 124 if (i == 0) 125 top = cur_entry; 126 else 127 bottom->next = cur_entry; 128 bottom = cur_entry; 129 } 130 return top; 131} 132 133ReportLocation *SymbolizeData(uptr addr) { 134 if (!Symbolizer::Get()->IsAvailable()) 135 return 0; 136 DataInfo info; 137 if (!Symbolizer::Get()->SymbolizeData(addr, &info)) 138 return 0; 139 ReportLocation *ent = (ReportLocation*)internal_alloc(MBlockReportStack, 140 sizeof(ReportLocation)); 141 internal_memset(ent, 0, sizeof(*ent)); 142 ent->type = ReportLocationGlobal; 143 ent->module = StripModuleName(info.module); 144 ent->offset = info.module_offset; 145 if (info.name) 146 ent->name = internal_strdup(info.name); 147 ent->addr = info.start; 148 ent->size = info.size; 149 return ent; 150} 151 152void SymbolizeFlush() { 153 if (!Symbolizer::Get()->IsAvailable()) 154 return; 155 Symbolizer::Get()->Flush(); 156} 157 158} // namespace __tsan 159