123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160 |
- //===-- sanitizer_symbolizer_markup.cpp -----------------------------------===//
- //
- // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
- // See https://llvm.org/LICENSE.txt for license information.
- // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
- //
- //===----------------------------------------------------------------------===//
- //
- // This file is shared between various sanitizers' runtime libraries.
- //
- // This generic support for offline symbolizing is based on the
- // Fuchsia port. We don't do any actual symbolization per se.
- // Instead, we emit text containing raw addresses and raw linkage
- // symbol names, embedded in Fuchsia's symbolization markup format.
- // See the spec at:
- // https://llvm.org/docs/SymbolizerMarkupFormat.html
- //===----------------------------------------------------------------------===//
- #include "sanitizer_symbolizer_markup.h"
- #include "sanitizer_common.h"
- #include "sanitizer_symbolizer.h"
- #include "sanitizer_symbolizer_markup_constants.h"
- namespace __sanitizer {
- void MarkupStackTracePrinter::RenderData(InternalScopedString *buffer,
- const char *format, const DataInfo *DI,
- const char *strip_path_prefix) {
- RenderContext(buffer);
- buffer->AppendF(kFormatData, DI->start);
- }
- bool MarkupStackTracePrinter::RenderNeedsSymbolization(const char *format) {
- return false;
- }
- // We don't support the stack_trace_format flag at all.
- void MarkupStackTracePrinter::RenderFrame(InternalScopedString *buffer,
- const char *format, int frame_no,
- uptr address, const AddressInfo *info,
- bool vs_style,
- const char *strip_path_prefix) {
- CHECK(!RenderNeedsSymbolization(format));
- RenderContext(buffer);
- buffer->AppendF(kFormatFrame, frame_no, address);
- }
- bool MarkupSymbolizerTool::SymbolizePC(uptr addr, SymbolizedStack *stack) {
- char buffer[kFormatFunctionMax];
- internal_snprintf(buffer, sizeof(buffer), kFormatFunction, addr);
- stack->info.function = internal_strdup(buffer);
- return true;
- }
- bool MarkupSymbolizerTool::SymbolizeData(uptr addr, DataInfo *info) {
- info->Clear();
- info->start = addr;
- return true;
- }
- const char *MarkupSymbolizerTool::Demangle(const char *name) {
- static char buffer[kFormatDemangleMax];
- internal_snprintf(buffer, sizeof(buffer), kFormatDemangle, name);
- return buffer;
- }
- // Fuchsia's implementation of symbolizer markup doesn't need to emit contextual
- // elements at this point.
- // Fuchsia's logging infrastructure emits enough information about
- // process memory layout that a post-processing filter can do the
- // symbolization and pretty-print the markup.
- #if !SANITIZER_FUCHSIA
- static bool ModulesEq(const LoadedModule &module,
- const RenderedModule &renderedModule) {
- return module.base_address() == renderedModule.base_address &&
- internal_memcmp(module.uuid(), renderedModule.uuid,
- module.uuid_size()) == 0 &&
- internal_strcmp(module.full_name(), renderedModule.full_name) == 0;
- }
- static bool ModuleHasBeenRendered(
- const LoadedModule &module,
- const InternalMmapVectorNoCtor<RenderedModule> &renderedModules) {
- for (const auto &renderedModule : renderedModules)
- if (ModulesEq(module, renderedModule))
- return true;
- return false;
- }
- static void RenderModule(InternalScopedString *buffer,
- const LoadedModule &module, uptr moduleId) {
- InternalScopedString buildIdBuffer;
- for (uptr i = 0; i < module.uuid_size(); i++)
- buildIdBuffer.AppendF("%02x", module.uuid()[i]);
- buffer->AppendF(kFormatModule, moduleId, module.full_name(),
- buildIdBuffer.data());
- buffer->Append("\n");
- }
- static void RenderMmaps(InternalScopedString *buffer,
- const LoadedModule &module, uptr moduleId) {
- InternalScopedString accessBuffer;
- // All module mmaps are readable at least
- for (const auto &range : module.ranges()) {
- accessBuffer.Append("r");
- if (range.writable)
- accessBuffer.Append("w");
- if (range.executable)
- accessBuffer.Append("x");
- //{{{mmap:%starting_addr:%size_in_hex:load:%moduleId:r%(w|x):%relative_addr}}}
- // module.base_address == dlpi_addr
- // range.beg == dlpi_addr + p_vaddr
- // relative address == p_vaddr == range.beg - module.base_address
- buffer->AppendF(kFormatMmap, range.beg, range.end - range.beg, moduleId,
- accessBuffer.data(), range.beg - module.base_address());
- buffer->Append("\n");
- accessBuffer.clear();
- }
- }
- void MarkupStackTracePrinter::RenderContext(InternalScopedString *buffer) {
- if (renderedModules_.size() == 0)
- buffer->Append("{{{reset}}}\n");
- const auto &modules = Symbolizer::GetOrInit()->GetRefreshedListOfModules();
- for (const auto &module : modules) {
- if (ModuleHasBeenRendered(module, renderedModules_))
- continue;
- // symbolizer markup id, used to refer to this modules from other contextual
- // elements
- uptr moduleId = renderedModules_.size();
- RenderModule(buffer, module, moduleId);
- RenderMmaps(buffer, module, moduleId);
- renderedModules_.push_back({
- internal_strdup(module.full_name()),
- module.base_address(),
- {},
- });
- // kModuleUUIDSize is the size of curModule.uuid
- CHECK_GE(kModuleUUIDSize, module.uuid_size());
- internal_memcpy(renderedModules_.back().uuid, module.uuid(),
- module.uuid_size());
- }
- }
- #endif // !SANITIZER_FUCHSIA
- } // namespace __sanitizer
|