Rafael Espindola | 01205f7 | 2015-09-22 18:19:46 +0000 | [diff] [blame] | 1 | //===- Target.h -------------------------------------------------*- C++ -*-===// |
| 2 | // |
| 3 | // The LLVM Linker |
| 4 | // |
| 5 | // This file is distributed under the University of Illinois Open Source |
| 6 | // License. See LICENSE.TXT for details. |
| 7 | // |
| 8 | //===----------------------------------------------------------------------===// |
| 9 | |
| 10 | #ifndef LLD_ELF_TARGET_H |
| 11 | #define LLD_ELF_TARGET_H |
| 12 | |
Simon Atanasyan | 49829a1 | 2015-09-29 05:34:03 +0000 | [diff] [blame] | 13 | #include "llvm/ADT/StringRef.h" |
Igor Kudrin | 15cd9ff | 2015-11-06 07:43:03 +0000 | [diff] [blame] | 14 | #include "llvm/Object/ELF.h" |
Simon Atanasyan | 49829a1 | 2015-09-29 05:34:03 +0000 | [diff] [blame] | 15 | |
Rafael Espindola | 01205f7 | 2015-09-22 18:19:46 +0000 | [diff] [blame] | 16 | #include <memory> |
| 17 | |
| 18 | namespace lld { |
Rafael Espindola | e0df00b | 2016-02-28 00:25:54 +0000 | [diff] [blame] | 19 | namespace elf { |
Rafael Espindola | 01205f7 | 2015-09-22 18:19:46 +0000 | [diff] [blame] | 20 | class SymbolBody; |
| 21 | |
| 22 | class TargetInfo { |
| 23 | public: |
Igor Kudrin | f6f4547 | 2015-11-10 08:39:27 +0000 | [diff] [blame] | 24 | uint64_t getVAStart() const; |
Adhemerval Zanella | 74bcf03 | 2016-02-12 13:43:03 +0000 | [diff] [blame] | 25 | virtual bool isTlsLocalDynamicRel(unsigned Type) const; |
| 26 | virtual bool isTlsGlobalDynamicRel(unsigned Type) const; |
Rui Ueyama | c516ae1 | 2016-01-29 02:33:45 +0000 | [diff] [blame] | 27 | virtual unsigned getDynRel(unsigned Type) const { return Type; } |
Rui Ueyama | 012eb78 | 2016-01-29 04:05:09 +0000 | [diff] [blame] | 28 | virtual bool isTlsDynRel(unsigned Type, const SymbolBody &S) const; |
George Rimar | 2960c98 | 2016-02-11 11:14:46 +0000 | [diff] [blame] | 29 | virtual unsigned getTlsGotRel(unsigned Type) const { return TlsGotRel; } |
Rui Ueyama | 57b676c | 2016-01-29 03:51:51 +0000 | [diff] [blame] | 30 | virtual void writeGotHeader(uint8_t *Buf) const {} |
| 31 | virtual void writeGotPltHeader(uint8_t *Buf) const {} |
| 32 | virtual void writeGotPlt(uint8_t *Buf, uint64_t Plt) const {}; |
Rui Ueyama | 69c30ed | 2016-01-29 03:00:30 +0000 | [diff] [blame] | 33 | |
| 34 | // If lazy binding is supported, the first entry of the PLT has code |
| 35 | // to call the dynamic linker to resolve PLT entries the first time |
| 36 | // they are called. This function writes that code. |
Rui Ueyama | 57b676c | 2016-01-29 03:51:51 +0000 | [diff] [blame] | 37 | virtual void writePltZero(uint8_t *Buf) const {} |
Rui Ueyama | 69c30ed | 2016-01-29 03:00:30 +0000 | [diff] [blame] | 38 | |
Rui Ueyama | 9398f86 | 2016-01-29 04:15:02 +0000 | [diff] [blame] | 39 | virtual void writePlt(uint8_t *Buf, uint64_t GotEntryAddr, |
Rui Ueyama | c516ae1 | 2016-01-29 02:33:45 +0000 | [diff] [blame] | 40 | uint64_t PltEntryAddr, int32_t Index, |
Rui Ueyama | 57b676c | 2016-01-29 03:51:51 +0000 | [diff] [blame] | 41 | unsigned RelOff) const {} |
Rui Ueyama | 2b0edc2 | 2016-01-08 02:41:35 +0000 | [diff] [blame] | 42 | |
Simon Atanasyan | 682aeea | 2016-01-14 20:42:09 +0000 | [diff] [blame] | 43 | // Returns true if a relocation is just a hint for linker to make for example |
| 44 | // some code optimization. Such relocations should not be handled as a regular |
| 45 | // ones and lead to dynamic relocation creation etc. |
Rui Ueyama | c516ae1 | 2016-01-29 02:33:45 +0000 | [diff] [blame] | 46 | virtual bool isHintRel(uint32_t Type) const; |
Simon Atanasyan | 682aeea | 2016-01-14 20:42:09 +0000 | [diff] [blame] | 47 | |
Rui Ueyama | 2b0edc2 | 2016-01-08 02:41:35 +0000 | [diff] [blame] | 48 | // Returns true if a relocation is relative to the place being relocated, |
| 49 | // such as relocations used for PC-relative instructions. Such relocations |
| 50 | // need not be fixed up if an image is loaded to a different address than |
| 51 | // the link-time address. So we don't have to emit a relocation for the |
| 52 | // dynamic linker if isRelRelative returns true. |
Rafael Espindola | ae24400 | 2015-10-05 19:30:12 +0000 | [diff] [blame] | 53 | virtual bool isRelRelative(uint32_t Type) const; |
Rui Ueyama | 2b0edc2 | 2016-01-08 02:41:35 +0000 | [diff] [blame] | 54 | |
Rui Ueyama | c516ae1 | 2016-01-29 02:33:45 +0000 | [diff] [blame] | 55 | virtual bool isSizeRel(uint32_t Type) const; |
| 56 | virtual bool needsDynRelative(unsigned Type) const { return false; } |
Rafael Espindola | a0a65f9 | 2016-02-09 15:11:01 +0000 | [diff] [blame] | 57 | virtual bool needsGot(uint32_t Type, SymbolBody &S) const; |
Rafael Espindola | 795dc5a | 2016-02-24 18:24:23 +0000 | [diff] [blame] | 58 | virtual bool refersToGotEntry(uint32_t Type) const; |
Rafael Espindola | 852860e | 2016-02-12 15:47:37 +0000 | [diff] [blame] | 59 | |
| 60 | enum PltNeed { Plt_No, Plt_Explicit, Plt_Implicit }; |
Rafael Espindola | 795dc5a | 2016-02-24 18:24:23 +0000 | [diff] [blame] | 61 | template <class ELFT> |
| 62 | PltNeed needsPlt(uint32_t Type, const SymbolBody &S) const; |
| 63 | |
Rui Ueyama | 96f0e0b | 2015-10-23 02:40:46 +0000 | [diff] [blame] | 64 | virtual void relocateOne(uint8_t *Loc, uint8_t *BufEnd, uint32_t Type, |
George Rimar | 4865148 | 2015-12-11 08:59:37 +0000 | [diff] [blame] | 65 | uint64_t P, uint64_t SA, uint64_t ZA = 0, |
Simon Atanasyan | 09b3e36 | 2015-12-01 21:24:45 +0000 | [diff] [blame] | 66 | uint8_t *PairedLoc = nullptr) const = 0; |
George Rimar | bfb7bf7 | 2015-12-21 10:00:12 +0000 | [diff] [blame] | 67 | virtual bool isGotRelative(uint32_t Type) const; |
Rui Ueyama | baf1651 | 2016-01-29 00:20:12 +0000 | [diff] [blame] | 68 | virtual bool canRelaxTls(unsigned Type, const SymbolBody *S) const; |
Rafael Espindola | f7ae359 | 2016-02-23 18:53:29 +0000 | [diff] [blame] | 69 | template <class ELFT> |
Rafael Espindola | fb1533b | 2016-02-22 21:23:29 +0000 | [diff] [blame] | 70 | bool needsCopyRel(uint32_t Type, const SymbolBody &S) const; |
Rui Ueyama | c516ae1 | 2016-01-29 02:33:45 +0000 | [diff] [blame] | 71 | virtual unsigned relaxTls(uint8_t *Loc, uint8_t *BufEnd, uint32_t Type, |
| 72 | uint64_t P, uint64_t SA, const SymbolBody *S) const; |
Rafael Espindola | 01205f7 | 2015-09-22 18:19:46 +0000 | [diff] [blame] | 73 | virtual ~TargetInfo(); |
| 74 | |
Hal Finkel | e3c2626 | 2015-10-08 22:23:54 +0000 | [diff] [blame] | 75 | unsigned PageSize = 4096; |
Hal Finkel | 736c741 | 2015-10-15 07:49:07 +0000 | [diff] [blame] | 76 | |
| 77 | // On freebsd x86_64 the first page cannot be mmaped. |
| 78 | // On linux that is controled by vm.mmap_min_addr. At least on some x86_64 |
| 79 | // installs that is 65536, so the first 15 pages cannot be used. |
| 80 | // Given that, the smallest value that can be used in here is 0x10000. |
| 81 | // If using 2MB pages, the smallest page aligned address that works is |
| 82 | // 0x200000, but it looks like every OS uses 4k pages for executables. |
| 83 | uint64_t VAStart = 0x10000; |
| 84 | |
Rui Ueyama | 724d625 | 2016-01-29 01:49:32 +0000 | [diff] [blame] | 85 | unsigned CopyRel; |
| 86 | unsigned GotRel; |
| 87 | unsigned PltRel; |
| 88 | unsigned RelativeRel; |
| 89 | unsigned IRelativeRel; |
| 90 | unsigned TlsGotRel = 0; |
Rui Ueyama | 724d625 | 2016-01-29 01:49:32 +0000 | [diff] [blame] | 91 | unsigned TlsModuleIndexRel; |
| 92 | unsigned TlsOffsetRel; |
Hal Finkel | 6c2a3b8 | 2015-10-08 21:51:31 +0000 | [diff] [blame] | 93 | unsigned PltEntrySize = 8; |
Rui Ueyama | 6251545 | 2016-01-29 03:00:32 +0000 | [diff] [blame] | 94 | unsigned PltZeroSize = 0; |
Igor Kudrin | 15cd9ff | 2015-11-06 07:43:03 +0000 | [diff] [blame] | 95 | unsigned GotHeaderEntriesNum = 0; |
Igor Kudrin | 351b41d | 2015-11-16 17:44:08 +0000 | [diff] [blame] | 96 | unsigned GotPltHeaderEntriesNum = 3; |
Rui Ueyama | 724d625 | 2016-01-29 01:49:32 +0000 | [diff] [blame] | 97 | bool UseLazyBinding = false; |
Rafael Espindola | fb1533b | 2016-02-22 21:23:29 +0000 | [diff] [blame] | 98 | |
| 99 | private: |
| 100 | virtual bool needsCopyRelImpl(uint32_t Type) const; |
Rafael Espindola | 993f027 | 2016-02-26 14:27:47 +0000 | [diff] [blame] | 101 | virtual bool needsPltImpl(uint32_t Type) const; |
Rafael Espindola | 01205f7 | 2015-09-22 18:19:46 +0000 | [diff] [blame] | 102 | }; |
| 103 | |
Hal Finkel | 6f97c2b | 2015-10-16 21:55:40 +0000 | [diff] [blame] | 104 | uint64_t getPPC64TocBase(); |
| 105 | |
Igor Kudrin | 15cd9ff | 2015-11-06 07:43:03 +0000 | [diff] [blame] | 106 | template <class ELFT> |
| 107 | typename llvm::object::ELFFile<ELFT>::uintX_t getMipsGpAddr(); |
| 108 | |
George Rimar | a07ff66 | 2015-12-21 10:12:06 +0000 | [diff] [blame] | 109 | template <class ELFT> bool isGnuIFunc(const SymbolBody &S); |
| 110 | |
Rui Ueyama | c1c282a | 2016-02-11 21:18:01 +0000 | [diff] [blame] | 111 | extern TargetInfo *Target; |
Rui Ueyama | 9100439 | 2015-10-13 16:08:15 +0000 | [diff] [blame] | 112 | TargetInfo *createTarget(); |
Rafael Espindola | 01205f7 | 2015-09-22 18:19:46 +0000 | [diff] [blame] | 113 | } |
| 114 | } |
| 115 | |
| 116 | #endif |