diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_stacktrace_libcdep.cpp b/compiler-rt/lib/sanitizer_common/sanitizer_stacktrace_libcdep.cpp --- a/compiler-rt/lib/sanitizer_common/sanitizer_stacktrace_libcdep.cpp +++ b/compiler-rt/lib/sanitizer_common/sanitizer_stacktrace_libcdep.cpp @@ -82,12 +82,15 @@ UnwindSlow(pc, context, max_depth); else UnwindSlow(pc, max_depth); + // If there are too few frames, the program may be built with + // -fno-asynchronous-unwind-tables. Fall back to fast unwinder below. + if (size > 2) + return; #else UNREACHABLE("slow unwind requested but not available"); #endif - } else { - UnwindFast(pc, bp, stack_top, stack_bottom, max_depth); } + UnwindFast(pc, bp, stack_top, stack_bottom, max_depth); } static int GetModuleAndOffsetForPc(uptr pc, char *module_name, diff --git a/compiler-rt/test/sanitizer_common/TestCases/Linux/symbolize_stack_fp.cpp b/compiler-rt/test/sanitizer_common/TestCases/Linux/symbolize_stack_fp.cpp new file mode 100644 --- /dev/null +++ b/compiler-rt/test/sanitizer_common/TestCases/Linux/symbolize_stack_fp.cpp @@ -0,0 +1,35 @@ +/// When the main program doesn't use .eh_frame, the slow unwinder does not work. +/// Test that we can fall back to the fast unwinder. +// RUN: %clangxx -O0 -g1 -fno-exceptions -fno-unwind-tables -fno-asynchronous-unwind-tables -fno-omit-frame-pointer -mno-omit-leaf-frame-pointer %s -o %t +// RUN: llvm-readelf -S %t | FileCheck %s --check-prefix=SEC +// RUN: %run %t 2>&1 | FileCheck %s + +/// No .eh_frame && -g => .debug_frame +// SEC: .debug_frame + +#include +#include + +template +struct A { + template + void RecursiveTemplateFunction(const T &t); +}; + +template +template +__attribute__((noinline)) void A::RecursiveTemplateFunction(const T &) { + std::vector t; + return A().RecursiveTemplateFunction(t); +} + +template <> +template +__attribute__((noinline)) void A<0>::RecursiveTemplateFunction(const T &) { + __sanitizer_print_stack_trace(); +} + +int main() { + // CHECK: {{vector<.*vector<.*vector<.*vector<.*vector<}} + A<10>().RecursiveTemplateFunction(0); +}