diff options
Diffstat (limited to 'contrib/llvm/lib/MC/MCDwarf.cpp')
-rw-r--r-- | contrib/llvm/lib/MC/MCDwarf.cpp | 399 |
1 files changed, 188 insertions, 211 deletions
diff --git a/contrib/llvm/lib/MC/MCDwarf.cpp b/contrib/llvm/lib/MC/MCDwarf.cpp index c84c486..a99ac4e 100644 --- a/contrib/llvm/lib/MC/MCDwarf.cpp +++ b/contrib/llvm/lib/MC/MCDwarf.cpp @@ -27,26 +27,8 @@ #include "llvm/Support/Path.h" #include "llvm/Support/SourceMgr.h" #include "llvm/Support/raw_ostream.h" -using namespace llvm; - -// Given a special op, return the address skip amount (in units of -// DWARF2_LINE_MIN_INSN_LENGTH. -#define SPECIAL_ADDR(op) (((op) - DWARF2_LINE_OPCODE_BASE)/DWARF2_LINE_RANGE) - -// The maximum address skip amount that can be encoded with a special op. -#define MAX_SPECIAL_ADDR_DELTA SPECIAL_ADDR(255) - -// First special line opcode - leave room for the standard opcodes. -// Note: If you want to change this, you'll have to update the -// "standard_opcode_lengths" table that is emitted in DwarfFileTable::Emit(). -#define DWARF2_LINE_OPCODE_BASE 13 - -// Minimum line offset in a special line info. opcode. This value -// was chosen to give a reasonable range of values. -#define DWARF2_LINE_BASE -5 -// Range of line offsets in a special line info. opcode. -#define DWARF2_LINE_RANGE 14 +using namespace llvm; static inline uint64_t ScaleAddrDelta(MCContext &Context, uint64_t AddrDelta) { unsigned MinInsnLength = Context.getAsmInfo()->getMinInstAlignment(); @@ -197,7 +179,8 @@ EmitDwarfLineTable(MCObjectStreamer *MCOS, MCSection *Section, // // This emits the Dwarf file and the line tables. // -void MCDwarfLineTable::Emit(MCObjectStreamer *MCOS) { +void MCDwarfLineTable::Emit(MCObjectStreamer *MCOS, + MCDwarfLineTableParams Params) { MCContext &context = MCOS->getContext(); auto &LineTables = context.getMCDwarfLineTables(); @@ -212,14 +195,17 @@ void MCDwarfLineTable::Emit(MCObjectStreamer *MCOS) { // Handle the rest of the Compile Units. for (const auto &CUIDTablePair : LineTables) - CUIDTablePair.second.EmitCU(MCOS); + CUIDTablePair.second.EmitCU(MCOS, Params); } -void MCDwarfDwoLineTable::Emit(MCStreamer &MCOS) const { - MCOS.EmitLabel(Header.Emit(&MCOS, None).second); +void MCDwarfDwoLineTable::Emit(MCStreamer &MCOS, + MCDwarfLineTableParams Params) const { + MCOS.EmitLabel(Header.Emit(&MCOS, Params, None).second); } -std::pair<MCSymbol *, MCSymbol *> MCDwarfLineTableHeader::Emit(MCStreamer *MCOS) const { +std::pair<MCSymbol *, MCSymbol *> +MCDwarfLineTableHeader::Emit(MCStreamer *MCOS, + MCDwarfLineTableParams Params) const { static const char StandardOpcodeLengths[] = { 0, // length of DW_LNS_copy 1, // length of DW_LNS_advance_pc @@ -234,9 +220,10 @@ std::pair<MCSymbol *, MCSymbol *> MCDwarfLineTableHeader::Emit(MCStreamer *MCOS) 0, // length of DW_LNS_set_epilogue_begin 1 // DW_LNS_set_isa }; - assert(array_lengthof(StandardOpcodeLengths) == - (DWARF2_LINE_OPCODE_BASE - 1)); - return Emit(MCOS, StandardOpcodeLengths); + assert(array_lengthof(StandardOpcodeLengths) >= + (Params.DWARF2LineOpcodeBase - 1U)); + return Emit(MCOS, Params, makeArrayRef(StandardOpcodeLengths, + Params.DWARF2LineOpcodeBase - 1)); } static const MCExpr *forceExpAbs(MCStreamer &OS, const MCExpr* Expr) { @@ -256,9 +243,8 @@ static void emitAbsValue(MCStreamer &OS, const MCExpr *Value, unsigned Size) { } std::pair<MCSymbol *, MCSymbol *> -MCDwarfLineTableHeader::Emit(MCStreamer *MCOS, +MCDwarfLineTableHeader::Emit(MCStreamer *MCOS, MCDwarfLineTableParams Params, ArrayRef<char> StandardOpcodeLengths) const { - MCContext &context = MCOS->getContext(); // Create a symbol at the beginning of the line table. @@ -293,8 +279,8 @@ MCDwarfLineTableHeader::Emit(MCStreamer *MCOS, // Parameters of the state machine, are next. MCOS->EmitIntValue(context.getAsmInfo()->getMinInstAlignment(), 1); MCOS->EmitIntValue(DWARF2_LINE_DEFAULT_IS_STMT, 1); - MCOS->EmitIntValue(DWARF2_LINE_BASE, 1); - MCOS->EmitIntValue(DWARF2_LINE_RANGE, 1); + MCOS->EmitIntValue(Params.DWARF2LineBase, 1); + MCOS->EmitIntValue(Params.DWARF2LineRange, 1); MCOS->EmitIntValue(StandardOpcodeLengths.size() + 1, 1); // Standard opcode lengths @@ -329,8 +315,9 @@ MCDwarfLineTableHeader::Emit(MCStreamer *MCOS, return std::make_pair(LineStartSym, LineEndSym); } -void MCDwarfLineTable::EmitCU(MCObjectStreamer *MCOS) const { - MCSymbol *LineEndSym = Header.Emit(MCOS).second; +void MCDwarfLineTable::EmitCU(MCObjectStreamer *MCOS, + MCDwarfLineTableParams Params) const { + MCSymbol *LineEndSym = Header.Emit(MCOS, Params).second; // Put out the line tables. for (const auto &LineSec : MCLineSections.getMCLineEntries()) @@ -416,21 +403,31 @@ unsigned MCDwarfLineTableHeader::getFile(StringRef &Directory, } /// Utility function to emit the encoding to a streamer. -void MCDwarfLineAddr::Emit(MCStreamer *MCOS, int64_t LineDelta, - uint64_t AddrDelta) { +void MCDwarfLineAddr::Emit(MCStreamer *MCOS, MCDwarfLineTableParams Params, + int64_t LineDelta, uint64_t AddrDelta) { MCContext &Context = MCOS->getContext(); SmallString<256> Tmp; raw_svector_ostream OS(Tmp); - MCDwarfLineAddr::Encode(Context, LineDelta, AddrDelta, OS); + MCDwarfLineAddr::Encode(Context, Params, LineDelta, AddrDelta, OS); MCOS->EmitBytes(OS.str()); } +/// Given a special op, return the address skip amount (in units of +/// DWARF2_LINE_MIN_INSN_LENGTH). +static uint64_t SpecialAddr(MCDwarfLineTableParams Params, uint64_t op) { + return (op - Params.DWARF2LineOpcodeBase) / Params.DWARF2LineRange; +} + /// Utility function to encode a Dwarf pair of LineDelta and AddrDeltas. -void MCDwarfLineAddr::Encode(MCContext &Context, int64_t LineDelta, - uint64_t AddrDelta, raw_ostream &OS) { +void MCDwarfLineAddr::Encode(MCContext &Context, MCDwarfLineTableParams Params, + int64_t LineDelta, uint64_t AddrDelta, + raw_ostream &OS) { uint64_t Temp, Opcode; bool NeedCopy = false; + // The maximum address skip amount that can be encoded with a special op. + uint64_t MaxSpecialAddrDelta = SpecialAddr(Params, 255); + // Scale the address delta by the minimum instruction length. AddrDelta = ScaleAddrDelta(Context, AddrDelta); @@ -438,7 +435,7 @@ void MCDwarfLineAddr::Encode(MCContext &Context, int64_t LineDelta, // DW_LNE_end_sequence. We cannot use special opcodes here, since we want the // end_sequence to emit the matrix entry. if (LineDelta == INT64_MAX) { - if (AddrDelta == MAX_SPECIAL_ADDR_DELTA) + if (AddrDelta == MaxSpecialAddrDelta) OS << char(dwarf::DW_LNS_const_add_pc); else if (AddrDelta) { OS << char(dwarf::DW_LNS_advance_pc); @@ -451,16 +448,16 @@ void MCDwarfLineAddr::Encode(MCContext &Context, int64_t LineDelta, } // Bias the line delta by the base. - Temp = LineDelta - DWARF2_LINE_BASE; + Temp = LineDelta - Params.DWARF2LineBase; // If the line increment is out of range of a special opcode, we must encode // it with DW_LNS_advance_line. - if (Temp >= DWARF2_LINE_RANGE) { + if (Temp >= Params.DWARF2LineRange) { OS << char(dwarf::DW_LNS_advance_line); encodeSLEB128(LineDelta, OS); LineDelta = 0; - Temp = 0 - DWARF2_LINE_BASE; + Temp = 0 - Params.DWARF2LineBase; NeedCopy = true; } @@ -471,19 +468,19 @@ void MCDwarfLineAddr::Encode(MCContext &Context, int64_t LineDelta, } // Bias the opcode by the special opcode base. - Temp += DWARF2_LINE_OPCODE_BASE; + Temp += Params.DWARF2LineOpcodeBase; // Avoid overflow when addr_delta is large. - if (AddrDelta < 256 + MAX_SPECIAL_ADDR_DELTA) { + if (AddrDelta < 256 + MaxSpecialAddrDelta) { // Try using a special opcode. - Opcode = Temp + AddrDelta * DWARF2_LINE_RANGE; + Opcode = Temp + AddrDelta * Params.DWARF2LineRange; if (Opcode <= 255) { OS << char(Opcode); return; } // Try using DW_LNS_const_add_pc followed by special op. - Opcode = Temp + (AddrDelta - MAX_SPECIAL_ADDR_DELTA) * DWARF2_LINE_RANGE; + Opcode = Temp + (AddrDelta - MaxSpecialAddrDelta) * Params.DWARF2LineRange; if (Opcode <= 255) { OS << char(dwarf::DW_LNS_const_add_pc); OS << char(Opcode); @@ -517,10 +514,14 @@ static void EmitGenDwarfAbbrev(MCStreamer *MCOS) { MCOS->EmitULEB128IntValue(1); MCOS->EmitULEB128IntValue(dwarf::DW_TAG_compile_unit); MCOS->EmitIntValue(dwarf::DW_CHILDREN_yes, 1); - EmitAbbrev(MCOS, dwarf::DW_AT_stmt_list, dwarf::DW_FORM_data4); - if (MCOS->getContext().getGenDwarfSectionSyms().size() > 1 && - MCOS->getContext().getDwarfVersion() >= 3) { - EmitAbbrev(MCOS, dwarf::DW_AT_ranges, dwarf::DW_FORM_data4); + EmitAbbrev(MCOS, dwarf::DW_AT_stmt_list, + context.getDwarfVersion() >= 4 ? dwarf::DW_FORM_sec_offset + : dwarf::DW_FORM_data4); + if (context.getGenDwarfSectionSyms().size() > 1 && + context.getDwarfVersion() >= 3) { + EmitAbbrev(MCOS, dwarf::DW_AT_ranges, + context.getDwarfVersion() >= 4 ? dwarf::DW_FORM_sec_offset + : dwarf::DW_FORM_data4); } else { EmitAbbrev(MCOS, dwarf::DW_AT_low_pc, dwarf::DW_FORM_addr); EmitAbbrev(MCOS, dwarf::DW_AT_high_pc, dwarf::DW_FORM_addr); @@ -845,7 +846,7 @@ void MCGenDwarfInfo::Emit(MCStreamer *MCOS) { LineSectionSymbol = MCOS->getDwarfLineTableSymbol(0); MCSymbol *AbbrevSectionSymbol = nullptr; MCSymbol *InfoSectionSymbol = nullptr; - MCSymbol *RangesSectionSymbol = NULL; + MCSymbol *RangesSectionSymbol = nullptr; // Create end symbols for each section, and remove empty sections MCOS->getContext().finalizeDwarfSections(*MCOS); @@ -998,38 +999,29 @@ static void EmitPersonality(MCStreamer &streamer, const MCSymbol &symbol, } namespace { - class FrameEmitterImpl { - int CFAOffset; - int InitialCFAOffset; - bool IsEH; - const MCSymbol *SectionStart; - public: - FrameEmitterImpl(bool isEH) - : CFAOffset(0), InitialCFAOffset(0), IsEH(isEH), SectionStart(nullptr) { - } - - void setSectionStart(const MCSymbol *Label) { SectionStart = Label; } - - /// Emit the unwind information in a compact way. - void EmitCompactUnwind(MCObjectStreamer &streamer, - const MCDwarfFrameInfo &frame); - - const MCSymbol &EmitCIE(MCObjectStreamer &streamer, - const MCSymbol *personality, - unsigned personalityEncoding, - const MCSymbol *lsda, - bool IsSignalFrame, - unsigned lsdaEncoding, - bool IsSimple); - MCSymbol *EmitFDE(MCObjectStreamer &streamer, - const MCSymbol &cieStart, - const MCDwarfFrameInfo &frame); - void EmitCFIInstructions(MCObjectStreamer &streamer, - ArrayRef<MCCFIInstruction> Instrs, - MCSymbol *BaseLabel); - void EmitCFIInstruction(MCObjectStreamer &Streamer, - const MCCFIInstruction &Instr); - }; +class FrameEmitterImpl { + int CFAOffset = 0; + int InitialCFAOffset = 0; + bool IsEH; + MCObjectStreamer &Streamer; + +public: + FrameEmitterImpl(bool IsEH, MCObjectStreamer &Streamer) + : IsEH(IsEH), Streamer(Streamer) {} + + /// Emit the unwind information in a compact way. + void EmitCompactUnwind(const MCDwarfFrameInfo &frame); + + const MCSymbol &EmitCIE(const MCSymbol *personality, + unsigned personalityEncoding, const MCSymbol *lsda, + bool IsSignalFrame, unsigned lsdaEncoding, + bool IsSimple); + void EmitFDE(const MCSymbol &cieStart, const MCDwarfFrameInfo &frame, + bool LastInSection, const MCSymbol &SectionStart); + void EmitCFIInstructions(ArrayRef<MCCFIInstruction> Instrs, + MCSymbol *BaseLabel); + void EmitCFIInstruction(const MCCFIInstruction &Instr); +}; } // end anonymous namespace @@ -1037,8 +1029,7 @@ static void emitEncodingByte(MCObjectStreamer &Streamer, unsigned Encoding) { Streamer.EmitIntValue(Encoding, 1); } -void FrameEmitterImpl::EmitCFIInstruction(MCObjectStreamer &Streamer, - const MCCFIInstruction &Instr) { +void FrameEmitterImpl::EmitCFIInstruction(const MCCFIInstruction &Instr) { int dataAlignmentFactor = getDataAlignmentFactor(Streamer); auto *MRI = Streamer.getContext().getRegisterInfo(); @@ -1150,6 +1141,11 @@ void FrameEmitterImpl::EmitCFIInstruction(MCObjectStreamer &Streamer, Streamer.EmitIntValue(dwarf::DW_CFA_restore | Reg, 1); return; } + case MCCFIInstruction::OpGnuArgsSize: { + Streamer.EmitIntValue(dwarf::DW_CFA_GNU_args_size, 1); + Streamer.EmitULEB128IntValue(Instr.getOffset()); + return; + } case MCCFIInstruction::OpEscape: Streamer.EmitBytes(Instr.getValues()); return; @@ -1158,8 +1154,7 @@ void FrameEmitterImpl::EmitCFIInstruction(MCObjectStreamer &Streamer, } /// Emit frame instructions to describe the layout of the frame. -void FrameEmitterImpl::EmitCFIInstructions(MCObjectStreamer &streamer, - ArrayRef<MCCFIInstruction> Instrs, +void FrameEmitterImpl::EmitCFIInstructions(ArrayRef<MCCFIInstruction> Instrs, MCSymbol *BaseLabel) { for (unsigned i = 0, N = Instrs.size(); i < N; ++i) { const MCCFIInstruction &Instr = Instrs[i]; @@ -1171,18 +1166,17 @@ void FrameEmitterImpl::EmitCFIInstructions(MCObjectStreamer &streamer, if (BaseLabel && Label) { MCSymbol *ThisSym = Label; if (ThisSym != BaseLabel) { - streamer.EmitDwarfAdvanceFrameAddr(BaseLabel, ThisSym); + Streamer.EmitDwarfAdvanceFrameAddr(BaseLabel, ThisSym); BaseLabel = ThisSym; } } - EmitCFIInstruction(streamer, Instr); + EmitCFIInstruction(Instr); } } /// Emit the unwind information in a compact way. -void FrameEmitterImpl::EmitCompactUnwind(MCObjectStreamer &Streamer, - const MCDwarfFrameInfo &Frame) { +void FrameEmitterImpl::EmitCompactUnwind(const MCDwarfFrameInfo &Frame) { MCContext &Context = Streamer.getContext(); const MCObjectFileInfo *MOFI = Context.getObjectFileInfo(); @@ -1254,39 +1248,39 @@ static unsigned getCIEVersion(bool IsEH, unsigned DwarfVersion) { case 3: return 3; case 4: + case 5: return 4; } llvm_unreachable("Unknown version"); } -const MCSymbol &FrameEmitterImpl::EmitCIE(MCObjectStreamer &streamer, - const MCSymbol *personality, +const MCSymbol &FrameEmitterImpl::EmitCIE(const MCSymbol *personality, unsigned personalityEncoding, const MCSymbol *lsda, bool IsSignalFrame, unsigned lsdaEncoding, bool IsSimple) { - MCContext &context = streamer.getContext(); + MCContext &context = Streamer.getContext(); const MCRegisterInfo *MRI = context.getRegisterInfo(); const MCObjectFileInfo *MOFI = context.getObjectFileInfo(); MCSymbol *sectionStart = context.createTempSymbol(); - streamer.EmitLabel(sectionStart); + Streamer.EmitLabel(sectionStart); MCSymbol *sectionEnd = context.createTempSymbol(); // Length - const MCExpr *Length = MakeStartMinusEndExpr(streamer, *sectionStart, - *sectionEnd, 4); - emitAbsValue(streamer, Length, 4); + const MCExpr *Length = + MakeStartMinusEndExpr(Streamer, *sectionStart, *sectionEnd, 4); + emitAbsValue(Streamer, Length, 4); // CIE ID unsigned CIE_ID = IsEH ? 0 : -1; - streamer.EmitIntValue(CIE_ID, 4); + Streamer.EmitIntValue(CIE_ID, 4); // Version uint8_t CIEVersion = getCIEVersion(IsEH, context.getDwarfVersion()); - streamer.EmitIntValue(CIEVersion, 1); + Streamer.EmitIntValue(CIEVersion, 1); // Augmentation String SmallString<8> Augmentation; @@ -1299,31 +1293,31 @@ const MCSymbol &FrameEmitterImpl::EmitCIE(MCObjectStreamer &streamer, Augmentation += "R"; if (IsSignalFrame) Augmentation += "S"; - streamer.EmitBytes(Augmentation); + Streamer.EmitBytes(Augmentation); } - streamer.EmitIntValue(0, 1); + Streamer.EmitIntValue(0, 1); if (CIEVersion >= 4) { // Address Size - streamer.EmitIntValue(context.getAsmInfo()->getPointerSize(), 1); + Streamer.EmitIntValue(context.getAsmInfo()->getPointerSize(), 1); // Segment Descriptor Size - streamer.EmitIntValue(0, 1); + Streamer.EmitIntValue(0, 1); } // Code Alignment Factor - streamer.EmitULEB128IntValue(context.getAsmInfo()->getMinInstAlignment()); + Streamer.EmitULEB128IntValue(context.getAsmInfo()->getMinInstAlignment()); // Data Alignment Factor - streamer.EmitSLEB128IntValue(getDataAlignmentFactor(streamer)); + Streamer.EmitSLEB128IntValue(getDataAlignmentFactor(Streamer)); // Return Address Register if (CIEVersion == 1) { assert(MRI->getRARegister() <= 255 && "DWARF 2 encodes return_address_register in one byte"); - streamer.EmitIntValue(MRI->getDwarfRegNum(MRI->getRARegister(), IsEH), 1); + Streamer.EmitIntValue(MRI->getDwarfRegNum(MRI->getRARegister(), IsEH), 1); } else { - streamer.EmitULEB128IntValue( + Streamer.EmitULEB128IntValue( MRI->getDwarfRegNum(MRI->getRARegister(), IsEH)); } @@ -1335,28 +1329,28 @@ const MCSymbol &FrameEmitterImpl::EmitCIE(MCObjectStreamer &streamer, // Personality Encoding augmentationLength += 1; // Personality - augmentationLength += getSizeForEncoding(streamer, personalityEncoding); + 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 - emitEncodingByte(streamer, personalityEncoding); + emitEncodingByte(Streamer, personalityEncoding); // Personality - EmitPersonality(streamer, *personality, personalityEncoding); + EmitPersonality(Streamer, *personality, personalityEncoding); } if (lsda) - emitEncodingByte(streamer, lsdaEncoding); + emitEncodingByte(Streamer, lsdaEncoding); // Encoding of the FDE pointers - emitEncodingByte(streamer, MOFI->getFDEEncoding()); + emitEncodingByte(Streamer, MOFI->getFDEEncoding()); } // Initial Instructions @@ -1365,22 +1359,23 @@ const MCSymbol &FrameEmitterImpl::EmitCIE(MCObjectStreamer &streamer, if (!IsSimple) { const std::vector<MCCFIInstruction> &Instructions = MAI->getInitialFrameState(); - EmitCFIInstructions(streamer, Instructions, nullptr); + EmitCFIInstructions(Instructions, nullptr); } InitialCFAOffset = CFAOffset; // Padding - streamer.EmitValueToAlignment(IsEH ? 4 : MAI->getPointerSize()); + Streamer.EmitValueToAlignment(IsEH ? 4 : MAI->getPointerSize()); - streamer.EmitLabel(sectionEnd); + Streamer.EmitLabel(sectionEnd); return *sectionStart; } -MCSymbol *FrameEmitterImpl::EmitFDE(MCObjectStreamer &streamer, - const MCSymbol &cieStart, - const MCDwarfFrameInfo &frame) { - MCContext &context = streamer.getContext(); +void FrameEmitterImpl::EmitFDE(const MCSymbol &cieStart, + const MCDwarfFrameInfo &frame, + bool LastInSection, + const MCSymbol &SectionStart) { + MCContext &context = Streamer.getContext(); MCSymbol *fdeStart = context.createTempSymbol(); MCSymbol *fdeEnd = context.createTempSymbol(); const MCObjectFileInfo *MOFI = context.getObjectFileInfo(); @@ -1388,107 +1383,103 @@ MCSymbol *FrameEmitterImpl::EmitFDE(MCObjectStreamer &streamer, CFAOffset = InitialCFAOffset; // Length - const MCExpr *Length = MakeStartMinusEndExpr(streamer, *fdeStart, *fdeEnd, 0); - emitAbsValue(streamer, Length, 4); + const MCExpr *Length = MakeStartMinusEndExpr(Streamer, *fdeStart, *fdeEnd, 0); + emitAbsValue(Streamer, Length, 4); - streamer.EmitLabel(fdeStart); + Streamer.EmitLabel(fdeStart); // CIE Pointer const MCAsmInfo *asmInfo = context.getAsmInfo(); if (IsEH) { - const MCExpr *offset = MakeStartMinusEndExpr(streamer, cieStart, *fdeStart, - 0); - emitAbsValue(streamer, offset, 4); + const MCExpr *offset = + MakeStartMinusEndExpr(Streamer, cieStart, *fdeStart, 0); + emitAbsValue(Streamer, offset, 4); } else if (!asmInfo->doesDwarfUseRelocationsAcrossSections()) { - const MCExpr *offset = MakeStartMinusEndExpr(streamer, *SectionStart, - cieStart, 0); - emitAbsValue(streamer, offset, 4); + const MCExpr *offset = + MakeStartMinusEndExpr(Streamer, SectionStart, cieStart, 0); + emitAbsValue(Streamer, offset, 4); } else { - streamer.EmitSymbolValue(&cieStart, 4); + Streamer.EmitSymbolValue(&cieStart, 4); } // PC Begin unsigned PCEncoding = IsEH ? MOFI->getFDEEncoding() : (unsigned)dwarf::DW_EH_PE_absptr; - unsigned PCSize = getSizeForEncoding(streamer, PCEncoding); - emitFDESymbol(streamer, *frame.Begin, PCEncoding, IsEH); + unsigned PCSize = getSizeForEncoding(Streamer, PCEncoding); + emitFDESymbol(Streamer, *frame.Begin, PCEncoding, IsEH); // PC Range - const MCExpr *Range = MakeStartMinusEndExpr(streamer, *frame.Begin, - *frame.End, 0); - emitAbsValue(streamer, Range, PCSize); + const MCExpr *Range = + MakeStartMinusEndExpr(Streamer, *frame.Begin, *frame.End, 0); + emitAbsValue(Streamer, Range, PCSize); if (IsEH) { // Augmentation Data Length unsigned augmentationLength = 0; if (frame.Lsda) - augmentationLength += getSizeForEncoding(streamer, frame.LsdaEncoding); + augmentationLength += getSizeForEncoding(Streamer, frame.LsdaEncoding); - streamer.EmitULEB128IntValue(augmentationLength); + Streamer.EmitULEB128IntValue(augmentationLength); // Augmentation Data if (frame.Lsda) - emitFDESymbol(streamer, *frame.Lsda, frame.LsdaEncoding, true); + emitFDESymbol(Streamer, *frame.Lsda, frame.LsdaEncoding, true); } // Call Frame Instructions - EmitCFIInstructions(streamer, frame.Instructions, frame.Begin); + EmitCFIInstructions(frame.Instructions, frame.Begin); // Padding - streamer.EmitValueToAlignment(PCSize); + // The size of a .eh_frame section has to be a multiple of the alignment + // since a null CIE is interpreted as the end. Old systems overaligned + // .eh_frame, so we do too and account for it in the last FDE. + unsigned Align = LastInSection ? asmInfo->getPointerSize() : PCSize; + Streamer.EmitValueToAlignment(Align); - return fdeEnd; + Streamer.EmitLabel(fdeEnd); } namespace { - struct CIEKey { - static const CIEKey getEmptyKey() { - return CIEKey(nullptr, 0, -1, false, false); - } - static const CIEKey getTombstoneKey() { - return CIEKey(nullptr, -1, 0, false, false); - } +struct CIEKey { + static const CIEKey getEmptyKey() { + return CIEKey(nullptr, 0, -1, false, false); + } + static const CIEKey getTombstoneKey() { + return CIEKey(nullptr, -1, 0, false, false); + } - CIEKey(const MCSymbol *Personality_, unsigned PersonalityEncoding_, - unsigned LsdaEncoding_, bool IsSignalFrame_, bool IsSimple_) - : Personality(Personality_), PersonalityEncoding(PersonalityEncoding_), - LsdaEncoding(LsdaEncoding_), IsSignalFrame(IsSignalFrame_), - IsSimple(IsSimple_) {} - const MCSymbol *Personality; - unsigned PersonalityEncoding; - unsigned LsdaEncoding; - bool IsSignalFrame; - bool IsSimple; - }; -} + CIEKey(const MCSymbol *Personality, unsigned PersonalityEncoding, + unsigned LsdaEncoding, bool IsSignalFrame, bool IsSimple) + : Personality(Personality), PersonalityEncoding(PersonalityEncoding), + LsdaEncoding(LsdaEncoding), IsSignalFrame(IsSignalFrame), + IsSimple(IsSimple) {} + const MCSymbol *Personality; + unsigned PersonalityEncoding; + unsigned LsdaEncoding; + bool IsSignalFrame; + bool IsSimple; +}; +} // anonymous namespace namespace llvm { - template <> - struct DenseMapInfo<CIEKey> { - static CIEKey getEmptyKey() { - return CIEKey::getEmptyKey(); - } - static CIEKey getTombstoneKey() { - return CIEKey::getTombstoneKey(); - } - static unsigned getHashValue(const CIEKey &Key) { - return static_cast<unsigned>(hash_combine(Key.Personality, - Key.PersonalityEncoding, - Key.LsdaEncoding, - Key.IsSignalFrame, - Key.IsSimple)); - } - static bool isEqual(const CIEKey &LHS, - const CIEKey &RHS) { - return LHS.Personality == RHS.Personality && - LHS.PersonalityEncoding == RHS.PersonalityEncoding && - LHS.LsdaEncoding == RHS.LsdaEncoding && - LHS.IsSignalFrame == RHS.IsSignalFrame && - LHS.IsSimple == RHS.IsSimple; - } - }; -} +template <> struct DenseMapInfo<CIEKey> { + static CIEKey getEmptyKey() { return CIEKey::getEmptyKey(); } + static CIEKey getTombstoneKey() { return CIEKey::getTombstoneKey(); } + static unsigned getHashValue(const CIEKey &Key) { + return static_cast<unsigned>( + hash_combine(Key.Personality, Key.PersonalityEncoding, Key.LsdaEncoding, + Key.IsSignalFrame, Key.IsSimple)); + } + static bool isEqual(const CIEKey &LHS, const CIEKey &RHS) { + return LHS.Personality == RHS.Personality && + LHS.PersonalityEncoding == RHS.PersonalityEncoding && + LHS.LsdaEncoding == RHS.LsdaEncoding && + LHS.IsSignalFrame == RHS.IsSignalFrame && + LHS.IsSimple == RHS.IsSimple; + } +}; +} // namespace llvm void MCDwarfFrameEmitter::Emit(MCObjectStreamer &Streamer, MCAsmBackend *MAB, bool IsEH) { @@ -1496,7 +1487,7 @@ void MCDwarfFrameEmitter::Emit(MCObjectStreamer &Streamer, MCAsmBackend *MAB, MCContext &Context = Streamer.getContext(); const MCObjectFileInfo *MOFI = Context.getObjectFileInfo(); - FrameEmitterImpl Emitter(IsEH); + FrameEmitterImpl Emitter(IsEH, Streamer); ArrayRef<MCDwarfFrameInfo> FrameArray = Streamer.getDwarfFrameInfos(); // Emit the compact unwind info if available. @@ -1514,7 +1505,7 @@ void MCDwarfFrameEmitter::Emit(MCObjectStreamer &Streamer, MCAsmBackend *MAB, NeedsEHFrameSection |= Frame.CompactUnwindEncoding == MOFI->getCompactUnwindDwarfEHFrameOnly(); - Emitter.EmitCompactUnwind(Streamer, Frame); + Emitter.EmitCompactUnwind(Frame); } } @@ -1527,23 +1518,15 @@ void MCDwarfFrameEmitter::Emit(MCObjectStreamer &Streamer, MCAsmBackend *MAB, Streamer.SwitchSection(&Section); MCSymbol *SectionStart = Context.createTempSymbol(); Streamer.EmitLabel(SectionStart); - Emitter.setSectionStart(SectionStart); - MCSymbol *FDEEnd = nullptr; DenseMap<CIEKey, const MCSymbol *> CIEStarts; const MCSymbol *DummyDebugKey = nullptr; - NeedsEHFrameSection = !MOFI->getSupportsCompactUnwindWithoutEHFrame(); - for (unsigned i = 0, n = FrameArray.size(); i < n; ++i) { - const MCDwarfFrameInfo &Frame = FrameArray[i]; - - // Emit the label from the previous iteration - if (FDEEnd) { - Streamer.EmitLabel(FDEEnd); - FDEEnd = nullptr; - } - - if (!NeedsEHFrameSection && Frame.CompactUnwindEncoding != + bool CanOmitDwarf = MOFI->getOmitDwarfIfHaveCompactUnwind(); + for (auto I = FrameArray.begin(), E = FrameArray.end(); I != E;) { + const MCDwarfFrameInfo &Frame = *I; + ++I; + if (CanOmitDwarf && Frame.CompactUnwindEncoding != MOFI->getCompactUnwindDwarfEHFrameOnly()) // Don't generate an EH frame if we don't need one. I.e., it's taken care // of by the compact unwind encoding. @@ -1553,18 +1536,12 @@ void MCDwarfFrameEmitter::Emit(MCObjectStreamer &Streamer, MCAsmBackend *MAB, Frame.LsdaEncoding, Frame.IsSignalFrame, Frame.IsSimple); const MCSymbol *&CIEStart = IsEH ? CIEStarts[Key] : DummyDebugKey; if (!CIEStart) - CIEStart = &Emitter.EmitCIE(Streamer, Frame.Personality, - Frame.PersonalityEncoding, Frame.Lsda, - Frame.IsSignalFrame, - Frame.LsdaEncoding, - Frame.IsSimple); + CIEStart = &Emitter.EmitCIE(Frame.Personality, Frame.PersonalityEncoding, + Frame.Lsda, Frame.IsSignalFrame, + Frame.LsdaEncoding, Frame.IsSimple); - FDEEnd = Emitter.EmitFDE(Streamer, *CIEStart, Frame); + Emitter.EmitFDE(*CIEStart, Frame, I == E, *SectionStart); } - - Streamer.EmitValueToAlignment(Context.getAsmInfo()->getPointerSize()); - if (FDEEnd) - Streamer.EmitLabel(FDEEnd); } void MCDwarfFrameEmitter::EmitAdvanceLoc(MCObjectStreamer &Streamer, |