forked from OSchip/llvm-project
parent
5b5061f0ca
commit
c2cfd9fa34
|
@ -215,89 +215,10 @@ static uintX_t getMipsGotVA(const SymbolBody &Body, uintX_t SymVA,
|
||||||
return Body.getGotVA<ELFT>();
|
return Body.getGotVA<ELFT>();
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class ELFT>
|
template <class ELFT> void InputSectionBase<ELFT>::relocate(uint8_t *Buf) {
|
||||||
template <class RelTy>
|
for (const Relocation &Rel : Relocations) {
|
||||||
void InputSectionBase<ELFT>::relocate(uint8_t *Buf, uint8_t *BufEnd,
|
uint8_t *Pos = Buf + Rel.Offset;
|
||||||
iterator_range<const RelTy *> Rels) {
|
*(uint64_t *)Pos = Rel.Sym->getVA<ELFT>(0);
|
||||||
size_t Num = Rels.end() - Rels.begin();
|
|
||||||
for (size_t I = 0; I < Num; ++I) {
|
|
||||||
const RelTy &RI = *(Rels.begin() + I);
|
|
||||||
uintX_t Offset = getOffset(RI.r_offset);
|
|
||||||
if (Offset == (uintX_t)-1)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
uintX_t A = getAddend<ELFT>(RI);
|
|
||||||
uint32_t SymIndex = RI.getSymbol(Config->Mips64EL);
|
|
||||||
uint32_t Type = RI.getType(Config->Mips64EL);
|
|
||||||
uint8_t *BufLoc = Buf + Offset;
|
|
||||||
uintX_t AddrLoc = OutSec->getVA() + Offset;
|
|
||||||
|
|
||||||
if (Target->pointsToLocalDynamicGotEntry(Type) &&
|
|
||||||
!Target->canRelaxTls(Type, nullptr)) {
|
|
||||||
Target->relocateOne(BufLoc, BufEnd, Type, AddrLoc,
|
|
||||||
Out<ELFT>::Got->getTlsIndexVA() + A);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
SymbolBody &Body = File->getSymbolBody(SymIndex).repl();
|
|
||||||
|
|
||||||
if (Target->canRelaxTls(Type, &Body)) {
|
|
||||||
uintX_t SymVA;
|
|
||||||
if (Target->needsGot(Type, Body))
|
|
||||||
SymVA = Body.getGotVA<ELFT>();
|
|
||||||
else
|
|
||||||
SymVA = Body.getVA<ELFT>();
|
|
||||||
// By optimizing TLS relocations, it is sometimes needed to skip
|
|
||||||
// relocations that immediately follow TLS relocations. This function
|
|
||||||
// knows how many slots we need to skip.
|
|
||||||
I += Target->relaxTls(BufLoc, BufEnd, Type, AddrLoc, SymVA, Body);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
// PPC64 has a special relocation representing the TOC base pointer
|
|
||||||
// that does not have a corresponding symbol.
|
|
||||||
if (Config->EMachine == EM_PPC64 && RI.getType(false) == R_PPC64_TOC) {
|
|
||||||
uintX_t SymVA = getPPC64TocBase() + A;
|
|
||||||
Target->relocateOne(BufLoc, BufEnd, Type, AddrLoc, SymVA, 0);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Target->isTlsGlobalDynamicRel(Type) &&
|
|
||||||
!Target->canRelaxTls(Type, &Body)) {
|
|
||||||
Target->relocateOne(BufLoc, BufEnd, Type, AddrLoc,
|
|
||||||
Out<ELFT>::Got->getGlobalDynAddr(Body) + A);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
uintX_t SymVA = Body.getVA<ELFT>(A);
|
|
||||||
uint8_t *PairedLoc = nullptr;
|
|
||||||
if (Config->EMachine == EM_MIPS)
|
|
||||||
PairedLoc = findMipsPairedReloc(Buf, &RI, Rels.end());
|
|
||||||
|
|
||||||
if (Target->needsPlt<ELFT>(Type, Body)) {
|
|
||||||
SymVA = Body.getPltVA<ELFT>() + A;
|
|
||||||
} else if (Target->needsGot(Type, Body)) {
|
|
||||||
if (Config->EMachine == EM_MIPS)
|
|
||||||
SymVA = getMipsGotVA<ELFT>(Body, SymVA, BufLoc, PairedLoc) + A;
|
|
||||||
else
|
|
||||||
SymVA = Body.getGotVA<ELFT>() + A;
|
|
||||||
if (Body.IsTls)
|
|
||||||
Type = Target->getTlsGotRel(Type);
|
|
||||||
} else if (Target->isSizeRel(Type) && Body.isPreemptible()) {
|
|
||||||
// A SIZE relocation is supposed to set a symbol size, but if a symbol
|
|
||||||
// can be preempted, the size at runtime may be different than link time.
|
|
||||||
// If that's the case, we leave the field alone rather than filling it
|
|
||||||
// with a possibly incorrect value.
|
|
||||||
continue;
|
|
||||||
} else if (Config->EMachine == EM_MIPS) {
|
|
||||||
SymVA = adjustMipsSymVA<ELFT>(Type, *File, Body, AddrLoc, SymVA) + A;
|
|
||||||
} else if (!Target->needsCopyRel<ELFT>(Type, Body) &&
|
|
||||||
Body.isPreemptible()) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
uintX_t Size = Body.getSize<ELFT>();
|
|
||||||
Target->relocateOne(BufLoc, BufEnd, Type, AddrLoc, SymVA, Size + A,
|
|
||||||
PairedLoc);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -321,14 +242,7 @@ template <class ELFT> void InputSection<ELFT>::writeTo(uint8_t *Buf) {
|
||||||
|
|
||||||
memcpy(Buf + OutSecOff, Data.data(), Data.size());
|
memcpy(Buf + OutSecOff, Data.data(), Data.size());
|
||||||
|
|
||||||
uint8_t *BufEnd = Buf + OutSecOff + Data.size();
|
this->relocate(Buf);
|
||||||
// Iterate over all relocation sections that apply to this section.
|
|
||||||
for (const Elf_Shdr *RelSec : this->RelocSections) {
|
|
||||||
if (RelSec->sh_type == SHT_RELA)
|
|
||||||
this->relocate(Buf, BufEnd, EObj.relas(RelSec));
|
|
||||||
else
|
|
||||||
this->relocate(Buf, BufEnd, EObj.rels(RelSec));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class ELFT>
|
template <class ELFT>
|
||||||
|
|
|
@ -23,6 +23,12 @@ template <class ELFT> class ObjectFile;
|
||||||
template <class ELFT> class OutputSection;
|
template <class ELFT> class OutputSection;
|
||||||
template <class ELFT> class OutputSectionBase;
|
template <class ELFT> class OutputSectionBase;
|
||||||
|
|
||||||
|
struct Relocation {
|
||||||
|
enum RelType { R_64 } Type;
|
||||||
|
uint64_t Offset;
|
||||||
|
SymbolBody *Sym;
|
||||||
|
};
|
||||||
|
|
||||||
// This corresponds to a section of an input file.
|
// This corresponds to a section of an input file.
|
||||||
template <class ELFT> class InputSectionBase {
|
template <class ELFT> class InputSectionBase {
|
||||||
protected:
|
protected:
|
||||||
|
@ -75,9 +81,8 @@ public:
|
||||||
InputSectionBase<ELFT> *getRelocTarget(const Elf_Rel &Rel) const;
|
InputSectionBase<ELFT> *getRelocTarget(const Elf_Rel &Rel) const;
|
||||||
InputSectionBase<ELFT> *getRelocTarget(const Elf_Rela &Rel) const;
|
InputSectionBase<ELFT> *getRelocTarget(const Elf_Rela &Rel) const;
|
||||||
|
|
||||||
template <class RelTy>
|
void relocate(uint8_t *Buf);
|
||||||
void relocate(uint8_t *Buf, uint8_t *BufEnd,
|
std::vector<Relocation> Relocations;
|
||||||
llvm::iterator_range<const RelTy *> Rels);
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
template <class RelTy>
|
template <class RelTy>
|
||||||
|
|
|
@ -1168,16 +1168,8 @@ template <class ELFT> void EHOutputSection<ELFT>::writeTo(uint8_t *Buf) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (EHInputSection<ELFT> *S : Sections) {
|
for (EHInputSection<ELFT> *S : Sections)
|
||||||
const Elf_Shdr *RelSec = S->RelocSection;
|
S->relocate(Buf);
|
||||||
if (!RelSec)
|
|
||||||
continue;
|
|
||||||
ELFFile<ELFT> &EObj = S->getFile()->getObj();
|
|
||||||
if (RelSec->sh_type == SHT_RELA)
|
|
||||||
S->relocate(Buf, nullptr, EObj.relas(RelSec));
|
|
||||||
else
|
|
||||||
S->relocate(Buf, nullptr, EObj.rels(RelSec));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class ELFT>
|
template <class ELFT>
|
||||||
|
|
|
@ -466,8 +466,11 @@ void Writer<ELFT>::scanRelocs(InputSectionBase<ELFT> &C,
|
||||||
// We can however do better than just copying the incoming relocation. We
|
// We can however do better than just copying the incoming relocation. We
|
||||||
// can process some of it and and just ask the dynamic linker to add the
|
// can process some of it and and just ask the dynamic linker to add the
|
||||||
// load address.
|
// load address.
|
||||||
if (!Config->Pic || Target->isRelRelative(Type) || Target->isSizeRel(Type))
|
if (!Config->Pic || Target->isRelRelative(Type) ||
|
||||||
|
Target->isSizeRel(Type)) {
|
||||||
|
C.Relocations.push_back({Relocation::R_64, RI.r_offset, &Body});
|
||||||
continue;
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
uintX_t Addend = getAddend<ELFT>(RI);
|
uintX_t Addend = getAddend<ELFT>(RI);
|
||||||
if (Config->EMachine == EM_PPC64 && RI.getType(false) == R_PPC64_TOC) {
|
if (Config->EMachine == EM_PPC64 && RI.getType(false) == R_PPC64_TOC) {
|
||||||
|
|
Loading…
Reference in New Issue