forked from OSchip/llvm-project
Split Header into individual fields.
This is similar to what was done for InputSection. With this the various fields are stored in host order and only converted to target order when writing. llvm-svn: 286327
This commit is contained in:
parent
7576cb0fa7
commit
04a2e348bb
|
|
@ -113,7 +113,7 @@ typename ELFT::uint InputSectionBase<ELFT>::getOffset(uintX_t Offset) const {
|
||||||
if (Offset != 0)
|
if (Offset != 0)
|
||||||
fatal(getName(this) + ": unsupported reference to the middle of '" +
|
fatal(getName(this) + ": unsupported reference to the middle of '" +
|
||||||
Name + "' section");
|
Name + "' section");
|
||||||
return this->OutSec->getVA();
|
return this->OutSec->Addr;
|
||||||
}
|
}
|
||||||
llvm_unreachable("invalid section kind");
|
llvm_unreachable("invalid section kind");
|
||||||
}
|
}
|
||||||
|
|
@ -267,7 +267,7 @@ static typename ELFT::uint getSymVA(uint32_t Type, typename ELFT::uint A,
|
||||||
case R_TLSDESC_CALL:
|
case R_TLSDESC_CALL:
|
||||||
llvm_unreachable("cannot relocate hint relocs");
|
llvm_unreachable("cannot relocate hint relocs");
|
||||||
case R_TLSLD:
|
case R_TLSLD:
|
||||||
return Out<ELFT>::Got->getTlsIndexOff() + A - Out<ELFT>::Got->getSize();
|
return Out<ELFT>::Got->getTlsIndexOff() + A - Out<ELFT>::Got->Size;
|
||||||
case R_TLSLD_PC:
|
case R_TLSLD_PC:
|
||||||
return Out<ELFT>::Got->getTlsIndexVA() + A - P;
|
return Out<ELFT>::Got->getTlsIndexVA() + A - P;
|
||||||
case R_THUNK_ABS:
|
case R_THUNK_ABS:
|
||||||
|
|
@ -278,8 +278,7 @@ static typename ELFT::uint getSymVA(uint32_t Type, typename ELFT::uint A,
|
||||||
case R_PPC_TOC:
|
case R_PPC_TOC:
|
||||||
return getPPC64TocBase() + A;
|
return getPPC64TocBase() + A;
|
||||||
case R_TLSGD:
|
case R_TLSGD:
|
||||||
return Out<ELFT>::Got->getGlobalDynOffset(Body) + A -
|
return Out<ELFT>::Got->getGlobalDynOffset(Body) + A - Out<ELFT>::Got->Size;
|
||||||
Out<ELFT>::Got->getSize();
|
|
||||||
case R_TLSGD_PC:
|
case R_TLSGD_PC:
|
||||||
return Out<ELFT>::Got->getGlobalDynAddr(Body) + A - P;
|
return Out<ELFT>::Got->getGlobalDynAddr(Body) + A - P;
|
||||||
case R_TLSDESC:
|
case R_TLSDESC:
|
||||||
|
|
@ -295,13 +294,12 @@ static typename ELFT::uint getSymVA(uint32_t Type, typename ELFT::uint A,
|
||||||
case R_SIZE:
|
case R_SIZE:
|
||||||
return Body.getSize<ELFT>() + A;
|
return Body.getSize<ELFT>() + A;
|
||||||
case R_GOTREL:
|
case R_GOTREL:
|
||||||
return Body.getVA<ELFT>(A) - Out<ELFT>::Got->getVA();
|
return Body.getVA<ELFT>(A) - Out<ELFT>::Got->Addr;
|
||||||
case R_GOTREL_FROM_END:
|
case R_GOTREL_FROM_END:
|
||||||
return Body.getVA<ELFT>(A) - Out<ELFT>::Got->getVA() -
|
return Body.getVA<ELFT>(A) - Out<ELFT>::Got->Addr - Out<ELFT>::Got->Size;
|
||||||
Out<ELFT>::Got->getSize();
|
|
||||||
case R_RELAX_TLS_GD_TO_IE_END:
|
case R_RELAX_TLS_GD_TO_IE_END:
|
||||||
case R_GOT_FROM_END:
|
case R_GOT_FROM_END:
|
||||||
return Body.getGotOffset<ELFT>() + A - Out<ELFT>::Got->getSize();
|
return Body.getGotOffset<ELFT>() + A - Out<ELFT>::Got->Size;
|
||||||
case R_RELAX_TLS_GD_TO_IE_ABS:
|
case R_RELAX_TLS_GD_TO_IE_ABS:
|
||||||
case R_GOT:
|
case R_GOT:
|
||||||
return Body.getGotVA<ELFT>() + A;
|
return Body.getGotVA<ELFT>() + A;
|
||||||
|
|
@ -312,9 +310,9 @@ static typename ELFT::uint getSymVA(uint32_t Type, typename ELFT::uint A,
|
||||||
case R_GOT_PC:
|
case R_GOT_PC:
|
||||||
return Body.getGotVA<ELFT>() + A - P;
|
return Body.getGotVA<ELFT>() + A - P;
|
||||||
case R_GOTONLY_PC:
|
case R_GOTONLY_PC:
|
||||||
return Out<ELFT>::Got->getVA() + A - P;
|
return Out<ELFT>::Got->Addr + A - P;
|
||||||
case R_GOTONLY_PC_FROM_END:
|
case R_GOTONLY_PC_FROM_END:
|
||||||
return Out<ELFT>::Got->getVA() + A - P + Out<ELFT>::Got->getSize();
|
return Out<ELFT>::Got->Addr + A - P + Out<ELFT>::Got->Size;
|
||||||
case R_RELAX_TLS_LD_TO_LE:
|
case R_RELAX_TLS_LD_TO_LE:
|
||||||
case R_RELAX_TLS_IE_TO_LE:
|
case R_RELAX_TLS_IE_TO_LE:
|
||||||
case R_RELAX_TLS_GD_TO_LE:
|
case R_RELAX_TLS_GD_TO_LE:
|
||||||
|
|
@ -366,8 +364,8 @@ static typename ELFT::uint getSymVA(uint32_t Type, typename ELFT::uint A,
|
||||||
if (Out<ELF64BE>::Opd) {
|
if (Out<ELF64BE>::Opd) {
|
||||||
// If this is a local call, and we currently have the address of a
|
// If this is a local call, and we currently have the address of a
|
||||||
// function-descriptor, get the underlying code address instead.
|
// function-descriptor, get the underlying code address instead.
|
||||||
uint64_t OpdStart = Out<ELF64BE>::Opd->getVA();
|
uint64_t OpdStart = Out<ELF64BE>::Opd->Addr;
|
||||||
uint64_t OpdEnd = OpdStart + Out<ELF64BE>::Opd->getSize();
|
uint64_t OpdEnd = OpdStart + Out<ELF64BE>::Opd->Size;
|
||||||
bool InOpd = OpdStart <= SymVA && SymVA < OpdEnd;
|
bool InOpd = OpdStart <= SymVA && SymVA < OpdEnd;
|
||||||
if (InOpd)
|
if (InOpd)
|
||||||
SymVA = read64be(&Out<ELF64BE>::OpdBuf[SymVA - OpdStart]);
|
SymVA = read64be(&Out<ELF64BE>::OpdBuf[SymVA - OpdStart]);
|
||||||
|
|
@ -408,7 +406,7 @@ void InputSection<ELFT>::relocateNonAlloc(uint8_t *Buf, ArrayRef<RelTy> Rels) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
uintX_t AddrLoc = this->OutSec->getVA() + Offset;
|
uintX_t AddrLoc = this->OutSec->Addr + Offset;
|
||||||
uint64_t SymVA = 0;
|
uint64_t SymVA = 0;
|
||||||
if (!Sym.isTls() || Out<ELFT>::TlsPhdr)
|
if (!Sym.isTls() || Out<ELFT>::TlsPhdr)
|
||||||
SymVA = SignExtend64<sizeof(uintX_t) * 8>(
|
SymVA = SignExtend64<sizeof(uintX_t) * 8>(
|
||||||
|
|
@ -440,7 +438,7 @@ void InputSectionBase<ELFT>::relocate(uint8_t *Buf, uint8_t *BufEnd) {
|
||||||
uint32_t Type = Rel.Type;
|
uint32_t Type = Rel.Type;
|
||||||
uintX_t A = Rel.Addend;
|
uintX_t A = Rel.Addend;
|
||||||
|
|
||||||
uintX_t AddrLoc = OutSec->getVA() + Offset;
|
uintX_t AddrLoc = OutSec->Addr + Offset;
|
||||||
RelExpr Expr = Rel.Expr;
|
RelExpr Expr = Rel.Expr;
|
||||||
uint64_t SymVA =
|
uint64_t SymVA =
|
||||||
SignExtend64<Bits>(getSymVA<ELFT>(Type, A, AddrLoc, *Rel.Sym, Expr));
|
SignExtend64<Bits>(getSymVA<ELFT>(Type, A, AddrLoc, *Rel.Sym, Expr));
|
||||||
|
|
|
||||||
|
|
@ -381,7 +381,7 @@ static void assignSectionSymbol(SymbolAssignment *Cmd,
|
||||||
|
|
||||||
if (auto *Body = dyn_cast<DefinedSynthetic<ELFT>>(Cmd->Sym)) {
|
if (auto *Body = dyn_cast<DefinedSynthetic<ELFT>>(Cmd->Sym)) {
|
||||||
Body->Section = Sec;
|
Body->Section = Sec;
|
||||||
Body->Value = Cmd->Expression(Value) - Sec->getVA();
|
Body->Value = Cmd->Expression(Value) - Sec->Addr;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
auto *Body = cast<DefinedRegular<ELFT>>(Cmd->Sym);
|
auto *Body = cast<DefinedRegular<ELFT>>(Cmd->Sym);
|
||||||
|
|
@ -389,7 +389,7 @@ static void assignSectionSymbol(SymbolAssignment *Cmd,
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class ELFT> static bool isTbss(OutputSectionBase<ELFT> *Sec) {
|
template <class ELFT> static bool isTbss(OutputSectionBase<ELFT> *Sec) {
|
||||||
return (Sec->getFlags() & SHF_TLS) && Sec->getType() == SHT_NOBITS;
|
return (Sec->Flags & SHF_TLS) && Sec->Type == SHT_NOBITS;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class ELFT> void LinkerScript<ELFT>::output(InputSection<ELFT> *S) {
|
template <class ELFT> void LinkerScript<ELFT>::output(InputSection<ELFT> *S) {
|
||||||
|
|
@ -399,13 +399,13 @@ template <class ELFT> void LinkerScript<ELFT>::output(InputSection<ELFT> *S) {
|
||||||
|
|
||||||
uintX_t Pos = IsTbss ? Dot + ThreadBssOffset : Dot;
|
uintX_t Pos = IsTbss ? Dot + ThreadBssOffset : Dot;
|
||||||
Pos = alignTo(Pos, S->Alignment);
|
Pos = alignTo(Pos, S->Alignment);
|
||||||
S->OutSecOff = Pos - CurOutSec->getVA();
|
S->OutSecOff = Pos - CurOutSec->Addr;
|
||||||
Pos += S->getSize();
|
Pos += S->getSize();
|
||||||
|
|
||||||
// Update output section size after adding each section. This is so that
|
// Update output section size after adding each section. This is so that
|
||||||
// SIZEOF works correctly in the case below:
|
// SIZEOF works correctly in the case below:
|
||||||
// .foo { *(.aaa) a = SIZEOF(.foo); *(.bbb) }
|
// .foo { *(.aaa) a = SIZEOF(.foo); *(.bbb) }
|
||||||
CurOutSec->setSize(Pos - CurOutSec->getVA());
|
CurOutSec->Size = Pos - CurOutSec->Addr;
|
||||||
|
|
||||||
if (IsTbss)
|
if (IsTbss)
|
||||||
ThreadBssOffset = Pos - Dot;
|
ThreadBssOffset = Pos - Dot;
|
||||||
|
|
@ -420,7 +420,7 @@ template <class ELFT> void LinkerScript<ELFT>::flush() {
|
||||||
for (InputSection<ELFT> *I : OutSec->Sections)
|
for (InputSection<ELFT> *I : OutSec->Sections)
|
||||||
output(I);
|
output(I);
|
||||||
} else {
|
} else {
|
||||||
Dot += CurOutSec->getSize();
|
Dot += CurOutSec->Size;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -434,8 +434,8 @@ void LinkerScript<ELFT>::switchTo(OutputSectionBase<ELFT> *Sec) {
|
||||||
flush();
|
flush();
|
||||||
CurOutSec = Sec;
|
CurOutSec = Sec;
|
||||||
|
|
||||||
Dot = alignTo(Dot, CurOutSec->getAlignment());
|
Dot = alignTo(Dot, CurOutSec->Addralign);
|
||||||
CurOutSec->setVA(isTbss(CurOutSec) ? Dot + ThreadBssOffset : Dot);
|
CurOutSec->Addr = isTbss(CurOutSec) ? Dot + ThreadBssOffset : Dot;
|
||||||
|
|
||||||
// If neither AT nor AT> is specified for an allocatable section, the linker
|
// If neither AT nor AT> is specified for an allocatable section, the linker
|
||||||
// will set the LMA such that the difference between VMA and LMA for the
|
// will set the LMA such that the difference between VMA and LMA for the
|
||||||
|
|
@ -450,7 +450,7 @@ template <class ELFT> void LinkerScript<ELFT>::process(BaseCommand &Base) {
|
||||||
if (AssignCmd->Name == ".") {
|
if (AssignCmd->Name == ".") {
|
||||||
// Update to location counter means update to section size.
|
// Update to location counter means update to section size.
|
||||||
Dot = AssignCmd->Expression(Dot);
|
Dot = AssignCmd->Expression(Dot);
|
||||||
CurOutSec->setSize(Dot - CurOutSec->getVA());
|
CurOutSec->Size = Dot - CurOutSec->Addr;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
assignSectionSymbol<ELFT>(AssignCmd, CurOutSec, Dot);
|
assignSectionSymbol<ELFT>(AssignCmd, CurOutSec, Dot);
|
||||||
|
|
@ -459,9 +459,9 @@ template <class ELFT> void LinkerScript<ELFT>::process(BaseCommand &Base) {
|
||||||
|
|
||||||
// Handle BYTE(), SHORT(), LONG(), or QUAD().
|
// Handle BYTE(), SHORT(), LONG(), or QUAD().
|
||||||
if (auto *DataCmd = dyn_cast<BytesDataCommand>(&Base)) {
|
if (auto *DataCmd = dyn_cast<BytesDataCommand>(&Base)) {
|
||||||
DataCmd->Offset = Dot - CurOutSec->getVA();
|
DataCmd->Offset = Dot - CurOutSec->Addr;
|
||||||
Dot += DataCmd->Size;
|
Dot += DataCmd->Size;
|
||||||
CurOutSec->setSize(Dot - CurOutSec->getVA());
|
CurOutSec->Size = Dot - CurOutSec->Addr;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -552,8 +552,8 @@ template <class ELFT> void LinkerScript<ELFT>::adjustSectionsBeforeSorting() {
|
||||||
std::vector<OutputSectionBase<ELFT> *> Secs =
|
std::vector<OutputSectionBase<ELFT> *> Secs =
|
||||||
findSections(Cmd->Name, *OutputSections);
|
findSections(Cmd->Name, *OutputSections);
|
||||||
if (!Secs.empty()) {
|
if (!Secs.empty()) {
|
||||||
Flags = Secs[0]->getFlags();
|
Flags = Secs[0]->Flags;
|
||||||
Type = Secs[0]->getType();
|
Type = Secs[0]->Type;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -654,10 +654,10 @@ void LinkerScript<ELFT>::assignAddresses(std::vector<PhdrEntry<ELFT>> &Phdrs) {
|
||||||
|
|
||||||
uintX_t MinVA = std::numeric_limits<uintX_t>::max();
|
uintX_t MinVA = std::numeric_limits<uintX_t>::max();
|
||||||
for (OutputSectionBase<ELFT> *Sec : *OutputSections) {
|
for (OutputSectionBase<ELFT> *Sec : *OutputSections) {
|
||||||
if (Sec->getFlags() & SHF_ALLOC)
|
if (Sec->Flags & SHF_ALLOC)
|
||||||
MinVA = std::min(MinVA, Sec->getVA());
|
MinVA = std::min(MinVA, Sec->Addr);
|
||||||
else
|
else
|
||||||
Sec->setVA(0);
|
Sec->Addr = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
uintX_t HeaderSize = getHeaderSize();
|
uintX_t HeaderSize = getHeaderSize();
|
||||||
|
|
@ -678,8 +678,8 @@ void LinkerScript<ELFT>::assignAddresses(std::vector<PhdrEntry<ELFT>> &Phdrs) {
|
||||||
// ELF and Program headers need to be right before the first section in
|
// ELF and Program headers need to be right before the first section in
|
||||||
// memory. Set their addresses accordingly.
|
// memory. Set their addresses accordingly.
|
||||||
MinVA = alignDown(MinVA - HeaderSize, Target->PageSize);
|
MinVA = alignDown(MinVA - HeaderSize, Target->PageSize);
|
||||||
Out<ELFT>::ElfHeader->setVA(MinVA);
|
Out<ELFT>::ElfHeader->Addr = MinVA;
|
||||||
Out<ELFT>::ProgramHeaders->setVA(Out<ELFT>::ElfHeader->getSize() + MinVA);
|
Out<ELFT>::ProgramHeaders->Addr = Out<ELFT>::ElfHeader->Size + MinVA;
|
||||||
FirstPTLoad->First = Out<ELFT>::ElfHeader;
|
FirstPTLoad->First = Out<ELFT>::ElfHeader;
|
||||||
if (!FirstPTLoad->Last)
|
if (!FirstPTLoad->Last)
|
||||||
FirstPTLoad->Last = Out<ELFT>::ProgramHeaders;
|
FirstPTLoad->Last = Out<ELFT>::ProgramHeaders;
|
||||||
|
|
@ -692,8 +692,8 @@ void LinkerScript<ELFT>::assignAddresses(std::vector<PhdrEntry<ELFT>> &Phdrs) {
|
||||||
// The code below removes empty PT_LOAD segment and updates
|
// The code below removes empty PT_LOAD segment and updates
|
||||||
// program headers size.
|
// program headers size.
|
||||||
Phdrs.erase(FirstPTLoad);
|
Phdrs.erase(FirstPTLoad);
|
||||||
Out<ELFT>::ProgramHeaders->setSize(sizeof(typename ELFT::Phdr) *
|
Out<ELFT>::ProgramHeaders->Size =
|
||||||
Phdrs.size());
|
sizeof(typename ELFT::Phdr) * Phdrs.size();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -731,7 +731,7 @@ std::vector<PhdrEntry<ELFT>> LinkerScript<ELFT>::createPhdrs() {
|
||||||
|
|
||||||
// Add output sections to program headers.
|
// Add output sections to program headers.
|
||||||
for (OutputSectionBase<ELFT> *Sec : *OutputSections) {
|
for (OutputSectionBase<ELFT> *Sec : *OutputSections) {
|
||||||
if (!(Sec->getFlags() & SHF_ALLOC))
|
if (!(Sec->Flags & SHF_ALLOC))
|
||||||
break;
|
break;
|
||||||
|
|
||||||
std::vector<size_t> PhdrIds = getPhdrIndices(Sec->getName());
|
std::vector<size_t> PhdrIds = getPhdrIndices(Sec->getName());
|
||||||
|
|
@ -833,7 +833,7 @@ template <class ELFT>
|
||||||
uint64_t LinkerScript<ELFT>::getOutputSectionAddress(StringRef Name) {
|
uint64_t LinkerScript<ELFT>::getOutputSectionAddress(StringRef Name) {
|
||||||
for (OutputSectionBase<ELFT> *Sec : *OutputSections)
|
for (OutputSectionBase<ELFT> *Sec : *OutputSections)
|
||||||
if (Sec->getName() == Name)
|
if (Sec->getName() == Name)
|
||||||
return Sec->getVA();
|
return Sec->Addr;
|
||||||
error("undefined section " + Name);
|
error("undefined section " + Name);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
@ -851,7 +851,7 @@ template <class ELFT>
|
||||||
uint64_t LinkerScript<ELFT>::getOutputSectionSize(StringRef Name) {
|
uint64_t LinkerScript<ELFT>::getOutputSectionSize(StringRef Name) {
|
||||||
for (OutputSectionBase<ELFT> *Sec : *OutputSections)
|
for (OutputSectionBase<ELFT> *Sec : *OutputSections)
|
||||||
if (Sec->getName() == Name)
|
if (Sec->getName() == Name)
|
||||||
return Sec->getSize();
|
return Sec->Size;
|
||||||
error("undefined section " + Name);
|
error("undefined section " + Name);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
@ -860,7 +860,7 @@ template <class ELFT>
|
||||||
uint64_t LinkerScript<ELFT>::getOutputSectionAlign(StringRef Name) {
|
uint64_t LinkerScript<ELFT>::getOutputSectionAlign(StringRef Name) {
|
||||||
for (OutputSectionBase<ELFT> *Sec : *OutputSections)
|
for (OutputSectionBase<ELFT> *Sec : *OutputSections)
|
||||||
if (Sec->getName() == Name)
|
if (Sec->getName() == Name)
|
||||||
return Sec->getAlignment();
|
return Sec->Addralign;
|
||||||
error("undefined section " + Name);
|
error("undefined section " + Name);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -36,14 +36,12 @@ template <class ELFT>
|
||||||
OutputSectionBase<ELFT>::OutputSectionBase(StringRef Name, uint32_t Type,
|
OutputSectionBase<ELFT>::OutputSectionBase(StringRef Name, uint32_t Type,
|
||||||
uintX_t Flags)
|
uintX_t Flags)
|
||||||
: Name(Name) {
|
: Name(Name) {
|
||||||
memset(&Header, 0, sizeof(Elf_Shdr));
|
this->Type = Type;
|
||||||
Header.sh_type = Type;
|
this->Flags = Flags;
|
||||||
Header.sh_flags = Flags;
|
this->Addralign = 1;
|
||||||
Header.sh_addralign = 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class ELFT> uint32_t OutputSectionBase<ELFT>::getPhdrFlags() const {
|
template <class ELFT> uint32_t OutputSectionBase<ELFT>::getPhdrFlags() const {
|
||||||
uintX_t Flags = getFlags();
|
|
||||||
uint32_t Ret = PF_R;
|
uint32_t Ret = PF_R;
|
||||||
if (Flags & SHF_WRITE)
|
if (Flags & SHF_WRITE)
|
||||||
Ret |= PF_W;
|
Ret |= PF_W;
|
||||||
|
|
@ -54,7 +52,16 @@ template <class ELFT> uint32_t OutputSectionBase<ELFT>::getPhdrFlags() const {
|
||||||
|
|
||||||
template <class ELFT>
|
template <class ELFT>
|
||||||
void OutputSectionBase<ELFT>::writeHeaderTo(Elf_Shdr *Shdr) {
|
void OutputSectionBase<ELFT>::writeHeaderTo(Elf_Shdr *Shdr) {
|
||||||
*Shdr = Header;
|
Shdr->sh_entsize = Entsize;
|
||||||
|
Shdr->sh_addralign = Addralign;
|
||||||
|
Shdr->sh_type = Type;
|
||||||
|
Shdr->sh_offset = Offset;
|
||||||
|
Shdr->sh_flags = Flags;
|
||||||
|
Shdr->sh_info = Info;
|
||||||
|
Shdr->sh_link = Link;
|
||||||
|
Shdr->sh_addr = Addr;
|
||||||
|
Shdr->sh_size = Size;
|
||||||
|
Shdr->sh_name = ShName;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class ELFT>
|
template <class ELFT>
|
||||||
|
|
@ -81,7 +88,7 @@ template <class ELFT> void GdbIndexSection<ELFT>::finalize() {
|
||||||
// GdbIndex header consist from version fields
|
// GdbIndex header consist from version fields
|
||||||
// and 5 more fields with different kinds of offsets.
|
// and 5 more fields with different kinds of offsets.
|
||||||
CuTypesOffset = CuListOffset + CompilationUnits.size() * CompilationUnitSize;
|
CuTypesOffset = CuListOffset + CompilationUnits.size() * CompilationUnitSize;
|
||||||
this->Header.sh_size = CuTypesOffset;
|
this->Size = CuTypesOffset;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class ELFT> void GdbIndexSection<ELFT>::writeTo(uint8_t *Buf) {
|
template <class ELFT> void GdbIndexSection<ELFT>::writeTo(uint8_t *Buf) {
|
||||||
|
|
@ -104,7 +111,7 @@ template <class ELFT> void GdbIndexSection<ELFT>::writeTo(uint8_t *Buf) {
|
||||||
template <class ELFT>
|
template <class ELFT>
|
||||||
GotPltSection<ELFT>::GotPltSection()
|
GotPltSection<ELFT>::GotPltSection()
|
||||||
: OutputSectionBase<ELFT>(".got.plt", SHT_PROGBITS, SHF_ALLOC | SHF_WRITE) {
|
: OutputSectionBase<ELFT>(".got.plt", SHT_PROGBITS, SHF_ALLOC | SHF_WRITE) {
|
||||||
this->Header.sh_addralign = Target->GotPltEntrySize;
|
this->Addralign = Target->GotPltEntrySize;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class ELFT> void GotPltSection<ELFT>::addEntry(SymbolBody &Sym) {
|
template <class ELFT> void GotPltSection<ELFT>::addEntry(SymbolBody &Sym) {
|
||||||
|
|
@ -117,7 +124,7 @@ template <class ELFT> bool GotPltSection<ELFT>::empty() const {
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class ELFT> void GotPltSection<ELFT>::finalize() {
|
template <class ELFT> void GotPltSection<ELFT>::finalize() {
|
||||||
this->Header.sh_size = (Target->GotPltHeaderEntriesNum + Entries.size()) *
|
this->Size = (Target->GotPltHeaderEntriesNum + Entries.size()) *
|
||||||
Target->GotPltEntrySize;
|
Target->GotPltEntrySize;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -134,8 +141,8 @@ template <class ELFT>
|
||||||
GotSection<ELFT>::GotSection()
|
GotSection<ELFT>::GotSection()
|
||||||
: OutputSectionBase<ELFT>(".got", SHT_PROGBITS, SHF_ALLOC | SHF_WRITE) {
|
: OutputSectionBase<ELFT>(".got", SHT_PROGBITS, SHF_ALLOC | SHF_WRITE) {
|
||||||
if (Config->EMachine == EM_MIPS)
|
if (Config->EMachine == EM_MIPS)
|
||||||
this->Header.sh_flags |= SHF_MIPS_GPREL;
|
this->Flags |= SHF_MIPS_GPREL;
|
||||||
this->Header.sh_addralign = Target->GotEntrySize;
|
this->Addralign = Target->GotEntrySize;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class ELFT> void GotSection<ELFT>::addEntry(SymbolBody &Sym) {
|
template <class ELFT> void GotSection<ELFT>::addEntry(SymbolBody &Sym) {
|
||||||
|
|
@ -281,7 +288,7 @@ typename GotSection<ELFT>::uintX_t GotSection<ELFT>::getMipsTlsOffset() const {
|
||||||
template <class ELFT>
|
template <class ELFT>
|
||||||
typename GotSection<ELFT>::uintX_t
|
typename GotSection<ELFT>::uintX_t
|
||||||
GotSection<ELFT>::getGlobalDynAddr(const SymbolBody &B) const {
|
GotSection<ELFT>::getGlobalDynAddr(const SymbolBody &B) const {
|
||||||
return this->getVA() + B.GlobalDynIndex * sizeof(uintX_t);
|
return this->Addr + B.GlobalDynIndex * sizeof(uintX_t);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class ELFT>
|
template <class ELFT>
|
||||||
|
|
@ -312,11 +319,11 @@ template <class ELFT> void GotSection<ELFT>::finalize() {
|
||||||
// page of the output section has at least one GOT relocation against it.
|
// page of the output section has at least one GOT relocation against it.
|
||||||
// Add 0x8000 to the section's size because the page address stored
|
// Add 0x8000 to the section's size because the page address stored
|
||||||
// in the GOT entry is calculated as (value + 0x8000) & ~0xffff.
|
// in the GOT entry is calculated as (value + 0x8000) & ~0xffff.
|
||||||
MipsPageEntries += (OutSec->getSize() + 0x8000 + 0xfffe) / 0xffff;
|
MipsPageEntries += (OutSec->Size + 0x8000 + 0xfffe) / 0xffff;
|
||||||
}
|
}
|
||||||
EntriesNum += getMipsLocalEntriesNum() + MipsGlobal.size();
|
EntriesNum += getMipsLocalEntriesNum() + MipsGlobal.size();
|
||||||
}
|
}
|
||||||
this->Header.sh_size = EntriesNum * sizeof(uintX_t);
|
this->Size = EntriesNum * sizeof(uintX_t);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class ELFT>
|
template <class ELFT>
|
||||||
|
|
@ -402,7 +409,7 @@ template <class ELFT> void GotSection<ELFT>::writeTo(uint8_t *Buf) {
|
||||||
template <class ELFT>
|
template <class ELFT>
|
||||||
PltSection<ELFT>::PltSection()
|
PltSection<ELFT>::PltSection()
|
||||||
: OutputSectionBase<ELFT>(".plt", SHT_PROGBITS, SHF_ALLOC | SHF_EXECINSTR) {
|
: OutputSectionBase<ELFT>(".plt", SHT_PROGBITS, SHF_ALLOC | SHF_EXECINSTR) {
|
||||||
this->Header.sh_addralign = 16;
|
this->Addralign = 16;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class ELFT> void PltSection<ELFT>::writeTo(uint8_t *Buf) {
|
template <class ELFT> void PltSection<ELFT>::writeTo(uint8_t *Buf) {
|
||||||
|
|
@ -415,7 +422,7 @@ template <class ELFT> void PltSection<ELFT>::writeTo(uint8_t *Buf) {
|
||||||
const SymbolBody *B = I.first;
|
const SymbolBody *B = I.first;
|
||||||
unsigned RelOff = I.second;
|
unsigned RelOff = I.second;
|
||||||
uint64_t Got = B->getGotPltVA<ELFT>();
|
uint64_t Got = B->getGotPltVA<ELFT>();
|
||||||
uint64_t Plt = this->getVA() + Off;
|
uint64_t Plt = this->Addr + Off;
|
||||||
Target->writePlt(Buf + Off, Got, Plt, B->PltIndex, RelOff);
|
Target->writePlt(Buf + Off, Got, Plt, B->PltIndex, RelOff);
|
||||||
Off += Target->PltEntrySize;
|
Off += Target->PltEntrySize;
|
||||||
}
|
}
|
||||||
|
|
@ -428,8 +435,7 @@ template <class ELFT> void PltSection<ELFT>::addEntry(SymbolBody &Sym) {
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class ELFT> void PltSection<ELFT>::finalize() {
|
template <class ELFT> void PltSection<ELFT>::finalize() {
|
||||||
this->Header.sh_size =
|
this->Size = Target->PltHeaderSize + Entries.size() * Target->PltEntrySize;
|
||||||
Target->PltHeaderSize + Entries.size() * Target->PltEntrySize;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class ELFT>
|
template <class ELFT>
|
||||||
|
|
@ -437,8 +443,8 @@ RelocationSection<ELFT>::RelocationSection(StringRef Name, bool Sort)
|
||||||
: OutputSectionBase<ELFT>(Name, Config->Rela ? SHT_RELA : SHT_REL,
|
: OutputSectionBase<ELFT>(Name, Config->Rela ? SHT_RELA : SHT_REL,
|
||||||
SHF_ALLOC),
|
SHF_ALLOC),
|
||||||
Sort(Sort) {
|
Sort(Sort) {
|
||||||
this->Header.sh_entsize = Config->Rela ? sizeof(Elf_Rela) : sizeof(Elf_Rel);
|
this->Entsize = Config->Rela ? sizeof(Elf_Rela) : sizeof(Elf_Rel);
|
||||||
this->Header.sh_addralign = sizeof(uintX_t);
|
this->Addralign = sizeof(uintX_t);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class ELFT>
|
template <class ELFT>
|
||||||
|
|
@ -487,25 +493,24 @@ template <class ELFT> void RelocationSection<ELFT>::writeTo(uint8_t *Buf) {
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class ELFT> unsigned RelocationSection<ELFT>::getRelocOffset() {
|
template <class ELFT> unsigned RelocationSection<ELFT>::getRelocOffset() {
|
||||||
return this->Header.sh_entsize * Relocs.size();
|
return this->Entsize * Relocs.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class ELFT> void RelocationSection<ELFT>::finalize() {
|
template <class ELFT> void RelocationSection<ELFT>::finalize() {
|
||||||
this->Header.sh_link = Out<ELFT>::DynSymTab
|
this->Link = Out<ELFT>::DynSymTab ? Out<ELFT>::DynSymTab->SectionIndex
|
||||||
? Out<ELFT>::DynSymTab->SectionIndex
|
|
||||||
: Out<ELFT>::SymTab->SectionIndex;
|
: Out<ELFT>::SymTab->SectionIndex;
|
||||||
this->Header.sh_size = Relocs.size() * this->Header.sh_entsize;
|
this->Size = Relocs.size() * this->Entsize;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class ELFT>
|
template <class ELFT>
|
||||||
HashTableSection<ELFT>::HashTableSection()
|
HashTableSection<ELFT>::HashTableSection()
|
||||||
: OutputSectionBase<ELFT>(".hash", SHT_HASH, SHF_ALLOC) {
|
: OutputSectionBase<ELFT>(".hash", SHT_HASH, SHF_ALLOC) {
|
||||||
this->Header.sh_entsize = sizeof(Elf_Word);
|
this->Entsize = sizeof(Elf_Word);
|
||||||
this->Header.sh_addralign = sizeof(Elf_Word);
|
this->Addralign = sizeof(Elf_Word);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class ELFT> void HashTableSection<ELFT>::finalize() {
|
template <class ELFT> void HashTableSection<ELFT>::finalize() {
|
||||||
this->Header.sh_link = Out<ELFT>::DynSymTab->SectionIndex;
|
this->Link = Out<ELFT>::DynSymTab->SectionIndex;
|
||||||
|
|
||||||
unsigned NumEntries = 2; // nbucket and nchain.
|
unsigned NumEntries = 2; // nbucket and nchain.
|
||||||
NumEntries += Out<ELFT>::DynSymTab->getNumSymbols(); // The chain entries.
|
NumEntries += Out<ELFT>::DynSymTab->getNumSymbols(); // The chain entries.
|
||||||
|
|
@ -514,7 +519,7 @@ template <class ELFT> void HashTableSection<ELFT>::finalize() {
|
||||||
// FIXME: This is simplistic. We can try to optimize it, but implementing
|
// FIXME: This is simplistic. We can try to optimize it, but implementing
|
||||||
// support for SHT_GNU_HASH is probably even more profitable.
|
// support for SHT_GNU_HASH is probably even more profitable.
|
||||||
NumEntries += Out<ELFT>::DynSymTab->getNumSymbols();
|
NumEntries += Out<ELFT>::DynSymTab->getNumSymbols();
|
||||||
this->Header.sh_size = NumEntries * sizeof(Elf_Word);
|
this->Size = NumEntries * sizeof(Elf_Word);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class ELFT> void HashTableSection<ELFT>::writeTo(uint8_t *Buf) {
|
template <class ELFT> void HashTableSection<ELFT>::writeTo(uint8_t *Buf) {
|
||||||
|
|
@ -546,8 +551,8 @@ static uint32_t hashGnu(StringRef Name) {
|
||||||
template <class ELFT>
|
template <class ELFT>
|
||||||
GnuHashTableSection<ELFT>::GnuHashTableSection()
|
GnuHashTableSection<ELFT>::GnuHashTableSection()
|
||||||
: OutputSectionBase<ELFT>(".gnu.hash", SHT_GNU_HASH, SHF_ALLOC) {
|
: OutputSectionBase<ELFT>(".gnu.hash", SHT_GNU_HASH, SHF_ALLOC) {
|
||||||
this->Header.sh_entsize = ELFT::Is64Bits ? 0 : 4;
|
this->Entsize = ELFT::Is64Bits ? 0 : 4;
|
||||||
this->Header.sh_addralign = sizeof(uintX_t);
|
this->Addralign = sizeof(uintX_t);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class ELFT>
|
template <class ELFT>
|
||||||
|
|
@ -591,8 +596,8 @@ template <class ELFT> void GnuHashTableSection<ELFT>::finalize() {
|
||||||
// Second hash shift estimation: just predefined values.
|
// Second hash shift estimation: just predefined values.
|
||||||
Shift2 = ELFT::Is64Bits ? 6 : 5;
|
Shift2 = ELFT::Is64Bits ? 6 : 5;
|
||||||
|
|
||||||
this->Header.sh_link = Out<ELFT>::DynSymTab->SectionIndex;
|
this->Link = Out<ELFT>::DynSymTab->SectionIndex;
|
||||||
this->Header.sh_size = sizeof(Elf_Word) * 4 // Header
|
this->Size = sizeof(Elf_Word) * 4 // Header
|
||||||
+ sizeof(Elf_Off) * MaskWords // Bloom Filter
|
+ sizeof(Elf_Off) * MaskWords // Bloom Filter
|
||||||
+ sizeof(Elf_Word) * NBuckets // Hash Buckets
|
+ sizeof(Elf_Word) * NBuckets // Hash Buckets
|
||||||
+ sizeof(Elf_Word) * NumHashed; // Hash Values
|
+ sizeof(Elf_Word) * NumHashed; // Hash Values
|
||||||
|
|
@ -691,15 +696,14 @@ static unsigned getVerDefNum() { return Config->VersionDefinitions.size() + 1; }
|
||||||
template <class ELFT>
|
template <class ELFT>
|
||||||
DynamicSection<ELFT>::DynamicSection()
|
DynamicSection<ELFT>::DynamicSection()
|
||||||
: OutputSectionBase<ELFT>(".dynamic", SHT_DYNAMIC, SHF_ALLOC | SHF_WRITE) {
|
: OutputSectionBase<ELFT>(".dynamic", SHT_DYNAMIC, SHF_ALLOC | SHF_WRITE) {
|
||||||
Elf_Shdr &Header = this->Header;
|
this->Addralign = sizeof(uintX_t);
|
||||||
Header.sh_addralign = sizeof(uintX_t);
|
this->Entsize = ELFT::Is64Bits ? 16 : 8;
|
||||||
Header.sh_entsize = ELFT::Is64Bits ? 16 : 8;
|
|
||||||
|
|
||||||
// .dynamic section is not writable on MIPS.
|
// .dynamic section is not writable on MIPS.
|
||||||
// See "Special Section" in Chapter 4 in the following document:
|
// See "Special Section" in Chapter 4 in the following document:
|
||||||
// ftp://www.linux-mips.org/pub/linux/mips/doc/ABI/mipsabi.pdf
|
// ftp://www.linux-mips.org/pub/linux/mips/doc/ABI/mipsabi.pdf
|
||||||
if (Config->EMachine == EM_MIPS)
|
if (Config->EMachine == EM_MIPS)
|
||||||
Header.sh_flags = SHF_ALLOC;
|
this->Flags = SHF_ALLOC;
|
||||||
|
|
||||||
addEntries();
|
addEntries();
|
||||||
}
|
}
|
||||||
|
|
@ -747,15 +751,15 @@ template <class ELFT> void DynamicSection<ELFT>::addEntries() {
|
||||||
|
|
||||||
// Add remaining entries to complete .dynamic contents.
|
// Add remaining entries to complete .dynamic contents.
|
||||||
template <class ELFT> void DynamicSection<ELFT>::finalize() {
|
template <class ELFT> void DynamicSection<ELFT>::finalize() {
|
||||||
if (this->Header.sh_size)
|
if (this->Size)
|
||||||
return; // Already finalized.
|
return; // Already finalized.
|
||||||
|
|
||||||
this->Header.sh_link = Out<ELFT>::DynStrTab->SectionIndex;
|
this->Link = Out<ELFT>::DynStrTab->SectionIndex;
|
||||||
|
|
||||||
if (Out<ELFT>::RelaDyn->hasRelocs()) {
|
if (Out<ELFT>::RelaDyn->hasRelocs()) {
|
||||||
bool IsRela = Config->Rela;
|
bool IsRela = Config->Rela;
|
||||||
Add({IsRela ? DT_RELA : DT_REL, Out<ELFT>::RelaDyn});
|
Add({IsRela ? DT_RELA : DT_REL, Out<ELFT>::RelaDyn});
|
||||||
Add({IsRela ? DT_RELASZ : DT_RELSZ, Out<ELFT>::RelaDyn->getSize()});
|
Add({IsRela ? DT_RELASZ : DT_RELSZ, Out<ELFT>::RelaDyn->Size});
|
||||||
Add({IsRela ? DT_RELAENT : DT_RELENT,
|
Add({IsRela ? DT_RELAENT : DT_RELENT,
|
||||||
uintX_t(IsRela ? sizeof(Elf_Rela) : sizeof(Elf_Rel))});
|
uintX_t(IsRela ? sizeof(Elf_Rela) : sizeof(Elf_Rel))});
|
||||||
|
|
||||||
|
|
@ -770,7 +774,7 @@ template <class ELFT> void DynamicSection<ELFT>::finalize() {
|
||||||
}
|
}
|
||||||
if (Out<ELFT>::RelaPlt && Out<ELFT>::RelaPlt->hasRelocs()) {
|
if (Out<ELFT>::RelaPlt && Out<ELFT>::RelaPlt->hasRelocs()) {
|
||||||
Add({DT_JMPREL, Out<ELFT>::RelaPlt});
|
Add({DT_JMPREL, Out<ELFT>::RelaPlt});
|
||||||
Add({DT_PLTRELSZ, Out<ELFT>::RelaPlt->getSize()});
|
Add({DT_PLTRELSZ, Out<ELFT>::RelaPlt->Size});
|
||||||
Add({Config->EMachine == EM_MIPS ? DT_MIPS_PLTGOT : DT_PLTGOT,
|
Add({Config->EMachine == EM_MIPS ? DT_MIPS_PLTGOT : DT_PLTGOT,
|
||||||
Out<ELFT>::GotPlt});
|
Out<ELFT>::GotPlt});
|
||||||
Add({DT_PLTREL, uint64_t(Config->Rela ? DT_RELA : DT_REL)});
|
Add({DT_PLTREL, uint64_t(Config->Rela ? DT_RELA : DT_REL)});
|
||||||
|
|
@ -779,7 +783,7 @@ template <class ELFT> void DynamicSection<ELFT>::finalize() {
|
||||||
Add({DT_SYMTAB, Out<ELFT>::DynSymTab});
|
Add({DT_SYMTAB, Out<ELFT>::DynSymTab});
|
||||||
Add({DT_SYMENT, sizeof(Elf_Sym)});
|
Add({DT_SYMENT, sizeof(Elf_Sym)});
|
||||||
Add({DT_STRTAB, Out<ELFT>::DynStrTab});
|
Add({DT_STRTAB, Out<ELFT>::DynStrTab});
|
||||||
Add({DT_STRSZ, Out<ELFT>::DynStrTab->getSize()});
|
Add({DT_STRSZ, Out<ELFT>::DynStrTab->Size});
|
||||||
if (Out<ELFT>::GnuHashTab)
|
if (Out<ELFT>::GnuHashTab)
|
||||||
Add({DT_GNU_HASH, Out<ELFT>::GnuHashTab});
|
Add({DT_GNU_HASH, Out<ELFT>::GnuHashTab});
|
||||||
if (Out<ELFT>::HashTab)
|
if (Out<ELFT>::HashTab)
|
||||||
|
|
@ -831,7 +835,7 @@ template <class ELFT> void DynamicSection<ELFT>::finalize() {
|
||||||
}
|
}
|
||||||
|
|
||||||
// +1 for DT_NULL
|
// +1 for DT_NULL
|
||||||
this->Header.sh_size = (Entries.size() + 1) * this->Header.sh_entsize;
|
this->Size = (Entries.size() + 1) * this->Entsize;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class ELFT> void DynamicSection<ELFT>::writeTo(uint8_t *Buf) {
|
template <class ELFT> void DynamicSection<ELFT>::writeTo(uint8_t *Buf) {
|
||||||
|
|
@ -841,10 +845,10 @@ template <class ELFT> void DynamicSection<ELFT>::writeTo(uint8_t *Buf) {
|
||||||
P->d_tag = E.Tag;
|
P->d_tag = E.Tag;
|
||||||
switch (E.Kind) {
|
switch (E.Kind) {
|
||||||
case Entry::SecAddr:
|
case Entry::SecAddr:
|
||||||
P->d_un.d_ptr = E.OutSec->getVA();
|
P->d_un.d_ptr = E.OutSec->Addr;
|
||||||
break;
|
break;
|
||||||
case Entry::SecSize:
|
case Entry::SecSize:
|
||||||
P->d_un.d_val = E.OutSec->getSize();
|
P->d_un.d_val = E.OutSec->Size;
|
||||||
break;
|
break;
|
||||||
case Entry::SymAddr:
|
case Entry::SymAddr:
|
||||||
P->d_un.d_ptr = E.Sym->template getVA<ELFT>();
|
P->d_un.d_ptr = E.Sym->template getVA<ELFT>();
|
||||||
|
|
@ -880,11 +884,11 @@ template <class ELFT> void EhFrameHeader<ELFT>::writeTo(uint8_t *Buf) {
|
||||||
Buf[1] = DW_EH_PE_pcrel | DW_EH_PE_sdata4;
|
Buf[1] = DW_EH_PE_pcrel | DW_EH_PE_sdata4;
|
||||||
Buf[2] = DW_EH_PE_udata4;
|
Buf[2] = DW_EH_PE_udata4;
|
||||||
Buf[3] = DW_EH_PE_datarel | DW_EH_PE_sdata4;
|
Buf[3] = DW_EH_PE_datarel | DW_EH_PE_sdata4;
|
||||||
write32<E>(Buf + 4, Out<ELFT>::EhFrame->getVA() - this->getVA() - 4);
|
write32<E>(Buf + 4, Out<ELFT>::EhFrame->Addr - this->Addr - 4);
|
||||||
write32<E>(Buf + 8, Fdes.size());
|
write32<E>(Buf + 8, Fdes.size());
|
||||||
Buf += 12;
|
Buf += 12;
|
||||||
|
|
||||||
uintX_t VA = this->getVA();
|
uintX_t VA = this->Addr;
|
||||||
for (FdeData &Fde : Fdes) {
|
for (FdeData &Fde : Fdes) {
|
||||||
write32<E>(Buf, Fde.Pc - VA);
|
write32<E>(Buf, Fde.Pc - VA);
|
||||||
write32<E>(Buf + 4, Fde.FdeVA - VA);
|
write32<E>(Buf + 4, Fde.FdeVA - VA);
|
||||||
|
|
@ -894,7 +898,7 @@ template <class ELFT> void EhFrameHeader<ELFT>::writeTo(uint8_t *Buf) {
|
||||||
|
|
||||||
template <class ELFT> void EhFrameHeader<ELFT>::finalize() {
|
template <class ELFT> void EhFrameHeader<ELFT>::finalize() {
|
||||||
// .eh_frame_hdr has a 12 bytes header followed by an array of FDEs.
|
// .eh_frame_hdr has a 12 bytes header followed by an array of FDEs.
|
||||||
this->Header.sh_size = 12 + Out<ELFT>::EhFrame->NumFdes * 8;
|
this->Size = 12 + Out<ELFT>::EhFrame->NumFdes * 8;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class ELFT>
|
template <class ELFT>
|
||||||
|
|
@ -906,17 +910,17 @@ template <class ELFT>
|
||||||
OutputSection<ELFT>::OutputSection(StringRef Name, uint32_t Type, uintX_t Flags)
|
OutputSection<ELFT>::OutputSection(StringRef Name, uint32_t Type, uintX_t Flags)
|
||||||
: OutputSectionBase<ELFT>(Name, Type, Flags) {
|
: OutputSectionBase<ELFT>(Name, Type, Flags) {
|
||||||
if (Type == SHT_RELA)
|
if (Type == SHT_RELA)
|
||||||
this->Header.sh_entsize = sizeof(Elf_Rela);
|
this->Entsize = sizeof(Elf_Rela);
|
||||||
else if (Type == SHT_REL)
|
else if (Type == SHT_REL)
|
||||||
this->Header.sh_entsize = sizeof(Elf_Rel);
|
this->Entsize = sizeof(Elf_Rel);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class ELFT> void OutputSection<ELFT>::finalize() {
|
template <class ELFT> void OutputSection<ELFT>::finalize() {
|
||||||
uint32_t Type = this->Header.sh_type;
|
uint32_t Type = this->Type;
|
||||||
if (this->Header.sh_flags & SHF_LINK_ORDER) {
|
if (this->Flags & SHF_LINK_ORDER) {
|
||||||
if (!Config->Relocatable) {
|
if (!Config->Relocatable) {
|
||||||
// SHF_LINK_ORDER only has meaning in relocatable objects
|
// SHF_LINK_ORDER only has meaning in relocatable objects
|
||||||
this->Header.sh_flags &= ~SHF_LINK_ORDER;
|
this->Flags &= ~SHF_LINK_ORDER;
|
||||||
}
|
}
|
||||||
else if (!this->Sections.empty()) {
|
else if (!this->Sections.empty()) {
|
||||||
// When doing a relocatable link we must preserve the link order
|
// When doing a relocatable link we must preserve the link order
|
||||||
|
|
@ -925,16 +929,16 @@ template <class ELFT> void OutputSection<ELFT>::finalize() {
|
||||||
// InputSection sh_link to the OutputSection sh_link, all InputSections
|
// InputSection sh_link to the OutputSection sh_link, all InputSections
|
||||||
// in the OutputSection have the same dependency.
|
// in the OutputSection have the same dependency.
|
||||||
if (auto *D = this->Sections.front()->getLinkOrderDep())
|
if (auto *D = this->Sections.front()->getLinkOrderDep())
|
||||||
this->Header.sh_link = D->OutSec->SectionIndex;
|
this->Link = D->OutSec->SectionIndex;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (Type != SHT_RELA && Type != SHT_REL)
|
if (Type != SHT_RELA && Type != SHT_REL)
|
||||||
return;
|
return;
|
||||||
this->Header.sh_link = Out<ELFT>::SymTab->SectionIndex;
|
this->Link = Out<ELFT>::SymTab->SectionIndex;
|
||||||
// sh_info for SHT_REL[A] sections should contain the section header index of
|
// sh_info for SHT_REL[A] sections should contain the section header index of
|
||||||
// the section to which the relocation applies.
|
// the section to which the relocation applies.
|
||||||
InputSectionBase<ELFT> *S = Sections[0]->getRelocatedSection();
|
InputSectionBase<ELFT> *S = Sections[0]->getRelocatedSection();
|
||||||
this->Header.sh_info = S->OutSec->SectionIndex;
|
this->Info = S->OutSec->SectionIndex;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class ELFT>
|
template <class ELFT>
|
||||||
|
|
@ -947,19 +951,19 @@ void OutputSection<ELFT>::addSection(InputSectionBase<ELFT> *C) {
|
||||||
// Keep sh_entsize value of the input section to be able to perform merging
|
// Keep sh_entsize value of the input section to be able to perform merging
|
||||||
// later during a final linking using the generated relocatable object.
|
// later during a final linking using the generated relocatable object.
|
||||||
if (Config->Relocatable && (S->Flags & SHF_MERGE))
|
if (Config->Relocatable && (S->Flags & SHF_MERGE))
|
||||||
this->Header.sh_entsize = S->Entsize;
|
this->Entsize = S->Entsize;
|
||||||
}
|
}
|
||||||
|
|
||||||
// This function is called after we sort input sections
|
// This function is called after we sort input sections
|
||||||
// and scan relocations to setup sections' offsets.
|
// and scan relocations to setup sections' offsets.
|
||||||
template <class ELFT> void OutputSection<ELFT>::assignOffsets() {
|
template <class ELFT> void OutputSection<ELFT>::assignOffsets() {
|
||||||
uintX_t Off = this->Header.sh_size;
|
uintX_t Off = this->Size;
|
||||||
for (InputSection<ELFT> *S : Sections) {
|
for (InputSection<ELFT> *S : Sections) {
|
||||||
Off = alignTo(Off, S->Alignment);
|
Off = alignTo(Off, S->Alignment);
|
||||||
S->OutSecOff = Off;
|
S->OutSecOff = Off;
|
||||||
Off += S->getSize();
|
Off += S->getSize();
|
||||||
}
|
}
|
||||||
this->Header.sh_size = Off;
|
this->Size = Off;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Sorts input sections by section name suffixes, so that .foo.N comes
|
// Sorts input sections by section name suffixes, so that .foo.N comes
|
||||||
|
|
@ -1052,7 +1056,7 @@ static void fill(uint8_t *Buf, size_t Size, ArrayRef<uint8_t> A) {
|
||||||
template <class ELFT> void OutputSection<ELFT>::writeTo(uint8_t *Buf) {
|
template <class ELFT> void OutputSection<ELFT>::writeTo(uint8_t *Buf) {
|
||||||
ArrayRef<uint8_t> Filler = Script<ELFT>::X->getFiller(this->Name);
|
ArrayRef<uint8_t> Filler = Script<ELFT>::X->getFiller(this->Name);
|
||||||
if (!Filler.empty())
|
if (!Filler.empty())
|
||||||
fill(Buf, this->getSize(), Filler);
|
fill(Buf, this->Size, Filler);
|
||||||
if (Config->Threads) {
|
if (Config->Threads) {
|
||||||
parallel_for_each(Sections.begin(), Sections.end(),
|
parallel_for_each(Sections.begin(), Sections.end(),
|
||||||
[=](InputSection<ELFT> *C) { C->writeTo(Buf); });
|
[=](InputSection<ELFT> *C) { C->writeTo(Buf); });
|
||||||
|
|
@ -1186,7 +1190,7 @@ static void writeCieFde(uint8_t *Buf, ArrayRef<uint8_t> D) {
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class ELFT> void EhOutputSection<ELFT>::finalize() {
|
template <class ELFT> void EhOutputSection<ELFT>::finalize() {
|
||||||
if (this->Header.sh_size)
|
if (this->Size)
|
||||||
return; // Already finalized.
|
return; // Already finalized.
|
||||||
|
|
||||||
size_t Off = 0;
|
size_t Off = 0;
|
||||||
|
|
@ -1199,7 +1203,7 @@ template <class ELFT> void EhOutputSection<ELFT>::finalize() {
|
||||||
Off += alignTo(Fde->size(), sizeof(uintX_t));
|
Off += alignTo(Fde->size(), sizeof(uintX_t));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
this->Header.sh_size = Off;
|
this->Size = Off;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class ELFT> static uint64_t readFdeAddr(uint8_t *Buf, int Size) {
|
template <class ELFT> static uint64_t readFdeAddr(uint8_t *Buf, int Size) {
|
||||||
|
|
@ -1231,7 +1235,7 @@ typename ELFT::uint EhOutputSection<ELFT>::getFdePc(uint8_t *Buf, size_t FdeOff,
|
||||||
if ((Enc & 0x70) == DW_EH_PE_absptr)
|
if ((Enc & 0x70) == DW_EH_PE_absptr)
|
||||||
return Addr;
|
return Addr;
|
||||||
if ((Enc & 0x70) == DW_EH_PE_pcrel)
|
if ((Enc & 0x70) == DW_EH_PE_pcrel)
|
||||||
return Addr + this->getVA() + Off;
|
return Addr + this->Addr + Off;
|
||||||
fatal("unknown FDE size relative encoding");
|
fatal("unknown FDE size relative encoding");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1262,7 +1266,7 @@ template <class ELFT> void EhOutputSection<ELFT>::writeTo(uint8_t *Buf) {
|
||||||
uint8_t Enc = getFdeEncoding<ELFT>(Cie->Piece->data());
|
uint8_t Enc = getFdeEncoding<ELFT>(Cie->Piece->data());
|
||||||
for (SectionPiece *Fde : Cie->FdePieces) {
|
for (SectionPiece *Fde : Cie->FdePieces) {
|
||||||
uintX_t Pc = getFdePc(Buf, Fde->OutputOff, Enc);
|
uintX_t Pc = getFdePc(Buf, Fde->OutputOff, Enc);
|
||||||
uintX_t FdeVA = this->getVA() + Fde->OutputOff;
|
uintX_t FdeVA = this->Addr + Fde->OutputOff;
|
||||||
Out<ELFT>::EhFrameHdr->addFde(Pc, FdeVA);
|
Out<ELFT>::EhFrameHdr->addFde(Pc, FdeVA);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1284,7 +1288,7 @@ void MergeOutputSection<ELFT>::addSection(InputSectionBase<ELFT> *C) {
|
||||||
auto *Sec = cast<MergeInputSection<ELFT>>(C);
|
auto *Sec = cast<MergeInputSection<ELFT>>(C);
|
||||||
Sec->OutSec = this;
|
Sec->OutSec = this;
|
||||||
this->updateAlignment(Sec->Alignment);
|
this->updateAlignment(Sec->Alignment);
|
||||||
this->Header.sh_entsize = Sec->Entsize;
|
this->Entsize = Sec->Entsize;
|
||||||
Sections.push_back(Sec);
|
Sections.push_back(Sec);
|
||||||
|
|
||||||
auto HashI = Sec->Hashes.begin();
|
auto HashI = Sec->Hashes.begin();
|
||||||
|
|
@ -1308,7 +1312,7 @@ unsigned MergeOutputSection<ELFT>::getOffset(CachedHashStringRef Val) {
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class ELFT> bool MergeOutputSection<ELFT>::shouldTailMerge() const {
|
template <class ELFT> bool MergeOutputSection<ELFT>::shouldTailMerge() const {
|
||||||
return Config->Optimize >= 2 && this->Header.sh_flags & SHF_STRINGS;
|
return Config->Optimize >= 2 && this->Flags & SHF_STRINGS;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class ELFT> void MergeOutputSection<ELFT>::finalize() {
|
template <class ELFT> void MergeOutputSection<ELFT>::finalize() {
|
||||||
|
|
@ -1316,7 +1320,7 @@ template <class ELFT> void MergeOutputSection<ELFT>::finalize() {
|
||||||
Builder.finalize();
|
Builder.finalize();
|
||||||
else
|
else
|
||||||
Builder.finalizeInOrder();
|
Builder.finalizeInOrder();
|
||||||
this->Header.sh_size = Builder.getSize();
|
this->Size = Builder.getSize();
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class ELFT> void MergeOutputSection<ELFT>::finalizePieces() {
|
template <class ELFT> void MergeOutputSection<ELFT>::finalizePieces() {
|
||||||
|
|
@ -1330,7 +1334,7 @@ StringTableSection<ELFT>::StringTableSection(StringRef Name, bool Dynamic)
|
||||||
Dynamic ? (uintX_t)SHF_ALLOC : 0),
|
Dynamic ? (uintX_t)SHF_ALLOC : 0),
|
||||||
Dynamic(Dynamic) {
|
Dynamic(Dynamic) {
|
||||||
// ELF string tables start with a NUL byte, so 1.
|
// ELF string tables start with a NUL byte, so 1.
|
||||||
this->setSize(1);
|
this->Size = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Adds a string to the string table. If HashIt is true we hash and check for
|
// Adds a string to the string table. If HashIt is true we hash and check for
|
||||||
|
|
@ -1340,12 +1344,12 @@ StringTableSection<ELFT>::StringTableSection(StringRef Name, bool Dynamic)
|
||||||
template <class ELFT>
|
template <class ELFT>
|
||||||
unsigned StringTableSection<ELFT>::addString(StringRef S, bool HashIt) {
|
unsigned StringTableSection<ELFT>::addString(StringRef S, bool HashIt) {
|
||||||
if (HashIt) {
|
if (HashIt) {
|
||||||
auto R = StringMap.insert(std::make_pair(S, this->getSize()));
|
auto R = StringMap.insert(std::make_pair(S, this->Size));
|
||||||
if (!R.second)
|
if (!R.second)
|
||||||
return R.first->second;
|
return R.first->second;
|
||||||
}
|
}
|
||||||
unsigned Ret = this->getSize();
|
unsigned Ret = this->Size;
|
||||||
this->setSize(this->getSize() + S.size() + 1);
|
this->Size = this->Size + S.size() + 1;
|
||||||
Strings.push_back(S);
|
Strings.push_back(S);
|
||||||
return Ret;
|
return Ret;
|
||||||
}
|
}
|
||||||
|
|
@ -1362,8 +1366,8 @@ template <class ELFT> void StringTableSection<ELFT>::writeTo(uint8_t *Buf) {
|
||||||
template <class ELFT>
|
template <class ELFT>
|
||||||
typename ELFT::uint DynamicReloc<ELFT>::getOffset() const {
|
typename ELFT::uint DynamicReloc<ELFT>::getOffset() const {
|
||||||
if (OutputSec)
|
if (OutputSec)
|
||||||
return OutputSec->getVA() + OffsetInSec;
|
return OutputSec->Addr + OffsetInSec;
|
||||||
return InputSec->OutSec->getVA() + InputSec->getOffset(OffsetInSec);
|
return InputSec->OutSec->Addr + InputSec->getOffset(OffsetInSec);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class ELFT>
|
template <class ELFT>
|
||||||
|
|
@ -1386,8 +1390,8 @@ SymbolTableSection<ELFT>::SymbolTableSection(
|
||||||
StrTabSec.isDynamic() ? SHT_DYNSYM : SHT_SYMTAB,
|
StrTabSec.isDynamic() ? SHT_DYNSYM : SHT_SYMTAB,
|
||||||
StrTabSec.isDynamic() ? (uintX_t)SHF_ALLOC : 0),
|
StrTabSec.isDynamic() ? (uintX_t)SHF_ALLOC : 0),
|
||||||
StrTabSec(StrTabSec) {
|
StrTabSec(StrTabSec) {
|
||||||
this->Header.sh_entsize = sizeof(Elf_Sym);
|
this->Entsize = sizeof(Elf_Sym);
|
||||||
this->Header.sh_addralign = sizeof(uintX_t);
|
this->Addralign = sizeof(uintX_t);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Orders symbols according to their positions in the GOT,
|
// Orders symbols according to their positions in the GOT,
|
||||||
|
|
@ -1418,12 +1422,12 @@ static uint8_t getSymbolBinding(SymbolBody *Body) {
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class ELFT> void SymbolTableSection<ELFT>::finalize() {
|
template <class ELFT> void SymbolTableSection<ELFT>::finalize() {
|
||||||
if (this->Header.sh_size)
|
if (this->Size)
|
||||||
return; // Already finalized.
|
return; // Already finalized.
|
||||||
|
|
||||||
this->Header.sh_size = getNumSymbols() * sizeof(Elf_Sym);
|
this->Size = getNumSymbols() * sizeof(Elf_Sym);
|
||||||
this->Header.sh_link = StrTabSec.SectionIndex;
|
this->Link = StrTabSec.SectionIndex;
|
||||||
this->Header.sh_info = NumLocals + 1;
|
this->Info = NumLocals + 1;
|
||||||
|
|
||||||
if (Config->Relocatable) {
|
if (Config->Relocatable) {
|
||||||
size_t I = NumLocals;
|
size_t I = NumLocals;
|
||||||
|
|
@ -1485,7 +1489,7 @@ void SymbolTableSection<ELFT>::writeLocalSymbols(uint8_t *&Buf) {
|
||||||
} else {
|
} else {
|
||||||
const OutputSectionBase<ELFT> *OutSec = Section->OutSec;
|
const OutputSectionBase<ELFT> *OutSec = Section->OutSec;
|
||||||
ESym->st_shndx = OutSec->SectionIndex;
|
ESym->st_shndx = OutSec->SectionIndex;
|
||||||
ESym->st_value = OutSec->getVA() + Section->getOffset(Body);
|
ESym->st_value = OutSec->Addr + Section->getOffset(Body);
|
||||||
}
|
}
|
||||||
ESym->st_name = P.second;
|
ESym->st_name = P.second;
|
||||||
ESym->st_size = Body.template getSize<ELFT>();
|
ESym->st_size = Body.template getSize<ELFT>();
|
||||||
|
|
@ -1564,7 +1568,7 @@ SymbolTableSection<ELFT>::getOutputSection(SymbolBody *Sym) {
|
||||||
template <class ELFT>
|
template <class ELFT>
|
||||||
VersionDefinitionSection<ELFT>::VersionDefinitionSection()
|
VersionDefinitionSection<ELFT>::VersionDefinitionSection()
|
||||||
: OutputSectionBase<ELFT>(".gnu.version_d", SHT_GNU_verdef, SHF_ALLOC) {
|
: OutputSectionBase<ELFT>(".gnu.version_d", SHT_GNU_verdef, SHF_ALLOC) {
|
||||||
this->Header.sh_addralign = sizeof(uint32_t);
|
this->Addralign = sizeof(uint32_t);
|
||||||
}
|
}
|
||||||
|
|
||||||
static StringRef getFileDefName() {
|
static StringRef getFileDefName() {
|
||||||
|
|
@ -1578,14 +1582,13 @@ template <class ELFT> void VersionDefinitionSection<ELFT>::finalize() {
|
||||||
for (VersionDefinition &V : Config->VersionDefinitions)
|
for (VersionDefinition &V : Config->VersionDefinitions)
|
||||||
V.NameOff = Out<ELFT>::DynStrTab->addString(V.Name);
|
V.NameOff = Out<ELFT>::DynStrTab->addString(V.Name);
|
||||||
|
|
||||||
this->Header.sh_size =
|
this->Size = (sizeof(Elf_Verdef) + sizeof(Elf_Verdaux)) * getVerDefNum();
|
||||||
(sizeof(Elf_Verdef) + sizeof(Elf_Verdaux)) * getVerDefNum();
|
this->Link = Out<ELFT>::DynStrTab->SectionIndex;
|
||||||
this->Header.sh_link = Out<ELFT>::DynStrTab->SectionIndex;
|
|
||||||
|
|
||||||
// sh_info should be set to the number of definitions. This fact is missed in
|
// sh_info should be set to the number of definitions. This fact is missed in
|
||||||
// documentation, but confirmed by binutils community:
|
// documentation, but confirmed by binutils community:
|
||||||
// https://sourceware.org/ml/binutils/2014-11/msg00355.html
|
// https://sourceware.org/ml/binutils/2014-11/msg00355.html
|
||||||
this->Header.sh_info = getVerDefNum();
|
this->Info = getVerDefNum();
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class ELFT>
|
template <class ELFT>
|
||||||
|
|
@ -1622,16 +1625,16 @@ void VersionDefinitionSection<ELFT>::writeTo(uint8_t *Buf) {
|
||||||
template <class ELFT>
|
template <class ELFT>
|
||||||
VersionTableSection<ELFT>::VersionTableSection()
|
VersionTableSection<ELFT>::VersionTableSection()
|
||||||
: OutputSectionBase<ELFT>(".gnu.version", SHT_GNU_versym, SHF_ALLOC) {
|
: OutputSectionBase<ELFT>(".gnu.version", SHT_GNU_versym, SHF_ALLOC) {
|
||||||
this->Header.sh_addralign = sizeof(uint16_t);
|
this->Addralign = sizeof(uint16_t);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class ELFT> void VersionTableSection<ELFT>::finalize() {
|
template <class ELFT> void VersionTableSection<ELFT>::finalize() {
|
||||||
this->Header.sh_size =
|
this->Size =
|
||||||
sizeof(Elf_Versym) * (Out<ELFT>::DynSymTab->getSymbols().size() + 1);
|
sizeof(Elf_Versym) * (Out<ELFT>::DynSymTab->getSymbols().size() + 1);
|
||||||
this->Header.sh_entsize = sizeof(Elf_Versym);
|
this->Entsize = sizeof(Elf_Versym);
|
||||||
// At the moment of june 2016 GNU docs does not mention that sh_link field
|
// At the moment of june 2016 GNU docs does not mention that sh_link field
|
||||||
// should be set, but Sun docs do. Also readelf relies on this field.
|
// should be set, but Sun docs do. Also readelf relies on this field.
|
||||||
this->Header.sh_link = Out<ELFT>::DynSymTab->SectionIndex;
|
this->Link = Out<ELFT>::DynSymTab->SectionIndex;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class ELFT> void VersionTableSection<ELFT>::writeTo(uint8_t *Buf) {
|
template <class ELFT> void VersionTableSection<ELFT>::writeTo(uint8_t *Buf) {
|
||||||
|
|
@ -1645,7 +1648,7 @@ template <class ELFT> void VersionTableSection<ELFT>::writeTo(uint8_t *Buf) {
|
||||||
template <class ELFT>
|
template <class ELFT>
|
||||||
VersionNeedSection<ELFT>::VersionNeedSection()
|
VersionNeedSection<ELFT>::VersionNeedSection()
|
||||||
: OutputSectionBase<ELFT>(".gnu.version_r", SHT_GNU_verneed, SHF_ALLOC) {
|
: OutputSectionBase<ELFT>(".gnu.version_r", SHT_GNU_verneed, SHF_ALLOC) {
|
||||||
this->Header.sh_addralign = sizeof(uint32_t);
|
this->Addralign = sizeof(uint32_t);
|
||||||
|
|
||||||
// Identifiers in verneed section start at 2 because 0 and 1 are reserved
|
// Identifiers in verneed section start at 2 because 0 and 1 are reserved
|
||||||
// for VER_NDX_LOCAL and VER_NDX_GLOBAL.
|
// for VER_NDX_LOCAL and VER_NDX_GLOBAL.
|
||||||
|
|
@ -1713,20 +1716,20 @@ template <class ELFT> void VersionNeedSection<ELFT>::writeTo(uint8_t *Buf) {
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class ELFT> void VersionNeedSection<ELFT>::finalize() {
|
template <class ELFT> void VersionNeedSection<ELFT>::finalize() {
|
||||||
this->Header.sh_link = Out<ELFT>::DynStrTab->SectionIndex;
|
this->Link = Out<ELFT>::DynStrTab->SectionIndex;
|
||||||
this->Header.sh_info = Needed.size();
|
this->Info = Needed.size();
|
||||||
unsigned Size = Needed.size() * sizeof(Elf_Verneed);
|
unsigned Size = Needed.size() * sizeof(Elf_Verneed);
|
||||||
for (std::pair<SharedFile<ELFT> *, size_t> &P : Needed)
|
for (std::pair<SharedFile<ELFT> *, size_t> &P : Needed)
|
||||||
Size += P.first->VerdefMap.size() * sizeof(Elf_Vernaux);
|
Size += P.first->VerdefMap.size() * sizeof(Elf_Vernaux);
|
||||||
this->Header.sh_size = Size;
|
this->Size = Size;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class ELFT>
|
template <class ELFT>
|
||||||
MipsReginfoOutputSection<ELFT>::MipsReginfoOutputSection()
|
MipsReginfoOutputSection<ELFT>::MipsReginfoOutputSection()
|
||||||
: OutputSectionBase<ELFT>(".reginfo", SHT_MIPS_REGINFO, SHF_ALLOC) {
|
: OutputSectionBase<ELFT>(".reginfo", SHT_MIPS_REGINFO, SHF_ALLOC) {
|
||||||
this->Header.sh_addralign = 4;
|
this->Addralign = 4;
|
||||||
this->Header.sh_entsize = sizeof(Elf_Mips_RegInfo);
|
this->Entsize = sizeof(Elf_Mips_RegInfo);
|
||||||
this->Header.sh_size = sizeof(Elf_Mips_RegInfo);
|
this->Size = sizeof(Elf_Mips_RegInfo);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class ELFT>
|
template <class ELFT>
|
||||||
|
|
@ -1735,7 +1738,7 @@ void MipsReginfoOutputSection<ELFT>::writeTo(uint8_t *Buf) {
|
||||||
if (Config->Relocatable)
|
if (Config->Relocatable)
|
||||||
R->ri_gp_value = 0;
|
R->ri_gp_value = 0;
|
||||||
else
|
else
|
||||||
R->ri_gp_value = Out<ELFT>::Got->getVA() + MipsGPOffset;
|
R->ri_gp_value = Out<ELFT>::Got->Addr + MipsGPOffset;
|
||||||
R->ri_gprmask = GprMask;
|
R->ri_gprmask = GprMask;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1751,23 +1754,23 @@ template <class ELFT>
|
||||||
MipsOptionsOutputSection<ELFT>::MipsOptionsOutputSection()
|
MipsOptionsOutputSection<ELFT>::MipsOptionsOutputSection()
|
||||||
: OutputSectionBase<ELFT>(".MIPS.options", SHT_MIPS_OPTIONS,
|
: OutputSectionBase<ELFT>(".MIPS.options", SHT_MIPS_OPTIONS,
|
||||||
SHF_ALLOC | SHF_MIPS_NOSTRIP) {
|
SHF_ALLOC | SHF_MIPS_NOSTRIP) {
|
||||||
this->Header.sh_addralign = 8;
|
this->Addralign = 8;
|
||||||
this->Header.sh_entsize = 1;
|
this->Entsize = 1;
|
||||||
this->Header.sh_size = sizeof(Elf_Mips_Options) + sizeof(Elf_Mips_RegInfo);
|
this->Size = sizeof(Elf_Mips_Options) + sizeof(Elf_Mips_RegInfo);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class ELFT>
|
template <class ELFT>
|
||||||
void MipsOptionsOutputSection<ELFT>::writeTo(uint8_t *Buf) {
|
void MipsOptionsOutputSection<ELFT>::writeTo(uint8_t *Buf) {
|
||||||
auto *Opt = reinterpret_cast<Elf_Mips_Options *>(Buf);
|
auto *Opt = reinterpret_cast<Elf_Mips_Options *>(Buf);
|
||||||
Opt->kind = ODK_REGINFO;
|
Opt->kind = ODK_REGINFO;
|
||||||
Opt->size = this->Header.sh_size;
|
Opt->size = this->Size;
|
||||||
Opt->section = 0;
|
Opt->section = 0;
|
||||||
Opt->info = 0;
|
Opt->info = 0;
|
||||||
auto *Reg = reinterpret_cast<Elf_Mips_RegInfo *>(Buf + sizeof(*Opt));
|
auto *Reg = reinterpret_cast<Elf_Mips_RegInfo *>(Buf + sizeof(*Opt));
|
||||||
if (Config->Relocatable)
|
if (Config->Relocatable)
|
||||||
Reg->ri_gp_value = 0;
|
Reg->ri_gp_value = 0;
|
||||||
else
|
else
|
||||||
Reg->ri_gp_value = Out<ELFT>::Got->getVA() + MipsGPOffset;
|
Reg->ri_gp_value = Out<ELFT>::Got->Addr + MipsGPOffset;
|
||||||
Reg->ri_gprmask = GprMask;
|
Reg->ri_gprmask = GprMask;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1782,9 +1785,9 @@ void MipsOptionsOutputSection<ELFT>::addSection(InputSectionBase<ELFT> *C) {
|
||||||
template <class ELFT>
|
template <class ELFT>
|
||||||
MipsAbiFlagsOutputSection<ELFT>::MipsAbiFlagsOutputSection()
|
MipsAbiFlagsOutputSection<ELFT>::MipsAbiFlagsOutputSection()
|
||||||
: OutputSectionBase<ELFT>(".MIPS.abiflags", SHT_MIPS_ABIFLAGS, SHF_ALLOC) {
|
: OutputSectionBase<ELFT>(".MIPS.abiflags", SHT_MIPS_ABIFLAGS, SHF_ALLOC) {
|
||||||
this->Header.sh_addralign = 8;
|
this->Addralign = 8;
|
||||||
this->Header.sh_entsize = sizeof(Elf_Mips_ABIFlags);
|
this->Entsize = sizeof(Elf_Mips_ABIFlags);
|
||||||
this->Header.sh_size = sizeof(Elf_Mips_ABIFlags);
|
this->Size = sizeof(Elf_Mips_ABIFlags);
|
||||||
memset(&Flags, 0, sizeof(Flags));
|
memset(&Flags, 0, sizeof(Flags));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1859,7 +1862,7 @@ OutputSectionFactory<ELFT>::create(const SectionKey<ELFT::Is64Bits> &Key,
|
||||||
uintX_t Flags = getOutFlags(C);
|
uintX_t Flags = getOutFlags(C);
|
||||||
OutputSectionBase<ELFT> *&Sec = Map[Key];
|
OutputSectionBase<ELFT> *&Sec = Map[Key];
|
||||||
if (Sec) {
|
if (Sec) {
|
||||||
Sec->updateFlags(Flags);
|
Sec->Flags |= Flags;
|
||||||
return {Sec, false};
|
return {Sec, false};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -71,13 +71,8 @@ public:
|
||||||
};
|
};
|
||||||
|
|
||||||
OutputSectionBase(StringRef Name, uint32_t Type, uintX_t Flags);
|
OutputSectionBase(StringRef Name, uint32_t Type, uintX_t Flags);
|
||||||
void setVA(uintX_t VA) { Header.sh_addr = VA; }
|
|
||||||
uintX_t getVA() const { return Header.sh_addr; }
|
|
||||||
void setLMAOffset(uintX_t LMAOff) { LMAOffset = LMAOff; }
|
void setLMAOffset(uintX_t LMAOff) { LMAOffset = LMAOff; }
|
||||||
uintX_t getLMA() const { return Header.sh_addr + LMAOffset; }
|
uintX_t getLMA() const { return Addr + LMAOffset; }
|
||||||
void setFileOffset(uintX_t Off) { Header.sh_offset = Off; }
|
|
||||||
uintX_t getFileOffset() { return Header.sh_offset; }
|
|
||||||
void setSHName(unsigned Val) { Header.sh_name = Val; }
|
|
||||||
void writeHeaderTo(Elf_Shdr *SHdr);
|
void writeHeaderTo(Elf_Shdr *SHdr);
|
||||||
StringRef getName() const { return Name; }
|
StringRef getName() const { return Name; }
|
||||||
|
|
||||||
|
|
@ -89,19 +84,11 @@ public:
|
||||||
|
|
||||||
unsigned SectionIndex;
|
unsigned SectionIndex;
|
||||||
|
|
||||||
// Returns the size of the section in the output file.
|
|
||||||
uintX_t getSize() const { return Header.sh_size; }
|
|
||||||
void setSize(uintX_t Val) { Header.sh_size = Val; }
|
|
||||||
uintX_t getFlags() const { return Header.sh_flags; }
|
|
||||||
void updateFlags(uintX_t Val) { Header.sh_flags |= Val; }
|
|
||||||
uint32_t getPhdrFlags() const;
|
uint32_t getPhdrFlags() const;
|
||||||
uintX_t getFileOff() const { return Header.sh_offset; }
|
|
||||||
uintX_t getAlignment() const { return Header.sh_addralign; }
|
|
||||||
uint32_t getType() const { return Header.sh_type; }
|
|
||||||
|
|
||||||
void updateAlignment(uintX_t Alignment) {
|
void updateAlignment(uintX_t Alignment) {
|
||||||
if (Alignment > Header.sh_addralign)
|
if (Alignment > Addralign)
|
||||||
Header.sh_addralign = Alignment;
|
Addralign = Alignment;
|
||||||
}
|
}
|
||||||
|
|
||||||
// If true, this section will be page aligned on disk.
|
// If true, this section will be page aligned on disk.
|
||||||
|
|
@ -122,10 +109,20 @@ public:
|
||||||
virtual void writeTo(uint8_t *Buf) {}
|
virtual void writeTo(uint8_t *Buf) {}
|
||||||
virtual ~OutputSectionBase() = default;
|
virtual ~OutputSectionBase() = default;
|
||||||
|
|
||||||
protected:
|
|
||||||
StringRef Name;
|
StringRef Name;
|
||||||
Elf_Shdr Header;
|
|
||||||
|
// The following fields correspond to Elf_Shdr members.
|
||||||
|
uintX_t Size = 0;
|
||||||
|
uintX_t Entsize = 0;
|
||||||
|
uintX_t Addralign = 0;
|
||||||
|
uintX_t Offset = 0;
|
||||||
|
uintX_t Flags = 0;
|
||||||
uintX_t LMAOffset = 0;
|
uintX_t LMAOffset = 0;
|
||||||
|
uintX_t Addr = 0;
|
||||||
|
uint32_t ShName = 0;
|
||||||
|
uint32_t Type = 0;
|
||||||
|
uint32_t Info = 0;
|
||||||
|
uint32_t Link = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
template <class ELFT>
|
template <class ELFT>
|
||||||
|
|
@ -187,7 +184,7 @@ public:
|
||||||
// after 'local' and 'global' entries.
|
// after 'local' and 'global' entries.
|
||||||
uintX_t getMipsTlsOffset() const;
|
uintX_t getMipsTlsOffset() const;
|
||||||
|
|
||||||
uintX_t getTlsIndexVA() { return Base::getVA() + TlsIndexOff; }
|
uintX_t getTlsIndexVA() { return this->Addr + TlsIndexOff; }
|
||||||
uint32_t getTlsIndexOff() const { return TlsIndexOff; }
|
uint32_t getTlsIndexOff() const { return TlsIndexOff; }
|
||||||
|
|
||||||
// Flag to force GOT to be in output if we have relocations
|
// Flag to force GOT to be in output if we have relocations
|
||||||
|
|
@ -794,7 +791,7 @@ private:
|
||||||
template <class ELFT> uint64_t getHeaderSize() {
|
template <class ELFT> uint64_t getHeaderSize() {
|
||||||
if (Config->OFormatBinary)
|
if (Config->OFormatBinary)
|
||||||
return 0;
|
return 0;
|
||||||
return Out<ELFT>::ElfHeader->getSize() + Out<ELFT>::ProgramHeaders->getSize();
|
return Out<ELFT>::ElfHeader->Size + Out<ELFT>::ProgramHeaders->Size;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class ELFT> uint8_t Out<ELFT>::First;
|
template <class ELFT> uint8_t Out<ELFT>::First;
|
||||||
|
|
|
||||||
|
|
@ -394,8 +394,8 @@ template <class ELFT> static void addCopyRelSymbol(SharedSymbol<ELFT> *SS) {
|
||||||
fatal("cannot create a copy relocation for symbol " + SS->getName());
|
fatal("cannot create a copy relocation for symbol " + SS->getName());
|
||||||
|
|
||||||
uintX_t Alignment = getAlignment(SS);
|
uintX_t Alignment = getAlignment(SS);
|
||||||
uintX_t Off = alignTo(Out<ELFT>::Bss->getSize(), Alignment);
|
uintX_t Off = alignTo(Out<ELFT>::Bss->Size, Alignment);
|
||||||
Out<ELFT>::Bss->setSize(Off + SymSize);
|
Out<ELFT>::Bss->Size = Off + SymSize;
|
||||||
Out<ELFT>::Bss->updateAlignment(Alignment);
|
Out<ELFT>::Bss->updateAlignment(Alignment);
|
||||||
uintX_t Shndx = SS->Sym.st_shndx;
|
uintX_t Shndx = SS->Sym.st_shndx;
|
||||||
uintX_t Value = SS->Sym.st_value;
|
uintX_t Value = SS->Sym.st_value;
|
||||||
|
|
|
||||||
|
|
@ -37,8 +37,8 @@ static typename ELFT::uint getSymVA(const SymbolBody &Body,
|
||||||
if (!Sec)
|
if (!Sec)
|
||||||
return D.Value;
|
return D.Value;
|
||||||
if (D.Value == DefinedSynthetic<ELFT>::SectionEnd)
|
if (D.Value == DefinedSynthetic<ELFT>::SectionEnd)
|
||||||
return Sec->getVA() + Sec->getSize();
|
return Sec->Addr + Sec->Size;
|
||||||
return Sec->getVA() + D.Value;
|
return Sec->Addr + D.Value;
|
||||||
}
|
}
|
||||||
case SymbolBody::DefinedRegularKind: {
|
case SymbolBody::DefinedRegularKind: {
|
||||||
auto &D = cast<DefinedRegular<ELFT>>(Body);
|
auto &D = cast<DefinedRegular<ELFT>>(Body);
|
||||||
|
|
@ -60,7 +60,7 @@ static typename ELFT::uint getSymVA(const SymbolBody &Body,
|
||||||
Offset += Addend;
|
Offset += Addend;
|
||||||
Addend = 0;
|
Addend = 0;
|
||||||
}
|
}
|
||||||
uintX_t VA = (SC->OutSec ? SC->OutSec->getVA() : 0) + SC->getOffset(Offset);
|
uintX_t VA = (SC->OutSec ? SC->OutSec->Addr : 0) + SC->getOffset(Offset);
|
||||||
if (D.isTls() && !Config->Relocatable) {
|
if (D.isTls() && !Config->Relocatable) {
|
||||||
if (!Out<ELFT>::TlsPhdr)
|
if (!Out<ELFT>::TlsPhdr)
|
||||||
fatal(getFilename(D.File) +
|
fatal(getFilename(D.File) +
|
||||||
|
|
@ -70,7 +70,7 @@ static typename ELFT::uint getSymVA(const SymbolBody &Body,
|
||||||
return VA;
|
return VA;
|
||||||
}
|
}
|
||||||
case SymbolBody::DefinedCommonKind:
|
case SymbolBody::DefinedCommonKind:
|
||||||
return In<ELFT>::Common->OutSec->getVA() + In<ELFT>::Common->OutSecOff +
|
return In<ELFT>::Common->OutSec->Addr + In<ELFT>::Common->OutSecOff +
|
||||||
cast<DefinedCommon>(Body).Offset;
|
cast<DefinedCommon>(Body).Offset;
|
||||||
case SymbolBody::SharedKind: {
|
case SymbolBody::SharedKind: {
|
||||||
auto &SS = cast<SharedSymbol<ELFT>>(Body);
|
auto &SS = cast<SharedSymbol<ELFT>>(Body);
|
||||||
|
|
@ -78,7 +78,7 @@ static typename ELFT::uint getSymVA(const SymbolBody &Body,
|
||||||
return 0;
|
return 0;
|
||||||
if (SS.isFunc())
|
if (SS.isFunc())
|
||||||
return Body.getPltVA<ELFT>();
|
return Body.getPltVA<ELFT>();
|
||||||
return Out<ELFT>::Bss->getVA() + SS.OffsetInBss;
|
return Out<ELFT>::Bss->Addr + SS.OffsetInBss;
|
||||||
}
|
}
|
||||||
case SymbolBody::UndefinedKind:
|
case SymbolBody::UndefinedKind:
|
||||||
return 0;
|
return 0;
|
||||||
|
|
@ -151,7 +151,7 @@ typename ELFT::uint SymbolBody::getVA(typename ELFT::uint Addend) const {
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class ELFT> typename ELFT::uint SymbolBody::getGotVA() const {
|
template <class ELFT> typename ELFT::uint SymbolBody::getGotVA() const {
|
||||||
return Out<ELFT>::Got->getVA() + getGotOffset<ELFT>();
|
return Out<ELFT>::Got->Addr + getGotOffset<ELFT>();
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class ELFT> typename ELFT::uint SymbolBody::getGotOffset() const {
|
template <class ELFT> typename ELFT::uint SymbolBody::getGotOffset() const {
|
||||||
|
|
@ -159,7 +159,7 @@ template <class ELFT> typename ELFT::uint SymbolBody::getGotOffset() const {
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class ELFT> typename ELFT::uint SymbolBody::getGotPltVA() const {
|
template <class ELFT> typename ELFT::uint SymbolBody::getGotPltVA() const {
|
||||||
return Out<ELFT>::GotPlt->getVA() + getGotPltOffset<ELFT>();
|
return Out<ELFT>::GotPlt->Addr + getGotPltOffset<ELFT>();
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class ELFT> typename ELFT::uint SymbolBody::getGotPltOffset() const {
|
template <class ELFT> typename ELFT::uint SymbolBody::getGotPltOffset() const {
|
||||||
|
|
@ -167,7 +167,7 @@ template <class ELFT> typename ELFT::uint SymbolBody::getGotPltOffset() const {
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class ELFT> typename ELFT::uint SymbolBody::getPltVA() const {
|
template <class ELFT> typename ELFT::uint SymbolBody::getPltVA() const {
|
||||||
return Out<ELFT>::Plt->getVA() + Target->PltHeaderSize +
|
return Out<ELFT>::Plt->Addr + Target->PltHeaderSize +
|
||||||
PltIndex * Target->PltEntrySize;
|
PltIndex * Target->PltEntrySize;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -107,7 +107,7 @@ BuildIdSection<ELFT>::BuildIdSection(size_t HashSize)
|
||||||
|
|
||||||
template <class ELFT>
|
template <class ELFT>
|
||||||
uint8_t *BuildIdSection<ELFT>::getOutputLoc(uint8_t *Start) const {
|
uint8_t *BuildIdSection<ELFT>::getOutputLoc(uint8_t *Start) const {
|
||||||
return Start + this->OutSec->getFileOffset() + this->OutSecOff;
|
return Start + this->OutSec->Offset + this->OutSecOff;
|
||||||
}
|
}
|
||||||
|
|
||||||
static std::vector<ArrayRef<uint8_t>> split(ArrayRef<uint8_t> Arr,
|
static std::vector<ArrayRef<uint8_t>> split(ArrayRef<uint8_t> Arr,
|
||||||
|
|
|
||||||
|
|
@ -355,7 +355,7 @@ RelExpr X86TargetInfo::adjustRelaxExpr(uint32_t Type, const uint8_t *Data,
|
||||||
}
|
}
|
||||||
|
|
||||||
void X86TargetInfo::writeGotPltHeader(uint8_t *Buf) const {
|
void X86TargetInfo::writeGotPltHeader(uint8_t *Buf) const {
|
||||||
write32le(Buf, Out<ELF32LE>::Dynamic->getVA());
|
write32le(Buf, Out<ELF32LE>::Dynamic->Addr);
|
||||||
}
|
}
|
||||||
|
|
||||||
void X86TargetInfo::writeGotPlt(uint8_t *Buf, const SymbolBody &S) const {
|
void X86TargetInfo::writeGotPlt(uint8_t *Buf, const SymbolBody &S) const {
|
||||||
|
|
@ -403,7 +403,7 @@ void X86TargetInfo::writePltHeader(uint8_t *Buf) const {
|
||||||
0x90, 0x90, 0x90, 0x90 // nop; nop; nop; nop
|
0x90, 0x90, 0x90, 0x90 // nop; nop; nop; nop
|
||||||
};
|
};
|
||||||
memcpy(Buf, PltData, sizeof(PltData));
|
memcpy(Buf, PltData, sizeof(PltData));
|
||||||
uint32_t Got = Out<ELF32LE>::GotPlt->getVA();
|
uint32_t Got = Out<ELF32LE>::GotPlt->Addr;
|
||||||
write32le(Buf + 2, Got + 4);
|
write32le(Buf + 2, Got + 4);
|
||||||
write32le(Buf + 8, Got + 8);
|
write32le(Buf + 8, Got + 8);
|
||||||
}
|
}
|
||||||
|
|
@ -420,7 +420,7 @@ void X86TargetInfo::writePlt(uint8_t *Buf, uint64_t GotEntryAddr,
|
||||||
|
|
||||||
// jmp *foo@GOT(%ebx) or jmp *foo_in_GOT
|
// jmp *foo@GOT(%ebx) or jmp *foo_in_GOT
|
||||||
Buf[1] = Config->Pic ? 0xa3 : 0x25;
|
Buf[1] = Config->Pic ? 0xa3 : 0x25;
|
||||||
uint32_t Got = Out<ELF32LE>::GotPlt->getVA();
|
uint32_t Got = Out<ELF32LE>::GotPlt->Addr;
|
||||||
write32le(Buf + 2, Config->Shared ? GotEntryAddr - Got : GotEntryAddr);
|
write32le(Buf + 2, Config->Shared ? GotEntryAddr - Got : GotEntryAddr);
|
||||||
write32le(Buf + 7, RelOff);
|
write32le(Buf + 7, RelOff);
|
||||||
write32le(Buf + 12, -Index * PltEntrySize - PltHeaderSize - 16);
|
write32le(Buf + 12, -Index * PltEntrySize - PltHeaderSize - 16);
|
||||||
|
|
@ -595,7 +595,7 @@ void X86_64TargetInfo<ELFT>::writeGotPltHeader(uint8_t *Buf) const {
|
||||||
// required, but it is documented in the psabi and the glibc dynamic linker
|
// required, but it is documented in the psabi and the glibc dynamic linker
|
||||||
// seems to use it (note that this is relevant for linking ld.so, not any
|
// seems to use it (note that this is relevant for linking ld.so, not any
|
||||||
// other program).
|
// other program).
|
||||||
write64le(Buf, Out<ELFT>::Dynamic->getVA());
|
write64le(Buf, Out<ELFT>::Dynamic->Addr);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class ELFT>
|
template <class ELFT>
|
||||||
|
|
@ -613,8 +613,8 @@ void X86_64TargetInfo<ELFT>::writePltHeader(uint8_t *Buf) const {
|
||||||
0x0f, 0x1f, 0x40, 0x00 // nopl 0x0(rax)
|
0x0f, 0x1f, 0x40, 0x00 // nopl 0x0(rax)
|
||||||
};
|
};
|
||||||
memcpy(Buf, PltData, sizeof(PltData));
|
memcpy(Buf, PltData, sizeof(PltData));
|
||||||
uint64_t Got = Out<ELFT>::GotPlt->getVA();
|
uint64_t Got = Out<ELFT>::GotPlt->Addr;
|
||||||
uint64_t Plt = Out<ELFT>::Plt->getVA();
|
uint64_t Plt = Out<ELFT>::Plt->Addr;
|
||||||
write32le(Buf + 2, Got - Plt + 2); // GOT+8
|
write32le(Buf + 2, Got - Plt + 2); // GOT+8
|
||||||
write32le(Buf + 8, Got - Plt + 4); // GOT+16
|
write32le(Buf + 8, Got - Plt + 4); // GOT+16
|
||||||
}
|
}
|
||||||
|
|
@ -1019,7 +1019,7 @@ uint64_t getPPC64TocBase() {
|
||||||
// TOC starts where the first of these sections starts. We always create a
|
// TOC starts where the first of these sections starts. We always create a
|
||||||
// .got when we see a relocation that uses it, so for us the start is always
|
// .got when we see a relocation that uses it, so for us the start is always
|
||||||
// the .got.
|
// the .got.
|
||||||
uint64_t TocVA = Out<ELF64BE>::Got->getVA();
|
uint64_t TocVA = Out<ELF64BE>::Got->Addr;
|
||||||
|
|
||||||
// Per the ppc64-elf-linux ABI, The TOC base is TOC value plus 0x8000
|
// Per the ppc64-elf-linux ABI, The TOC base is TOC value plus 0x8000
|
||||||
// thus permitting a full 64 Kbytes segment. Note that the glibc startup
|
// thus permitting a full 64 Kbytes segment. Note that the glibc startup
|
||||||
|
|
@ -1254,7 +1254,7 @@ uint32_t AArch64TargetInfo::getDynRel(uint32_t Type) const {
|
||||||
}
|
}
|
||||||
|
|
||||||
void AArch64TargetInfo::writeGotPlt(uint8_t *Buf, const SymbolBody &) const {
|
void AArch64TargetInfo::writeGotPlt(uint8_t *Buf, const SymbolBody &) const {
|
||||||
write64le(Buf, Out<ELF64LE>::Plt->getVA());
|
write64le(Buf, Out<ELF64LE>::Plt->Addr);
|
||||||
}
|
}
|
||||||
|
|
||||||
static uint64_t getAArch64Page(uint64_t Expr) {
|
static uint64_t getAArch64Page(uint64_t Expr) {
|
||||||
|
|
@ -1274,8 +1274,8 @@ void AArch64TargetInfo::writePltHeader(uint8_t *Buf) const {
|
||||||
};
|
};
|
||||||
memcpy(Buf, PltData, sizeof(PltData));
|
memcpy(Buf, PltData, sizeof(PltData));
|
||||||
|
|
||||||
uint64_t Got = Out<ELF64LE>::GotPlt->getVA();
|
uint64_t Got = Out<ELF64LE>::GotPlt->Addr;
|
||||||
uint64_t Plt = Out<ELF64LE>::Plt->getVA();
|
uint64_t Plt = Out<ELF64LE>::Plt->Addr;
|
||||||
relocateOne(Buf + 4, R_AARCH64_ADR_PREL_PG_HI21,
|
relocateOne(Buf + 4, R_AARCH64_ADR_PREL_PG_HI21,
|
||||||
getAArch64Page(Got + 16) - getAArch64Page(Plt + 4));
|
getAArch64Page(Got + 16) - getAArch64Page(Plt + 4));
|
||||||
relocateOne(Buf + 8, R_AARCH64_LDST64_ABS_LO12_NC, Got + 16);
|
relocateOne(Buf + 8, R_AARCH64_LDST64_ABS_LO12_NC, Got + 16);
|
||||||
|
|
@ -1616,7 +1616,7 @@ uint32_t ARMTargetInfo::getDynRel(uint32_t Type) const {
|
||||||
}
|
}
|
||||||
|
|
||||||
void ARMTargetInfo::writeGotPlt(uint8_t *Buf, const SymbolBody &) const {
|
void ARMTargetInfo::writeGotPlt(uint8_t *Buf, const SymbolBody &) const {
|
||||||
write32le(Buf, Out<ELF32LE>::Plt->getVA());
|
write32le(Buf, Out<ELF32LE>::Plt->Addr);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ARMTargetInfo::writePltHeader(uint8_t *Buf) const {
|
void ARMTargetInfo::writePltHeader(uint8_t *Buf) const {
|
||||||
|
|
@ -1628,8 +1628,8 @@ void ARMTargetInfo::writePltHeader(uint8_t *Buf) const {
|
||||||
0x00, 0x00, 0x00, 0x00, // L2: .word &(.got.plt) - L1 - 8
|
0x00, 0x00, 0x00, 0x00, // L2: .word &(.got.plt) - L1 - 8
|
||||||
};
|
};
|
||||||
memcpy(Buf, PltData, sizeof(PltData));
|
memcpy(Buf, PltData, sizeof(PltData));
|
||||||
uint64_t GotPlt = Out<ELF32LE>::GotPlt->getVA();
|
uint64_t GotPlt = Out<ELF32LE>::GotPlt->Addr;
|
||||||
uint64_t L1 = Out<ELF32LE>::Plt->getVA() + 8;
|
uint64_t L1 = Out<ELF32LE>::Plt->Addr + 8;
|
||||||
write32le(Buf + 16, GotPlt - L1 - 8);
|
write32le(Buf + 16, GotPlt - L1 - 8);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1996,7 +1996,7 @@ bool MipsTargetInfo<ELFT>::isTlsGlobalDynamicRel(uint32_t Type) const {
|
||||||
|
|
||||||
template <class ELFT>
|
template <class ELFT>
|
||||||
void MipsTargetInfo<ELFT>::writeGotPlt(uint8_t *Buf, const SymbolBody &) const {
|
void MipsTargetInfo<ELFT>::writeGotPlt(uint8_t *Buf, const SymbolBody &) const {
|
||||||
write32<ELFT::TargetEndianness>(Buf, Out<ELFT>::Plt->getVA());
|
write32<ELFT::TargetEndianness>(Buf, Out<ELFT>::Plt->Addr);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <endianness E, uint8_t BSIZE, uint8_t SHIFT>
|
template <endianness E, uint8_t BSIZE, uint8_t SHIFT>
|
||||||
|
|
@ -2063,7 +2063,7 @@ void MipsTargetInfo<ELFT>::writePltHeader(uint8_t *Buf) const {
|
||||||
write32<E>(Buf + 20, 0x0018c082); // srl $24, $24, 2
|
write32<E>(Buf + 20, 0x0018c082); // srl $24, $24, 2
|
||||||
write32<E>(Buf + 24, 0x0320f809); // jalr $25
|
write32<E>(Buf + 24, 0x0320f809); // jalr $25
|
||||||
write32<E>(Buf + 28, 0x2718fffe); // subu $24, $24, 2
|
write32<E>(Buf + 28, 0x2718fffe); // subu $24, $24, 2
|
||||||
uint64_t Got = Out<ELFT>::GotPlt->getVA();
|
uint64_t Got = Out<ELFT>::GotPlt->Addr;
|
||||||
writeMipsHi16<E>(Buf, Got);
|
writeMipsHi16<E>(Buf, Got);
|
||||||
writeMipsLo16<E>(Buf + 4, Got);
|
writeMipsLo16<E>(Buf + 4, Got);
|
||||||
writeMipsLo16<E>(Buf + 8, Got);
|
writeMipsLo16<E>(Buf + 8, Got);
|
||||||
|
|
|
||||||
|
|
@ -183,7 +183,7 @@ Thunk<ELFT>::Thunk(const SymbolBody &D, const InputSection<ELFT> &O)
|
||||||
: Destination(D), Owner(O), Offset(O.getThunkOff() + O.getThunksSize()) {}
|
: Destination(D), Owner(O), Offset(O.getThunkOff() + O.getThunksSize()) {}
|
||||||
|
|
||||||
template <class ELFT> typename ELFT::uint Thunk<ELFT>::getVA() const {
|
template <class ELFT> typename ELFT::uint Thunk<ELFT>::getVA() const {
|
||||||
return Owner.OutSec->getVA() + Owner.OutSecOff + Offset;
|
return Owner.OutSec->Addr + Owner.OutSecOff + Offset;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class ELFT> Thunk<ELFT>::~Thunk() = default;
|
template <class ELFT> Thunk<ELFT>::~Thunk() = default;
|
||||||
|
|
|
||||||
|
|
@ -222,7 +222,7 @@ template <class ELFT> void Writer<ELFT>::createSyntheticSections() {
|
||||||
Out<ELFT>::VerNeed = make<VersionNeedSection<ELFT>>();
|
Out<ELFT>::VerNeed = make<VersionNeedSection<ELFT>>();
|
||||||
|
|
||||||
Out<ELFT>::ElfHeader = make<OutputSectionBase<ELFT>>("", 0, SHF_ALLOC);
|
Out<ELFT>::ElfHeader = make<OutputSectionBase<ELFT>>("", 0, SHF_ALLOC);
|
||||||
Out<ELFT>::ElfHeader->setSize(sizeof(Elf_Ehdr));
|
Out<ELFT>::ElfHeader->Size = sizeof(Elf_Ehdr);
|
||||||
Out<ELFT>::ProgramHeaders = make<OutputSectionBase<ELFT>>("", 0, SHF_ALLOC);
|
Out<ELFT>::ProgramHeaders = make<OutputSectionBase<ELFT>>("", 0, SHF_ALLOC);
|
||||||
Out<ELFT>::ProgramHeaders->updateAlignment(sizeof(uintX_t));
|
Out<ELFT>::ProgramHeaders->updateAlignment(sizeof(uintX_t));
|
||||||
|
|
||||||
|
|
@ -263,7 +263,7 @@ template <class ELFT> void Writer<ELFT>::createSyntheticSections() {
|
||||||
// ftp://www.linux-mips.org/pub/linux/mips/doc/ABI/mipsabi.pdf
|
// ftp://www.linux-mips.org/pub/linux/mips/doc/ABI/mipsabi.pdf
|
||||||
Out<ELFT>::MipsRldMap = make<OutputSection<ELFT>>(".rld_map", SHT_PROGBITS,
|
Out<ELFT>::MipsRldMap = make<OutputSection<ELFT>>(".rld_map", SHT_PROGBITS,
|
||||||
SHF_ALLOC | SHF_WRITE);
|
SHF_ALLOC | SHF_WRITE);
|
||||||
Out<ELFT>::MipsRldMap->setSize(sizeof(uintX_t));
|
Out<ELFT>::MipsRldMap->Size = sizeof(uintX_t);
|
||||||
Out<ELFT>::MipsRldMap->updateAlignment(sizeof(uintX_t));
|
Out<ELFT>::MipsRldMap->updateAlignment(sizeof(uintX_t));
|
||||||
}
|
}
|
||||||
if (!Config->VersionDefinitions.empty())
|
if (!Config->VersionDefinitions.empty())
|
||||||
|
|
@ -394,12 +394,12 @@ template <class ELFT>
|
||||||
bool elf::isRelroSection(const OutputSectionBase<ELFT> *Sec) {
|
bool elf::isRelroSection(const OutputSectionBase<ELFT> *Sec) {
|
||||||
if (!Config->ZRelro)
|
if (!Config->ZRelro)
|
||||||
return false;
|
return false;
|
||||||
typename ELFT::uint Flags = Sec->getFlags();
|
typename ELFT::uint Flags = Sec->Flags;
|
||||||
if (!(Flags & SHF_ALLOC) || !(Flags & SHF_WRITE))
|
if (!(Flags & SHF_ALLOC) || !(Flags & SHF_WRITE))
|
||||||
return false;
|
return false;
|
||||||
if (Flags & SHF_TLS)
|
if (Flags & SHF_TLS)
|
||||||
return true;
|
return true;
|
||||||
uint32_t Type = Sec->getType();
|
uint32_t Type = Sec->Type;
|
||||||
if (Type == SHT_INIT_ARRAY || Type == SHT_FINI_ARRAY ||
|
if (Type == SHT_INIT_ARRAY || Type == SHT_FINI_ARRAY ||
|
||||||
Type == SHT_PREINIT_ARRAY)
|
Type == SHT_PREINIT_ARRAY)
|
||||||
return true;
|
return true;
|
||||||
|
|
@ -422,14 +422,10 @@ static bool compareSectionsNonScript(const OutputSectionBase<ELFT> *A,
|
||||||
if (AIsInterp != BIsInterp)
|
if (AIsInterp != BIsInterp)
|
||||||
return AIsInterp;
|
return AIsInterp;
|
||||||
|
|
||||||
typedef typename ELFT::uint uintX_t;
|
|
||||||
uintX_t AFlags = A->getFlags();
|
|
||||||
uintX_t BFlags = B->getFlags();
|
|
||||||
|
|
||||||
// Allocatable sections go first to reduce the total PT_LOAD size and
|
// Allocatable sections go first to reduce the total PT_LOAD size and
|
||||||
// so debug info doesn't change addresses in actual code.
|
// so debug info doesn't change addresses in actual code.
|
||||||
bool AIsAlloc = AFlags & SHF_ALLOC;
|
bool AIsAlloc = A->Flags & SHF_ALLOC;
|
||||||
bool BIsAlloc = BFlags & SHF_ALLOC;
|
bool BIsAlloc = B->Flags & SHF_ALLOC;
|
||||||
if (AIsAlloc != BIsAlloc)
|
if (AIsAlloc != BIsAlloc)
|
||||||
return AIsAlloc;
|
return AIsAlloc;
|
||||||
|
|
||||||
|
|
@ -440,8 +436,8 @@ static bool compareSectionsNonScript(const OutputSectionBase<ELFT> *A,
|
||||||
|
|
||||||
// We want the read only sections first so that they go in the PT_LOAD
|
// We want the read only sections first so that they go in the PT_LOAD
|
||||||
// covering the program headers at the start of the file.
|
// covering the program headers at the start of the file.
|
||||||
bool AIsWritable = AFlags & SHF_WRITE;
|
bool AIsWritable = A->Flags & SHF_WRITE;
|
||||||
bool BIsWritable = BFlags & SHF_WRITE;
|
bool BIsWritable = B->Flags & SHF_WRITE;
|
||||||
if (AIsWritable != BIsWritable)
|
if (AIsWritable != BIsWritable)
|
||||||
return BIsWritable;
|
return BIsWritable;
|
||||||
|
|
||||||
|
|
@ -451,8 +447,8 @@ static bool compareSectionsNonScript(const OutputSectionBase<ELFT> *A,
|
||||||
// We only do that if we are not using linker scripts, since with linker
|
// We only do that if we are not using linker scripts, since with linker
|
||||||
// scripts ro and rx sections are in the same PT_LOAD, so their relative
|
// scripts ro and rx sections are in the same PT_LOAD, so their relative
|
||||||
// order is not important.
|
// order is not important.
|
||||||
bool AIsExec = AFlags & SHF_EXECINSTR;
|
bool AIsExec = A->Flags & SHF_EXECINSTR;
|
||||||
bool BIsExec = BFlags & SHF_EXECINSTR;
|
bool BIsExec = B->Flags & SHF_EXECINSTR;
|
||||||
if (AIsExec != BIsExec)
|
if (AIsExec != BIsExec)
|
||||||
return BIsExec;
|
return BIsExec;
|
||||||
}
|
}
|
||||||
|
|
@ -463,8 +459,8 @@ static bool compareSectionsNonScript(const OutputSectionBase<ELFT> *A,
|
||||||
// PT_LOAD, so stick TLS sections directly before R/W sections. The TLS NOBITS
|
// PT_LOAD, so stick TLS sections directly before R/W sections. The TLS NOBITS
|
||||||
// sections are placed here as they don't take up virtual address space in the
|
// sections are placed here as they don't take up virtual address space in the
|
||||||
// PT_LOAD.
|
// PT_LOAD.
|
||||||
bool AIsTls = AFlags & SHF_TLS;
|
bool AIsTls = A->Flags & SHF_TLS;
|
||||||
bool BIsTls = BFlags & SHF_TLS;
|
bool BIsTls = B->Flags & SHF_TLS;
|
||||||
if (AIsTls != BIsTls)
|
if (AIsTls != BIsTls)
|
||||||
return AIsTls;
|
return AIsTls;
|
||||||
|
|
||||||
|
|
@ -473,8 +469,8 @@ static bool compareSectionsNonScript(const OutputSectionBase<ELFT> *A,
|
||||||
// them is a p_memsz that is larger than p_filesz. Seeing that it
|
// them is a p_memsz that is larger than p_filesz. Seeing that it
|
||||||
// zeros the end of the PT_LOAD, so that has to correspond to the
|
// zeros the end of the PT_LOAD, so that has to correspond to the
|
||||||
// nobits sections.
|
// nobits sections.
|
||||||
bool AIsNoBits = A->getType() == SHT_NOBITS;
|
bool AIsNoBits = A->Type == SHT_NOBITS;
|
||||||
bool BIsNoBits = B->getType() == SHT_NOBITS;
|
bool BIsNoBits = B->Type == SHT_NOBITS;
|
||||||
if (AIsNoBits != BIsNoBits)
|
if (AIsNoBits != BIsNoBits)
|
||||||
return BIsNoBits;
|
return BIsNoBits;
|
||||||
|
|
||||||
|
|
@ -522,7 +518,7 @@ template <class ELFT> void PhdrEntry<ELFT>::add(OutputSectionBase<ELFT> *Sec) {
|
||||||
Last = Sec;
|
Last = Sec;
|
||||||
if (!First)
|
if (!First)
|
||||||
First = Sec;
|
First = Sec;
|
||||||
H.p_align = std::max<typename ELFT::uint>(H.p_align, Sec->getAlignment());
|
H.p_align = std::max<typename ELFT::uint>(H.p_align, Sec->Addralign);
|
||||||
if (H.p_type == PT_LOAD)
|
if (H.p_type == PT_LOAD)
|
||||||
Sec->FirstInPtLoad = First;
|
Sec->FirstInPtLoad = First;
|
||||||
}
|
}
|
||||||
|
|
@ -699,17 +695,17 @@ template <class ELFT> void Writer<ELFT>::createSections() {
|
||||||
template <class ELFT>
|
template <class ELFT>
|
||||||
static bool canSharePtLoad(const OutputSectionBase<ELFT> &S1,
|
static bool canSharePtLoad(const OutputSectionBase<ELFT> &S1,
|
||||||
const OutputSectionBase<ELFT> &S2) {
|
const OutputSectionBase<ELFT> &S2) {
|
||||||
if (!(S1.getFlags() & SHF_ALLOC) || !(S2.getFlags() & SHF_ALLOC))
|
if (!(S1.Flags & SHF_ALLOC) || !(S2.Flags & SHF_ALLOC))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
bool S1IsWrite = S1.getFlags() & SHF_WRITE;
|
bool S1IsWrite = S1.Flags & SHF_WRITE;
|
||||||
bool S2IsWrite = S2.getFlags() & SHF_WRITE;
|
bool S2IsWrite = S2.Flags & SHF_WRITE;
|
||||||
if (S1IsWrite != S2IsWrite)
|
if (S1IsWrite != S2IsWrite)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (!S1IsWrite)
|
if (!S1IsWrite)
|
||||||
return true; // RO and RX share a PT_LOAD with linker scripts.
|
return true; // RO and RX share a PT_LOAD with linker scripts.
|
||||||
return (S1.getFlags() & SHF_EXECINSTR) == (S2.getFlags() & SHF_EXECINSTR);
|
return (S1.Flags & SHF_EXECINSTR) == (S2.Flags & SHF_EXECINSTR);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class ELFT> void Writer<ELFT>::sortSections() {
|
template <class ELFT> void Writer<ELFT>::sortSections() {
|
||||||
|
|
@ -850,7 +846,7 @@ template <class ELFT> void Writer<ELFT>::finalizeSections() {
|
||||||
unsigned I = 1;
|
unsigned I = 1;
|
||||||
for (OutputSectionBase<ELFT> *Sec : OutputSections) {
|
for (OutputSectionBase<ELFT> *Sec : OutputSections) {
|
||||||
Sec->SectionIndex = I++;
|
Sec->SectionIndex = I++;
|
||||||
Sec->setSHName(Out<ELFT>::ShStrTab->addString(Sec->getName()));
|
Sec->ShName = Out<ELFT>::ShStrTab->addString(Sec->getName());
|
||||||
}
|
}
|
||||||
|
|
||||||
// Finalizers fix each section's size.
|
// Finalizers fix each section's size.
|
||||||
|
|
@ -934,7 +930,7 @@ template <class ELFT> void Writer<ELFT>::addPredefinedSections() {
|
||||||
Add(Out<ELFT>::Plt);
|
Add(Out<ELFT>::Plt);
|
||||||
if (!Out<ELFT>::EhFrame->empty())
|
if (!Out<ELFT>::EhFrame->empty())
|
||||||
Add(Out<ELFT>::EhFrameHdr);
|
Add(Out<ELFT>::EhFrameHdr);
|
||||||
if (Out<ELFT>::Bss->getSize() > 0)
|
if (Out<ELFT>::Bss->Size > 0)
|
||||||
Add(Out<ELFT>::Bss);
|
Add(Out<ELFT>::Bss);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -981,13 +977,13 @@ OutputSectionBase<ELFT> *Writer<ELFT>::findSection(StringRef Name) {
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class ELFT> static bool needsPtLoad(OutputSectionBase<ELFT> *Sec) {
|
template <class ELFT> static bool needsPtLoad(OutputSectionBase<ELFT> *Sec) {
|
||||||
if (!(Sec->getFlags() & SHF_ALLOC))
|
if (!(Sec->Flags & SHF_ALLOC))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// Don't allocate VA space for TLS NOBITS sections. The PT_TLS PHDR is
|
// Don't allocate VA space for TLS NOBITS sections. The PT_TLS PHDR is
|
||||||
// responsible for allocating space for them, not the PT_LOAD that
|
// responsible for allocating space for them, not the PT_LOAD that
|
||||||
// contains the TLS initialization image.
|
// contains the TLS initialization image.
|
||||||
if (Sec->getFlags() & SHF_TLS && Sec->getType() == SHT_NOBITS)
|
if (Sec->Flags & SHF_TLS && Sec->Type == SHT_NOBITS)
|
||||||
return false;
|
return false;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
@ -1035,13 +1031,13 @@ template <class ELFT> std::vector<PhdrEntry<ELFT>> Writer<ELFT>::createPhdrs() {
|
||||||
Phdr Note(PT_NOTE, PF_R);
|
Phdr Note(PT_NOTE, PF_R);
|
||||||
Phdr ARMExidx(PT_ARM_EXIDX, PF_R);
|
Phdr ARMExidx(PT_ARM_EXIDX, PF_R);
|
||||||
for (OutputSectionBase<ELFT> *Sec : OutputSections) {
|
for (OutputSectionBase<ELFT> *Sec : OutputSections) {
|
||||||
if (!(Sec->getFlags() & SHF_ALLOC))
|
if (!(Sec->Flags & SHF_ALLOC))
|
||||||
break;
|
break;
|
||||||
|
|
||||||
// If we meet TLS section then we create TLS header
|
// If we meet TLS section then we create TLS header
|
||||||
// and put all TLS sections inside for further use when
|
// and put all TLS sections inside for further use when
|
||||||
// assign addresses.
|
// assign addresses.
|
||||||
if (Sec->getFlags() & SHF_TLS)
|
if (Sec->Flags & SHF_TLS)
|
||||||
TlsHdr.add(Sec);
|
TlsHdr.add(Sec);
|
||||||
|
|
||||||
if (!needsPtLoad(Sec))
|
if (!needsPtLoad(Sec))
|
||||||
|
|
@ -1062,9 +1058,9 @@ template <class ELFT> std::vector<PhdrEntry<ELFT>> Writer<ELFT>::createPhdrs() {
|
||||||
|
|
||||||
if (isRelroSection(Sec))
|
if (isRelroSection(Sec))
|
||||||
RelRo.add(Sec);
|
RelRo.add(Sec);
|
||||||
if (Sec->getType() == SHT_NOTE)
|
if (Sec->Type == SHT_NOTE)
|
||||||
Note.add(Sec);
|
Note.add(Sec);
|
||||||
if (Config->EMachine == EM_ARM && Sec->getType() == SHT_ARM_EXIDX)
|
if (Config->EMachine == EM_ARM && Sec->Type == SHT_ARM_EXIDX)
|
||||||
ARMExidx.add(Sec);
|
ARMExidx.add(Sec);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1148,10 +1144,10 @@ template <class ELFT> void Writer<ELFT>::fixSectionAlignments() {
|
||||||
// list, but have them to simplify the code.
|
// list, but have them to simplify the code.
|
||||||
template <class ELFT> void Writer<ELFT>::fixHeaders() {
|
template <class ELFT> void Writer<ELFT>::fixHeaders() {
|
||||||
uintX_t BaseVA = ScriptConfig->HasSections ? 0 : Config->ImageBase;
|
uintX_t BaseVA = ScriptConfig->HasSections ? 0 : Config->ImageBase;
|
||||||
Out<ELFT>::ElfHeader->setVA(BaseVA);
|
Out<ELFT>::ElfHeader->Addr = BaseVA;
|
||||||
uintX_t Off = Out<ELFT>::ElfHeader->getSize();
|
uintX_t Off = Out<ELFT>::ElfHeader->Size;
|
||||||
Out<ELFT>::ProgramHeaders->setVA(Off + BaseVA);
|
Out<ELFT>::ProgramHeaders->Addr = Off + BaseVA;
|
||||||
Out<ELFT>::ProgramHeaders->setSize(sizeof(Elf_Phdr) * Phdrs.size());
|
Out<ELFT>::ProgramHeaders->Size = sizeof(Elf_Phdr) * Phdrs.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Assign VAs (addresses at run-time) to output sections.
|
// Assign VAs (addresses at run-time) to output sections.
|
||||||
|
|
@ -1159,7 +1155,7 @@ template <class ELFT> void Writer<ELFT>::assignAddresses() {
|
||||||
uintX_t VA = Config->ImageBase + getHeaderSize<ELFT>();
|
uintX_t VA = Config->ImageBase + getHeaderSize<ELFT>();
|
||||||
uintX_t ThreadBssOffset = 0;
|
uintX_t ThreadBssOffset = 0;
|
||||||
for (OutputSectionBase<ELFT> *Sec : OutputSections) {
|
for (OutputSectionBase<ELFT> *Sec : OutputSections) {
|
||||||
uintX_t Alignment = Sec->getAlignment();
|
uintX_t Alignment = Sec->Addralign;
|
||||||
if (Sec->PageAlign)
|
if (Sec->PageAlign)
|
||||||
Alignment = std::max<uintX_t>(Alignment, Config->MaxPageSize);
|
Alignment = std::max<uintX_t>(Alignment, Config->MaxPageSize);
|
||||||
|
|
||||||
|
|
@ -1170,13 +1166,13 @@ template <class ELFT> void Writer<ELFT>::assignAddresses() {
|
||||||
// We only assign VAs to allocated sections.
|
// We only assign VAs to allocated sections.
|
||||||
if (needsPtLoad(Sec)) {
|
if (needsPtLoad(Sec)) {
|
||||||
VA = alignTo(VA, Alignment);
|
VA = alignTo(VA, Alignment);
|
||||||
Sec->setVA(VA);
|
Sec->Addr = VA;
|
||||||
VA += Sec->getSize();
|
VA += Sec->Size;
|
||||||
} else if (Sec->getFlags() & SHF_TLS && Sec->getType() == SHT_NOBITS) {
|
} else if (Sec->Flags & SHF_TLS && Sec->Type == SHT_NOBITS) {
|
||||||
uintX_t TVA = VA + ThreadBssOffset;
|
uintX_t TVA = VA + ThreadBssOffset;
|
||||||
TVA = alignTo(TVA, Alignment);
|
TVA = alignTo(TVA, Alignment);
|
||||||
Sec->setVA(TVA);
|
Sec->Addr = TVA;
|
||||||
ThreadBssOffset = TVA - VA + Sec->getSize();
|
ThreadBssOffset = TVA - VA + Sec->Size;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1187,7 +1183,7 @@ template <class ELFT> void Writer<ELFT>::assignAddresses() {
|
||||||
// executables without any address adjustment.
|
// executables without any address adjustment.
|
||||||
template <class ELFT, class uintX_t>
|
template <class ELFT, class uintX_t>
|
||||||
static uintX_t getFileAlignment(uintX_t Off, OutputSectionBase<ELFT> *Sec) {
|
static uintX_t getFileAlignment(uintX_t Off, OutputSectionBase<ELFT> *Sec) {
|
||||||
uintX_t Alignment = Sec->getAlignment();
|
uintX_t Alignment = Sec->Addralign;
|
||||||
if (Sec->PageAlign)
|
if (Sec->PageAlign)
|
||||||
Alignment = std::max<uintX_t>(Alignment, Config->MaxPageSize);
|
Alignment = std::max<uintX_t>(Alignment, Config->MaxPageSize);
|
||||||
Off = alignTo(Off, Alignment);
|
Off = alignTo(Off, Alignment);
|
||||||
|
|
@ -1200,26 +1196,26 @@ static uintX_t getFileAlignment(uintX_t Off, OutputSectionBase<ELFT> *Sec) {
|
||||||
// If two sections share the same PT_LOAD the file offset is calculated using
|
// If two sections share the same PT_LOAD the file offset is calculated using
|
||||||
// this formula: Off2 = Off1 + (VA2 - VA1).
|
// this formula: Off2 = Off1 + (VA2 - VA1).
|
||||||
if (Sec == First)
|
if (Sec == First)
|
||||||
return alignTo(Off, Target->MaxPageSize, Sec->getVA());
|
return alignTo(Off, Target->MaxPageSize, Sec->Addr);
|
||||||
return First->getFileOffset() + Sec->getVA() - First->getVA();
|
return First->Offset + Sec->Addr - First->Addr;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class ELFT, class uintX_t>
|
template <class ELFT, class uintX_t>
|
||||||
void setOffset(OutputSectionBase<ELFT> *Sec, uintX_t &Off) {
|
void setOffset(OutputSectionBase<ELFT> *Sec, uintX_t &Off) {
|
||||||
if (Sec->getType() == SHT_NOBITS) {
|
if (Sec->Type == SHT_NOBITS) {
|
||||||
Sec->setFileOffset(Off);
|
Sec->Offset = Off;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Off = getFileAlignment<ELFT>(Off, Sec);
|
Off = getFileAlignment<ELFT>(Off, Sec);
|
||||||
Sec->setFileOffset(Off);
|
Sec->Offset = Off;
|
||||||
Off += Sec->getSize();
|
Off += Sec->Size;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class ELFT> void Writer<ELFT>::assignFileOffsetsBinary() {
|
template <class ELFT> void Writer<ELFT>::assignFileOffsetsBinary() {
|
||||||
uintX_t Off = 0;
|
uintX_t Off = 0;
|
||||||
for (OutputSectionBase<ELFT> *Sec : OutputSections)
|
for (OutputSectionBase<ELFT> *Sec : OutputSections)
|
||||||
if (Sec->getFlags() & SHF_ALLOC)
|
if (Sec->Flags & SHF_ALLOC)
|
||||||
setOffset(Sec, Off);
|
setOffset(Sec, Off);
|
||||||
FileSize = alignTo(Off, sizeof(uintX_t));
|
FileSize = alignTo(Off, sizeof(uintX_t));
|
||||||
}
|
}
|
||||||
|
|
@ -1245,12 +1241,12 @@ template <class ELFT> void Writer<ELFT>::setPhdrs() {
|
||||||
OutputSectionBase<ELFT> *First = P.First;
|
OutputSectionBase<ELFT> *First = P.First;
|
||||||
OutputSectionBase<ELFT> *Last = P.Last;
|
OutputSectionBase<ELFT> *Last = P.Last;
|
||||||
if (First) {
|
if (First) {
|
||||||
H.p_filesz = Last->getFileOff() - First->getFileOff();
|
H.p_filesz = Last->Offset - First->Offset;
|
||||||
if (Last->getType() != SHT_NOBITS)
|
if (Last->Type != SHT_NOBITS)
|
||||||
H.p_filesz += Last->getSize();
|
H.p_filesz += Last->Size;
|
||||||
H.p_memsz = Last->getVA() + Last->getSize() - First->getVA();
|
H.p_memsz = Last->Addr + Last->Size - First->Addr;
|
||||||
H.p_offset = First->getFileOff();
|
H.p_offset = First->Offset;
|
||||||
H.p_vaddr = First->getVA();
|
H.p_vaddr = First->Addr;
|
||||||
if (!P.HasLMA)
|
if (!P.HasLMA)
|
||||||
H.p_paddr = First->getLMA();
|
H.p_paddr = First->getLMA();
|
||||||
}
|
}
|
||||||
|
|
@ -1298,7 +1294,7 @@ static uint16_t getELFType() {
|
||||||
template <class ELFT> void Writer<ELFT>::fixAbsoluteSymbols() {
|
template <class ELFT> void Writer<ELFT>::fixAbsoluteSymbols() {
|
||||||
// __ehdr_start is the location of program headers.
|
// __ehdr_start is the location of program headers.
|
||||||
if (ElfSym<ELFT>::EhdrStart)
|
if (ElfSym<ELFT>::EhdrStart)
|
||||||
ElfSym<ELFT>::EhdrStart->Value = Out<ELFT>::ProgramHeaders->getVA();
|
ElfSym<ELFT>::EhdrStart->Value = Out<ELFT>::ProgramHeaders->Addr;
|
||||||
|
|
||||||
auto Set = [](DefinedRegular<ELFT> *S1, DefinedRegular<ELFT> *S2, uintX_t V) {
|
auto Set = [](DefinedRegular<ELFT> *S1, DefinedRegular<ELFT> *S2, uintX_t V) {
|
||||||
if (S1)
|
if (S1)
|
||||||
|
|
@ -1382,8 +1378,8 @@ template <class ELFT> void Writer<ELFT>::openFile() {
|
||||||
template <class ELFT> void Writer<ELFT>::writeSectionsBinary() {
|
template <class ELFT> void Writer<ELFT>::writeSectionsBinary() {
|
||||||
uint8_t *Buf = Buffer->getBufferStart();
|
uint8_t *Buf = Buffer->getBufferStart();
|
||||||
for (OutputSectionBase<ELFT> *Sec : OutputSections)
|
for (OutputSectionBase<ELFT> *Sec : OutputSections)
|
||||||
if (Sec->getFlags() & SHF_ALLOC)
|
if (Sec->Flags & SHF_ALLOC)
|
||||||
Sec->writeTo(Buf + Sec->getFileOff());
|
Sec->writeTo(Buf + Sec->Offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Convert the .ARM.exidx table entries that use relative PREL31 offsets to
|
// Convert the .ARM.exidx table entries that use relative PREL31 offsets to
|
||||||
|
|
@ -1449,23 +1445,23 @@ template <class ELFT> void Writer<ELFT>::writeSections() {
|
||||||
// before processing relocations in code-containing sections.
|
// before processing relocations in code-containing sections.
|
||||||
Out<ELFT>::Opd = findSection(".opd");
|
Out<ELFT>::Opd = findSection(".opd");
|
||||||
if (Out<ELFT>::Opd) {
|
if (Out<ELFT>::Opd) {
|
||||||
Out<ELFT>::OpdBuf = Buf + Out<ELFT>::Opd->getFileOff();
|
Out<ELFT>::OpdBuf = Buf + Out<ELFT>::Opd->Offset;
|
||||||
Out<ELFT>::Opd->writeTo(Buf + Out<ELFT>::Opd->getFileOff());
|
Out<ELFT>::Opd->writeTo(Buf + Out<ELFT>::Opd->Offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (OutputSectionBase<ELFT> *Sec : OutputSections)
|
for (OutputSectionBase<ELFT> *Sec : OutputSections)
|
||||||
if (Sec != Out<ELFT>::Opd && Sec != Out<ELFT>::EhFrameHdr)
|
if (Sec != Out<ELFT>::Opd && Sec != Out<ELFT>::EhFrameHdr)
|
||||||
Sec->writeTo(Buf + Sec->getFileOff());
|
Sec->writeTo(Buf + Sec->Offset);
|
||||||
|
|
||||||
OutputSectionBase<ELFT> *ARMExidx = findSection(".ARM.exidx");
|
OutputSectionBase<ELFT> *ARMExidx = findSection(".ARM.exidx");
|
||||||
if (!Config->Relocatable)
|
if (!Config->Relocatable)
|
||||||
if (auto *OS = dyn_cast_or_null<OutputSection<ELFT>>(ARMExidx))
|
if (auto *OS = dyn_cast_or_null<OutputSection<ELFT>>(ARMExidx))
|
||||||
sortARMExidx(Buf + OS->getFileOff(), OS->getVA(), OS->getSize());
|
sortARMExidx(Buf + OS->Offset, OS->Addr, OS->Size);
|
||||||
|
|
||||||
// The .eh_frame_hdr depends on .eh_frame section contents, therefore
|
// The .eh_frame_hdr depends on .eh_frame section contents, therefore
|
||||||
// it should be written after .eh_frame is written.
|
// it should be written after .eh_frame is written.
|
||||||
if (!Out<ELFT>::EhFrame->empty() && Out<ELFT>::EhFrameHdr)
|
if (!Out<ELFT>::EhFrame->empty() && Out<ELFT>::EhFrameHdr)
|
||||||
Out<ELFT>::EhFrameHdr->writeTo(Buf + Out<ELFT>::EhFrameHdr->getFileOff());
|
Out<ELFT>::EhFrameHdr->writeTo(Buf + Out<ELFT>::EhFrameHdr->Offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class ELFT> void Writer<ELFT>::writeBuildId() {
|
template <class ELFT> void Writer<ELFT>::writeBuildId() {
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue