xref: /netbsd-src/external/gpl3/gcc.old/dist/libsanitizer/tsan/tsan_symbolize.cc (revision 63aea4bd5b445e491ff0389fe27ec78b3099dba3)
1 //===-- tsan_symbolize.cc -------------------------------------------------===//
2 //
3 // This file is distributed under the University of Illinois Open Source
4 // License. See LICENSE.TXT for details.
5 //
6 //===----------------------------------------------------------------------===//
7 //
8 // This file is a part of ThreadSanitizer (TSan), a race detector.
9 //
10 //===----------------------------------------------------------------------===//
11 
12 #include "tsan_symbolize.h"
13 
14 #include "sanitizer_common/sanitizer_common.h"
15 #include "sanitizer_common/sanitizer_placement_new.h"
16 #include "sanitizer_common/sanitizer_symbolizer.h"
17 #include "tsan_flags.h"
18 #include "tsan_report.h"
19 #include "tsan_rtl.h"
20 
21 namespace __tsan {
22 
23 struct ScopedInSymbolizer {
24   ScopedInSymbolizer() {
25     ThreadState *thr = cur_thread();
26     CHECK(!thr->in_symbolizer);
27     thr->in_symbolizer = true;
28   }
29 
30   ~ScopedInSymbolizer() {
31     ThreadState *thr = cur_thread();
32     CHECK(thr->in_symbolizer);
33     thr->in_symbolizer = false;
34   }
35 };
36 
37 ReportStack *NewReportStackEntry(uptr addr) {
38   ReportStack *ent = (ReportStack*)internal_alloc(MBlockReportStack,
39                                                   sizeof(ReportStack));
40   internal_memset(ent, 0, sizeof(*ent));
41   ent->pc = addr;
42   return ent;
43 }
44 
45 // Strip module path to make output shorter.
46 static char *StripModuleName(const char *module) {
47   if (module == 0)
48     return 0;
49   const char *short_module_name = internal_strrchr(module, '/');
50   if (short_module_name)
51     short_module_name += 1;
52   else
53     short_module_name = module;
54   return internal_strdup(short_module_name);
55 }
56 
57 static ReportStack *NewReportStackEntry(const AddressInfo &info) {
58   ReportStack *ent = NewReportStackEntry(info.address);
59   ent->module = StripModuleName(info.module);
60   ent->offset = info.module_offset;
61   if (info.function)
62     ent->func = internal_strdup(info.function);
63   if (info.file)
64     ent->file = internal_strdup(info.file);
65   ent->line = info.line;
66   ent->col = info.column;
67   return ent;
68 }
69 
70 ReportStack *SymbolizeCode(uptr addr) {
71   if (!IsSymbolizerAvailable())
72     return SymbolizeCodeAddr2Line(addr);
73   ScopedInSymbolizer in_symbolizer;
74   static const uptr kMaxAddrFrames = 16;
75   InternalScopedBuffer<AddressInfo> addr_frames(kMaxAddrFrames);
76   for (uptr i = 0; i < kMaxAddrFrames; i++)
77     new(&addr_frames[i]) AddressInfo();
78   uptr addr_frames_num = __sanitizer::SymbolizeCode(addr, addr_frames.data(),
79                                                     kMaxAddrFrames);
80   if (addr_frames_num == 0)
81     return NewReportStackEntry(addr);
82   ReportStack *top = 0;
83   ReportStack *bottom = 0;
84   for (uptr i = 0; i < addr_frames_num; i++) {
85     ReportStack *cur_entry = NewReportStackEntry(addr_frames[i]);
86     CHECK(cur_entry);
87     addr_frames[i].Clear();
88     if (i == 0)
89       top = cur_entry;
90     else
91       bottom->next = cur_entry;
92     bottom = cur_entry;
93   }
94   return top;
95 }
96 
97 ReportLocation *SymbolizeData(uptr addr) {
98   if (!IsSymbolizerAvailable())
99     return 0;
100   ScopedInSymbolizer in_symbolizer;
101   DataInfo info;
102   if (!__sanitizer::SymbolizeData(addr, &info))
103     return 0;
104   ReportLocation *ent = (ReportLocation*)internal_alloc(MBlockReportStack,
105                                                         sizeof(ReportLocation));
106   internal_memset(ent, 0, sizeof(*ent));
107   ent->type = ReportLocationGlobal;
108   ent->module = StripModuleName(info.module);
109   ent->offset = info.module_offset;
110   if (info.name)
111     ent->name = internal_strdup(info.name);
112   ent->addr = info.start;
113   ent->size = info.size;
114   return ent;
115 }
116 
117 }  // namespace __tsan
118