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
--;
38 // May be overriden by JIT/JAVA/etc,
39 // whatever produces PCs marked with kExternalPCBit.
40 SANITIZER_WEAK_DEFAULT_IMPL
41 bool __tsan_symbolize_external(uptr pc
, char *func_buf
, uptr func_siz
,
42 char *file_buf
, uptr file_siz
, int *line
,
47 // New API: call __tsan_symbolize_external_ex only when it exists.
48 // Once old clients are gone, provide dummy implementation.
49 SANITIZER_WEAK_DEFAULT_IMPL
50 void __tsan_symbolize_external_ex(uptr pc
,
51 void (*add_frame
)(void *, const char *,
52 const char *, int, int),
55 struct SymbolizedStackBuilder
{
56 SymbolizedStack
*head
;
57 SymbolizedStack
*tail
;
61 static void AddFrame(void *ctx
, const char *function_name
, const char *file
,
62 int line
, int column
) {
63 SymbolizedStackBuilder
*ssb
= (struct SymbolizedStackBuilder
*)ctx
;
65 ssb
->tail
->next
= SymbolizedStack::New(ssb
->addr
);
66 ssb
->tail
= ssb
->tail
->next
;
68 ssb
->head
= ssb
->tail
= SymbolizedStack::New(ssb
->addr
);
70 AddressInfo
*info
= &ssb
->tail
->info
;
72 info
->function
= internal_strdup(function_name
);
75 info
->file
= internal_strdup(file
);
78 info
->column
= column
;
81 SymbolizedStack
*SymbolizeCode(uptr addr
) {
82 // Check if PC comes from non-native land.
83 if (addr
& kExternalPCBit
) {
84 SymbolizedStackBuilder ssb
= {nullptr, nullptr, addr
};
85 __tsan_symbolize_external_ex(addr
, AddFrame
, &ssb
);
88 // Legacy code: remove along with the declaration above
89 // once all clients using this API are gone.
90 // Declare static to not consume too much stack space.
91 // We symbolize reports in a single thread, so this is fine.
92 static char func_buf
[1024];
93 static char file_buf
[1024];
95 SymbolizedStack
*frame
= SymbolizedStack::New(addr
);
96 if (__tsan_symbolize_external(addr
, func_buf
, sizeof(func_buf
), file_buf
,
97 sizeof(file_buf
), &line
, &col
)) {
98 frame
->info
.function
= internal_strdup(func_buf
);
99 frame
->info
.file
= internal_strdup(file_buf
);
100 frame
->info
.line
= line
;
101 frame
->info
.column
= col
;
105 return Symbolizer::GetOrInit()->SymbolizePC(addr
);
108 ReportLocation
*SymbolizeData(uptr addr
) {
110 if (!Symbolizer::GetOrInit()->SymbolizeData(addr
, &info
))
112 ReportLocation
*ent
= ReportLocation::New(ReportLocationGlobal
);
113 internal_memcpy(&ent
->global
, &info
, sizeof(info
));
117 void SymbolizeFlush() {
118 Symbolizer::GetOrInit()->Flush();
121 } // namespace __tsan