Original file line number Diff line number Diff line change
Expand Up @@ -16,57 +16,68 @@

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;
Expand All @@ -80,11 +91,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",
Expand All @@ -93,11 +104,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",
Expand All @@ -107,34 +118,34 @@ 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("(<unknown module>)", 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();

info.uuid_size = 2;
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
Expand All @@ -144,54 +155,54 @@ 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
EXPECT_STREQ("(/path/to/module+0x200) (BuildId: 5566)", str.data());
#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 <null>", 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();

Expand Down
8 changes: 4 additions & 4 deletions compiler-rt/lib/tsan/rtl/tsan_report.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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");
Expand Down
19 changes: 11 additions & 8 deletions compiler-rt/lib/ubsan/ubsan_diag.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -149,9 +149,10 @@ static void RenderLocation(InternalScopedString *Buffer, Location Loc) {
if (SLoc.isInvalid())
Buffer->AppendF("<unknown>");
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:
Expand All @@ -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->AppendF("%p", reinterpret_cast<void *>(Info.address));
return;
Expand Down