ELF: Move code for GNU_IFUNC to one place. NFC.

This does not solve the problem that we call isGnuIFunc function
both from RelocationSection and from the Writer::scanRelocs, but
this at least should improve readability. I'm taking an incremental
approach to reduce complexity.

llvm-svn: 258753
This commit is contained in:
Rui Ueyama 2016-01-26 00:24:57 +00:00
parent 968b090552
commit b0210e83b3
1 changed files with 15 additions and 3 deletions

View File

@ -300,15 +300,27 @@ template <class ELFT> void RelocationSection<ELFT>::writeTo(uint8_t *Buf) {
bool NeedsGot = Body && Target->relocNeedsGot(Type, *Body);
bool CBP = canBePreempted(Body, NeedsGot);
// For a symbol with STT_GNU_IFUNC type, we always create a PLT and
// a GOT entry for the symbol, and emit an IRELATIVE reloc rather than
// the usual JUMP_SLOT reloc for the GOT entry. For the details, you
// want to read http://www.airs.com/blog/archives/403
if (!CBP && Body && isGnuIFunc<ELFT>(*Body)) {
P->setSymbolAndType(0, Target->getIRelativeReloc(), Config->Mips64EL);
if (Out<ELFT>::GotPlt)
P->r_offset = Out<ELFT>::GotPlt->getEntryAddr(*Body);
else
P->r_offset = Out<ELFT>::Got->getEntryAddr(*Body);
continue;
}
bool LazyReloc = Body && Target->supportsLazyRelocations() &&
Target->relocNeedsPlt(Type, *Body);
bool IsDynRelative = Type == Target->getRelativeReloc();
unsigned Sym = CBP ? Body->DynamicSymbolTableIndex : 0;
unsigned Reloc;
if (!CBP && Body && isGnuIFunc<ELFT>(*Body))
Reloc = Target->getIRelativeReloc();
else if (!CBP || IsDynRelative)
if (!CBP || IsDynRelative)
Reloc = Target->getRelativeReloc();
else if (LazyReloc)
Reloc = Target->getPltReloc();