sanitizer_stacktrace_printer.cpp 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365
  1. //===-- sanitizer_common.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 sanitizers' run-time libraries.
  10. //
  11. //===----------------------------------------------------------------------===//
  12. #include "sanitizer_stacktrace_printer.h"
  13. #include "sanitizer_common.h"
  14. #include "sanitizer_file.h"
  15. #include "sanitizer_flags.h"
  16. #include "sanitizer_fuchsia.h"
  17. #include "sanitizer_symbolizer_markup.h"
  18. namespace __sanitizer {
  19. StackTracePrinter *StackTracePrinter::GetOrInit() {
  20. static StackTracePrinter *stacktrace_printer;
  21. static StaticSpinMutex init_mu;
  22. SpinMutexLock l(&init_mu);
  23. if (stacktrace_printer)
  24. return stacktrace_printer;
  25. stacktrace_printer = StackTracePrinter::NewStackTracePrinter();
  26. CHECK(stacktrace_printer);
  27. return stacktrace_printer;
  28. }
  29. const char *StackTracePrinter::StripFunctionName(const char *function) {
  30. if (!common_flags()->demangle)
  31. return function;
  32. if (!function)
  33. return nullptr;
  34. auto try_strip = [function](const char *prefix) -> const char * {
  35. const uptr prefix_len = internal_strlen(prefix);
  36. if (!internal_strncmp(function, prefix, prefix_len))
  37. return function + prefix_len;
  38. return nullptr;
  39. };
  40. if (SANITIZER_APPLE) {
  41. if (const char *s = try_strip("wrap_"))
  42. return s;
  43. } else if (SANITIZER_WINDOWS) {
  44. if (const char *s = try_strip("__asan_wrap_"))
  45. return s;
  46. } else {
  47. if (const char *s = try_strip("___interceptor_"))
  48. return s;
  49. if (const char *s = try_strip("__interceptor_"))
  50. return s;
  51. }
  52. return function;
  53. }
  54. // sanitizer_symbolizer_markup.cpp implements these differently.
  55. #if !SANITIZER_SYMBOLIZER_MARKUP
  56. StackTracePrinter *StackTracePrinter::NewStackTracePrinter() {
  57. if (common_flags()->enable_symbolizer_markup)
  58. return new (GetGlobalLowLevelAllocator()) MarkupStackTracePrinter();
  59. return new (GetGlobalLowLevelAllocator()) FormattedStackTracePrinter();
  60. }
  61. static const char *DemangleFunctionName(const char *function) {
  62. if (!common_flags()->demangle)
  63. return function;
  64. if (!function)
  65. return nullptr;
  66. // NetBSD uses indirection for old threading functions for historical reasons
  67. // The mangled names are internal implementation detail and should not be
  68. // exposed even in backtraces.
  69. #if SANITIZER_NETBSD
  70. if (!internal_strcmp(function, "__libc_mutex_init"))
  71. return "pthread_mutex_init";
  72. if (!internal_strcmp(function, "__libc_mutex_lock"))
  73. return "pthread_mutex_lock";
  74. if (!internal_strcmp(function, "__libc_mutex_trylock"))
  75. return "pthread_mutex_trylock";
  76. if (!internal_strcmp(function, "__libc_mutex_unlock"))
  77. return "pthread_mutex_unlock";
  78. if (!internal_strcmp(function, "__libc_mutex_destroy"))
  79. return "pthread_mutex_destroy";
  80. if (!internal_strcmp(function, "__libc_mutexattr_init"))
  81. return "pthread_mutexattr_init";
  82. if (!internal_strcmp(function, "__libc_mutexattr_settype"))
  83. return "pthread_mutexattr_settype";
  84. if (!internal_strcmp(function, "__libc_mutexattr_destroy"))
  85. return "pthread_mutexattr_destroy";
  86. if (!internal_strcmp(function, "__libc_cond_init"))
  87. return "pthread_cond_init";
  88. if (!internal_strcmp(function, "__libc_cond_signal"))
  89. return "pthread_cond_signal";
  90. if (!internal_strcmp(function, "__libc_cond_broadcast"))
  91. return "pthread_cond_broadcast";
  92. if (!internal_strcmp(function, "__libc_cond_wait"))
  93. return "pthread_cond_wait";
  94. if (!internal_strcmp(function, "__libc_cond_timedwait"))
  95. return "pthread_cond_timedwait";
  96. if (!internal_strcmp(function, "__libc_cond_destroy"))
  97. return "pthread_cond_destroy";
  98. if (!internal_strcmp(function, "__libc_rwlock_init"))
  99. return "pthread_rwlock_init";
  100. if (!internal_strcmp(function, "__libc_rwlock_rdlock"))
  101. return "pthread_rwlock_rdlock";
  102. if (!internal_strcmp(function, "__libc_rwlock_wrlock"))
  103. return "pthread_rwlock_wrlock";
  104. if (!internal_strcmp(function, "__libc_rwlock_tryrdlock"))
  105. return "pthread_rwlock_tryrdlock";
  106. if (!internal_strcmp(function, "__libc_rwlock_trywrlock"))
  107. return "pthread_rwlock_trywrlock";
  108. if (!internal_strcmp(function, "__libc_rwlock_unlock"))
  109. return "pthread_rwlock_unlock";
  110. if (!internal_strcmp(function, "__libc_rwlock_destroy"))
  111. return "pthread_rwlock_destroy";
  112. if (!internal_strcmp(function, "__libc_thr_keycreate"))
  113. return "pthread_key_create";
  114. if (!internal_strcmp(function, "__libc_thr_setspecific"))
  115. return "pthread_setspecific";
  116. if (!internal_strcmp(function, "__libc_thr_getspecific"))
  117. return "pthread_getspecific";
  118. if (!internal_strcmp(function, "__libc_thr_keydelete"))
  119. return "pthread_key_delete";
  120. if (!internal_strcmp(function, "__libc_thr_once"))
  121. return "pthread_once";
  122. if (!internal_strcmp(function, "__libc_thr_self"))
  123. return "pthread_self";
  124. if (!internal_strcmp(function, "__libc_thr_exit"))
  125. return "pthread_exit";
  126. if (!internal_strcmp(function, "__libc_thr_setcancelstate"))
  127. return "pthread_setcancelstate";
  128. if (!internal_strcmp(function, "__libc_thr_equal"))
  129. return "pthread_equal";
  130. if (!internal_strcmp(function, "__libc_thr_curcpu"))
  131. return "pthread_curcpu_np";
  132. if (!internal_strcmp(function, "__libc_thr_sigsetmask"))
  133. return "pthread_sigmask";
  134. #endif
  135. return function;
  136. }
  137. static void MaybeBuildIdToBuffer(const AddressInfo &info, bool PrefixSpace,
  138. InternalScopedString *buffer) {
  139. if (info.uuid_size) {
  140. if (PrefixSpace)
  141. buffer->AppendF(" ");
  142. buffer->AppendF("(BuildId: ");
  143. for (uptr i = 0; i < info.uuid_size; ++i) {
  144. buffer->AppendF("%02x", info.uuid[i]);
  145. }
  146. buffer->AppendF(")");
  147. }
  148. }
  149. static const char kDefaultFormat[] = " #%n %p %F %L";
  150. void FormattedStackTracePrinter::RenderFrame(InternalScopedString *buffer,
  151. const char *format, int frame_no,
  152. uptr address,
  153. const AddressInfo *info,
  154. bool vs_style,
  155. const char *strip_path_prefix) {
  156. // info will be null in the case where symbolization is not needed for the
  157. // given format. This ensures that the code below will get a hard failure
  158. // rather than print incorrect information in case RenderNeedsSymbolization
  159. // ever ends up out of sync with this function. If non-null, the addresses
  160. // should match.
  161. CHECK(!info || address == info->address);
  162. if (0 == internal_strcmp(format, "DEFAULT"))
  163. format = kDefaultFormat;
  164. for (const char *p = format; *p != '\0'; p++) {
  165. if (*p != '%') {
  166. buffer->AppendF("%c", *p);
  167. continue;
  168. }
  169. p++;
  170. switch (*p) {
  171. case '%':
  172. buffer->Append("%");
  173. break;
  174. // Frame number and all fields of AddressInfo structure.
  175. case 'n':
  176. buffer->AppendF("%u", frame_no);
  177. break;
  178. case 'p':
  179. buffer->AppendF("0x%zx", address);
  180. break;
  181. case 'm':
  182. buffer->AppendF("%s", StripPathPrefix(info->module, strip_path_prefix));
  183. break;
  184. case 'o':
  185. buffer->AppendF("0x%zx", info->module_offset);
  186. break;
  187. case 'b':
  188. MaybeBuildIdToBuffer(*info, /*PrefixSpace=*/false, buffer);
  189. break;
  190. case 'f':
  191. buffer->AppendF("%s",
  192. DemangleFunctionName(StripFunctionName(info->function)));
  193. break;
  194. case 'q':
  195. buffer->AppendF("0x%zx", info->function_offset != AddressInfo::kUnknown
  196. ? info->function_offset
  197. : 0x0);
  198. break;
  199. case 's':
  200. buffer->AppendF("%s", StripPathPrefix(info->file, strip_path_prefix));
  201. break;
  202. case 'l':
  203. buffer->AppendF("%d", info->line);
  204. break;
  205. case 'c':
  206. buffer->AppendF("%d", info->column);
  207. break;
  208. // Smarter special cases.
  209. case 'F':
  210. // Function name and offset, if file is unknown.
  211. if (info->function) {
  212. buffer->AppendF(
  213. "in %s", DemangleFunctionName(StripFunctionName(info->function)));
  214. if (!info->file && info->function_offset != AddressInfo::kUnknown)
  215. buffer->AppendF("+0x%zx", info->function_offset);
  216. }
  217. break;
  218. case 'S':
  219. // File/line information.
  220. RenderSourceLocation(buffer, info->file, info->line, info->column,
  221. vs_style, strip_path_prefix);
  222. break;
  223. case 'L':
  224. // Source location, or module location.
  225. if (info->file) {
  226. RenderSourceLocation(buffer, info->file, info->line, info->column,
  227. vs_style, strip_path_prefix);
  228. } else if (info->module) {
  229. RenderModuleLocation(buffer, info->module, info->module_offset,
  230. info->module_arch, strip_path_prefix);
  231. #if !SANITIZER_APPLE
  232. MaybeBuildIdToBuffer(*info, /*PrefixSpace=*/true, buffer);
  233. #endif
  234. } else {
  235. buffer->AppendF("(<unknown module>)");
  236. }
  237. break;
  238. case 'M':
  239. // Module basename and offset, or PC.
  240. if (address & kExternalPCBit) {
  241. // There PCs are not meaningful.
  242. } else if (info->module) {
  243. // Always strip the module name for %M.
  244. RenderModuleLocation(buffer, StripModuleName(info->module),
  245. info->module_offset, info->module_arch, "");
  246. #if !SANITIZER_APPLE
  247. MaybeBuildIdToBuffer(*info, /*PrefixSpace=*/true, buffer);
  248. #endif
  249. } else {
  250. buffer->AppendF("(%p)", (void *)address);
  251. }
  252. break;
  253. default:
  254. Report("Unsupported specifier in stack frame format: %c (%p)!\n", *p,
  255. (void *)p);
  256. Die();
  257. }
  258. }
  259. }
  260. bool FormattedStackTracePrinter::RenderNeedsSymbolization(const char *format) {
  261. if (0 == internal_strcmp(format, "DEFAULT"))
  262. format = kDefaultFormat;
  263. for (const char *p = format; *p != '\0'; p++) {
  264. if (*p != '%')
  265. continue;
  266. p++;
  267. switch (*p) {
  268. case '%':
  269. break;
  270. case 'n':
  271. // frame_no
  272. break;
  273. case 'p':
  274. // address
  275. break;
  276. default:
  277. return true;
  278. }
  279. }
  280. return false;
  281. }
  282. void FormattedStackTracePrinter::RenderData(InternalScopedString *buffer,
  283. const char *format,
  284. const DataInfo *DI,
  285. const char *strip_path_prefix) {
  286. for (const char *p = format; *p != '\0'; p++) {
  287. if (*p != '%') {
  288. buffer->AppendF("%c", *p);
  289. continue;
  290. }
  291. p++;
  292. switch (*p) {
  293. case '%':
  294. buffer->Append("%");
  295. break;
  296. case 's':
  297. buffer->AppendF("%s", StripPathPrefix(DI->file, strip_path_prefix));
  298. break;
  299. case 'l':
  300. buffer->AppendF("%zu", DI->line);
  301. break;
  302. case 'g':
  303. buffer->AppendF("%s", DI->name);
  304. break;
  305. default:
  306. Report("Unsupported specifier in stack frame format: %c (%p)!\n", *p,
  307. (void *)p);
  308. Die();
  309. }
  310. }
  311. }
  312. #endif // !SANITIZER_SYMBOLIZER_MARKUP
  313. void StackTracePrinter::RenderSourceLocation(InternalScopedString *buffer,
  314. const char *file, int line,
  315. int column, bool vs_style,
  316. const char *strip_path_prefix) {
  317. if (vs_style && line > 0) {
  318. buffer->AppendF("%s(%d", StripPathPrefix(file, strip_path_prefix), line);
  319. if (column > 0)
  320. buffer->AppendF(",%d", column);
  321. buffer->AppendF(")");
  322. return;
  323. }
  324. buffer->AppendF("%s", StripPathPrefix(file, strip_path_prefix));
  325. if (line > 0) {
  326. buffer->AppendF(":%d", line);
  327. if (column > 0)
  328. buffer->AppendF(":%d", column);
  329. }
  330. }
  331. void StackTracePrinter::RenderModuleLocation(InternalScopedString *buffer,
  332. const char *module, uptr offset,
  333. ModuleArch arch,
  334. const char *strip_path_prefix) {
  335. buffer->AppendF("(%s", StripPathPrefix(module, strip_path_prefix));
  336. if (arch != kModuleArchUnknown) {
  337. buffer->AppendF(":%s", ModuleArchToString(arch));
  338. }
  339. buffer->AppendF("+0x%zx)", offset);
  340. }
  341. } // namespace __sanitizer