1 //===-- tsan_symbolize.cc -------------------------------------------------===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 // This file is a part of ThreadSanitizer (TSan), a race detector.
12 //===----------------------------------------------------------------------===//
14 #include "tsan_symbolize.h"
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"
25 void EnterSymbolizer() {
26 ThreadState
*thr
= cur_thread();
27 CHECK(!thr
->in_symbolizer
);
28 thr
->in_symbolizer
= true;
31 void ExitSymbolizer() {
32 ThreadState
*thr
= cur_thread();
33 CHECK(thr
->in_symbolizer
);
34 thr
->in_symbolizer
= false;
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 if (!Symbolizer::Get()->IsAvailable())
109 return SymbolizeCodeAddr2Line(addr
);
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
]);
123 addr_frames
[i
].Clear();
127 bottom
->next
= cur_entry
;
133 ReportLocation
*SymbolizeData(uptr addr
) {
134 if (!Symbolizer::Get()->IsAvailable())
137 if (!Symbolizer::Get()->SymbolizeData(addr
, &info
))
139 ReportLocation
*ent
= (ReportLocation
*)internal_alloc(MBlockReportStack
,
140 sizeof(ReportLocation
));
141 internal_memset(ent
, 0, sizeof(*ent
));
142 ent
->type
= ReportLocationGlobal
;
143 ent
->module
= StripModuleName(info
.module
);
144 ent
->offset
= info
.module_offset
;
146 ent
->name
= internal_strdup(info
.name
);
147 ent
->addr
= info
.start
;
148 ent
->size
= info
.size
;
152 void SymbolizeFlush() {
153 if (!Symbolizer::Get()->IsAvailable())
155 Symbolizer::Get()->Flush();
158 } // namespace __tsan