• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
EnterSymbolizer()25 void EnterSymbolizer() {
26   ThreadState *thr = cur_thread();
27   CHECK(!thr->in_symbolizer);
28   thr->in_symbolizer = true;
29   thr->ignore_interceptors++;
30 }
31 
ExitSymbolizer()32 void ExitSymbolizer() {
33   ThreadState *thr = cur_thread();
34   CHECK(thr->in_symbolizer);
35   thr->in_symbolizer = false;
36   thr->ignore_interceptors--;
37 }
38 
NewReportStackEntry(uptr addr)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 
NewReportStackEntry(const AddressInfo & info)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 
__tsan_symbolize_external(uptr pc,char * func_buf,uptr func_siz,char * file_buf,uptr file_siz,int * line,int * col)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 
SymbolizeCode(uptr addr)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 
SymbolizeData(uptr addr)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 
SymbolizeFlush()150 void SymbolizeFlush() {
151   Symbolizer::Get()->Flush();
152 }
153 
154 }  // namespace __tsan
155