sanitizer_symbolizer_libbacktrace.cc 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205
  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. #include "sanitizer_platform.h"
  13. #include "sanitizer_internal_defs.h"
  14. #include "sanitizer_symbolizer.h"
  15. #include "sanitizer_symbolizer_libbacktrace.h"
  16. #if SANITIZER_LIBBACKTRACE
  17. # include "backtrace-supported.h"
  18. # if SANITIZER_POSIX && BACKTRACE_SUPPORTED && !BACKTRACE_USES_MALLOC
  19. # include "backtrace.h"
  20. # if SANITIZER_CP_DEMANGLE
  21. # undef ARRAY_SIZE
  22. # include "demangle.h"
  23. # endif
  24. # else
  25. # define SANITIZER_LIBBACKTRACE 0
  26. # endif
  27. #endif
  28. namespace __sanitizer {
  29. #if SANITIZER_LIBBACKTRACE
  30. namespace {
  31. # if SANITIZER_CP_DEMANGLE
  32. struct CplusV3DemangleData {
  33. char *buf;
  34. uptr size, allocated;
  35. };
  36. extern "C" {
  37. static void CplusV3DemangleCallback(const char *s, size_t l, void *vdata) {
  38. CplusV3DemangleData *data = (CplusV3DemangleData *)vdata;
  39. uptr needed = data->size + l + 1;
  40. if (needed > data->allocated) {
  41. data->allocated *= 2;
  42. if (needed > data->allocated)
  43. data->allocated = needed;
  44. char *buf = (char *)InternalAlloc(data->allocated);
  45. if (data->buf) {
  46. internal_memcpy(buf, data->buf, data->size);
  47. InternalFree(data->buf);
  48. }
  49. data->buf = buf;
  50. }
  51. internal_memcpy(data->buf + data->size, s, l);
  52. data->buf[data->size + l] = '\0';
  53. data->size += l;
  54. }
  55. } // extern "C"
  56. char *CplusV3Demangle(const char *name) {
  57. CplusV3DemangleData data;
  58. data.buf = 0;
  59. data.size = 0;
  60. data.allocated = 0;
  61. if (cplus_demangle_v3_callback(name, DMGL_PARAMS | DMGL_ANSI,
  62. CplusV3DemangleCallback, &data)) {
  63. if (data.size + 64 > data.allocated)
  64. return data.buf;
  65. char *buf = internal_strdup(data.buf);
  66. InternalFree(data.buf);
  67. return buf;
  68. }
  69. if (data.buf)
  70. InternalFree(data.buf);
  71. return 0;
  72. }
  73. # endif // SANITIZER_CP_DEMANGLE
  74. struct SymbolizeCodeData {
  75. AddressInfo *frames;
  76. uptr n_frames;
  77. uptr max_frames;
  78. const char *module_name;
  79. uptr module_offset;
  80. };
  81. extern "C" {
  82. static int SymbolizeCodePCInfoCallback(void *vdata, uintptr_t addr,
  83. const char *filename, int lineno,
  84. const char *function) {
  85. SymbolizeCodeData *cdata = (SymbolizeCodeData *)vdata;
  86. if (function) {
  87. AddressInfo *info = &cdata->frames[cdata->n_frames++];
  88. info->Clear();
  89. info->FillAddressAndModuleInfo(addr, cdata->module_name,
  90. cdata->module_offset);
  91. info->function = LibbacktraceSymbolizer::Demangle(function, true);
  92. if (filename)
  93. info->file = internal_strdup(filename);
  94. info->line = lineno;
  95. if (cdata->n_frames == cdata->max_frames)
  96. return 1;
  97. }
  98. return 0;
  99. }
  100. static void SymbolizeCodeCallback(void *vdata, uintptr_t addr,
  101. const char *symname, uintptr_t, uintptr_t) {
  102. SymbolizeCodeData *cdata = (SymbolizeCodeData *)vdata;
  103. if (symname) {
  104. AddressInfo *info = &cdata->frames[0];
  105. info->Clear();
  106. info->FillAddressAndModuleInfo(addr, cdata->module_name,
  107. cdata->module_offset);
  108. info->function = LibbacktraceSymbolizer::Demangle(symname, true);
  109. cdata->n_frames = 1;
  110. }
  111. }
  112. static void SymbolizeDataCallback(void *vdata, uintptr_t, const char *symname,
  113. uintptr_t symval, uintptr_t symsize) {
  114. DataInfo *info = (DataInfo *)vdata;
  115. if (symname && symval) {
  116. info->name = LibbacktraceSymbolizer::Demangle(symname, true);
  117. info->start = symval;
  118. info->size = symsize;
  119. }
  120. }
  121. static void ErrorCallback(void *, const char *, int) {}
  122. } // extern "C"
  123. } // namespace
  124. LibbacktraceSymbolizer *LibbacktraceSymbolizer::get(LowLevelAllocator *alloc) {
  125. // State created in backtrace_create_state is leaked.
  126. void *state = (void *)(backtrace_create_state("/proc/self/exe", 0,
  127. ErrorCallback, NULL));
  128. if (!state)
  129. return 0;
  130. return new(*alloc) LibbacktraceSymbolizer(state);
  131. }
  132. uptr LibbacktraceSymbolizer::SymbolizeCode(uptr addr, AddressInfo *frames,
  133. uptr max_frames,
  134. const char *module_name,
  135. uptr module_offset) {
  136. SymbolizeCodeData data;
  137. data.frames = frames;
  138. data.n_frames = 0;
  139. data.max_frames = max_frames;
  140. data.module_name = module_name;
  141. data.module_offset = module_offset;
  142. backtrace_pcinfo((backtrace_state *)state_, addr, SymbolizeCodePCInfoCallback,
  143. ErrorCallback, &data);
  144. if (data.n_frames)
  145. return data.n_frames;
  146. backtrace_syminfo((backtrace_state *)state_, addr, SymbolizeCodeCallback,
  147. ErrorCallback, &data);
  148. return data.n_frames;
  149. }
  150. bool LibbacktraceSymbolizer::SymbolizeData(uptr addr, DataInfo *info) {
  151. backtrace_syminfo((backtrace_state *)state_, addr, SymbolizeDataCallback,
  152. ErrorCallback, info);
  153. return true;
  154. }
  155. #else // SANITIZER_LIBBACKTRACE
  156. LibbacktraceSymbolizer *LibbacktraceSymbolizer::get(LowLevelAllocator *alloc) {
  157. return 0;
  158. }
  159. uptr LibbacktraceSymbolizer::SymbolizeCode(uptr addr, AddressInfo *frames,
  160. uptr max_frames,
  161. const char *module_name,
  162. uptr module_offset) {
  163. (void)state_;
  164. return 0;
  165. }
  166. bool LibbacktraceSymbolizer::SymbolizeData(uptr addr, DataInfo *info) {
  167. return false;
  168. }
  169. #endif // SANITIZER_LIBBACKTRACE
  170. char *LibbacktraceSymbolizer::Demangle(const char *name, bool always_alloc) {
  171. #if SANITIZER_LIBBACKTRACE && SANITIZER_CP_DEMANGLE
  172. if (char *demangled = CplusV3Demangle(name))
  173. return demangled;
  174. #endif
  175. if (always_alloc)
  176. return internal_strdup(name);
  177. return 0;
  178. }
  179. } // namespace __sanitizer