forked from OSchip/llvm-project
[sanitizer] Fall back to fast unwinder
`-fno-exceptions -fno-asynchronous-unwind-tables` compiled programs don't produce .eh_frame on Linux and other ELF platforms, so the slow unwinder cannot print stack traces. Just fall back to the fast unwinder: this allows -fno-asynchronous-unwind-tables without requiring the sanitizer option `fast_unwind_on_fatal=1` Reviewed By: #sanitizers, vitalybuka Differential Revision: https://reviews.llvm.org/D102046
This commit is contained in:
parent
4901199f5b
commit
fa27255d16
|
@ -82,12 +82,15 @@ void BufferedStackTrace::Unwind(u32 max_depth, uptr pc, uptr bp, void *context,
|
|||
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,
|
||||
|
|
|
@ -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 <sanitizer/common_interface_defs.h>
|
||||
#include <vector>
|
||||
|
||||
template <int N>
|
||||
struct A {
|
||||
template <class T>
|
||||
void RecursiveTemplateFunction(const T &t);
|
||||
};
|
||||
|
||||
template <int N>
|
||||
template <class T>
|
||||
__attribute__((noinline)) void A<N>::RecursiveTemplateFunction(const T &) {
|
||||
std::vector<T> t;
|
||||
return A<N - 1>().RecursiveTemplateFunction(t);
|
||||
}
|
||||
|
||||
template <>
|
||||
template <class T>
|
||||
__attribute__((noinline)) void A<0>::RecursiveTemplateFunction(const T &) {
|
||||
__sanitizer_print_stack_trace();
|
||||
}
|
||||
|
||||
int main() {
|
||||
// CHECK: {{vector<.*vector<.*vector<.*vector<.*vector<}}
|
||||
A<10>().RecursiveTemplateFunction(0);
|
||||
}
|
Loading…
Reference in New Issue