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 39// Legacy API. 40// May be overriden by JIT/JAVA/etc, 41// whatever produces PCs marked with kExternalPCBit. 42SANITIZER_WEAK_DEFAULT_IMPL 43bool __tsan_symbolize_external(uptr pc, char *func_buf, uptr func_siz, 44 char *file_buf, uptr file_siz, int *line, 45 int *col) { 46 return false; 47} 48 49// New API: call __tsan_symbolize_external_ex only when it exists. 50// Once old clients are gone, provide dummy implementation. 51SANITIZER_WEAK_DEFAULT_IMPL 52void __tsan_symbolize_external_ex(uptr pc, 53 void (*add_frame)(void *, const char *, 54 const char *, int, int), 55 void *ctx) {} 56 57struct SymbolizedStackBuilder { 58 SymbolizedStack *head; 59 SymbolizedStack *tail; 60 uptr addr; 61}; 62 63static void AddFrame(void *ctx, const char *function_name, const char *file, 64 int line, int column) { 65 SymbolizedStackBuilder *ssb = (struct SymbolizedStackBuilder *)ctx; 66 if (ssb->tail) { 67 ssb->tail->next = SymbolizedStack::New(ssb->addr); 68 ssb->tail = ssb->tail->next; 69 } else { 70 ssb->head = ssb->tail = SymbolizedStack::New(ssb->addr); 71 } 72 AddressInfo *info = &ssb->tail->info; 73 if (function_name) { 74 info->function = internal_strdup(function_name); 75 } 76 if (file) { 77 info->file = internal_strdup(file); 78 } 79 info->line = line; 80 info->column = column; 81} 82 83SymbolizedStack *SymbolizeCode(uptr addr) { 84 // Check if PC comes from non-native land. 85 if (addr & kExternalPCBit) { 86 SymbolizedStackBuilder ssb = {nullptr, nullptr, addr}; 87 __tsan_symbolize_external_ex(addr, AddFrame, &ssb); 88 if (ssb.head) 89 return ssb.head; 90 // Legacy code: remove along with the declaration above 91 // once all clients using this API are gone. 92 // Declare static to not consume too much stack space. 93 // We symbolize reports in a single thread, so this is fine. 94 static char func_buf[1024]; 95 static char file_buf[1024]; 96 int line, col; 97 SymbolizedStack *frame = SymbolizedStack::New(addr); 98 if (__tsan_symbolize_external(addr, func_buf, sizeof(func_buf), file_buf, 99 sizeof(file_buf), &line, &col)) { 100 frame->info.function = internal_strdup(func_buf); 101 frame->info.file = internal_strdup(file_buf); 102 frame->info.line = line; 103 frame->info.column = col; 104 } 105 return frame; 106 } 107 return Symbolizer::GetOrInit()->SymbolizePC(addr); 108} 109 110ReportLocation *SymbolizeData(uptr addr) { 111 DataInfo info; 112 if (!Symbolizer::GetOrInit()->SymbolizeData(addr, &info)) 113 return 0; 114 ReportLocation *ent = ReportLocation::New(ReportLocationGlobal); 115 internal_memcpy(&ent->global, &info, sizeof(info)); 116 return ent; 117} 118 119void SymbolizeFlush() { 120 Symbolizer::GetOrInit()->Flush(); 121} 122 123} // namespace __tsan 124