// Creates program headers as instructed by PHDRS linker script command. std::vector<PhdrEntry *> LinkerScript::createPhdrs() { std::vector<PhdrEntry *> Ret; // Process PHDRS and FILEHDR keywords because they are not // real output sections and cannot be added in the following loop. for (const PhdrsCommand &Cmd : PhdrsCommands) { PhdrEntry *Phdr = make<PhdrEntry>(Cmd.Type, Cmd.Flags ? *Cmd.Flags : PF_R); if (Cmd.HasFilehdr) Phdr->add(Out::ElfHeader); if (Cmd.HasPhdrs) Phdr->add(Out::ProgramHeaders); if (Cmd.LMAExpr) { Phdr->p_paddr = Cmd.LMAExpr().getValue(); Phdr->HasLMA = true; } Ret.push_back(Phdr); } // Add output sections to program headers. for (OutputSection *Sec : OutputSections) { // Assign headers specified by linker script for (size_t Id : getPhdrIndices(Sec)) { Ret[Id]->add(Sec); if (!PhdrsCommands[Id].Flags.hasValue()) Ret[Id]->p_flags |= Sec->getPhdrFlags(); } } return Ret; }
std::vector<PhdrEntry<ELFT>> LinkerScript<ELFT>::createPhdrs(ArrayRef<OutputSectionBase<ELFT> *> Sections) { std::vector<PhdrEntry<ELFT>> Ret; for (const PhdrsCommand &Cmd : Opt.PhdrsCommands) { Ret.emplace_back(Cmd.Type, Cmd.Flags == UINT_MAX ? PF_R : Cmd.Flags); PhdrEntry<ELFT> &Phdr = Ret.back(); if (Cmd.HasFilehdr) Phdr.add(Out<ELFT>::ElfHeader); if (Cmd.HasPhdrs) Phdr.add(Out<ELFT>::ProgramHeaders); switch (Cmd.Type) { case PT_INTERP: if (Out<ELFT>::Interp) Phdr.add(Out<ELFT>::Interp); break; case PT_DYNAMIC: if (isOutputDynamic<ELFT>()) { Phdr.H.p_flags = toPhdrFlags(Out<ELFT>::Dynamic->getFlags()); Phdr.add(Out<ELFT>::Dynamic); } break; case PT_GNU_EH_FRAME: if (!Out<ELFT>::EhFrame->empty() && Out<ELFT>::EhFrameHdr) { Phdr.H.p_flags = toPhdrFlags(Out<ELFT>::EhFrameHdr->getFlags()); Phdr.add(Out<ELFT>::EhFrameHdr); } break; } } PhdrEntry<ELFT> *Load = nullptr; uintX_t Flags = PF_R; for (OutputSectionBase<ELFT> *Sec : Sections) { if (!(Sec->getFlags() & SHF_ALLOC)) break; std::vector<size_t> PhdrIds = getPhdrIndices(Sec->getName()); if (!PhdrIds.empty()) { // Assign headers specified by linker script for (size_t Id : PhdrIds) { Ret[Id].add(Sec); if (Opt.PhdrsCommands[Id].Flags == UINT_MAX) Ret[Id].H.p_flags |= toPhdrFlags(Sec->getFlags()); } } else { // If we have no load segment or flags've changed then we want new load // segment. uintX_t NewFlags = toPhdrFlags(Sec->getFlags()); if (Load == nullptr || Flags != NewFlags) { Load = &*Ret.emplace(Ret.end(), PT_LOAD, NewFlags); Flags = NewFlags; } Load->add(Sec); } } return Ret; }