From 17a0650641915ffc430dfc78e2d4e2e27b884333 Mon Sep 17 00:00:00 2001 From: Daniel Dunbar Date: Fri, 19 Mar 2010 07:09:18 +0000 Subject: [PATCH] MC/Mach-O: Lift relocation emission logic a bit higher to separate evaluation / relocation handling from the actual .o writing. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@98942 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/MC/MCAssembler.cpp | 133 ++++++++++++++++++++++++----------------- 1 file changed, 77 insertions(+), 56 deletions(-) diff --git a/lib/MC/MCAssembler.cpp b/lib/MC/MCAssembler.cpp index e88e5749383..7b4512e7d4e 100644 --- a/lib/MC/MCAssembler.cpp +++ b/lib/MC/MCAssembler.cpp @@ -170,6 +170,27 @@ class MachObjectWriter { unsigned Is64Bit : 1; unsigned IsLSB : 1; + /// @name Relocation Data + /// @{ + + struct MachRelocationEntry { + uint32_t Word0; + uint32_t Word1; + }; + + llvm::DenseMap > Relocations; + + /// @} + /// @name Symbol Table Data + + SmallString<256> StringTable; + std::vector LocalSymbolData; + std::vector ExternalSymbolData; + std::vector UndefinedSymbolData; + + /// @} + public: MachObjectWriter(raw_ostream &_OS, bool _Is64Bit, bool _IsLSB = true) : OS(_OS), Is64Bit(_Is64Bit), IsLSB(_IsLSB) { @@ -464,14 +485,9 @@ public: Write32(Address); } - struct MachRelocationEntry { - uint32_t Word0; - uint32_t Word1; - }; - void ComputeScatteredRelocationInfo(MCAssembler &Asm, MCFragment &Fragment, - MCAsmFixup &Fixup, - const MCValue &Target, - std::vector &Relocs) { + void RecordScatteredRelocation(MCAssembler &Asm, MCFragment &Fragment, + const MCAsmFixup &Fixup, MCValue Target, + uint64_t &FixedValue) { uint32_t Address = Fragment.getOffset() + Fixup.Offset; unsigned IsPCRel = isFixupKindPCRel(Fixup.Kind); unsigned Log2Size = getFixupKindLog2Size(Fixup.Kind); @@ -504,15 +520,7 @@ public: Value2 = B_SD->getAddress(); } - MachRelocationEntry MRE; - MRE.Word0 = ((Address << 0) | - (Type << 24) | - (Log2Size << 28) | - (IsPCRel << 30) | - RF_Scattered); - MRE.Word1 = Value; - Relocs.push_back(MRE); - + // Relocations are written out in reverse order, so the PAIR comes first. if (Type == RIT_Difference || Type == RIT_LocalDifference) { MachRelocationEntry MRE; MRE.Word0 = ((0 << 0) | @@ -521,24 +529,25 @@ public: (IsPCRel << 30) | RF_Scattered); MRE.Word1 = Value2; - Relocs.push_back(MRE); + Relocations[Fragment.getParent()].push_back(MRE); } + + MachRelocationEntry MRE; + MRE.Word0 = ((Address << 0) | + (Type << 24) | + (Log2Size << 28) | + (IsPCRel << 30) | + RF_Scattered); + MRE.Word1 = Value; + Relocations[Fragment.getParent()].push_back(MRE); } - void ComputeRelocationInfo(MCAssembler &Asm, MCDataFragment &Fragment, - MCAsmFixup &Fixup, - std::vector &Relocs) { + void RecordRelocation(MCAssembler &Asm, MCDataFragment &Fragment, + const MCAsmFixup &Fixup, MCValue Target, + uint64_t &FixedValue) { unsigned IsPCRel = isFixupKindPCRel(Fixup.Kind); unsigned Log2Size = getFixupKindLog2Size(Fixup.Kind); - // FIXME: Share layout object. - MCAsmLayout Layout(Asm); - - // Evaluate the fixup; if the value was resolved, no relocation is needed. - MCValue Target; - if (Asm.EvaluateFixup(Layout, Fixup, &Fragment, Target, Fixup.FixedValue)) - return; - // If this is a difference or a defined symbol plus an offset, then we need // a scattered relocation entry. uint32_t Offset = Target.getConstant(); @@ -546,9 +555,10 @@ public: Offset += 1 << Log2Size; if (Target.getSymB() || (Target.getSymA() && !Target.getSymA()->getSymbol().isUndefined() && - Offset)) - return ComputeScatteredRelocationInfo(Asm, Fragment, Fixup, Target, - Relocs); + Offset)) { + RecordScatteredRelocation(Asm, Fragment, Fixup, Target, FixedValue); + return; + } // See . uint32_t Address = Fragment.getOffset() + Fixup.Offset; @@ -596,7 +606,20 @@ public: (Log2Size << 25) | (IsExtern << 27) | (Type << 28)); - Relocs.push_back(MRE); + Relocations[Fragment.getParent()].push_back(MRE); + } + + void ComputeRelocationInfo(MCAssembler &Asm, MCDataFragment &Fragment, + MCAsmFixup &Fixup) { + // FIXME: Share layout object. + MCAsmLayout Layout(Asm); + + // Evaluate the fixup; if the value was resolved, no relocation is needed. + MCValue Target; + if (Asm.EvaluateFixup(Layout, Fixup, &Fragment, Target, Fixup.FixedValue)) + return; + + RecordRelocation(Asm, Fragment, Fixup, Target, Fixup.FixedValue); } void BindIndirectSymbols(MCAssembler &Asm) { @@ -820,32 +843,24 @@ public: WriteSegmentLoadCommand(NumSections, VMSize, SectionDataStart, SectionDataSize); - // ... and then the section headers. - // - // We also compute the section relocations while we do this. Note that - // computing relocation info will also update the fixup to have the correct - // value; this will overwrite the appropriate data in the fragment when it - // is written. - std::vector RelocInfos; - uint64_t RelocTableEnd = SectionDataStart + SectionDataFileSize; for (MCAssembler::iterator it = Asm.begin(), ie = Asm.end(); it != ie; ++it) { MCSectionData &SD = *it; - - // The assembler writes relocations in the reverse order they were seen. - // - // FIXME: It is probably more complicated than this. - unsigned NumRelocsStart = RelocInfos.size(); - for (MCSectionData::reverse_iterator it2 = SD.rbegin(), - ie2 = SD.rend(); it2 != ie2; ++it2) + for (MCSectionData::iterator it2 = SD.begin(), + ie2 = SD.end(); it2 != ie2; ++it2) if (MCDataFragment *DF = dyn_cast(&*it2)) for (unsigned i = 0, e = DF->fixup_size(); i != e; ++i) - ComputeRelocationInfo(Asm, *DF, DF->getFixups()[e - i - 1], - RelocInfos); + ComputeRelocationInfo(Asm, *DF, DF->getFixups()[i]); + } - unsigned NumRelocs = RelocInfos.size() - NumRelocsStart; - uint64_t SectionStart = SectionDataStart + SD.getAddress(); - WriteSection(SD, SectionStart, RelocTableEnd, NumRelocs); + // ... and then the section headers. + uint64_t RelocTableEnd = SectionDataStart + SectionDataFileSize; + for (MCAssembler::iterator it = Asm.begin(), + ie = Asm.end(); it != ie; ++it) { + std::vector &Relocs = Relocations[it]; + unsigned NumRelocs = Relocs.size(); + uint64_t SectionStart = SectionDataStart + it->getAddress(); + WriteSection(*it, SectionStart, RelocTableEnd, NumRelocs); RelocTableEnd += NumRelocs * RelocationInfoSize; } @@ -891,9 +906,15 @@ public: WriteZeros(SectionDataPadding); // Write the relocation entries. - for (unsigned i = 0, e = RelocInfos.size(); i != e; ++i) { - Write32(RelocInfos[i].Word0); - Write32(RelocInfos[i].Word1); + for (MCAssembler::iterator it = Asm.begin(), + ie = Asm.end(); it != ie; ++it) { + // Write the section relocation entries, in reverse order to match 'as' + // (approximately, the exact algorithm is more complicated than this). + std::vector &Relocs = Relocations[it]; + for (unsigned i = 0, e = Relocs.size(); i != e; ++i) { + Write32(Relocs[e - i - 1].Word0); + Write32(Relocs[e - i - 1].Word1); + } } // Write the symbol table data, if used. -- 2.34.1