Add support for producing .deubg_frame sections.

llvm-svn: 131121
This commit is contained in:
Rafael Espindola 2011-05-10 03:54:12 +00:00
parent b6444c0401
commit 1ecb12fc57
5 changed files with 111 additions and 47 deletions

View File

@ -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);
};

View File

@ -58,6 +58,10 @@ public:
return TLOF->getEHFrameSection();
}
const MCSection *getDwarfFrameSection() const {
return TLOF->getDwarfFrameSection();
}
unsigned getFDEEncoding(bool CFI) const {
return TLOF->getFDEEncoding(CFI);
}

View File

@ -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 &section = *asmInfo.getEHFrameSection();
const MCSection &section = isEH ?
*asmInfo.getEHFrameSection() : *asmInfo.getDwarfFrameSection();
streamer.SwitchSection(&section);
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,

View File

@ -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);
}

View File

@ -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')