From c55ae3f8a6451dc372f0d903229ac2d1bb4d8df0 Mon Sep 17 00:00:00 2001 From: Alexander Richardson Date: Tue, 13 Nov 2018 10:54:49 +0000 Subject: [PATCH] Fix .cfi_restore with register numbers > 64 Summary: DW_CFA_restore can only encode register numbers up to 64 (6 bits unsigned int). For regsiter numbers > 64 we have to use DW_CFA_restore_extended instead which uses a ULEB128 value. I discovered this problem in the out-of-tree CHERI target since we use DWARF register number 89 for our return capability register. Reviewers: probinson, dblaikie, aprantl, espindola Reviewed By: dblaikie Subscribers: JohnReagan, emaste, JDevlieghere, llvm-commits Differential Revision: https://reviews.llvm.org/D54420 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@346751 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/MC/MCDwarf.cpp | 7 ++++++- test/MC/ELF/cfi-restore-extended.s | 17 +++++++++++++++++ 2 files changed, 23 insertions(+), 1 deletion(-) create mode 100644 test/MC/ELF/cfi-restore-extended.s diff --git a/lib/MC/MCDwarf.cpp b/lib/MC/MCDwarf.cpp index 7093446815f..66dfe7b7fa4 100644 --- a/lib/MC/MCDwarf.cpp +++ b/lib/MC/MCDwarf.cpp @@ -1418,7 +1418,12 @@ void FrameEmitterImpl::EmitCFIInstruction(const MCCFIInstruction &Instr) { unsigned Reg = Instr.getRegister(); if (!IsEH) Reg = MRI->getDwarfRegNumFromDwarfEHRegNum(Reg); - Streamer.EmitIntValue(dwarf::DW_CFA_restore | Reg, 1); + if (Reg < 64) { + Streamer.EmitIntValue(dwarf::DW_CFA_restore | Reg, 1); + } else { + Streamer.EmitIntValue(dwarf::DW_CFA_restore_extended, 1); + Streamer.EmitULEB128IntValue(Reg); + } return; } case MCCFIInstruction::OpGnuArgsSize: diff --git a/test/MC/ELF/cfi-restore-extended.s b/test/MC/ELF/cfi-restore-extended.s new file mode 100644 index 00000000000..e7371089934 --- /dev/null +++ b/test/MC/ELF/cfi-restore-extended.s @@ -0,0 +1,17 @@ +// RUN: llvm-mc -filetype=obj -triple x86_64-pc-linux-gnu %s -o - | llvm-dwarfdump -debug-frame - | FileCheck %s + +// Check that register numbers greater than 63 can be used in .cfi_restore directives +f: + .cfi_startproc + nop +// CHECK: DW_CFA_advance_loc: 1 + .cfi_restore %rbp +// CHECK-NEXT: DW_CFA_restore: reg6 + nop +// CHECK-NEXT: DW_CFA_advance_loc: 1 + .cfi_restore 89 +// CHECK-NEXT: DW_CFA_restore_extended: reg89 +// CHECK-NEXT: DW_CFA_nop: + nop + .cfi_endproc +