Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
//===-- sanitizer_common_printer_test.cc ----------------------------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file is a part of sanitizer_common test suite.
//
//===----------------------------------------------------------------------===//
#include "sanitizer_common/sanitizer_stacktrace_printer.h"

#include "gtest/gtest.h"

namespace __sanitizer {

TEST(SanitizerStacktracePrinter, RenderSourceLocation) {
InternalScopedString str(128);
RenderSourceLocation(&str, "/dir/file.cc", 10, 5, "");
EXPECT_STREQ("/dir/file.cc:10:5", str.data());

str.clear();
RenderSourceLocation(&str, "/dir/file.cc", 11, 0, "");
EXPECT_STREQ("/dir/file.cc:11", str.data());

str.clear();
RenderSourceLocation(&str, "/dir/file.cc", 0, 0, "");
EXPECT_STREQ("/dir/file.cc", str.data());

str.clear();
RenderSourceLocation(&str, "/dir/file.cc", 10, 5, "/dir/");
EXPECT_STREQ("file.cc:10:5", str.data());
}

TEST(SanitizerStacktracePrinter, RenderModuleLocation) {
InternalScopedString str(128);
RenderModuleLocation(&str, "/dir/exe", 0x123, "");
EXPECT_STREQ("(/dir/exe+0x123)", str.data());

// Check that we strip file prefix if necessary.
str.clear();
RenderModuleLocation(&str, "/dir/exe", 0x123, "/dir/");
EXPECT_STREQ("(exe+0x123)", str.data());
}

TEST(SanitizerStacktracePrinter, RenderFrame) {
int frame_no = 42;
AddressInfo info;
info.address = 0x400000;
info.module = internal_strdup("/path/to/my/module");
info.module_offset = 0x200;
info.function = internal_strdup("function_foo");
info.function_offset = 0x100;
info.file = internal_strdup("/path/to/my/source");
info.line = 10;
info.column = 5;
InternalScopedString str(256);

// 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, "/path/to/", "function_");
EXPECT_STREQ("% Frame:42 PC:0x400000 Module:my/module ModuleOffset:0x200 "
"Function:foo FunctionOffset:0x100 Source:my/source Line:10 "
"Column:5",
str.data());
info.Clear();
str.clear();

// Test special format specifiers.
info.address = 0x400000;
RenderFrame(&str, "%M", frame_no, info);
EXPECT_NE(nullptr, internal_strstr(str.data(), "400000"));
str.clear();

RenderFrame(&str, "%L", frame_no, info);
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);
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);
EXPECT_STREQ("(/path/to/module+0x200)", str.data());
str.clear();

info.function = internal_strdup("my_function");
RenderFrame(&str, "%F", frame_no, info);
EXPECT_STREQ("in my_function", str.data());
str.clear();

info.function_offset = 0x100;
RenderFrame(&str, "%F %S", frame_no, info);
EXPECT_STREQ("in my_function+0x100 <null>", str.data());
str.clear();

info.file = internal_strdup("my_file");
RenderFrame(&str, "%F %S", frame_no, info);
EXPECT_STREQ("in my_function my_file", str.data());
str.clear();

info.line = 10;
RenderFrame(&str, "%F %S", frame_no, info);
EXPECT_STREQ("in my_function my_file:10", str.data());
str.clear();

info.column = 5;
RenderFrame(&str, "%S %L", frame_no, info);
EXPECT_STREQ("my_file:10:5 my_file:10:5", str.data());
str.clear();

info.Clear();
}

} // namespace __sanitizer
27 changes: 5 additions & 22 deletions compiler-rt/lib/tsan/rtl/tsan_report.cc
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
#include "tsan_rtl.h"
#include "sanitizer_common/sanitizer_placement_new.h"
#include "sanitizer_common/sanitizer_report_decorator.h"
#include "sanitizer_common/sanitizer_stacktrace_printer.h"

namespace __tsan {

Expand Down Expand Up @@ -112,34 +113,16 @@ static const char *ReportTypeString(ReportType typ) {
return "";
}

static const char *StripFunctionName(const char *function, const char *prefix) {
if (function == 0) return 0;
if (prefix == 0) return function;
uptr prefix_len = internal_strlen(prefix);
if (0 == internal_strncmp(function, prefix, prefix_len))
return function + prefix_len;
return function;
}

void PrintStack(const ReportStack *ent) {
if (ent == 0) {
Printf(" [failed to restore the stack]\n\n");
return;
}
for (int i = 0; ent; ent = ent->next, i++) {
const AddressInfo &info = ent->info;
Printf(" #%d %s %s:%d", i,
StripFunctionName(info.function, "__interceptor_"),
StripPathPrefix(info.file, common_flags()->strip_path_prefix),
info.line);
if (info.column)
Printf(":%d", info.column);
if (info.module && info.module_offset) {
Printf(" (%s+%p)\n", StripModuleName(info.module),
(void *)info.module_offset);
} else {
Printf(" (%p)\n", (void *)info.address);
}
InternalScopedString res(2 * GetPageSizeCached());
RenderFrame(&res, " #%n %f %S %M", i, ent->info,
common_flags()->strip_path_prefix, "__interceptor_");
Printf("%s\n", res.data());
}
Printf("\n");
}
Expand Down
13 changes: 8 additions & 5 deletions compiler-rt/lib/ubsan/ubsan_diag.cc
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
#include "ubsan_flags.h"
#include "sanitizer_common/sanitizer_report_decorator.h"
#include "sanitizer_common/sanitizer_stacktrace.h"
#include "sanitizer_common/sanitizer_stacktrace_printer.h"
#include "sanitizer_common/sanitizer_symbolizer.h"
#include <stdio.h>

Expand Down Expand Up @@ -129,14 +130,16 @@ static void renderLocation(Location Loc) {
if (SLoc.isInvalid())
LocBuffer.append("<unknown>");
else
PrintSourceLocation(&LocBuffer, SLoc.getFilename(), SLoc.getLine(),
SLoc.getColumn());
RenderSourceLocation(&LocBuffer, SLoc.getFilename(), SLoc.getLine(),
SLoc.getColumn(), common_flags()->strip_path_prefix);
break;
}
case Location::LK_Module:
PrintModuleAndOffset(&LocBuffer, Loc.getModuleLocation().getModuleName(),
Loc.getModuleLocation().getOffset());
case Location::LK_Module: {
ModuleLocation MLoc = Loc.getModuleLocation();
RenderModuleLocation(&LocBuffer, MLoc.getModuleName(), MLoc.getOffset(),
common_flags()->strip_path_prefix);
break;
}
case Location::LK_Memory:
LocBuffer.append("%p", Loc.getMemoryLocation());
break;
Expand Down