From 4d2d9c07a535a19dd86e733ce5bd7c1196320198 Mon Sep 17 00:00:00 2001 From: Rafael Espindola Date: Fri, 18 Nov 2016 19:02:15 +0000 Subject: [PATCH] Simplify handling of SHF_LINK_ORDER. It seems a lot simpler to just sort the sections and let the relocations do the rest. llvm-svn: 287365 --- lld/ELF/OutputSections.cpp | 16 +++++++++++++ lld/ELF/Writer.cpp | 60 ---------------------------------------------- 2 files changed, 16 insertions(+), 60 deletions(-) diff --git a/lld/ELF/OutputSections.cpp b/lld/ELF/OutputSections.cpp index cdbe628..b04d969 100644 --- a/lld/ELF/OutputSections.cpp +++ b/lld/ELF/OutputSections.cpp @@ -181,8 +181,24 @@ OutputSection::OutputSection(StringRef Name, uint32_t Type, uintX_t Flags) this->Entsize = getEntsize(Type); } +template +static bool compareByFilePosition(InputSection *A, + InputSection *B) { + auto *LA = cast>(A->getLinkOrderDep()); + auto *LB = cast>(B->getLinkOrderDep()); + OutputSectionBase *AOut = LA->OutSec; + OutputSectionBase *BOut = LB->OutSec; + if (AOut != BOut) + return AOut->SectionIndex < BOut->SectionIndex; + return LA->OutSecOff < LB->OutSecOff; +} + template void OutputSection::finalize() { if ((this->Flags & SHF_LINK_ORDER) && !this->Sections.empty()) { + std::sort(Sections.begin(), Sections.end(), compareByFilePosition); + Size = 0; + assignOffsets(); + // We must preserve the link order dependency of sections with the // SHF_LINK_ORDER flag. The dependency is indicated by the sh_link field. We // need to translate the InputSection sh_link to the OutputSection sh_link, diff --git a/lld/ELF/Writer.cpp b/lld/ELF/Writer.cpp index 35a792a..7744a60 100644 --- a/lld/ELF/Writer.cpp +++ b/lld/ELF/Writer.cpp @@ -1478,61 +1478,6 @@ template void Writer::writeSectionsBinary() { Sec->writeTo(Buf + Sec->Offset); } -// Convert the .ARM.exidx table entries that use relative PREL31 offsets to -// Absolute addresses. This form is internal to LLD and is only used to -// make reordering the table simpler. -static void ARMExidxEntryPrelToAbs(uint8_t *Loc, uint64_t EntryVA) { - uint64_t Addr = Target->getImplicitAddend(Loc, R_ARM_PREL31) + EntryVA; - bool InlineEntry = - (read32le(Loc + 4) == 1 || (read32le(Loc + 4) & 0x80000000)); - if (InlineEntry) - // Set flag in unused bit of code address so that when we convert back we - // know which table entries to leave alone. - Addr |= 0x1; - else - write32le(Loc + 4, - Target->getImplicitAddend(Loc + 4, R_ARM_PREL31) + EntryVA + 4); - write32le(Loc, Addr); -} - -// Convert the .ARM.exidx table entries from the internal to LLD form using -// absolute addresses back to relative PREL31 offsets. -static void ARMExidxEntryAbsToPrel(uint8_t *Loc, uint64_t EntryVA) { - uint64_t Off = read32le(Loc) - EntryVA; - // ARMExidxEntryPreltoAbs sets bit 0 if the table entry has inline data - // that is not an address - bool InlineEntry = Off & 0x1; - Target->relocateOne(Loc, R_ARM_PREL31, Off & ~0x1); - if (!InlineEntry) - Target->relocateOne(Loc + 4, R_ARM_PREL31, - read32le(Loc + 4) - (EntryVA + 4)); -} - -// The table formed by the .ARM.exidx OutputSection has entries with two -// 4-byte fields: -// | PREL31 offset to function | Action to take for function | -// The table must be ordered in ascending virtual address of the functions -// identified by the first field of the table. Instead of using the -// SHF_LINK_ORDER dependency to reorder the sections prior to relocation we -// sort the table post-relocation. -// Ref: Exception handling ABI for the ARM architecture -static void sortARMExidx(uint8_t *Buf, uint64_t OutSecVA, uint64_t Size) { - struct ARMExidxEntry { - ulittle32_t Target; - ulittle32_t Action; - }; - ARMExidxEntry *Start = (ARMExidxEntry *)Buf; - size_t NumEnt = Size / sizeof(ARMExidxEntry); - for (uint64_t Off = 0; Off < Size; Off += 8) - ARMExidxEntryPrelToAbs(Buf + Off, OutSecVA + Off); - std::stable_sort(Start, Start + NumEnt, - [](const ARMExidxEntry &A, const ARMExidxEntry &B) { - return A.Target < B.Target; - }); - for (uint64_t Off = 0; Off < Size; Off += 8) - ARMExidxEntryAbsToPrel(Buf + Off, OutSecVA + Off); -} - // Write section contents to a mmap'ed file. template void Writer::writeSections() { uint8_t *Buf = Buffer->getBufferStart(); @@ -1556,11 +1501,6 @@ template void Writer::writeSections() { if (Sec != Out::Opd && Sec != Out::EhFrameHdr) Sec->writeTo(Buf + Sec->Offset); - OutputSectionBase *ARMExidx = findSection(".ARM.exidx"); - if (!Config->Relocatable) - if (auto *OS = dyn_cast_or_null>(ARMExidx)) - sortARMExidx(Buf + OS->Offset, OS->Addr, OS->Size); - // The .eh_frame_hdr depends on .eh_frame section contents, therefore // it should be written after .eh_frame is written. if (!Out::EhFrame->empty() && Out::EhFrameHdr) -- 2.7.4