1 // -*- C++ -*- 2 //===----------------------------------------------------------------------===// 3 // 4 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 5 // See https://llvm.org/LICENSE.txt for license information. 6 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 7 // 8 //===----------------------------------------------------------------------===// 9 10 // Ensure that libunwind doesn't crash on invalid info; the Linux aarch64 11 // sigreturn frame check would previously attempt to access invalid memory in 12 // this scenario. 13 // REQUIRES: linux && (target={{aarch64-.+}} || target={{s390x-.+}} || target={{x86_64-.+}}) 14 15 // GCC doesn't support __attribute__((naked)) on AArch64. 16 // UNSUPPORTED: gcc 17 18 // Inline assembly is incompatible with MSAN. 19 // UNSUPPORTED: msan 20 21 #undef NDEBUG 22 #include <assert.h> 23 #include <libunwind.h> 24 #include <stdio.h> 25 26 __attribute__((naked)) void bad_unwind_info() { 27 #if defined(__aarch64__) 28 __asm__("// not using 0 because unwinder was already resilient to that\n" 29 "mov x8, #4\n" 30 "stp x30, x8, [sp, #-16]!\n" 31 ".cfi_def_cfa_offset 16\n" 32 "// purposely use incorrect offset for x30\n" 33 ".cfi_offset x30, -8\n" 34 "bl stepper\n" 35 "ldr x30, [sp], #16\n" 36 ".cfi_def_cfa_offset 0\n" 37 ".cfi_restore x30\n" 38 "ret\n"); 39 #elif defined(__s390x__) 40 __asm__("stmg %r14,%r15,112(%r15)\n" 41 "mvghi 104(%r15),4\n" 42 "# purposely use incorrect offset for %r14\n" 43 ".cfi_offset 14, -56\n" 44 ".cfi_offset 15, -40\n" 45 "lay %r15,-160(%r15)\n" 46 ".cfi_def_cfa_offset 320\n" 47 "brasl %r14,stepper\n" 48 "lmg %r14,%r15,272(%r15)\n" 49 ".cfi_restore 15\n" 50 ".cfi_restore 14\n" 51 ".cfi_def_cfa_offset 160\n" 52 "br %r14\n"); 53 #elif defined(__x86_64__) 54 __asm__("pushq %rbx\n" 55 ".cfi_def_cfa_offset 16\n" 56 "movq 8(%rsp), %rbx\n" 57 "# purposely corrupt return value on stack\n" 58 "movq $4, 8(%rsp)\n" 59 "callq stepper\n" 60 "movq %rbx, 8(%rsp)\n" 61 "popq %rbx\n" 62 ".cfi_def_cfa_offset 8\n" 63 "ret\n"); 64 #else 65 #error This test is only supported on aarch64, s390x, or x86-64 66 #endif 67 } 68 69 extern "C" void stepper() { 70 unw_cursor_t cursor; 71 unw_context_t uc; 72 unw_getcontext(&uc); 73 unw_init_local(&cursor, &uc); 74 // stepping to bad_unwind_info should succeed 75 assert(unw_step(&cursor) > 0); 76 // stepping past bad_unwind_info should fail but not crash 77 assert(unw_step(&cursor) <= 0); 78 } 79 80 int main() { bad_unwind_info(); } 81