sanitizer_symbolizer_markup.cpp 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160
  1. //===-- sanitizer_symbolizer_markup.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 various sanitizers' runtime libraries.
  10. //
  11. // This generic support for offline symbolizing is based on the
  12. // Fuchsia port. We don't do any actual symbolization per se.
  13. // Instead, we emit text containing raw addresses and raw linkage
  14. // symbol names, embedded in Fuchsia's symbolization markup format.
  15. // See the spec at:
  16. // https://llvm.org/docs/SymbolizerMarkupFormat.html
  17. //===----------------------------------------------------------------------===//
  18. #include "sanitizer_symbolizer_markup.h"
  19. #include "sanitizer_common.h"
  20. #include "sanitizer_symbolizer.h"
  21. #include "sanitizer_symbolizer_markup_constants.h"
  22. namespace __sanitizer {
  23. void MarkupStackTracePrinter::RenderData(InternalScopedString *buffer,
  24. const char *format, const DataInfo *DI,
  25. const char *strip_path_prefix) {
  26. RenderContext(buffer);
  27. buffer->AppendF(kFormatData, DI->start);
  28. }
  29. bool MarkupStackTracePrinter::RenderNeedsSymbolization(const char *format) {
  30. return false;
  31. }
  32. // We don't support the stack_trace_format flag at all.
  33. void MarkupStackTracePrinter::RenderFrame(InternalScopedString *buffer,
  34. const char *format, int frame_no,
  35. uptr address, const AddressInfo *info,
  36. bool vs_style,
  37. const char *strip_path_prefix) {
  38. CHECK(!RenderNeedsSymbolization(format));
  39. RenderContext(buffer);
  40. buffer->AppendF(kFormatFrame, frame_no, address);
  41. }
  42. bool MarkupSymbolizerTool::SymbolizePC(uptr addr, SymbolizedStack *stack) {
  43. char buffer[kFormatFunctionMax];
  44. internal_snprintf(buffer, sizeof(buffer), kFormatFunction, addr);
  45. stack->info.function = internal_strdup(buffer);
  46. return true;
  47. }
  48. bool MarkupSymbolizerTool::SymbolizeData(uptr addr, DataInfo *info) {
  49. info->Clear();
  50. info->start = addr;
  51. return true;
  52. }
  53. const char *MarkupSymbolizerTool::Demangle(const char *name) {
  54. static char buffer[kFormatDemangleMax];
  55. internal_snprintf(buffer, sizeof(buffer), kFormatDemangle, name);
  56. return buffer;
  57. }
  58. // Fuchsia's implementation of symbolizer markup doesn't need to emit contextual
  59. // elements at this point.
  60. // Fuchsia's logging infrastructure emits enough information about
  61. // process memory layout that a post-processing filter can do the
  62. // symbolization and pretty-print the markup.
  63. #if !SANITIZER_FUCHSIA
  64. static bool ModulesEq(const LoadedModule &module,
  65. const RenderedModule &renderedModule) {
  66. return module.base_address() == renderedModule.base_address &&
  67. internal_memcmp(module.uuid(), renderedModule.uuid,
  68. module.uuid_size()) == 0 &&
  69. internal_strcmp(module.full_name(), renderedModule.full_name) == 0;
  70. }
  71. static bool ModuleHasBeenRendered(
  72. const LoadedModule &module,
  73. const InternalMmapVectorNoCtor<RenderedModule> &renderedModules) {
  74. for (const auto &renderedModule : renderedModules)
  75. if (ModulesEq(module, renderedModule))
  76. return true;
  77. return false;
  78. }
  79. static void RenderModule(InternalScopedString *buffer,
  80. const LoadedModule &module, uptr moduleId) {
  81. InternalScopedString buildIdBuffer;
  82. for (uptr i = 0; i < module.uuid_size(); i++)
  83. buildIdBuffer.AppendF("%02x", module.uuid()[i]);
  84. buffer->AppendF(kFormatModule, moduleId, module.full_name(),
  85. buildIdBuffer.data());
  86. buffer->Append("\n");
  87. }
  88. static void RenderMmaps(InternalScopedString *buffer,
  89. const LoadedModule &module, uptr moduleId) {
  90. InternalScopedString accessBuffer;
  91. // All module mmaps are readable at least
  92. for (const auto &range : module.ranges()) {
  93. accessBuffer.Append("r");
  94. if (range.writable)
  95. accessBuffer.Append("w");
  96. if (range.executable)
  97. accessBuffer.Append("x");
  98. //{{{mmap:%starting_addr:%size_in_hex:load:%moduleId:r%(w|x):%relative_addr}}}
  99. // module.base_address == dlpi_addr
  100. // range.beg == dlpi_addr + p_vaddr
  101. // relative address == p_vaddr == range.beg - module.base_address
  102. buffer->AppendF(kFormatMmap, range.beg, range.end - range.beg, moduleId,
  103. accessBuffer.data(), range.beg - module.base_address());
  104. buffer->Append("\n");
  105. accessBuffer.clear();
  106. }
  107. }
  108. void MarkupStackTracePrinter::RenderContext(InternalScopedString *buffer) {
  109. if (renderedModules_.size() == 0)
  110. buffer->Append("{{{reset}}}\n");
  111. const auto &modules = Symbolizer::GetOrInit()->GetRefreshedListOfModules();
  112. for (const auto &module : modules) {
  113. if (ModuleHasBeenRendered(module, renderedModules_))
  114. continue;
  115. // symbolizer markup id, used to refer to this modules from other contextual
  116. // elements
  117. uptr moduleId = renderedModules_.size();
  118. RenderModule(buffer, module, moduleId);
  119. RenderMmaps(buffer, module, moduleId);
  120. renderedModules_.push_back({
  121. internal_strdup(module.full_name()),
  122. module.base_address(),
  123. {},
  124. });
  125. // kModuleUUIDSize is the size of curModule.uuid
  126. CHECK_GE(kModuleUUIDSize, module.uuid_size());
  127. internal_memcpy(renderedModules_.back().uuid, module.uuid(),
  128. module.uuid_size());
  129. }
  130. }
  131. #endif // !SANITIZER_FUCHSIA
  132. } // namespace __sanitizer