diff --git a/include/llvm/MC/MCDwarf.h b/include/llvm/MC/MCDwarf.h index 1589e14ff5a..90c37285674 100644 --- a/include/llvm/MC/MCDwarf.h +++ b/include/llvm/MC/MCDwarf.h @@ -281,7 +281,8 @@ namespace llvm { // // This emits the frame info section. // - static void Emit(MCStreamer &streamer, bool usingCFI); + static void Emit(MCStreamer &streamer, bool usingCFI, + bool isEH); static void EmitAdvanceLoc(MCStreamer &Streamer, uint64_t AddrDelta); static void EncodeAdvanceLoc(uint64_t AddrDelta, raw_ostream &OS); }; diff --git a/include/llvm/Target/TargetAsmInfo.h b/include/llvm/Target/TargetAsmInfo.h index 0271b670464..1ae94eef8f1 100644 --- a/include/llvm/Target/TargetAsmInfo.h +++ b/include/llvm/Target/TargetAsmInfo.h @@ -58,6 +58,10 @@ public: return TLOF->getEHFrameSection(); } + const MCSection *getDwarfFrameSection() const { + return TLOF->getDwarfFrameSection(); + } + unsigned getFDEEncoding(bool CFI) const { return TLOF->getFDEEncoding(CFI); } diff --git a/lib/MC/MCDwarf.cpp b/lib/MC/MCDwarf.cpp index cfd68c12f8b..e7e2cbb139f 100644 --- a/lib/MC/MCDwarf.cpp +++ b/lib/MC/MCDwarf.cpp @@ -501,10 +501,12 @@ namespace { int CFAOffset; int CIENum; bool UsingCFI; + bool IsEH; public: - FrameEmitterImpl(bool usingCFI) : CFAOffset(0), CIENum(0), - UsingCFI(usingCFI) { + FrameEmitterImpl(bool usingCFI, bool isEH) : CFAOffset(0), CIENum(0), + UsingCFI(usingCFI), + IsEH(isEH) { } const MCSymbol &EmitCIE(MCStreamer &streamer, @@ -647,20 +649,23 @@ const MCSymbol &FrameEmitterImpl::EmitCIE(MCStreamer &streamer, streamer.EmitAbsValue(Length, 4); // CIE ID - streamer.EmitIntValue(0, 4); + unsigned CIE_ID = IsEH ? 0 : -1; + streamer.EmitIntValue(CIE_ID, 4); // Version streamer.EmitIntValue(dwarf::DW_CIE_VERSION, 1); // Augmentation String SmallString<8> Augmentation; - Augmentation += "z"; - if (personality) - Augmentation += "P"; - if (lsda) - Augmentation += "L"; - Augmentation += "R"; - streamer.EmitBytes(Augmentation.str(), 0); + if (IsEH) { + Augmentation += "z"; + if (personality) + Augmentation += "P"; + if (lsda) + Augmentation += "L"; + Augmentation += "R"; + streamer.EmitBytes(Augmentation.str(), 0); + } streamer.EmitIntValue(0, 1); // Code Alignment Factor @@ -675,30 +680,32 @@ const MCSymbol &FrameEmitterImpl::EmitCIE(MCStreamer &streamer, // Augmentation Data Length (optional) unsigned augmentationLength = 0; - if (personality) { - // Personality Encoding + if (IsEH) { + if (personality) { + // Personality Encoding + augmentationLength += 1; + // Personality + augmentationLength += getSizeForEncoding(streamer, personalityEncoding); + } + if (lsda) + augmentationLength += 1; + // Encoding of the FDE pointers augmentationLength += 1; - // Personality - augmentationLength += getSizeForEncoding(streamer, personalityEncoding); - } - if (lsda) - augmentationLength += 1; - // Encoding of the FDE pointers - augmentationLength += 1; - streamer.EmitULEB128IntValue(augmentationLength); + streamer.EmitULEB128IntValue(augmentationLength); - // Augmentation Data (optional) - if (personality) { - // Personality Encoding - streamer.EmitIntValue(personalityEncoding, 1); - // Personality - EmitPersonality(streamer, *personality, personalityEncoding); + // Augmentation Data (optional) + if (personality) { + // Personality Encoding + streamer.EmitIntValue(personalityEncoding, 1); + // Personality + EmitPersonality(streamer, *personality, personalityEncoding); + } + if (lsda) + streamer.EmitIntValue(lsdaEncoding, 1); // LSDA Encoding + // Encoding of the FDE pointers + streamer.EmitIntValue(asmInfo.getFDEEncoding(UsingCFI), 1); } - if (lsda) - streamer.EmitIntValue(lsdaEncoding, 1); // LSDA Encoding - // Encoding of the FDE pointers - streamer.EmitIntValue(asmInfo.getFDEEncoding(UsingCFI), 1); // Initial Instructions @@ -718,7 +725,7 @@ const MCSymbol &FrameEmitterImpl::EmitCIE(MCStreamer &streamer, EmitCFIInstructions(streamer, Instructions, NULL); // Padding - streamer.EmitValueToAlignment(4); + streamer.EmitValueToAlignment(IsEH ? 4 : asmInfo.getPointerSize()); streamer.EmitLabel(sectionEnd); return *sectionStart; @@ -752,31 +759,35 @@ MCSymbol *FrameEmitterImpl::EmitFDE(MCStreamer &streamer, unsigned size = getSizeForEncoding(streamer, fdeEncoding); // PC Begin - EmitSymbol(streamer, *frame.Begin, fdeEncoding); + unsigned PCBeginEncoding = IsEH ? fdeEncoding : dwarf::DW_EH_PE_absptr; + unsigned PCBeginSize = getSizeForEncoding(streamer, PCBeginEncoding); + EmitSymbol(streamer, *frame.Begin, PCBeginEncoding); // PC Range const MCExpr *Range = MakeStartMinusEndExpr(streamer, *frame.Begin, *frame.End, 0); streamer.EmitAbsValue(Range, size); - // Augmentation Data Length - unsigned augmentationLength = 0; + if (IsEH) { + // Augmentation Data Length + unsigned augmentationLength = 0; - if (frame.Lsda) - augmentationLength += getSizeForEncoding(streamer, frame.LsdaEncoding); + if (frame.Lsda) + augmentationLength += getSizeForEncoding(streamer, frame.LsdaEncoding); - streamer.EmitULEB128IntValue(augmentationLength); + streamer.EmitULEB128IntValue(augmentationLength); - // Augmentation Data - if (frame.Lsda) - EmitSymbol(streamer, *frame.Lsda, frame.LsdaEncoding); + // Augmentation Data + if (frame.Lsda) + EmitSymbol(streamer, *frame.Lsda, frame.LsdaEncoding); + } // Call Frame Instructions EmitCFIInstructions(streamer, frame.Instructions, frame.Begin); // Padding - streamer.EmitValueToAlignment(size); + streamer.EmitValueToAlignment(PCBeginSize); return fdeEnd; } @@ -823,21 +834,24 @@ namespace llvm { } void MCDwarfFrameEmitter::Emit(MCStreamer &streamer, - bool usingCFI) { + bool usingCFI, + bool isEH) { const MCContext &context = streamer.getContext(); const TargetAsmInfo &asmInfo = context.getTargetAsmInfo(); - const MCSection §ion = *asmInfo.getEHFrameSection(); + const MCSection §ion = isEH ? + *asmInfo.getEHFrameSection() : *asmInfo.getDwarfFrameSection(); streamer.SwitchSection(§ion); MCSymbol *fdeEnd = NULL; DenseMap CIEStarts; - FrameEmitterImpl Emitter(usingCFI); + FrameEmitterImpl Emitter(usingCFI, isEH); + const MCSymbol *DummyDebugKey = NULL; for (unsigned i = 0, n = streamer.getNumFrameInfos(); i < n; ++i) { const MCDwarfFrameInfo &frame = streamer.getFrameInfo(i); CIEKey key(frame.Personality, frame.PersonalityEncoding, frame.LsdaEncoding); - const MCSymbol *&cieStart = CIEStarts[key]; + const MCSymbol *&cieStart = isEH ? CIEStarts[key] : DummyDebugKey; if (!cieStart) cieStart = &Emitter.EmitCIE(streamer, frame.Personality, frame.PersonalityEncoding, frame.Lsda, diff --git a/lib/MC/MCStreamer.cpp b/lib/MC/MCStreamer.cpp index d84e0c2369d..689e408a1a0 100644 --- a/lib/MC/MCStreamer.cpp +++ b/lib/MC/MCStreamer.cpp @@ -369,5 +369,8 @@ void MCStreamer::EmitFrames(bool usingCFI) { return; if (EmitEHFrame) - MCDwarfFrameEmitter::Emit(*this, usingCFI); + MCDwarfFrameEmitter::Emit(*this, usingCFI, true); + + if (EmitDebugFrame) + MCDwarfFrameEmitter::Emit(*this, usingCFI, false); } diff --git a/test/MC/ELF/cfi-sections.s b/test/MC/ELF/cfi-sections.s new file mode 100644 index 00000000000..a273e320c59 --- /dev/null +++ b/test/MC/ELF/cfi-sections.s @@ -0,0 +1,42 @@ +// RUN: llvm-mc -filetype=obj -triple x86_64-pc-linux-gnu %s -o - | elf-dump --dump-section-data | FileCheck -check-prefix=ELF_64 %s +// RUN: llvm-mc -filetype=obj -triple i686-pc-linux-gnu %s -o - | elf-dump --dump-section-data | FileCheck -check-prefix=ELF_32 %s + + +// The only difference in gas' output in this test is that we don't produce +// the relocations to .debug_frame (we know their values). + +.cfi_sections .debug_frame + +f1: + .cfi_startproc + nop + .cfi_endproc + +f2: + .cfi_startproc + nop + .cfi_endproc + +// ELF_64: (('sh_name', 0x00000011) # '.debug_frame' +// ELF_64-NEXT: ('sh_type', 0x00000001) +// ELF_64-NEXT: ('sh_flags', 0x00000000) +// ELF_64-NEXT: ('sh_addr', 0x00000000) +// ELF_64-NEXT: ('sh_offset', 0x00000048) +// ELF_64-NEXT: ('sh_size', 0x00000048) +// ELF_64-NEXT: ('sh_link', 0x00000000) +// ELF_64-NEXT: ('sh_info', 0x00000000) +// ELF_64-NEXT: ('sh_addralign', 0x00000008) +// ELF_64-NEXT: ('sh_entsize', 0x00000000) +// ELF_64-NEXT: ('_section_data', '14000000 ffffffff 01000178 100c0708 90010000 00000000 14000000 1c000000 00000000 00000000 01000000 00000000 14000000 34000000 00000000 00000000 01000000 00000000') + +// ELF_32: (('sh_name', 0x00000010) # '.debug_frame' +// ELF_32-NEXT: ('sh_type', 0x00000001) +// ELF_32-NEXT: ('sh_flags', 0x00000000) +// ELF_32-NEXT: ('sh_addr', 0x00000000) +// ELF_32-NEXT: ('sh_offset', 0x00000038) +// ELF_32-NEXT: ('sh_size', 0x00000034) +// ELF_32-NEXT: ('sh_link', 0x00000000) +// ELF_32-NEXT: ('sh_info', 0x00000000) +// ELF_32-NEXT: ('sh_addralign', 0x00000004) +// ELF_32-NEXT: ('sh_entsize', 0x00000000) +// ELF_32-NEXT: ('_section_data', '10000000 ffffffff 0100017c 080c0404 88010000 0c000000 18000000 00000000 01000000 0c000000 28000000 01000000 01000000')