85 lines · cpp
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-exception7//8//===----------------------------------------------------------------------===//9 10// Ensure that libunwind doesn't crash on invalid info; the Linux aarch6411// sigreturn frame check would previously attempt to access invalid memory in12// this scenario.13// REQUIRES: target={{(aarch64|s390x|x86_64)-.+}}14// UNSUPPORTED: target={{.*-windows.*}}15 16// GCC doesn't support __attribute__((naked)) on AArch64.17// UNSUPPORTED: gcc18 19// Inline assembly is incompatible with MSAN.20// UNSUPPORTED: msan21 22#undef NDEBUG23#include <assert.h>24#include <libunwind.h>25#include <stdio.h>26 27__attribute__((naked)) void bad_unwind_info() {28#if defined(__aarch64__)29 __asm__("// not using 0 because unwinder was already resilient to that\n"30 "mov x8, #4\n"31 "stp x30, x8, [sp, #-16]!\n"32 ".cfi_def_cfa_offset 16\n"33 "// purposely use incorrect offset for x30\n"34 ".cfi_offset x30, -8\n"35 "bl stepper\n"36 "ldr x30, [sp], #16\n"37 ".cfi_def_cfa_offset 0\n"38 ".cfi_restore x30\n"39 "ret\n");40#elif defined(__s390x__)41 __asm__("stmg %r14,%r15,112(%r15)\n"42 "mvghi 104(%r15),4\n"43 "# purposely use incorrect offset for %r14\n"44 ".cfi_offset 14, -56\n"45 ".cfi_offset 15, -40\n"46 "lay %r15,-160(%r15)\n"47 ".cfi_def_cfa_offset 320\n"48 "brasl %r14,stepper\n"49 "lmg %r14,%r15,272(%r15)\n"50 ".cfi_restore 15\n"51 ".cfi_restore 14\n"52 ".cfi_def_cfa_offset 160\n"53 "br %r14\n");54#elif defined(__x86_64__)55 __asm__("pushq %rbx\n"56 ".cfi_def_cfa_offset 16\n"57 "movq 8(%rsp), %rbx\n"58 "# purposely corrupt return value on stack\n"59 "movq $4, 8(%rsp)\n"60 "callq stepper\n"61 "movq %rbx, 8(%rsp)\n"62 "popq %rbx\n"63 ".cfi_def_cfa_offset 8\n"64 "ret\n");65#else66#error This test is only supported on aarch64, s390x, or x86-6467#endif68}69 70extern "C" void stepper() {71 unw_cursor_t cursor;72 unw_context_t uc;73 unw_getcontext(&uc);74 unw_init_local(&cursor, &uc);75 // stepping to bad_unwind_info should succeed76 assert(unw_step(&cursor) > 0);77 // stepping past bad_unwind_info should fail but not crash78 assert(unw_step(&cursor) <= 0);79}80 81int main(int, char **) {82 bad_unwind_info();83 return 0;84}85