diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_common_interface_posix.inc b/compiler-rt/lib/sanitizer_common/sanitizer_common_interface_posix.inc index a5259be9335aca..6b567edc97a857 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_common_interface_posix.inc +++ b/compiler-rt/lib/sanitizer_common/sanitizer_common_interface_posix.inc @@ -9,6 +9,7 @@ //===----------------------------------------------------------------------===// INTERFACE_WEAK_FUNCTION(__sanitizer_symbolize_code) INTERFACE_WEAK_FUNCTION(__sanitizer_symbolize_data) +INTERFACE_WEAK_FUNCTION(__sanitizer_symbolize_frame) INTERFACE_WEAK_FUNCTION(__sanitizer_symbolize_demangle) INTERFACE_WEAK_FUNCTION(__sanitizer_symbolize_flush) INTERFACE_WEAK_FUNCTION(__sanitizer_symbolize_set_demangle) diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_symbolizer_internal.h b/compiler-rt/lib/sanitizer_common/sanitizer_symbolizer_internal.h index 3ec4d80105a245..2345aee9855413 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_symbolizer_internal.h +++ b/compiler-rt/lib/sanitizer_common/sanitizer_symbolizer_internal.h @@ -160,6 +160,15 @@ void ParseSymbolizePCOutput(const char *str, SymbolizedStack *res); // Used by LLVMSymbolizer and InternalSymbolizer. void ParseSymbolizeDataOutput(const char *str, DataInfo *info); +// Parses repeated strings in the following format: +// +// +// :[:] +// [|??] [|??] [|??] +// Used by LLVMSymbolizer and InternalSymbolizer. +void ParseSymbolizeFrameOutput(const char *str, + InternalMmapVector *locals); + } // namespace __sanitizer #endif // SANITIZER_SYMBOLIZER_INTERNAL_H diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_symbolizer_libcdep.cpp b/compiler-rt/lib/sanitizer_common/sanitizer_symbolizer_libcdep.cpp index d910aef3f74162..0d5af6ccdd2d85 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_symbolizer_libcdep.cpp +++ b/compiler-rt/lib/sanitizer_common/sanitizer_symbolizer_libcdep.cpp @@ -385,8 +385,8 @@ void ParseSymbolizeDataOutput(const char *str, DataInfo *info) { str = ExtractUptr(str, "\n", &info->line); } -static void ParseSymbolizeFrameOutput(const char *str, - InternalMmapVector *locals) { +void ParseSymbolizeFrameOutput(const char *str, + InternalMmapVector *locals) { if (internal_strncmp(str, "??", 2) == 0) return; diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_symbolizer_posix_libcdep.cpp b/compiler-rt/lib/sanitizer_common/sanitizer_symbolizer_posix_libcdep.cpp index 724ad4722909f1..d92349c04fffab 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_symbolizer_posix_libcdep.cpp +++ b/compiler-rt/lib/sanitizer_common/sanitizer_symbolizer_posix_libcdep.cpp @@ -324,6 +324,9 @@ __sanitizer_symbolize_code(const char *ModuleName, u64 ModuleOffset, SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE bool __sanitizer_symbolize_data(const char *ModuleName, u64 ModuleOffset, char *Buffer, int MaxLength); +SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE bool +__sanitizer_symbolize_frame(const char *ModuleName, u64 ModuleOffset, + char *Buffer, int MaxLength); SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE void __sanitizer_symbolize_flush(); SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE bool @@ -366,6 +369,16 @@ class InternalSymbolizer final : public SymbolizerTool { return result; } + bool SymbolizeFrame(uptr addr, FrameInfo *info) override { + if (&__sanitizer_symbolize_frame == nullptr) + return false; + bool result = __sanitizer_symbolize_frame(info->module, info->module_offset, + buffer_, sizeof(buffer_)); + if (result) + ParseSymbolizeFrameOutput(buffer_, &info->locals); + return result; + } + void Flush() override { if (&__sanitizer_symbolize_flush) __sanitizer_symbolize_flush(); diff --git a/compiler-rt/lib/sanitizer_common/symbolizer/sanitizer_symbolize.cpp b/compiler-rt/lib/sanitizer_common/symbolizer/sanitizer_symbolize.cpp index ac27c0e25715f2..877191943fb5d4 100644 --- a/compiler-rt/lib/sanitizer_common/symbolizer/sanitizer_symbolize.cpp +++ b/compiler-rt/lib/sanitizer_common/symbolizer/sanitizer_symbolize.cpp @@ -115,6 +115,29 @@ bool __sanitizer_symbolize_data(const char *ModuleName, uint64_t ModuleOffset, Result.c_str()) < MaxLength; } +bool __sanitizer_symbolize_frame(const char *ModuleName, uint64_t ModuleOffset, + char *Buffer, int MaxLength) { + std::string Result; + { + llvm::symbolize::PrinterConfig Config = getDefaultPrinterConfig(); + llvm::raw_string_ostream OS(Result); + llvm::symbolize::Request Request{ModuleName, ModuleOffset}; + auto Printer = std::make_unique( + OS, symbolize_error_handler(OS), Config); + + // TODO: it is neccessary to set proper SectionIndex here. + // object::SectionedAddress::UndefSection works for only absolute addresses. + auto ResOrErr = getDefaultSymbolizer()->symbolizeFrame( + ModuleName, + {ModuleOffset, llvm::object::SectionedAddress::UndefSection}); + if (!ResOrErr) + return false; + Printer->print(Request, ResOrErr.get()); + } + return __sanitizer::internal_snprintf(Buffer, MaxLength, "%s", + Result.c_str()) < MaxLength; +} + void __sanitizer_symbolize_flush() { if (Symbolizer) Symbolizer->flush(); diff --git a/compiler-rt/lib/sanitizer_common/symbolizer/scripts/build_symbolizer.sh b/compiler-rt/lib/sanitizer_common/symbolizer/scripts/build_symbolizer.sh index 524ddca1b9f3e4..6eb9fa7abb7e0c 100755 --- a/compiler-rt/lib/sanitizer_common/symbolizer/scripts/build_symbolizer.sh +++ b/compiler-rt/lib/sanitizer_common/symbolizer/scripts/build_symbolizer.sh @@ -140,6 +140,7 @@ $AR rc symbolizer.a sanitizer_symbolize.o sanitizer_wrappers.o SYMBOLIZER_API_LIST=__sanitizer_symbolize_code SYMBOLIZER_API_LIST+=,__sanitizer_symbolize_data +SYMBOLIZER_API_LIST+=,__sanitizer_symbolize_frame SYMBOLIZER_API_LIST+=,__sanitizer_symbolize_flush SYMBOLIZER_API_LIST+=,__sanitizer_symbolize_demangle SYMBOLIZER_API_LIST+=,__sanitizer_symbolize_set_demangle diff --git a/compiler-rt/lib/sanitizer_common/symbolizer/scripts/global_symbols.txt b/compiler-rt/lib/sanitizer_common/symbolizer/scripts/global_symbols.txt index 5cafae54660ef9..0a4bc6989a0d72 100644 --- a/compiler-rt/lib/sanitizer_common/symbolizer/scripts/global_symbols.txt +++ b/compiler-rt/lib/sanitizer_common/symbolizer/scripts/global_symbols.txt @@ -59,6 +59,7 @@ __sanitizer_symbolize_code T __sanitizer_symbolize_data T __sanitizer_symbolize_demangle T __sanitizer_symbolize_flush T +__sanitizer_symbolize_frame T __sanitizer_symbolize_set_demangle T __sanitizer_symbolize_set_inline_frames T __strdup U diff --git a/compiler-rt/test/sanitizer_common/TestCases/Linux/internal_symbolizer.cpp b/compiler-rt/test/sanitizer_common/TestCases/Linux/internal_symbolizer.cpp index d4eb300cf3d900..2421616676cfac 100644 --- a/compiler-rt/test/sanitizer_common/TestCases/Linux/internal_symbolizer.cpp +++ b/compiler-rt/test/sanitizer_common/TestCases/Linux/internal_symbolizer.cpp @@ -17,6 +17,8 @@ bool __sanitizer_symbolize_code(const char *ModuleName, uint64_t ModuleOffset, bool SymbolizeInlineFrames); bool __sanitizer_symbolize_data(const char *ModuleName, uint64_t ModuleOffset, char *Buffer, int MaxLength); +bool __sanitizer_symbolize_frame(const char *ModuleName, uint64_t ModuleOffset, + char *Buffer, int MaxLength); void __sanitizer_print_stack_trace(); bool __sanitizer_symbolize_demangle(const char *Name, char *Buffer, int MaxLength); @@ -132,6 +134,40 @@ void TestData() { // CHECK-NEXT: internal_symbolizer.cpp:[[# @LINE - 13]] } +__attribute__((noinline)) std::string SymbolizeLocalVars(FrameInfo frame) { + auto modul_offset = GetModuleAndOffset(frame.address); + char buffer[1024] = {}; + ScopedInSymbolizer in_symbolizer; + __sanitizer_symbolize_frame(modul_offset.first, modul_offset.second, buffer, + std::size(buffer)); + return buffer; +} + +__attribute__(( + noinline, + no_sanitize_address /* Asan merges allocas destroying variable DI*/)) void +TestFrame() { + volatile int var = 1; + void *address = GetPC(); + fprintf(stderr, "%s: %s\n", __FUNCTION__, + SymbolizeLocalVars({ + 0, + "", + "", + reinterpret_cast( + reinterpret_cast(address)), + }) + .c_str()); + // CHECK-LABEL: TestFrame: TestFrame + // CHECK-NEXT: var + // CHECK-NEXT: internal_symbolizer.cpp:[[# @LINE - 13]] + // CHECK-NEXT: {{-?[0-9]+ +[0-9]+}} + // CHECK-NEXT: TestFrame + // CHECK-NEXT: address + // CHECK-NEXT: internal_symbolizer.cpp:[[# @LINE - 16]] + // CHECK-NEXT: {{-?[0-9]+ +[0-9]+}} +} + void TestDemangle() { char out[128]; assert(!__sanitizer_symbolize_demangle("1A", out, sizeof(out))); @@ -149,5 +185,6 @@ int main() { TestNoInline(); TestLongFunctionNames(); TestData(); + TestFrame(); TestDemangle(); }