#include <errno.h>
#include <libunwind.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
constexpr uintptr_t vapi_glue_addr_ext_32 = 0x8b80;
constexpr uintptr_t vapi_addr_64 = 0x8e00;
constexpr size_t vapi_size_64 = 0x0200;
constexpr uintptr_t vapi_glue_addr_begin = vapi_glue_addr_ext_32;
constexpr uintptr_t vapi_glue_addr_end = vapi_addr_64 + vapi_size_64;
struct FunctionDescriptor {
uintptr_t entry;
uintptr_t toc;
uintptr_t env;
};
void my_atexit_handler(void) {
FunctionDescriptor *fd = reinterpret_cast<FunctionDescriptor *>(exit);
bool llu_enabled =
vapi_glue_addr_begin <= fd->entry && fd->entry < vapi_glue_addr_end;
fprintf(stderr, "Retrieve a cursor to `main` by stepping up.\n");
unw_context_t context;
unw_cursor_t cursor;
unw_getcontext(&context);
unw_init_local(&cursor, &context);
unw_step(&cursor);
if (!llu_enabled)
fprintf(stderr,
"libunwind: the next return address=VAPI_NOT_ENABLED from VAPI\n");
unw_step(&cursor);
if (!llu_enabled)
fprintf(stderr,
"libunwind: The return address in stack VAPI_NOT_ENABLED is within "
"the range of VAPI address; set isKnownVapiNotActive to true\n");
unw_step(&cursor);
fprintf(stderr, "Resume `main` at the call to `trapper`.\n");
if (!llu_enabled)
fprintf(stderr,
"libunwind: VAPI: executing return glue VAPI_NOT_ENABLED\n");
unw_resume(&cursor);
}
void trapper(void) {
__builtin_debugtrap();
_Exit(EXIT_FAILURE);
}
int main(void) {
if (setenv("LIBUNWIND_PRINT_UNWINDING", "1", true) != 0) {
perror("setenv");
abort();
}
if (atexit(my_atexit_handler) != 0) {
perror("atexit");
abort();
}
if (signal(SIGTRAP, exit) == SIG_ERR) {
perror("signal");
abort();
}
trapper();
_Exit(0);
}