1//===-- sanitizer_symbolizer_libbacktrace.cc ------------------------------===// 2// 3// This file is distributed under the University of Illinois Open Source 4// License. See LICENSE.TXT for details. 5// 6//===----------------------------------------------------------------------===// 7// 8// This file is shared between AddressSanitizer and ThreadSanitizer 9// run-time libraries. 10// Libbacktrace implementation of symbolizer parts. 11//===----------------------------------------------------------------------===// 12 13#include "sanitizer_platform.h" 14 15#include "sanitizer_internal_defs.h" 16#include "sanitizer_symbolizer.h" 17#include "sanitizer_symbolizer_libbacktrace.h" 18 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 24# undef ARRAY_SIZE 25# include "demangle.h" 26# endif 27# else 28# define SANITIZER_LIBBACKTRACE 0 29# endif 30#endif 31 32namespace __sanitizer { 33 34static char *DemangleAlloc(const char *name, bool always_alloc); 35 36#if SANITIZER_LIBBACKTRACE 37 38namespace { 39 40# if SANITIZER_CP_DEMANGLE 41struct CplusV3DemangleData { 42 char *buf; 43 uptr size, allocated; 44}; 45 46extern "C" { 47static void CplusV3DemangleCallback(const char *s, size_t l, void *vdata) { 48 CplusV3DemangleData *data = (CplusV3DemangleData *)vdata; 49 uptr needed = data->size + l + 1; 50 if (needed > data->allocated) { 51 data->allocated *= 2; 52 if (needed > data->allocated) 53 data->allocated = needed; 54 char *buf = (char *)InternalAlloc(data->allocated); 55 if (data->buf) { 56 internal_memcpy(buf, data->buf, data->size); 57 InternalFree(data->buf); 58 } 59 data->buf = buf; 60 } 61 internal_memcpy(data->buf + data->size, s, l); 62 data->buf[data->size + l] = '\0'; 63 data->size += l; 64} 65} // extern "C" 66 67char *CplusV3Demangle(const char *name) { 68 CplusV3DemangleData data; 69 data.buf = 0; 70 data.size = 0; 71 data.allocated = 0; 72 if (cplus_demangle_v3_callback(name, DMGL_PARAMS | DMGL_ANSI, 73 CplusV3DemangleCallback, &data)) { 74 if (data.size + 64 > data.allocated) 75 return data.buf; 76 char *buf = internal_strdup(data.buf); 77 InternalFree(data.buf); 78 return buf; 79 } 80 if (data.buf) 81 InternalFree(data.buf); 82 return 0; 83} 84# endif // SANITIZER_CP_DEMANGLE 85 86struct SymbolizeCodeCallbackArg { 87 SymbolizedStack *first; 88 SymbolizedStack *last; 89 uptr frames_symbolized; 90 91 AddressInfo *get_new_frame(uintptr_t addr) { 92 CHECK(last); 93 if (frames_symbolized > 0) { 94 SymbolizedStack *cur = SymbolizedStack::New(addr); 95 AddressInfo *info = &cur->info; 96 info->FillModuleInfo(first->info.module, first->info.module_offset, 97 first->info.module_arch); 98 last->next = cur; 99 last = cur; 100 } 101 CHECK_EQ(addr, first->info.address); 102 CHECK_EQ(addr, last->info.address); 103 return &last->info; 104 } 105}; 106 107extern "C" { 108static int SymbolizeCodePCInfoCallback(void *vdata, uintptr_t addr, 109 const char *filename, int lineno, 110 const char *function) { 111 SymbolizeCodeCallbackArg *cdata = (SymbolizeCodeCallbackArg *)vdata; 112 if (function) { 113 AddressInfo *info = cdata->get_new_frame(addr); 114 info->function = DemangleAlloc(function, /*always_alloc*/ true); 115 if (filename) 116 info->file = internal_strdup(filename); 117 info->line = lineno; 118 cdata->frames_symbolized++; 119 } 120 return 0; 121} 122 123static void SymbolizeCodeCallback(void *vdata, uintptr_t addr, 124 const char *symname, uintptr_t, uintptr_t) { 125 SymbolizeCodeCallbackArg *cdata = (SymbolizeCodeCallbackArg *)vdata; 126 if (symname) { 127 AddressInfo *info = cdata->get_new_frame(addr); 128 info->function = DemangleAlloc(symname, /*always_alloc*/ true); 129 cdata->frames_symbolized++; 130 } 131} 132 133static void SymbolizeDataCallback(void *vdata, uintptr_t, const char *symname, 134 uintptr_t symval, uintptr_t symsize) { 135 DataInfo *info = (DataInfo *)vdata; 136 if (symname && symval) { 137 info->name = DemangleAlloc(symname, /*always_alloc*/ true); 138 info->start = symval; 139 info->size = symsize; 140 } 141} 142 143static void ErrorCallback(void *, const char *, int) {} 144} // extern "C" 145 146} // namespace 147 148LibbacktraceSymbolizer *LibbacktraceSymbolizer::get(LowLevelAllocator *alloc) { 149 // State created in backtrace_create_state is leaked. 150 void *state = (void *)(backtrace_create_state("/proc/self/exe", 0, 151 ErrorCallback, NULL)); 152 if (!state) 153 return 0; 154 return new(*alloc) LibbacktraceSymbolizer(state); 155} 156 157bool LibbacktraceSymbolizer::SymbolizePC(uptr addr, SymbolizedStack *stack) { 158 SymbolizeCodeCallbackArg data; 159 data.first = stack; 160 data.last = stack; 161 data.frames_symbolized = 0; 162 backtrace_pcinfo((backtrace_state *)state_, addr, SymbolizeCodePCInfoCallback, 163 ErrorCallback, &data); 164 if (data.frames_symbolized > 0) 165 return true; 166 backtrace_syminfo((backtrace_state *)state_, addr, SymbolizeCodeCallback, 167 ErrorCallback, &data); 168 return (data.frames_symbolized > 0); 169} 170 171bool LibbacktraceSymbolizer::SymbolizeData(uptr addr, DataInfo *info) { 172 backtrace_syminfo((backtrace_state *)state_, addr, SymbolizeDataCallback, 173 ErrorCallback, info); 174 return true; 175} 176 177#else // SANITIZER_LIBBACKTRACE 178 179LibbacktraceSymbolizer *LibbacktraceSymbolizer::get(LowLevelAllocator *alloc) { 180 return 0; 181} 182 183bool LibbacktraceSymbolizer::SymbolizePC(uptr addr, SymbolizedStack *stack) { 184 (void)state_; 185 return false; 186} 187 188bool LibbacktraceSymbolizer::SymbolizeData(uptr addr, DataInfo *info) { 189 return false; 190} 191 192#endif // SANITIZER_LIBBACKTRACE 193 194static char *DemangleAlloc(const char *name, bool always_alloc) { 195#if SANITIZER_LIBBACKTRACE && SANITIZER_CP_DEMANGLE 196 if (char *demangled = CplusV3Demangle(name)) 197 return demangled; 198#endif 199 if (always_alloc) 200 return internal_strdup(name); 201 return 0; 202} 203 204const char *LibbacktraceSymbolizer::Demangle(const char *name) { 205 return DemangleAlloc(name, /*always_alloc*/ false); 206} 207 208} // namespace __sanitizer 209