Path: blob/main/contrib/llvm-project/compiler-rt/lib/tsan/go/tsan_go.cpp
35268 views
//===-- tsan_go.cpp -------------------------------------------------------===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//7//8// ThreadSanitizer runtime for Go language.9//10//===----------------------------------------------------------------------===//1112#include "tsan_rtl.h"13#include "tsan_symbolize.h"14#include "sanitizer_common/sanitizer_common.h"15#include <stdlib.h>1617namespace __tsan {1819void InitializeInterceptors() {20}2122void InitializeDynamicAnnotations() {23}2425bool IsExpectedReport(uptr addr, uptr size) {26return false;27}2829void *Alloc(uptr sz) { return InternalAlloc(sz); }3031void FreeImpl(void *p) { InternalFree(p); }3233// Callback into Go.34static void (*go_runtime_cb)(uptr cmd, void *ctx);3536enum {37CallbackGetProc = 0,38CallbackSymbolizeCode = 1,39CallbackSymbolizeData = 2,40};4142struct SymbolizeCodeContext {43uptr pc;44char *func;45char *file;46uptr line;47uptr off;48uptr res;49};5051SymbolizedStack *SymbolizeCode(uptr addr) {52SymbolizedStack *first = SymbolizedStack::New(addr);53SymbolizedStack *s = first;54for (;;) {55SymbolizeCodeContext cbctx;56internal_memset(&cbctx, 0, sizeof(cbctx));57cbctx.pc = addr;58go_runtime_cb(CallbackSymbolizeCode, &cbctx);59if (cbctx.res == 0)60break;61AddressInfo &info = s->info;62info.module_offset = cbctx.off;63info.function = internal_strdup(cbctx.func ? cbctx.func : "??");64info.file = internal_strdup(cbctx.file ? cbctx.file : "-");65info.line = cbctx.line;66info.column = 0;6768if (cbctx.pc == addr) // outermost (non-inlined) function69break;70addr = cbctx.pc;71// Allocate a stack entry for the parent of the inlined function.72SymbolizedStack *s2 = SymbolizedStack::New(addr);73s->next = s2;74s = s2;75}76return first;77}7879struct SymbolizeDataContext {80uptr addr;81uptr heap;82uptr start;83uptr size;84char *name;85char *file;86uptr line;87uptr res;88};8990ReportLocation *SymbolizeData(uptr addr) {91SymbolizeDataContext cbctx;92internal_memset(&cbctx, 0, sizeof(cbctx));93cbctx.addr = addr;94go_runtime_cb(CallbackSymbolizeData, &cbctx);95if (!cbctx.res)96return 0;97if (cbctx.heap) {98MBlock *b = ctx->metamap.GetBlock(cbctx.start);99if (!b)100return 0;101auto *loc = New<ReportLocation>();102loc->type = ReportLocationHeap;103loc->heap_chunk_start = cbctx.start;104loc->heap_chunk_size = b->siz;105loc->tid = b->tid;106loc->stack = SymbolizeStackId(b->stk);107return loc;108} else {109auto *loc = New<ReportLocation>();110loc->type = ReportLocationGlobal;111loc->global.name = internal_strdup(cbctx.name ? cbctx.name : "??");112loc->global.file = internal_strdup(cbctx.file ? cbctx.file : "??");113loc->global.line = cbctx.line;114loc->global.start = cbctx.start;115loc->global.size = cbctx.size;116return loc;117}118}119120static ThreadState *main_thr;121static bool inited;122123static Processor* get_cur_proc() {124if (UNLIKELY(!inited)) {125// Running Initialize().126// We have not yet returned the Processor to Go, so we cannot ask it back.127// Currently, Initialize() does not use the Processor, so return nullptr.128return nullptr;129}130Processor *proc;131go_runtime_cb(CallbackGetProc, &proc);132return proc;133}134135Processor *ThreadState::proc() {136return get_cur_proc();137}138139extern "C" {140141static ThreadState *AllocGoroutine() {142auto *thr = (ThreadState *)Alloc(sizeof(ThreadState));143internal_memset(thr, 0, sizeof(*thr));144return thr;145}146147void __tsan_init(ThreadState **thrp, Processor **procp,148void (*cb)(uptr cmd, void *cb)) {149go_runtime_cb = cb;150ThreadState *thr = AllocGoroutine();151main_thr = *thrp = thr;152Initialize(thr);153*procp = thr->proc1;154inited = true;155}156157void __tsan_fini() {158// FIXME: Not necessary thread 0.159ThreadState *thr = main_thr;160int res = Finalize(thr);161exit(res);162}163164void __tsan_map_shadow(uptr addr, uptr size) {165MapShadow(addr, size);166}167168void __tsan_read(ThreadState *thr, void *addr, void *pc) {169MemoryAccess(thr, (uptr)pc, (uptr)addr, 1, kAccessRead);170}171172void __tsan_read_pc(ThreadState *thr, void *addr, uptr callpc, uptr pc) {173if (callpc != 0)174FuncEntry(thr, callpc);175MemoryAccess(thr, (uptr)pc, (uptr)addr, 1, kAccessRead);176if (callpc != 0)177FuncExit(thr);178}179180void __tsan_write(ThreadState *thr, void *addr, void *pc) {181MemoryAccess(thr, (uptr)pc, (uptr)addr, 1, kAccessWrite);182}183184void __tsan_write_pc(ThreadState *thr, void *addr, uptr callpc, uptr pc) {185if (callpc != 0)186FuncEntry(thr, callpc);187MemoryAccess(thr, (uptr)pc, (uptr)addr, 1, kAccessWrite);188if (callpc != 0)189FuncExit(thr);190}191192void __tsan_read_range(ThreadState *thr, void *addr, uptr size, uptr pc) {193MemoryAccessRange(thr, (uptr)pc, (uptr)addr, size, false);194}195196void __tsan_write_range(ThreadState *thr, void *addr, uptr size, uptr pc) {197MemoryAccessRange(thr, (uptr)pc, (uptr)addr, size, true);198}199200void __tsan_func_enter(ThreadState *thr, void *pc) {201FuncEntry(thr, (uptr)pc);202}203204void __tsan_func_exit(ThreadState *thr) {205FuncExit(thr);206}207208void __tsan_malloc(ThreadState *thr, uptr pc, uptr p, uptr sz) {209CHECK(inited);210if (thr && pc)211ctx->metamap.AllocBlock(thr, pc, p, sz);212MemoryResetRange(thr, pc, (uptr)p, sz);213}214215void __tsan_free(uptr p, uptr sz) {216ctx->metamap.FreeRange(get_cur_proc(), p, sz, false);217}218219void __tsan_go_start(ThreadState *parent, ThreadState **pthr, void *pc) {220ThreadState *thr = AllocGoroutine();221*pthr = thr;222Tid goid = ThreadCreate(parent, (uptr)pc, 0, true);223ThreadStart(thr, goid, 0, ThreadType::Regular);224}225226void __tsan_go_end(ThreadState *thr) {227ThreadFinish(thr);228Free(thr);229}230231void __tsan_proc_create(Processor **pproc) {232*pproc = ProcCreate();233}234235void __tsan_proc_destroy(Processor *proc) {236ProcDestroy(proc);237}238239void __tsan_acquire(ThreadState *thr, void *addr) {240Acquire(thr, 0, (uptr)addr);241}242243void __tsan_release_acquire(ThreadState *thr, void *addr) {244ReleaseStoreAcquire(thr, 0, (uptr)addr);245}246247void __tsan_release(ThreadState *thr, void *addr) {248ReleaseStore(thr, 0, (uptr)addr);249}250251void __tsan_release_merge(ThreadState *thr, void *addr) {252Release(thr, 0, (uptr)addr);253}254255void __tsan_finalizer_goroutine(ThreadState *thr) { AcquireGlobal(thr); }256257void __tsan_mutex_before_lock(ThreadState *thr, uptr addr, uptr write) {258if (write)259MutexPreLock(thr, 0, addr);260else261MutexPreReadLock(thr, 0, addr);262}263264void __tsan_mutex_after_lock(ThreadState *thr, uptr addr, uptr write) {265if (write)266MutexPostLock(thr, 0, addr);267else268MutexPostReadLock(thr, 0, addr);269}270271void __tsan_mutex_before_unlock(ThreadState *thr, uptr addr, uptr write) {272if (write)273MutexUnlock(thr, 0, addr);274else275MutexReadUnlock(thr, 0, addr);276}277278void __tsan_go_ignore_sync_begin(ThreadState *thr) {279ThreadIgnoreSyncBegin(thr, 0);280}281282void __tsan_go_ignore_sync_end(ThreadState *thr) { ThreadIgnoreSyncEnd(thr); }283284void __tsan_report_count(u64 *pn) {285Lock lock(&ctx->report_mtx);286*pn = ctx->nreported;287}288289} // extern "C"290} // namespace __tsan291292293