Index: ELF/Writer.cpp =================================================================== --- ELF/Writer.cpp +++ ELF/Writer.cpp @@ -28,10 +28,6 @@ using namespace lld; using namespace lld::elf; -// Usually there are 2 dummies sections: ELF header and program header. -// Relocatable output does not require program headers to be created. -unsigned dummySectionsNum() { return Config->Relocatable ? 1 : 2; } - namespace { // The writer writes a SymbolTable result to a file. template class Writer { @@ -76,6 +72,7 @@ void assignAddresses(); void assignFileOffsets(); void setPhdrs(); + void fixHeaders(); void fixSectionAlignments(); void fixAbsoluteSymbols(); void openFile(); @@ -103,14 +100,7 @@ BumpPtrAllocator Alloc; std::vector *> OutputSections; std::vector>> OwningSections; - - // We create a section for the ELF header and one for the program headers. - ArrayRef *> getSections() const { - return makeArrayRef(OutputSections).slice(dummySectionsNum()); - } - unsigned getNumSections() const { - return OutputSections.size() + 1 - dummySectionsNum(); - } + unsigned getNumSections() const { return OutputSections.size() + 1; } void addRelIpltSymbols(); void addStartEndSymbols(); @@ -224,6 +214,7 @@ assignFileOffsets(); } else { createPhdrs(); + fixHeaders(); fixSectionAlignments(); assignAddresses(); assignFileOffsets(); @@ -962,10 +953,6 @@ // Create output section objects and add them to OutputSections. template void Writer::createSections() { - OutputSections.push_back(Out::ElfHeader); - if (!Config->Relocatable) - OutputSections.push_back(Out::ProgramHeaders); - // Add .interp first because some loaders want to see that section // on the first page of the executable file when loaded into memory. if (needsInterpSection()) @@ -1054,7 +1041,7 @@ } } - for (OutputSectionBase *Sec : getSections()) + for (OutputSectionBase *Sec : OutputSections) Sec->assignOffsets(); // Now that we have defined all possible symbols including linker- @@ -1096,11 +1083,11 @@ std::stable_sort(OutputSections.begin(), OutputSections.end(), compareSections); - for (unsigned I = dummySectionsNum(), N = OutputSections.size(); I < N; ++I) - OutputSections[I]->SectionIndex = I + 1 - dummySectionsNum(); - - for (OutputSectionBase *Sec : getSections()) + unsigned I = 1; + for (OutputSectionBase *Sec : OutputSections) { + Sec->SectionIndex = I++; Sec->setSHName(Out::ShStrTab->addString(Sec->getName())); + } // Finalizers fix each section's size. // .dynsym is finalized early since that may fill up .gnu.hash. @@ -1268,6 +1255,7 @@ uintX_t Flags = PF_R; Phdr *Load = AddHdr(PT_LOAD, Flags); AddSec(*Load, Out::ElfHeader); + AddSec(*Load, Out::ProgramHeaders); Phdr TlsHdr(PT_TLS, PF_R); Phdr RelRo(PT_GNU_RELRO, PF_R); @@ -1355,11 +1343,23 @@ } } +// We should set file offsets and VAs for elf header and program headers +// sections. These are special, we do not include them into output sections +// list, but have them to simplify the code. +template void Writer::fixHeaders() { + Out::ElfHeader->setVA(Target->getVAStart()); + Out::ElfHeader->setFileOffset(0); + uintX_t Off = Out::ElfHeader->getSize(); + Out::ProgramHeaders->setVA(Off + Target->getVAStart()); + Out::ProgramHeaders->setFileOffset(Off); +} + // Assign VAs (addresses at run-time) to output sections. template void Writer::assignAddresses() { - uintX_t ThreadBssOffset = 0; - uintX_t VA = Target->getVAStart(); + uintX_t VA = Target->getVAStart() + Out::ElfHeader->getSize() + + Out::ProgramHeaders->getSize(); + uintX_t ThreadBssOffset = 0; for (OutputSectionBase *Sec : OutputSections) { uintX_t Align = Sec->getAlign(); if (Sec->PageAlign) @@ -1381,7 +1381,9 @@ // Assign file offsets to output sections. template void Writer::assignFileOffsets() { - uintX_t Off = 0; + uintX_t Off = + Out::ElfHeader->getSize() + Out::ProgramHeaders->getSize(); + for (OutputSectionBase *Sec : OutputSections) { if (Sec->getType() == SHT_NOBITS) { Sec->setFileOffset(Off); @@ -1529,7 +1531,7 @@ // Write the section header table. Note that the first table entry is null. auto *SHdrs = reinterpret_cast(Buf + EHdr->e_shoff); - for (OutputSectionBase *Sec : getSections()) + for (OutputSectionBase *Sec : OutputSections) Sec->writeHeaderTo(++SHdrs); }