From 04e5b7fd17748bd10ae0f30cb571103e5da0dde5 Mon Sep 17 00:00:00 2001 From: Tim Northover Date: Wed, 18 May 2022 11:40:46 +0100 Subject: [PATCH] AArch64: fall back to DWARF instead of crashing on weird .cfi directives CodeGen will only produce fixed formwat prologues, but hand-written assembly can have .cfi directives in any combination they want. This should cause a fallback to DWARF rather than an assertion failure (or an incorrect compact unwind if assertions are disabled). --- .../Target/AArch64/MCTargetDesc/AArch64AsmBackend.cpp | 19 ++++++++++--------- llvm/test/MC/AArch64/arm64-compact-unwind-fallback.s | 15 +++++++++++++++ 2 files changed, 25 insertions(+), 9 deletions(-) diff --git a/llvm/lib/Target/AArch64/MCTargetDesc/AArch64AsmBackend.cpp b/llvm/lib/Target/AArch64/MCTargetDesc/AArch64AsmBackend.cpp index 85b2212..c1188d1 100644 --- a/llvm/lib/Target/AArch64/MCTargetDesc/AArch64AsmBackend.cpp +++ b/llvm/lib/Target/AArch64/MCTargetDesc/AArch64AsmBackend.cpp @@ -593,17 +593,18 @@ public: if (XReg != AArch64::FP) return CU::UNWIND_ARM64_MODE_DWARF; - assert(XReg == AArch64::FP && "Invalid frame pointer!"); - assert(i + 2 < e && "Insufficient CFI instructions to define a frame!"); + if (i + 2 >= e) + return CU::UNWIND_ARM64_MODE_DWARF; const MCCFIInstruction &LRPush = Instrs[++i]; - assert(LRPush.getOperation() == MCCFIInstruction::OpOffset && - "Link register not pushed!"); + if (LRPush.getOperation() != MCCFIInstruction::OpOffset) + return CU::UNWIND_ARM64_MODE_DWARF; const MCCFIInstruction &FPPush = Instrs[++i]; - assert(FPPush.getOperation() == MCCFIInstruction::OpOffset && - "Frame pointer not pushed!"); + if (FPPush.getOperation() != MCCFIInstruction::OpOffset) + return CU::UNWIND_ARM64_MODE_DWARF; - assert(FPPush.getOffset() + 8 == LRPush.getOffset()); + if (FPPush.getOffset() + 8 != LRPush.getOffset()) + return CU::UNWIND_ARM64_MODE_DWARF; CurOffset = FPPush.getOffset(); unsigned LRReg = *MRI.getLLVMRegNum(LRPush.getRegister(), true); @@ -612,8 +613,8 @@ public: LRReg = getXRegFromWReg(LRReg); FPReg = getXRegFromWReg(FPReg); - assert(LRReg == AArch64::LR && FPReg == AArch64::FP && - "Pushing invalid registers for frame!"); + if (LRReg != AArch64::LR || FPReg != AArch64::FP) + return CU::UNWIND_ARM64_MODE_DWARF; // Indicate that the function has a frame. CompactUnwindEncoding |= CU::UNWIND_ARM64_MODE_FRAME; diff --git a/llvm/test/MC/AArch64/arm64-compact-unwind-fallback.s b/llvm/test/MC/AArch64/arm64-compact-unwind-fallback.s index 12525b7..317b671 100644 --- a/llvm/test/MC/AArch64/arm64-compact-unwind-fallback.s +++ b/llvm/test/MC/AArch64/arm64-compact-unwind-fallback.s @@ -6,6 +6,8 @@ // CHECK: Contents of __compact_unwind section: // CHECK: compact encoding: 0x03000000 // CHECK: compact encoding: 0x03000000 +// CHECK: compact encoding: 0x03000000 +// CHECK: compact encoding: 0x03000000 // CHECK: .eh_frame contents: // CHECK: DW_CFA_def_cfa: reg1 +32 @@ -23,3 +25,16 @@ _cfi_dwarf1: .cfi_def_cfa_offset 32 .cfi_def_cfa_offset 64 .cfi_endproc + +_cfi_dwarf2: + .cfi_startproc + .cfi_def_cfa w29, 16 + .cfi_def_cfa w29, 16 + .cfi_endproc + +_cfi_dwarf3: + .cfi_startproc + .cfi_def_cfa w29, 16 + .cfi_offset w16, -16 + .cfi_offset w17, -8 + .cfi_endproc -- 2.7.4