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 // Denotes fake PC values that come from JIT/JAVA/etc.
38 // For such PC values __tsan_symbolize_external() will be called.
39 const uptr kExternalPCBit
= 1ULL << 60;
41 // May be overriden by JIT/JAVA/etc,
42 // whatever produces PCs marked with kExternalPCBit.
43 extern "C" bool __tsan_symbolize_external(uptr pc
,
44 char *func_buf
, uptr func_siz
,
45 char *file_buf
, uptr file_siz
,
47 SANITIZER_WEAK_ATTRIBUTE
;
49 bool __tsan_symbolize_external(uptr pc
,
50 char *func_buf
, uptr func_siz
,
51 char *file_buf
, uptr file_siz
,
52 int *line
, int *col
) {
56 ReportStack
*SymbolizeCode(uptr addr
) {
57 // Check if PC comes from non-native land.
58 if (addr
& kExternalPCBit
) {
59 // Declare static to not consume too much stack space.
60 // We symbolize reports in a single thread, so this is fine.
61 static char func_buf
[1024];
62 static char file_buf
[1024];
64 ReportStack
*ent
= ReportStack::New(addr
);
65 if (!__tsan_symbolize_external(addr
, func_buf
, sizeof(func_buf
),
66 file_buf
, sizeof(file_buf
), &line
, &col
))
68 ent
->info
.function
= internal_strdup(func_buf
);
69 ent
->info
.file
= internal_strdup(file_buf
);
70 ent
->info
.line
= line
;
71 ent
->info
.column
= col
;
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
= Symbolizer::GetOrInit()->SymbolizePC(
79 addr
, addr_frames
.data(), kMaxAddrFrames
);
80 if (addr_frames_num
== 0)
81 return ReportStack::New(addr
);
83 ReportStack
*bottom
= 0;
84 for (uptr i
= 0; i
< addr_frames_num
; i
++) {
85 ReportStack
*cur_entry
= ReportStack::New(addr
);
86 cur_entry
->info
= addr_frames
[i
];
90 bottom
->next
= cur_entry
;
96 ReportLocation
*SymbolizeData(uptr addr
) {
98 if (!Symbolizer::GetOrInit()->SymbolizeData(addr
, &info
))
100 ReportLocation
*ent
= ReportLocation::New(ReportLocationGlobal
);
105 void SymbolizeFlush() {
106 Symbolizer::GetOrInit()->Flush();
109 } // namespace __tsan