sanitizer_symbolizer_libbacktrace.cpp 6.1 KB

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