Index: lib/sanitizer_common/sanitizer_common.cc =================================================================== --- lib/sanitizer_common/sanitizer_common.cc +++ lib/sanitizer_common/sanitizer_common.cc @@ -243,7 +243,8 @@ return; InternalScopedString buff(kMaxSummaryLength); buff.append("%s ", error_type); - RenderFrame(&buff, "%L %F", 0, info, common_flags()->strip_path_prefix); + RenderFrame(&buff, "%L %F", 0, info, common_flags()->symbolize_vs_style, + common_flags()->strip_path_prefix); ReportErrorSummary(buff.data()); } #endif Index: lib/sanitizer_common/sanitizer_flags.inc =================================================================== --- lib/sanitizer_common/sanitizer_flags.inc +++ lib/sanitizer_common/sanitizer_flags.inc @@ -146,6 +146,9 @@ "in core file.") COMMON_FLAG(bool, symbolize_inline_frames, true, "Print inlined frames in stacktraces. Defaults to true.") +COMMON_FLAG(bool, symbolize_vs_style, false, + "Print file locations in Visual Studio style (e.g: " + " file(10,42): ...") COMMON_FLAG(const char *, stack_trace_format, "DEFAULT", "Format string used to render stack frames. " "See sanitizer_stacktrace_printer.h for the format description. " Index: lib/sanitizer_common/sanitizer_stacktrace_libcdep.cc =================================================================== --- lib/sanitizer_common/sanitizer_stacktrace_libcdep.cc +++ lib/sanitizer_common/sanitizer_stacktrace_libcdep.cc @@ -35,7 +35,8 @@ for (SymbolizedStack *cur = frames; cur; cur = cur->next) { frame_desc.clear(); RenderFrame(&frame_desc, common_flags()->stack_trace_format, frame_num++, - cur->info, common_flags()->strip_path_prefix); + cur->info, common_flags()->symbolize_vs_style, + common_flags()->strip_path_prefix); Printf("%s\n", frame_desc.data()); } frames->ClearAll(); Index: lib/sanitizer_common/sanitizer_stacktrace_printer.h =================================================================== --- lib/sanitizer_common/sanitizer_stacktrace_printer.h +++ lib/sanitizer_common/sanitizer_stacktrace_printer.h @@ -48,11 +48,13 @@ // 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, - const AddressInfo &info, const char *strip_path_prefix = "", + const AddressInfo &info, bool vs_style, + const char *strip_path_prefix = "", const char *strip_func_prefix = ""); void RenderSourceLocation(InternalScopedString *buffer, const char *file, - int line, int column, const char *strip_path_prefix); + int line, int column, const char *strip_path_prefix, + bool vs_style); void RenderModuleLocation(InternalScopedString *buffer, const char *module, uptr offset, const char *strip_path_prefix); Index: lib/sanitizer_common/sanitizer_stacktrace_printer.cc =================================================================== --- lib/sanitizer_common/sanitizer_stacktrace_printer.cc +++ lib/sanitizer_common/sanitizer_stacktrace_printer.cc @@ -26,8 +26,8 @@ static const char kDefaultFormat[] = " #%n %p %F %L"; void RenderFrame(InternalScopedString *buffer, const char *format, int frame_no, - const AddressInfo &info, const char *strip_path_prefix, - const char *strip_func_prefix) { + const AddressInfo &info, bool vs_style, + const char *strip_path_prefix, const char *strip_func_prefix) { if (0 == internal_strcmp(format, "DEFAULT")) format = kDefaultFormat; for (const char *p = format; *p != '\0'; p++) { @@ -82,14 +82,14 @@ break; case 'S': // File/line information. - RenderSourceLocation(buffer, info.file, info.line, info.column, + RenderSourceLocation(buffer, info.file, info.line, info.column, vs_style, strip_path_prefix); break; case 'L': // Source location, or module location. if (info.file) { RenderSourceLocation(buffer, info.file, info.line, info.column, - strip_path_prefix); + vs_style, strip_path_prefix); } else if (info.module) { RenderModuleLocation(buffer, info.module, info.module_offset, strip_path_prefix); @@ -106,15 +106,24 @@ buffer->append("(%p)", (void *)info.address); break; default: - Report("Unsupported specifier in stack frame format: %c (0x%zx)!\n", - *p, *p); + Report("Unsupported specifier in stack frame format: %c (0x%zx)!\n", *p, + *p); Die(); } } } void RenderSourceLocation(InternalScopedString *buffer, const char *file, - int line, int column, const char *strip_path_prefix) { + 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) + buffer->append(",%d", column); + buffer->append(")"); + return; + } + buffer->append("%s", StripPathPrefix(file, strip_path_prefix)); if (line > 0) { buffer->append(":%d", line); Index: lib/sanitizer_common/tests/sanitizer_stacktrace_printer_test.cc =================================================================== --- lib/sanitizer_common/tests/sanitizer_stacktrace_printer_test.cc +++ lib/sanitizer_common/tests/sanitizer_stacktrace_printer_test.cc @@ -18,20 +18,36 @@ TEST(SanitizerStacktracePrinter, RenderSourceLocation) { InternalScopedString str(128); - RenderSourceLocation(&str, "/dir/file.cc", 10, 5, ""); + 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, ""); + 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, ""); + RenderSourceLocation(&str, "/dir/file.cc", 0, 0, false, ""); EXPECT_STREQ("/dir/file.cc", str.data()); str.clear(); - RenderSourceLocation(&str, "/dir/file.cc", 10, 5, "/dir/"); + 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, ""); + EXPECT_STREQ("/dir/file.cc(10:5)", str.data()); + + str.clear(); + 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, ""); + EXPECT_STREQ("/dir/file.cc", str.data()); + + str.clear(); + RenderSourceLocation(&str, "/dir/file.cc", 10, 5, true, "/dir/"); + EXPECT_STREQ("file.cc(10,5)", str.data()); } TEST(SanitizerStacktracePrinter, RenderModuleLocation) { @@ -62,7 +78,7 @@ 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_"); + frame_no, info, false, "/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", @@ -72,50 +88,59 @@ // Test special format specifiers. info.address = 0x400000; - RenderFrame(&str, "%M", frame_no, info); + RenderFrame(&str, "%M", frame_no, info, false); EXPECT_NE(nullptr, internal_strstr(str.data(), "400000")); str.clear(); - RenderFrame(&str, "%L", frame_no, info); + RenderFrame(&str, "%L", frame_no, 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); + RenderFrame(&str, "%M", frame_no, 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); + RenderFrame(&str, "%L", frame_no, info, false); EXPECT_STREQ("(/path/to/module+0x200)", str.data()); str.clear(); info.function = internal_strdup("my_function"); - RenderFrame(&str, "%F", frame_no, info); + RenderFrame(&str, "%F", frame_no, info, false); EXPECT_STREQ("in my_function", str.data()); str.clear(); info.function_offset = 0x100; - RenderFrame(&str, "%F %S", frame_no, info); + RenderFrame(&str, "%F %S", frame_no, 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); + RenderFrame(&str, "%F %S", frame_no, info, false); EXPECT_STREQ("in my_function my_file", str.data()); str.clear(); info.line = 10; - RenderFrame(&str, "%F %S", frame_no, info); + RenderFrame(&str, "%F %S", frame_no, info, false); + EXPECT_STREQ("in my_function my_file:10", str.data()); + str.clear(); + + // Make sure we don't print VS-style if we have no column info + RenderFrame(&str, "%F %S", frame_no, info, true); EXPECT_STREQ("in my_function my_file:10", str.data()); str.clear(); info.column = 5; - RenderFrame(&str, "%S %L", frame_no, info); + RenderFrame(&str, "%S %L", frame_no, info, false); EXPECT_STREQ("my_file:10:5 my_file:10:5", str.data()); str.clear(); + RenderFrame(&str, "%S %L", frame_no, info, true); + EXPECT_STREQ("my_file(10,5) my_file(10,5)", str.data()); + str.clear(); + info.Clear(); } Index: lib/tsan/rtl/tsan_report.cc =================================================================== --- lib/tsan/rtl/tsan_report.cc +++ lib/tsan/rtl/tsan_report.cc @@ -120,6 +120,7 @@ for (int i = 0; frame && frame->info.address; frame = frame->next, i++) { InternalScopedString res(2 * GetPageSizeCached()); RenderFrame(&res, common_flags()->stack_trace_format, i, frame->info, + common_flags()->symbolize_vs_style, common_flags()->strip_path_prefix, "__interceptor_"); Printf("%s\n", res.data()); } Index: lib/ubsan/ubsan_diag.cc =================================================================== --- lib/ubsan/ubsan_diag.cc +++ lib/ubsan/ubsan_diag.cc @@ -121,7 +121,8 @@ LocBuffer.append(""); else RenderSourceLocation(&LocBuffer, SLoc.getFilename(), SLoc.getLine(), - SLoc.getColumn(), common_flags()->strip_path_prefix); + SLoc.getColumn(), common_flags()->symbolize_vs_style, + common_flags()->strip_path_prefix); break; } case Location::LK_Memory: @@ -131,6 +132,7 @@ const AddressInfo &Info = Loc.getSymbolizedStack()->info; if (Info.file) { RenderSourceLocation(&LocBuffer, Info.file, Info.line, Info.column, + common_flags()->symbolize_vs_style, common_flags()->strip_path_prefix); } else if (Info.module) { RenderModuleLocation(&LocBuffer, Info.module, Info.module_offset,