Unwinding out of signal handlers currently does not work since the sigreturn trampoline is not annotated with CFI data. Fix this by detecting the sigreturn trampoline during unwinding and providing appropriate unwind data manually. This follows closely the approach used by existing code for the AArch64 target. Reviewed by: MaskRay Differential Revision: https://reviews.llvm.org/D124765
59 lines
1.7 KiB
C++
59 lines
1.7 KiB
C++
// -*- C++ -*-
|
|
//===----------------------------------------------------------------------===//
|
|
//
|
|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
|
// See https://llvm.org/LICENSE.txt for license information.
|
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// Ensure that leaf function can be unwund.
|
|
// REQUIRES: linux && (target={{aarch64-.+}} || target={{s390x-.+}} || target={{x86_64-.+}})
|
|
|
|
// TODO: Figure out why this fails with Memory Sanitizer.
|
|
// XFAIL: msan
|
|
|
|
#include <assert.h>
|
|
#include <dlfcn.h>
|
|
#include <signal.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <sys/types.h>
|
|
#include <unistd.h>
|
|
#include <unwind.h>
|
|
|
|
_Unwind_Reason_Code frame_handler(struct _Unwind_Context* ctx, void* arg) {
|
|
(void)arg;
|
|
Dl_info info = { 0, 0, 0, 0 };
|
|
|
|
// Unwind util the main is reached, above frames deeped on the platfrom and architecture.
|
|
if (dladdr(reinterpret_cast<void *>(_Unwind_GetIP(ctx)), &info) &&
|
|
info.dli_sname && !strcmp("main", info.dli_sname)) {
|
|
_Exit(0);
|
|
}
|
|
return _URC_NO_REASON;
|
|
}
|
|
|
|
void signal_handler(int signum) {
|
|
(void)signum;
|
|
_Unwind_Backtrace(frame_handler, NULL);
|
|
_Exit(-1);
|
|
}
|
|
|
|
__attribute__((noinline)) void crashing_leaf_func(void) {
|
|
// libunwind searches for the address before the return address which points
|
|
// to the trap instruction. NOP guarantees the trap instruction is not the
|
|
// first instruction of the function.
|
|
// We should keep this here for other unwinders that also decrement pc.
|
|
__asm__ __volatile__("nop");
|
|
__builtin_trap();
|
|
}
|
|
|
|
int main(int, char**) {
|
|
signal(SIGTRAP, signal_handler);
|
|
signal(SIGILL, signal_handler);
|
|
crashing_leaf_func();
|
|
return -2;
|
|
}
|