[MC] Use the non-EH register mapping in the debug_frame section.

On 32bits x86 Darwin, the register mappings for the eh_frane and
debug_frame sections are different. Thus the same CFI instructions
should result in different registers in the object file. The
problem isn't target specific though, but it requires that the
mappings for EH register numbers be different from the standard
Dwarf one.

The patch looks a bit clumsy. LLVM uses the EH mapping as
canonical for everything frame related. Thus we need to do a
double conversion EH -> LLVM -> Non-EH, when emitting the
debug_frame section.

Fixes PR22363.

Differential Revision: http://reviews.llvm.org/D7593

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@230670 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Frederic Riss 2015-02-26 19:48:07 +00:00
parent 298988eb79
commit 09e8018e14
2 changed files with 58 additions and 4 deletions

View File

@ -1045,11 +1045,16 @@ static void emitEncodingByte(MCObjectStreamer &Streamer, unsigned Encoding) {
void FrameEmitterImpl::EmitCFIInstruction(MCObjectStreamer &Streamer, void FrameEmitterImpl::EmitCFIInstruction(MCObjectStreamer &Streamer,
const MCCFIInstruction &Instr) { const MCCFIInstruction &Instr) {
int dataAlignmentFactor = getDataAlignmentFactor(Streamer); int dataAlignmentFactor = getDataAlignmentFactor(Streamer);
auto *MRI = Streamer.getContext().getRegisterInfo();
switch (Instr.getOperation()) { switch (Instr.getOperation()) {
case MCCFIInstruction::OpRegister: { case MCCFIInstruction::OpRegister: {
unsigned Reg1 = Instr.getRegister(); unsigned Reg1 = Instr.getRegister();
unsigned Reg2 = Instr.getRegister2(); unsigned Reg2 = Instr.getRegister2();
if (!IsEH) {
Reg1 = MRI->getDwarfRegNum(MRI->getLLVMRegNum(Reg1, true), false);
Reg2 = MRI->getDwarfRegNum(MRI->getLLVMRegNum(Reg2, true), false);
}
Streamer.EmitIntValue(dwarf::DW_CFA_register, 1); Streamer.EmitIntValue(dwarf::DW_CFA_register, 1);
Streamer.EmitULEB128IntValue(Reg1); Streamer.EmitULEB128IntValue(Reg1);
Streamer.EmitULEB128IntValue(Reg2); Streamer.EmitULEB128IntValue(Reg2);
@ -1082,8 +1087,11 @@ void FrameEmitterImpl::EmitCFIInstruction(MCObjectStreamer &Streamer,
return; return;
} }
case MCCFIInstruction::OpDefCfa: { case MCCFIInstruction::OpDefCfa: {
unsigned Reg = Instr.getRegister();
if (!IsEH)
Reg = MRI->getDwarfRegNum(MRI->getLLVMRegNum(Reg, true), false);
Streamer.EmitIntValue(dwarf::DW_CFA_def_cfa, 1); Streamer.EmitIntValue(dwarf::DW_CFA_def_cfa, 1);
Streamer.EmitULEB128IntValue(Instr.getRegister()); Streamer.EmitULEB128IntValue(Reg);
CFAOffset = -Instr.getOffset(); CFAOffset = -Instr.getOffset();
Streamer.EmitULEB128IntValue(CFAOffset); Streamer.EmitULEB128IntValue(CFAOffset);
@ -1091,8 +1099,11 @@ void FrameEmitterImpl::EmitCFIInstruction(MCObjectStreamer &Streamer,
} }
case MCCFIInstruction::OpDefCfaRegister: { case MCCFIInstruction::OpDefCfaRegister: {
unsigned Reg = Instr.getRegister();
if (!IsEH)
Reg = MRI->getDwarfRegNum(MRI->getLLVMRegNum(Reg, true), false);
Streamer.EmitIntValue(dwarf::DW_CFA_def_cfa_register, 1); Streamer.EmitIntValue(dwarf::DW_CFA_def_cfa_register, 1);
Streamer.EmitULEB128IntValue(Instr.getRegister()); Streamer.EmitULEB128IntValue(Reg);
return; return;
} }
@ -1103,6 +1114,9 @@ void FrameEmitterImpl::EmitCFIInstruction(MCObjectStreamer &Streamer,
Instr.getOperation() == MCCFIInstruction::OpRelOffset; Instr.getOperation() == MCCFIInstruction::OpRelOffset;
unsigned Reg = Instr.getRegister(); unsigned Reg = Instr.getRegister();
if (!IsEH)
Reg = MRI->getDwarfRegNum(MRI->getLLVMRegNum(Reg, true), false);
int Offset = Instr.getOffset(); int Offset = Instr.getOffset();
if (IsRelative) if (IsRelative)
Offset -= CFAOffset; Offset -= CFAOffset;
@ -1136,6 +1150,8 @@ void FrameEmitterImpl::EmitCFIInstruction(MCObjectStreamer &Streamer,
} }
case MCCFIInstruction::OpRestore: { case MCCFIInstruction::OpRestore: {
unsigned Reg = Instr.getRegister(); unsigned Reg = Instr.getRegister();
if (!IsEH)
Reg = MRI->getDwarfRegNum(MRI->getLLVMRegNum(Reg, true), false);
Streamer.EmitIntValue(dwarf::DW_CFA_restore | Reg, 1); Streamer.EmitIntValue(dwarf::DW_CFA_restore | Reg, 1);
return; return;
} }
@ -1290,10 +1306,10 @@ const MCSymbol &FrameEmitterImpl::EmitCIE(MCObjectStreamer &streamer,
if (CIEVersion == 1) { if (CIEVersion == 1) {
assert(MRI->getRARegister() <= 255 && assert(MRI->getRARegister() <= 255 &&
"DWARF 2 encodes return_address_register in one byte"); "DWARF 2 encodes return_address_register in one byte");
streamer.EmitIntValue(MRI->getDwarfRegNum(MRI->getRARegister(), true), 1); streamer.EmitIntValue(MRI->getDwarfRegNum(MRI->getRARegister(), IsEH), 1);
} else { } else {
streamer.EmitULEB128IntValue( streamer.EmitULEB128IntValue(
MRI->getDwarfRegNum(MRI->getRARegister(), true)); MRI->getDwarfRegNum(MRI->getRARegister(), IsEH));
} }
// Augmentation Data Length (optional) // Augmentation Data Length (optional)

View File

@ -0,0 +1,38 @@
; RUN: llc -filetype=obj %s -o - | llvm-dwarfdump -debug-dump=frames - | FileCheck %s
; IR reduced from a dummy:
; void foo() {}
; x86 Darwin uses different register mappings for eh_frame and debug_frame
; sections. Check that the right mapping is used in debug_frame.
; In the debug_frame mapping, regsiter 4 is ESP, thus the below tests that
; the CFA is ESP+4 upon function entry.
; CHECK: .debug_frame contents:
; CHECK: ffffffff CIE
; CHECK-NOT: {{CIE|FDE}}
; CHECK: DW_CFA_def_cfa: reg4 +4
; ModuleID = 'foo.c'
target datalayout = "e-m:o-p:32:32-f64:32:64-f80:128-n8:16:32-S128"
target triple = "i386-apple-macosx10.10.0"
; Function Attrs: nounwind ssp
define void @foo() #0 {
entry:
ret void
}
attributes #0 = { nounwind }
!llvm.dbg.cu = !{!0}
!llvm.module.flags = !{!3, !4, !5}
!llvm.ident = !{!6}
!0 = !{!"0x11\0012\00clang version 3.7.0 (trunk 230514) (llvm/trunk 230518)\000\00\000\00\001", !1, !2, !2, !2, !2, !2} ; [ DW_TAG_compile_unit ] [/tmp/foo.c] [DW_LANG_C99]
!1 = !{!"foo.c", !"/tmp"}
!2 = !{}
!3 = !{i32 2, !"Dwarf Version", i32 2}
!4 = !{i32 2, !"Debug Info Version", i32 2}
!5 = !{i32 1, !"PIC Level", i32 2}
!6 = !{!"clang version 3.7.0 (trunk 230514) (llvm/trunk 230518)"}