re PR tree-optimization/59100 (requesting optimization of safe rotate function)
[official-gcc.git] / libsanitizer / tsan / tsan_symbolize.cc
blobc0e794be2d2e80780921f1ea2d29920a5a6f1ac7
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 //===----------------------------------------------------------------------===//
12 #include "tsan_symbolize.h"
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"
21 namespace __tsan {
23 void EnterSymbolizer() {
24 ThreadState *thr = cur_thread();
25 CHECK(!thr->in_symbolizer);
26 thr->in_symbolizer = true;
29 void ExitSymbolizer() {
30 ThreadState *thr = cur_thread();
31 CHECK(thr->in_symbolizer);
32 thr->in_symbolizer = false;
35 ReportStack *NewReportStackEntry(uptr addr) {
36 ReportStack *ent = (ReportStack*)internal_alloc(MBlockReportStack,
37 sizeof(ReportStack));
38 internal_memset(ent, 0, sizeof(*ent));
39 ent->pc = addr;
40 return ent;
43 static ReportStack *NewReportStackEntry(const AddressInfo &info) {
44 ReportStack *ent = NewReportStackEntry(info.address);
45 ent->module = StripModuleName(info.module);
46 ent->offset = info.module_offset;
47 if (info.function)
48 ent->func = internal_strdup(info.function);
49 if (info.file)
50 ent->file = internal_strdup(info.file);
51 ent->line = info.line;
52 ent->col = info.column;
53 return ent;
57 ReportStack *next;
58 char *module;
59 uptr offset;
60 uptr pc;
61 char *func;
62 char *file;
63 int line;
64 int col;
67 // Denotes fake PC values that come from JIT/JAVA/etc.
68 // For such PC values __tsan_symbolize_external() will be called.
69 const uptr kExternalPCBit = 1ULL << 60;
71 // May be overriden by JIT/JAVA/etc,
72 // whatever produces PCs marked with kExternalPCBit.
73 extern "C" bool __tsan_symbolize_external(uptr pc,
74 char *func_buf, uptr func_siz,
75 char *file_buf, uptr file_siz,
76 int *line, int *col)
77 SANITIZER_WEAK_ATTRIBUTE;
79 bool __tsan_symbolize_external(uptr pc,
80 char *func_buf, uptr func_siz,
81 char *file_buf, uptr file_siz,
82 int *line, int *col) {
83 return false;
86 ReportStack *SymbolizeCode(uptr addr) {
87 // Check if PC comes from non-native land.
88 if (addr & kExternalPCBit) {
89 // Declare static to not consume too much stack space.
90 // We symbolize reports in a single thread, so this is fine.
91 static char func_buf[1024];
92 static char file_buf[1024];
93 int line, col;
94 if (!__tsan_symbolize_external(addr, func_buf, sizeof(func_buf),
95 file_buf, sizeof(file_buf), &line, &col))
96 return NewReportStackEntry(addr);
97 ReportStack *ent = NewReportStackEntry(addr);
98 ent->module = 0;
99 ent->offset = 0;
100 ent->func = internal_strdup(func_buf);
101 ent->file = internal_strdup(file_buf);
102 ent->line = line;
103 ent->col = col;
104 return ent;
106 if (!Symbolizer::Get()->IsAvailable())
107 return SymbolizeCodeAddr2Line(addr);
108 static const uptr kMaxAddrFrames = 16;
109 InternalScopedBuffer<AddressInfo> addr_frames(kMaxAddrFrames);
110 for (uptr i = 0; i < kMaxAddrFrames; i++)
111 new(&addr_frames[i]) AddressInfo();
112 uptr addr_frames_num = Symbolizer::Get()->SymbolizeCode(
113 addr, addr_frames.data(), kMaxAddrFrames);
114 if (addr_frames_num == 0)
115 return NewReportStackEntry(addr);
116 ReportStack *top = 0;
117 ReportStack *bottom = 0;
118 for (uptr i = 0; i < addr_frames_num; i++) {
119 ReportStack *cur_entry = NewReportStackEntry(addr_frames[i]);
120 CHECK(cur_entry);
121 addr_frames[i].Clear();
122 if (i == 0)
123 top = cur_entry;
124 else
125 bottom->next = cur_entry;
126 bottom = cur_entry;
128 return top;
131 ReportLocation *SymbolizeData(uptr addr) {
132 if (!Symbolizer::Get()->IsAvailable())
133 return 0;
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;
150 void SymbolizeFlush() {
151 if (!Symbolizer::Get()->IsAvailable())
152 return;
153 Symbolizer::Get()->Flush();
156 } // namespace __tsan