//===- 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 "llvm/ADT/StringRef.h" #include "llvm/Object/ELF.h" #include namespace lld { namespace elf2 { class SymbolBody; class TargetInfo { public: unsigned getPageSize() const { return PageSize; } uint64_t getVAStart() const; unsigned getCopyReloc() const { return CopyReloc; } unsigned getGotReloc() const { return GotReloc; } unsigned getPltReloc() const { return PltReloc; } unsigned getRelativeReloc() const { return RelativeReloc; } unsigned getIRelativeReloc() const { return IRelativeReloc; } bool isTlsLocalDynamicReloc(unsigned Type) const { return Type == TlsLocalDynamicReloc; } bool isTlsGlobalDynamicReloc(unsigned Type) const { return Type == TlsGlobalDynamicReloc; } unsigned getTlsModuleIndexReloc() const { return TlsModuleIndexReloc; } unsigned getTlsOffsetReloc() const { return TlsOffsetReloc; } unsigned getPltZeroEntrySize() const { return PltZeroEntrySize; } unsigned getPltEntrySize() const { return PltEntrySize; } bool supportsLazyRelocations() const { return LazyRelocations; } unsigned getGotHeaderEntriesNum() const { return GotHeaderEntriesNum; } unsigned getGotPltHeaderEntriesNum() const { return GotPltHeaderEntriesNum; } virtual unsigned getDynReloc(unsigned Type) const { return Type; } virtual bool isTlsDynReloc(unsigned Type, const SymbolBody &S) const { return false; } virtual unsigned getTlsGotReloc(unsigned Type = -1) const { return TlsGotReloc; } virtual void writeGotHeaderEntries(uint8_t *Buf) const; virtual void writeGotPltHeaderEntries(uint8_t *Buf) const; virtual void writeGotPltEntry(uint8_t *Buf, uint64_t Plt) const = 0; virtual void writePltZeroEntry(uint8_t *Buf, uint64_t GotEntryAddr, uint64_t PltEntryAddr) const = 0; virtual void writePltEntry(uint8_t *Buf, uint64_t GotAddr, uint64_t GotEntryAddr, uint64_t PltEntryAddr, int32_t Index, unsigned RelOff) const = 0; // Returns true if a relocation is relative to the place being relocated, // such as relocations used for PC-relative instructions. Such relocations // need not be fixed up if an image is loaded to a different address than // the link-time address. So we don't have to emit a relocation for the // dynamic linker if isRelRelative returns true. virtual bool isRelRelative(uint32_t Type) const; virtual bool isSizeReloc(uint32_t Type) const; virtual bool relocNeedsDynRelative(unsigned Type) const { return false; } virtual bool relocNeedsGot(uint32_t Type, const SymbolBody &S) const = 0; virtual bool relocNeedsPlt(uint32_t Type, const SymbolBody &S) const = 0; 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; virtual bool isGotRelative(uint32_t Type) const; virtual bool isTlsOptimized(unsigned Type, const SymbolBody *S) const; virtual bool needsCopyRel(uint32_t Type, const SymbolBody &S) const; virtual unsigned relocateTlsOptimize(uint8_t *Loc, uint8_t *BufEnd, uint32_t Type, uint64_t P, uint64_t SA, const SymbolBody &S) const; virtual ~TargetInfo(); protected: unsigned PageSize = 4096; // 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. // If using 2MB pages, the smallest page aligned address that works is // 0x200000, but it looks like every OS uses 4k pages for executables. uint64_t VAStart = 0x10000; unsigned CopyReloc; unsigned PCRelReloc; unsigned GotReloc; unsigned PltReloc; unsigned RelativeReloc; unsigned IRelativeReloc; unsigned TlsGotReloc = 0; unsigned TlsLocalDynamicReloc = 0; unsigned TlsGlobalDynamicReloc = 0; unsigned TlsModuleIndexReloc; unsigned TlsOffsetReloc; unsigned PltEntrySize = 8; unsigned PltZeroEntrySize = 0; unsigned GotHeaderEntriesNum = 0; unsigned GotPltHeaderEntriesNum = 3; bool LazyRelocations = false; }; uint64_t getPPC64TocBase(); template typename llvm::object::ELFFile::uintX_t getMipsGpAddr(); template bool isGnuIFunc(const SymbolBody &S); extern std::unique_ptr Target; TargetInfo *createTarget(); } } #endif