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