1 //===-- sanitizer_symbolizer_libbacktrace.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 shared between AddressSanitizer and ThreadSanitizer
10 // Libbacktrace implementation of symbolizer parts.
11 //===----------------------------------------------------------------------===//
13 #include "sanitizer_platform.h"
15 #include "sanitizer_internal_defs.h"
16 #include "sanitizer_symbolizer.h"
17 #include "sanitizer_symbolizer_libbacktrace.h"
19 #if SANITIZER_LIBBACKTRACE
20 # include "backtrace-supported.h"
21 # if SANITIZER_POSIX && BACKTRACE_SUPPORTED && !BACKTRACE_USES_MALLOC
22 # include "backtrace.h"
23 # if SANITIZER_CP_DEMANGLE
25 # include "demangle.h"
28 # define SANITIZER_LIBBACKTRACE 0
32 namespace __sanitizer
{
34 #if SANITIZER_LIBBACKTRACE
38 # if SANITIZER_CP_DEMANGLE
39 struct CplusV3DemangleData
{
45 static void CplusV3DemangleCallback(const char *s
, size_t l
, void *vdata
) {
46 CplusV3DemangleData
*data
= (CplusV3DemangleData
*)vdata
;
47 uptr needed
= data
->size
+ l
+ 1;
48 if (needed
> data
->allocated
) {
50 if (needed
> data
->allocated
)
51 data
->allocated
= needed
;
52 char *buf
= (char *)InternalAlloc(data
->allocated
);
54 internal_memcpy(buf
, data
->buf
, data
->size
);
55 InternalFree(data
->buf
);
59 internal_memcpy(data
->buf
+ data
->size
, s
, l
);
60 data
->buf
[data
->size
+ l
] = '\0';
65 char *CplusV3Demangle(const char *name
) {
66 CplusV3DemangleData data
;
70 if (cplus_demangle_v3_callback(name
, DMGL_PARAMS
| DMGL_ANSI
,
71 CplusV3DemangleCallback
, &data
)) {
72 if (data
.size
+ 64 > data
.allocated
)
74 char *buf
= internal_strdup(data
.buf
);
75 InternalFree(data
.buf
);
79 InternalFree(data
.buf
);
82 # endif // SANITIZER_CP_DEMANGLE
84 struct SymbolizeCodeData
{
88 const char *module_name
;
93 static int SymbolizeCodePCInfoCallback(void *vdata
, uintptr_t addr
,
94 const char *filename
, int lineno
,
95 const char *function
) {
96 SymbolizeCodeData
*cdata
= (SymbolizeCodeData
*)vdata
;
98 AddressInfo
*info
= &cdata
->frames
[cdata
->n_frames
++];
100 info
->FillAddressAndModuleInfo(addr
, cdata
->module_name
,
101 cdata
->module_offset
);
102 info
->function
= LibbacktraceSymbolizer::Demangle(function
, true);
104 info
->file
= internal_strdup(filename
);
106 if (cdata
->n_frames
== cdata
->max_frames
)
112 static void SymbolizeCodeCallback(void *vdata
, uintptr_t addr
,
113 const char *symname
, uintptr_t, uintptr_t) {
114 SymbolizeCodeData
*cdata
= (SymbolizeCodeData
*)vdata
;
116 AddressInfo
*info
= &cdata
->frames
[0];
118 info
->FillAddressAndModuleInfo(addr
, cdata
->module_name
,
119 cdata
->module_offset
);
120 info
->function
= LibbacktraceSymbolizer::Demangle(symname
, true);
125 static void SymbolizeDataCallback(void *vdata
, uintptr_t, const char *symname
,
126 uintptr_t symval
, uintptr_t symsize
) {
127 DataInfo
*info
= (DataInfo
*)vdata
;
128 if (symname
&& symval
) {
129 info
->name
= LibbacktraceSymbolizer::Demangle(symname
, true);
130 info
->start
= symval
;
131 info
->size
= symsize
;
135 static void ErrorCallback(void *, const char *, int) {}
140 LibbacktraceSymbolizer
*LibbacktraceSymbolizer::get(LowLevelAllocator
*alloc
) {
141 // State created in backtrace_create_state is leaked.
142 void *state
= (void *)(backtrace_create_state("/proc/self/exe", 0,
143 ErrorCallback
, NULL
));
146 return new(*alloc
) LibbacktraceSymbolizer(state
);
149 uptr
LibbacktraceSymbolizer::SymbolizeCode(uptr addr
, AddressInfo
*frames
,
151 const char *module_name
,
152 uptr module_offset
) {
153 SymbolizeCodeData data
;
154 data
.frames
= frames
;
156 data
.max_frames
= max_frames
;
157 data
.module_name
= module_name
;
158 data
.module_offset
= module_offset
;
159 backtrace_pcinfo((backtrace_state
*)state_
, addr
, SymbolizeCodePCInfoCallback
,
160 ErrorCallback
, &data
);
162 return data
.n_frames
;
163 backtrace_syminfo((backtrace_state
*)state_
, addr
, SymbolizeCodeCallback
,
164 ErrorCallback
, &data
);
165 return data
.n_frames
;
168 bool LibbacktraceSymbolizer::SymbolizeData(DataInfo
*info
) {
169 backtrace_syminfo((backtrace_state
*)state_
, info
->address
,
170 SymbolizeDataCallback
, ErrorCallback
, info
);
174 #else // SANITIZER_LIBBACKTRACE
176 LibbacktraceSymbolizer
*LibbacktraceSymbolizer::get(LowLevelAllocator
*alloc
) {
180 uptr
LibbacktraceSymbolizer::SymbolizeCode(uptr addr
, AddressInfo
*frames
,
182 const char *module_name
,
183 uptr module_offset
) {
188 bool LibbacktraceSymbolizer::SymbolizeData(DataInfo
*info
) {
192 #endif // SANITIZER_LIBBACKTRACE
194 char *LibbacktraceSymbolizer::Demangle(const char *name
, bool always_alloc
) {
195 #if SANITIZER_LIBBACKTRACE && SANITIZER_CP_DEMANGLE
196 if (char *demangled
= CplusV3Demangle(name
))
200 return internal_strdup(name
);
204 } // namespace __sanitizer