sanitizer_stacktrace_printer.cc 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131
  1. //===-- sanitizer_common.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 sanitizers' run-time libraries.
  9. //
  10. //===----------------------------------------------------------------------===//
  11. #include "sanitizer_stacktrace_printer.h"
  12. namespace __sanitizer {
  13. static const char *StripFunctionName(const char *function, const char *prefix) {
  14. if (function == 0) return 0;
  15. if (prefix == 0) return function;
  16. uptr prefix_len = internal_strlen(prefix);
  17. if (0 == internal_strncmp(function, prefix, prefix_len))
  18. return function + prefix_len;
  19. return function;
  20. }
  21. static const char kDefaultFormat[] = " #%n %p %F %L";
  22. void RenderFrame(InternalScopedString *buffer, const char *format, int frame_no,
  23. const AddressInfo &info, const char *strip_path_prefix,
  24. const char *strip_func_prefix) {
  25. if (0 == internal_strcmp(format, "DEFAULT"))
  26. format = kDefaultFormat;
  27. for (const char *p = format; *p != '\0'; p++) {
  28. if (*p != '%') {
  29. buffer->append("%c", *p);
  30. continue;
  31. }
  32. p++;
  33. switch (*p) {
  34. case '%':
  35. buffer->append("%%");
  36. break;
  37. // Frame number and all fields of AddressInfo structure.
  38. case 'n':
  39. buffer->append("%zu", frame_no);
  40. break;
  41. case 'p':
  42. buffer->append("0x%zx", info.address);
  43. break;
  44. case 'm':
  45. buffer->append("%s", StripPathPrefix(info.module, strip_path_prefix));
  46. break;
  47. case 'o':
  48. buffer->append("0x%zx", info.module_offset);
  49. break;
  50. case 'f':
  51. buffer->append("%s", StripFunctionName(info.function, strip_func_prefix));
  52. break;
  53. case 'q':
  54. buffer->append("0x%zx", info.function_offset != AddressInfo::kUnknown
  55. ? info.function_offset
  56. : 0x0);
  57. break;
  58. case 's':
  59. buffer->append("%s", StripPathPrefix(info.file, strip_path_prefix));
  60. break;
  61. case 'l':
  62. buffer->append("%d", info.line);
  63. break;
  64. case 'c':
  65. buffer->append("%d", info.column);
  66. break;
  67. // Smarter special cases.
  68. case 'F':
  69. // Function name and offset, if file is unknown.
  70. if (info.function) {
  71. buffer->append("in %s",
  72. StripFunctionName(info.function, strip_func_prefix));
  73. if (!info.file && info.function_offset != AddressInfo::kUnknown)
  74. buffer->append("+0x%zx", info.function_offset);
  75. }
  76. break;
  77. case 'S':
  78. // File/line information.
  79. RenderSourceLocation(buffer, info.file, info.line, info.column,
  80. strip_path_prefix);
  81. break;
  82. case 'L':
  83. // Source location, or module location.
  84. if (info.file) {
  85. RenderSourceLocation(buffer, info.file, info.line, info.column,
  86. strip_path_prefix);
  87. } else if (info.module) {
  88. RenderModuleLocation(buffer, info.module, info.module_offset,
  89. strip_path_prefix);
  90. } else {
  91. buffer->append("(<unknown module>)");
  92. }
  93. break;
  94. case 'M':
  95. // Module basename and offset, or PC.
  96. if (info.module)
  97. buffer->append("(%s+%p)", StripModuleName(info.module),
  98. (void *)info.module_offset);
  99. else
  100. buffer->append("(%p)", (void *)info.address);
  101. break;
  102. default:
  103. Report("Unsupported specifier in stack frame format: %c (0x%zx)!\n",
  104. *p, *p);
  105. Die();
  106. }
  107. }
  108. }
  109. void RenderSourceLocation(InternalScopedString *buffer, const char *file,
  110. int line, int column, const char *strip_path_prefix) {
  111. buffer->append("%s", StripPathPrefix(file, strip_path_prefix));
  112. if (line > 0) {
  113. buffer->append(":%d", line);
  114. if (column > 0)
  115. buffer->append(":%d", column);
  116. }
  117. }
  118. void RenderModuleLocation(InternalScopedString *buffer, const char *module,
  119. uptr offset, const char *strip_path_prefix) {
  120. buffer->append("(%s+0x%zx)", StripPathPrefix(module, strip_path_prefix),
  121. offset);
  122. }
  123. } // namespace __sanitizer