Index: ELF/Target.h =================================================================== --- ELF/Target.h +++ ELF/Target.h @@ -55,7 +55,9 @@ virtual bool isSizeRel(uint32_t Type) const; virtual bool needsDynRelative(unsigned Type) const { return false; } virtual bool needsGot(uint32_t Type, SymbolBody &S) const; - virtual bool needsPlt(uint32_t Type, SymbolBody &S) const; + + enum PltNeed { Plt_No, Plt_Explicit, Plt_Implicit }; + virtual PltNeed needsPlt(uint32_t Type, const SymbolBody &S) const; virtual void relocateOne(uint8_t *Loc, uint8_t *BufEnd, uint32_t Type, uint64_t P, uint64_t SA, uint64_t ZA = 0, uint8_t *PairedLoc = nullptr) const = 0; Index: ELF/Target.cpp =================================================================== --- ELF/Target.cpp +++ ELF/Target.cpp @@ -91,7 +91,7 @@ bool needsCopyRel(uint32_t Type, const SymbolBody &S) const override; bool needsDynRelative(unsigned Type) const override; bool needsGot(uint32_t Type, SymbolBody &S) const override; - bool needsPlt(uint32_t Type, SymbolBody &S) const override; + PltNeed needsPlt(uint32_t Type, const SymbolBody &S) const override; void relocateOne(uint8_t *Loc, uint8_t *BufEnd, uint32_t Type, uint64_t P, uint64_t SA, uint64_t ZA = 0, uint8_t *PairedLoc = nullptr) const override; @@ -122,7 +122,7 @@ int32_t Index, unsigned RelOff) const override; bool needsCopyRel(uint32_t Type, const SymbolBody &S) const override; bool needsGot(uint32_t Type, SymbolBody &S) const override; - bool needsPlt(uint32_t Type, SymbolBody &S) const override; + PltNeed needsPlt(uint32_t Type, const SymbolBody &S) const override; void relocateOne(uint8_t *Loc, uint8_t *BufEnd, uint32_t Type, uint64_t P, uint64_t SA, uint64_t ZA = 0, uint8_t *PairedLoc = nullptr) const override; @@ -158,7 +158,7 @@ void writePlt(uint8_t *Buf, uint64_t GotEntryAddr, uint64_t PltEntryAddr, int32_t Index, unsigned RelOff) const override; bool needsGot(uint32_t Type, SymbolBody &S) const override; - bool needsPlt(uint32_t Type, SymbolBody &S) const override; + PltNeed needsPlt(uint32_t Type, const SymbolBody &S) const override; void relocateOne(uint8_t *Loc, uint8_t *BufEnd, uint32_t Type, uint64_t P, uint64_t SA, uint64_t ZA = 0, uint8_t *PairedLoc = nullptr) const override; @@ -177,7 +177,7 @@ bool isTlsDynRel(unsigned Type, const SymbolBody &S) const override; bool needsCopyRel(uint32_t Type, const SymbolBody &S) const override; bool needsGot(uint32_t Type, SymbolBody &S) const override; - bool needsPlt(uint32_t Type, SymbolBody &S) const override; + PltNeed needsPlt(uint32_t Type, const SymbolBody &S) const override; void relocateOne(uint8_t *Loc, uint8_t *BufEnd, uint32_t Type, uint64_t P, uint64_t SA, uint64_t ZA = 0, uint8_t *PairedLoc = nullptr) const override; @@ -198,7 +198,7 @@ void writeGotHeader(uint8_t *Buf) const override; bool needsCopyRel(uint32_t Type, const SymbolBody &S) const override; bool needsGot(uint32_t Type, SymbolBody &S) const override; - bool needsPlt(uint32_t Type, SymbolBody &S) const override; + PltNeed needsPlt(uint32_t Type, const SymbolBody &S) const override; void relocateOne(uint8_t *Loc, uint8_t *BufEnd, uint32_t Type, uint64_t P, uint64_t S, uint64_t ZA = 0, uint8_t *PairedLoc = nullptr) const override; @@ -265,7 +265,10 @@ bool TargetInfo::needsGot(uint32_t Type, SymbolBody &S) const { return false; } -bool TargetInfo::needsPlt(uint32_t Type, SymbolBody &S) const { return false; } +TargetInfo::PltNeed TargetInfo::needsPlt(uint32_t Type, + const SymbolBody &S) const { + return Plt_No; +} unsigned TargetInfo::relaxTls(uint8_t *Loc, uint8_t *BufEnd, uint32_t Type, uint64_t P, uint64_t SA, @@ -380,10 +383,13 @@ return Type == R_386_GOT32 || needsPlt(Type, S); } -bool X86TargetInfo::needsPlt(uint32_t Type, SymbolBody &S) const { - return isGnuIFunc(S) || - (Type == R_386_PLT32 && canBePreempted(&S, true)) || - (Type == R_386_PC32 && S.isShared()); +TargetInfo::PltNeed X86TargetInfo::needsPlt(uint32_t Type, + const SymbolBody &S) const { + if (isGnuIFunc(S) || + (Type == R_386_PLT32 && canBePreempted(&S, true)) || + (Type == R_386_PC32 && S.isShared())) + return Plt_Explicit; + return Plt_No; } bool X86TargetInfo::isGotRelative(uint32_t Type) const { @@ -654,15 +660,16 @@ return Type == R_X86_64_GOTTPOFF || Type == R_X86_64_TLSGD; } -bool X86_64TargetInfo::needsPlt(uint32_t Type, SymbolBody &S) const { +TargetInfo::PltNeed X86_64TargetInfo::needsPlt(uint32_t Type, + const SymbolBody &S) const { if (needsCopyRel(Type, S)) - return false; + return Plt_No; if (isGnuIFunc(S)) - return true; + return Plt_Explicit; switch (Type) { default: - return false; + return Plt_No; case R_X86_64_32: case R_X86_64_64: case R_X86_64_PC32: @@ -690,11 +697,12 @@ // plt. That is identified by special relocation types (R_X86_64_JUMP_SLOT, // R_386_JMP_SLOT, etc). if (!S.isShared()) - return false; - S.NeedsCopyOrPltAddr = true; - return true; + return Plt_No; + return Plt_Implicit; case R_X86_64_PLT32: - return canBePreempted(&S, true); + if (canBePreempted(&S, true)) + return Plt_Explicit; + return Plt_No; } } @@ -1003,9 +1011,12 @@ } } -bool PPC64TargetInfo::needsPlt(uint32_t Type, SymbolBody &S) const { +TargetInfo::PltNeed PPC64TargetInfo::needsPlt(uint32_t Type, + const SymbolBody &S) const { // These are function calls that need to be redirected through a PLT stub. - return Type == R_PPC64_REL24 && canBePreempted(&S, false); + if (Type == R_PPC64_REL24 && canBePreempted(&S, false)) + return Plt_Explicit; + return Plt_No; } bool PPC64TargetInfo::isRelRelative(uint32_t Type) const { @@ -1250,17 +1261,20 @@ } } -bool AArch64TargetInfo::needsPlt(uint32_t Type, SymbolBody &S) const { +TargetInfo::PltNeed AArch64TargetInfo::needsPlt(uint32_t Type, + const SymbolBody &S) const { if (isGnuIFunc(S)) - return true; + return Plt_Explicit; switch (Type) { default: - return false; + return Plt_No; case R_AARCH64_CALL26: case R_AARCH64_CONDBR19: case R_AARCH64_JUMP26: case R_AARCH64_TSTBR14: - return canBePreempted(&S, true); + if (canBePreempted(&S, true)) + return Plt_Explicit; + return Plt_No; } } @@ -1442,8 +1456,9 @@ } template -bool MipsTargetInfo::needsPlt(uint32_t Type, SymbolBody &S) const { - return false; +TargetInfo::PltNeed MipsTargetInfo::needsPlt(uint32_t Type, + const SymbolBody &S) const { + return Plt_No; } static uint16_t mipsHigh(uint64_t V) { return (V + 0x8000) >> 16; } Index: ELF/Writer.cpp =================================================================== --- ELF/Writer.cpp +++ ELF/Writer.cpp @@ -336,7 +336,12 @@ // If a relocation needs PLT, we create a PLT and a GOT slot // for the symbol. - if (Body && Target->needsPlt(Type, *Body)) { + TargetInfo::PltNeed NeedPlt = TargetInfo::Plt_No; + if (Body) + NeedPlt = Target->needsPlt(Type, *Body); + if (NeedPlt) { + if (NeedPlt == TargetInfo::Plt_Implicit) + Body->NeedsCopyOrPltAddr = true; if (Body->isInPlt()) continue; Out::Plt->addEntry(Body);