//===- Target.h -------------------------------------------------*- C++ -*-===// // // The LLVM Linker // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// #ifndef LLD_ELF_TARGET_H #define LLD_ELF_TARGET_H #include "InputSection.h" #include "lld/Common/ErrorHandler.h" #include "llvm/Object/ELF.h" namespace lld { std::string toString(elf::RelType Type); namespace elf { class Defined; class InputFile; class Symbol; class TargetInfo { public: virtual uint32_t calcEFlags() const { return 0; } virtual bool isPicRel(RelType Type) const { return true; } virtual RelType getDynRel(RelType Type) const { return Type; } virtual void writeGotPltHeader(uint8_t *Buf) const {} virtual void writeGotPlt(uint8_t *Buf, const Symbol &S) const {}; virtual void writeIgotPlt(uint8_t *Buf, const Symbol &S) const; virtual int64_t getImplicitAddend(const uint8_t *Buf, RelType Type) const; // If lazy binding is supported, the first entry of the PLT has code // to call the dynamic linker to resolve PLT entries the first time // they are called. This function writes that code. virtual void writePltHeader(uint8_t *Buf) const {} virtual void writePlt(uint8_t *Buf, uint64_t GotEntryAddr, uint64_t PltEntryAddr, int32_t Index, unsigned RelOff) const {} virtual void addPltHeaderSymbols(InputSectionBase *IS) const {} virtual void addPltSymbols(InputSectionBase *IS, uint64_t Off) const {} // Returns true if a relocation only uses the low bits of a value such that // all those bits are in in the same page. For example, if the relocation // only uses the low 12 bits in a system with 4k pages. If this is true, the // bits will always have the same value at runtime and we don't have to emit // a dynamic relocation. virtual bool usesOnlyLowPageBits(RelType Type) const; // Decide whether a Thunk is needed for the relocation from File // targeting S. virtual bool needsThunk(RelExpr Expr, RelType RelocType, const InputFile *File, uint64_t BranchAddr, const Symbol &S) const; // Return true if we can reach Dst from Src with Relocation RelocType virtual bool inBranchRange(RelType Type, uint64_t Src, uint64_t Dst) const; virtual RelExpr getRelExpr(RelType Type, const Symbol &S, const uint8_t *Loc) const = 0; virtual void relocateOne(uint8_t *Loc, RelType Type, uint64_t Val) const = 0; virtual ~TargetInfo(); unsigned TlsGdRelaxSkip = 1; unsigned PageSize = 4096; unsigned DefaultMaxPageSize = 4096; uint64_t getImageBase(); // Offset of _GLOBAL_OFFSET_TABLE_ from base of .got section. Use -1 for // end of .got uint64_t GotBaseSymOff = 0; // On systems with range extensions we place collections of Thunks at // regular spacings that enable the majority of branches reach the Thunks. uint32_t ThunkSectionSpacing = 0; RelType CopyRel; RelType GotRel; RelType PltRel; RelType RelativeRel; RelType IRelativeRel; RelType TlsDescRel; RelType TlsGotRel; RelType TlsModuleIndexRel; RelType TlsOffsetRel; unsigned GotEntrySize = 0; unsigned GotPltEntrySize = 0; unsigned PltEntrySize; unsigned PltHeaderSize; // At least on x86_64 positions 1 and 2 are used by the first plt entry // to support lazy loading. unsigned GotPltHeaderEntriesNum = 3; // Set to 0 for variant 2 unsigned TcbSize = 0; bool NeedsThunks = false; // A 4-byte field corresponding to one or more trap instructions, used to pad // executable OutputSections. uint32_t TrapInstr = 0; virtual RelExpr adjustRelaxExpr(RelType Type, const uint8_t *Data, RelExpr Expr) const; virtual void relaxGot(uint8_t *Loc, uint64_t Val) const; virtual void relaxTlsGdToIe(uint8_t *Loc, RelType Type, uint64_t Val) const; virtual void relaxTlsGdToLe(uint8_t *Loc, RelType Type, uint64_t Val) const; virtual void relaxTlsIeToLe(uint8_t *Loc, RelType Type, uint64_t Val) const; virtual void relaxTlsLdToLe(uint8_t *Loc, RelType Type, uint64_t Val) const; protected: // On FreeBSD x86_64 the first page cannot be mmaped. // On Linux that is controled by vm.mmap_min_addr. At least on some x86_64 // installs that is 65536, so the first 15 pages cannot be used. // Given that, the smallest value that can be used in here is 0x10000. uint64_t DefaultImageBase = 0x10000; }; TargetInfo *getAArch64TargetInfo(); TargetInfo *getAMDGPUTargetInfo(); TargetInfo *getARMTargetInfo(); TargetInfo *getAVRTargetInfo(); TargetInfo *getPPC64TargetInfo(); TargetInfo *getPPCTargetInfo(); TargetInfo *getSPARCV9TargetInfo(); TargetInfo *getX32TargetInfo(); TargetInfo *getX86TargetInfo(); TargetInfo *getX86_64TargetInfo(); template TargetInfo *getMipsTargetInfo(); std::string getErrorLocation(const uint8_t *Loc); uint64_t getPPC64TocBase(); uint64_t getAArch64Page(uint64_t Expr); extern TargetInfo *Target; TargetInfo *getTarget(); template bool isMipsPIC(const Defined *Sym); static inline void reportRangeError(uint8_t *Loc, RelType Type, const Twine &V, int64_t Min, uint64_t Max) { error(getErrorLocation(Loc) + "relocation " + lld::toString(Type) + " out of range: " + V + " is not in [" + Twine(Min) + ", " + Twine(Max) + "]"); } template static void checkInt(uint8_t *Loc, int64_t V, RelType Type) { if (!llvm::isInt(V)) reportRangeError(Loc, Type, Twine(V), llvm::minIntN(N), llvm::maxIntN(N)); } template static void checkUInt(uint8_t *Loc, uint64_t V, RelType Type) { if (!llvm::isUInt(V)) reportRangeError(Loc, Type, Twine(V), 0, llvm::maxUIntN(N)); } template static void checkIntUInt(uint8_t *Loc, uint64_t V, RelType Type) { if (!llvm::isInt(V) && !llvm::isUInt(V)) // For the error message we should cast V to a signed integer so that error // messages show a small negative value rather than an extremely large one reportRangeError(Loc, Type, Twine((int64_t)V), llvm::minIntN(N), llvm::maxUIntN(N)); } template static void checkAlignment(uint8_t *Loc, uint64_t V, RelType Type) { if ((V & (N - 1)) != 0) error(getErrorLocation(Loc) + "improper alignment for relocation " + lld::toString(Type) + ": 0x" + llvm::utohexstr(V) + " is not aligned to " + Twine(N) + " bytes"); } } // namespace elf } // namespace lld #endif