diff options
author | Rafael Espindola <rafael.espindola@gmail.com> | 2011-05-10 03:54:12 +0000 |
---|---|---|
committer | Rafael Espindola <rafael.espindola@gmail.com> | 2011-05-10 03:54:12 +0000 |
commit | 40a7dbbeff44c4cbd8c7e4f07f28dd614f8a5d08 (patch) | |
tree | 2fb42afa5dde9c0da64044de5af88cdb34290643 | |
parent | 774466a8a5388d334b57053fbbfd22b547b729ed (diff) | |
download | external_llvm-40a7dbbeff44c4cbd8c7e4f07f28dd614f8a5d08.zip external_llvm-40a7dbbeff44c4cbd8c7e4f07f28dd614f8a5d08.tar.gz external_llvm-40a7dbbeff44c4cbd8c7e4f07f28dd614f8a5d08.tar.bz2 |
Add support for producing .deubg_frame sections.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@131121 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r-- | include/llvm/MC/MCDwarf.h | 3 | ||||
-rw-r--r-- | include/llvm/Target/TargetAsmInfo.h | 4 | ||||
-rw-r--r-- | lib/MC/MCDwarf.cpp | 104 | ||||
-rw-r--r-- | lib/MC/MCStreamer.cpp | 5 | ||||
-rw-r--r-- | test/MC/ELF/cfi-sections.s | 42 |
5 files changed, 111 insertions, 47 deletions
diff --git a/include/llvm/MC/MCDwarf.h b/include/llvm/MC/MCDwarf.h index 1589e14..90c3728 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 0271b67..1ae94ee 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 cfd68c1..e7e2cbb 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 - augmentationLength += 1; - // Personality - augmentationLength += getSizeForEncoding(streamer, personalityEncoding); - } - if (lsda) + if (IsEH) { + if (personality) { + // Personality Encoding + augmentationLength += 1; + // Personality + augmentationLength += getSizeForEncoding(streamer, personalityEncoding); + } + if (lsda) + augmentationLength += 1; + // Encoding of the FDE pointers 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<CIEKey, const MCSymbol*> 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 d84e0c2..689e408 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 0000000..a273e32 --- /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') |