1*ee754c2dSkamil //===-- tsan_symbolize.cc -------------------------------------------------===//
2*ee754c2dSkamil //
3*ee754c2dSkamil //                     The LLVM Compiler Infrastructure
4*ee754c2dSkamil //
5*ee754c2dSkamil // This file is distributed under the University of Illinois Open Source
6*ee754c2dSkamil // License. See LICENSE.TXT for details.
7*ee754c2dSkamil //
8*ee754c2dSkamil //===----------------------------------------------------------------------===//
9*ee754c2dSkamil //
10*ee754c2dSkamil // This file is a part of ThreadSanitizer (TSan), a race detector.
11*ee754c2dSkamil //
12*ee754c2dSkamil //===----------------------------------------------------------------------===//
13*ee754c2dSkamil 
14*ee754c2dSkamil #include "tsan_symbolize.h"
15*ee754c2dSkamil 
16*ee754c2dSkamil #include "sanitizer_common/sanitizer_common.h"
17*ee754c2dSkamil #include "sanitizer_common/sanitizer_placement_new.h"
18*ee754c2dSkamil #include "sanitizer_common/sanitizer_symbolizer.h"
19*ee754c2dSkamil #include "tsan_flags.h"
20*ee754c2dSkamil #include "tsan_report.h"
21*ee754c2dSkamil #include "tsan_rtl.h"
22*ee754c2dSkamil 
23*ee754c2dSkamil namespace __tsan {
24*ee754c2dSkamil 
EnterSymbolizer()25*ee754c2dSkamil void EnterSymbolizer() {
26*ee754c2dSkamil   ThreadState *thr = cur_thread();
27*ee754c2dSkamil   CHECK(!thr->in_symbolizer);
28*ee754c2dSkamil   thr->in_symbolizer = true;
29*ee754c2dSkamil   thr->ignore_interceptors++;
30*ee754c2dSkamil }
31*ee754c2dSkamil 
ExitSymbolizer()32*ee754c2dSkamil void ExitSymbolizer() {
33*ee754c2dSkamil   ThreadState *thr = cur_thread();
34*ee754c2dSkamil   CHECK(thr->in_symbolizer);
35*ee754c2dSkamil   thr->in_symbolizer = false;
36*ee754c2dSkamil   thr->ignore_interceptors--;
37*ee754c2dSkamil }
38*ee754c2dSkamil 
39*ee754c2dSkamil // Legacy API.
40*ee754c2dSkamil // May be overriden by JIT/JAVA/etc,
41*ee754c2dSkamil // whatever produces PCs marked with kExternalPCBit.
42*ee754c2dSkamil SANITIZER_WEAK_DEFAULT_IMPL
__tsan_symbolize_external(uptr pc,char * func_buf,uptr func_siz,char * file_buf,uptr file_siz,int * line,int * col)43*ee754c2dSkamil bool __tsan_symbolize_external(uptr pc, char *func_buf, uptr func_siz,
44*ee754c2dSkamil                                char *file_buf, uptr file_siz, int *line,
45*ee754c2dSkamil                                int *col) {
46*ee754c2dSkamil   return false;
47*ee754c2dSkamil }
48*ee754c2dSkamil 
49*ee754c2dSkamil // New API: call __tsan_symbolize_external_ex only when it exists.
50*ee754c2dSkamil // Once old clients are gone, provide dummy implementation.
51*ee754c2dSkamil SANITIZER_WEAK_DEFAULT_IMPL
__tsan_symbolize_external_ex(uptr pc,void (* add_frame)(void *,const char *,const char *,int,int),void * ctx)52*ee754c2dSkamil void __tsan_symbolize_external_ex(uptr pc,
53*ee754c2dSkamil                                   void (*add_frame)(void *, const char *,
54*ee754c2dSkamil                                                     const char *, int, int),
55*ee754c2dSkamil                                   void *ctx) {}
56*ee754c2dSkamil 
57*ee754c2dSkamil struct SymbolizedStackBuilder {
58*ee754c2dSkamil   SymbolizedStack *head;
59*ee754c2dSkamil   SymbolizedStack *tail;
60*ee754c2dSkamil   uptr addr;
61*ee754c2dSkamil };
62*ee754c2dSkamil 
AddFrame(void * ctx,const char * function_name,const char * file,int line,int column)63*ee754c2dSkamil static void AddFrame(void *ctx, const char *function_name, const char *file,
64*ee754c2dSkamil                      int line, int column) {
65*ee754c2dSkamil   SymbolizedStackBuilder *ssb = (struct SymbolizedStackBuilder *)ctx;
66*ee754c2dSkamil   if (ssb->tail) {
67*ee754c2dSkamil     ssb->tail->next = SymbolizedStack::New(ssb->addr);
68*ee754c2dSkamil     ssb->tail = ssb->tail->next;
69*ee754c2dSkamil   } else {
70*ee754c2dSkamil     ssb->head = ssb->tail = SymbolizedStack::New(ssb->addr);
71*ee754c2dSkamil   }
72*ee754c2dSkamil   AddressInfo *info = &ssb->tail->info;
73*ee754c2dSkamil   if (function_name) {
74*ee754c2dSkamil     info->function = internal_strdup(function_name);
75*ee754c2dSkamil   }
76*ee754c2dSkamil   if (file) {
77*ee754c2dSkamil     info->file = internal_strdup(file);
78*ee754c2dSkamil   }
79*ee754c2dSkamil   info->line = line;
80*ee754c2dSkamil   info->column = column;
81*ee754c2dSkamil }
82*ee754c2dSkamil 
SymbolizeCode(uptr addr)83*ee754c2dSkamil SymbolizedStack *SymbolizeCode(uptr addr) {
84*ee754c2dSkamil   // Check if PC comes from non-native land.
85*ee754c2dSkamil   if (addr & kExternalPCBit) {
86*ee754c2dSkamil     SymbolizedStackBuilder ssb = {nullptr, nullptr, addr};
87*ee754c2dSkamil     __tsan_symbolize_external_ex(addr, AddFrame, &ssb);
88*ee754c2dSkamil     if (ssb.head)
89*ee754c2dSkamil       return ssb.head;
90*ee754c2dSkamil     // Legacy code: remove along with the declaration above
91*ee754c2dSkamil     // once all clients using this API are gone.
92*ee754c2dSkamil     // Declare static to not consume too much stack space.
93*ee754c2dSkamil     // We symbolize reports in a single thread, so this is fine.
94*ee754c2dSkamil     static char func_buf[1024];
95*ee754c2dSkamil     static char file_buf[1024];
96*ee754c2dSkamil     int line, col;
97*ee754c2dSkamil     SymbolizedStack *frame = SymbolizedStack::New(addr);
98*ee754c2dSkamil     if (__tsan_symbolize_external(addr, func_buf, sizeof(func_buf), file_buf,
99*ee754c2dSkamil                                   sizeof(file_buf), &line, &col)) {
100*ee754c2dSkamil       frame->info.function = internal_strdup(func_buf);
101*ee754c2dSkamil       frame->info.file = internal_strdup(file_buf);
102*ee754c2dSkamil       frame->info.line = line;
103*ee754c2dSkamil       frame->info.column = col;
104*ee754c2dSkamil     }
105*ee754c2dSkamil     return frame;
106*ee754c2dSkamil   }
107*ee754c2dSkamil   return Symbolizer::GetOrInit()->SymbolizePC(addr);
108*ee754c2dSkamil }
109*ee754c2dSkamil 
SymbolizeData(uptr addr)110*ee754c2dSkamil ReportLocation *SymbolizeData(uptr addr) {
111*ee754c2dSkamil   DataInfo info;
112*ee754c2dSkamil   if (!Symbolizer::GetOrInit()->SymbolizeData(addr, &info))
113*ee754c2dSkamil     return 0;
114*ee754c2dSkamil   ReportLocation *ent = ReportLocation::New(ReportLocationGlobal);
115*ee754c2dSkamil   internal_memcpy(&ent->global, &info, sizeof(info));
116*ee754c2dSkamil   return ent;
117*ee754c2dSkamil }
118*ee754c2dSkamil 
SymbolizeFlush()119*ee754c2dSkamil void SymbolizeFlush() {
120*ee754c2dSkamil   Symbolizer::GetOrInit()->Flush();
121*ee754c2dSkamil }
122*ee754c2dSkamil 
123*ee754c2dSkamil }  // namespace __tsan
124