blob: 9aa804c6c5abe94a83d6a4c91957b7c75332a9c8 [file] [log] [blame]
Rafael Espindola01205f72015-09-22 18:19:46 +00001//===- Target.cpp ---------------------------------------------------------===//
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//===----------------------------------------------------------------------===//
Rui Ueyama34f29242015-10-13 19:51:57 +00009//
Rui Ueyama66072272015-10-15 19:52:27 +000010// Machine-specific things, such as applying relocations, creation of
11// GOT or PLT entries, etc., are handled in this file.
12//
13// Refer the ELF spec for the single letter varaibles, S, A or P, used
14// in this file. SA is S+A.
Rui Ueyama34f29242015-10-13 19:51:57 +000015//
16//===----------------------------------------------------------------------===//
Rafael Espindola01205f72015-09-22 18:19:46 +000017
18#include "Target.h"
Rafael Espindolac4010882015-09-22 20:54:08 +000019#include "Error.h"
Rui Ueyamaaf21d922015-10-08 20:06:07 +000020#include "OutputSections.h"
Rafael Espindola3ef3a4c2015-09-29 23:22:16 +000021#include "Symbols.h"
Rafael Espindola01205f72015-09-22 18:19:46 +000022
23#include "llvm/ADT/ArrayRef.h"
Rafael Espindolac4010882015-09-22 20:54:08 +000024#include "llvm/Object/ELF.h"
Rafael Espindola01205f72015-09-22 18:19:46 +000025#include "llvm/Support/Endian.h"
26#include "llvm/Support/ELF.h"
27
28using namespace llvm;
Rafael Espindolac4010882015-09-22 20:54:08 +000029using namespace llvm::object;
Rafael Espindola0872ea32015-09-24 14:16:02 +000030using namespace llvm::support::endian;
Rafael Espindola01205f72015-09-22 18:19:46 +000031using namespace llvm::ELF;
32
33namespace lld {
34namespace elf2 {
35
36std::unique_ptr<TargetInfo> Target;
37
Rafael Espindolae7e57b22015-11-09 21:43:00 +000038template <endianness E> static void add32(void *P, int32_t V) {
39 write32<E>(P, read32<E>(P) + V);
40}
Igor Kudrin15cd9ff2015-11-06 07:43:03 +000041
Rafael Espindolae7e57b22015-11-09 21:43:00 +000042static void add32le(uint8_t *P, int32_t V) { add32<support::little>(P, V); }
43static void or32le(uint8_t *P, int32_t V) { write32le(P, read32le(P) | V); }
Rui Ueyamaefc23de2015-10-14 21:30:32 +000044
Igor Kudrin9b7e7db2015-11-26 09:49:44 +000045template <unsigned N> static void checkInt(int64_t V, uint32_t Type) {
46 if (isInt<N>(V))
47 return;
48 StringRef S = getELFRelocationTypeName(Config->EMachine, Type);
49 error("Relocation " + S + " out of range");
50}
51
52template <unsigned N> static void checkUInt(uint64_t V, uint32_t Type) {
53 if (isUInt<N>(V))
54 return;
55 StringRef S = getELFRelocationTypeName(Config->EMachine, Type);
56 error("Relocation " + S + " out of range");
57}
58
Igor Kudrinfea8ed52015-11-26 10:05:24 +000059template <unsigned N> static void checkIntUInt(uint64_t V, uint32_t Type) {
60 if (isInt<N>(V) || isUInt<N>(V))
61 return;
62 StringRef S = getELFRelocationTypeName(Config->EMachine, Type);
63 error("Relocation " + S + " out of range");
64}
65
Igor Kudrin9b7e7db2015-11-26 09:49:44 +000066template <unsigned N> static void checkAlignment(uint64_t V, uint32_t Type) {
67 if ((V & (N - 1)) == 0)
68 return;
69 StringRef S = getELFRelocationTypeName(Config->EMachine, Type);
70 error("Improper alignment for relocation " + S);
71}
72
George Rimara07ff662015-12-21 10:12:06 +000073template <class ELFT> bool isGnuIFunc(const SymbolBody &S) {
Rafael Espindola4d4b06a2015-12-24 00:47:42 +000074 if (auto *SS = dyn_cast<DefinedElf<ELFT>>(&S))
George Rimara07ff662015-12-21 10:12:06 +000075 return SS->Sym.getType() == STT_GNU_IFUNC;
76 return false;
77}
78
79template bool isGnuIFunc<ELF32LE>(const SymbolBody &S);
80template bool isGnuIFunc<ELF32BE>(const SymbolBody &S);
81template bool isGnuIFunc<ELF64LE>(const SymbolBody &S);
82template bool isGnuIFunc<ELF64BE>(const SymbolBody &S);
83
Rui Ueyamaefc23de2015-10-14 21:30:32 +000084namespace {
85class X86TargetInfo final : public TargetInfo {
86public:
87 X86TargetInfo();
George Rimar77b77792015-11-25 22:15:01 +000088 void writeGotPltHeaderEntries(uint8_t *Buf) const override;
George Rimard23970f2015-11-25 20:41:53 +000089 unsigned getDynReloc(unsigned Type) const override;
George Rimar6f17e092015-12-17 09:32:21 +000090 unsigned getTlsGotReloc(unsigned Type) const override;
91 bool isTlsDynReloc(unsigned Type, const SymbolBody &S) const override;
George Rimar648a2c32015-10-20 08:54:27 +000092 void writeGotPltEntry(uint8_t *Buf, uint64_t Plt) const override;
93 void writePltZeroEntry(uint8_t *Buf, uint64_t GotEntryAddr,
94 uint64_t PltEntryAddr) const override;
George Rimar77b77792015-11-25 22:15:01 +000095 void writePltEntry(uint8_t *Buf, uint64_t GotAddr, uint64_t GotEntryAddr,
96 uint64_t PltEntryAddr, int32_t Index,
97 unsigned RelOff) const override;
Rui Ueyama02dfd492015-12-17 01:18:40 +000098 bool needsCopyRel(uint32_t Type, const SymbolBody &S) const override;
George Rimar6f17e092015-12-17 09:32:21 +000099 bool relocNeedsDynRelative(unsigned Type) const override;
Rui Ueyamaefc23de2015-10-14 21:30:32 +0000100 bool relocNeedsGot(uint32_t Type, const SymbolBody &S) const override;
Rui Ueyamaefc23de2015-10-14 21:30:32 +0000101 bool relocNeedsPlt(uint32_t Type, const SymbolBody &S) const override;
Rui Ueyama96f0e0b2015-10-23 02:40:46 +0000102 void relocateOne(uint8_t *Loc, uint8_t *BufEnd, uint32_t Type, uint64_t P,
George Rimar48651482015-12-11 08:59:37 +0000103 uint64_t SA, uint64_t ZA = 0,
104 uint8_t *PairedLoc = nullptr) const override;
George Rimar2558e122015-12-09 09:55:54 +0000105 bool isTlsOptimized(unsigned Type, const SymbolBody *S) const override;
106 unsigned relocateTlsOptimize(uint8_t *Loc, uint8_t *BufEnd, uint32_t Type,
107 uint64_t P, uint64_t SA,
108 const SymbolBody &S) const override;
George Rimarbfb7bf72015-12-21 10:00:12 +0000109 bool isGotRelative(uint32_t Type) const override;
George Rimar2558e122015-12-09 09:55:54 +0000110
111private:
112 void relocateTlsLdToLe(uint8_t *Loc, uint8_t *BufEnd, uint64_t P,
113 uint64_t SA) const;
114 void relocateTlsGdToIe(uint8_t *Loc, uint8_t *BufEnd, uint64_t P,
115 uint64_t SA) const;
116 void relocateTlsGdToLe(uint8_t *Loc, uint8_t *BufEnd, uint64_t P,
117 uint64_t SA) const;
George Rimar6f17e092015-12-17 09:32:21 +0000118 void relocateTlsIeToLe(unsigned Type, uint8_t *Loc, uint8_t *BufEnd,
119 uint64_t P, uint64_t SA) const;
Rui Ueyamaefc23de2015-10-14 21:30:32 +0000120};
121
122class X86_64TargetInfo final : public TargetInfo {
123public:
124 X86_64TargetInfo();
George Rimar6f17e092015-12-17 09:32:21 +0000125 bool isTlsDynReloc(unsigned Type, const SymbolBody &S) const override;
Igor Kudrin351b41d2015-11-16 17:44:08 +0000126 void writeGotPltHeaderEntries(uint8_t *Buf) const override;
George Rimar648a2c32015-10-20 08:54:27 +0000127 void writeGotPltEntry(uint8_t *Buf, uint64_t Plt) const override;
128 void writePltZeroEntry(uint8_t *Buf, uint64_t GotEntryAddr,
129 uint64_t PltEntryAddr) const override;
George Rimar77b77792015-11-25 22:15:01 +0000130 void writePltEntry(uint8_t *Buf, uint64_t GotAddr, uint64_t GotEntryAddr,
131 uint64_t PltEntryAddr, int32_t Index,
132 unsigned RelOff) const override;
Rui Ueyama02dfd492015-12-17 01:18:40 +0000133 bool needsCopyRel(uint32_t Type, const SymbolBody &S) const override;
Rui Ueyamaefc23de2015-10-14 21:30:32 +0000134 bool relocNeedsGot(uint32_t Type, const SymbolBody &S) const override;
135 bool relocNeedsPlt(uint32_t Type, const SymbolBody &S) const override;
Rui Ueyama96f0e0b2015-10-23 02:40:46 +0000136 void relocateOne(uint8_t *Loc, uint8_t *BufEnd, uint32_t Type, uint64_t P,
George Rimar48651482015-12-11 08:59:37 +0000137 uint64_t SA, uint64_t ZA = 0,
138 uint8_t *PairedLoc = nullptr) const override;
Rui Ueyamaefc23de2015-10-14 21:30:32 +0000139 bool isRelRelative(uint32_t Type) const override;
George Rimar6713cf82015-11-25 21:46:05 +0000140 bool isTlsOptimized(unsigned Type, const SymbolBody *S) const override;
Rui Ueyama3a7c2f62016-01-08 00:13:23 +0000141 bool isSizeReloc(uint32_t Type) const override;
George Rimar6713cf82015-11-25 21:46:05 +0000142 unsigned relocateTlsOptimize(uint8_t *Loc, uint8_t *BufEnd, uint32_t Type,
George Rimar25411f252015-12-04 11:20:13 +0000143 uint64_t P, uint64_t SA,
144 const SymbolBody &S) const override;
George Rimar6713cf82015-11-25 21:46:05 +0000145
146private:
147 void relocateTlsLdToLe(uint8_t *Loc, uint8_t *BufEnd, uint64_t P,
148 uint64_t SA) const;
149 void relocateTlsGdToLe(uint8_t *Loc, uint8_t *BufEnd, uint64_t P,
150 uint64_t SA) const;
George Rimar25411f252015-12-04 11:20:13 +0000151 void relocateTlsGdToIe(uint8_t *Loc, uint8_t *BufEnd, uint64_t P,
152 uint64_t SA) const;
George Rimar6713cf82015-11-25 21:46:05 +0000153 void relocateTlsIeToLe(uint8_t *Loc, uint8_t *BufEnd, uint64_t P,
154 uint64_t SA) const;
Rui Ueyamaefc23de2015-10-14 21:30:32 +0000155};
156
Davide Italiano8c3444362016-01-11 19:45:33 +0000157class PPCTargetInfo final : public TargetInfo {
158public:
159 PPCTargetInfo();
160 void writeGotPltEntry(uint8_t *Buf, uint64_t Plt) const override;
161 void writePltZeroEntry(uint8_t *Buf, uint64_t GotEntryAddr,
162 uint64_t PltEntryAddr) const override;
163 void writePltEntry(uint8_t *Buf, uint64_t GotAddr, uint64_t GotEntryAddr,
164 uint64_t PltEntryAddr, int32_t Index,
165 unsigned RelOff) const override;
166 bool relocNeedsGot(uint32_t Type, const SymbolBody &S) const override;
167 bool relocNeedsPlt(uint32_t Type, const SymbolBody &S) const override;
168 void relocateOne(uint8_t *Loc, uint8_t *BufEnd, uint32_t Type, uint64_t P,
169 uint64_t SA, uint64_t ZA = 0,
170 uint8_t *PairedLoc = nullptr) const override;
171 bool isRelRelative(uint32_t Type) const override;
172};
173
Rui Ueyamaefc23de2015-10-14 21:30:32 +0000174class PPC64TargetInfo final : public TargetInfo {
175public:
176 PPC64TargetInfo();
George Rimar648a2c32015-10-20 08:54:27 +0000177 void writeGotPltEntry(uint8_t *Buf, uint64_t Plt) const override;
178 void writePltZeroEntry(uint8_t *Buf, uint64_t GotEntryAddr,
179 uint64_t PltEntryAddr) const override;
George Rimar77b77792015-11-25 22:15:01 +0000180 void writePltEntry(uint8_t *Buf, uint64_t GotAddr, uint64_t GotEntryAddr,
181 uint64_t PltEntryAddr, int32_t Index,
182 unsigned RelOff) const override;
Rui Ueyamaefc23de2015-10-14 21:30:32 +0000183 bool relocNeedsGot(uint32_t Type, const SymbolBody &S) const override;
184 bool relocNeedsPlt(uint32_t Type, const SymbolBody &S) const override;
Rui Ueyama96f0e0b2015-10-23 02:40:46 +0000185 void relocateOne(uint8_t *Loc, uint8_t *BufEnd, uint32_t Type, uint64_t P,
George Rimar48651482015-12-11 08:59:37 +0000186 uint64_t SA, uint64_t ZA = 0,
187 uint8_t *PairedLoc = nullptr) const override;
Rui Ueyamaefc23de2015-10-14 21:30:32 +0000188 bool isRelRelative(uint32_t Type) const override;
189};
190
Rui Ueyamaefc23de2015-10-14 21:30:32 +0000191class AArch64TargetInfo final : public TargetInfo {
192public:
193 AArch64TargetInfo();
Igor Kudrincfe47f52015-12-05 06:20:24 +0000194 unsigned getDynReloc(unsigned Type) const override;
George Rimar648a2c32015-10-20 08:54:27 +0000195 void writeGotPltEntry(uint8_t *Buf, uint64_t Plt) const override;
196 void writePltZeroEntry(uint8_t *Buf, uint64_t GotEntryAddr,
197 uint64_t PltEntryAddr) const override;
George Rimar77b77792015-11-25 22:15:01 +0000198 void writePltEntry(uint8_t *Buf, uint64_t GotAddr, uint64_t GotEntryAddr,
199 uint64_t PltEntryAddr, int32_t Index,
200 unsigned RelOff) const override;
George Rimar3d737e42016-01-13 13:04:46 +0000201 unsigned getTlsGotReloc(unsigned Type = -1) const override;
202 bool isTlsDynReloc(unsigned Type, const SymbolBody &S) const override;
Rui Ueyama02dfd492015-12-17 01:18:40 +0000203 bool needsCopyRel(uint32_t Type, const SymbolBody &S) const override;
Rui Ueyamaefc23de2015-10-14 21:30:32 +0000204 bool relocNeedsGot(uint32_t Type, const SymbolBody &S) const override;
205 bool relocNeedsPlt(uint32_t Type, const SymbolBody &S) const override;
Rui Ueyama96f0e0b2015-10-23 02:40:46 +0000206 void relocateOne(uint8_t *Loc, uint8_t *BufEnd, uint32_t Type, uint64_t P,
George Rimar48651482015-12-11 08:59:37 +0000207 uint64_t SA, uint64_t ZA = 0,
208 uint8_t *PairedLoc = nullptr) const override;
Rui Ueyamaefc23de2015-10-14 21:30:32 +0000209};
210
Tom Stellard80efb162016-01-07 03:59:08 +0000211class AMDGPUTargetInfo final : public TargetInfo {
212public:
213 AMDGPUTargetInfo();
214 void writeGotPltEntry(uint8_t *Buf, uint64_t Plt) const override;
215 void writePltZeroEntry(uint8_t *Buf, uint64_t GotEntryAddr,
216 uint64_t PltEntryAddr) const override;
217 void writePltEntry(uint8_t *Buf, uint64_t GotAddr, uint64_t GotEntryAddr,
218 uint64_t PltEntryAddr, int32_t Index,
219 unsigned RelOff) const override;
220 bool relocNeedsGot(uint32_t Type, const SymbolBody &S) const override;
221 bool relocNeedsPlt(uint32_t Type, const SymbolBody &S) const override;
222 void relocateOne(uint8_t *Loc, uint8_t *BufEnd, uint32_t Type, uint64_t P,
223 uint64_t SA, uint64_t ZA = 0,
224 uint8_t *PairedLoc = nullptr) const override;
225};
226
Rui Ueyamaefc23de2015-10-14 21:30:32 +0000227template <class ELFT> class MipsTargetInfo final : public TargetInfo {
228public:
229 MipsTargetInfo();
Igor Kudrin15cd9ff2015-11-06 07:43:03 +0000230 void writeGotHeaderEntries(uint8_t *Buf) const override;
George Rimar648a2c32015-10-20 08:54:27 +0000231 void writeGotPltEntry(uint8_t *Buf, uint64_t Plt) const override;
232 void writePltZeroEntry(uint8_t *Buf, uint64_t GotEntryAddr,
233 uint64_t PltEntryAddr) const override;
George Rimar77b77792015-11-25 22:15:01 +0000234 void writePltEntry(uint8_t *Buf, uint64_t GotAddr, uint64_t GotEntryAddr,
235 uint64_t PltEntryAddr, int32_t Index,
236 unsigned RelOff) const override;
Rui Ueyamaefc23de2015-10-14 21:30:32 +0000237 bool relocNeedsGot(uint32_t Type, const SymbolBody &S) const override;
238 bool relocNeedsPlt(uint32_t Type, const SymbolBody &S) const override;
Rui Ueyama96f0e0b2015-10-23 02:40:46 +0000239 void relocateOne(uint8_t *Loc, uint8_t *BufEnd, uint32_t Type, uint64_t P,
George Rimar48651482015-12-11 08:59:37 +0000240 uint64_t SA, uint64_t ZA = 0,
241 uint8_t *PairedLoc = nullptr) const override;
Simon Atanasyan682aeea2016-01-14 20:42:09 +0000242 bool isHintReloc(uint32_t Type) const override;
Simon Atanasyan0fc0acf2015-12-21 17:36:40 +0000243 bool isRelRelative(uint32_t Type) const override;
Rui Ueyamaefc23de2015-10-14 21:30:32 +0000244};
245} // anonymous namespace
246
Rui Ueyama91004392015-10-13 16:08:15 +0000247TargetInfo *createTarget() {
248 switch (Config->EMachine) {
249 case EM_386:
250 return new X86TargetInfo();
251 case EM_AARCH64:
252 return new AArch64TargetInfo();
Tom Stellard80efb162016-01-07 03:59:08 +0000253 case EM_AMDGPU:
254 return new AMDGPUTargetInfo();
Rui Ueyama91004392015-10-13 16:08:15 +0000255 case EM_MIPS:
Simon Atanasyan9c2d7882015-10-14 14:24:46 +0000256 switch (Config->EKind) {
257 case ELF32LEKind:
258 return new MipsTargetInfo<ELF32LE>();
259 case ELF32BEKind:
260 return new MipsTargetInfo<ELF32BE>();
261 default:
262 error("Unsupported MIPS target");
263 }
Davide Italiano8c3444362016-01-11 19:45:33 +0000264 case EM_PPC:
265 return new PPCTargetInfo();
Rui Ueyama91004392015-10-13 16:08:15 +0000266 case EM_PPC64:
267 return new PPC64TargetInfo();
268 case EM_X86_64:
269 return new X86_64TargetInfo();
270 }
271 error("Unknown target machine");
272}
273
Rafael Espindola01205f72015-09-22 18:19:46 +0000274TargetInfo::~TargetInfo() {}
275
George Rimar6713cf82015-11-25 21:46:05 +0000276bool TargetInfo::isTlsOptimized(unsigned Type, const SymbolBody *S) const {
George Rimar77d1cb12015-11-24 09:00:06 +0000277 return false;
278}
279
Igor Kudrinf6f45472015-11-10 08:39:27 +0000280uint64_t TargetInfo::getVAStart() const { return Config->Shared ? 0 : VAStart; }
281
Rui Ueyama02dfd492015-12-17 01:18:40 +0000282bool TargetInfo::needsCopyRel(uint32_t Type, const SymbolBody &S) const {
George Rimarbc590fe2015-10-28 16:48:58 +0000283 return false;
284}
285
George Rimarbfb7bf72015-12-21 10:00:12 +0000286bool TargetInfo::isGotRelative(uint32_t Type) const { return false; }
287
Simon Atanasyan682aeea2016-01-14 20:42:09 +0000288bool TargetInfo::isHintReloc(uint32_t Type) const { return false; }
289
Rafael Espindolaae244002015-10-05 19:30:12 +0000290bool TargetInfo::isRelRelative(uint32_t Type) const { return true; }
291
Rui Ueyama3a7c2f62016-01-08 00:13:23 +0000292bool TargetInfo::isSizeReloc(uint32_t Type) const { return false; }
George Rimar48651482015-12-11 08:59:37 +0000293
George Rimar6713cf82015-11-25 21:46:05 +0000294unsigned TargetInfo::relocateTlsOptimize(uint8_t *Loc, uint8_t *BufEnd,
George Rimar25411f252015-12-04 11:20:13 +0000295 uint32_t Type, uint64_t P, uint64_t SA,
296 const SymbolBody &S) const {
George Rimar6713cf82015-11-25 21:46:05 +0000297 return 0;
298}
George Rimar77d1cb12015-11-24 09:00:06 +0000299
Igor Kudrin15cd9ff2015-11-06 07:43:03 +0000300void TargetInfo::writeGotHeaderEntries(uint8_t *Buf) const {}
301
Igor Kudrin351b41d2015-11-16 17:44:08 +0000302void TargetInfo::writeGotPltHeaderEntries(uint8_t *Buf) const {}
303
Rafael Espindola7f074422015-09-22 21:35:51 +0000304X86TargetInfo::X86TargetInfo() {
George Rimar70e25082015-11-25 11:27:40 +0000305 CopyReloc = R_386_COPY;
Rafael Espindola7f074422015-09-22 21:35:51 +0000306 PCRelReloc = R_386_PC32;
307 GotReloc = R_386_GLOB_DAT;
George Rimar648a2c32015-10-20 08:54:27 +0000308 PltReloc = R_386_JUMP_SLOT;
George Rimara07ff662015-12-21 10:12:06 +0000309 IRelativeReloc = R_386_IRELATIVE;
George Rimar6f17e092015-12-17 09:32:21 +0000310 RelativeReloc = R_386_RELATIVE;
George Rimar9db204a2015-12-02 09:58:20 +0000311 TlsGotReloc = R_386_TLS_TPOFF;
312 TlsGlobalDynamicReloc = R_386_TLS_GD;
313 TlsLocalDynamicReloc = R_386_TLS_LDM;
314 TlsModuleIndexReloc = R_386_TLS_DTPMOD32;
315 TlsOffsetReloc = R_386_TLS_DTPOFF32;
George Rimar77b77792015-11-25 22:15:01 +0000316 LazyRelocations = true;
317 PltEntrySize = 16;
318 PltZeroEntrySize = 16;
319}
320
321void X86TargetInfo::writeGotPltHeaderEntries(uint8_t *Buf) const {
322 write32le(Buf, Out<ELF32LE>::Dynamic->getVA());
323}
324
325void X86TargetInfo::writeGotPltEntry(uint8_t *Buf, uint64_t Plt) const {
326 // Skip 6 bytes of "pushl (GOT+4)"
327 write32le(Buf, Plt + 6);
Rafael Espindola7f074422015-09-22 21:35:51 +0000328}
Rafael Espindola01205f72015-09-22 18:19:46 +0000329
George Rimard23970f2015-11-25 20:41:53 +0000330unsigned X86TargetInfo::getDynReloc(unsigned Type) const {
331 if (Type == R_386_TLS_LE)
332 return R_386_TLS_TPOFF;
333 if (Type == R_386_TLS_LE_32)
334 return R_386_TLS_TPOFF32;
335 return Type;
336}
337
George Rimar6f17e092015-12-17 09:32:21 +0000338unsigned X86TargetInfo::getTlsGotReloc(unsigned Type) const {
339 if (Type == R_386_TLS_IE)
340 return Type;
341 return TlsGotReloc;
342}
343
344bool X86TargetInfo::isTlsDynReloc(unsigned Type, const SymbolBody &S) const {
George Rimar9db204a2015-12-02 09:58:20 +0000345 if (Type == R_386_TLS_LE || Type == R_386_TLS_LE_32 ||
346 Type == R_386_TLS_GOTIE)
George Rimard23970f2015-11-25 20:41:53 +0000347 return Config->Shared;
George Rimar6f17e092015-12-17 09:32:21 +0000348 if (Type == R_386_TLS_IE)
349 return canBePreempted(&S, true);
George Rimar2558e122015-12-09 09:55:54 +0000350 return Type == R_386_TLS_GD;
George Rimard23970f2015-11-25 20:41:53 +0000351}
352
George Rimar648a2c32015-10-20 08:54:27 +0000353void X86TargetInfo::writePltZeroEntry(uint8_t *Buf, uint64_t GotEntryAddr,
George Rimar77b77792015-11-25 22:15:01 +0000354 uint64_t PltEntryAddr) const {
355 // Executable files and shared object files have
356 // separate procedure linkage tables.
357 if (Config->Shared) {
358 const uint8_t V[] = {
Rui Ueyamaf53b1b72016-01-05 16:35:46 +0000359 0xff, 0xb3, 0x04, 0x00, 0x00, 0x00, // pushl 4(%ebx)
George Rimar77b77792015-11-25 22:15:01 +0000360 0xff, 0xa3, 0x08, 0x00, 0x00, 0x00, // jmp *8(%ebx)
361 0x90, 0x90, 0x90, 0x90 // nop;nop;nop;nop
362 };
363 memcpy(Buf, V, sizeof(V));
364 return;
365 }
George Rimar648a2c32015-10-20 08:54:27 +0000366
George Rimar77b77792015-11-25 22:15:01 +0000367 const uint8_t PltData[] = {
368 0xff, 0x35, 0x00, 0x00, 0x00, 0x00, // pushl (GOT+4)
369 0xff, 0x25, 0x00, 0x00, 0x00, 0x00, // jmp *(GOT+8)
370 0x90, 0x90, 0x90, 0x90 // nop;nop;nop;nop
371 };
372 memcpy(Buf, PltData, sizeof(PltData));
373 write32le(Buf + 2, GotEntryAddr + 4); // GOT+4
374 write32le(Buf + 8, GotEntryAddr + 8); // GOT+8
375}
376
377void X86TargetInfo::writePltEntry(uint8_t *Buf, uint64_t GotAddr,
378 uint64_t GotEntryAddr, uint64_t PltEntryAddr,
379 int32_t Index, unsigned RelOff) const {
380 const uint8_t Inst[] = {
381 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, // jmp *foo_in_GOT|*foo@GOT(%ebx)
382 0x68, 0x00, 0x00, 0x00, 0x00, // pushl $reloc_offset
383 0xe9, 0x00, 0x00, 0x00, 0x00 // jmp .PLT0@PC
384 };
Rui Ueyama1500a902015-09-29 23:00:47 +0000385 memcpy(Buf, Inst, sizeof(Inst));
George Rimar77b77792015-11-25 22:15:01 +0000386 // jmp *foo@GOT(%ebx) or jmp *foo_in_GOT
387 Buf[1] = Config->Shared ? 0xa3 : 0x25;
388 write32le(Buf + 2, Config->Shared ? (GotEntryAddr - GotAddr) : GotEntryAddr);
389 write32le(Buf + 7, RelOff);
390 write32le(Buf + 12, -Index * PltEntrySize - PltZeroEntrySize - 16);
Rafael Espindola01205f72015-09-22 18:19:46 +0000391}
392
Rui Ueyama02dfd492015-12-17 01:18:40 +0000393bool X86TargetInfo::needsCopyRel(uint32_t Type, const SymbolBody &S) const {
George Rimar70e25082015-11-25 11:27:40 +0000394 if (Type == R_386_32 || Type == R_386_16 || Type == R_386_8)
395 if (auto *SS = dyn_cast<SharedSymbol<ELF32LE>>(&S))
396 return SS->Sym.getType() == STT_OBJECT;
397 return false;
398}
399
Rafael Espindola3ef3a4c2015-09-29 23:22:16 +0000400bool X86TargetInfo::relocNeedsGot(uint32_t Type, const SymbolBody &S) const {
Rui Ueyama62d0e322015-12-17 00:04:18 +0000401 if (S.isTls() && Type == R_386_TLS_GD)
George Rimar2558e122015-12-09 09:55:54 +0000402 return Target->isTlsOptimized(Type, &S) && canBePreempted(&S, true);
George Rimar6f17e092015-12-17 09:32:21 +0000403 if (Type == R_386_TLS_GOTIE || Type == R_386_TLS_IE)
George Rimar2558e122015-12-09 09:55:54 +0000404 return !isTlsOptimized(Type, &S);
405 return Type == R_386_GOT32 || relocNeedsPlt(Type, S);
Rafael Espindola01205f72015-09-22 18:19:46 +0000406}
407
Rafael Espindola3ef3a4c2015-09-29 23:22:16 +0000408bool X86TargetInfo::relocNeedsPlt(uint32_t Type, const SymbolBody &S) const {
George Rimara07ff662015-12-21 10:12:06 +0000409 return isGnuIFunc<ELF32LE>(S) ||
410 (Type == R_386_PLT32 && canBePreempted(&S, true)) ||
George Rimarb72a9c62015-12-10 09:03:39 +0000411 (Type == R_386_PC32 && S.isShared());
Rafael Espindola01205f72015-09-22 18:19:46 +0000412}
413
George Rimarbfb7bf72015-12-21 10:00:12 +0000414bool X86TargetInfo::isGotRelative(uint32_t Type) const {
415 // This relocation does not require got entry,
416 // but it is relative to got and needs it to be created.
417 // Here we request for that.
418 return Type == R_386_GOTOFF;
419}
420
Rui Ueyama96f0e0b2015-10-23 02:40:46 +0000421void X86TargetInfo::relocateOne(uint8_t *Loc, uint8_t *BufEnd, uint32_t Type,
George Rimar48651482015-12-11 08:59:37 +0000422 uint64_t P, uint64_t SA, uint64_t ZA,
Simon Atanasyan09b3e362015-12-01 21:24:45 +0000423 uint8_t *PairedLoc) const {
Rafael Espindolac4010882015-09-22 20:54:08 +0000424 switch (Type) {
Igor Kudrinb4a09272015-12-01 08:41:20 +0000425 case R_386_32:
426 add32le(Loc, SA);
427 break;
Rafael Espindola8acb95c2015-09-29 14:42:37 +0000428 case R_386_GOT32:
George Rimarbfb7bf72015-12-21 10:00:12 +0000429 case R_386_GOTOFF:
Rui Ueyama66072272015-10-15 19:52:27 +0000430 add32le(Loc, SA - Out<ELF32LE>::Got->getVA());
Rafael Espindola8acb95c2015-09-29 14:42:37 +0000431 break;
George Rimar13934772015-11-25 20:20:31 +0000432 case R_386_GOTPC:
433 add32le(Loc, SA + Out<ELF32LE>::Got->getVA() - P);
434 break;
Rafael Espindolac4010882015-09-22 20:54:08 +0000435 case R_386_PC32:
George Rimarb72a9c62015-12-10 09:03:39 +0000436 case R_386_PLT32:
Rui Ueyama96f0e0b2015-10-23 02:40:46 +0000437 add32le(Loc, SA - P);
Rafael Espindolac4010882015-09-22 20:54:08 +0000438 break;
George Rimar9db204a2015-12-02 09:58:20 +0000439 case R_386_TLS_GD:
440 case R_386_TLS_LDM:
441 case R_386_TLS_TPOFF: {
442 uint64_t V = SA - Out<ELF32LE>::Got->getVA() -
443 Out<ELF32LE>::Got->getNumEntries() * 4;
444 checkInt<32>(V, Type);
445 write32le(Loc, V);
446 break;
447 }
George Rimar6f17e092015-12-17 09:32:21 +0000448 case R_386_TLS_IE:
George Rimar9db204a2015-12-02 09:58:20 +0000449 case R_386_TLS_LDO_32:
450 write32le(Loc, SA);
451 break;
George Rimard23970f2015-11-25 20:41:53 +0000452 case R_386_TLS_LE:
453 write32le(Loc, SA - Out<ELF32LE>::TlsPhdr->p_memsz);
454 break;
455 case R_386_TLS_LE_32:
456 write32le(Loc, Out<ELF32LE>::TlsPhdr->p_memsz - SA);
457 break;
Rafael Espindolac4010882015-09-22 20:54:08 +0000458 default:
Rui Ueyama1c42afc2015-10-12 15:49:06 +0000459 error("unrecognized reloc " + Twine(Type));
Rafael Espindolac4010882015-09-22 20:54:08 +0000460 }
461}
462
George Rimar2558e122015-12-09 09:55:54 +0000463bool X86TargetInfo::isTlsOptimized(unsigned Type, const SymbolBody *S) const {
Rui Ueyama62d0e322015-12-17 00:04:18 +0000464 if (Config->Shared || (S && !S->isTls()))
George Rimar2558e122015-12-09 09:55:54 +0000465 return false;
466 return Type == R_386_TLS_LDO_32 || Type == R_386_TLS_LDM ||
467 Type == R_386_TLS_GD ||
George Rimar6f17e092015-12-17 09:32:21 +0000468 (Type == R_386_TLS_IE && !canBePreempted(S, true)) ||
George Rimar2558e122015-12-09 09:55:54 +0000469 (Type == R_386_TLS_GOTIE && !canBePreempted(S, true));
470}
471
George Rimar6f17e092015-12-17 09:32:21 +0000472bool X86TargetInfo::relocNeedsDynRelative(unsigned Type) const {
473 return Config->Shared && Type == R_386_TLS_IE;
474}
475
George Rimar2558e122015-12-09 09:55:54 +0000476unsigned X86TargetInfo::relocateTlsOptimize(uint8_t *Loc, uint8_t *BufEnd,
477 uint32_t Type, uint64_t P,
478 uint64_t SA,
479 const SymbolBody &S) const {
480 switch (Type) {
481 case R_386_TLS_GD:
482 if (canBePreempted(&S, true))
483 relocateTlsGdToIe(Loc, BufEnd, P, SA);
484 else
485 relocateTlsGdToLe(Loc, BufEnd, P, SA);
486 // The next relocation should be against __tls_get_addr, so skip it
487 return 1;
488 case R_386_TLS_GOTIE:
George Rimar6f17e092015-12-17 09:32:21 +0000489 case R_386_TLS_IE:
490 relocateTlsIeToLe(Type, Loc, BufEnd, P, SA);
George Rimar2558e122015-12-09 09:55:54 +0000491 return 0;
492 case R_386_TLS_LDM:
493 relocateTlsLdToLe(Loc, BufEnd, P, SA);
494 // The next relocation should be against __tls_get_addr, so skip it
495 return 1;
496 case R_386_TLS_LDO_32:
497 relocateOne(Loc, BufEnd, R_386_TLS_LE, P, SA);
498 return 0;
499 }
500 llvm_unreachable("Unknown TLS optimization");
501}
502
503// "Ulrich Drepper, ELF Handling For Thread-Local Storage" (5.1
504// IA-32 Linker Optimizations, http://www.akkadia.org/drepper/tls.pdf) shows
505// how GD can be optimized to IE:
506// leal x@tlsgd(, %ebx, 1),
507// call __tls_get_addr@plt
508// Is converted to:
509// movl %gs:0, %eax
510// addl x@gotntpoff(%ebx), %eax
511void X86TargetInfo::relocateTlsGdToIe(uint8_t *Loc, uint8_t *BufEnd, uint64_t P,
512 uint64_t SA) const {
513 const uint8_t Inst[] = {
514 0x65, 0xa1, 0x00, 0x00, 0x00, 0x00, // movl %gs:0, %eax
515 0x03, 0x83, 0x00, 0x00, 0x00, 0x00 // addl 0(%ebx), %eax
516 };
517 memcpy(Loc - 3, Inst, sizeof(Inst));
518 relocateOne(Loc + 5, BufEnd, R_386_32, P,
519 SA - Out<ELF32LE>::Got->getVA() -
520 Out<ELF32LE>::Got->getNumEntries() * 4);
521}
522
523// GD can be optimized to LE:
524// leal x@tlsgd(, %ebx, 1),
525// call __tls_get_addr@plt
526// Can be converted to:
527// movl %gs:0,%eax
528// addl $x@ntpoff,%eax
529// But gold emits subl $foo@tpoff,%eax instead of addl.
530// These instructions are completely equal in behavior.
531// This method generates subl to be consistent with gold.
532void X86TargetInfo::relocateTlsGdToLe(uint8_t *Loc, uint8_t *BufEnd, uint64_t P,
533 uint64_t SA) const {
534 const uint8_t Inst[] = {
535 0x65, 0xa1, 0x00, 0x00, 0x00, 0x00, // movl %gs:0, %eax
536 0x81, 0xe8, 0x00, 0x00, 0x00, 0x00 // subl 0(%ebx), %eax
537 };
538 memcpy(Loc - 3, Inst, sizeof(Inst));
539 relocateOne(Loc + 5, BufEnd, R_386_32, P,
540 Out<ELF32LE>::TlsPhdr->p_memsz - SA);
541}
542
543// LD can be optimized to LE:
544// leal foo(%reg),%eax
545// call ___tls_get_addr
546// Is converted to:
547// movl %gs:0,%eax
548// nop
549// leal 0(%esi,1),%esi
550void X86TargetInfo::relocateTlsLdToLe(uint8_t *Loc, uint8_t *BufEnd, uint64_t P,
551 uint64_t SA) const {
552 const uint8_t Inst[] = {
553 0x65, 0xa1, 0x00, 0x00, 0x00, 0x00, // movl %gs:0,%eax
554 0x90, // nop
555 0x8d, 0x74, 0x26, 0x00 // leal 0(%esi,1),%esi
556 };
557 memcpy(Loc - 2, Inst, sizeof(Inst));
558}
559
George Rimar6f17e092015-12-17 09:32:21 +0000560// In some conditions, relocations can be optimized to avoid using GOT.
561// This function does that for Initial Exec to Local Exec case.
562// Read "ELF Handling For Thread-Local Storage, 5.1
563// IA-32 Linker Optimizations" (http://www.akkadia.org/drepper/tls.pdf)
George Rimar2558e122015-12-09 09:55:54 +0000564// by Ulrich Drepper for details.
George Rimar6f17e092015-12-17 09:32:21 +0000565void X86TargetInfo::relocateTlsIeToLe(unsigned Type, uint8_t *Loc,
566 uint8_t *BufEnd, uint64_t P,
George Rimar2558e122015-12-09 09:55:54 +0000567 uint64_t SA) const {
George Rimar6f17e092015-12-17 09:32:21 +0000568 // Ulrich's document section 6.2 says that @gotntpoff can
569 // be used with MOVL or ADDL instructions.
570 // @indntpoff is similar to @gotntpoff, but for use in
571 // position dependent code.
George Rimar2558e122015-12-09 09:55:54 +0000572 uint8_t *Inst = Loc - 2;
George Rimar6f17e092015-12-17 09:32:21 +0000573 uint8_t *Op = Loc - 1;
George Rimar2558e122015-12-09 09:55:54 +0000574 uint8_t Reg = (Loc[-1] >> 3) & 7;
575 bool IsMov = *Inst == 0x8b;
George Rimar6f17e092015-12-17 09:32:21 +0000576 if (Type == R_386_TLS_IE) {
577 // For R_386_TLS_IE relocation we perform the next transformations:
578 // MOVL foo@INDNTPOFF,%EAX is transformed to MOVL $foo,%EAX
579 // MOVL foo@INDNTPOFF,%REG is transformed to MOVL $foo,%REG
580 // ADDL foo@INDNTPOFF,%REG is transformed to ADDL $foo,%REG
581 // First one is special because when EAX is used the sequence is 5 bytes
582 // long, otherwise it is 6 bytes.
583 if (*Op == 0xa1) {
584 *Op = 0xb8;
585 } else {
586 *Inst = IsMov ? 0xc7 : 0x81;
587 *Op = 0xc0 | ((*Op >> 3) & 7);
588 }
589 } else {
590 // R_386_TLS_GOTIE relocation can be optimized to
591 // R_386_TLS_LE so that it does not use GOT.
592 // "MOVL foo@GOTTPOFF(%RIP), %REG" is transformed to "MOVL $foo, %REG".
593 // "ADDL foo@GOTNTPOFF(%RIP), %REG" is transformed to "LEAL foo(%REG), %REG"
594 // Note: gold converts to ADDL instead of LEAL.
595 *Inst = IsMov ? 0xc7 : 0x8d;
596 if (IsMov)
597 *Op = 0xc0 | ((*Op >> 3) & 7);
598 else
599 *Op = 0x80 | Reg | (Reg << 3);
600 }
George Rimar2558e122015-12-09 09:55:54 +0000601 relocateOne(Loc, BufEnd, R_386_TLS_LE, P, SA);
602}
603
Rafael Espindola7f074422015-09-22 21:35:51 +0000604X86_64TargetInfo::X86_64TargetInfo() {
George Rimarbc590fe2015-10-28 16:48:58 +0000605 CopyReloc = R_X86_64_COPY;
Rafael Espindola7f074422015-09-22 21:35:51 +0000606 PCRelReloc = R_X86_64_PC32;
607 GotReloc = R_X86_64_GLOB_DAT;
George Rimar648a2c32015-10-20 08:54:27 +0000608 PltReloc = R_X86_64_JUMP_SLOT;
Rafael Espindolaae244002015-10-05 19:30:12 +0000609 RelativeReloc = R_X86_64_RELATIVE;
George Rimara07ff662015-12-21 10:12:06 +0000610 IRelativeReloc = R_X86_64_IRELATIVE;
George Rimar687138c2015-11-13 16:28:53 +0000611 TlsGotReloc = R_X86_64_TPOFF64;
Michael J. Spencer1e225612015-11-11 01:00:24 +0000612 TlsLocalDynamicReloc = R_X86_64_TLSLD;
Michael J. Spencer627ae702015-11-13 00:28:34 +0000613 TlsGlobalDynamicReloc = R_X86_64_TLSGD;
Michael J. Spencer1e225612015-11-11 01:00:24 +0000614 TlsModuleIndexReloc = R_X86_64_DTPMOD64;
Michael J. Spencer627ae702015-11-13 00:28:34 +0000615 TlsOffsetReloc = R_X86_64_DTPOFF64;
George Rimar648a2c32015-10-20 08:54:27 +0000616 LazyRelocations = true;
617 PltEntrySize = 16;
618 PltZeroEntrySize = 16;
619}
620
Igor Kudrin351b41d2015-11-16 17:44:08 +0000621void X86_64TargetInfo::writeGotPltHeaderEntries(uint8_t *Buf) const {
622 write64le(Buf, Out<ELF64LE>::Dynamic->getVA());
623}
624
George Rimar648a2c32015-10-20 08:54:27 +0000625void X86_64TargetInfo::writeGotPltEntry(uint8_t *Buf, uint64_t Plt) const {
626 // Skip 6 bytes of "jmpq *got(%rip)"
627 write32le(Buf, Plt + 6);
628}
629
630void X86_64TargetInfo::writePltZeroEntry(uint8_t *Buf, uint64_t GotEntryAddr,
631 uint64_t PltEntryAddr) const {
632 const uint8_t PltData[] = {
633 0xff, 0x35, 0x00, 0x00, 0x00, 0x00, // pushq GOT+8(%rip)
634 0xff, 0x25, 0x00, 0x00, 0x00, 0x00, // jmp *GOT+16(%rip)
635 0x0f, 0x1f, 0x40, 0x00 // nopl 0x0(rax)
636 };
637 memcpy(Buf, PltData, sizeof(PltData));
638 write32le(Buf + 2, GotEntryAddr - PltEntryAddr + 2); // GOT+8
639 write32le(Buf + 8, GotEntryAddr - PltEntryAddr + 4); // GOT+16
Rafael Espindola7f074422015-09-22 21:35:51 +0000640}
Rafael Espindola01205f72015-09-22 18:19:46 +0000641
George Rimar77b77792015-11-25 22:15:01 +0000642void X86_64TargetInfo::writePltEntry(uint8_t *Buf, uint64_t GotAddr,
643 uint64_t GotEntryAddr,
644 uint64_t PltEntryAddr, int32_t Index,
645 unsigned RelOff) const {
George Rimar648a2c32015-10-20 08:54:27 +0000646 const uint8_t Inst[] = {
647 0xff, 0x25, 0x00, 0x00, 0x00, 0x00, // jmpq *got(%rip)
648 0x68, 0x00, 0x00, 0x00, 0x00, // pushq <relocation index>
649 0xe9, 0x00, 0x00, 0x00, 0x00 // jmpq plt[0]
650 };
Rui Ueyama1500a902015-09-29 23:00:47 +0000651 memcpy(Buf, Inst, sizeof(Inst));
Rafael Espindola01205f72015-09-22 18:19:46 +0000652
George Rimar648a2c32015-10-20 08:54:27 +0000653 write32le(Buf + 2, GotEntryAddr - PltEntryAddr - 6);
654 write32le(Buf + 7, Index);
655 write32le(Buf + 12, -Index * PltEntrySize - PltZeroEntrySize - 16);
Rafael Espindola01205f72015-09-22 18:19:46 +0000656}
657
Rui Ueyama02dfd492015-12-17 01:18:40 +0000658bool X86_64TargetInfo::needsCopyRel(uint32_t Type, const SymbolBody &S) const {
George Rimarbc590fe2015-10-28 16:48:58 +0000659 if (Type == R_X86_64_32S || Type == R_X86_64_32 || Type == R_X86_64_PC32 ||
660 Type == R_X86_64_64)
661 if (auto *SS = dyn_cast<SharedSymbol<ELF64LE>>(&S))
662 return SS->Sym.getType() == STT_OBJECT;
663 return false;
664}
665
Rafael Espindola3ef3a4c2015-09-29 23:22:16 +0000666bool X86_64TargetInfo::relocNeedsGot(uint32_t Type, const SymbolBody &S) const {
George Rimar25411f252015-12-04 11:20:13 +0000667 if (Type == R_X86_64_TLSGD)
668 return Target->isTlsOptimized(Type, &S) && canBePreempted(&S, true);
George Rimar77d1cb12015-11-24 09:00:06 +0000669 if (Type == R_X86_64_GOTTPOFF)
George Rimar6713cf82015-11-25 21:46:05 +0000670 return !isTlsOptimized(Type, &S);
George Rimar25411f252015-12-04 11:20:13 +0000671 return Type == R_X86_64_GOTPCREL || relocNeedsPlt(Type, S);
Rafael Espindola01205f72015-09-22 18:19:46 +0000672}
673
George Rimar6f17e092015-12-17 09:32:21 +0000674bool X86_64TargetInfo::isTlsDynReloc(unsigned Type, const SymbolBody &S) const {
George Rimar25411f252015-12-04 11:20:13 +0000675 return Type == R_X86_64_GOTTPOFF || Type == R_X86_64_TLSGD;
George Rimard23970f2015-11-25 20:41:53 +0000676}
677
Rafael Espindola3ef3a4c2015-09-29 23:22:16 +0000678bool X86_64TargetInfo::relocNeedsPlt(uint32_t Type, const SymbolBody &S) const {
Rui Ueyama02dfd492015-12-17 01:18:40 +0000679 if (needsCopyRel(Type, S))
George Rimarbc590fe2015-10-28 16:48:58 +0000680 return false;
George Rimara07ff662015-12-21 10:12:06 +0000681 if (isGnuIFunc<ELF64LE>(S))
682 return true;
George Rimarbc590fe2015-10-28 16:48:58 +0000683
Rafael Espindola01205f72015-09-22 18:19:46 +0000684 switch (Type) {
685 default:
686 return false;
Rafael Espindola227556e2015-10-14 16:15:46 +0000687 case R_X86_64_32:
George Rimar52687212015-10-28 18:33:08 +0000688 case R_X86_64_64:
Rafael Espindola3ef3a4c2015-09-29 23:22:16 +0000689 case R_X86_64_PC32:
690 // This relocation is defined to have a value of (S + A - P).
Rafael Espindola3c412e12015-09-30 12:30:58 +0000691 // The problems start when a non PIC program calls a function in a shared
Rafael Espindola3ef3a4c2015-09-29 23:22:16 +0000692 // library.
Rafael Espindola9a0db7c2015-09-29 23:23:53 +0000693 // In an ideal world, we could just report an error saying the relocation
Rafael Espindola3ef3a4c2015-09-29 23:22:16 +0000694 // can overflow at runtime.
Rafael Espindola3c412e12015-09-30 12:30:58 +0000695 // In the real world with glibc, crt1.o has a R_X86_64_PC32 pointing to
696 // libc.so.
697 //
698 // The general idea on how to handle such cases is to create a PLT entry
699 // and use that as the function value.
700 //
701 // For the static linking part, we just return true and everything else
702 // will use the the PLT entry as the address.
703 //
Rafael Espindola3ef3a4c2015-09-29 23:22:16 +0000704 // The remaining (unimplemented) problem is making sure pointer equality
Rafael Espindola3c412e12015-09-30 12:30:58 +0000705 // still works. We need the help of the dynamic linker for that. We
706 // let it know that we have a direct reference to a so symbol by creating
707 // an undefined symbol with a non zero st_value. Seeing that, the
Rafael Espindola3ef3a4c2015-09-29 23:22:16 +0000708 // dynamic linker resolves the symbol to the value of the symbol we created.
709 // This is true even for got entries, so pointer equality is maintained.
710 // To avoid an infinite loop, the only entry that points to the
Rafael Espindola3c412e12015-09-30 12:30:58 +0000711 // real function is a dedicated got entry used by the plt. That is
712 // identified by special relocation types (R_X86_64_JUMP_SLOT,
713 // R_386_JMP_SLOT, etc).
Rafael Espindola3ef3a4c2015-09-29 23:22:16 +0000714 return S.isShared();
Rafael Espindola01205f72015-09-22 18:19:46 +0000715 case R_X86_64_PLT32:
George Rimar8911d852015-10-16 23:52:24 +0000716 return canBePreempted(&S, true);
Rafael Espindola01205f72015-09-22 18:19:46 +0000717 }
718}
Rafael Espindolac4010882015-09-22 20:54:08 +0000719
Rafael Espindolaae244002015-10-05 19:30:12 +0000720bool X86_64TargetInfo::isRelRelative(uint32_t Type) const {
721 switch (Type) {
722 default:
723 return false;
Michael J. Spencera5d9d1f2015-11-11 01:27:58 +0000724 case R_X86_64_DTPOFF32:
Michael J. Spencerac2307b2015-11-11 01:28:11 +0000725 case R_X86_64_DTPOFF64:
Igor Kudrinb4a09272015-12-01 08:41:20 +0000726 case R_X86_64_PC8:
727 case R_X86_64_PC16:
728 case R_X86_64_PC32:
729 case R_X86_64_PC64:
730 case R_X86_64_PLT32:
Rafael Espindolaae244002015-10-05 19:30:12 +0000731 return true;
732 }
733}
734
Rui Ueyama3a7c2f62016-01-08 00:13:23 +0000735bool X86_64TargetInfo::isSizeReloc(uint32_t Type) const {
736 return Type == R_X86_64_SIZE32 || Type == R_X86_64_SIZE64;
George Rimar48651482015-12-11 08:59:37 +0000737}
738
George Rimar77d1cb12015-11-24 09:00:06 +0000739bool X86_64TargetInfo::isTlsOptimized(unsigned Type,
George Rimar6713cf82015-11-25 21:46:05 +0000740 const SymbolBody *S) const {
Rui Ueyama62d0e322015-12-17 00:04:18 +0000741 if (Config->Shared || (S && !S->isTls()))
George Rimar77d1cb12015-11-24 09:00:06 +0000742 return false;
George Rimar25411f252015-12-04 11:20:13 +0000743 return Type == R_X86_64_TLSGD || Type == R_X86_64_TLSLD ||
744 Type == R_X86_64_DTPOFF32 ||
George Rimar6713cf82015-11-25 21:46:05 +0000745 (Type == R_X86_64_GOTTPOFF && !canBePreempted(S, true));
746}
747
748// "Ulrich Drepper, ELF Handling For Thread-Local Storage" (5.5
749// x86-x64 linker optimizations, http://www.akkadia.org/drepper/tls.pdf) shows
750// how LD can be optimized to LE:
751// leaq bar@tlsld(%rip), %rdi
752// callq __tls_get_addr@PLT
753// leaq bar@dtpoff(%rax), %rcx
754// Is converted to:
755// .word 0x6666
756// .byte 0x66
757// mov %fs:0,%rax
758// leaq bar@tpoff(%rax), %rcx
759void X86_64TargetInfo::relocateTlsLdToLe(uint8_t *Loc, uint8_t *BufEnd,
760 uint64_t P, uint64_t SA) const {
761 const uint8_t Inst[] = {
762 0x66, 0x66, //.word 0x6666
763 0x66, //.byte 0x66
764 0x64, 0x48, 0x8b, 0x04, 0x25, 0x00, 0x00, 0x00, 0x00 // mov %fs:0,%rax
765 };
766 memcpy(Loc - 3, Inst, sizeof(Inst));
767}
768
769// "Ulrich Drepper, ELF Handling For Thread-Local Storage" (5.5
770// x86-x64 linker optimizations, http://www.akkadia.org/drepper/tls.pdf) shows
771// how GD can be optimized to LE:
772// .byte 0x66
773// leaq x@tlsgd(%rip), %rdi
774// .word 0x6666
775// rex64
776// call __tls_get_addr@plt
777// Is converted to:
778// mov %fs:0x0,%rax
779// lea x@tpoff,%rax
780void X86_64TargetInfo::relocateTlsGdToLe(uint8_t *Loc, uint8_t *BufEnd,
781 uint64_t P, uint64_t SA) const {
782 const uint8_t Inst[] = {
783 0x64, 0x48, 0x8b, 0x04, 0x25, 0x00, 0x00, 0x00, 0x00, // mov %fs:0x0,%rax
784 0x48, 0x8d, 0x80, 0x00, 0x00, 0x00, 0x00 // lea x@tpoff,%rax
785 };
786 memcpy(Loc - 4, Inst, sizeof(Inst));
787 relocateOne(Loc + 8, BufEnd, R_X86_64_TPOFF32, P, SA);
George Rimar77d1cb12015-11-24 09:00:06 +0000788}
789
George Rimar25411f252015-12-04 11:20:13 +0000790// "Ulrich Drepper, ELF Handling For Thread-Local Storage" (5.5
791// x86-x64 linker optimizations, http://www.akkadia.org/drepper/tls.pdf) shows
792// how GD can be optimized to IE:
793// .byte 0x66
794// leaq x@tlsgd(%rip), %rdi
795// .word 0x6666
796// rex64
797// call __tls_get_addr@plt
798// Is converted to:
799// mov %fs:0x0,%rax
800// addq x@tpoff,%rax
801void X86_64TargetInfo::relocateTlsGdToIe(uint8_t *Loc, uint8_t *BufEnd,
802 uint64_t P, uint64_t SA) const {
803 const uint8_t Inst[] = {
804 0x64, 0x48, 0x8b, 0x04, 0x25, 0x00, 0x00, 0x00, 0x00, // mov %fs:0x0,%rax
805 0x48, 0x03, 0x05, 0x00, 0x00, 0x00, 0x00 // addq x@tpoff,%rax
806 };
807 memcpy(Loc - 4, Inst, sizeof(Inst));
808 relocateOne(Loc + 8, BufEnd, R_X86_64_TPOFF64, P + 12, SA);
809}
810
George Rimar77d1cb12015-11-24 09:00:06 +0000811// In some conditions, R_X86_64_GOTTPOFF relocation can be optimized to
George Rimarc55b4e22015-12-07 16:54:56 +0000812// R_X86_64_TPOFF32 so that it does not use GOT.
George Rimar77d1cb12015-11-24 09:00:06 +0000813// This function does that. Read "ELF Handling For Thread-Local Storage,
814// 5.5 x86-x64 linker optimizations" (http://www.akkadia.org/drepper/tls.pdf)
815// by Ulrich Drepper for details.
George Rimar6713cf82015-11-25 21:46:05 +0000816void X86_64TargetInfo::relocateTlsIeToLe(uint8_t *Loc, uint8_t *BufEnd,
817 uint64_t P, uint64_t SA) const {
George Rimar77d1cb12015-11-24 09:00:06 +0000818 // Ulrich's document section 6.5 says that @gottpoff(%rip) must be
819 // used in MOVQ or ADDQ instructions only.
820 // "MOVQ foo@GOTTPOFF(%RIP), %REG" is transformed to "MOVQ $foo, %REG".
821 // "ADDQ foo@GOTTPOFF(%RIP), %REG" is transformed to "LEAQ foo(%REG), %REG"
822 // (if the register is not RSP/R12) or "ADDQ $foo, %RSP".
823 // Opcodes info can be found at http://ref.x86asm.net/coder64.html#x48.
824 uint8_t *Prefix = Loc - 3;
825 uint8_t *Inst = Loc - 2;
826 uint8_t *RegSlot = Loc - 1;
827 uint8_t Reg = Loc[-1] >> 3;
828 bool IsMov = *Inst == 0x8b;
829 bool RspAdd = !IsMov && Reg == 4;
830 // r12 and rsp registers requires special handling.
831 // Problem is that for other registers, for example leaq 0xXXXXXXXX(%r11),%r11
832 // result out is 7 bytes: 4d 8d 9b XX XX XX XX,
833 // but leaq 0xXXXXXXXX(%r12),%r12 is 8 bytes: 4d 8d a4 24 XX XX XX XX.
834 // The same true for rsp. So we convert to addq for them, saving 1 byte that
835 // we dont have.
836 if (RspAdd)
837 *Inst = 0x81;
838 else
839 *Inst = IsMov ? 0xc7 : 0x8d;
840 if (*Prefix == 0x4c)
841 *Prefix = (IsMov || RspAdd) ? 0x49 : 0x4d;
842 *RegSlot = (IsMov || RspAdd) ? (0xc0 | Reg) : (0x80 | Reg | (Reg << 3));
843 relocateOne(Loc, BufEnd, R_X86_64_TPOFF32, P, SA);
844}
845
George Rimar6713cf82015-11-25 21:46:05 +0000846// This function applies a TLS relocation with an optimization as described
847// in the Ulrich's document. As a result of rewriting instructions at the
848// relocation target, relocations immediately follow the TLS relocation (which
849// would be applied to rewritten instructions) may have to be skipped.
850// This function returns a number of relocations that need to be skipped.
851unsigned X86_64TargetInfo::relocateTlsOptimize(uint8_t *Loc, uint8_t *BufEnd,
852 uint32_t Type, uint64_t P,
George Rimar25411f252015-12-04 11:20:13 +0000853 uint64_t SA,
854 const SymbolBody &S) const {
George Rimar6713cf82015-11-25 21:46:05 +0000855 switch (Type) {
Igor Kudrinb4a09272015-12-01 08:41:20 +0000856 case R_X86_64_DTPOFF32:
857 relocateOne(Loc, BufEnd, R_X86_64_TPOFF32, P, SA);
858 return 0;
George Rimar6713cf82015-11-25 21:46:05 +0000859 case R_X86_64_GOTTPOFF:
860 relocateTlsIeToLe(Loc, BufEnd, P, SA);
861 return 0;
George Rimar25411f252015-12-04 11:20:13 +0000862 case R_X86_64_TLSGD: {
863 if (canBePreempted(&S, true))
864 relocateTlsGdToIe(Loc, BufEnd, P, SA);
865 else
866 relocateTlsGdToLe(Loc, BufEnd, P, SA);
George Rimar6713cf82015-11-25 21:46:05 +0000867 // The next relocation should be against __tls_get_addr, so skip it
868 return 1;
George Rimar25411f252015-12-04 11:20:13 +0000869 }
Igor Kudrinb4a09272015-12-01 08:41:20 +0000870 case R_X86_64_TLSLD:
871 relocateTlsLdToLe(Loc, BufEnd, P, SA);
872 // The next relocation should be against __tls_get_addr, so skip it
873 return 1;
George Rimar6713cf82015-11-25 21:46:05 +0000874 }
875 llvm_unreachable("Unknown TLS optimization");
876}
877
Rui Ueyama96f0e0b2015-10-23 02:40:46 +0000878void X86_64TargetInfo::relocateOne(uint8_t *Loc, uint8_t *BufEnd, uint32_t Type,
George Rimar48651482015-12-11 08:59:37 +0000879 uint64_t P, uint64_t SA, uint64_t ZA,
Simon Atanasyan09b3e362015-12-01 21:24:45 +0000880 uint8_t *PairedLoc) const {
Rafael Espindolac4010882015-09-22 20:54:08 +0000881 switch (Type) {
Rui Ueyama3835b492015-10-23 16:13:27 +0000882 case R_X86_64_32:
Igor Kudrin9b7e7db2015-11-26 09:49:44 +0000883 checkUInt<32>(SA, Type);
884 write32le(Loc, SA);
885 break;
Rafael Espindolac4010882015-09-22 20:54:08 +0000886 case R_X86_64_32S:
Igor Kudrin9b7e7db2015-11-26 09:49:44 +0000887 checkInt<32>(SA, Type);
Rui Ueyama66072272015-10-15 19:52:27 +0000888 write32le(Loc, SA);
Rafael Espindolac4010882015-09-22 20:54:08 +0000889 break;
Igor Kudrinb4a09272015-12-01 08:41:20 +0000890 case R_X86_64_64:
891 write64le(Loc, SA);
892 break;
Michael J. Spencera5d9d1f2015-11-11 01:27:58 +0000893 case R_X86_64_DTPOFF32:
894 write32le(Loc, SA);
895 break;
Igor Kudrinb4a09272015-12-01 08:41:20 +0000896 case R_X86_64_DTPOFF64:
897 write64le(Loc, SA);
898 break;
899 case R_X86_64_GOTPCREL:
900 case R_X86_64_PC32:
901 case R_X86_64_PLT32:
902 case R_X86_64_TLSGD:
903 case R_X86_64_TLSLD:
904 write32le(Loc, SA - P);
905 break;
George Rimar48651482015-12-11 08:59:37 +0000906 case R_X86_64_SIZE32:
907 write32le(Loc, ZA);
908 break;
909 case R_X86_64_SIZE64:
910 write64le(Loc, ZA);
911 break;
Rafael Espindolaac1c0f82015-11-05 15:22:26 +0000912 case R_X86_64_TPOFF32: {
Rafael Espindolaea7a1e902015-11-06 22:14:44 +0000913 uint64_t Val = SA - Out<ELF64LE>::TlsPhdr->p_memsz;
Igor Kudrin9b7e7db2015-11-26 09:49:44 +0000914 checkInt<32>(Val, Type);
Rafael Espindolaac1c0f82015-11-05 15:22:26 +0000915 write32le(Loc, Val);
Michael J. Spencerd77f0d22015-11-03 22:39:09 +0000916 break;
Rafael Espindolaac1c0f82015-11-05 15:22:26 +0000917 }
Igor Kudrinb4a09272015-12-01 08:41:20 +0000918 case R_X86_64_TPOFF64:
919 write32le(Loc, SA - P);
920 break;
Rafael Espindolac4010882015-09-22 20:54:08 +0000921 default:
Rui Ueyama1c42afc2015-10-12 15:49:06 +0000922 error("unrecognized reloc " + Twine(Type));
Rafael Espindolac4010882015-09-22 20:54:08 +0000923 }
924}
925
Hal Finkel3c8cc672015-10-12 20:56:18 +0000926// Relocation masks following the #lo(value), #hi(value), #ha(value),
927// #higher(value), #highera(value), #highest(value), and #highesta(value)
928// macros defined in section 4.5.1. Relocation Types of the PPC-elf64abi
929// document.
Rui Ueyamac44e5a12015-10-23 16:54:58 +0000930static uint16_t applyPPCLo(uint64_t V) { return V; }
931static uint16_t applyPPCHi(uint64_t V) { return V >> 16; }
932static uint16_t applyPPCHa(uint64_t V) { return (V + 0x8000) >> 16; }
933static uint16_t applyPPCHigher(uint64_t V) { return V >> 32; }
934static uint16_t applyPPCHighera(uint64_t V) { return (V + 0x8000) >> 32; }
Hal Finkel3c8cc672015-10-12 20:56:18 +0000935static uint16_t applyPPCHighest(uint64_t V) { return V >> 48; }
Hal Finkel3c8cc672015-10-12 20:56:18 +0000936static uint16_t applyPPCHighesta(uint64_t V) { return (V + 0x8000) >> 48; }
937
Davide Italiano8c3444362016-01-11 19:45:33 +0000938PPCTargetInfo::PPCTargetInfo() {}
939void PPCTargetInfo::writeGotPltEntry(uint8_t *Buf, uint64_t Plt) const {}
940void PPCTargetInfo::writePltZeroEntry(uint8_t *Buf, uint64_t GotEntryAddr,
941 uint64_t PltEntryAddr) const {}
942void PPCTargetInfo::writePltEntry(uint8_t *Buf, uint64_t GotAddr,
943 uint64_t GotEntryAddr,
944 uint64_t PltEntryAddr, int32_t Index,
945 unsigned RelOff) const {}
946bool PPCTargetInfo::relocNeedsGot(uint32_t Type, const SymbolBody &S) const {
947 return false;
948}
949bool PPCTargetInfo::relocNeedsPlt(uint32_t Type, const SymbolBody &S) const {
950 return false;
951}
952bool PPCTargetInfo::isRelRelative(uint32_t Type) const { return false; }
953
954void PPCTargetInfo::relocateOne(uint8_t *Loc, uint8_t *BufEnd, uint32_t Type,
955 uint64_t P, uint64_t SA, uint64_t ZA,
956 uint8_t *PairedLoc) const {
957 switch (Type) {
958 case R_PPC_ADDR16_HA:
959 write16be(Loc, applyPPCHa(SA));
960 break;
961 case R_PPC_ADDR16_LO:
962 write16be(Loc, applyPPCLo(SA));
963 break;
964 default:
965 error("unrecognized reloc " + Twine(Type));
966 }
967}
968
Rafael Espindolac4010882015-09-22 20:54:08 +0000969PPC64TargetInfo::PPC64TargetInfo() {
Hal Finkel3c8cc672015-10-12 20:56:18 +0000970 PCRelReloc = R_PPC64_REL24;
971 GotReloc = R_PPC64_GLOB_DAT;
Hal Finkelbe0823d2015-10-12 20:58:52 +0000972 RelativeReloc = R_PPC64_RELATIVE;
Hal Finkel6c2a3b82015-10-08 21:51:31 +0000973 PltEntrySize = 32;
Hal Finkelc848b322015-10-12 19:34:29 +0000974
975 // We need 64K pages (at least under glibc/Linux, the loader won't
976 // set different permissions on a finer granularity than that).
Hal Finkele3c26262015-10-08 22:23:54 +0000977 PageSize = 65536;
Hal Finkel736c7412015-10-15 07:49:07 +0000978
979 // The PPC64 ELF ABI v1 spec, says:
980 //
981 // It is normally desirable to put segments with different characteristics
982 // in separate 256 Mbyte portions of the address space, to give the
983 // operating system full paging flexibility in the 64-bit address space.
984 //
985 // And because the lowest non-zero 256M boundary is 0x10000000, PPC64 linkers
986 // use 0x10000000 as the starting address.
987 VAStart = 0x10000000;
Rafael Espindolac4010882015-09-22 20:54:08 +0000988}
Hal Finkel3c8cc672015-10-12 20:56:18 +0000989
Hal Finkel6f97c2b2015-10-16 21:55:40 +0000990uint64_t getPPC64TocBase() {
Hal Finkel3c8cc672015-10-12 20:56:18 +0000991 // The TOC consists of sections .got, .toc, .tocbss, .plt in that
992 // order. The TOC starts where the first of these sections starts.
993
994 // FIXME: This obviously does not do the right thing when there is no .got
995 // section, but there is a .toc or .tocbss section.
996 uint64_t TocVA = Out<ELF64BE>::Got->getVA();
997 if (!TocVA)
998 TocVA = Out<ELF64BE>::Plt->getVA();
999
1000 // Per the ppc64-elf-linux ABI, The TOC base is TOC value plus 0x8000
1001 // thus permitting a full 64 Kbytes segment. Note that the glibc startup
1002 // code (crt1.o) assumes that you can get from the TOC base to the
1003 // start of the .toc section with only a single (signed) 16-bit relocation.
1004 return TocVA + 0x8000;
1005}
1006
George Rimar648a2c32015-10-20 08:54:27 +00001007void PPC64TargetInfo::writeGotPltEntry(uint8_t *Buf, uint64_t Plt) const {}
1008void PPC64TargetInfo::writePltZeroEntry(uint8_t *Buf, uint64_t GotEntryAddr,
1009 uint64_t PltEntryAddr) const {}
George Rimar77b77792015-11-25 22:15:01 +00001010void PPC64TargetInfo::writePltEntry(uint8_t *Buf, uint64_t GotAddr,
1011 uint64_t GotEntryAddr,
1012 uint64_t PltEntryAddr, int32_t Index,
1013 unsigned RelOff) const {
Hal Finkel3c8cc672015-10-12 20:56:18 +00001014 uint64_t Off = GotEntryAddr - getPPC64TocBase();
1015
1016 // FIXME: What we should do, in theory, is get the offset of the function
1017 // descriptor in the .opd section, and use that as the offset from %r2 (the
1018 // TOC-base pointer). Instead, we have the GOT-entry offset, and that will
1019 // be a pointer to the function descriptor in the .opd section. Using
1020 // this scheme is simpler, but requires an extra indirection per PLT dispatch.
1021
Hal Finkelfa92f682015-10-13 21:47:34 +00001022 write32be(Buf, 0xf8410028); // std %r2, 40(%r1)
Hal Finkel3c8cc672015-10-12 20:56:18 +00001023 write32be(Buf + 4, 0x3d620000 | applyPPCHa(Off)); // addis %r11, %r2, X@ha
1024 write32be(Buf + 8, 0xe98b0000 | applyPPCLo(Off)); // ld %r12, X@l(%r11)
1025 write32be(Buf + 12, 0xe96c0000); // ld %r11,0(%r12)
1026 write32be(Buf + 16, 0x7d6903a6); // mtctr %r11
1027 write32be(Buf + 20, 0xe84c0008); // ld %r2,8(%r12)
1028 write32be(Buf + 24, 0xe96c0010); // ld %r11,16(%r12)
1029 write32be(Buf + 28, 0x4e800420); // bctr
1030}
1031
Rafael Espindola3ef3a4c2015-09-29 23:22:16 +00001032bool PPC64TargetInfo::relocNeedsGot(uint32_t Type, const SymbolBody &S) const {
Hal Finkel3c8cc672015-10-12 20:56:18 +00001033 if (relocNeedsPlt(Type, S))
1034 return true;
1035
1036 switch (Type) {
1037 default: return false;
1038 case R_PPC64_GOT16:
Hal Finkel3c8cc672015-10-12 20:56:18 +00001039 case R_PPC64_GOT16_DS:
Igor Kudrinb4a09272015-12-01 08:41:20 +00001040 case R_PPC64_GOT16_HA:
1041 case R_PPC64_GOT16_HI:
1042 case R_PPC64_GOT16_LO:
Hal Finkel3c8cc672015-10-12 20:56:18 +00001043 case R_PPC64_GOT16_LO_DS:
1044 return true;
1045 }
Rafael Espindola3ef3a4c2015-09-29 23:22:16 +00001046}
Hal Finkel3c8cc672015-10-12 20:56:18 +00001047
Rafael Espindola3ef3a4c2015-09-29 23:22:16 +00001048bool PPC64TargetInfo::relocNeedsPlt(uint32_t Type, const SymbolBody &S) const {
Hal Finkel3c8cc672015-10-12 20:56:18 +00001049 // These are function calls that need to be redirected through a PLT stub.
Hal Finkel82281982015-10-17 00:48:20 +00001050 return Type == R_PPC64_REL24 && canBePreempted(&S, false);
Rafael Espindola3ef3a4c2015-09-29 23:22:16 +00001051}
Hal Finkel3c8cc672015-10-12 20:56:18 +00001052
Hal Finkelbe0823d2015-10-12 20:58:52 +00001053bool PPC64TargetInfo::isRelRelative(uint32_t Type) const {
1054 switch (Type) {
1055 default:
Hal Finkelbe0823d2015-10-12 20:58:52 +00001056 return true;
Hal Finkel00918622015-10-16 19:01:50 +00001057 case R_PPC64_ADDR64:
Igor Kudrinb4a09272015-12-01 08:41:20 +00001058 case R_PPC64_TOC:
Hal Finkel00918622015-10-16 19:01:50 +00001059 return false;
Hal Finkelbe0823d2015-10-12 20:58:52 +00001060 }
1061}
1062
Rui Ueyama96f0e0b2015-10-23 02:40:46 +00001063void PPC64TargetInfo::relocateOne(uint8_t *Loc, uint8_t *BufEnd, uint32_t Type,
George Rimar48651482015-12-11 08:59:37 +00001064 uint64_t P, uint64_t SA, uint64_t ZA,
Simon Atanasyan09b3e362015-12-01 21:24:45 +00001065 uint8_t *PairedLoc) const {
Hal Finkel3c8cc672015-10-12 20:56:18 +00001066 uint64_t TB = getPPC64TocBase();
1067
Hal Finkel3c8cc672015-10-12 20:56:18 +00001068 // For a TOC-relative relocation, adjust the addend and proceed in terms of
1069 // the corresponding ADDR16 relocation type.
Rafael Espindola3efa4e92015-09-22 21:12:55 +00001070 switch (Type) {
Rafael Espindola826941a2015-10-15 18:19:39 +00001071 case R_PPC64_TOC16: Type = R_PPC64_ADDR16; SA -= TB; break;
1072 case R_PPC64_TOC16_DS: Type = R_PPC64_ADDR16_DS; SA -= TB; break;
Igor Kudrinb4a09272015-12-01 08:41:20 +00001073 case R_PPC64_TOC16_HA: Type = R_PPC64_ADDR16_HA; SA -= TB; break;
1074 case R_PPC64_TOC16_HI: Type = R_PPC64_ADDR16_HI; SA -= TB; break;
Rafael Espindola826941a2015-10-15 18:19:39 +00001075 case R_PPC64_TOC16_LO: Type = R_PPC64_ADDR16_LO; SA -= TB; break;
1076 case R_PPC64_TOC16_LO_DS: Type = R_PPC64_ADDR16_LO_DS; SA -= TB; break;
Hal Finkel3c8cc672015-10-12 20:56:18 +00001077 default: break;
1078 }
1079
Hal Finkel3c8cc672015-10-12 20:56:18 +00001080 switch (Type) {
Igor Kudrinb4a09272015-12-01 08:41:20 +00001081 case R_PPC64_ADDR14: {
1082 checkAlignment<4>(SA, Type);
1083 // Preserve the AA/LK bits in the branch instruction
1084 uint8_t AALK = Loc[3];
1085 write16be(Loc + 2, (AALK & 3) | (SA & 0xfffc));
1086 break;
1087 }
Hal Finkel3c8cc672015-10-12 20:56:18 +00001088 case R_PPC64_ADDR16:
Igor Kudrin9b7e7db2015-11-26 09:49:44 +00001089 checkInt<16>(SA, Type);
Rui Ueyama96f0e0b2015-10-23 02:40:46 +00001090 write16be(Loc, SA);
Rafael Espindola3efa4e92015-09-22 21:12:55 +00001091 break;
Hal Finkel3c8cc672015-10-12 20:56:18 +00001092 case R_PPC64_ADDR16_DS:
Igor Kudrin9b7e7db2015-11-26 09:49:44 +00001093 checkInt<16>(SA, Type);
Rui Ueyama96f0e0b2015-10-23 02:40:46 +00001094 write16be(Loc, (read16be(Loc) & 3) | (SA & ~3));
Hal Finkel3c8cc672015-10-12 20:56:18 +00001095 break;
Igor Kudrinb4a09272015-12-01 08:41:20 +00001096 case R_PPC64_ADDR16_HA:
1097 write16be(Loc, applyPPCHa(SA));
Hal Finkel3c8cc672015-10-12 20:56:18 +00001098 break;
1099 case R_PPC64_ADDR16_HI:
Rui Ueyama96f0e0b2015-10-23 02:40:46 +00001100 write16be(Loc, applyPPCHi(SA));
Hal Finkel3c8cc672015-10-12 20:56:18 +00001101 break;
Hal Finkel3c8cc672015-10-12 20:56:18 +00001102 case R_PPC64_ADDR16_HIGHER:
Rui Ueyama96f0e0b2015-10-23 02:40:46 +00001103 write16be(Loc, applyPPCHigher(SA));
Hal Finkel3c8cc672015-10-12 20:56:18 +00001104 break;
1105 case R_PPC64_ADDR16_HIGHERA:
Rui Ueyama96f0e0b2015-10-23 02:40:46 +00001106 write16be(Loc, applyPPCHighera(SA));
Hal Finkel3c8cc672015-10-12 20:56:18 +00001107 break;
1108 case R_PPC64_ADDR16_HIGHEST:
Rui Ueyama96f0e0b2015-10-23 02:40:46 +00001109 write16be(Loc, applyPPCHighest(SA));
Hal Finkel3c8cc672015-10-12 20:56:18 +00001110 break;
1111 case R_PPC64_ADDR16_HIGHESTA:
Rui Ueyama96f0e0b2015-10-23 02:40:46 +00001112 write16be(Loc, applyPPCHighesta(SA));
Hal Finkel3c8cc672015-10-12 20:56:18 +00001113 break;
Igor Kudrinb4a09272015-12-01 08:41:20 +00001114 case R_PPC64_ADDR16_LO:
1115 write16be(Loc, applyPPCLo(SA));
Hal Finkel3c8cc672015-10-12 20:56:18 +00001116 break;
Igor Kudrinb4a09272015-12-01 08:41:20 +00001117 case R_PPC64_ADDR16_LO_DS:
1118 write16be(Loc, (read16be(Loc) & 3) | (applyPPCLo(SA) & ~3));
Hal Finkel3c8cc672015-10-12 20:56:18 +00001119 break;
1120 case R_PPC64_ADDR32:
Igor Kudrin9b7e7db2015-11-26 09:49:44 +00001121 checkInt<32>(SA, Type);
Rui Ueyama96f0e0b2015-10-23 02:40:46 +00001122 write32be(Loc, SA);
Hal Finkel3c8cc672015-10-12 20:56:18 +00001123 break;
Igor Kudrinb4a09272015-12-01 08:41:20 +00001124 case R_PPC64_ADDR64:
1125 write64be(Loc, SA);
1126 break;
1127 case R_PPC64_REL16_HA:
1128 write16be(Loc, applyPPCHa(SA - P));
1129 break;
1130 case R_PPC64_REL16_HI:
1131 write16be(Loc, applyPPCHi(SA - P));
1132 break;
1133 case R_PPC64_REL16_LO:
1134 write16be(Loc, applyPPCLo(SA - P));
1135 break;
Hal Finkel3c8cc672015-10-12 20:56:18 +00001136 case R_PPC64_REL24: {
Hal Finkel82281982015-10-17 00:48:20 +00001137 // If we have an undefined weak symbol, we might get here with a symbol
1138 // address of zero. That could overflow, but the code must be unreachable,
1139 // so don't bother doing anything at all.
1140 if (!SA)
1141 break;
1142
Hal Finkeldaedc122015-10-12 23:16:53 +00001143 uint64_t PltStart = Out<ELF64BE>::Plt->getVA();
1144 uint64_t PltEnd = PltStart + Out<ELF64BE>::Plt->getSize();
Rui Ueyama9e82fa22015-10-15 19:39:36 +00001145 bool InPlt = PltStart <= SA && SA < PltEnd;
Hal Finkeldaedc122015-10-12 23:16:53 +00001146
1147 if (!InPlt && Out<ELF64BE>::Opd) {
1148 // If this is a local call, and we currently have the address of a
1149 // function-descriptor, get the underlying code address instead.
1150 uint64_t OpdStart = Out<ELF64BE>::Opd->getVA();
1151 uint64_t OpdEnd = OpdStart + Out<ELF64BE>::Opd->getSize();
Rui Ueyama9e82fa22015-10-15 19:39:36 +00001152 bool InOpd = OpdStart <= SA && SA < OpdEnd;
Hal Finkeldaedc122015-10-12 23:16:53 +00001153
1154 if (InOpd)
Rui Ueyama9e82fa22015-10-15 19:39:36 +00001155 SA = read64be(&Out<ELF64BE>::OpdBuf[SA - OpdStart]);
Hal Finkeldaedc122015-10-12 23:16:53 +00001156 }
1157
Hal Finkel3c8cc672015-10-12 20:56:18 +00001158 uint32_t Mask = 0x03FFFFFC;
Igor Kudrin9b7e7db2015-11-26 09:49:44 +00001159 checkInt<24>(SA - P, Type);
Rui Ueyama96f0e0b2015-10-23 02:40:46 +00001160 write32be(Loc, (read32be(Loc) & ~Mask) | ((SA - P) & Mask));
Hal Finkel87bbd5f2015-10-12 21:19:18 +00001161
Rui Ueyama96f0e0b2015-10-23 02:40:46 +00001162 uint32_t Nop = 0x60000000;
1163 if (InPlt && Loc + 8 <= BufEnd && read32be(Loc + 4) == Nop)
1164 write32be(Loc + 4, 0xe8410028); // ld %r2, 40(%r1)
Hal Finkel3c8cc672015-10-12 20:56:18 +00001165 break;
1166 }
1167 case R_PPC64_REL32:
Igor Kudrin9b7e7db2015-11-26 09:49:44 +00001168 checkInt<32>(SA - P, Type);
Rui Ueyama96f0e0b2015-10-23 02:40:46 +00001169 write32be(Loc, SA - P);
Hal Finkel3c8cc672015-10-12 20:56:18 +00001170 break;
1171 case R_PPC64_REL64:
Rui Ueyama96f0e0b2015-10-23 02:40:46 +00001172 write64be(Loc, SA - P);
Hal Finkel3c8cc672015-10-12 20:56:18 +00001173 break;
Hal Finkel6f97c2b2015-10-16 21:55:40 +00001174 case R_PPC64_TOC:
Rui Ueyama96f0e0b2015-10-23 02:40:46 +00001175 write64be(Loc, SA);
Rafael Espindola3efa4e92015-09-22 21:12:55 +00001176 break;
1177 default:
Rui Ueyama1c42afc2015-10-12 15:49:06 +00001178 error("unrecognized reloc " + Twine(Type));
Rafael Espindola3efa4e92015-09-22 21:12:55 +00001179 }
1180}
Rafael Espindola1d6063e2015-09-22 21:24:52 +00001181
Igor Kudrindb7de9f2015-11-17 18:01:30 +00001182AArch64TargetInfo::AArch64TargetInfo() {
Igor Kudrin9606d192015-12-03 08:05:35 +00001183 CopyReloc = R_AARCH64_COPY;
George Rimara4804352016-01-11 14:15:17 +00001184 IRelativeReloc = R_AARCH64_IRELATIVE;
Igor Kudrin5d2bffd2015-11-24 06:48:31 +00001185 GotReloc = R_AARCH64_GLOB_DAT;
Igor Kudrindb7de9f2015-11-17 18:01:30 +00001186 PltReloc = R_AARCH64_JUMP_SLOT;
George Rimar3d737e42016-01-13 13:04:46 +00001187 TlsGotReloc = R_AARCH64_TLS_TPREL64;
Igor Kudrindb7de9f2015-11-17 18:01:30 +00001188 LazyRelocations = true;
1189 PltEntrySize = 16;
1190 PltZeroEntrySize = 32;
1191}
George Rimar648a2c32015-10-20 08:54:27 +00001192
Igor Kudrincfe47f52015-12-05 06:20:24 +00001193unsigned AArch64TargetInfo::getDynReloc(unsigned Type) const {
1194 if (Type == R_AARCH64_ABS32 || Type == R_AARCH64_ABS64)
1195 return Type;
1196 StringRef S = getELFRelocationTypeName(EM_AARCH64, Type);
1197 error("Relocation " + S + " cannot be used when making a shared object; "
1198 "recompile with -fPIC.");
1199}
1200
Igor Kudrindb7de9f2015-11-17 18:01:30 +00001201void AArch64TargetInfo::writeGotPltEntry(uint8_t *Buf, uint64_t Plt) const {
1202 write64le(Buf, Out<ELF64LE>::Plt->getVA());
1203}
1204
George Rimar648a2c32015-10-20 08:54:27 +00001205void AArch64TargetInfo::writePltZeroEntry(uint8_t *Buf, uint64_t GotEntryAddr,
Igor Kudrindb7de9f2015-11-17 18:01:30 +00001206 uint64_t PltEntryAddr) const {
1207 const uint8_t PltData[] = {
1208 0xf0, 0x7b, 0xbf, 0xa9, // stp x16, x30, [sp,#-16]!
1209 0x10, 0x00, 0x00, 0x90, // adrp x16, Page(&(.plt.got[2]))
1210 0x11, 0x02, 0x40, 0xf9, // ldr x17, [x16, Offset(&(.plt.got[2]))]
1211 0x10, 0x02, 0x00, 0x91, // add x16, x16, Offset(&(.plt.got[2]))
1212 0x20, 0x02, 0x1f, 0xd6, // br x17
1213 0x1f, 0x20, 0x03, 0xd5, // nop
1214 0x1f, 0x20, 0x03, 0xd5, // nop
1215 0x1f, 0x20, 0x03, 0xd5 // nop
1216 };
1217 memcpy(Buf, PltData, sizeof(PltData));
1218
1219 relocateOne(Buf + 4, Buf + 8, R_AARCH64_ADR_PREL_PG_HI21, PltEntryAddr + 4,
1220 GotEntryAddr + 16);
1221 relocateOne(Buf + 8, Buf + 12, R_AARCH64_LDST64_ABS_LO12_NC, PltEntryAddr + 8,
1222 GotEntryAddr + 16);
1223 relocateOne(Buf + 12, Buf + 16, R_AARCH64_ADD_ABS_LO12_NC, PltEntryAddr + 12,
1224 GotEntryAddr + 16);
1225}
1226
George Rimar77b77792015-11-25 22:15:01 +00001227void AArch64TargetInfo::writePltEntry(uint8_t *Buf, uint64_t GotAddr,
1228 uint64_t GotEntryAddr,
1229 uint64_t PltEntryAddr, int32_t Index,
1230 unsigned RelOff) const {
Igor Kudrindb7de9f2015-11-17 18:01:30 +00001231 const uint8_t Inst[] = {
1232 0x10, 0x00, 0x00, 0x90, // adrp x16, Page(&(.plt.got[n]))
1233 0x11, 0x02, 0x40, 0xf9, // ldr x17, [x16, Offset(&(.plt.got[n]))]
1234 0x10, 0x02, 0x00, 0x91, // add x16, x16, Offset(&(.plt.got[n]))
1235 0x20, 0x02, 0x1f, 0xd6 // br x17
1236 };
1237 memcpy(Buf, Inst, sizeof(Inst));
1238
1239 relocateOne(Buf, Buf + 4, R_AARCH64_ADR_PREL_PG_HI21, PltEntryAddr,
1240 GotEntryAddr);
1241 relocateOne(Buf + 4, Buf + 8, R_AARCH64_LDST64_ABS_LO12_NC, PltEntryAddr + 4,
1242 GotEntryAddr);
1243 relocateOne(Buf + 8, Buf + 12, R_AARCH64_ADD_ABS_LO12_NC, PltEntryAddr + 8,
1244 GotEntryAddr);
1245}
1246
George Rimar3d737e42016-01-13 13:04:46 +00001247unsigned AArch64TargetInfo::getTlsGotReloc(unsigned Type) const {
1248 if (Type == R_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21 ||
1249 Type == R_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC)
1250 return Type;
1251 return TlsGotReloc;
1252}
1253
1254bool AArch64TargetInfo::isTlsDynReloc(unsigned Type,
1255 const SymbolBody &S) const {
1256 return Type == R_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21 ||
1257 Type == R_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC;
1258}
1259
Rui Ueyama02dfd492015-12-17 01:18:40 +00001260bool AArch64TargetInfo::needsCopyRel(uint32_t Type, const SymbolBody &S) const {
Igor Kudrin9606d192015-12-03 08:05:35 +00001261 if (Config->Shared)
1262 return false;
1263 switch (Type) {
1264 default:
1265 return false;
1266 case R_AARCH64_ABS16:
1267 case R_AARCH64_ABS32:
1268 case R_AARCH64_ABS64:
1269 case R_AARCH64_ADD_ABS_LO12_NC:
1270 case R_AARCH64_ADR_PREL_LO21:
1271 case R_AARCH64_ADR_PREL_PG_HI21:
1272 case R_AARCH64_LDST8_ABS_LO12_NC:
1273 case R_AARCH64_LDST32_ABS_LO12_NC:
1274 case R_AARCH64_LDST64_ABS_LO12_NC:
Davide Italiano0d4fbae2016-01-14 01:30:21 +00001275 case R_AARCH64_LDST128_ABS_LO12_NC:
Igor Kudrin9606d192015-12-03 08:05:35 +00001276 if (auto *SS = dyn_cast<SharedSymbol<ELF64LE>>(&S))
1277 return SS->Sym.getType() == STT_OBJECT;
1278 return false;
1279 }
1280}
1281
Rafael Espindola3ef3a4c2015-09-29 23:22:16 +00001282bool AArch64TargetInfo::relocNeedsGot(uint32_t Type,
1283 const SymbolBody &S) const {
George Rimar3d737e42016-01-13 13:04:46 +00001284 switch (Type) {
1285 case R_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC:
1286 case R_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21:
1287 case R_AARCH64_ADR_GOT_PAGE:
1288 case R_AARCH64_LD64_GOT_LO12_NC:
1289 return true;
1290 default:
1291 return relocNeedsPlt(Type, S);
1292 }
Rafael Espindola3ef3a4c2015-09-29 23:22:16 +00001293}
Igor Kudrindb7de9f2015-11-17 18:01:30 +00001294
Rafael Espindola3ef3a4c2015-09-29 23:22:16 +00001295bool AArch64TargetInfo::relocNeedsPlt(uint32_t Type,
1296 const SymbolBody &S) const {
George Rimara4804352016-01-11 14:15:17 +00001297 if (isGnuIFunc<ELF64LE>(S))
1298 return true;
Igor Kudrindb7de9f2015-11-17 18:01:30 +00001299 switch (Type) {
1300 default:
1301 return false;
Igor Kudrindb7de9f2015-11-17 18:01:30 +00001302 case R_AARCH64_CALL26:
George Rimar4102bfb2016-01-11 14:22:00 +00001303 case R_AARCH64_CONDBR19:
Igor Kudrinb4a09272015-12-01 08:41:20 +00001304 case R_AARCH64_JUMP26:
George Rimar1395dbd2016-01-11 14:27:05 +00001305 case R_AARCH64_TSTBR14:
Igor Kudrindb7de9f2015-11-17 18:01:30 +00001306 return canBePreempted(&S, true);
1307 }
Rafael Espindola3ef3a4c2015-09-29 23:22:16 +00001308}
Davide Italiano1d750a62015-09-27 08:45:38 +00001309
Davide Italianoef4be6b2015-10-06 19:01:32 +00001310static void updateAArch64Adr(uint8_t *L, uint64_t Imm) {
Davide Italiano1f31a2c2015-10-02 22:00:42 +00001311 uint32_t ImmLo = (Imm & 0x3) << 29;
1312 uint32_t ImmHi = ((Imm & 0x1FFFFC) >> 2) << 5;
1313 uint64_t Mask = (0x3 << 29) | (0x7FFFF << 5);
Rui Ueyama87bc41b2015-10-06 18:54:43 +00001314 write32le(L, (read32le(L) & ~Mask) | ImmLo | ImmHi);
Davide Italiano1f31a2c2015-10-02 22:00:42 +00001315}
1316
Davide Italiano318ca222015-10-02 22:13:51 +00001317// Page(Expr) is the page address of the expression Expr, defined
1318// as (Expr & ~0xFFF). (This applies even if the machine page size
Davide Italianod9b5be42015-10-02 22:17:09 +00001319// supported by the platform has a different value.)
Davide Italianoef4be6b2015-10-06 19:01:32 +00001320static uint64_t getAArch64Page(uint64_t Expr) {
Davide Italiano318ca222015-10-02 22:13:51 +00001321 return Expr & (~static_cast<uint64_t>(0xFFF));
Davide Italiano1f31a2c2015-10-02 22:00:42 +00001322}
1323
Rui Ueyama96f0e0b2015-10-23 02:40:46 +00001324void AArch64TargetInfo::relocateOne(uint8_t *Loc, uint8_t *BufEnd,
Simon Atanasyan09b3e362015-12-01 21:24:45 +00001325 uint32_t Type, uint64_t P, uint64_t SA,
George Rimar48651482015-12-11 08:59:37 +00001326 uint64_t ZA, uint8_t *PairedLoc) const {
Davide Italiano1d750a62015-09-27 08:45:38 +00001327 switch (Type) {
Davide Italianodf88f962015-10-04 00:59:16 +00001328 case R_AARCH64_ABS16:
Igor Kudrinfea8ed52015-11-26 10:05:24 +00001329 checkIntUInt<16>(SA, Type);
Rui Ueyama96f0e0b2015-10-23 02:40:46 +00001330 write16le(Loc, SA);
Davide Italianodf88f962015-10-04 00:59:16 +00001331 break;
1332 case R_AARCH64_ABS32:
Igor Kudrinfea8ed52015-11-26 10:05:24 +00001333 checkIntUInt<32>(SA, Type);
Rui Ueyama96f0e0b2015-10-23 02:40:46 +00001334 write32le(Loc, SA);
Davide Italianodf88f962015-10-04 00:59:16 +00001335 break;
1336 case R_AARCH64_ABS64:
Rui Ueyama96f0e0b2015-10-23 02:40:46 +00001337 write64le(Loc, SA);
Davide Italianodf88f962015-10-04 00:59:16 +00001338 break;
Davide Italiano0b6974b2015-10-03 19:56:07 +00001339 case R_AARCH64_ADD_ABS_LO12_NC:
Davide Italianoa7165742015-10-16 21:06:55 +00001340 // This relocation stores 12 bits and there's no instruction
1341 // to do it. Instead, we do a 32 bits store of the value
Rui Ueyama96f0e0b2015-10-23 02:40:46 +00001342 // of r_addend bitwise-or'ed Loc. This assumes that the addend
1343 // bits in Loc are zero.
1344 or32le(Loc, (SA & 0xFFF) << 10);
Davide Italiano0b6974b2015-10-03 19:56:07 +00001345 break;
Igor Kudrinb4a09272015-12-01 08:41:20 +00001346 case R_AARCH64_ADR_GOT_PAGE: {
1347 uint64_t X = getAArch64Page(SA) - getAArch64Page(P);
1348 checkInt<33>(X, Type);
1349 updateAArch64Adr(Loc, (X >> 12) & 0x1FFFFF); // X[32:12]
1350 break;
1351 }
Rui Ueyamaee8c53b2015-10-06 19:57:01 +00001352 case R_AARCH64_ADR_PREL_LO21: {
Rafael Espindola826941a2015-10-15 18:19:39 +00001353 uint64_t X = SA - P;
Igor Kudrin9b7e7db2015-11-26 09:49:44 +00001354 checkInt<21>(X, Type);
Rui Ueyama96f0e0b2015-10-23 02:40:46 +00001355 updateAArch64Adr(Loc, X & 0x1FFFFF);
Davide Italiano1d750a62015-09-27 08:45:38 +00001356 break;
Rui Ueyamaee8c53b2015-10-06 19:57:01 +00001357 }
George Rimar3d737e42016-01-13 13:04:46 +00001358 case R_AARCH64_ADR_PREL_PG_HI21:
1359 case R_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21: {
Rafael Espindola826941a2015-10-15 18:19:39 +00001360 uint64_t X = getAArch64Page(SA) - getAArch64Page(P);
Igor Kudrin9b7e7db2015-11-26 09:49:44 +00001361 checkInt<33>(X, Type);
Rui Ueyama96f0e0b2015-10-23 02:40:46 +00001362 updateAArch64Adr(Loc, (X >> 12) & 0x1FFFFF); // X[32:12]
Davide Italiano1f31a2c2015-10-02 22:00:42 +00001363 break;
Rui Ueyamaee8c53b2015-10-06 19:57:01 +00001364 }
Igor Kudrinb4a09272015-12-01 08:41:20 +00001365 case R_AARCH64_CALL26:
1366 case R_AARCH64_JUMP26: {
Igor Kudrinb34115b2015-11-13 03:26:59 +00001367 uint64_t X = SA - P;
Igor Kudrin9b7e7db2015-11-26 09:49:44 +00001368 checkInt<28>(X, Type);
Igor Kudrinb34115b2015-11-13 03:26:59 +00001369 or32le(Loc, (X & 0x0FFFFFFC) >> 2);
1370 break;
1371 }
George Rimar4102bfb2016-01-11 14:22:00 +00001372 case R_AARCH64_CONDBR19: {
1373 uint64_t X = SA - P;
1374 checkInt<21>(X, Type);
1375 or32le(Loc, (X & 0x1FFFFC) << 3);
1376 break;
1377 }
Igor Kudrin5d2bffd2015-11-24 06:48:31 +00001378 case R_AARCH64_LD64_GOT_LO12_NC:
George Rimar3d737e42016-01-13 13:04:46 +00001379 case R_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC:
Igor Kudrin9b7e7db2015-11-26 09:49:44 +00001380 checkAlignment<8>(SA, Type);
Igor Kudrin5d2bffd2015-11-24 06:48:31 +00001381 or32le(Loc, (SA & 0xFF8) << 7);
1382 break;
Davide Italiano0d4fbae2016-01-14 01:30:21 +00001383 case R_AARCH64_LDST128_ABS_LO12_NC:
1384 or32le(Loc, (SA & 0x0FF8) << 6);
1385 break;
Davide Italianodc67f9b2015-11-20 21:35:38 +00001386 case R_AARCH64_LDST8_ABS_LO12_NC:
Davide Italianodc67f9b2015-11-20 21:35:38 +00001387 or32le(Loc, (SA & 0xFFF) << 10);
1388 break;
Igor Kudrinb4a09272015-12-01 08:41:20 +00001389 case R_AARCH64_LDST32_ABS_LO12_NC:
1390 or32le(Loc, (SA & 0xFFC) << 8);
1391 break;
1392 case R_AARCH64_LDST64_ABS_LO12_NC:
1393 or32le(Loc, (SA & 0xFF8) << 7);
1394 break;
Davide Italiano3300b792015-10-29 19:55:59 +00001395 case R_AARCH64_PREL16:
Igor Kudrinfea8ed52015-11-26 10:05:24 +00001396 checkIntUInt<16>(SA - P, Type);
Davide Italiano3300b792015-10-29 19:55:59 +00001397 write16le(Loc, SA - P);
1398 break;
1399 case R_AARCH64_PREL32:
Igor Kudrinfea8ed52015-11-26 10:05:24 +00001400 checkIntUInt<32>(SA - P, Type);
Davide Italiano3300b792015-10-29 19:55:59 +00001401 write32le(Loc, SA - P);
1402 break;
Davide Italianob12d6682015-10-28 16:14:18 +00001403 case R_AARCH64_PREL64:
Davide Italianob12d6682015-10-28 16:14:18 +00001404 write64le(Loc, SA - P);
1405 break;
George Rimar1395dbd2016-01-11 14:27:05 +00001406 case R_AARCH64_TSTBR14: {
1407 uint64_t X = SA - P;
1408 checkInt<16>(X, Type);
1409 or32le(Loc, (X & 0xFFFC) << 3);
1410 break;
1411 }
Davide Italiano1d750a62015-09-27 08:45:38 +00001412 default:
Rui Ueyama1c42afc2015-10-12 15:49:06 +00001413 error("unrecognized reloc " + Twine(Type));
Davide Italiano1d750a62015-09-27 08:45:38 +00001414 }
1415}
Simon Atanasyan49829a12015-09-29 05:34:03 +00001416
Tom Stellard80efb162016-01-07 03:59:08 +00001417AMDGPUTargetInfo::AMDGPUTargetInfo() {}
1418
1419void AMDGPUTargetInfo::writeGotPltEntry(uint8_t *Buf, uint64_t Plt) const {
1420 llvm_unreachable("not implemented");
1421}
1422
1423void AMDGPUTargetInfo::writePltZeroEntry(uint8_t *Buf, uint64_t GotEntryAddr,
1424 uint64_t PltEntryAddr) const {
1425 llvm_unreachable("not implemented");
1426}
1427
1428void AMDGPUTargetInfo::writePltEntry(uint8_t *Buf, uint64_t GotAddr,
1429 uint64_t GotEntryAddr,
1430 uint64_t PltEntryAddr, int32_t Index,
1431 unsigned RelOff) const {
1432 llvm_unreachable("not implemented");
1433}
1434
1435bool AMDGPUTargetInfo::relocNeedsGot(uint32_t Type, const SymbolBody &S) const {
1436 return false;
1437}
1438
1439bool AMDGPUTargetInfo::relocNeedsPlt(uint32_t Type, const SymbolBody &S) const {
1440 return false;
1441}
1442
Rui Ueyama1300e6b2016-01-07 20:34:16 +00001443// Implementing relocations for AMDGPU is low priority since most
1444// programs don't use relocations now. Thus, this function is not
1445// actually called (relocateOne is called for each relocation).
1446// That's why the AMDGPU port works without implementing this function.
Tom Stellard80efb162016-01-07 03:59:08 +00001447void AMDGPUTargetInfo::relocateOne(uint8_t *Loc, uint8_t *BufEnd, uint32_t Type,
1448 uint64_t P, uint64_t SA, uint64_t ZA,
1449 uint8_t *PairedLoc) const {
1450 llvm_unreachable("not implemented");
1451}
1452
Simon Atanasyan9c2d7882015-10-14 14:24:46 +00001453template <class ELFT> MipsTargetInfo<ELFT>::MipsTargetInfo() {
Hal Finkele3c26262015-10-08 22:23:54 +00001454 PageSize = 65536;
Igor Kudrin15cd9ff2015-11-06 07:43:03 +00001455 GotHeaderEntriesNum = 2;
1456}
1457
1458template <class ELFT>
1459void MipsTargetInfo<ELFT>::writeGotHeaderEntries(uint8_t *Buf) const {
Rui Ueyama24e39522015-12-03 20:57:45 +00001460 typedef typename ELFFile<ELFT>::Elf_Off Elf_Off;
Igor Kudrin15cd9ff2015-11-06 07:43:03 +00001461 auto *P = reinterpret_cast<Elf_Off *>(Buf);
1462 // Module pointer
1463 P[1] = ELFT::Is64Bits ? 0x8000000000000000 : 0x80000000;
Simon Atanasyan49829a12015-09-29 05:34:03 +00001464}
1465
Simon Atanasyan9c2d7882015-10-14 14:24:46 +00001466template <class ELFT>
George Rimar648a2c32015-10-20 08:54:27 +00001467void MipsTargetInfo<ELFT>::writeGotPltEntry(uint8_t *Buf, uint64_t Plt) const {}
1468template <class ELFT>
1469void MipsTargetInfo<ELFT>::writePltZeroEntry(uint8_t *Buf, uint64_t GotEntryAddr,
1470 uint64_t PltEntryAddr) const {}
1471template <class ELFT>
George Rimar77b77792015-11-25 22:15:01 +00001472void MipsTargetInfo<ELFT>::writePltEntry(uint8_t *Buf, uint64_t GotAddr,
1473 uint64_t GotEntryAddr,
1474 uint64_t PltEntryAddr, int32_t Index,
1475 unsigned RelOff) const {}
Simon Atanasyan49829a12015-09-29 05:34:03 +00001476
Simon Atanasyan9c2d7882015-10-14 14:24:46 +00001477template <class ELFT>
1478bool MipsTargetInfo<ELFT>::relocNeedsGot(uint32_t Type,
1479 const SymbolBody &S) const {
Simon Atanasyan96306bb2015-11-25 20:58:52 +00001480 return Type == R_MIPS_GOT16 || Type == R_MIPS_CALL16;
Rafael Espindola3ef3a4c2015-09-29 23:22:16 +00001481}
Simon Atanasyan49829a12015-09-29 05:34:03 +00001482
Simon Atanasyan9c2d7882015-10-14 14:24:46 +00001483template <class ELFT>
1484bool MipsTargetInfo<ELFT>::relocNeedsPlt(uint32_t Type,
1485 const SymbolBody &S) const {
Rafael Espindola3ef3a4c2015-09-29 23:22:16 +00001486 return false;
1487}
Simon Atanasyan49829a12015-09-29 05:34:03 +00001488
Simon Atanasyan35031192015-12-15 06:06:34 +00001489static uint16_t mipsHigh(uint64_t V) { return (V + 0x8000) >> 16; }
Simon Atanasyan2cd670d2015-12-13 06:49:01 +00001490
Simon Atanasyan0fc0acf2015-12-21 17:36:40 +00001491template <endianness E, uint8_t BSIZE>
1492static void applyMipsPcReloc(uint8_t *Loc, uint32_t Type, uint64_t P,
1493 uint64_t SA) {
1494 uint32_t Mask = ~(0xffffffff << BSIZE);
1495 uint32_t Instr = read32<E>(Loc);
1496 int64_t A = SignExtend64<BSIZE + 2>((Instr & Mask) << 2);
1497 checkAlignment<4>(SA + A, Type);
1498 int64_t V = SA + A - P;
1499 checkInt<BSIZE + 2>(V, Type);
1500 write32<E>(Loc, (Instr & ~Mask) | ((V >> 2) & Mask));
1501}
1502
Simon Atanasyan9c2d7882015-10-14 14:24:46 +00001503template <class ELFT>
Rui Ueyama96f0e0b2015-10-23 02:40:46 +00001504void MipsTargetInfo<ELFT>::relocateOne(uint8_t *Loc, uint8_t *BufEnd,
Simon Atanasyan09b3e362015-12-01 21:24:45 +00001505 uint32_t Type, uint64_t P, uint64_t SA,
George Rimar48651482015-12-11 08:59:37 +00001506 uint64_t ZA, uint8_t *PairedLoc) const {
Rafael Espindolae7e57b22015-11-09 21:43:00 +00001507 const endianness E = ELFT::TargetEndianness;
Simon Atanasyan3b732ac2015-10-12 15:10:02 +00001508 switch (Type) {
1509 case R_MIPS_32:
Rafael Espindolae7e57b22015-11-09 21:43:00 +00001510 add32<E>(Loc, SA);
Simon Atanasyan3b732ac2015-10-12 15:10:02 +00001511 break;
Rui Ueyama7ee3cf72015-12-03 20:59:51 +00001512 case R_MIPS_CALL16:
1513 case R_MIPS_GOT16: {
1514 int64_t V = SA - getMipsGpAddr<ELFT>();
1515 if (Type == R_MIPS_GOT16)
1516 checkInt<16>(V, Type);
1517 write32<E>(Loc, (read32<E>(Loc) & 0xffff0000) | (V & 0xffff));
1518 break;
1519 }
Simon Atanasyan57830b62015-12-25 13:02:13 +00001520 case R_MIPS_GPREL16: {
1521 uint32_t Instr = read32<E>(Loc);
1522 int64_t V = SA + SignExtend64<16>(Instr & 0xffff) - getMipsGpAddr<ELFT>();
1523 checkInt<16>(V, Type);
1524 write32<E>(Loc, (Instr & 0xffff0000) | (V & 0xffff));
1525 break;
1526 }
1527 case R_MIPS_GPREL32:
1528 write32<E>(Loc, SA + int32_t(read32<E>(Loc)) - getMipsGpAddr<ELFT>());
1529 break;
Simon Atanasyan09b3e362015-12-01 21:24:45 +00001530 case R_MIPS_HI16: {
1531 uint32_t Instr = read32<E>(Loc);
1532 if (PairedLoc) {
1533 uint64_t AHL = ((Instr & 0xffff) << 16) +
Rui Ueyama24e39522015-12-03 20:57:45 +00001534 SignExtend64<16>(read32<E>(PairedLoc) & 0xffff);
Simon Atanasyan2cd670d2015-12-13 06:49:01 +00001535 write32<E>(Loc, (Instr & 0xffff0000) | mipsHigh(SA + AHL));
Simon Atanasyan09b3e362015-12-01 21:24:45 +00001536 } else {
1537 warning("Can't find matching R_MIPS_LO16 relocation for R_MIPS_HI16");
Simon Atanasyan2cd670d2015-12-13 06:49:01 +00001538 write32<E>(Loc, (Instr & 0xffff0000) | mipsHigh(SA));
Simon Atanasyan09b3e362015-12-01 21:24:45 +00001539 }
1540 break;
1541 }
Simon Atanasyane4361852015-12-13 06:49:14 +00001542 case R_MIPS_JALR:
1543 // Ignore this optimization relocation for now
1544 break;
Simon Atanasyan09b3e362015-12-01 21:24:45 +00001545 case R_MIPS_LO16: {
1546 uint32_t Instr = read32<E>(Loc);
Rui Ueyama24e39522015-12-03 20:57:45 +00001547 int64_t AHL = SignExtend64<16>(Instr & 0xffff);
Simon Atanasyan09b3e362015-12-01 21:24:45 +00001548 write32<E>(Loc, (Instr & 0xffff0000) | ((SA + AHL) & 0xffff));
1549 break;
1550 }
Simon Atanasyan0fc0acf2015-12-21 17:36:40 +00001551 case R_MIPS_PC16:
1552 applyMipsPcReloc<E, 16>(Loc, Type, P, SA);
1553 break;
1554 case R_MIPS_PC19_S2:
1555 applyMipsPcReloc<E, 19>(Loc, Type, P, SA);
1556 break;
1557 case R_MIPS_PC21_S2:
1558 applyMipsPcReloc<E, 21>(Loc, Type, P, SA);
1559 break;
1560 case R_MIPS_PC26_S2:
1561 applyMipsPcReloc<E, 26>(Loc, Type, P, SA);
1562 break;
1563 case R_MIPS_PCHI16: {
1564 uint32_t Instr = read32<E>(Loc);
1565 if (PairedLoc) {
1566 uint64_t AHL = ((Instr & 0xffff) << 16) +
1567 SignExtend64<16>(read32<E>(PairedLoc) & 0xffff);
1568 write32<E>(Loc, (Instr & 0xffff0000) | mipsHigh(SA + AHL - P));
1569 } else {
1570 warning("Can't find matching R_MIPS_PCLO16 relocation for R_MIPS_PCHI16");
1571 write32<E>(Loc, (Instr & 0xffff0000) | mipsHigh(SA - P));
1572 }
1573 break;
1574 }
1575 case R_MIPS_PCLO16: {
1576 uint32_t Instr = read32<E>(Loc);
1577 int64_t AHL = SignExtend64<16>(Instr & 0xffff);
1578 write32<E>(Loc, (Instr & 0xffff0000) | ((SA + AHL - P) & 0xffff));
1579 break;
1580 }
Simon Atanasyan3b732ac2015-10-12 15:10:02 +00001581 default:
Rui Ueyama1c42afc2015-10-12 15:49:06 +00001582 error("unrecognized reloc " + Twine(Type));
Simon Atanasyan3b732ac2015-10-12 15:10:02 +00001583 }
1584}
Igor Kudrin15cd9ff2015-11-06 07:43:03 +00001585
Simon Atanasyan0fc0acf2015-12-21 17:36:40 +00001586template <class ELFT>
Simon Atanasyan682aeea2016-01-14 20:42:09 +00001587bool MipsTargetInfo<ELFT>::isHintReloc(uint32_t Type) const {
1588 return Type == R_MIPS_JALR;
1589}
1590
1591template <class ELFT>
Simon Atanasyan0fc0acf2015-12-21 17:36:40 +00001592bool MipsTargetInfo<ELFT>::isRelRelative(uint32_t Type) const {
1593 switch (Type) {
1594 default:
1595 return false;
1596 case R_MIPS_PC16:
1597 case R_MIPS_PC19_S2:
1598 case R_MIPS_PC21_S2:
1599 case R_MIPS_PC26_S2:
1600 case R_MIPS_PCHI16:
1601 case R_MIPS_PCLO16:
1602 return true;
1603 }
1604}
1605
Rui Ueyama3f11c8c2015-12-24 08:41:12 +00001606// _gp is a MIPS-specific ABI-defined symbol which points to
1607// a location that is relative to GOT. This function returns
1608// the value for the symbol.
Rui Ueyama24e39522015-12-03 20:57:45 +00001609template <class ELFT> typename ELFFile<ELFT>::uintX_t getMipsGpAddr() {
Rui Ueyama3f11c8c2015-12-24 08:41:12 +00001610 unsigned GPOffset = 0x7ff0;
1611 if (uint64_t V = Out<ELFT>::Got->getVA())
1612 return V + GPOffset;
1613 return 0;
Igor Kudrin15cd9ff2015-11-06 07:43:03 +00001614}
1615
1616template uint32_t getMipsGpAddr<ELF32LE>();
1617template uint32_t getMipsGpAddr<ELF32BE>();
1618template uint64_t getMipsGpAddr<ELF64LE>();
1619template uint64_t getMipsGpAddr<ELF64BE>();
Rafael Espindola01205f72015-09-22 18:19:46 +00001620}
1621}