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 thr->ignore_interceptors++; 30} 31 32void ExitSymbolizer() { 33 ThreadState *thr = cur_thread(); 34 CHECK(thr->in_symbolizer); 35 thr->in_symbolizer = false; 36 thr->ignore_interceptors--; 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 47static ReportStack *NewReportStackEntry(const AddressInfo &info) { 48 ReportStack *ent = NewReportStackEntry(info.address); 49 ent->module = StripModuleName(info.module); 50 ent->offset = info.module_offset; 51 if (info.function) 52 ent->func = internal_strdup(info.function); 53 if (info.file) 54 ent->file = internal_strdup(info.file); 55 ent->line = info.line; 56 ent->col = info.column; 57 return ent; 58} 59 60 61 ReportStack *next; 62 char *module; 63 uptr offset; 64 uptr pc; 65 char *func; 66 char *file; 67 int line; 68 int col; 69 70 71// Denotes fake PC values that come from JIT/JAVA/etc. 72// For such PC values __tsan_symbolize_external() will be called. 73const uptr kExternalPCBit = 1ULL << 60; 74 75// May be overriden by JIT/JAVA/etc, 76// whatever produces PCs marked with kExternalPCBit. 77extern "C" bool __tsan_symbolize_external(uptr pc, 78 char *func_buf, uptr func_siz, 79 char *file_buf, uptr file_siz, 80 int *line, int *col) 81 SANITIZER_WEAK_ATTRIBUTE; 82 83bool __tsan_symbolize_external(uptr pc, 84 char *func_buf, uptr func_siz, 85 char *file_buf, uptr file_siz, 86 int *line, int *col) { 87 return false; 88} 89 90ReportStack *SymbolizeCode(uptr addr) { 91 // Check if PC comes from non-native land. 92 if (addr & kExternalPCBit) { 93 // Declare static to not consume too much stack space. 94 // We symbolize reports in a single thread, so this is fine. 95 static char func_buf[1024]; 96 static char file_buf[1024]; 97 int line, col; 98 if (!__tsan_symbolize_external(addr, func_buf, sizeof(func_buf), 99 file_buf, sizeof(file_buf), &line, &col)) 100 return NewReportStackEntry(addr); 101 ReportStack *ent = NewReportStackEntry(addr); 102 ent->module = 0; 103 ent->offset = 0; 104 ent->func = internal_strdup(func_buf); 105 ent->file = internal_strdup(file_buf); 106 ent->line = line; 107 ent->col = col; 108 return ent; 109 } 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()->SymbolizePC( 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 DataInfo info; 135 if (!Symbolizer::Get()->SymbolizeData(addr, &info)) 136 return 0; 137 ReportLocation *ent = (ReportLocation*)internal_alloc(MBlockReportStack, 138 sizeof(ReportLocation)); 139 internal_memset(ent, 0, sizeof(*ent)); 140 ent->type = ReportLocationGlobal; 141 ent->module = StripModuleName(info.module); 142 ent->offset = info.module_offset; 143 if (info.name) 144 ent->name = internal_strdup(info.name); 145 ent->addr = info.start; 146 ent->size = info.size; 147 return ent; 148} 149 150void SymbolizeFlush() { 151 Symbolizer::Get()->Flush(); 152} 153 154} // namespace __tsan 155