diff --git a/compiler-rt/lib/hwasan/hwasan_report.cpp b/compiler-rt/lib/hwasan/hwasan_report.cpp index efe6f57704919..5b6920f7da30b 100644 --- a/compiler-rt/lib/hwasan/hwasan_report.cpp +++ b/compiler-rt/lib/hwasan/hwasan_report.cpp @@ -246,9 +246,10 @@ static void PrintStackAllocations(StackAllocationsRingBuffer *sa, frame_desc.append(" record_addr:0x%zx record:0x%zx", reinterpret_cast(record_addr), record); if (SymbolizedStack *frame = Symbolizer::GetOrInit()->SymbolizePC(pc)) { - RenderFrame(&frame_desc, " %F %L", 0, frame->info.address, &frame->info, - common_flags()->symbolize_vs_style, - common_flags()->strip_path_prefix); + StackTracePrinter::GetOrInit()->RenderFrame( + &frame_desc, " %F %L", 0, frame->info.address, &frame->info, + common_flags()->symbolize_vs_style, + common_flags()->strip_path_prefix); frame->ClearAll(); } Printf("%s\n", frame_desc.data()); diff --git a/compiler-rt/lib/msan/msan_report.cpp b/compiler-rt/lib/msan/msan_report.cpp index 90164e50ca3ac..99bf81f66dc9e 100644 --- a/compiler-rt/lib/msan/msan_report.cpp +++ b/compiler-rt/lib/msan/msan_report.cpp @@ -269,7 +269,7 @@ void DescribeMemoryRange(const void *x, uptr size) { void ReportUMRInsideAddressRange(const char *function, const void *start, uptr size, uptr offset) { - function = StripFunctionName(function); + function = StackTracePrinter::GetOrInit()->StripFunctionName(function); Decorator d; Printf("%s", d.Warning()); Printf("%sUninitialized bytes in %s%s%s at offset %zu inside [%p, %zu)%s\n", diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_stacktrace_libcdep.cpp b/compiler-rt/lib/sanitizer_common/sanitizer_stacktrace_libcdep.cpp index 47983ee7ec713..2a0417ed96de1 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_stacktrace_libcdep.cpp +++ b/compiler-rt/lib/sanitizer_common/sanitizer_stacktrace_libcdep.cpp @@ -29,7 +29,8 @@ class StackTraceTextPrinter { frame_delimiter_(frame_delimiter), output_(output), dedup_token_(dedup_token), - symbolize_(RenderNeedsSymbolization(stack_trace_fmt)) {} + symbolize_(StackTracePrinter::GetOrInit()->RenderNeedsSymbolization( + stack_trace_fmt)) {} bool ProcessAddressFrames(uptr pc) { SymbolizedStack *frames = symbolize_ @@ -40,10 +41,10 @@ class StackTraceTextPrinter { for (SymbolizedStack *cur = frames; cur; cur = cur->next) { uptr prev_len = output_->length(); - RenderFrame(output_, stack_trace_fmt_, frame_num_++, cur->info.address, - symbolize_ ? &cur->info : nullptr, - common_flags()->symbolize_vs_style, - common_flags()->strip_path_prefix); + StackTracePrinter::GetOrInit()->RenderFrame( + output_, stack_trace_fmt_, frame_num_++, cur->info.address, + symbolize_ ? &cur->info : nullptr, common_flags()->symbolize_vs_style, + common_flags()->strip_path_prefix); if (prev_len != output_->length()) output_->append("%c", frame_delimiter_); @@ -210,7 +211,8 @@ void __sanitizer_symbolize_global(uptr data_addr, const char *fmt, DataInfo DI; if (!Symbolizer::GetOrInit()->SymbolizeData(data_addr, &DI)) return; InternalScopedString data_desc; - RenderData(&data_desc, fmt, &DI, common_flags()->strip_path_prefix); + StackTracePrinter::GetOrInit()->RenderData(&data_desc, fmt, &DI, + common_flags()->strip_path_prefix); internal_strncpy(out_buf, data_desc.data(), out_buf_size); out_buf[out_buf_size - 1] = 0; } diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_stacktrace_printer.cpp b/compiler-rt/lib/sanitizer_common/sanitizer_stacktrace_printer.cpp index 45c480d225c7f..9d9b479f70b4d 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_stacktrace_printer.cpp +++ b/compiler-rt/lib/sanitizer_common/sanitizer_stacktrace_printer.cpp @@ -12,13 +12,30 @@ #include "sanitizer_stacktrace_printer.h" +#include "sanitizer_common.h" #include "sanitizer_file.h" #include "sanitizer_flags.h" #include "sanitizer_fuchsia.h" namespace __sanitizer { -const char *StripFunctionName(const char *function) { + +StackTracePrinter *StackTracePrinter::GetOrInit() { + static StackTracePrinter *stacktrace_printer; + static StaticSpinMutex init_mu; + SpinMutexLock l(&init_mu); + if (stacktrace_printer) + return stacktrace_printer; + + stacktrace_printer = + new (GetGlobalLowLevelAllocator()) FormattedStackTracePrinter(); + + CHECK(stacktrace_printer); + return stacktrace_printer; +} + +const char *FormattedStackTracePrinter::StripFunctionName( + const char *function) { if (!common_flags()->demangle) return function; if (!function) @@ -141,9 +158,12 @@ static void MaybeBuildIdToBuffer(const AddressInfo &info, bool PrefixSpace, static const char kDefaultFormat[] = " #%n %p %F %L"; -void RenderFrame(InternalScopedString *buffer, const char *format, int frame_no, - uptr address, const AddressInfo *info, bool vs_style, - const char *strip_path_prefix) { +void FormattedStackTracePrinter::RenderFrame(InternalScopedString *buffer, + const char *format, int frame_no, + uptr address, + const AddressInfo *info, + bool vs_style, + const char *strip_path_prefix) { // info will be null in the case where symbolization is not needed for the // given format. This ensures that the code below will get a hard failure // rather than print incorrect information in case RenderNeedsSymbolization @@ -250,7 +270,7 @@ void RenderFrame(InternalScopedString *buffer, const char *format, int frame_no, } } -bool RenderNeedsSymbolization(const char *format) { +bool FormattedStackTracePrinter::RenderNeedsSymbolization(const char *format) { if (0 == internal_strcmp(format, "DEFAULT")) format = kDefaultFormat; for (const char *p = format; *p != '\0'; p++) { @@ -273,8 +293,10 @@ bool RenderNeedsSymbolization(const char *format) { return false; } -void RenderData(InternalScopedString *buffer, const char *format, - const DataInfo *DI, const char *strip_path_prefix) { +void FormattedStackTracePrinter::RenderData(InternalScopedString *buffer, + const char *format, + const DataInfo *DI, + const char *strip_path_prefix) { for (const char *p = format; *p != '\0'; p++) { if (*p != '%') { buffer->append("%c", *p); @@ -304,9 +326,9 @@ void RenderData(InternalScopedString *buffer, const char *format, #endif // !SANITIZER_SYMBOLIZER_MARKUP -void RenderSourceLocation(InternalScopedString *buffer, const char *file, - int line, int column, bool vs_style, - const char *strip_path_prefix) { +void FormattedStackTracePrinter::RenderSourceLocation( + InternalScopedString *buffer, const char *file, int line, int column, + bool vs_style, const char *strip_path_prefix) { if (vs_style && line > 0) { buffer->append("%s(%d", StripPathPrefix(file, strip_path_prefix), line); if (column > 0) @@ -323,9 +345,9 @@ void RenderSourceLocation(InternalScopedString *buffer, const char *file, } } -void RenderModuleLocation(InternalScopedString *buffer, const char *module, - uptr offset, ModuleArch arch, - const char *strip_path_prefix) { +void FormattedStackTracePrinter::RenderModuleLocation( + InternalScopedString *buffer, const char *module, uptr offset, + ModuleArch arch, const char *strip_path_prefix) { buffer->append("(%s", StripPathPrefix(module, strip_path_prefix)); if (arch != kModuleArchUnknown) { buffer->append(":%s", ModuleArchToString(arch)); diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_stacktrace_printer.h b/compiler-rt/lib/sanitizer_common/sanitizer_stacktrace_printer.h index bf2755a2e8f45..bbdf70e7ab65a 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_stacktrace_printer.h +++ b/compiler-rt/lib/sanitizer_common/sanitizer_stacktrace_printer.h @@ -13,61 +13,107 @@ #define SANITIZER_STACKTRACE_PRINTER_H #include "sanitizer_common.h" +#include "sanitizer_internal_defs.h" #include "sanitizer_symbolizer.h" namespace __sanitizer { -// Strip interceptor prefixes from function name. -const char *StripFunctionName(const char *function); - -// Render the contents of "info" structure, which represents the contents of -// stack frame "frame_no" and appends it to the "buffer". "format" is a -// string with placeholders, which is copied to the output with -// placeholders substituted with the contents of "info". For example, -// format string -// " frame %n: function %F at %S" -// will be turned into -// " frame 10: function foo::bar() at my/file.cc:10" -// You may additionally pass "strip_path_prefix" to strip prefixes of paths to -// source files and modules. -// Here's the full list of available placeholders: -// %% - represents a '%' character; -// %n - frame number (copy of frame_no); -// %p - PC in hex format; -// %m - path to module (binary or shared object); -// %o - offset in the module in hex format; -// %f - function name; -// %q - offset in the function in hex format (*if available*); -// %s - path to source file; -// %l - line in the source file; -// %c - column in the source file; -// %F - if function is known to be , prints "in ", possibly -// followed by the offset in this function, but only if source file -// is unknown; -// %S - prints file/line/column information; -// %L - prints location information: file/line/column, if it is known, or -// module+offset if it is known, or () string. -// %M - prints module basename and offset, if it is known, or PC. -void RenderFrame(InternalScopedString *buffer, const char *format, int frame_no, - uptr address, const AddressInfo *info, bool vs_style, - const char *strip_path_prefix = ""); - -bool RenderNeedsSymbolization(const char *format); - -void RenderSourceLocation(InternalScopedString *buffer, const char *file, - int line, int column, bool vs_style, - const char *strip_path_prefix); - -void RenderModuleLocation(InternalScopedString *buffer, const char *module, - uptr offset, ModuleArch arch, - const char *strip_path_prefix); - -// Same as RenderFrame, but for data section (global variables). -// Accepts %s, %l from above. -// Also accepts: -// %g - name of the global variable. -void RenderData(InternalScopedString *buffer, const char *format, - const DataInfo *DI, const char *strip_path_prefix = ""); +// StacktracePrinter is an interface that is implemented by +// classes that can perform rendering of the different parts +// of a stacktrace. +class StackTracePrinter { + public: + static StackTracePrinter *GetOrInit(); + + virtual const char *StripFunctionName(const char *function) { + UNIMPLEMENTED(); + } + + virtual void RenderFrame(InternalScopedString *buffer, const char *format, + int frame_no, uptr address, const AddressInfo *info, + bool vs_style, const char *strip_path_prefix = "") { + UNIMPLEMENTED(); + } + + virtual bool RenderNeedsSymbolization(const char *format) { return false; } + + virtual void RenderSourceLocation(InternalScopedString *buffer, + const char *file, int line, int column, + bool vs_style, + const char *strip_path_prefix) {} + + virtual void RenderModuleLocation(InternalScopedString *buffer, + const char *module, uptr offset, + ModuleArch arch, + const char *strip_path_prefix) {} + virtual void RenderData(InternalScopedString *buffer, const char *format, + const DataInfo *DI, + const char *strip_path_prefix = "") { + UNIMPLEMENTED(); + } + + protected: + ~StackTracePrinter() {} +}; + +class FormattedStackTracePrinter : public StackTracePrinter { + public: + // Strip interceptor prefixes from function name. + const char *StripFunctionName(const char *function) override; + + // Render the contents of "info" structure, which represents the contents of + // stack frame "frame_no" and appends it to the "buffer". "format" is a + // string with placeholders, which is copied to the output with + // placeholders substituted with the contents of "info". For example, + // format string + // " frame %n: function %F at %S" + // will be turned into + // " frame 10: function foo::bar() at my/file.cc:10" + // You may additionally pass "strip_path_prefix" to strip prefixes of paths to + // source files and modules. + // Here's the full list of available placeholders: + // %% - represents a '%' character; + // %n - frame number (copy of frame_no); + // %p - PC in hex format; + // %m - path to module (binary or shared object); + // %o - offset in the module in hex format; + // %f - function name; + // %q - offset in the function in hex format (*if available*); + // %s - path to source file; + // %l - line in the source file; + // %c - column in the source file; + // %F - if function is known to be , prints "in ", possibly + // followed by the offset in this function, but only if source file + // is unknown; + // %S - prints file/line/column information; + // %L - prints location information: file/line/column, if it is known, or + // module+offset if it is known, or () string. + // %M - prints module basename and offset, if it is known, or PC. + void RenderFrame(InternalScopedString *buffer, const char *format, + int frame_no, uptr address, const AddressInfo *info, + bool vs_style, const char *strip_path_prefix = "") override; + + bool RenderNeedsSymbolization(const char *format) override; + + void RenderSourceLocation(InternalScopedString *buffer, const char *file, + int line, int column, bool vs_style, + const char *strip_path_prefix) override; + + void RenderModuleLocation(InternalScopedString *buffer, const char *module, + uptr offset, ModuleArch arch, + const char *strip_path_prefix) override; + + // Same as RenderFrame, but for data section (global variables). + // Accepts %s, %l from above. + // Also accepts: + // %g - name of the global variable. + void RenderData(InternalScopedString *buffer, const char *format, + const DataInfo *DI, + const char *strip_path_prefix = "") override; + + protected: + ~FormattedStackTracePrinter() {} +}; } // namespace __sanitizer diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_symbolizer_markup.cpp b/compiler-rt/lib/sanitizer_common/sanitizer_symbolizer_markup.cpp index c8c10de10d03a..cf2309d0ed198 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_symbolizer_markup.cpp +++ b/compiler-rt/lib/sanitizer_common/sanitizer_symbolizer_markup.cpp @@ -81,17 +81,24 @@ bool Symbolizer::SymbolizeData(uptr addr, DataInfo *info) { } // We ignore the format argument to __sanitizer_symbolize_global. -void RenderData(InternalScopedString *buffer, const char *format, - const DataInfo *DI, const char *strip_path_prefix) { +void FormattedStackTracePrinter::RenderData(InternalScopedString *buffer, + const char *format, + const DataInfo *DI, + const char *strip_path_prefix) { buffer->append(kFormatData, DI->start); } -bool RenderNeedsSymbolization(const char *format) { return false; } +bool FormattedStackTracePrinter::RenderNeedsSymbolization(const char *format) { + return false; +} // We don't support the stack_trace_format flag at all. -void RenderFrame(InternalScopedString *buffer, const char *format, int frame_no, - uptr address, const AddressInfo *info, bool vs_style, - const char *strip_path_prefix) { +void FormattedStackTracePrinter::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)); buffer->append(kFormatFrame, frame_no, address); } diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_symbolizer_report.cpp b/compiler-rt/lib/sanitizer_common/sanitizer_symbolizer_report.cpp index 73915715c5ba2..ef8cf55f0e997 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_symbolizer_report.cpp +++ b/compiler-rt/lib/sanitizer_common/sanitizer_symbolizer_report.cpp @@ -33,9 +33,9 @@ void ReportErrorSummary(const char *error_type, const AddressInfo &info, if (!common_flags()->print_summary) return; InternalScopedString buff; buff.append("%s ", error_type); - RenderFrame(&buff, "%L %F", 0, info.address, &info, - common_flags()->symbolize_vs_style, - common_flags()->strip_path_prefix); + StackTracePrinter::GetOrInit()->RenderFrame( + &buff, "%L %F", 0, info.address, &info, + common_flags()->symbolize_vs_style, common_flags()->strip_path_prefix); ReportErrorSummary(buff.data(), alt_tool_name); } #endif diff --git a/compiler-rt/lib/sanitizer_common/tests/sanitizer_stacktrace_printer_test.cpp b/compiler-rt/lib/sanitizer_common/tests/sanitizer_stacktrace_printer_test.cpp index 489ef4dbb5b7d..c616a90279c86 100644 --- a/compiler-rt/lib/sanitizer_common/tests/sanitizer_stacktrace_printer_test.cpp +++ b/compiler-rt/lib/sanitizer_common/tests/sanitizer_stacktrace_printer_test.cpp @@ -16,57 +16,69 @@ namespace __sanitizer { -TEST(SanitizerStacktracePrinter, RenderSourceLocation) { +class TestFormattedStackTracePrinter final : public FormattedStackTracePrinter { + public: + ~TestFormattedStackTracePrinter() {} +}; + +TEST(FormattedStackTracePrinter, RenderSourceLocation) { InternalScopedString str; - RenderSourceLocation(&str, "/dir/file.cc", 10, 5, false, ""); + TestFormattedStackTracePrinter printer; + + printer.RenderSourceLocation(&str, "/dir/file.cc", 10, 5, false, ""); EXPECT_STREQ("/dir/file.cc:10:5", str.data()); str.clear(); - RenderSourceLocation(&str, "/dir/file.cc", 11, 0, false, ""); + printer.RenderSourceLocation(&str, "/dir/file.cc", 11, 0, false, ""); EXPECT_STREQ("/dir/file.cc:11", str.data()); str.clear(); - RenderSourceLocation(&str, "/dir/file.cc", 0, 0, false, ""); + printer.RenderSourceLocation(&str, "/dir/file.cc", 0, 0, false, ""); EXPECT_STREQ("/dir/file.cc", str.data()); str.clear(); - RenderSourceLocation(&str, "/dir/file.cc", 10, 5, false, "/dir/"); + printer.RenderSourceLocation(&str, "/dir/file.cc", 10, 5, false, "/dir/"); EXPECT_STREQ("file.cc:10:5", str.data()); str.clear(); - RenderSourceLocation(&str, "/dir/file.cc", 10, 5, true, ""); + printer.RenderSourceLocation(&str, "/dir/file.cc", 10, 5, true, ""); EXPECT_STREQ("/dir/file.cc(10,5)", str.data()); str.clear(); - RenderSourceLocation(&str, "/dir/file.cc", 11, 0, true, ""); + printer.RenderSourceLocation(&str, "/dir/file.cc", 11, 0, true, ""); EXPECT_STREQ("/dir/file.cc(11)", str.data()); str.clear(); - RenderSourceLocation(&str, "/dir/file.cc", 0, 0, true, ""); + printer.RenderSourceLocation(&str, "/dir/file.cc", 0, 0, true, ""); EXPECT_STREQ("/dir/file.cc", str.data()); str.clear(); - RenderSourceLocation(&str, "/dir/file.cc", 10, 5, true, "/dir/"); + printer.RenderSourceLocation(&str, "/dir/file.cc", 10, 5, true, "/dir/"); EXPECT_STREQ("file.cc(10,5)", str.data()); } -TEST(SanitizerStacktracePrinter, RenderModuleLocation) { +TEST(FormattedStackTracePrinter, RenderModuleLocation) { InternalScopedString str; - RenderModuleLocation(&str, "/dir/exe", 0x123, kModuleArchUnknown, ""); + TestFormattedStackTracePrinter printer; + printer.RenderModuleLocation(&str, "/dir/exe", 0x123, kModuleArchUnknown, + ""); EXPECT_STREQ("(/dir/exe+0x123)", str.data()); // Check that we strip file prefix if necessary. str.clear(); - RenderModuleLocation(&str, "/dir/exe", 0x123, kModuleArchUnknown, "/dir/"); + printer.RenderModuleLocation(&str, "/dir/exe", 0x123, kModuleArchUnknown, + "/dir/"); EXPECT_STREQ("(exe+0x123)", str.data()); // Check that we render the arch. str.clear(); - RenderModuleLocation(&str, "/dir/exe", 0x123, kModuleArchX86_64H, "/dir/"); + printer.RenderModuleLocation(&str, "/dir/exe", 0x123, kModuleArchX86_64H, + "/dir/"); EXPECT_STREQ("(exe:x86_64h+0x123)", str.data()); } -TEST(SanitizerStacktracePrinter, RenderFrame) { +TEST(FormattedStackTracePrinter, RenderFrame) { + TestFormattedStackTracePrinter printer; int frame_no = 42; AddressInfo info; info.address = 0x400000; @@ -80,11 +92,11 @@ TEST(SanitizerStacktracePrinter, RenderFrame) { InternalScopedString str; // Dump all the AddressInfo fields. - RenderFrame(&str, - "%% Frame:%n PC:%p Module:%m ModuleOffset:%o " - "Function:%f FunctionOffset:%q Source:%s Line:%l " - "Column:%c", - frame_no, info.address, &info, false, "/path/to/"); + printer.RenderFrame(&str, + "%% Frame:%n PC:%p Module:%m ModuleOffset:%o " + "Function:%f FunctionOffset:%q Source:%s Line:%l " + "Column:%c", + frame_no, info.address, &info, false, "/path/to/"); EXPECT_STREQ("% Frame:42 PC:0x400000 Module:my/module ModuleOffset:0x200 " "Function:foo FunctionOffset:0x100 Source:my/source Line:10 " "Column:5", @@ -93,11 +105,11 @@ TEST(SanitizerStacktracePrinter, RenderFrame) { str.clear(); // Check that RenderFrame() strips interceptor prefixes. info.function = internal_strdup(SANITIZER_STRINGIFY(WRAP(bar))); - RenderFrame(&str, - "%% Frame:%n PC:%p Module:%m ModuleOffset:%o " - "Function:%f FunctionOffset:%q Source:%s Line:%l " - "Column:%c", - frame_no, info.address, &info, false, "/path/to/"); + printer.RenderFrame(&str, + "%% Frame:%n PC:%p Module:%m ModuleOffset:%o " + "Function:%f FunctionOffset:%q Source:%s Line:%l " + "Column:%c", + frame_no, info.address, &info, false, "/path/to/"); EXPECT_STREQ("% Frame:42 PC:0x400000 Module:my/module ModuleOffset:0x200 " "Function:bar FunctionOffset:0x100 Source:my/source Line:10 " "Column:5", @@ -107,26 +119,26 @@ TEST(SanitizerStacktracePrinter, RenderFrame) { // Test special format specifiers. info.address = 0x400000; - RenderFrame(&str, "%M", frame_no, info.address, &info, false); + printer.RenderFrame(&str, "%M", frame_no, info.address, &info, false); EXPECT_NE(nullptr, internal_strstr(str.data(), "400000")); str.clear(); - RenderFrame(&str, "%L", frame_no, info.address, &info, false); + printer.RenderFrame(&str, "%L", frame_no, info.address, &info, false); EXPECT_STREQ("()", str.data()); str.clear(); info.module = internal_strdup("/path/to/module"); info.module_offset = 0x200; - RenderFrame(&str, "%M", frame_no, info.address, &info, false); + printer.RenderFrame(&str, "%M", frame_no, info.address, &info, false); EXPECT_NE(nullptr, internal_strstr(str.data(), "(module+0x")); EXPECT_NE(nullptr, internal_strstr(str.data(), "200")); str.clear(); - RenderFrame(&str, "%L", frame_no, info.address, &info, false); + printer.RenderFrame(&str, "%L", frame_no, info.address, &info, false); EXPECT_STREQ("(/path/to/module+0x200)", str.data()); str.clear(); - RenderFrame(&str, "%b", frame_no, info.address, &info, false); + printer.RenderFrame(&str, "%b", frame_no, info.address, &info, false); EXPECT_STREQ("", str.data()); str.clear(); @@ -134,7 +146,7 @@ TEST(SanitizerStacktracePrinter, RenderFrame) { info.uuid[0] = 0x55; info.uuid[1] = 0x66; - RenderFrame(&str, "%M", frame_no, info.address, &info, false); + printer.RenderFrame(&str, "%M", frame_no, info.address, &info, false); EXPECT_NE(nullptr, internal_strstr(str.data(), "(module+0x")); EXPECT_NE(nullptr, internal_strstr(str.data(), "200")); #if SANITIZER_APPLE @@ -144,7 +156,7 @@ TEST(SanitizerStacktracePrinter, RenderFrame) { #endif str.clear(); - RenderFrame(&str, "%L", frame_no, info.address, &info, false); + printer.RenderFrame(&str, "%L", frame_no, info.address, &info, false); #if SANITIZER_APPLE EXPECT_STREQ("(/path/to/module+0x200)", str.data()); #else @@ -152,46 +164,46 @@ TEST(SanitizerStacktracePrinter, RenderFrame) { #endif str.clear(); - RenderFrame(&str, "%b", frame_no, info.address, &info, false); + printer.RenderFrame(&str, "%b", frame_no, info.address, &info, false); EXPECT_STREQ("(BuildId: 5566)", str.data()); str.clear(); info.function = internal_strdup("my_function"); - RenderFrame(&str, "%F", frame_no, info.address, &info, false); + printer.RenderFrame(&str, "%F", frame_no, info.address, &info, false); EXPECT_STREQ("in my_function", str.data()); str.clear(); info.function_offset = 0x100; - RenderFrame(&str, "%F %S", frame_no, info.address, &info, false); + printer.RenderFrame(&str, "%F %S", frame_no, info.address, &info, false); EXPECT_STREQ("in my_function+0x100 ", str.data()); str.clear(); info.file = internal_strdup("my_file"); - RenderFrame(&str, "%F %S", frame_no, info.address, &info, false); + printer.RenderFrame(&str, "%F %S", frame_no, info.address, &info, false); EXPECT_STREQ("in my_function my_file", str.data()); str.clear(); info.line = 10; - RenderFrame(&str, "%F %S", frame_no, info.address, &info, false); + printer.RenderFrame(&str, "%F %S", frame_no, info.address, &info, false); EXPECT_STREQ("in my_function my_file:10", str.data()); str.clear(); info.column = 5; - RenderFrame(&str, "%S %L", frame_no, info.address, &info, false); + printer.RenderFrame(&str, "%S %L", frame_no, info.address, &info, false); EXPECT_STREQ("my_file:10:5 my_file:10:5", str.data()); str.clear(); - RenderFrame(&str, "%S %L", frame_no, info.address, &info, true); + printer.RenderFrame(&str, "%S %L", frame_no, info.address, &info, true); EXPECT_STREQ("my_file(10,5) my_file(10,5)", str.data()); str.clear(); info.column = 0; - RenderFrame(&str, "%F %S", frame_no, info.address, &info, true); + printer.RenderFrame(&str, "%F %S", frame_no, info.address, &info, true); EXPECT_STREQ("in my_function my_file(10)", str.data()); str.clear(); info.line = 0; - RenderFrame(&str, "%F %S", frame_no, info.address, &info, true); + printer.RenderFrame(&str, "%F %S", frame_no, info.address, &info, true); EXPECT_STREQ("in my_function my_file", str.data()); str.clear(); diff --git a/compiler-rt/lib/tsan/rtl/tsan_report.cpp b/compiler-rt/lib/tsan/rtl/tsan_report.cpp index 3ae666e1212f7..4028d18107840 100644 --- a/compiler-rt/lib/tsan/rtl/tsan_report.cpp +++ b/compiler-rt/lib/tsan/rtl/tsan_report.cpp @@ -106,10 +106,10 @@ void PrintStack(const ReportStack *ent) { SymbolizedStack *frame = ent->frames; for (int i = 0; frame && frame->info.address; frame = frame->next, i++) { InternalScopedString res; - RenderFrame(&res, common_flags()->stack_trace_format, i, - frame->info.address, &frame->info, - common_flags()->symbolize_vs_style, - common_flags()->strip_path_prefix); + StackTracePrinter::GetOrInit()->RenderFrame( + &res, common_flags()->stack_trace_format, i, frame->info.address, + &frame->info, common_flags()->symbolize_vs_style, + common_flags()->strip_path_prefix); Printf("%s\n", res.data()); } Printf("\n"); diff --git a/compiler-rt/lib/ubsan/ubsan_diag.cpp b/compiler-rt/lib/ubsan/ubsan_diag.cpp index dd99613abbe3f..d86b70350c18a 100644 --- a/compiler-rt/lib/ubsan/ubsan_diag.cpp +++ b/compiler-rt/lib/ubsan/ubsan_diag.cpp @@ -149,9 +149,10 @@ static void RenderLocation(InternalScopedString *Buffer, Location Loc) { if (SLoc.isInvalid()) Buffer->append(""); else - RenderSourceLocation(Buffer, SLoc.getFilename(), SLoc.getLine(), - SLoc.getColumn(), common_flags()->symbolize_vs_style, - common_flags()->strip_path_prefix); + StackTracePrinter::GetOrInit()->RenderSourceLocation( + Buffer, SLoc.getFilename(), SLoc.getLine(), SLoc.getColumn(), + common_flags()->symbolize_vs_style, + common_flags()->strip_path_prefix); return; } case Location::LK_Memory: @@ -160,12 +161,14 @@ static void RenderLocation(InternalScopedString *Buffer, Location Loc) { case Location::LK_Symbolized: { const AddressInfo &Info = Loc.getSymbolizedStack()->info; if (Info.file) - RenderSourceLocation(Buffer, Info.file, Info.line, Info.column, - common_flags()->symbolize_vs_style, - common_flags()->strip_path_prefix); + StackTracePrinter::GetOrInit()->RenderSourceLocation( + Buffer, Info.file, Info.line, Info.column, + common_flags()->symbolize_vs_style, + common_flags()->strip_path_prefix); else if (Info.module) - RenderModuleLocation(Buffer, Info.module, Info.module_offset, - Info.module_arch, common_flags()->strip_path_prefix); + StackTracePrinter::GetOrInit()->RenderModuleLocation( + Buffer, Info.module, Info.module_offset, Info.module_arch, + common_flags()->strip_path_prefix); else Buffer->append("%p", reinterpret_cast(Info.address)); return;