124 lines · cpp
1//===-- tsan_symbolize.cpp ------------------------------------------------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8//9// This file is a part of ThreadSanitizer (TSan), a race detector.10//11//===----------------------------------------------------------------------===//12 13#include "tsan_symbolize.h"14 15#include "sanitizer_common/sanitizer_common.h"16#include "sanitizer_common/sanitizer_placement_new.h"17#include "sanitizer_common/sanitizer_symbolizer.h"18#include "tsan_flags.h"19#include "tsan_report.h"20#include "tsan_rtl.h"21 22namespace __tsan {23 24void EnterSymbolizer() {25 ThreadState *thr = cur_thread();26 CHECK(!thr->in_symbolizer);27 thr->in_symbolizer = true;28 thr->ignore_interceptors++;29}30 31void ExitSymbolizer() {32 ThreadState *thr = cur_thread();33 CHECK(thr->in_symbolizer);34 thr->in_symbolizer = false;35 thr->ignore_interceptors--;36}37 38// Legacy API.39// May be overriden by JIT/JAVA/etc,40// whatever produces PCs marked with kExternalPCBit.41SANITIZER_WEAK_DEFAULT_IMPL42bool __tsan_symbolize_external(uptr pc, char *func_buf, uptr func_siz,43 char *file_buf, uptr file_siz, int *line,44 int *col) {45 return false;46}47 48// New API: call __tsan_symbolize_external_ex only when it exists.49// Once old clients are gone, provide dummy implementation.50SANITIZER_WEAK_DEFAULT_IMPL51void __tsan_symbolize_external_ex(uptr pc,52 void (*add_frame)(void *, const char *,53 const char *, int, int),54 void *ctx) {}55 56struct SymbolizedStackBuilder {57 SymbolizedStack *head;58 SymbolizedStack *tail;59 uptr addr;60};61 62static void AddFrame(void *ctx, const char *function_name, const char *file,63 int line, int column) {64 SymbolizedStackBuilder *ssb = (struct SymbolizedStackBuilder *)ctx;65 if (ssb->tail) {66 ssb->tail->next = SymbolizedStack::New(ssb->addr);67 ssb->tail = ssb->tail->next;68 } else {69 ssb->head = ssb->tail = SymbolizedStack::New(ssb->addr);70 }71 AddressInfo *info = &ssb->tail->info;72 if (function_name) {73 info->function = internal_strdup(function_name);74 }75 if (file) {76 info->file = internal_strdup(file);77 }78 info->line = line;79 info->column = column;80}81 82SymbolizedStack *SymbolizeCode(uptr addr) {83 // Check if PC comes from non-native land.84 if (addr & kExternalPCBit) {85 SymbolizedStackBuilder ssb = {nullptr, nullptr, addr};86 __tsan_symbolize_external_ex(addr, AddFrame, &ssb);87 if (ssb.head)88 return ssb.head;89 // Legacy code: remove along with the declaration above90 // once all clients using this API are gone.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 SymbolizedStack *frame = SymbolizedStack::New(addr);97 if (__tsan_symbolize_external(addr, func_buf, sizeof(func_buf), file_buf,98 sizeof(file_buf), &line, &col)) {99 frame->info.function = internal_strdup(func_buf);100 frame->info.file = internal_strdup(file_buf);101 frame->info.line = line;102 frame->info.column = col;103 }104 return frame;105 }106 return Symbolizer::GetOrInit()->SymbolizePC(addr);107}108 109ReportLocation *SymbolizeData(uptr addr) {110 DataInfo info;111 if (!Symbolizer::GetOrInit()->SymbolizeData(addr, &info))112 return 0;113 auto *ent = New<ReportLocation>();114 ent->type = ReportLocationGlobal;115 internal_memcpy(&ent->global, &info, sizeof(info));116 return ent;117}118 119void SymbolizeFlush() {120 Symbolizer::GetOrInit()->Flush();121}122 123} // namespace __tsan124