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 struct ScopedInSymbolizer {
     26   ScopedInSymbolizer() {
     27     ThreadState *thr = cur_thread();
     28     CHECK(!thr->in_symbolizer);
     29     thr->in_symbolizer = true;
     30   }
     31 
     32   ~ScopedInSymbolizer() {
     33     ThreadState *thr = cur_thread();
     34     CHECK(thr->in_symbolizer);
     35     thr->in_symbolizer = false;
     36   }
     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 // Strip module path to make output shorter.
     48 static char *StripModuleName(const char *module) {
     49   if (module == 0)
     50     return 0;
     51   const char *short_module_name = internal_strrchr(module, '/');
     52   if (short_module_name)
     53     short_module_name += 1;
     54   else
     55     short_module_name = module;
     56   return internal_strdup(short_module_name);
     57 }
     58 
     59 static ReportStack *NewReportStackEntry(const AddressInfo &info) {
     60   ReportStack *ent = NewReportStackEntry(info.address);
     61   ent->module = StripModuleName(info.module);
     62   ent->offset = info.module_offset;
     63   if (info.function)
     64     ent->func = internal_strdup(info.function);
     65   if (info.file)
     66     ent->file = internal_strdup(info.file);
     67   ent->line = info.line;
     68   ent->col = info.column;
     69   return ent;
     70 }
     71 
     72 ReportStack *SymbolizeCode(uptr addr) {
     73   if (!IsSymbolizerAvailable())
     74     return SymbolizeCodeAddr2Line(addr);
     75   ScopedInSymbolizer in_symbolizer;
     76   static const uptr kMaxAddrFrames = 16;
     77   InternalScopedBuffer<AddressInfo> addr_frames(kMaxAddrFrames);
     78   for (uptr i = 0; i < kMaxAddrFrames; i++)
     79     new(&addr_frames[i]) AddressInfo();
     80   uptr addr_frames_num = __sanitizer::SymbolizeCode(addr, addr_frames.data(),
     81                                                     kMaxAddrFrames);
     82   if (addr_frames_num == 0)
     83     return NewReportStackEntry(addr);
     84   ReportStack *top = 0;
     85   ReportStack *bottom = 0;
     86   for (uptr i = 0; i < addr_frames_num; i++) {
     87     ReportStack *cur_entry = NewReportStackEntry(addr_frames[i]);
     88     CHECK(cur_entry);
     89     addr_frames[i].Clear();
     90     if (i == 0)
     91       top = cur_entry;
     92     else
     93       bottom->next = cur_entry;
     94     bottom = cur_entry;
     95   }
     96   return top;
     97 }
     98 
     99 ReportLocation *SymbolizeData(uptr addr) {
    100   if (!IsSymbolizerAvailable())
    101     return 0;
    102   ScopedInSymbolizer in_symbolizer;
    103   DataInfo info;
    104   if (!__sanitizer::SymbolizeData(addr, &info))
    105     return 0;
    106   ReportLocation *ent = (ReportLocation*)internal_alloc(MBlockReportStack,
    107                                                         sizeof(ReportLocation));
    108   internal_memset(ent, 0, sizeof(*ent));
    109   ent->type = ReportLocationGlobal;
    110   ent->module = StripModuleName(info.module);
    111   ent->offset = info.module_offset;
    112   if (info.name)
    113     ent->name = internal_strdup(info.name);
    114   ent->addr = info.start;
    115   ent->size = info.size;
    116   return ent;
    117 }
    118 
    119 void SymbolizeFlush() {
    120   if (!IsSymbolizerAvailable())
    121     return;
    122   ScopedInSymbolizer in_symbolizer;
    123   __sanitizer::FlushSymbolizer();
    124 }
    125 
    126 }  // namespace __tsan
    127