forked from OSchip/llvm-project
				
			Use the plt entry as the address of some symbols.
This is the function equivalent of a copy relocation. Since functions are expected to change sizes, we cannot use copy relocations. In situations where one would be needed, what is done instead is: * Create a plt entry * Output an undefined symbol whose addr is the plt entry. The dynamic linker makes sure any shared library uses the plt entry as the function address. llvm-svn: 260224
This commit is contained in:
		
							parent
							
								
									ad3293744a
								
							
						
					
					
						commit
						a0a65f973a
					
				| 
						 | 
					@ -1328,7 +1328,7 @@ void SymbolTableSection<ELFT>::writeGlobalSymbols(uint8_t *Buf) {
 | 
				
			||||||
      OutSec = Out<ELFT>::Bss;
 | 
					      OutSec = Out<ELFT>::Bss;
 | 
				
			||||||
      break;
 | 
					      break;
 | 
				
			||||||
    case SymbolBody::SharedKind: {
 | 
					    case SymbolBody::SharedKind: {
 | 
				
			||||||
      if (cast<SharedSymbol<ELFT>>(Body)->NeedsCopy)
 | 
					      if (cast<SharedSymbol<ELFT>>(Body)->needsCopy())
 | 
				
			||||||
        OutSec = Out<ELFT>::Bss;
 | 
					        OutSec = Out<ELFT>::Bss;
 | 
				
			||||||
      break;
 | 
					      break;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -56,9 +56,12 @@ typename ELFFile<ELFT>::uintX_t SymbolBody::getVA() const {
 | 
				
			||||||
    return Out<ELFT>::Bss->getVA() + cast<DefinedCommon>(this)->OffsetInBss;
 | 
					    return Out<ELFT>::Bss->getVA() + cast<DefinedCommon>(this)->OffsetInBss;
 | 
				
			||||||
  case SharedKind: {
 | 
					  case SharedKind: {
 | 
				
			||||||
    auto *SS = cast<SharedSymbol<ELFT>>(this);
 | 
					    auto *SS = cast<SharedSymbol<ELFT>>(this);
 | 
				
			||||||
    if (SS->NeedsCopy)
 | 
					    if (!SS->NeedsCopyOrPltAddr)
 | 
				
			||||||
 | 
					      return 0;
 | 
				
			||||||
 | 
					    if (SS->IsFunc)
 | 
				
			||||||
 | 
					      return getPltVA<ELFT>();
 | 
				
			||||||
 | 
					    else
 | 
				
			||||||
      return Out<ELFT>::Bss->getVA() + SS->OffsetInBss;
 | 
					      return Out<ELFT>::Bss->getVA() + SS->OffsetInBss;
 | 
				
			||||||
    return 0;
 | 
					 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
  case UndefinedElfKind:
 | 
					  case UndefinedElfKind:
 | 
				
			||||||
  case UndefinedKind:
 | 
					  case UndefinedKind:
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -130,7 +130,8 @@ protected:
 | 
				
			||||||
  SymbolBody(Kind K, StringRef Name, bool IsWeak, uint8_t Visibility,
 | 
					  SymbolBody(Kind K, StringRef Name, bool IsWeak, uint8_t Visibility,
 | 
				
			||||||
             bool IsTls, bool IsFunc)
 | 
					             bool IsTls, bool IsFunc)
 | 
				
			||||||
      : SymbolKind(K), IsWeak(IsWeak), Visibility(Visibility),
 | 
					      : SymbolKind(K), IsWeak(IsWeak), Visibility(Visibility),
 | 
				
			||||||
        MustBeInDynSym(false), IsTls(IsTls), IsFunc(IsFunc), Name(Name) {
 | 
					        MustBeInDynSym(false), NeedsCopyOrPltAddr(false), IsTls(IsTls),
 | 
				
			||||||
 | 
					        IsFunc(IsFunc), Name(Name) {
 | 
				
			||||||
    IsUsedInRegularObj = K != SharedKind && K != LazyKind;
 | 
					    IsUsedInRegularObj = K != SharedKind && K != LazyKind;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -148,9 +149,14 @@ public:
 | 
				
			||||||
  // If true, the symbol is added to .dynsym symbol table.
 | 
					  // If true, the symbol is added to .dynsym symbol table.
 | 
				
			||||||
  unsigned MustBeInDynSym : 1;
 | 
					  unsigned MustBeInDynSym : 1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // True if the linker has to generate a copy relocation for this shared
 | 
				
			||||||
 | 
					  // symbol or if the symbol should point to its plt entry.
 | 
				
			||||||
 | 
					  unsigned NeedsCopyOrPltAddr : 1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
protected:
 | 
					protected:
 | 
				
			||||||
  unsigned IsTls : 1;
 | 
					  unsigned IsTls : 1;
 | 
				
			||||||
  unsigned IsFunc : 1;
 | 
					  unsigned IsFunc : 1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  StringRef Name;
 | 
					  StringRef Name;
 | 
				
			||||||
  Symbol *Backref = nullptr;
 | 
					  Symbol *Backref = nullptr;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
| 
						 | 
					@ -280,10 +286,10 @@ public:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  SharedFile<ELFT> *File;
 | 
					  SharedFile<ELFT> *File;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  // True if the linker has to generate a copy relocation for this shared
 | 
					  // OffsetInBss is significant only when needsCopy() is true.
 | 
				
			||||||
  // symbol. OffsetInBss is significant only when NeedsCopy is true.
 | 
					 | 
				
			||||||
  bool NeedsCopy = false;
 | 
					 | 
				
			||||||
  uintX_t OffsetInBss = 0;
 | 
					  uintX_t OffsetInBss = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  bool needsCopy() const { return this->NeedsCopyOrPltAddr && !this->IsFunc; }
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// This class represents a symbol defined in an archive file. It is
 | 
					// This class represents a symbol defined in an archive file. It is
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -90,8 +90,8 @@ public:
 | 
				
			||||||
                int32_t Index, unsigned RelOff) const override;
 | 
					                int32_t Index, unsigned RelOff) const override;
 | 
				
			||||||
  bool needsCopyRel(uint32_t Type, const SymbolBody &S) const override;
 | 
					  bool needsCopyRel(uint32_t Type, const SymbolBody &S) const override;
 | 
				
			||||||
  bool needsDynRelative(unsigned Type) const override;
 | 
					  bool needsDynRelative(unsigned Type) const override;
 | 
				
			||||||
  bool needsGot(uint32_t Type, const SymbolBody &S) const override;
 | 
					  bool needsGot(uint32_t Type, SymbolBody &S) const override;
 | 
				
			||||||
  bool needsPlt(uint32_t Type, const SymbolBody &S) const override;
 | 
					  bool needsPlt(uint32_t Type, SymbolBody &S) const override;
 | 
				
			||||||
  void relocateOne(uint8_t *Loc, uint8_t *BufEnd, uint32_t Type, uint64_t P,
 | 
					  void relocateOne(uint8_t *Loc, uint8_t *BufEnd, uint32_t Type, uint64_t P,
 | 
				
			||||||
                   uint64_t SA, uint64_t ZA = 0,
 | 
					                   uint64_t SA, uint64_t ZA = 0,
 | 
				
			||||||
                   uint8_t *PairedLoc = nullptr) const override;
 | 
					                   uint8_t *PairedLoc = nullptr) const override;
 | 
				
			||||||
| 
						 | 
					@ -121,8 +121,8 @@ public:
 | 
				
			||||||
  void writePlt(uint8_t *Buf, uint64_t GotEntryAddr, uint64_t PltEntryAddr,
 | 
					  void writePlt(uint8_t *Buf, uint64_t GotEntryAddr, uint64_t PltEntryAddr,
 | 
				
			||||||
                int32_t Index, unsigned RelOff) const override;
 | 
					                int32_t Index, unsigned RelOff) const override;
 | 
				
			||||||
  bool needsCopyRel(uint32_t Type, const SymbolBody &S) const override;
 | 
					  bool needsCopyRel(uint32_t Type, const SymbolBody &S) const override;
 | 
				
			||||||
  bool needsGot(uint32_t Type, const SymbolBody &S) const override;
 | 
					  bool needsGot(uint32_t Type, SymbolBody &S) const override;
 | 
				
			||||||
  bool needsPlt(uint32_t Type, const SymbolBody &S) const override;
 | 
					  bool needsPlt(uint32_t Type, SymbolBody &S) const override;
 | 
				
			||||||
  void relocateOne(uint8_t *Loc, uint8_t *BufEnd, uint32_t Type, uint64_t P,
 | 
					  void relocateOne(uint8_t *Loc, uint8_t *BufEnd, uint32_t Type, uint64_t P,
 | 
				
			||||||
                   uint64_t SA, uint64_t ZA = 0,
 | 
					                   uint64_t SA, uint64_t ZA = 0,
 | 
				
			||||||
                   uint8_t *PairedLoc = nullptr) const override;
 | 
					                   uint8_t *PairedLoc = nullptr) const override;
 | 
				
			||||||
| 
						 | 
					@ -157,8 +157,8 @@ public:
 | 
				
			||||||
  PPC64TargetInfo();
 | 
					  PPC64TargetInfo();
 | 
				
			||||||
  void writePlt(uint8_t *Buf, uint64_t GotEntryAddr, uint64_t PltEntryAddr,
 | 
					  void writePlt(uint8_t *Buf, uint64_t GotEntryAddr, uint64_t PltEntryAddr,
 | 
				
			||||||
                int32_t Index, unsigned RelOff) const override;
 | 
					                int32_t Index, unsigned RelOff) const override;
 | 
				
			||||||
  bool needsGot(uint32_t Type, const SymbolBody &S) const override;
 | 
					  bool needsGot(uint32_t Type, SymbolBody &S) const override;
 | 
				
			||||||
  bool needsPlt(uint32_t Type, const SymbolBody &S) const override;
 | 
					  bool needsPlt(uint32_t Type, SymbolBody &S) const override;
 | 
				
			||||||
  void relocateOne(uint8_t *Loc, uint8_t *BufEnd, uint32_t Type, uint64_t P,
 | 
					  void relocateOne(uint8_t *Loc, uint8_t *BufEnd, uint32_t Type, uint64_t P,
 | 
				
			||||||
                   uint64_t SA, uint64_t ZA = 0,
 | 
					                   uint64_t SA, uint64_t ZA = 0,
 | 
				
			||||||
                   uint8_t *PairedLoc = nullptr) const override;
 | 
					                   uint8_t *PairedLoc = nullptr) const override;
 | 
				
			||||||
| 
						 | 
					@ -176,8 +176,8 @@ public:
 | 
				
			||||||
  unsigned getTlsGotRel(unsigned Type = -1) const override;
 | 
					  unsigned getTlsGotRel(unsigned Type = -1) const override;
 | 
				
			||||||
  bool isTlsDynRel(unsigned Type, const SymbolBody &S) const override;
 | 
					  bool isTlsDynRel(unsigned Type, const SymbolBody &S) const override;
 | 
				
			||||||
  bool needsCopyRel(uint32_t Type, const SymbolBody &S) const override;
 | 
					  bool needsCopyRel(uint32_t Type, const SymbolBody &S) const override;
 | 
				
			||||||
  bool needsGot(uint32_t Type, const SymbolBody &S) const override;
 | 
					  bool needsGot(uint32_t Type, SymbolBody &S) const override;
 | 
				
			||||||
  bool needsPlt(uint32_t Type, const SymbolBody &S) const override;
 | 
					  bool needsPlt(uint32_t Type, SymbolBody &S) const override;
 | 
				
			||||||
  void relocateOne(uint8_t *Loc, uint8_t *BufEnd, uint32_t Type, uint64_t P,
 | 
					  void relocateOne(uint8_t *Loc, uint8_t *BufEnd, uint32_t Type, uint64_t P,
 | 
				
			||||||
                   uint64_t SA, uint64_t ZA = 0,
 | 
					                   uint64_t SA, uint64_t ZA = 0,
 | 
				
			||||||
                   uint8_t *PairedLoc = nullptr) const override;
 | 
					                   uint8_t *PairedLoc = nullptr) const override;
 | 
				
			||||||
| 
						 | 
					@ -197,8 +197,8 @@ public:
 | 
				
			||||||
  unsigned getDynRel(unsigned Type) const override;
 | 
					  unsigned getDynRel(unsigned Type) const override;
 | 
				
			||||||
  void writeGotHeader(uint8_t *Buf) const override;
 | 
					  void writeGotHeader(uint8_t *Buf) const override;
 | 
				
			||||||
  bool needsCopyRel(uint32_t Type, const SymbolBody &S) const override;
 | 
					  bool needsCopyRel(uint32_t Type, const SymbolBody &S) const override;
 | 
				
			||||||
  bool needsGot(uint32_t Type, const SymbolBody &S) const override;
 | 
					  bool needsGot(uint32_t Type, SymbolBody &S) const override;
 | 
				
			||||||
  bool needsPlt(uint32_t Type, const SymbolBody &S) const override;
 | 
					  bool needsPlt(uint32_t Type, SymbolBody &S) const override;
 | 
				
			||||||
  void relocateOne(uint8_t *Loc, uint8_t *BufEnd, uint32_t Type, uint64_t P,
 | 
					  void relocateOne(uint8_t *Loc, uint8_t *BufEnd, uint32_t Type, uint64_t P,
 | 
				
			||||||
                   uint64_t SA, uint64_t ZA = 0,
 | 
					                   uint64_t SA, uint64_t ZA = 0,
 | 
				
			||||||
                   uint8_t *PairedLoc = nullptr) const override;
 | 
					                   uint8_t *PairedLoc = nullptr) const override;
 | 
				
			||||||
| 
						 | 
					@ -263,13 +263,9 @@ bool TargetInfo::isHintRel(uint32_t Type) const { return false; }
 | 
				
			||||||
bool TargetInfo::isRelRelative(uint32_t Type) const { return true; }
 | 
					bool TargetInfo::isRelRelative(uint32_t Type) const { return true; }
 | 
				
			||||||
bool TargetInfo::isSizeRel(uint32_t Type) const { return false; }
 | 
					bool TargetInfo::isSizeRel(uint32_t Type) const { return false; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
bool TargetInfo::needsGot(uint32_t Type, const SymbolBody &S) const {
 | 
					bool TargetInfo::needsGot(uint32_t Type, SymbolBody &S) const { return false; }
 | 
				
			||||||
  return false;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
bool TargetInfo::needsPlt(uint32_t Type, const SymbolBody &S) const {
 | 
					bool TargetInfo::needsPlt(uint32_t Type, SymbolBody &S) const { return false; }
 | 
				
			||||||
  return false;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
unsigned TargetInfo::relaxTls(uint8_t *Loc, uint8_t *BufEnd, uint32_t Type,
 | 
					unsigned TargetInfo::relaxTls(uint8_t *Loc, uint8_t *BufEnd, uint32_t Type,
 | 
				
			||||||
                              uint64_t P, uint64_t SA,
 | 
					                              uint64_t P, uint64_t SA,
 | 
				
			||||||
| 
						 | 
					@ -376,7 +372,7 @@ bool X86TargetInfo::needsCopyRel(uint32_t Type, const SymbolBody &S) const {
 | 
				
			||||||
  return false;
 | 
					  return false;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
bool X86TargetInfo::needsGot(uint32_t Type, const SymbolBody &S) const {
 | 
					bool X86TargetInfo::needsGot(uint32_t Type, SymbolBody &S) const {
 | 
				
			||||||
  if (S.isTls() && Type == R_386_TLS_GD)
 | 
					  if (S.isTls() && Type == R_386_TLS_GD)
 | 
				
			||||||
    return Target->canRelaxTls(Type, &S) && canBePreempted(&S, true);
 | 
					    return Target->canRelaxTls(Type, &S) && canBePreempted(&S, true);
 | 
				
			||||||
  if (Type == R_386_TLS_GOTIE || Type == R_386_TLS_IE)
 | 
					  if (Type == R_386_TLS_GOTIE || Type == R_386_TLS_IE)
 | 
				
			||||||
| 
						 | 
					@ -384,7 +380,7 @@ bool X86TargetInfo::needsGot(uint32_t Type, const SymbolBody &S) const {
 | 
				
			||||||
  return Type == R_386_GOT32 || needsPlt(Type, S);
 | 
					  return Type == R_386_GOT32 || needsPlt(Type, S);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
bool X86TargetInfo::needsPlt(uint32_t Type, const SymbolBody &S) const {
 | 
					bool X86TargetInfo::needsPlt(uint32_t Type, SymbolBody &S) const {
 | 
				
			||||||
  return isGnuIFunc<ELF32LE>(S) ||
 | 
					  return isGnuIFunc<ELF32LE>(S) ||
 | 
				
			||||||
         (Type == R_386_PLT32 && canBePreempted(&S, true)) ||
 | 
					         (Type == R_386_PLT32 && canBePreempted(&S, true)) ||
 | 
				
			||||||
         (Type == R_386_PC32 && S.isShared());
 | 
					         (Type == R_386_PC32 && S.isShared());
 | 
				
			||||||
| 
						 | 
					@ -646,7 +642,7 @@ bool X86_64TargetInfo::needsCopyRel(uint32_t Type, const SymbolBody &S) const {
 | 
				
			||||||
  return false;
 | 
					  return false;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
bool X86_64TargetInfo::needsGot(uint32_t Type, const SymbolBody &S) const {
 | 
					bool X86_64TargetInfo::needsGot(uint32_t Type, SymbolBody &S) const {
 | 
				
			||||||
  if (Type == R_X86_64_TLSGD)
 | 
					  if (Type == R_X86_64_TLSGD)
 | 
				
			||||||
    return Target->canRelaxTls(Type, &S) && canBePreempted(&S, true);
 | 
					    return Target->canRelaxTls(Type, &S) && canBePreempted(&S, true);
 | 
				
			||||||
  if (Type == R_X86_64_GOTTPOFF)
 | 
					  if (Type == R_X86_64_GOTTPOFF)
 | 
				
			||||||
| 
						 | 
					@ -658,7 +654,7 @@ bool X86_64TargetInfo::isTlsDynRel(unsigned Type, const SymbolBody &S) const {
 | 
				
			||||||
  return Type == R_X86_64_GOTTPOFF || Type == R_X86_64_TLSGD;
 | 
					  return Type == R_X86_64_GOTTPOFF || Type == R_X86_64_TLSGD;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
bool X86_64TargetInfo::needsPlt(uint32_t Type, const SymbolBody &S) const {
 | 
					bool X86_64TargetInfo::needsPlt(uint32_t Type, SymbolBody &S) const {
 | 
				
			||||||
  if (needsCopyRel(Type, S))
 | 
					  if (needsCopyRel(Type, S))
 | 
				
			||||||
    return false;
 | 
					    return false;
 | 
				
			||||||
  if (isGnuIFunc<ELF64LE>(S))
 | 
					  if (isGnuIFunc<ELF64LE>(S))
 | 
				
			||||||
| 
						 | 
					@ -684,17 +680,19 @@ bool X86_64TargetInfo::needsPlt(uint32_t Type, const SymbolBody &S) const {
 | 
				
			||||||
    // For the static linking part, we just return true and everything else
 | 
					    // For the static linking part, we just return true and everything else
 | 
				
			||||||
    // will use the the PLT entry as the address.
 | 
					    // will use the the PLT entry as the address.
 | 
				
			||||||
    //
 | 
					    //
 | 
				
			||||||
    // The remaining (unimplemented) problem is making sure pointer equality
 | 
					    // The remaining problem is making sure pointer equality still works. We
 | 
				
			||||||
    // still works. We need the help of the dynamic linker for that. We
 | 
					    // need the help of the dynamic linker for that. We let it know that we have
 | 
				
			||||||
    // let it know that we have a direct reference to a so symbol by creating
 | 
					    // a direct reference to a so symbol by creating an undefined symbol with a
 | 
				
			||||||
    // an undefined symbol with a non zero st_value. Seeing that, the
 | 
					    // non zero st_value. Seeing that, the dynamic linker resolves the symbol to
 | 
				
			||||||
    // dynamic linker resolves the symbol to the value of the symbol we created.
 | 
					    // the value of the symbol we created. This is true even for got entries, so
 | 
				
			||||||
    // This is true even for got entries, so pointer equality is maintained.
 | 
					    // pointer equality is maintained. To avoid an infinite loop, the only entry
 | 
				
			||||||
    // To avoid an infinite loop, the only entry that points to the
 | 
					    // that points to the real function is a dedicated got entry used by the
 | 
				
			||||||
    // real function is a dedicated got entry used by the plt. That is
 | 
					    // plt. That is identified by special relocation types (R_X86_64_JUMP_SLOT,
 | 
				
			||||||
    // identified by special relocation types (R_X86_64_JUMP_SLOT,
 | 
					 | 
				
			||||||
    // R_386_JMP_SLOT, etc).
 | 
					    // R_386_JMP_SLOT, etc).
 | 
				
			||||||
    return S.isShared();
 | 
					    if (!S.isShared())
 | 
				
			||||||
 | 
					      return false;
 | 
				
			||||||
 | 
					    S.NeedsCopyOrPltAddr = true;
 | 
				
			||||||
 | 
					    return true;
 | 
				
			||||||
  case R_X86_64_PLT32:
 | 
					  case R_X86_64_PLT32:
 | 
				
			||||||
    return canBePreempted(&S, true);
 | 
					    return canBePreempted(&S, true);
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
| 
						 | 
					@ -989,7 +987,7 @@ void PPC64TargetInfo::writePlt(uint8_t *Buf, uint64_t GotEntryAddr,
 | 
				
			||||||
  write32be(Buf + 28, 0x4e800420);                   // bctr
 | 
					  write32be(Buf + 28, 0x4e800420);                   // bctr
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
bool PPC64TargetInfo::needsGot(uint32_t Type, const SymbolBody &S) const {
 | 
					bool PPC64TargetInfo::needsGot(uint32_t Type, SymbolBody &S) const {
 | 
				
			||||||
  if (needsPlt(Type, S))
 | 
					  if (needsPlt(Type, S))
 | 
				
			||||||
    return true;
 | 
					    return true;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1005,7 +1003,7 @@ bool PPC64TargetInfo::needsGot(uint32_t Type, const SymbolBody &S) const {
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
bool PPC64TargetInfo::needsPlt(uint32_t Type, const SymbolBody &S) const {
 | 
					bool PPC64TargetInfo::needsPlt(uint32_t Type, SymbolBody &S) const {
 | 
				
			||||||
  // These are function calls that need to be redirected through a PLT stub.
 | 
					  // These are function calls that need to be redirected through a PLT stub.
 | 
				
			||||||
  return Type == R_PPC64_REL24 && canBePreempted(&S, false);
 | 
					  return Type == R_PPC64_REL24 && canBePreempted(&S, false);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -1240,7 +1238,7 @@ bool AArch64TargetInfo::needsCopyRel(uint32_t Type, const SymbolBody &S) const {
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
bool AArch64TargetInfo::needsGot(uint32_t Type, const SymbolBody &S) const {
 | 
					bool AArch64TargetInfo::needsGot(uint32_t Type, SymbolBody &S) const {
 | 
				
			||||||
  switch (Type) {
 | 
					  switch (Type) {
 | 
				
			||||||
  case R_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC:
 | 
					  case R_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC:
 | 
				
			||||||
  case R_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21:
 | 
					  case R_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21:
 | 
				
			||||||
| 
						 | 
					@ -1252,7 +1250,7 @@ bool AArch64TargetInfo::needsGot(uint32_t Type, const SymbolBody &S) const {
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
bool AArch64TargetInfo::needsPlt(uint32_t Type, const SymbolBody &S) const {
 | 
					bool AArch64TargetInfo::needsPlt(uint32_t Type, SymbolBody &S) const {
 | 
				
			||||||
  if (isGnuIFunc<ELF64LE>(S))
 | 
					  if (isGnuIFunc<ELF64LE>(S))
 | 
				
			||||||
    return true;
 | 
					    return true;
 | 
				
			||||||
  switch (Type) {
 | 
					  switch (Type) {
 | 
				
			||||||
| 
						 | 
					@ -1439,12 +1437,12 @@ bool MipsTargetInfo<ELFT>::needsCopyRel(uint32_t Type,
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
template <class ELFT>
 | 
					template <class ELFT>
 | 
				
			||||||
bool MipsTargetInfo<ELFT>::needsGot(uint32_t Type, const SymbolBody &S) const {
 | 
					bool MipsTargetInfo<ELFT>::needsGot(uint32_t Type, SymbolBody &S) const {
 | 
				
			||||||
  return Type == R_MIPS_GOT16 || Type == R_MIPS_CALL16;
 | 
					  return Type == R_MIPS_GOT16 || Type == R_MIPS_CALL16;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
template <class ELFT>
 | 
					template <class ELFT>
 | 
				
			||||||
bool MipsTargetInfo<ELFT>::needsPlt(uint32_t Type, const SymbolBody &S) const {
 | 
					bool MipsTargetInfo<ELFT>::needsPlt(uint32_t Type, SymbolBody &S) const {
 | 
				
			||||||
  return false;
 | 
					  return false;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -54,8 +54,8 @@ public:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  virtual bool isSizeRel(uint32_t Type) const;
 | 
					  virtual bool isSizeRel(uint32_t Type) const;
 | 
				
			||||||
  virtual bool needsDynRelative(unsigned Type) const { return false; }
 | 
					  virtual bool needsDynRelative(unsigned Type) const { return false; }
 | 
				
			||||||
  virtual bool needsGot(uint32_t Type, const SymbolBody &S) const;
 | 
					  virtual bool needsGot(uint32_t Type, SymbolBody &S) const;
 | 
				
			||||||
  virtual bool needsPlt(uint32_t Type, const SymbolBody &S) const;
 | 
					  virtual bool needsPlt(uint32_t Type, SymbolBody &S) const;
 | 
				
			||||||
  virtual void relocateOne(uint8_t *Loc, uint8_t *BufEnd, uint32_t Type,
 | 
					  virtual void relocateOne(uint8_t *Loc, uint8_t *BufEnd, uint32_t Type,
 | 
				
			||||||
                           uint64_t P, uint64_t SA, uint64_t ZA = 0,
 | 
					                           uint64_t P, uint64_t SA, uint64_t ZA = 0,
 | 
				
			||||||
                           uint8_t *PairedLoc = nullptr) const = 0;
 | 
					                           uint8_t *PairedLoc = nullptr) const = 0;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -302,10 +302,10 @@ void Writer<ELFT>::scanRelocs(
 | 
				
			||||||
    // If a symbol in a DSO is referenced directly instead of through GOT,
 | 
					    // If a symbol in a DSO is referenced directly instead of through GOT,
 | 
				
			||||||
    // we need to create a copy relocation for the symbol.
 | 
					    // we need to create a copy relocation for the symbol.
 | 
				
			||||||
    if (auto *B = dyn_cast_or_null<SharedSymbol<ELFT>>(Body)) {
 | 
					    if (auto *B = dyn_cast_or_null<SharedSymbol<ELFT>>(Body)) {
 | 
				
			||||||
      if (B->NeedsCopy)
 | 
					      if (B->needsCopy())
 | 
				
			||||||
        continue;
 | 
					        continue;
 | 
				
			||||||
      if (Target->needsCopyRel(Type, *B)) {
 | 
					      if (Target->needsCopyRel(Type, *B)) {
 | 
				
			||||||
        B->NeedsCopy = true;
 | 
					        B->NeedsCopyOrPltAddr = true;
 | 
				
			||||||
        Out<ELFT>::RelaDyn->addReloc(
 | 
					        Out<ELFT>::RelaDyn->addReloc(
 | 
				
			||||||
            {Target->CopyRel, DynamicReloc<ELFT>::Off_Bss, B});
 | 
					            {Target->CopyRel, DynamicReloc<ELFT>::Off_Bss, B});
 | 
				
			||||||
        continue;
 | 
					        continue;
 | 
				
			||||||
| 
						 | 
					@ -968,7 +968,7 @@ template <class ELFT> bool Writer<ELFT>::createSections() {
 | 
				
			||||||
    if (auto *C = dyn_cast<DefinedCommon>(Body))
 | 
					    if (auto *C = dyn_cast<DefinedCommon>(Body))
 | 
				
			||||||
      CommonSymbols.push_back(C);
 | 
					      CommonSymbols.push_back(C);
 | 
				
			||||||
    if (auto *SC = dyn_cast<SharedSymbol<ELFT>>(Body))
 | 
					    if (auto *SC = dyn_cast<SharedSymbol<ELFT>>(Body))
 | 
				
			||||||
      if (SC->NeedsCopy)
 | 
					      if (SC->needsCopy())
 | 
				
			||||||
        CopyRelSymbols.push_back(SC);
 | 
					        CopyRelSymbols.push_back(SC);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (!includeInSymtab<ELFT>(*Body))
 | 
					    if (!includeInSymtab<ELFT>(*Body))
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,4 @@
 | 
				
			||||||
 | 
						.globl	set_data
 | 
				
			||||||
 | 
						.type	set_data,@function
 | 
				
			||||||
 | 
					set_data:
 | 
				
			||||||
 | 
						retq
 | 
				
			||||||
| 
						 | 
					@ -43,4 +43,4 @@ nop
 | 
				
			||||||
.text
 | 
					.text
 | 
				
			||||||
.globl _start
 | 
					.globl _start
 | 
				
			||||||
_start:
 | 
					_start:
 | 
				
			||||||
callq do
 | 
					callq do@plt
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,23 @@
 | 
				
			||||||
 | 
					// REQUIRES: x86
 | 
				
			||||||
 | 
					// RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t.o
 | 
				
			||||||
 | 
					// RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %p/Inputs/undef-with-plt-addr.s -o %t2.o
 | 
				
			||||||
 | 
					// RUN: ld.lld %t2.o -o %t2.so -shared
 | 
				
			||||||
 | 
					// RUN: ld.lld %t.o %t2.so -o %t3
 | 
				
			||||||
 | 
					// RUN: llvm-readobj -t -s %t3 | FileCheck %s
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.globl _start
 | 
				
			||||||
 | 
					_start:
 | 
				
			||||||
 | 
					movabsq	$set_data, %rax
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Test that set_data has an address in the .plt
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// CHECK:      Name: .plt
 | 
				
			||||||
 | 
					// CHECK-NEXT: Type: SHT_PROGBITS
 | 
				
			||||||
 | 
					// CHECK-NEXT: Flags [
 | 
				
			||||||
 | 
					// CHECK-NEXT:   SHF_ALLOC
 | 
				
			||||||
 | 
					// CHECK-NEXT:   SHF_EXECINSTR
 | 
				
			||||||
 | 
					// CHECK-NEXT: ]
 | 
				
			||||||
 | 
					// CHECK-NEXT: Address: 0x11010
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// CHECK:      Name:    set_data
 | 
				
			||||||
 | 
					// CHECK-NEXT: Value:   0x11020
 | 
				
			||||||
		Loading…
	
		Reference in New Issue