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