Home | History | Annotate | Download | only in go
      1 //===-- tsan_go.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 // ThreadSanitizer runtime for Go language.
     11 //
     12 //===----------------------------------------------------------------------===//
     13 
     14 #include "tsan_rtl.h"
     15 #include "tsan_symbolize.h"
     16 #include "sanitizer_common/sanitizer_common.h"
     17 #include <stdlib.h>
     18 
     19 namespace __tsan {
     20 
     21 void InitializeInterceptors() {
     22 }
     23 
     24 void InitializeDynamicAnnotations() {
     25 }
     26 
     27 bool IsExpectedReport(uptr addr, uptr size) {
     28   return false;
     29 }
     30 
     31 ReportLocation *SymbolizeData(uptr addr) {
     32   return 0;
     33 }
     34 
     35 void *internal_alloc(MBlockType typ, uptr sz) {
     36   return InternalAlloc(sz);
     37 }
     38 
     39 void internal_free(void *p) {
     40   InternalFree(p);
     41 }
     42 
     43 struct SymbolizeContext {
     44   uptr pc;
     45   char *func;
     46   char *file;
     47   uptr line;
     48   uptr off;
     49   uptr res;
     50 };
     51 
     52 // Callback into Go.
     53 static void (*symbolize_cb)(SymbolizeContext *ctx);
     54 
     55 SymbolizedStack *SymbolizeCode(uptr addr) {
     56   SymbolizedStack *s = SymbolizedStack::New(addr);
     57   SymbolizeContext ctx;
     58   internal_memset(&ctx, 0, sizeof(ctx));
     59   ctx.pc = addr;
     60   symbolize_cb(&ctx);
     61   if (ctx.res) {
     62     AddressInfo &info = s->info;
     63     info.module_offset = ctx.off;
     64     info.function = internal_strdup(ctx.func ? ctx.func : "??");
     65     info.file = internal_strdup(ctx.file ? ctx.file : "-");
     66     info.line = ctx.line;
     67     info.column = 0;
     68   }
     69   return s;
     70 }
     71 
     72 extern "C" {
     73 
     74 static ThreadState *main_thr;
     75 static bool inited;
     76 
     77 static ThreadState *AllocGoroutine() {
     78   ThreadState *thr = (ThreadState*)internal_alloc(MBlockThreadContex,
     79       sizeof(ThreadState));
     80   internal_memset(thr, 0, sizeof(*thr));
     81   return thr;
     82 }
     83 
     84 void __tsan_init(ThreadState **thrp, void (*cb)(SymbolizeContext *cb)) {
     85   symbolize_cb = cb;
     86   ThreadState *thr = AllocGoroutine();
     87   main_thr = *thrp = thr;
     88   Initialize(thr);
     89   inited = true;
     90 }
     91 
     92 void __tsan_fini() {
     93   // FIXME: Not necessary thread 0.
     94   ThreadState *thr = main_thr;
     95   int res = Finalize(thr);
     96   exit(res);
     97 }
     98 
     99 void __tsan_map_shadow(uptr addr, uptr size) {
    100   MapShadow(addr, size);
    101 }
    102 
    103 void __tsan_read(ThreadState *thr, void *addr, void *pc) {
    104   MemoryRead(thr, (uptr)pc, (uptr)addr, kSizeLog1);
    105 }
    106 
    107 void __tsan_read_pc(ThreadState *thr, void *addr, uptr callpc, uptr pc) {
    108   if (callpc != 0)
    109     FuncEntry(thr, callpc);
    110   MemoryRead(thr, (uptr)pc, (uptr)addr, kSizeLog1);
    111   if (callpc != 0)
    112     FuncExit(thr);
    113 }
    114 
    115 void __tsan_write(ThreadState *thr, void *addr, void *pc) {
    116   MemoryWrite(thr, (uptr)pc, (uptr)addr, kSizeLog1);
    117 }
    118 
    119 void __tsan_write_pc(ThreadState *thr, void *addr, uptr callpc, uptr pc) {
    120   if (callpc != 0)
    121     FuncEntry(thr, callpc);
    122   MemoryWrite(thr, (uptr)pc, (uptr)addr, kSizeLog1);
    123   if (callpc != 0)
    124     FuncExit(thr);
    125 }
    126 
    127 void __tsan_read_range(ThreadState *thr, void *addr, uptr size, uptr pc) {
    128   MemoryAccessRange(thr, (uptr)pc, (uptr)addr, size, false);
    129 }
    130 
    131 void __tsan_write_range(ThreadState *thr, void *addr, uptr size, uptr pc) {
    132   MemoryAccessRange(thr, (uptr)pc, (uptr)addr, size, true);
    133 }
    134 
    135 void __tsan_func_enter(ThreadState *thr, void *pc) {
    136   FuncEntry(thr, (uptr)pc);
    137 }
    138 
    139 void __tsan_func_exit(ThreadState *thr) {
    140   FuncExit(thr);
    141 }
    142 
    143 void __tsan_malloc(void *p, uptr sz) {
    144   if (!inited)
    145     return;
    146   MemoryResetRange(0, 0, (uptr)p, sz);
    147 }
    148 
    149 void __tsan_go_start(ThreadState *parent, ThreadState **pthr, void *pc) {
    150   ThreadState *thr = AllocGoroutine();
    151   *pthr = thr;
    152   int goid = ThreadCreate(parent, (uptr)pc, 0, true);
    153   ThreadStart(thr, goid, 0);
    154 }
    155 
    156 void __tsan_go_end(ThreadState *thr) {
    157   ThreadFinish(thr);
    158   internal_free(thr);
    159 }
    160 
    161 void __tsan_acquire(ThreadState *thr, void *addr) {
    162   Acquire(thr, 0, (uptr)addr);
    163 }
    164 
    165 void __tsan_release(ThreadState *thr, void *addr) {
    166   ReleaseStore(thr, 0, (uptr)addr);
    167 }
    168 
    169 void __tsan_release_merge(ThreadState *thr, void *addr) {
    170   Release(thr, 0, (uptr)addr);
    171 }
    172 
    173 void __tsan_finalizer_goroutine(ThreadState *thr) {
    174   AcquireGlobal(thr, 0);
    175 }
    176 
    177 void __tsan_mutex_before_lock(ThreadState *thr, uptr addr, uptr write) {
    178 }
    179 
    180 void __tsan_mutex_after_lock(ThreadState *thr, uptr addr, uptr write) {
    181   if (write)
    182     MutexLock(thr, 0, addr);
    183   else
    184     MutexReadLock(thr, 0, addr);
    185 }
    186 
    187 void __tsan_mutex_before_unlock(ThreadState *thr, uptr addr, uptr write) {
    188   if (write)
    189     MutexUnlock(thr, 0, addr);
    190   else
    191     MutexReadUnlock(thr, 0, addr);
    192 }
    193 
    194 void __tsan_go_ignore_sync_begin(ThreadState *thr) {
    195   ThreadIgnoreSyncBegin(thr, 0);
    196 }
    197 
    198 void __tsan_go_ignore_sync_end(ThreadState *thr) {
    199   ThreadIgnoreSyncEnd(thr, 0);
    200 }
    201 
    202 }  // extern "C"
    203 }  // namespace __tsan
    204 
    205 namespace __sanitizer {
    206 
    207 void SymbolizerPrepareForSandboxing() {
    208   // Nothing to do here for Go.
    209 }
    210 
    211 }  // namespace __sanitizer
    212