[ELF] - Store PhdrEntry values by pointers instead of storing by value.

That is slightly more convinent as allows to store pointer on
program header entry in a more safe way.
 
Change was used in 2 patches currently on review.

Differential revision: https://reviews.llvm.org/D35832

llvm-svn: 309253
This commit is contained in:
George Rimar 2017-07-27 07:46:50 +00:00
parent 678188d48b
commit aa3541875e
3 changed files with 84 additions and 82 deletions

View File

@ -761,7 +761,7 @@ void LinkerScript::adjustSectionsAfterSorting() {
removeEmptyCommands();
}
void LinkerScript::allocateHeaders(std::vector<PhdrEntry> &Phdrs) {
void LinkerScript::allocateHeaders(std::vector<PhdrEntry *> &Phdrs) {
uint64_t Min = std::numeric_limits<uint64_t>::max();
for (OutputSectionCommand *Cmd : OutputSectionCommands) {
OutputSection *Sec = Cmd->Sec;
@ -769,10 +769,11 @@ void LinkerScript::allocateHeaders(std::vector<PhdrEntry> &Phdrs) {
Min = std::min<uint64_t>(Min, Sec->Addr);
}
auto FirstPTLoad = llvm::find_if(
Phdrs, [](const PhdrEntry &E) { return E.p_type == PT_LOAD; });
if (FirstPTLoad == Phdrs.end())
auto It = llvm::find_if(
Phdrs, [](const PhdrEntry *E) { return E->p_type == PT_LOAD; });
if (It == Phdrs.end())
return;
PhdrEntry *FirstPTLoad = *It;
uint64_t HeaderSize = getHeaderSize();
if (HeaderSize <= Min || Script->hasPhdrsCommands()) {
@ -799,11 +800,11 @@ void LinkerScript::allocateHeaders(std::vector<PhdrEntry> &Phdrs) {
}
FirstPTLoad->First = ActualFirst;
} else {
Phdrs.erase(FirstPTLoad);
Phdrs.erase(It);
}
auto PhdrI = llvm::find_if(
Phdrs, [](const PhdrEntry &E) { return E.p_type == PT_PHDR; });
Phdrs, [](const PhdrEntry *E) { return E->p_type == PT_PHDR; });
if (PhdrI != Phdrs.end())
Phdrs.erase(PhdrI);
}
@ -845,24 +846,25 @@ void LinkerScript::assignAddresses() {
}
// Creates program headers as instructed by PHDRS linker script command.
std::vector<PhdrEntry> LinkerScript::createPhdrs() {
std::vector<PhdrEntry> Ret;
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 : Opt.PhdrsCommands) {
Ret.emplace_back(Cmd.Type, Cmd.Flags == UINT_MAX ? PF_R : Cmd.Flags);
PhdrEntry &Phdr = Ret.back();
PhdrEntry *Phdr =
make<PhdrEntry>(Cmd.Type, Cmd.Flags == UINT_MAX ? PF_R : Cmd.Flags);
if (Cmd.HasFilehdr)
Phdr.add(Out::ElfHeader);
Phdr->add(Out::ElfHeader);
if (Cmd.HasPhdrs)
Phdr.add(Out::ProgramHeaders);
Phdr->add(Out::ProgramHeaders);
if (Cmd.LMAExpr) {
Phdr.p_paddr = Cmd.LMAExpr().getValue();
Phdr.HasLMA = true;
Phdr->p_paddr = Cmd.LMAExpr().getValue();
Phdr->HasLMA = true;
}
Ret.push_back(Phdr);
}
// Add output sections to program headers.
@ -870,9 +872,9 @@ std::vector<PhdrEntry> LinkerScript::createPhdrs() {
// Assign headers specified by linker script
for (size_t Id : getPhdrIndices(Cmd)) {
OutputSection *Sec = Cmd->Sec;
Ret[Id].add(Sec);
Ret[Id]->add(Sec);
if (Opt.PhdrsCommands[Id].Flags == UINT_MAX)
Ret[Id].p_flags |= Sec->getPhdrFlags();
Ret[Id]->p_flags |= Sec->getPhdrFlags();
}
}
return Ret;

View File

@ -283,13 +283,13 @@ public:
void adjustSectionsBeforeSorting();
void adjustSectionsAfterSorting();
std::vector<PhdrEntry> createPhdrs();
std::vector<PhdrEntry *> createPhdrs();
bool ignoreInterpSection();
bool shouldKeep(InputSectionBase *S);
void assignOffsets(OutputSectionCommand *Cmd);
void assignAddresses();
void allocateHeaders(std::vector<PhdrEntry> &Phdrs);
void allocateHeaders(std::vector<PhdrEntry *> &Phdrs);
void addSymbol(SymbolAssignment *Cmd);
void processCommands(OutputSectionFactory &Factory);

View File

@ -57,9 +57,9 @@ private:
void finalizeSections();
void addPredefinedSections();
std::vector<PhdrEntry> createPhdrs();
std::vector<PhdrEntry *> createPhdrs();
void removeEmptyPTLoad();
void addPtArmExid(std::vector<PhdrEntry> &Phdrs);
void addPtArmExid(std::vector<PhdrEntry *> &Phdrs);
void assignFileOffsets();
void assignFileOffsetsBinary();
void setPhdrs();
@ -82,7 +82,7 @@ private:
OutputSection *findSectionInScript(StringRef Name);
OutputSectionCommand *findSectionCommand(StringRef Name);
std::vector<PhdrEntry> Phdrs;
std::vector<PhdrEntry *> Phdrs;
uint64_t FileSize;
uint64_t SectionHeaderOff;
@ -125,12 +125,12 @@ template <class ELFT> static bool needsInterpSection() {
template <class ELFT> void elf::writeResult() { Writer<ELFT>().run(); }
template <class ELFT> void Writer<ELFT>::removeEmptyPTLoad() {
auto I = std::remove_if(Phdrs.begin(), Phdrs.end(), [&](const PhdrEntry &P) {
if (P.p_type != PT_LOAD)
auto I = llvm::remove_if(Phdrs, [&](const PhdrEntry *P) {
if (P->p_type != PT_LOAD)
return false;
if (!P.First)
if (!P->First)
return true;
uint64_t Size = P.Last->Addr + P.Last->Size - P.First->Addr;
uint64_t Size = P->Last->Addr + P->Last->Size - P->First->Addr;
return Size == 0;
});
Phdrs.erase(I, Phdrs.end());
@ -1424,11 +1424,11 @@ static uint64_t computeFlags(uint64_t Flags) {
// Decide which program headers to create and which sections to include in each
// one.
template <class ELFT> std::vector<PhdrEntry> Writer<ELFT>::createPhdrs() {
std::vector<PhdrEntry> Ret;
template <class ELFT> std::vector<PhdrEntry *> Writer<ELFT>::createPhdrs() {
std::vector<PhdrEntry *> Ret;
auto AddHdr = [&](unsigned Type, unsigned Flags) -> PhdrEntry * {
Ret.emplace_back(Type, Flags);
return &Ret.back();
Ret.push_back(make<PhdrEntry>(Type, Flags));
return Ret.back();
};
// The first phdr entry is PT_PHDR which describes the program header itself.
@ -1468,14 +1468,14 @@ template <class ELFT> std::vector<PhdrEntry> Writer<ELFT>::createPhdrs() {
}
// Add a TLS segment if any.
PhdrEntry TlsHdr(PT_TLS, PF_R);
PhdrEntry *TlsHdr = make<PhdrEntry>(PT_TLS, PF_R);
for (OutputSectionCommand *Cmd : OutputSectionCommands) {
OutputSection *Sec = Cmd->Sec;
if (Sec->Flags & SHF_TLS)
TlsHdr.add(Sec);
TlsHdr->add(Sec);
}
if (TlsHdr.First)
Ret.push_back(std::move(TlsHdr));
if (TlsHdr->First)
Ret.push_back(TlsHdr);
// Add an entry for .dynamic.
if (InX::DynSymTab)
@ -1484,14 +1484,14 @@ template <class ELFT> std::vector<PhdrEntry> Writer<ELFT>::createPhdrs() {
// PT_GNU_RELRO includes all sections that should be marked as
// read-only by dynamic linker after proccessing relocations.
PhdrEntry RelRo(PT_GNU_RELRO, PF_R);
PhdrEntry *RelRo = make<PhdrEntry>(PT_GNU_RELRO, PF_R);
for (OutputSectionCommand *Cmd : OutputSectionCommands) {
OutputSection *Sec = Cmd->Sec;
if (needsPtLoad(Sec) && isRelroSection(Sec))
RelRo.add(Sec);
RelRo->add(Sec);
}
if (RelRo.First)
Ret.push_back(std::move(RelRo));
if (RelRo->First)
Ret.push_back(RelRo);
// PT_GNU_EH_FRAME is a special section pointing on .eh_frame_hdr.
if (!In<ELFT>::EhFrame->empty() && In<ELFT>::EhFrameHdr &&
@ -1538,7 +1538,7 @@ template <class ELFT> std::vector<PhdrEntry> Writer<ELFT>::createPhdrs() {
}
template <class ELFT>
void Writer<ELFT>::addPtArmExid(std::vector<PhdrEntry> &Phdrs) {
void Writer<ELFT>::addPtArmExid(std::vector<PhdrEntry *> &Phdrs) {
if (Config->EMachine != EM_ARM)
return;
auto I = llvm::find_if(OutputSectionCommands, [](OutputSectionCommand *Cmd) {
@ -1548,8 +1548,8 @@ void Writer<ELFT>::addPtArmExid(std::vector<PhdrEntry> &Phdrs) {
return;
// PT_ARM_EXIDX is the ARM EHABI equivalent of PT_GNU_EH_FRAME
PhdrEntry ARMExidx(PT_ARM_EXIDX, PF_R);
ARMExidx.add((*I)->Sec);
PhdrEntry *ARMExidx = make<PhdrEntry>(PT_ARM_EXIDX, PF_R);
ARMExidx->add((*I)->Sec);
Phdrs.push_back(ARMExidx);
}
@ -1565,20 +1565,20 @@ template <class ELFT> void Writer<ELFT>::fixSectionAlignments() {
};
};
for (const PhdrEntry &P : Phdrs)
if (P.p_type == PT_LOAD && P.First)
PageAlign(P.First);
for (const PhdrEntry *P : Phdrs)
if (P->p_type == PT_LOAD && P->First)
PageAlign(P->First);
for (const PhdrEntry &P : Phdrs) {
if (P.p_type != PT_GNU_RELRO)
for (const PhdrEntry *P : Phdrs) {
if (P->p_type != PT_GNU_RELRO)
continue;
if (P.First)
PageAlign(P.First);
if (P->First)
PageAlign(P->First);
// Find the first section after PT_GNU_RELRO. If it is in a PT_LOAD we
// have to align it to a page.
auto End = OutputSectionCommands.end();
auto I =
std::find(OutputSectionCommands.begin(), End, Script->getCmd(P.Last));
std::find(OutputSectionCommands.begin(), End, Script->getCmd(P->Last));
if (I == End || (I + 1) == End)
continue;
OutputSection *Sec = (*(I + 1))->Sec;
@ -1646,35 +1646,35 @@ template <class ELFT> void Writer<ELFT>::assignFileOffsets() {
// Finalize the program headers. We call this function after we assign
// file offsets and VAs to all sections.
template <class ELFT> void Writer<ELFT>::setPhdrs() {
for (PhdrEntry &P : Phdrs) {
OutputSection *First = P.First;
OutputSection *Last = P.Last;
for (PhdrEntry *P : Phdrs) {
OutputSection *First = P->First;
OutputSection *Last = P->Last;
if (First) {
P.p_filesz = Last->Offset - First->Offset;
P->p_filesz = Last->Offset - First->Offset;
if (Last->Type != SHT_NOBITS)
P.p_filesz += Last->Size;
P.p_memsz = Last->Addr + Last->Size - First->Addr;
P.p_offset = First->Offset;
P.p_vaddr = First->Addr;
if (!P.HasLMA)
P.p_paddr = First->getLMA();
P->p_filesz += Last->Size;
P->p_memsz = Last->Addr + Last->Size - First->Addr;
P->p_offset = First->Offset;
P->p_vaddr = First->Addr;
if (!P->HasLMA)
P->p_paddr = First->getLMA();
}
if (P.p_type == PT_LOAD)
P.p_align = std::max<uint64_t>(P.p_align, Config->MaxPageSize);
else if (P.p_type == PT_GNU_RELRO) {
P.p_align = 1;
if (P->p_type == PT_LOAD)
P->p_align = std::max<uint64_t>(P->p_align, Config->MaxPageSize);
else if (P->p_type == PT_GNU_RELRO) {
P->p_align = 1;
// The glibc dynamic loader rounds the size down, so we need to round up
// to protect the last page. This is a no-op on FreeBSD which always
// rounds up.
P.p_memsz = alignTo(P.p_memsz, Target->PageSize);
P->p_memsz = alignTo(P->p_memsz, Target->PageSize);
}
// The TLS pointer goes after PT_TLS. At least glibc will align it,
// so round up the size to make sure the offsets are correct.
if (P.p_type == PT_TLS) {
Out::TlsPhdr = &P;
if (P.p_memsz)
P.p_memsz = alignTo(P.p_memsz, P.p_align);
if (P->p_type == PT_TLS) {
Out::TlsPhdr = P;
if (P->p_memsz)
P->p_memsz = alignTo(P->p_memsz, P->p_align);
}
}
}
@ -1728,14 +1728,14 @@ template <class ELFT> void Writer<ELFT>::fixPredefinedSymbols() {
PhdrEntry *Last = nullptr;
PhdrEntry *LastRO = nullptr;
PhdrEntry *LastRW = nullptr;
for (PhdrEntry &P : Phdrs) {
if (P.p_type != PT_LOAD)
for (PhdrEntry *P : Phdrs) {
if (P->p_type != PT_LOAD)
continue;
Last = &P;
if (P.p_flags & PF_W)
LastRW = &P;
Last = P;
if (P->p_flags & PF_W)
LastRW = P;
else
LastRO = &P;
LastRO = P;
}
auto Set = [](DefinedRegular *S, OutputSection *Sec, uint64_t Value) {
@ -1812,15 +1812,15 @@ template <class ELFT> void Writer<ELFT>::writeHeader() {
// Write the program header table.
auto *HBuf = reinterpret_cast<Elf_Phdr *>(Buf + EHdr->e_phoff);
for (PhdrEntry &P : Phdrs) {
HBuf->p_type = P.p_type;
HBuf->p_flags = P.p_flags;
HBuf->p_offset = P.p_offset;
HBuf->p_vaddr = P.p_vaddr;
HBuf->p_paddr = P.p_paddr;
HBuf->p_filesz = P.p_filesz;
HBuf->p_memsz = P.p_memsz;
HBuf->p_align = P.p_align;
for (PhdrEntry *P : Phdrs) {
HBuf->p_type = P->p_type;
HBuf->p_flags = P->p_flags;
HBuf->p_offset = P->p_offset;
HBuf->p_vaddr = P->p_vaddr;
HBuf->p_paddr = P->p_paddr;
HBuf->p_filesz = P->p_filesz;
HBuf->p_memsz = P->p_memsz;
HBuf->p_align = P->p_align;
++HBuf;
}