Home | History | Annotate | Download | only in rtl
      1 //===-- tsan_symbolize.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 // This file is a part of ThreadSanitizer (TSan), a race detector.
     11 //
     12 //===----------------------------------------------------------------------===//
     13 
     14 #include "tsan_symbolize.h"
     15 
     16 #include "sanitizer_common/sanitizer_common.h"
     17 #include "sanitizer_common/sanitizer_placement_new.h"
     18 #include "sanitizer_common/sanitizer_symbolizer.h"
     19 #include "tsan_flags.h"
     20 #include "tsan_report.h"
     21 #include "tsan_rtl.h"
     22 
     23 namespace __tsan {
     24 
     25 void EnterSymbolizer() {
     26   ThreadState *thr = cur_thread();
     27   CHECK(!thr->in_symbolizer);
     28   thr->in_symbolizer = true;
     29   thr->ignore_interceptors++;
     30 }
     31 
     32 void ExitSymbolizer() {
     33   ThreadState *thr = cur_thread();
     34   CHECK(thr->in_symbolizer);
     35   thr->in_symbolizer = false;
     36   thr->ignore_interceptors--;
     37 }
     38 
     39 ReportStack *NewReportStackEntry(uptr addr) {
     40   ReportStack *ent = (ReportStack*)internal_alloc(MBlockReportStack,
     41                                                   sizeof(ReportStack));
     42   internal_memset(ent, 0, sizeof(*ent));
     43   ent->pc = addr;
     44   return ent;
     45 }
     46 
     47 static ReportStack *NewReportStackEntry(const AddressInfo &info) {
     48   ReportStack *ent = NewReportStackEntry(info.address);
     49   ent->module = StripModuleName(info.module);
     50   ent->offset = info.module_offset;
     51   if (info.function)
     52     ent->func = internal_strdup(info.function);
     53   if (info.file)
     54     ent->file = internal_strdup(info.file);
     55   ent->line = info.line;
     56   ent->col = info.column;
     57   return ent;
     58 }
     59 
     60 
     61   ReportStack *next;
     62   char *module;
     63   uptr offset;
     64   uptr pc;
     65   char *func;
     66   char *file;
     67   int line;
     68   int col;
     69 
     70 
     71 // Denotes fake PC values that come from JIT/JAVA/etc.
     72 // For such PC values __tsan_symbolize_external() will be called.
     73 const uptr kExternalPCBit = 1ULL << 60;
     74 
     75 // May be overriden by JIT/JAVA/etc,
     76 // whatever produces PCs marked with kExternalPCBit.
     77 extern "C" bool __tsan_symbolize_external(uptr pc,
     78                                char *func_buf, uptr func_siz,
     79                                char *file_buf, uptr file_siz,
     80                                int *line, int *col)
     81                                SANITIZER_WEAK_ATTRIBUTE;
     82 
     83 bool __tsan_symbolize_external(uptr pc,
     84                                char *func_buf, uptr func_siz,
     85                                char *file_buf, uptr file_siz,
     86                                int *line, int *col) {
     87   return false;
     88 }
     89 
     90 ReportStack *SymbolizeCode(uptr addr) {
     91   // Check if PC comes from non-native land.
     92   if (addr & kExternalPCBit) {
     93     // Declare static to not consume too much stack space.
     94     // We symbolize reports in a single thread, so this is fine.
     95     static char func_buf[1024];
     96     static char file_buf[1024];
     97     int line, col;
     98     if (!__tsan_symbolize_external(addr, func_buf, sizeof(func_buf),
     99                                   file_buf, sizeof(file_buf), &line, &col))
    100       return NewReportStackEntry(addr);
    101     ReportStack *ent = NewReportStackEntry(addr);
    102     ent->module = 0;
    103     ent->offset = 0;
    104     ent->func = internal_strdup(func_buf);
    105     ent->file = internal_strdup(file_buf);
    106     ent->line = line;
    107     ent->col = col;
    108     return ent;
    109   }
    110   static const uptr kMaxAddrFrames = 16;
    111   InternalScopedBuffer<AddressInfo> addr_frames(kMaxAddrFrames);
    112   for (uptr i = 0; i < kMaxAddrFrames; i++)
    113     new(&addr_frames[i]) AddressInfo();
    114   uptr addr_frames_num = Symbolizer::Get()->SymbolizePC(
    115       addr, addr_frames.data(), kMaxAddrFrames);
    116   if (addr_frames_num == 0)
    117     return NewReportStackEntry(addr);
    118   ReportStack *top = 0;
    119   ReportStack *bottom = 0;
    120   for (uptr i = 0; i < addr_frames_num; i++) {
    121     ReportStack *cur_entry = NewReportStackEntry(addr_frames[i]);
    122     CHECK(cur_entry);
    123     addr_frames[i].Clear();
    124     if (i == 0)
    125       top = cur_entry;
    126     else
    127       bottom->next = cur_entry;
    128     bottom = cur_entry;
    129   }
    130   return top;
    131 }
    132 
    133 ReportLocation *SymbolizeData(uptr addr) {
    134   DataInfo info;
    135   if (!Symbolizer::Get()->SymbolizeData(addr, &info))
    136     return 0;
    137   ReportLocation *ent = (ReportLocation*)internal_alloc(MBlockReportStack,
    138                                                         sizeof(ReportLocation));
    139   internal_memset(ent, 0, sizeof(*ent));
    140   ent->type = ReportLocationGlobal;
    141   ent->module = StripModuleName(info.module);
    142   ent->offset = info.module_offset;
    143   if (info.name)
    144     ent->name = internal_strdup(info.name);
    145   ent->addr = info.start;
    146   ent->size = info.size;
    147   return ent;
    148 }
    149 
    150 void SymbolizeFlush() {
    151   Symbolizer::Get()->Flush();
    152 }
    153 
    154 }  // namespace __tsan
    155