Index: ELF/Writer.cpp =================================================================== --- ELF/Writer.cpp +++ ELF/Writer.cpp @@ -55,6 +55,7 @@ void addPredefinedSections(); bool needsGot(); + void createLoads(std::vector& Dest); std::vector createPhdrs(); void assignAddresses(); void assignFileOffsets(); @@ -919,32 +920,51 @@ return true; } +template +static PhdrEntry *addHdr(std::vector> &Dest, + unsigned Type, unsigned Flags) { + Dest.emplace_back(Type, Flags); + return &Dest.back(); +} + +template void Writer::createLoads(std::vector &Dest) { + // Add the first PT_LOAD segment for regular output sections. + uintX_t Flags = PF_R; + Phdr *Load = addHdr(Dest, PT_LOAD, Flags); + Load->add(Out::ElfHeader); + Load->add(Out::ProgramHeaders); + + for (OutputSectionBase *Sec : OutputSections) { + if (!needsPtLoad(Sec)) + continue; + + // If flags changed then we want new load segment. + uintX_t NewFlags = Sec->getPhdrFlags(); + if (Flags != NewFlags) { + Load = addHdr(Dest, PT_LOAD, NewFlags); + Flags = NewFlags; + } + + Load->add(Sec); + } +} + // Decide which program headers to create and which sections to include in each // one. -template -std::vector> Writer::createPhdrs() { +template std::vector> Writer::createPhdrs() { std::vector Ret; - auto AddHdr = [&](unsigned Type, unsigned Flags) -> Phdr * { - Ret.emplace_back(Type, Flags); - return &Ret.back(); - }; - // The first phdr entry is PT_PHDR which describes the program header itself. - Phdr &Hdr = *AddHdr(PT_PHDR, PF_R); + Phdr &Hdr = *addHdr(Ret, PT_PHDR, PF_R); Hdr.add(Out::ProgramHeaders); // PT_INTERP must be the second entry if exists. if (Out::Interp) { - Phdr &Hdr = *AddHdr(PT_INTERP, Out::Interp->getPhdrFlags()); + Phdr &Hdr = *addHdr(Ret, PT_INTERP, Out::Interp->getPhdrFlags()); Hdr.add(Out::Interp); } - // Add the first PT_LOAD segment for regular output sections. - uintX_t Flags = PF_R; - Phdr *Load = AddHdr(PT_LOAD, Flags); - Load->add(Out::ElfHeader); - Load->add(Out::ProgramHeaders); + createLoads(Ret); Phdr TlsHdr(PT_TLS, PF_R); Phdr RelRo(PT_GNU_RELRO, PF_R); @@ -962,15 +982,6 @@ if (!needsPtLoad(Sec)) continue; - // If flags changed then we want new load segment. - uintX_t NewFlags = Sec->getPhdrFlags(); - if (Flags != NewFlags) { - Load = AddHdr(PT_LOAD, NewFlags); - Flags = NewFlags; - } - - Load->add(Sec); - if (isRelroSection(Sec)) RelRo.add(Sec); if (Sec->getType() == SHT_NOTE) @@ -983,7 +994,7 @@ // Add an entry for .dynamic. if (Out::DynSymTab) { - Phdr &H = *AddHdr(PT_DYNAMIC, Out::Dynamic->getPhdrFlags()); + Phdr &H = *addHdr(Ret, PT_DYNAMIC, Out::Dynamic->getPhdrFlags()); H.add(Out::Dynamic); } @@ -994,14 +1005,15 @@ // PT_GNU_EH_FRAME is a special section pointing on .eh_frame_hdr. if (!Out::EhFrame->empty() && Out::EhFrameHdr) { - Phdr &Hdr = *AddHdr(PT_GNU_EH_FRAME, Out::EhFrameHdr->getPhdrFlags()); + Phdr &Hdr = + *addHdr(Ret, PT_GNU_EH_FRAME, Out::EhFrameHdr->getPhdrFlags()); Hdr.add(Out::EhFrameHdr); } // PT_GNU_STACK is a special section to tell the loader to make the // pages for the stack non-executable. if (!Config->ZExecStack) - AddHdr(PT_GNU_STACK, PF_R | PF_W); + addHdr(Ret, PT_GNU_STACK, PF_R | PF_W); if (Note.First) Ret.push_back(std::move(Note));