#undef NDEBUG
#include <assert.h>
#include <libunwind.h>
#include <stdio.h>
__attribute__((naked)) void bad_unwind_info() {
#if defined(__aarch64__)
__asm__("// not using 0 because unwinder was already resilient to that\n"
"mov x8, #4\n"
"stp x30, x8, [sp, #-16]!\n"
".cfi_def_cfa_offset 16\n"
"// purposely use incorrect offset for x30\n"
".cfi_offset x30, -8\n"
"bl stepper\n"
"ldr x30, [sp], #16\n"
".cfi_def_cfa_offset 0\n"
".cfi_restore x30\n"
"ret\n");
#elif defined(__s390x__)
__asm__("stmg %r14,%r15,112(%r15)\n"
"mvghi 104(%r15),4\n"
"# purposely use incorrect offset for %r14\n"
".cfi_offset 14, -56\n"
".cfi_offset 15, -40\n"
"lay %r15,-160(%r15)\n"
".cfi_def_cfa_offset 320\n"
"brasl %r14,stepper\n"
"lmg %r14,%r15,272(%r15)\n"
".cfi_restore 15\n"
".cfi_restore 14\n"
".cfi_def_cfa_offset 160\n"
"br %r14\n");
#elif defined(__x86_64__)
__asm__("pushq %rbx\n"
".cfi_def_cfa_offset 16\n"
"movq 8(%rsp), %rbx\n"
"# purposely corrupt return value on stack\n"
"movq $4, 8(%rsp)\n"
"callq stepper\n"
"movq %rbx, 8(%rsp)\n"
"popq %rbx\n"
".cfi_def_cfa_offset 8\n"
"ret\n");
#else
#error This test is only supported on aarch64, s390x, or x86-64
#endif
}
extern "C" void stepper() {
unw_cursor_t cursor;
unw_context_t uc;
unw_getcontext(&uc);
unw_init_local(&cursor, &uc);
assert(unw_step(&cursor) > 0);
assert(unw_step(&cursor) <= 0);
}
int main(int, char **) {
bad_unwind_info();
return 0;
}