123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209 |
- //===-- sanitizer_symbolizer_libbacktrace.cpp -----------------------------===//
- //
- // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
- // See https://llvm.org/LICENSE.txt for license information.
- // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
- //
- //===----------------------------------------------------------------------===//
- //
- // This file is shared between AddressSanitizer and ThreadSanitizer
- // run-time libraries.
- // Libbacktrace implementation of symbolizer parts.
- //===----------------------------------------------------------------------===//
- #include "sanitizer_platform.h"
- #include "sanitizer_internal_defs.h"
- #include "sanitizer_symbolizer.h"
- #include "sanitizer_symbolizer_libbacktrace.h"
- #if SANITIZER_LIBBACKTRACE
- # error #include "backtrace-supported.h"
- # if SANITIZER_POSIX && BACKTRACE_SUPPORTED && !BACKTRACE_USES_MALLOC
- # error #include "backtrace.h"
- # if SANITIZER_CP_DEMANGLE
- # undef ARRAY_SIZE
- # error #include "demangle.h"
- # endif
- # else
- # define SANITIZER_LIBBACKTRACE 0
- # endif
- #endif
- namespace __sanitizer {
- static char *DemangleAlloc(const char *name, bool always_alloc);
- #if SANITIZER_LIBBACKTRACE
- namespace {
- # if SANITIZER_CP_DEMANGLE
- struct CplusV3DemangleData {
- char *buf;
- uptr size, allocated;
- };
- extern "C" {
- static void CplusV3DemangleCallback(const char *s, size_t l, void *vdata) {
- CplusV3DemangleData *data = (CplusV3DemangleData *)vdata;
- uptr needed = data->size + l + 1;
- if (needed > data->allocated) {
- data->allocated *= 2;
- if (needed > data->allocated)
- data->allocated = needed;
- char *buf = (char *)InternalAlloc(data->allocated);
- if (data->buf) {
- internal_memcpy(buf, data->buf, data->size);
- InternalFree(data->buf);
- }
- data->buf = buf;
- }
- internal_memcpy(data->buf + data->size, s, l);
- data->buf[data->size + l] = '\0';
- data->size += l;
- }
- } // extern "C"
- char *CplusV3Demangle(const char *name) {
- CplusV3DemangleData data;
- data.buf = 0;
- data.size = 0;
- data.allocated = 0;
- if (cplus_demangle_v3_callback(name, DMGL_PARAMS | DMGL_ANSI,
- CplusV3DemangleCallback, &data)) {
- if (data.size + 64 > data.allocated)
- return data.buf;
- char *buf = internal_strdup(data.buf);
- InternalFree(data.buf);
- return buf;
- }
- if (data.buf)
- InternalFree(data.buf);
- return 0;
- }
- # endif // SANITIZER_CP_DEMANGLE
- struct SymbolizeCodeCallbackArg {
- SymbolizedStack *first;
- SymbolizedStack *last;
- uptr frames_symbolized;
- AddressInfo *get_new_frame(uintptr_t addr) {
- CHECK(last);
- if (frames_symbolized > 0) {
- SymbolizedStack *cur = SymbolizedStack::New(addr);
- AddressInfo *info = &cur->info;
- info->FillModuleInfo(first->info.module, first->info.module_offset,
- first->info.module_arch);
- last->next = cur;
- last = cur;
- }
- CHECK_EQ(addr, first->info.address);
- CHECK_EQ(addr, last->info.address);
- return &last->info;
- }
- };
- extern "C" {
- static int SymbolizeCodePCInfoCallback(void *vdata, uintptr_t addr,
- const char *filename, int lineno,
- const char *function) {
- SymbolizeCodeCallbackArg *cdata = (SymbolizeCodeCallbackArg *)vdata;
- if (function) {
- AddressInfo *info = cdata->get_new_frame(addr);
- info->function = DemangleAlloc(function, /*always_alloc*/ true);
- if (filename)
- info->file = internal_strdup(filename);
- info->line = lineno;
- cdata->frames_symbolized++;
- }
- return 0;
- }
- static void SymbolizeCodeCallback(void *vdata, uintptr_t addr,
- const char *symname, uintptr_t, uintptr_t) {
- SymbolizeCodeCallbackArg *cdata = (SymbolizeCodeCallbackArg *)vdata;
- if (symname) {
- AddressInfo *info = cdata->get_new_frame(addr);
- info->function = DemangleAlloc(symname, /*always_alloc*/ true);
- cdata->frames_symbolized++;
- }
- }
- static void SymbolizeDataCallback(void *vdata, uintptr_t, const char *symname,
- uintptr_t symval, uintptr_t symsize) {
- DataInfo *info = (DataInfo *)vdata;
- if (symname && symval) {
- info->name = DemangleAlloc(symname, /*always_alloc*/ true);
- info->start = symval;
- info->size = symsize;
- }
- }
- static void ErrorCallback(void *, const char *, int) {}
- } // extern "C"
- } // namespace
- LibbacktraceSymbolizer *LibbacktraceSymbolizer::get(LowLevelAllocator *alloc) {
- // State created in backtrace_create_state is leaked.
- void *state = (void *)(backtrace_create_state("/proc/self/exe", 0,
- ErrorCallback, NULL));
- if (!state)
- return 0;
- return new(*alloc) LibbacktraceSymbolizer(state);
- }
- bool LibbacktraceSymbolizer::SymbolizePC(uptr addr, SymbolizedStack *stack) {
- SymbolizeCodeCallbackArg data;
- data.first = stack;
- data.last = stack;
- data.frames_symbolized = 0;
- backtrace_pcinfo((backtrace_state *)state_, addr, SymbolizeCodePCInfoCallback,
- ErrorCallback, &data);
- if (data.frames_symbolized > 0)
- return true;
- backtrace_syminfo((backtrace_state *)state_, addr, SymbolizeCodeCallback,
- ErrorCallback, &data);
- return (data.frames_symbolized > 0);
- }
- bool LibbacktraceSymbolizer::SymbolizeData(uptr addr, DataInfo *info) {
- backtrace_syminfo((backtrace_state *)state_, addr, SymbolizeDataCallback,
- ErrorCallback, info);
- return true;
- }
- #else // SANITIZER_LIBBACKTRACE
- LibbacktraceSymbolizer *LibbacktraceSymbolizer::get(LowLevelAllocator *alloc) {
- return 0;
- }
- bool LibbacktraceSymbolizer::SymbolizePC(uptr addr, SymbolizedStack *stack) {
- (void)state_;
- return false;
- }
- bool LibbacktraceSymbolizer::SymbolizeData(uptr addr, DataInfo *info) {
- return false;
- }
- #endif // SANITIZER_LIBBACKTRACE
- static char *DemangleAlloc(const char *name, bool always_alloc) {
- #if SANITIZER_LIBBACKTRACE && SANITIZER_CP_DEMANGLE
- if (char *demangled = CplusV3Demangle(name))
- return demangled;
- #endif
- if (always_alloc)
- return internal_strdup(name);
- return 0;
- }
- const char *LibbacktraceSymbolizer::Demangle(const char *name) {
- return DemangleAlloc(name, /*always_alloc*/ false);
- }
- } // namespace __sanitizer
|