blob: 60cdddf71d275fd7e5ab93a7d1dd41f69442711a [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//
10// Machine-specific stuff, such as applying relocations, creation of
11// GOT or PLT entries, etc., are is handled in this file.
12//
13//===----------------------------------------------------------------------===//
Rafael Espindola01205f72015-09-22 18:19:46 +000014
15#include "Target.h"
Rafael Espindolac4010882015-09-22 20:54:08 +000016#include "Error.h"
Rui Ueyamaaf21d922015-10-08 20:06:07 +000017#include "OutputSections.h"
Rafael Espindola3ef3a4c2015-09-29 23:22:16 +000018#include "Symbols.h"
Rafael Espindola01205f72015-09-22 18:19:46 +000019
20#include "llvm/ADT/ArrayRef.h"
Rafael Espindolac4010882015-09-22 20:54:08 +000021#include "llvm/Object/ELF.h"
Rafael Espindola01205f72015-09-22 18:19:46 +000022#include "llvm/Support/Endian.h"
23#include "llvm/Support/ELF.h"
24
25using namespace llvm;
Rafael Espindolac4010882015-09-22 20:54:08 +000026using namespace llvm::object;
Rafael Espindola0872ea32015-09-24 14:16:02 +000027using namespace llvm::support::endian;
Rafael Espindola01205f72015-09-22 18:19:46 +000028using namespace llvm::ELF;
29
30namespace lld {
31namespace elf2 {
32
33std::unique_ptr<TargetInfo> Target;
34
Rui Ueyamaefc23de2015-10-14 21:30:32 +000035static void add32le(uint8_t *L, int32_t V) { write32le(L, read32le(L) + V); }
36static void add32be(uint8_t *L, int32_t V) { write32be(L, read32be(L) + V); }
37static void or32le(uint8_t *L, int32_t V) { write32le(L, read32le(L) | V); }
38
39template <bool IsLE> static void add32(uint8_t *L, int32_t V);
40template <> void add32<true>(uint8_t *L, int32_t V) { add32le(L, V); }
41template <> void add32<false>(uint8_t *L, int32_t V) { add32be(L, V); }
42
43namespace {
44class X86TargetInfo final : public TargetInfo {
45public:
46 X86TargetInfo();
47 void writePltEntry(uint8_t *Buf, uint64_t GotEntryAddr,
48 uint64_t PltEntryAddr) const override;
49 bool relocNeedsGot(uint32_t Type, const SymbolBody &S) const override;
50 bool relocPointsToGot(uint32_t Type) const override;
51 bool relocNeedsPlt(uint32_t Type, const SymbolBody &S) const override;
52 void relocateOne(uint8_t *Buf, uint8_t *BufEnd, const void *RelP,
53 uint32_t Type, uint64_t BaseAddr,
54 uint64_t SymVA) const override;
55};
56
57class X86_64TargetInfo final : public TargetInfo {
58public:
59 X86_64TargetInfo();
60 unsigned getPLTRefReloc(unsigned Type) const override;
61 void writePltEntry(uint8_t *Buf, uint64_t GotEntryAddr,
62 uint64_t PltEntryAddr) const override;
63 bool relocNeedsGot(uint32_t Type, const SymbolBody &S) const override;
64 bool relocNeedsPlt(uint32_t Type, const SymbolBody &S) const override;
65 void relocateOne(uint8_t *Buf, uint8_t *BufEnd, const void *RelP,
66 uint32_t Type, uint64_t BaseAddr,
67 uint64_t SymVA) const override;
68 bool isRelRelative(uint32_t Type) const override;
69};
70
71class PPC64TargetInfo final : public TargetInfo {
72public:
73 PPC64TargetInfo();
74 void writePltEntry(uint8_t *Buf, uint64_t GotEntryAddr,
75 uint64_t PltEntryAddr) const override;
76 bool relocNeedsGot(uint32_t Type, const SymbolBody &S) const override;
77 bool relocNeedsPlt(uint32_t Type, const SymbolBody &S) const override;
78 void relocateOne(uint8_t *Buf, uint8_t *BufEnd, const void *RelP,
79 uint32_t Type, uint64_t BaseAddr,
80 uint64_t SymVA) const override;
81 bool isRelRelative(uint32_t Type) const override;
82};
83
84class PPCTargetInfo final : public TargetInfo {
85public:
86 PPCTargetInfo();
87 void writePltEntry(uint8_t *Buf, uint64_t GotEntryAddr,
88 uint64_t PltEntryAddr) const override;
89 bool relocNeedsGot(uint32_t Type, const SymbolBody &S) const override;
90 bool relocNeedsPlt(uint32_t Type, const SymbolBody &S) const override;
91 void relocateOne(uint8_t *Buf, uint8_t *BufEnd, const void *RelP,
92 uint32_t Type, uint64_t BaseAddr,
93 uint64_t SymVA) const override;
94};
95
96class AArch64TargetInfo final : public TargetInfo {
97public:
98 AArch64TargetInfo();
99 void writePltEntry(uint8_t *Buf, uint64_t GotEntryAddr,
100 uint64_t PltEntryAddr) const override;
101 bool relocNeedsGot(uint32_t Type, const SymbolBody &S) const override;
102 bool relocNeedsPlt(uint32_t Type, const SymbolBody &S) const override;
103 void relocateOne(uint8_t *Buf, uint8_t *BufEnd, const void *RelP,
104 uint32_t Type, uint64_t BaseAddr,
105 uint64_t SymVA) const override;
106};
107
108template <class ELFT> class MipsTargetInfo final : public TargetInfo {
109public:
110 MipsTargetInfo();
111 void writePltEntry(uint8_t *Buf, uint64_t GotEntryAddr,
112 uint64_t PltEntryAddr) const override;
113 bool relocNeedsGot(uint32_t Type, const SymbolBody &S) const override;
114 bool relocNeedsPlt(uint32_t Type, const SymbolBody &S) const override;
115 void relocateOne(uint8_t *Buf, uint8_t *BufEnd, const void *RelP,
116 uint32_t Type, uint64_t BaseAddr,
117 uint64_t SymVA) const override;
118};
119} // anonymous namespace
120
Rui Ueyama91004392015-10-13 16:08:15 +0000121TargetInfo *createTarget() {
122 switch (Config->EMachine) {
123 case EM_386:
124 return new X86TargetInfo();
125 case EM_AARCH64:
126 return new AArch64TargetInfo();
127 case EM_MIPS:
Simon Atanasyan9c2d7882015-10-14 14:24:46 +0000128 switch (Config->EKind) {
129 case ELF32LEKind:
130 return new MipsTargetInfo<ELF32LE>();
131 case ELF32BEKind:
132 return new MipsTargetInfo<ELF32BE>();
133 default:
134 error("Unsupported MIPS target");
135 }
Rui Ueyama91004392015-10-13 16:08:15 +0000136 case EM_PPC:
137 return new PPCTargetInfo();
138 case EM_PPC64:
139 return new PPC64TargetInfo();
140 case EM_X86_64:
141 return new X86_64TargetInfo();
142 }
143 error("Unknown target machine");
144}
145
Rafael Espindola01205f72015-09-22 18:19:46 +0000146TargetInfo::~TargetInfo() {}
147
Rafael Espindola227556e2015-10-14 16:15:46 +0000148unsigned TargetInfo::getPLTRefReloc(unsigned Type) const { return PCRelReloc; }
149
Rafael Espindola6d7fcdb2015-09-29 13:36:32 +0000150bool TargetInfo::relocPointsToGot(uint32_t Type) const { return false; }
151
Rafael Espindolaae244002015-10-05 19:30:12 +0000152bool TargetInfo::isRelRelative(uint32_t Type) const { return true; }
153
Rafael Espindola7f074422015-09-22 21:35:51 +0000154X86TargetInfo::X86TargetInfo() {
155 PCRelReloc = R_386_PC32;
156 GotReloc = R_386_GLOB_DAT;
Rafael Espindola8acb95c2015-09-29 14:42:37 +0000157 GotRefReloc = R_386_GOT32;
Rafael Espindola7f074422015-09-22 21:35:51 +0000158}
Rafael Espindola01205f72015-09-22 18:19:46 +0000159
160void X86TargetInfo::writePltEntry(uint8_t *Buf, uint64_t GotEntryAddr,
Rui Ueyamac58656c2015-10-13 16:59:30 +0000161 uint64_t PltEntryAddr) const {
162 // jmpl *val; nop; nop
163 const uint8_t Inst[] = {0xff, 0x25, 0, 0, 0, 0, 0x90, 0x90};
Rui Ueyama1500a902015-09-29 23:00:47 +0000164 memcpy(Buf, Inst, sizeof(Inst));
Rui Ueyamac58656c2015-10-13 16:59:30 +0000165 assert(isUInt<32>(GotEntryAddr));
166 write32le(Buf + 2, GotEntryAddr);
Rafael Espindola01205f72015-09-22 18:19:46 +0000167}
168
Rafael Espindola3ef3a4c2015-09-29 23:22:16 +0000169bool X86TargetInfo::relocNeedsGot(uint32_t Type, const SymbolBody &S) const {
Rui Ueyama5ba3ac42015-09-30 01:40:08 +0000170 return Type == R_386_GOT32 || relocNeedsPlt(Type, S);
Rafael Espindola01205f72015-09-22 18:19:46 +0000171}
172
Rafael Espindola6d7fcdb2015-09-29 13:36:32 +0000173bool X86TargetInfo::relocPointsToGot(uint32_t Type) const {
174 return Type == R_386_GOTPC;
175}
176
Rafael Espindola3ef3a4c2015-09-29 23:22:16 +0000177bool X86TargetInfo::relocNeedsPlt(uint32_t Type, const SymbolBody &S) const {
George Rimar730c2782015-10-07 18:46:13 +0000178 return Type == R_386_PLT32 || (Type == R_386_PC32 && S.isShared());
Rafael Espindola01205f72015-09-22 18:19:46 +0000179}
180
Hal Finkel87bbd5f2015-10-12 21:19:18 +0000181void X86TargetInfo::relocateOne(uint8_t *Buf, uint8_t *BufEnd, const void *RelP,
182 uint32_t Type, uint64_t BaseAddr,
183 uint64_t SymVA) const {
Rafael Espindolac4010882015-09-22 20:54:08 +0000184 typedef ELFFile<ELF32LE>::Elf_Rel Elf_Rel;
185 auto &Rel = *reinterpret_cast<const Elf_Rel *>(RelP);
186
187 uint32_t Offset = Rel.r_offset;
Rui Ueyama87bc41b2015-10-06 18:54:43 +0000188 uint8_t *Loc = Buf + Offset;
Rafael Espindolac4010882015-09-22 20:54:08 +0000189 switch (Type) {
Rafael Espindola8acb95c2015-09-29 14:42:37 +0000190 case R_386_GOT32:
Rui Ueyamaaf21d922015-10-08 20:06:07 +0000191 add32le(Loc, SymVA - Out<ELF32LE>::Got->getVA());
Rafael Espindola8acb95c2015-09-29 14:42:37 +0000192 break;
Rafael Espindolac4010882015-09-22 20:54:08 +0000193 case R_386_PC32:
Rui Ueyama87bc41b2015-10-06 18:54:43 +0000194 add32le(Loc, SymVA - (BaseAddr + Offset));
Rafael Espindolac4010882015-09-22 20:54:08 +0000195 break;
196 case R_386_32:
Rui Ueyama87bc41b2015-10-06 18:54:43 +0000197 add32le(Loc, SymVA);
Rafael Espindolac4010882015-09-22 20:54:08 +0000198 break;
199 default:
Rui Ueyama1c42afc2015-10-12 15:49:06 +0000200 error("unrecognized reloc " + Twine(Type));
Rafael Espindolac4010882015-09-22 20:54:08 +0000201 }
202}
203
Rafael Espindola7f074422015-09-22 21:35:51 +0000204X86_64TargetInfo::X86_64TargetInfo() {
205 PCRelReloc = R_X86_64_PC32;
206 GotReloc = R_X86_64_GLOB_DAT;
Rafael Espindola8acb95c2015-09-29 14:42:37 +0000207 GotRefReloc = R_X86_64_PC32;
Rafael Espindolaae244002015-10-05 19:30:12 +0000208 RelativeReloc = R_X86_64_RELATIVE;
Rafael Espindola7f074422015-09-22 21:35:51 +0000209}
Rafael Espindola01205f72015-09-22 18:19:46 +0000210
211void X86_64TargetInfo::writePltEntry(uint8_t *Buf, uint64_t GotEntryAddr,
Rui Ueyamac58656c2015-10-13 16:59:30 +0000212 uint64_t PltEntryAddr) const {
213 // jmpq *val(%rip); nop; nop
214 const uint8_t Inst[] = {0xff, 0x25, 0, 0, 0, 0, 0x90, 0x90};
Rui Ueyama1500a902015-09-29 23:00:47 +0000215 memcpy(Buf, Inst, sizeof(Inst));
Rafael Espindola01205f72015-09-22 18:19:46 +0000216
Rui Ueyamac58656c2015-10-13 16:59:30 +0000217 uint64_t NextPC = PltEntryAddr + 6;
218 int64_t Delta = GotEntryAddr - NextPC;
219 assert(isInt<32>(Delta));
220 write32le(Buf + 2, Delta);
Rafael Espindola01205f72015-09-22 18:19:46 +0000221}
222
Rafael Espindola3ef3a4c2015-09-29 23:22:16 +0000223bool X86_64TargetInfo::relocNeedsGot(uint32_t Type, const SymbolBody &S) const {
Rui Ueyama5ba3ac42015-09-30 01:40:08 +0000224 return Type == R_X86_64_GOTPCREL || relocNeedsPlt(Type, S);
Rafael Espindola01205f72015-09-22 18:19:46 +0000225}
226
Rafael Espindola227556e2015-10-14 16:15:46 +0000227unsigned X86_64TargetInfo::getPLTRefReloc(unsigned Type) const {
228 switch (Type) {
229 case R_X86_64_32:
230 return R_X86_64_32;
231 case R_X86_64_PC32:
232 case R_X86_64_PLT32:
233 return R_X86_64_PC32;
234 }
235 llvm_unreachable("Unexpected relocation");
236}
237
Rafael Espindola3ef3a4c2015-09-29 23:22:16 +0000238bool X86_64TargetInfo::relocNeedsPlt(uint32_t Type, const SymbolBody &S) const {
Rafael Espindola01205f72015-09-22 18:19:46 +0000239 switch (Type) {
240 default:
241 return false;
Rafael Espindola227556e2015-10-14 16:15:46 +0000242 case R_X86_64_32:
Rafael Espindola3ef3a4c2015-09-29 23:22:16 +0000243 case R_X86_64_PC32:
244 // This relocation is defined to have a value of (S + A - P).
Rafael Espindola3c412e12015-09-30 12:30:58 +0000245 // The problems start when a non PIC program calls a function in a shared
Rafael Espindola3ef3a4c2015-09-29 23:22:16 +0000246 // library.
Rafael Espindola9a0db7c2015-09-29 23:23:53 +0000247 // In an ideal world, we could just report an error saying the relocation
Rafael Espindola3ef3a4c2015-09-29 23:22:16 +0000248 // can overflow at runtime.
Rafael Espindola3c412e12015-09-30 12:30:58 +0000249 // In the real world with glibc, crt1.o has a R_X86_64_PC32 pointing to
250 // libc.so.
251 //
252 // The general idea on how to handle such cases is to create a PLT entry
253 // and use that as the function value.
254 //
255 // For the static linking part, we just return true and everything else
256 // will use the the PLT entry as the address.
257 //
Rafael Espindola3ef3a4c2015-09-29 23:22:16 +0000258 // The remaining (unimplemented) problem is making sure pointer equality
Rafael Espindola3c412e12015-09-30 12:30:58 +0000259 // still works. We need the help of the dynamic linker for that. We
260 // let it know that we have a direct reference to a so symbol by creating
261 // an undefined symbol with a non zero st_value. Seeing that, the
Rafael Espindola3ef3a4c2015-09-29 23:22:16 +0000262 // dynamic linker resolves the symbol to the value of the symbol we created.
263 // This is true even for got entries, so pointer equality is maintained.
264 // To avoid an infinite loop, the only entry that points to the
Rafael Espindola3c412e12015-09-30 12:30:58 +0000265 // real function is a dedicated got entry used by the plt. That is
266 // identified by special relocation types (R_X86_64_JUMP_SLOT,
267 // R_386_JMP_SLOT, etc).
Rafael Espindola3ef3a4c2015-09-29 23:22:16 +0000268 return S.isShared();
Rafael Espindola01205f72015-09-22 18:19:46 +0000269 case R_X86_64_PLT32:
270 return true;
271 }
272}
Rafael Espindolac4010882015-09-22 20:54:08 +0000273
Rafael Espindolaae244002015-10-05 19:30:12 +0000274bool X86_64TargetInfo::isRelRelative(uint32_t Type) const {
275 switch (Type) {
276 default:
277 return false;
278 case R_X86_64_PC64:
279 case R_X86_64_PC32:
280 case R_X86_64_PC16:
281 case R_X86_64_PC8:
282 return true;
283 }
284}
285
Hal Finkel87bbd5f2015-10-12 21:19:18 +0000286void X86_64TargetInfo::relocateOne(uint8_t *Buf, uint8_t *BufEnd,
287 const void *RelP, uint32_t Type,
288 uint64_t BaseAddr, uint64_t SymVA) const {
Rafael Espindolac4010882015-09-22 20:54:08 +0000289 typedef ELFFile<ELF64LE>::Elf_Rela Elf_Rela;
290 auto &Rel = *reinterpret_cast<const Elf_Rela *>(RelP);
291
292 uint64_t Offset = Rel.r_offset;
Rui Ueyama87bc41b2015-10-06 18:54:43 +0000293 uint8_t *Loc = Buf + Offset;
Rafael Espindolac4010882015-09-22 20:54:08 +0000294 switch (Type) {
295 case R_X86_64_PC32:
Rafael Espindolacdfecff2015-09-23 20:08:25 +0000296 case R_X86_64_GOTPCREL:
Rui Ueyama87bc41b2015-10-06 18:54:43 +0000297 write32le(Loc, SymVA + Rel.r_addend - (BaseAddr + Offset));
Rafael Espindolac4010882015-09-22 20:54:08 +0000298 break;
299 case R_X86_64_64:
Rui Ueyama87bc41b2015-10-06 18:54:43 +0000300 write64le(Loc, SymVA + Rel.r_addend);
Rafael Espindolac4010882015-09-22 20:54:08 +0000301 break;
302 case R_X86_64_32: {
303 case R_X86_64_32S:
304 uint64_t VA = SymVA + Rel.r_addend;
305 if (Type == R_X86_64_32 && !isUInt<32>(VA))
306 error("R_X86_64_32 out of range");
307 else if (!isInt<32>(VA))
308 error("R_X86_64_32S out of range");
309
Rui Ueyama87bc41b2015-10-06 18:54:43 +0000310 write32le(Loc, VA);
Rafael Espindolac4010882015-09-22 20:54:08 +0000311 break;
312 }
313 default:
Rui Ueyama1c42afc2015-10-12 15:49:06 +0000314 error("unrecognized reloc " + Twine(Type));
Rafael Espindolac4010882015-09-22 20:54:08 +0000315 }
316}
317
Hal Finkel3c8cc672015-10-12 20:56:18 +0000318// Relocation masks following the #lo(value), #hi(value), #ha(value),
319// #higher(value), #highera(value), #highest(value), and #highesta(value)
320// macros defined in section 4.5.1. Relocation Types of the PPC-elf64abi
321// document.
322
323static uint16_t applyPPCLo(uint64_t V) { return V & 0xffff; }
324
325static uint16_t applyPPCHi(uint64_t V) { return (V >> 16) & 0xffff; }
326
327static uint16_t applyPPCHa(uint64_t V) { return ((V + 0x8000) >> 16) & 0xffff; }
328
329static uint16_t applyPPCHigher(uint64_t V) { return (V >> 32) & 0xffff; }
330
331static uint16_t applyPPCHighera(uint64_t V) {
332 return ((V + 0x8000) >> 32) & 0xffff;
333}
334
335static uint16_t applyPPCHighest(uint64_t V) { return V >> 48; }
336
337static uint16_t applyPPCHighesta(uint64_t V) { return (V + 0x8000) >> 48; }
338
Rafael Espindolac4010882015-09-22 20:54:08 +0000339PPC64TargetInfo::PPC64TargetInfo() {
Hal Finkel3c8cc672015-10-12 20:56:18 +0000340 PCRelReloc = R_PPC64_REL24;
341 GotReloc = R_PPC64_GLOB_DAT;
342 GotRefReloc = R_PPC64_REL64;
Hal Finkelbe0823d2015-10-12 20:58:52 +0000343 RelativeReloc = R_PPC64_RELATIVE;
Hal Finkel6c2a3b82015-10-08 21:51:31 +0000344 PltEntrySize = 32;
Hal Finkelc848b322015-10-12 19:34:29 +0000345
346 // We need 64K pages (at least under glibc/Linux, the loader won't
347 // set different permissions on a finer granularity than that).
Hal Finkele3c26262015-10-08 22:23:54 +0000348 PageSize = 65536;
Hal Finkel736c7412015-10-15 07:49:07 +0000349
350 // The PPC64 ELF ABI v1 spec, says:
351 //
352 // It is normally desirable to put segments with different characteristics
353 // in separate 256 Mbyte portions of the address space, to give the
354 // operating system full paging flexibility in the 64-bit address space.
355 //
356 // And because the lowest non-zero 256M boundary is 0x10000000, PPC64 linkers
357 // use 0x10000000 as the starting address.
358 VAStart = 0x10000000;
Rafael Espindolac4010882015-09-22 20:54:08 +0000359}
Hal Finkel3c8cc672015-10-12 20:56:18 +0000360
361static uint64_t getPPC64TocBase() {
362 // The TOC consists of sections .got, .toc, .tocbss, .plt in that
363 // order. The TOC starts where the first of these sections starts.
364
365 // FIXME: This obviously does not do the right thing when there is no .got
366 // section, but there is a .toc or .tocbss section.
367 uint64_t TocVA = Out<ELF64BE>::Got->getVA();
368 if (!TocVA)
369 TocVA = Out<ELF64BE>::Plt->getVA();
370
371 // Per the ppc64-elf-linux ABI, The TOC base is TOC value plus 0x8000
372 // thus permitting a full 64 Kbytes segment. Note that the glibc startup
373 // code (crt1.o) assumes that you can get from the TOC base to the
374 // start of the .toc section with only a single (signed) 16-bit relocation.
375 return TocVA + 0x8000;
376}
377
Rafael Espindolac4010882015-09-22 20:54:08 +0000378void PPC64TargetInfo::writePltEntry(uint8_t *Buf, uint64_t GotEntryAddr,
Rui Ueyamac58656c2015-10-13 16:59:30 +0000379 uint64_t PltEntryAddr) const {
Hal Finkel3c8cc672015-10-12 20:56:18 +0000380 uint64_t Off = GotEntryAddr - getPPC64TocBase();
381
382 // FIXME: What we should do, in theory, is get the offset of the function
383 // descriptor in the .opd section, and use that as the offset from %r2 (the
384 // TOC-base pointer). Instead, we have the GOT-entry offset, and that will
385 // be a pointer to the function descriptor in the .opd section. Using
386 // this scheme is simpler, but requires an extra indirection per PLT dispatch.
387
Hal Finkelfa92f682015-10-13 21:47:34 +0000388 write32be(Buf, 0xf8410028); // std %r2, 40(%r1)
Hal Finkel3c8cc672015-10-12 20:56:18 +0000389 write32be(Buf + 4, 0x3d620000 | applyPPCHa(Off)); // addis %r11, %r2, X@ha
390 write32be(Buf + 8, 0xe98b0000 | applyPPCLo(Off)); // ld %r12, X@l(%r11)
391 write32be(Buf + 12, 0xe96c0000); // ld %r11,0(%r12)
392 write32be(Buf + 16, 0x7d6903a6); // mtctr %r11
393 write32be(Buf + 20, 0xe84c0008); // ld %r2,8(%r12)
394 write32be(Buf + 24, 0xe96c0010); // ld %r11,16(%r12)
395 write32be(Buf + 28, 0x4e800420); // bctr
396}
397
Rafael Espindola3ef3a4c2015-09-29 23:22:16 +0000398bool PPC64TargetInfo::relocNeedsGot(uint32_t Type, const SymbolBody &S) const {
Hal Finkel3c8cc672015-10-12 20:56:18 +0000399 if (relocNeedsPlt(Type, S))
400 return true;
401
402 switch (Type) {
403 default: return false;
404 case R_PPC64_GOT16:
405 case R_PPC64_GOT16_LO:
406 case R_PPC64_GOT16_HI:
407 case R_PPC64_GOT16_HA:
408 case R_PPC64_GOT16_DS:
409 case R_PPC64_GOT16_LO_DS:
410 return true;
411 }
Rafael Espindola3ef3a4c2015-09-29 23:22:16 +0000412}
Hal Finkel3c8cc672015-10-12 20:56:18 +0000413
Rafael Espindola3ef3a4c2015-09-29 23:22:16 +0000414bool PPC64TargetInfo::relocNeedsPlt(uint32_t Type, const SymbolBody &S) const {
Hal Finkel3c8cc672015-10-12 20:56:18 +0000415 if (Type != R_PPC64_REL24)
416 return false;
417
418 // These are function calls that need to be redirected through a PLT stub.
Hal Finkelae3f05b2015-10-15 06:44:19 +0000419 return S.isShared();
Rafael Espindola3ef3a4c2015-09-29 23:22:16 +0000420}
Hal Finkel3c8cc672015-10-12 20:56:18 +0000421
Hal Finkelbe0823d2015-10-12 20:58:52 +0000422bool PPC64TargetInfo::isRelRelative(uint32_t Type) const {
423 switch (Type) {
424 default:
425 return false;
426 case R_PPC64_REL24:
427 case R_PPC64_REL14:
428 case R_PPC64_REL14_BRTAKEN:
429 case R_PPC64_REL14_BRNTAKEN:
430 case R_PPC64_REL32:
431 case R_PPC64_REL64:
432 return true;
433 }
434}
435
Hal Finkel87bbd5f2015-10-12 21:19:18 +0000436void PPC64TargetInfo::relocateOne(uint8_t *Buf, uint8_t *BufEnd,
437 const void *RelP, uint32_t Type,
Rui Ueyamaaf21d922015-10-08 20:06:07 +0000438 uint64_t BaseAddr, uint64_t SymVA) const {
Rafael Espindola3efa4e92015-09-22 21:12:55 +0000439 typedef ELFFile<ELF64BE>::Elf_Rela Elf_Rela;
440 auto &Rel = *reinterpret_cast<const Elf_Rela *>(RelP);
441
Hal Finkel3c8cc672015-10-12 20:56:18 +0000442 uint8_t *L = Buf + Rel.r_offset;
443 uint64_t S = SymVA;
444 int64_t A = Rel.r_addend;
445 uint64_t P = BaseAddr + Rel.r_offset;
446 uint64_t TB = getPPC64TocBase();
447
448 if (Type == R_PPC64_TOC) {
449 write64be(L, TB);
450 return;
451 }
452
453 // For a TOC-relative relocation, adjust the addend and proceed in terms of
454 // the corresponding ADDR16 relocation type.
Rafael Espindola3efa4e92015-09-22 21:12:55 +0000455 switch (Type) {
Hal Finkel3c8cc672015-10-12 20:56:18 +0000456 case R_PPC64_TOC16: Type = R_PPC64_ADDR16; A -= TB; break;
457 case R_PPC64_TOC16_DS: Type = R_PPC64_ADDR16_DS; A -= TB; break;
458 case R_PPC64_TOC16_LO: Type = R_PPC64_ADDR16_LO; A -= TB; break;
459 case R_PPC64_TOC16_LO_DS: Type = R_PPC64_ADDR16_LO_DS; A -= TB; break;
460 case R_PPC64_TOC16_HI: Type = R_PPC64_ADDR16_HI; A -= TB; break;
461 case R_PPC64_TOC16_HA: Type = R_PPC64_ADDR16_HA; A -= TB; break;
462 default: break;
463 }
464
465 uint64_t R = S + A;
466
467 switch (Type) {
468 case R_PPC64_ADDR16:
469 write16be(L, applyPPCLo(R));
Rafael Espindola3efa4e92015-09-22 21:12:55 +0000470 break;
Hal Finkel3c8cc672015-10-12 20:56:18 +0000471 case R_PPC64_ADDR16_DS:
472 if (!isInt<16>(R))
473 error("Relocation R_PPC64_ADDR16_DS overflow");
474 write16be(L, (read16be(L) & 3) | (R & ~3));
475 break;
476 case R_PPC64_ADDR16_LO:
477 write16be(L, applyPPCLo(R));
478 break;
479 case R_PPC64_ADDR16_LO_DS:
480 write16be(L, (read16be(L) & 3) | (applyPPCLo(R) & ~3));
481 break;
482 case R_PPC64_ADDR16_HI:
483 write16be(L, applyPPCHi(R));
484 break;
485 case R_PPC64_ADDR16_HA:
486 write16be(L, applyPPCHa(R));
487 break;
488 case R_PPC64_ADDR16_HIGHER:
489 write16be(L, applyPPCHigher(R));
490 break;
491 case R_PPC64_ADDR16_HIGHERA:
492 write16be(L, applyPPCHighera(R));
493 break;
494 case R_PPC64_ADDR16_HIGHEST:
495 write16be(L, applyPPCHighest(R));
496 break;
497 case R_PPC64_ADDR16_HIGHESTA:
498 write16be(L, applyPPCHighesta(R));
499 break;
500 case R_PPC64_ADDR14: {
501 if ((R & 3) != 0)
502 error("Improper alignment for relocation R_PPC64_ADDR14");
503
504 // Preserve the AA/LK bits in the branch instruction
505 uint8_t AALK = L[3];
506 write16be(L + 2, (AALK & 3) | (R & 0xfffc));
507 break;
508 }
509 case R_PPC64_REL16_LO:
510 write16be(L, applyPPCLo(R - P));
511 break;
512 case R_PPC64_REL16_HI:
513 write16be(L, applyPPCHi(R - P));
514 break;
515 case R_PPC64_REL16_HA:
516 write16be(L, applyPPCHa(R - P));
517 break;
518 case R_PPC64_ADDR32:
519 if (!isInt<32>(R))
520 error("Relocation R_PPC64_ADDR32 overflow");
521 write32be(L, R);
522 break;
523 case R_PPC64_REL24: {
Hal Finkeldaedc122015-10-12 23:16:53 +0000524 uint64_t PltStart = Out<ELF64BE>::Plt->getVA();
525 uint64_t PltEnd = PltStart + Out<ELF64BE>::Plt->getSize();
Hal Finkel4e961dd2015-10-13 22:54:24 +0000526 bool InPlt = PltStart <= R && R < PltEnd;
Hal Finkeldaedc122015-10-12 23:16:53 +0000527
528 if (!InPlt && Out<ELF64BE>::Opd) {
529 // If this is a local call, and we currently have the address of a
530 // function-descriptor, get the underlying code address instead.
531 uint64_t OpdStart = Out<ELF64BE>::Opd->getVA();
532 uint64_t OpdEnd = OpdStart + Out<ELF64BE>::Opd->getSize();
Hal Finkel4e961dd2015-10-13 22:54:24 +0000533 bool InOpd = OpdStart <= R && R < OpdEnd;
Hal Finkeldaedc122015-10-12 23:16:53 +0000534
535 if (InOpd)
Hal Finkel4e961dd2015-10-13 22:54:24 +0000536 R = read64be(&Out<ELF64BE>::OpdBuf[R - OpdStart]);
Hal Finkeldaedc122015-10-12 23:16:53 +0000537 }
538
Hal Finkel3c8cc672015-10-12 20:56:18 +0000539 uint32_t Mask = 0x03FFFFFC;
540 if (!isInt<24>(R - P))
541 error("Relocation R_PPC64_REL24 overflow");
542 write32be(L, (read32be(L) & ~Mask) | ((R - P) & Mask));
Hal Finkel87bbd5f2015-10-12 21:19:18 +0000543
Hal Finkel515ed442015-10-13 20:31:33 +0000544 if (InPlt && L + 8 <= BufEnd &&
Hal Finkel87bbd5f2015-10-12 21:19:18 +0000545 read32be(L + 4) == 0x60000000 /* nop */)
546 write32be(L + 4, 0xe8410028); // ld %r2, 40(%r1)
Hal Finkel3c8cc672015-10-12 20:56:18 +0000547 break;
548 }
549 case R_PPC64_REL32:
550 if (!isInt<32>(R - P))
551 error("Relocation R_PPC64_REL32 overflow");
552 write32be(L, R - P);
553 break;
554 case R_PPC64_REL64:
555 write64be(L, R - P);
556 break;
557 case R_PPC64_ADDR64:
558 write64be(L, R);
Rafael Espindola3efa4e92015-09-22 21:12:55 +0000559 break;
560 default:
Rui Ueyama1c42afc2015-10-12 15:49:06 +0000561 error("unrecognized reloc " + Twine(Type));
Rafael Espindola3efa4e92015-09-22 21:12:55 +0000562 }
563}
Rafael Espindola1d6063e2015-09-22 21:24:52 +0000564
565PPCTargetInfo::PPCTargetInfo() {
566 // PCRelReloc = FIXME
Rafael Espindola7f074422015-09-22 21:35:51 +0000567 // GotReloc = FIXME
Hal Finkele3c26262015-10-08 22:23:54 +0000568 PageSize = 65536;
Rafael Espindola1d6063e2015-09-22 21:24:52 +0000569}
570void PPCTargetInfo::writePltEntry(uint8_t *Buf, uint64_t GotEntryAddr,
Rui Ueyamac58656c2015-10-13 16:59:30 +0000571 uint64_t PltEntryAddr) const {}
Rafael Espindola3ef3a4c2015-09-29 23:22:16 +0000572bool PPCTargetInfo::relocNeedsGot(uint32_t Type, const SymbolBody &S) const {
573 return false;
574}
575bool PPCTargetInfo::relocNeedsPlt(uint32_t Type, const SymbolBody &S) const {
576 return false;
577}
Hal Finkel87bbd5f2015-10-12 21:19:18 +0000578void PPCTargetInfo::relocateOne(uint8_t *Buf, uint8_t *BufEnd,
579 const void *RelP, uint32_t Type,
Rui Ueyamaaf21d922015-10-08 20:06:07 +0000580 uint64_t BaseAddr, uint64_t SymVA) const {}
Rafael Espindola1d6063e2015-09-22 21:24:52 +0000581
Davide Italianocde93362015-09-26 00:32:04 +0000582AArch64TargetInfo::AArch64TargetInfo() {
583 // PCRelReloc = FIXME
584 // GotReloc = FIXME
585}
586void AArch64TargetInfo::writePltEntry(uint8_t *Buf, uint64_t GotEntryAddr,
Rui Ueyamac58656c2015-10-13 16:59:30 +0000587 uint64_t PltEntryAddr) const {}
Rafael Espindola3ef3a4c2015-09-29 23:22:16 +0000588bool AArch64TargetInfo::relocNeedsGot(uint32_t Type,
589 const SymbolBody &S) const {
590 return false;
591}
592bool AArch64TargetInfo::relocNeedsPlt(uint32_t Type,
593 const SymbolBody &S) const {
594 return false;
595}
Davide Italiano1d750a62015-09-27 08:45:38 +0000596
Davide Italianoef4be6b2015-10-06 19:01:32 +0000597static void updateAArch64Adr(uint8_t *L, uint64_t Imm) {
Davide Italiano1f31a2c2015-10-02 22:00:42 +0000598 uint32_t ImmLo = (Imm & 0x3) << 29;
599 uint32_t ImmHi = ((Imm & 0x1FFFFC) >> 2) << 5;
600 uint64_t Mask = (0x3 << 29) | (0x7FFFF << 5);
Rui Ueyama87bc41b2015-10-06 18:54:43 +0000601 write32le(L, (read32le(L) & ~Mask) | ImmLo | ImmHi);
Davide Italiano1f31a2c2015-10-02 22:00:42 +0000602}
603
Davide Italiano318ca222015-10-02 22:13:51 +0000604// Page(Expr) is the page address of the expression Expr, defined
605// as (Expr & ~0xFFF). (This applies even if the machine page size
Davide Italianod9b5be42015-10-02 22:17:09 +0000606// supported by the platform has a different value.)
Davide Italianoef4be6b2015-10-06 19:01:32 +0000607static uint64_t getAArch64Page(uint64_t Expr) {
Davide Italiano318ca222015-10-02 22:13:51 +0000608 return Expr & (~static_cast<uint64_t>(0xFFF));
Davide Italiano1f31a2c2015-10-02 22:00:42 +0000609}
610
Hal Finkel87bbd5f2015-10-12 21:19:18 +0000611void AArch64TargetInfo::relocateOne(uint8_t *Buf, uint8_t *BufEnd,
612 const void *RelP, uint32_t Type,
613 uint64_t BaseAddr, uint64_t SymVA) const {
Davide Italiano1d750a62015-09-27 08:45:38 +0000614 typedef ELFFile<ELF64LE>::Elf_Rela Elf_Rela;
615 auto &Rel = *reinterpret_cast<const Elf_Rela *>(RelP);
616
Rui Ueyamaee8c53b2015-10-06 19:57:01 +0000617 uint8_t *L = Buf + Rel.r_offset;
Davide Italiano1d750a62015-09-27 08:45:38 +0000618 uint64_t S = SymVA;
619 int64_t A = Rel.r_addend;
620 uint64_t P = BaseAddr + Rel.r_offset;
621 switch (Type) {
Davide Italianodf88f962015-10-04 00:59:16 +0000622 case R_AARCH64_ABS16:
Rui Ueyamaee8c53b2015-10-06 19:57:01 +0000623 if (!isInt<16>(S + A))
624 error("Relocation R_AARCH64_ABS16 out of range");
Davide Italiano06d84322015-10-07 22:10:02 +0000625 write16le(L, S + A);
Davide Italianodf88f962015-10-04 00:59:16 +0000626 break;
627 case R_AARCH64_ABS32:
Rui Ueyamaee8c53b2015-10-06 19:57:01 +0000628 if (!isInt<32>(S + A))
629 error("Relocation R_AARCH64_ABS32 out of range");
Davide Italiano06d84322015-10-07 22:10:02 +0000630 write32le(L, S + A);
Davide Italianodf88f962015-10-04 00:59:16 +0000631 break;
632 case R_AARCH64_ABS64:
Rui Ueyamaee8c53b2015-10-06 19:57:01 +0000633 // No overflow check needed.
Davide Italiano06d84322015-10-07 22:10:02 +0000634 write64le(L, S + A);
Davide Italianodf88f962015-10-04 00:59:16 +0000635 break;
Davide Italiano0b6974b2015-10-03 19:56:07 +0000636 case R_AARCH64_ADD_ABS_LO12_NC:
Rui Ueyamaee8c53b2015-10-06 19:57:01 +0000637 // No overflow check needed.
638 or32le(L, ((S + A) & 0xFFF) << 10);
Davide Italiano0b6974b2015-10-03 19:56:07 +0000639 break;
Rui Ueyamaee8c53b2015-10-06 19:57:01 +0000640 case R_AARCH64_ADR_PREL_LO21: {
641 uint64_t X = S + A - P;
642 if (!isInt<21>(X))
643 error("Relocation R_AARCH64_ADR_PREL_LO21 out of range");
644 updateAArch64Adr(L, X & 0x1FFFFF);
Davide Italiano1d750a62015-09-27 08:45:38 +0000645 break;
Rui Ueyamaee8c53b2015-10-06 19:57:01 +0000646 }
647 case R_AARCH64_ADR_PREL_PG_HI21: {
648 uint64_t X = getAArch64Page(S + A) - getAArch64Page(P);
649 if (!isInt<33>(X))
650 error("Relocation R_AARCH64_ADR_PREL_PG_HI21 out of range");
651 updateAArch64Adr(L, (X >> 12) & 0x1FFFFF); // X[32:12]
Davide Italiano1f31a2c2015-10-02 22:00:42 +0000652 break;
Rui Ueyamaee8c53b2015-10-06 19:57:01 +0000653 }
Davide Italiano1d750a62015-09-27 08:45:38 +0000654 default:
Rui Ueyama1c42afc2015-10-12 15:49:06 +0000655 error("unrecognized reloc " + Twine(Type));
Davide Italiano1d750a62015-09-27 08:45:38 +0000656 }
657}
Simon Atanasyan49829a12015-09-29 05:34:03 +0000658
Simon Atanasyan9c2d7882015-10-14 14:24:46 +0000659template <class ELFT> MipsTargetInfo<ELFT>::MipsTargetInfo() {
Simon Atanasyan49829a12015-09-29 05:34:03 +0000660 // PCRelReloc = FIXME
661 // GotReloc = FIXME
Hal Finkele3c26262015-10-08 22:23:54 +0000662 PageSize = 65536;
Simon Atanasyan49829a12015-09-29 05:34:03 +0000663}
664
Simon Atanasyan9c2d7882015-10-14 14:24:46 +0000665template <class ELFT>
666void MipsTargetInfo<ELFT>::writePltEntry(uint8_t *Buf, uint64_t GotEntryAddr,
667 uint64_t PltEntryAddr) const {}
Simon Atanasyan49829a12015-09-29 05:34:03 +0000668
Simon Atanasyan9c2d7882015-10-14 14:24:46 +0000669template <class ELFT>
670bool MipsTargetInfo<ELFT>::relocNeedsGot(uint32_t Type,
671 const SymbolBody &S) const {
Rafael Espindola3ef3a4c2015-09-29 23:22:16 +0000672 return false;
673}
Simon Atanasyan49829a12015-09-29 05:34:03 +0000674
Simon Atanasyan9c2d7882015-10-14 14:24:46 +0000675template <class ELFT>
676bool MipsTargetInfo<ELFT>::relocNeedsPlt(uint32_t Type,
677 const SymbolBody &S) const {
Rafael Espindola3ef3a4c2015-09-29 23:22:16 +0000678 return false;
679}
Simon Atanasyan49829a12015-09-29 05:34:03 +0000680
Simon Atanasyan9c2d7882015-10-14 14:24:46 +0000681template <class ELFT>
682void MipsTargetInfo<ELFT>::relocateOne(uint8_t *Buf, uint8_t *BufEnd,
683 const void *RelP, uint32_t Type,
684 uint64_t BaseAddr,
685 uint64_t SymVA) const {
686 const bool IsLE = ELFT::TargetEndianness == support::little;
687 typedef typename ELFFile<ELFT>::Elf_Rel Elf_Rel;
Simon Atanasyan3b732ac2015-10-12 15:10:02 +0000688 auto &Rel = *reinterpret_cast<const Elf_Rel *>(RelP);
689
690 switch (Type) {
691 case R_MIPS_32:
Simon Atanasyan9c2d7882015-10-14 14:24:46 +0000692 add32<IsLE>(Buf + Rel.r_offset, SymVA);
Simon Atanasyan3b732ac2015-10-12 15:10:02 +0000693 break;
694 default:
Rui Ueyama1c42afc2015-10-12 15:49:06 +0000695 error("unrecognized reloc " + Twine(Type));
Simon Atanasyan3b732ac2015-10-12 15:10:02 +0000696 }
697}
Rafael Espindola01205f72015-09-22 18:19:46 +0000698}
699}