12d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines//===-- sanitizer_symbolizer_libbacktrace.cc ------------------------------===//
22d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines//
32d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines//                     The LLVM Compiler Infrastructure
42d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines//
52d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines// This file is distributed under the University of Illinois Open Source
62d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines// License. See LICENSE.TXT for details.
72d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines//
82d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines//===----------------------------------------------------------------------===//
92d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines//
102d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines// This file is shared between AddressSanitizer and ThreadSanitizer
112d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines// run-time libraries.
122d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines// Libbacktrace implementation of symbolizer parts.
132d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines//===----------------------------------------------------------------------===//
142d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines
152d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#include "sanitizer_platform.h"
162d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines
172d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#include "sanitizer_internal_defs.h"
182d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#include "sanitizer_symbolizer.h"
192d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#include "sanitizer_symbolizer_libbacktrace.h"
202d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines
212d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#if SANITIZER_LIBBACKTRACE
222d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines# include "backtrace-supported.h"
232d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines# if SANITIZER_POSIX && BACKTRACE_SUPPORTED && !BACKTRACE_USES_MALLOC
242d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#  include "backtrace.h"
252d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#  if SANITIZER_CP_DEMANGLE
262d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#   undef ARRAY_SIZE
272d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#   include "demangle.h"
282d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#  endif
292d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines# else
302d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#  define SANITIZER_LIBBACKTRACE 0
312d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines# endif
322d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#endif
332d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines
342d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hinesnamespace __sanitizer {
352d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines
367c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainarstatic char *DemangleAlloc(const char *name, bool always_alloc);
377c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar
382d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#if SANITIZER_LIBBACKTRACE
392d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines
402d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hinesnamespace {
412d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines
422d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines# if SANITIZER_CP_DEMANGLE
432d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hinesstruct CplusV3DemangleData {
442d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  char *buf;
452d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  uptr size, allocated;
462d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines};
472d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines
482d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hinesextern "C" {
492d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hinesstatic void CplusV3DemangleCallback(const char *s, size_t l, void *vdata) {
502d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  CplusV3DemangleData *data = (CplusV3DemangleData *)vdata;
512d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  uptr needed = data->size + l + 1;
522d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  if (needed > data->allocated) {
532d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines    data->allocated *= 2;
542d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines    if (needed > data->allocated)
552d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines      data->allocated = needed;
562d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines    char *buf = (char *)InternalAlloc(data->allocated);
572d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines    if (data->buf) {
582d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines      internal_memcpy(buf, data->buf, data->size);
592d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines      InternalFree(data->buf);
602d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines    }
612d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines    data->buf = buf;
622d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  }
632d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  internal_memcpy(data->buf + data->size, s, l);
642d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  data->buf[data->size + l] = '\0';
652d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  data->size += l;
662d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines}
672d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines}  // extern "C"
682d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines
692d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hineschar *CplusV3Demangle(const char *name) {
702d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  CplusV3DemangleData data;
712d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  data.buf = 0;
722d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  data.size = 0;
732d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  data.allocated = 0;
742d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  if (cplus_demangle_v3_callback(name, DMGL_PARAMS | DMGL_ANSI,
752d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines                                 CplusV3DemangleCallback, &data)) {
762d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines    if (data.size + 64 > data.allocated)
772d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines      return data.buf;
782d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines    char *buf = internal_strdup(data.buf);
792d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines    InternalFree(data.buf);
802d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines    return buf;
812d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  }
822d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  if (data.buf)
832d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines    InternalFree(data.buf);
842d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  return 0;
852d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines}
862d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines# endif  // SANITIZER_CP_DEMANGLE
872d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines
8886277eb844c4983c81de62d7c050e92fe7155788Stephen Hinesstruct SymbolizeCodeCallbackArg {
8986277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  SymbolizedStack *first;
9086277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  SymbolizedStack *last;
917c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar  uptr frames_symbolized;
927c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar
937c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar  AddressInfo *get_new_frame(uintptr_t addr) {
947c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar    CHECK(last);
957c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar    if (frames_symbolized > 0) {
967c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar      SymbolizedStack *cur = SymbolizedStack::New(addr);
977c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar      AddressInfo *info = &cur->info;
987c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar      info->FillModuleInfo(first->info.module, first->info.module_offset);
997c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar      last->next = cur;
1007c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar      last = cur;
10186277eb844c4983c81de62d7c050e92fe7155788Stephen Hines    }
1027c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar    CHECK_EQ(addr, first->info.address);
1037c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar    CHECK_EQ(addr, last->info.address);
1047c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar    return &last->info;
10586277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  }
1062d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines};
1072d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines
1082d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hinesextern "C" {
1092d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hinesstatic int SymbolizeCodePCInfoCallback(void *vdata, uintptr_t addr,
1102d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines                                       const char *filename, int lineno,
1112d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines                                       const char *function) {
11286277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  SymbolizeCodeCallbackArg *cdata = (SymbolizeCodeCallbackArg *)vdata;
1132d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  if (function) {
1147c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar    AddressInfo *info = cdata->get_new_frame(addr);
1157c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar    info->function = DemangleAlloc(function, /*always_alloc*/ true);
1162d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines    if (filename)
1172d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines      info->file = internal_strdup(filename);
1182d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines    info->line = lineno;
1197c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar    cdata->frames_symbolized++;
1202d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  }
1212d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  return 0;
1222d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines}
1232d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines
1242d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hinesstatic void SymbolizeCodeCallback(void *vdata, uintptr_t addr,
1252d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines                                  const char *symname, uintptr_t, uintptr_t) {
12686277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  SymbolizeCodeCallbackArg *cdata = (SymbolizeCodeCallbackArg *)vdata;
1272d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  if (symname) {
1287c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar    AddressInfo *info = cdata->get_new_frame(addr);
1297c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar    info->function = DemangleAlloc(symname, /*always_alloc*/ true);
1307c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar    cdata->frames_symbolized++;
1312d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  }
1322d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines}
1332d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines
1342d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hinesstatic void SymbolizeDataCallback(void *vdata, uintptr_t, const char *symname,
1352d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines                                  uintptr_t symval, uintptr_t symsize) {
1362d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  DataInfo *info = (DataInfo *)vdata;
1372d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  if (symname && symval) {
1387c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar    info->name = DemangleAlloc(symname, /*always_alloc*/ true);
1392d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines    info->start = symval;
1402d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines    info->size = symsize;
1412d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  }
1422d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines}
1432d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines
1442d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hinesstatic void ErrorCallback(void *, const char *, int) {}
1452d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines}  // extern "C"
1462d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines
1472d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines}  // namespace
1482d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines
1492d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen HinesLibbacktraceSymbolizer *LibbacktraceSymbolizer::get(LowLevelAllocator *alloc) {
1502d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  // State created in backtrace_create_state is leaked.
1512d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  void *state = (void *)(backtrace_create_state("/proc/self/exe", 0,
1522d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines                                                ErrorCallback, NULL));
1532d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  if (!state)
1542d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines    return 0;
1552d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  return new(*alloc) LibbacktraceSymbolizer(state);
1562d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines}
1572d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines
1587c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainarbool LibbacktraceSymbolizer::SymbolizePC(uptr addr, SymbolizedStack *stack) {
15986277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  SymbolizeCodeCallbackArg data;
1607c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar  data.first = stack;
1617c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar  data.last = stack;
1627c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar  data.frames_symbolized = 0;
1632d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  backtrace_pcinfo((backtrace_state *)state_, addr, SymbolizeCodePCInfoCallback,
1642d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines                   ErrorCallback, &data);
1657c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar  if (data.frames_symbolized > 0)
1667c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar    return true;
1672d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  backtrace_syminfo((backtrace_state *)state_, addr, SymbolizeCodeCallback,
1682d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines                    ErrorCallback, &data);
1697c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar  return (data.frames_symbolized > 0);
1702d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines}
1712d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines
17286277eb844c4983c81de62d7c050e92fe7155788Stephen Hinesbool LibbacktraceSymbolizer::SymbolizeData(uptr addr, DataInfo *info) {
17386277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  backtrace_syminfo((backtrace_state *)state_, addr, SymbolizeDataCallback,
17486277eb844c4983c81de62d7c050e92fe7155788Stephen Hines                    ErrorCallback, info);
1752d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  return true;
1762d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines}
1772d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines
1782d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#else  // SANITIZER_LIBBACKTRACE
1792d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines
1802d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen HinesLibbacktraceSymbolizer *LibbacktraceSymbolizer::get(LowLevelAllocator *alloc) {
1812d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  return 0;
1822d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines}
1832d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines
1847c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainarbool LibbacktraceSymbolizer::SymbolizePC(uptr addr, SymbolizedStack *stack) {
1852d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  (void)state_;
1867c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar  return false;
1872d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines}
1882d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines
18986277eb844c4983c81de62d7c050e92fe7155788Stephen Hinesbool LibbacktraceSymbolizer::SymbolizeData(uptr addr, DataInfo *info) {
1902d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  return false;
1912d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines}
1922d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines
1932d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#endif  // SANITIZER_LIBBACKTRACE
1942d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines
1957c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainarstatic char *DemangleAlloc(const char *name, bool always_alloc) {
1962d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#if SANITIZER_LIBBACKTRACE && SANITIZER_CP_DEMANGLE
1972d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  if (char *demangled = CplusV3Demangle(name))
1982d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines    return demangled;
1992d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#endif
2002d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  if (always_alloc)
2012d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines    return internal_strdup(name);
2022d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  return 0;
2032d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines}
2042d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines
2057c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainarconst char *LibbacktraceSymbolizer::Demangle(const char *name) {
2067c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar  return DemangleAlloc(name, /*always_alloc*/ false);
2077c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar}
2087c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar
2092d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines}  // namespace __sanitizer
210