1 //===-- tsan_symbolize.cpp ------------------------------------------------===//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
9 // This file is a part of ThreadSanitizer (TSan), a race detector.
11 //===----------------------------------------------------------------------===//
13 #include "tsan_symbolize.h"
15 #include "sanitizer_common/sanitizer_common.h"
16 #include "sanitizer_common/sanitizer_placement_new.h"
17 #include "sanitizer_common/sanitizer_symbolizer.h"
18 #include "tsan_flags.h"
19 #include "tsan_report.h"
24 void EnterSymbolizer() {
25 ThreadState
*thr
= cur_thread();
26 CHECK(!thr
->in_symbolizer
);
27 thr
->in_symbolizer
= true;
28 thr
->ignore_interceptors
++;
31 void ExitSymbolizer() {
32 ThreadState
*thr
= cur_thread();
33 CHECK(thr
->in_symbolizer
);
34 thr
->in_symbolizer
= false;
35 thr
->ignore_interceptors
--;
39 // May be overriden by JIT/JAVA/etc,
40 // whatever produces PCs marked with kExternalPCBit.
41 SANITIZER_WEAK_DEFAULT_IMPL
42 bool __tsan_symbolize_external(uptr pc
, char *func_buf
, uptr func_siz
,
43 char *file_buf
, uptr file_siz
, int *line
,
48 // New API: call __tsan_symbolize_external_ex only when it exists.
49 // Once old clients are gone, provide dummy implementation.
50 SANITIZER_WEAK_DEFAULT_IMPL
51 void __tsan_symbolize_external_ex(uptr pc
,
52 void (*add_frame
)(void *, const char *,
53 const char *, int, int),
56 struct SymbolizedStackBuilder
{
57 SymbolizedStack
*head
;
58 SymbolizedStack
*tail
;
62 static void AddFrame(void *ctx
, const char *function_name
, const char *file
,
63 int line
, int column
) {
64 SymbolizedStackBuilder
*ssb
= (struct SymbolizedStackBuilder
*)ctx
;
66 ssb
->tail
->next
= SymbolizedStack::New(ssb
->addr
);
67 ssb
->tail
= ssb
->tail
->next
;
69 ssb
->head
= ssb
->tail
= SymbolizedStack::New(ssb
->addr
);
71 AddressInfo
*info
= &ssb
->tail
->info
;
73 info
->function
= internal_strdup(function_name
);
76 info
->file
= internal_strdup(file
);
79 info
->column
= column
;
82 SymbolizedStack
*SymbolizeCode(uptr addr
) {
83 // Check if PC comes from non-native land.
84 if (addr
& kExternalPCBit
) {
85 SymbolizedStackBuilder ssb
= {nullptr, nullptr, addr
};
86 __tsan_symbolize_external_ex(addr
, AddFrame
, &ssb
);
89 // Legacy code: remove along with the declaration above
90 // once all clients using this API are gone.
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 SymbolizedStack
*frame
= SymbolizedStack::New(addr
);
97 if (__tsan_symbolize_external(addr
, func_buf
, sizeof(func_buf
), file_buf
,
98 sizeof(file_buf
), &line
, &col
)) {
99 frame
->info
.function
= internal_strdup(func_buf
);
100 frame
->info
.file
= internal_strdup(file_buf
);
101 frame
->info
.line
= line
;
102 frame
->info
.column
= col
;
106 return Symbolizer::GetOrInit()->SymbolizePC(addr
);
109 ReportLocation
*SymbolizeData(uptr addr
) {
111 if (!Symbolizer::GetOrInit()->SymbolizeData(addr
, &info
))
113 auto *ent
= New
<ReportLocation
>();
114 ent
->type
= ReportLocationGlobal
;
115 internal_memcpy(&ent
->global
, &info
, sizeof(info
));
119 void SymbolizeFlush() {
120 Symbolizer::GetOrInit()->Flush();
123 } // namespace __tsan