1353944Sdim//===-- tsan_symbolize.cpp ------------------------------------------------===// 2353944Sdim// 3353944Sdim// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4353944Sdim// See https://llvm.org/LICENSE.txt for license information. 5353944Sdim// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6353944Sdim// 7353944Sdim//===----------------------------------------------------------------------===// 8353944Sdim// 9353944Sdim// This file is a part of ThreadSanitizer (TSan), a race detector. 10353944Sdim// 11353944Sdim//===----------------------------------------------------------------------===// 12353944Sdim 13353944Sdim#include "tsan_symbolize.h" 14353944Sdim 15353944Sdim#include "sanitizer_common/sanitizer_common.h" 16353944Sdim#include "sanitizer_common/sanitizer_placement_new.h" 17353944Sdim#include "sanitizer_common/sanitizer_symbolizer.h" 18353944Sdim#include "tsan_flags.h" 19353944Sdim#include "tsan_report.h" 20353944Sdim#include "tsan_rtl.h" 21353944Sdim 22353944Sdimnamespace __tsan { 23353944Sdim 24353944Sdimvoid EnterSymbolizer() { 25353944Sdim ThreadState *thr = cur_thread(); 26353944Sdim CHECK(!thr->in_symbolizer); 27353944Sdim thr->in_symbolizer = true; 28353944Sdim thr->ignore_interceptors++; 29353944Sdim} 30353944Sdim 31353944Sdimvoid ExitSymbolizer() { 32353944Sdim ThreadState *thr = cur_thread(); 33353944Sdim CHECK(thr->in_symbolizer); 34353944Sdim thr->in_symbolizer = false; 35353944Sdim thr->ignore_interceptors--; 36353944Sdim} 37353944Sdim 38353944Sdim// Legacy API. 39353944Sdim// May be overriden by JIT/JAVA/etc, 40353944Sdim// whatever produces PCs marked with kExternalPCBit. 41353944SdimSANITIZER_WEAK_DEFAULT_IMPL 42353944Sdimbool __tsan_symbolize_external(uptr pc, char *func_buf, uptr func_siz, 43353944Sdim char *file_buf, uptr file_siz, int *line, 44353944Sdim int *col) { 45353944Sdim return false; 46353944Sdim} 47353944Sdim 48353944Sdim// New API: call __tsan_symbolize_external_ex only when it exists. 49353944Sdim// Once old clients are gone, provide dummy implementation. 50353944SdimSANITIZER_WEAK_DEFAULT_IMPL 51353944Sdimvoid __tsan_symbolize_external_ex(uptr pc, 52353944Sdim void (*add_frame)(void *, const char *, 53353944Sdim const char *, int, int), 54353944Sdim void *ctx) {} 55353944Sdim 56353944Sdimstruct SymbolizedStackBuilder { 57353944Sdim SymbolizedStack *head; 58353944Sdim SymbolizedStack *tail; 59353944Sdim uptr addr; 60353944Sdim}; 61353944Sdim 62353944Sdimstatic void AddFrame(void *ctx, const char *function_name, const char *file, 63353944Sdim int line, int column) { 64353944Sdim SymbolizedStackBuilder *ssb = (struct SymbolizedStackBuilder *)ctx; 65353944Sdim if (ssb->tail) { 66353944Sdim ssb->tail->next = SymbolizedStack::New(ssb->addr); 67353944Sdim ssb->tail = ssb->tail->next; 68353944Sdim } else { 69353944Sdim ssb->head = ssb->tail = SymbolizedStack::New(ssb->addr); 70353944Sdim } 71353944Sdim AddressInfo *info = &ssb->tail->info; 72353944Sdim if (function_name) { 73353944Sdim info->function = internal_strdup(function_name); 74353944Sdim } 75353944Sdim if (file) { 76353944Sdim info->file = internal_strdup(file); 77353944Sdim } 78353944Sdim info->line = line; 79353944Sdim info->column = column; 80353944Sdim} 81353944Sdim 82353944SdimSymbolizedStack *SymbolizeCode(uptr addr) { 83353944Sdim // Check if PC comes from non-native land. 84353944Sdim if (addr & kExternalPCBit) { 85353944Sdim SymbolizedStackBuilder ssb = {nullptr, nullptr, addr}; 86353944Sdim __tsan_symbolize_external_ex(addr, AddFrame, &ssb); 87353944Sdim if (ssb.head) 88353944Sdim return ssb.head; 89353944Sdim // Legacy code: remove along with the declaration above 90353944Sdim // once all clients using this API are gone. 91353944Sdim // Declare static to not consume too much stack space. 92353944Sdim // We symbolize reports in a single thread, so this is fine. 93353944Sdim static char func_buf[1024]; 94353944Sdim static char file_buf[1024]; 95353944Sdim int line, col; 96353944Sdim SymbolizedStack *frame = SymbolizedStack::New(addr); 97353944Sdim if (__tsan_symbolize_external(addr, func_buf, sizeof(func_buf), file_buf, 98353944Sdim sizeof(file_buf), &line, &col)) { 99353944Sdim frame->info.function = internal_strdup(func_buf); 100353944Sdim frame->info.file = internal_strdup(file_buf); 101353944Sdim frame->info.line = line; 102353944Sdim frame->info.column = col; 103353944Sdim } 104353944Sdim return frame; 105353944Sdim } 106353944Sdim return Symbolizer::GetOrInit()->SymbolizePC(addr); 107353944Sdim} 108353944Sdim 109353944SdimReportLocation *SymbolizeData(uptr addr) { 110353944Sdim DataInfo info; 111353944Sdim if (!Symbolizer::GetOrInit()->SymbolizeData(addr, &info)) 112353944Sdim return 0; 113353944Sdim ReportLocation *ent = ReportLocation::New(ReportLocationGlobal); 114353944Sdim internal_memcpy(&ent->global, &info, sizeof(info)); 115353944Sdim return ent; 116353944Sdim} 117353944Sdim 118353944Sdimvoid SymbolizeFlush() { 119353944Sdim Symbolizer::GetOrInit()->Flush(); 120353944Sdim} 121353944Sdim 122353944Sdim} // namespace __tsan 123