1 //===-- tsan_symbolize.cc -------------------------------------------------===//
3 // This file is distributed under the University of Illinois Open Source
4 // License. See LICENSE.TXT for details.
6 //===----------------------------------------------------------------------===//
8 // This file is a part of ThreadSanitizer (TSan), a race detector.
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"
23 void EnterSymbolizer() {
24 ThreadState
*thr
= cur_thread();
25 CHECK(!thr
->in_symbolizer
);
26 thr
->in_symbolizer
= true;
27 thr
->ignore_interceptors
++;
30 void ExitSymbolizer() {
31 ThreadState
*thr
= cur_thread();
32 CHECK(thr
->in_symbolizer
);
33 thr
->in_symbolizer
= false;
34 thr
->ignore_interceptors
--;
37 ReportStack
*NewReportStackEntry(uptr addr
) {
38 ReportStack
*ent
= (ReportStack
*)internal_alloc(MBlockReportStack
,
40 internal_memset(ent
, 0, sizeof(*ent
));
45 static ReportStack
*NewReportStackEntry(const AddressInfo
&info
) {
46 ReportStack
*ent
= NewReportStackEntry(info
.address
);
47 ent
->module
= StripModuleName(info
.module
);
48 ent
->offset
= info
.module_offset
;
50 ent
->func
= internal_strdup(info
.function
);
52 ent
->file
= internal_strdup(info
.file
);
53 ent
->line
= info
.line
;
54 ent
->col
= info
.column
;
69 // Denotes fake PC values that come from JIT/JAVA/etc.
70 // For such PC values __tsan_symbolize_external() will be called.
71 const uptr kExternalPCBit
= 1ULL << 60;
73 // May be overriden by JIT/JAVA/etc,
74 // whatever produces PCs marked with kExternalPCBit.
75 extern "C" bool __tsan_symbolize_external(uptr pc
,
76 char *func_buf
, uptr func_siz
,
77 char *file_buf
, uptr file_siz
,
79 SANITIZER_WEAK_ATTRIBUTE
;
81 bool __tsan_symbolize_external(uptr pc
,
82 char *func_buf
, uptr func_siz
,
83 char *file_buf
, uptr file_siz
,
84 int *line
, int *col
) {
88 ReportStack
*SymbolizeCode(uptr addr
) {
89 // Check if PC comes from non-native land.
90 if (addr
& kExternalPCBit
) {
91 // Declare static to not consume too much stack space.
92 // We symbolize reports in a single thread, so this is fine.
93 static char func_buf
[1024];
94 static char file_buf
[1024];
96 if (!__tsan_symbolize_external(addr
, func_buf
, sizeof(func_buf
),
97 file_buf
, sizeof(file_buf
), &line
, &col
))
98 return NewReportStackEntry(addr
);
99 ReportStack
*ent
= NewReportStackEntry(addr
);
102 ent
->func
= internal_strdup(func_buf
);
103 ent
->file
= internal_strdup(file_buf
);
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()->SymbolizePC(
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
]);
121 addr_frames
[i
].Clear();
125 bottom
->next
= cur_entry
;
131 ReportLocation
*SymbolizeData(uptr addr
) {
133 if (!Symbolizer::Get()->SymbolizeData(addr
, &info
))
135 ReportLocation
*ent
= (ReportLocation
*)internal_alloc(MBlockReportStack
,
136 sizeof(ReportLocation
));
137 internal_memset(ent
, 0, sizeof(*ent
));
138 ent
->type
= ReportLocationGlobal
;
139 ent
->module
= StripModuleName(info
.module
);
140 ent
->offset
= info
.module_offset
;
142 ent
->name
= internal_strdup(info
.name
);
143 ent
->addr
= info
.start
;
144 ent
->size
= info
.size
;
148 void SymbolizeFlush() {
149 Symbolizer::Get()->Flush();
152 } // namespace __tsan