summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/sanitizer_common/sanitizer_flags.cc5
-rw-r--r--lib/sanitizer_common/sanitizer_flags.h1
-rw-r--r--lib/sanitizer_common/sanitizer_stacktrace_libcdep.cc4
-rw-r--r--lib/tsan/rtl/tsan_flags.cc1
-rw-r--r--lib/tsan/rtl/tsan_report.cc4
-rw-r--r--lib/tsan/rtl/tsan_rtl.h2
-rw-r--r--lib/tsan/rtl/tsan_rtl_report.cc15
-rw-r--r--test/sanitizer_common/TestCases/print-stack-trace.cc20
8 files changed, 34 insertions, 18 deletions
diff --git a/lib/sanitizer_common/sanitizer_flags.cc b/lib/sanitizer_common/sanitizer_flags.cc
index 55644e0d6..40b6ec067 100644
--- a/lib/sanitizer_common/sanitizer_flags.cc
+++ b/lib/sanitizer_common/sanitizer_flags.cc
@@ -68,6 +68,7 @@ void SetCommonFlagsDefaults(CommonFlags *f) {
f->print_suppressions = true;
f->disable_coredump = (SANITIZER_WORDSIZE == 64);
f->symbolize_inline_frames = true;
+ f->stack_trace_format = "DEFAULT";
}
void ParseCommonFlagsFromString(CommonFlags *f, const char *str) {
@@ -161,6 +162,10 @@ void ParseCommonFlagsFromString(CommonFlags *f, const char *str) {
"default and for sanitizers that don't reserve lots of virtual memory.");
ParseFlag(str, &f->symbolize_inline_frames, "symbolize_inline_frames",
"Print inlined frames in stacktraces. Defaults to true.");
+ ParseFlag(str, &f->stack_trace_format, "stack_trace_format",
+ "Format string used to render stack frames. "
+ "See sanitizer_stacktrace_printer.h for the format description. "
+ "Use DEFAULT to get default format.");
// Do a sanity check for certain flags.
if (f->malloc_context_size < 1)
diff --git a/lib/sanitizer_common/sanitizer_flags.h b/lib/sanitizer_common/sanitizer_flags.h
index 6d1d9b60b..4791397a5 100644
--- a/lib/sanitizer_common/sanitizer_flags.h
+++ b/lib/sanitizer_common/sanitizer_flags.h
@@ -62,6 +62,7 @@ struct CommonFlags {
bool print_suppressions;
bool disable_coredump;
bool symbolize_inline_frames;
+ const char *stack_trace_format;
};
inline CommonFlags *common_flags() {
diff --git a/lib/sanitizer_common/sanitizer_stacktrace_libcdep.cc b/lib/sanitizer_common/sanitizer_stacktrace_libcdep.cc
index 2c37ebc81..13fb01f92 100644
--- a/lib/sanitizer_common/sanitizer_stacktrace_libcdep.cc
+++ b/lib/sanitizer_common/sanitizer_stacktrace_libcdep.cc
@@ -43,8 +43,8 @@ void StackTrace::Print() const {
for (uptr j = 0; j < addr_frames_num; j++) {
AddressInfo &info = addr_frames[j];
frame_desc.clear();
- RenderFrame(&frame_desc, "DEFAULT", frame_num++, info,
- common_flags()->strip_path_prefix);
+ RenderFrame(&frame_desc, common_flags()->stack_trace_format, frame_num++,
+ info, common_flags()->strip_path_prefix);
Printf("%s\n", frame_desc.data());
info.Clear();
}
diff --git a/lib/tsan/rtl/tsan_flags.cc b/lib/tsan/rtl/tsan_flags.cc
index 92b312cb2..5dc331f59 100644
--- a/lib/tsan/rtl/tsan_flags.cc
+++ b/lib/tsan/rtl/tsan_flags.cc
@@ -99,6 +99,7 @@ void InitializeFlags(Flags *f, const char *env) {
cf->allow_addr2line = true;
cf->detect_deadlocks = true;
cf->print_suppressions = false;
+ cf->stack_trace_format = " #%n %f %S %M";
// Let a frontend override.
ParseFlags(f, __tsan_default_options());
diff --git a/lib/tsan/rtl/tsan_report.cc b/lib/tsan/rtl/tsan_report.cc
index 1503a0489..f4a1ddb69 100644
--- a/lib/tsan/rtl/tsan_report.cc
+++ b/lib/tsan/rtl/tsan_report.cc
@@ -118,9 +118,9 @@ void PrintStack(const ReportStack *ent) {
Printf(" [failed to restore the stack]\n\n");
return;
}
- for (int i = 0; ent; ent = ent->next, i++) {
+ for (int i = 0; ent && ent->info.address; ent = ent->next, i++) {
InternalScopedString res(2 * GetPageSizeCached());
- RenderFrame(&res, " #%n %f %S %M", i, ent->info,
+ RenderFrame(&res, common_flags()->stack_trace_format, i, ent->info,
common_flags()->strip_path_prefix, "__interceptor_");
Printf("%s\n", res.data());
}
diff --git a/lib/tsan/rtl/tsan_rtl.h b/lib/tsan/rtl/tsan_rtl.h
index 3ace2f560..3d483bc4b 100644
--- a/lib/tsan/rtl/tsan_rtl.h
+++ b/lib/tsan/rtl/tsan_rtl.h
@@ -586,7 +586,7 @@ ReportStack *SkipTsanInternalFrames(ReportStack *ent);
u32 CurrentStackId(ThreadState *thr, uptr pc);
ReportStack *SymbolizeStackId(u32 stack_id);
void PrintCurrentStack(ThreadState *thr, uptr pc);
-void PrintCurrentStackSlow(); // uses libunwind
+void PrintCurrentStackSlow(uptr pc); // uses libunwind
void Initialize(ThreadState *thr);
int Finalize(ThreadState *thr);
diff --git a/lib/tsan/rtl/tsan_rtl_report.cc b/lib/tsan/rtl/tsan_rtl_report.cc
index 00be37164..c7a00c906 100644
--- a/lib/tsan/rtl/tsan_rtl_report.cc
+++ b/lib/tsan/rtl/tsan_rtl_report.cc
@@ -41,7 +41,7 @@ void TsanCheckFailed(const char *file, int line, const char *cond,
Printf("FATAL: ThreadSanitizer CHECK failed: "
"%s:%d \"%s\" (0x%zx, 0x%zx)\n",
file, line, cond, (uptr)v1, (uptr)v2);
- PrintCurrentStackSlow();
+ PrintCurrentStackSlow(StackTrace::GetCurrentPc());
Die();
}
@@ -668,12 +668,12 @@ void PrintCurrentStack(ThreadState *thr, uptr pc) {
PrintStack(SymbolizeStack(trace));
}
-void PrintCurrentStackSlow() {
+void PrintCurrentStackSlow(uptr pc) {
#ifndef TSAN_GO
BufferedStackTrace *ptrace =
new(internal_alloc(MBlockStackTrace, sizeof(BufferedStackTrace)))
BufferedStackTrace();
- ptrace->Unwind(kStackTraceMax, StackTrace::GetCurrentPc(), 0, 0, 0, 0, false);
+ ptrace->Unwind(kStackTraceMax, pc, 0, 0, 0, 0, false);
for (uptr i = 0; i < ptrace->size / 2; i++) {
uptr tmp = ptrace->trace_buffer[i];
ptrace->trace_buffer[i] = ptrace->trace_buffer[ptrace->size - i - 1];
@@ -684,3 +684,12 @@ void PrintCurrentStackSlow() {
}
} // namespace __tsan
+
+using namespace __tsan;
+
+extern "C" {
+SANITIZER_INTERFACE_ATTRIBUTE
+void __sanitizer_print_stack_trace() {
+ PrintCurrentStackSlow(StackTrace::GetCurrentPc());
+}
+} // extern "C"
diff --git a/test/sanitizer_common/TestCases/print-stack-trace.cc b/test/sanitizer_common/TestCases/print-stack-trace.cc
index a842ca65d..1251f67b8 100644
--- a/test/sanitizer_common/TestCases/print-stack-trace.cc
+++ b/test/sanitizer_common/TestCases/print-stack-trace.cc
@@ -1,10 +1,7 @@
-// RUN: %clangxx -O0 %s -o %t && %run %t 2>&1 | FileCheck %s
-// RUN: %clangxx -O3 %s -o %t && %run %t 2>&1 | FileCheck %s
-// RUN: %tool_options=symbolize_inline_frames=false %run %t 2>&1 | FileCheck %s --check-prefix=NOINLINE
-
-// Not yet implemented for TSan.
-// https://code.google.com/p/address-sanitizer/issues/detail?id=243
-// XFAIL: tsan
+// RUN: %clangxx -O0 %s -o %t && %tool_options=stack_trace_format=DEFAULT %run %t 2>&1 | FileCheck %s
+// RUN: %clangxx -O3 %s -o %t && %tool_options=stack_trace_format=DEFAULT %run %t 2>&1 | FileCheck %s
+// RUN: %tool_options='stack_trace_format="frame:%n lineno:%l"' %run %t 2>&1 | FileCheck %s --check-prefix=CUSTOM
+// RUN: %tool_options=symbolize_inline_frames=false:stack_trace_format=DEFAULT %run %t 2>&1 | FileCheck %s --check-prefix=NOINLINE
#include <sanitizer/common_interface_defs.h>
@@ -17,8 +14,11 @@ int main() {
return 0;
}
// CHECK: {{ #0 0x.* in __sanitizer_print_stack_trace}}
-// CHECK: {{ #1 0x.* in FooBarBaz(\(\))? .*print-stack-trace.cc:12}}
-// CHECK: {{ #2 0x.* in main.*print-stack-trace.cc:16}}
+// CHECK: {{ #1 0x.* in FooBarBaz(\(\))? .*print-stack-trace.cc:9}}
+// CHECK: {{ #2 0x.* in main.*print-stack-trace.cc:13}}
+
+// CUSTOM: frame:1 lineno:9
+// CUSTOM: frame:2 lineno:13
// NOINLINE: #0 0x{{.*}} in __sanitizer_print_stack_trace
-// NOINLINE: #1 0x{{.*}} in main{{.*}}print-stack-trace.cc:12
+// NOINLINE: #1 0x{{.*}} in main{{.*}}print-stack-trace.cc:9