xref: /llvm-project-15.0.7/lld/ELF/Target.cpp (revision 09178283)
1 //===- 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 //===----------------------------------------------------------------------===//
9 //
10 // 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.
15 //
16 //===----------------------------------------------------------------------===//
17 
18 #include "Target.h"
19 #include "Error.h"
20 #include "OutputSections.h"
21 #include "Symbols.h"
22 
23 #include "llvm/ADT/ArrayRef.h"
24 #include "llvm/Object/ELF.h"
25 #include "llvm/Support/Endian.h"
26 #include "llvm/Support/ELF.h"
27 
28 using namespace llvm;
29 using namespace llvm::object;
30 using namespace llvm::support::endian;
31 using namespace llvm::ELF;
32 
33 namespace lld {
34 namespace elf2 {
35 
36 std::unique_ptr<TargetInfo> Target;
37 
38 static void add32le(uint8_t *L, int32_t V) { write32le(L, read32le(L) + V); }
39 static void add32be(uint8_t *L, int32_t V) { write32be(L, read32be(L) + V); }
40 static void or32le(uint8_t *L, int32_t V) { write32le(L, read32le(L) | V); }
41 
42 template <bool IsLE> static void add32(uint8_t *L, int32_t V);
43 template <> void add32<true>(uint8_t *L, int32_t V) { add32le(L, V); }
44 template <> void add32<false>(uint8_t *L, int32_t V) { add32be(L, V); }
45 
46 namespace {
47 class X86TargetInfo final : public TargetInfo {
48 public:
49   X86TargetInfo();
50   void writePltEntry(uint8_t *Buf, uint64_t GotEntryAddr,
51                      uint64_t PltEntryAddr) const override;
52   bool relocNeedsGot(uint32_t Type, const SymbolBody &S) const override;
53   bool relocPointsToGot(uint32_t Type) const override;
54   bool relocNeedsPlt(uint32_t Type, const SymbolBody &S) const override;
55   void relocateOne(uint8_t *Buf, uint8_t *BufEnd, const void *RelP,
56                    uint32_t Type, uint64_t BaseAddr,
57                    uint64_t SA) const override;
58 };
59 
60 class X86_64TargetInfo final : public TargetInfo {
61 public:
62   X86_64TargetInfo();
63   unsigned getPLTRefReloc(unsigned Type) const override;
64   void writePltEntry(uint8_t *Buf, uint64_t GotEntryAddr,
65                      uint64_t PltEntryAddr) const override;
66   bool relocNeedsGot(uint32_t Type, const SymbolBody &S) const override;
67   bool relocNeedsPlt(uint32_t Type, const SymbolBody &S) const override;
68   void relocateOne(uint8_t *Buf, uint8_t *BufEnd, const void *RelP,
69                    uint32_t Type, uint64_t BaseAddr,
70                    uint64_t SA) const override;
71   bool isRelRelative(uint32_t Type) const override;
72 };
73 
74 class PPC64TargetInfo final : public TargetInfo {
75 public:
76   PPC64TargetInfo();
77   void writePltEntry(uint8_t *Buf, uint64_t GotEntryAddr,
78                      uint64_t PltEntryAddr) const override;
79   bool relocNeedsGot(uint32_t Type, const SymbolBody &S) const override;
80   bool relocNeedsPlt(uint32_t Type, const SymbolBody &S) const override;
81   void relocateOne(uint8_t *Buf, uint8_t *BufEnd, const void *RelP,
82                    uint32_t Type, uint64_t BaseAddr,
83                    uint64_t SA) const override;
84   bool isRelRelative(uint32_t Type) const override;
85 };
86 
87 class PPCTargetInfo final : public TargetInfo {
88 public:
89   PPCTargetInfo();
90   void writePltEntry(uint8_t *Buf, uint64_t GotEntryAddr,
91                      uint64_t PltEntryAddr) const override;
92   bool relocNeedsGot(uint32_t Type, const SymbolBody &S) const override;
93   bool relocNeedsPlt(uint32_t Type, const SymbolBody &S) const override;
94   void relocateOne(uint8_t *Buf, uint8_t *BufEnd, const void *RelP,
95                    uint32_t Type, uint64_t BaseAddr,
96                    uint64_t SA) const override;
97 };
98 
99 class AArch64TargetInfo final : public TargetInfo {
100 public:
101   AArch64TargetInfo();
102   void writePltEntry(uint8_t *Buf, uint64_t GotEntryAddr,
103                      uint64_t PltEntryAddr) const override;
104   bool relocNeedsGot(uint32_t Type, const SymbolBody &S) const override;
105   bool relocNeedsPlt(uint32_t Type, const SymbolBody &S) const override;
106   void relocateOne(uint8_t *Buf, uint8_t *BufEnd, const void *RelP,
107                    uint32_t Type, uint64_t BaseAddr,
108                    uint64_t SA) const override;
109 };
110 
111 template <class ELFT> class MipsTargetInfo final : public TargetInfo {
112 public:
113   MipsTargetInfo();
114   void writePltEntry(uint8_t *Buf, uint64_t GotEntryAddr,
115                      uint64_t PltEntryAddr) const override;
116   bool relocNeedsGot(uint32_t Type, const SymbolBody &S) const override;
117   bool relocNeedsPlt(uint32_t Type, const SymbolBody &S) const override;
118   void relocateOne(uint8_t *Buf, uint8_t *BufEnd, const void *RelP,
119                    uint32_t Type, uint64_t BaseAddr,
120                    uint64_t SA) const override;
121 };
122 } // anonymous namespace
123 
124 TargetInfo *createTarget() {
125   switch (Config->EMachine) {
126   case EM_386:
127     return new X86TargetInfo();
128   case EM_AARCH64:
129     return new AArch64TargetInfo();
130   case EM_MIPS:
131     switch (Config->EKind) {
132     case ELF32LEKind:
133       return new MipsTargetInfo<ELF32LE>();
134     case ELF32BEKind:
135       return new MipsTargetInfo<ELF32BE>();
136     default:
137       error("Unsupported MIPS target");
138     }
139   case EM_PPC:
140     return new PPCTargetInfo();
141   case EM_PPC64:
142     return new PPC64TargetInfo();
143   case EM_X86_64:
144     return new X86_64TargetInfo();
145   }
146   error("Unknown target machine");
147 }
148 
149 TargetInfo::~TargetInfo() {}
150 
151 unsigned TargetInfo::getPLTRefReloc(unsigned Type) const { return PCRelReloc; }
152 
153 bool TargetInfo::relocPointsToGot(uint32_t Type) const { return false; }
154 
155 bool TargetInfo::isRelRelative(uint32_t Type) const { return true; }
156 
157 X86TargetInfo::X86TargetInfo() {
158   PCRelReloc = R_386_PC32;
159   GotReloc = R_386_GLOB_DAT;
160   GotRefReloc = R_386_GOT32;
161 }
162 
163 void X86TargetInfo::writePltEntry(uint8_t *Buf, uint64_t GotEntryAddr,
164                                   uint64_t PltEntryAddr) const {
165   // jmpl *val; nop; nop
166   const uint8_t Inst[] = {0xff, 0x25, 0, 0, 0, 0, 0x90, 0x90};
167   memcpy(Buf, Inst, sizeof(Inst));
168   assert(isUInt<32>(GotEntryAddr));
169   write32le(Buf + 2, GotEntryAddr);
170 }
171 
172 bool X86TargetInfo::relocNeedsGot(uint32_t Type, const SymbolBody &S) const {
173   return Type == R_386_GOT32 || relocNeedsPlt(Type, S);
174 }
175 
176 bool X86TargetInfo::relocPointsToGot(uint32_t Type) const {
177   return Type == R_386_GOTPC;
178 }
179 
180 bool X86TargetInfo::relocNeedsPlt(uint32_t Type, const SymbolBody &S) const {
181   return Type == R_386_PLT32 || (Type == R_386_PC32 && S.isShared());
182 }
183 
184 void X86TargetInfo::relocateOne(uint8_t *Buf, uint8_t *BufEnd, const void *RelP,
185                                 uint32_t Type, uint64_t BaseAddr,
186                                 uint64_t SA) const {
187   typedef ELFFile<ELF32LE>::Elf_Rel Elf_Rel;
188   auto &Rel = *reinterpret_cast<const Elf_Rel *>(RelP);
189 
190   uint32_t Offset = Rel.r_offset;
191   uint8_t *Loc = Buf + Offset;
192   switch (Type) {
193   case R_386_GOT32:
194     add32le(Loc, SA - Out<ELF32LE>::Got->getVA());
195     break;
196   case R_386_PC32:
197     add32le(Loc, SA - BaseAddr - Offset);
198     break;
199   case R_386_32:
200     add32le(Loc, SA);
201     break;
202   default:
203     error("unrecognized reloc " + Twine(Type));
204   }
205 }
206 
207 X86_64TargetInfo::X86_64TargetInfo() {
208   PCRelReloc = R_X86_64_PC32;
209   GotReloc = R_X86_64_GLOB_DAT;
210   GotRefReloc = R_X86_64_PC32;
211   RelativeReloc = R_X86_64_RELATIVE;
212 }
213 
214 void X86_64TargetInfo::writePltEntry(uint8_t *Buf, uint64_t GotEntryAddr,
215                                      uint64_t PltEntryAddr) const {
216   // jmpq *val(%rip); nop; nop
217   const uint8_t Inst[] = {0xff, 0x25, 0, 0, 0, 0, 0x90, 0x90};
218   memcpy(Buf, Inst, sizeof(Inst));
219 
220   uint64_t NextPC = PltEntryAddr + 6;
221   int64_t Delta = GotEntryAddr - NextPC;
222   assert(isInt<32>(Delta));
223   write32le(Buf + 2, Delta);
224 }
225 
226 bool X86_64TargetInfo::relocNeedsGot(uint32_t Type, const SymbolBody &S) const {
227   return Type == R_X86_64_GOTPCREL || relocNeedsPlt(Type, S);
228 }
229 
230 unsigned X86_64TargetInfo::getPLTRefReloc(unsigned Type) const {
231   switch (Type) {
232   case R_X86_64_32:
233     return R_X86_64_32;
234   case R_X86_64_PC32:
235   case R_X86_64_PLT32:
236     return R_X86_64_PC32;
237   }
238   llvm_unreachable("Unexpected relocation");
239 }
240 
241 bool X86_64TargetInfo::relocNeedsPlt(uint32_t Type, const SymbolBody &S) const {
242   switch (Type) {
243   default:
244     return false;
245   case R_X86_64_32:
246   case R_X86_64_PC32:
247     // This relocation is defined to have a value of (S + A - P).
248     // The problems start when a non PIC program calls a function in a shared
249     // library.
250     // In an ideal world, we could just report an error saying the relocation
251     // can overflow at runtime.
252     // In the real world with glibc, crt1.o has a R_X86_64_PC32 pointing to
253     // libc.so.
254     //
255     // The general idea on how to handle such cases is to create a PLT entry
256     // and use that as the function value.
257     //
258     // For the static linking part, we just return true and everything else
259     // will use the the PLT entry as the address.
260     //
261     // The remaining (unimplemented) problem is making sure pointer equality
262     // still works. We need the help of the dynamic linker for that. We
263     // let it know that we have a direct reference to a so symbol by creating
264     // an undefined symbol with a non zero st_value. Seeing that, the
265     // dynamic linker resolves the symbol to the value of the symbol we created.
266     // This is true even for got entries, so pointer equality is maintained.
267     // To avoid an infinite loop, the only entry that points to the
268     // real function is a dedicated got entry used by the plt. That is
269     // identified by special relocation types (R_X86_64_JUMP_SLOT,
270     // R_386_JMP_SLOT, etc).
271     return S.isShared();
272   case R_X86_64_PLT32:
273     return true;
274   }
275 }
276 
277 bool X86_64TargetInfo::isRelRelative(uint32_t Type) const {
278   switch (Type) {
279   default:
280     return false;
281   case R_X86_64_PC64:
282   case R_X86_64_PC32:
283   case R_X86_64_PC16:
284   case R_X86_64_PC8:
285     return true;
286   }
287 }
288 
289 void X86_64TargetInfo::relocateOne(uint8_t *Buf, uint8_t *BufEnd,
290                                    const void *RelP, uint32_t Type,
291                                    uint64_t BaseAddr, uint64_t SA) const {
292   typedef ELFFile<ELF64LE>::Elf_Rela Elf_Rela;
293   auto &Rel = *reinterpret_cast<const Elf_Rela *>(RelP);
294 
295   uint64_t Offset = Rel.r_offset;
296   uint8_t *Loc = Buf + Offset;
297   switch (Type) {
298   case R_X86_64_PC32:
299   case R_X86_64_GOTPCREL:
300     write32le(Loc, SA - BaseAddr - Offset);
301     break;
302   case R_X86_64_64:
303     write64le(Loc, SA);
304     break;
305   case R_X86_64_32: {
306   case R_X86_64_32S:
307     if (Type == R_X86_64_32 && !isUInt<32>(SA))
308       error("R_X86_64_32 out of range");
309     else if (!isInt<32>(SA))
310       error("R_X86_64_32S out of range");
311     write32le(Loc, SA);
312     break;
313   }
314   default:
315     error("unrecognized reloc " + Twine(Type));
316   }
317 }
318 
319 // Relocation masks following the #lo(value), #hi(value), #ha(value),
320 // #higher(value), #highera(value), #highest(value), and #highesta(value)
321 // macros defined in section 4.5.1. Relocation Types of the PPC-elf64abi
322 // document.
323 
324 static uint16_t applyPPCLo(uint64_t V) { return V & 0xffff; }
325 
326 static uint16_t applyPPCHi(uint64_t V) { return (V >> 16) & 0xffff; }
327 
328 static uint16_t applyPPCHa(uint64_t V) { return ((V + 0x8000) >> 16) & 0xffff; }
329 
330 static uint16_t applyPPCHigher(uint64_t V) { return (V >> 32) & 0xffff; }
331 
332 static uint16_t applyPPCHighera(uint64_t V) {
333   return ((V + 0x8000) >> 32) & 0xffff;
334 }
335 
336 static uint16_t applyPPCHighest(uint64_t V) { return V >> 48; }
337 
338 static uint16_t applyPPCHighesta(uint64_t V) { return (V + 0x8000) >> 48; }
339 
340 PPC64TargetInfo::PPC64TargetInfo() {
341   PCRelReloc = R_PPC64_REL24;
342   GotReloc = R_PPC64_GLOB_DAT;
343   GotRefReloc = R_PPC64_REL64;
344   RelativeReloc = R_PPC64_RELATIVE;
345   PltEntrySize = 32;
346 
347   // We need 64K pages (at least under glibc/Linux, the loader won't
348   // set different permissions on a finer granularity than that).
349   PageSize = 65536;
350 
351   // The PPC64 ELF ABI v1 spec, says:
352   //
353   //   It is normally desirable to put segments with different characteristics
354   //   in separate 256 Mbyte portions of the address space, to give the
355   //   operating system full paging flexibility in the 64-bit address space.
356   //
357   // And because the lowest non-zero 256M boundary is 0x10000000, PPC64 linkers
358   // use 0x10000000 as the starting address.
359   VAStart = 0x10000000;
360 }
361 
362 static uint64_t getPPC64TocBase() {
363   // The TOC consists of sections .got, .toc, .tocbss, .plt in that
364   // order. The TOC starts where the first of these sections starts.
365 
366   // FIXME: This obviously does not do the right thing when there is no .got
367   // section, but there is a .toc or .tocbss section.
368   uint64_t TocVA = Out<ELF64BE>::Got->getVA();
369   if (!TocVA)
370     TocVA = Out<ELF64BE>::Plt->getVA();
371 
372   // Per the ppc64-elf-linux ABI, The TOC base is TOC value plus 0x8000
373   // thus permitting a full 64 Kbytes segment. Note that the glibc startup
374   // code (crt1.o) assumes that you can get from the TOC base to the
375   // start of the .toc section with only a single (signed) 16-bit relocation.
376   return TocVA + 0x8000;
377 }
378 
379 void PPC64TargetInfo::writePltEntry(uint8_t *Buf, uint64_t GotEntryAddr,
380                                     uint64_t PltEntryAddr) const {
381   uint64_t Off = GotEntryAddr - getPPC64TocBase();
382 
383   // FIXME: What we should do, in theory, is get the offset of the function
384   // descriptor in the .opd section, and use that as the offset from %r2 (the
385   // TOC-base pointer). Instead, we have the GOT-entry offset, and that will
386   // be a pointer to the function descriptor in the .opd section. Using
387   // this scheme is simpler, but requires an extra indirection per PLT dispatch.
388 
389   write32be(Buf,      0xf8410028);                   // std %r2, 40(%r1)
390   write32be(Buf + 4,  0x3d620000 | applyPPCHa(Off)); // addis %r11, %r2, X@ha
391   write32be(Buf + 8,  0xe98b0000 | applyPPCLo(Off)); // ld %r12, X@l(%r11)
392   write32be(Buf + 12, 0xe96c0000);                   // ld %r11,0(%r12)
393   write32be(Buf + 16, 0x7d6903a6);                   // mtctr %r11
394   write32be(Buf + 20, 0xe84c0008);                   // ld %r2,8(%r12)
395   write32be(Buf + 24, 0xe96c0010);                   // ld %r11,16(%r12)
396   write32be(Buf + 28, 0x4e800420);                   // bctr
397 }
398 
399 bool PPC64TargetInfo::relocNeedsGot(uint32_t Type, const SymbolBody &S) const {
400   if (relocNeedsPlt(Type, S))
401     return true;
402 
403   switch (Type) {
404   default: return false;
405   case R_PPC64_GOT16:
406   case R_PPC64_GOT16_LO:
407   case R_PPC64_GOT16_HI:
408   case R_PPC64_GOT16_HA:
409   case R_PPC64_GOT16_DS:
410   case R_PPC64_GOT16_LO_DS:
411     return true;
412   }
413 }
414 
415 bool PPC64TargetInfo::relocNeedsPlt(uint32_t Type, const SymbolBody &S) const {
416   if (Type != R_PPC64_REL24)
417     return false;
418 
419   // These are function calls that need to be redirected through a PLT stub.
420   return S.isShared() || (S.isUndefined() && S.isWeak());
421 }
422 
423 bool PPC64TargetInfo::isRelRelative(uint32_t Type) const {
424   switch (Type) {
425   default:
426     return false;
427   case R_PPC64_REL24:
428   case R_PPC64_REL14:
429   case R_PPC64_REL14_BRTAKEN:
430   case R_PPC64_REL14_BRNTAKEN:
431   case R_PPC64_REL32:
432   case R_PPC64_REL64:
433     return true;
434   }
435 }
436 
437 void PPC64TargetInfo::relocateOne(uint8_t *Buf, uint8_t *BufEnd,
438                                   const void *RelP, uint32_t Type,
439                                   uint64_t BaseAddr, uint64_t SA) const {
440   typedef ELFFile<ELF64BE>::Elf_Rela Elf_Rela;
441   auto &Rel = *reinterpret_cast<const Elf_Rela *>(RelP);
442 
443   uint8_t *L = Buf + Rel.r_offset;
444   uint64_t P = BaseAddr + Rel.r_offset;
445   uint64_t TB = getPPC64TocBase();
446 
447   if (Type == R_PPC64_TOC) {
448     write64be(L, TB);
449     return;
450   }
451 
452   // For a TOC-relative relocation, adjust the addend and proceed in terms of
453   // the corresponding ADDR16 relocation type.
454   switch (Type) {
455   case R_PPC64_TOC16:       Type = R_PPC64_ADDR16;       SA -= TB; break;
456   case R_PPC64_TOC16_DS:    Type = R_PPC64_ADDR16_DS;    SA -= TB; break;
457   case R_PPC64_TOC16_LO:    Type = R_PPC64_ADDR16_LO;    SA -= TB; break;
458   case R_PPC64_TOC16_LO_DS: Type = R_PPC64_ADDR16_LO_DS; SA -= TB; break;
459   case R_PPC64_TOC16_HI:    Type = R_PPC64_ADDR16_HI;    SA -= TB; break;
460   case R_PPC64_TOC16_HA:    Type = R_PPC64_ADDR16_HA;    SA -= TB; break;
461   default: break;
462   }
463 
464   switch (Type) {
465   case R_PPC64_ADDR16:
466     if (!isInt<16>(SA))
467       error("Relocation R_PPC64_ADDR16 overflow");
468     write16be(L, SA);
469     break;
470   case R_PPC64_ADDR16_DS:
471     if (!isInt<16>(SA))
472       error("Relocation R_PPC64_ADDR16_DS overflow");
473     write16be(L, (read16be(L) & 3) | (SA & ~3));
474     break;
475   case R_PPC64_ADDR16_LO:
476     write16be(L, applyPPCLo(SA));
477     break;
478   case R_PPC64_ADDR16_LO_DS:
479     write16be(L, (read16be(L) & 3) | (applyPPCLo(SA) & ~3));
480     break;
481   case R_PPC64_ADDR16_HI:
482     write16be(L, applyPPCHi(SA));
483     break;
484   case R_PPC64_ADDR16_HA:
485     write16be(L, applyPPCHa(SA));
486     break;
487   case R_PPC64_ADDR16_HIGHER:
488     write16be(L, applyPPCHigher(SA));
489     break;
490   case R_PPC64_ADDR16_HIGHERA:
491     write16be(L, applyPPCHighera(SA));
492     break;
493   case R_PPC64_ADDR16_HIGHEST:
494     write16be(L, applyPPCHighest(SA));
495     break;
496   case R_PPC64_ADDR16_HIGHESTA:
497     write16be(L, applyPPCHighesta(SA));
498     break;
499   case R_PPC64_ADDR14: {
500     if ((SA & 3) != 0)
501       error("Improper alignment for relocation R_PPC64_ADDR14");
502 
503     // Preserve the AA/LK bits in the branch instruction
504     uint8_t AALK = L[3];
505     write16be(L + 2, (AALK & 3) | (SA & 0xfffc));
506     break;
507   }
508   case R_PPC64_REL16_LO:
509     write16be(L, applyPPCLo(SA - P));
510     break;
511   case R_PPC64_REL16_HI:
512     write16be(L, applyPPCHi(SA - P));
513     break;
514   case R_PPC64_REL16_HA:
515     write16be(L, applyPPCHa(SA - P));
516     break;
517   case R_PPC64_ADDR32:
518     if (!isInt<32>(SA))
519       error("Relocation R_PPC64_ADDR32 overflow");
520     write32be(L, SA);
521     break;
522   case R_PPC64_REL24: {
523     uint64_t PltStart = Out<ELF64BE>::Plt->getVA();
524     uint64_t PltEnd = PltStart + Out<ELF64BE>::Plt->getSize();
525     bool InPlt = PltStart <= SA && SA < PltEnd;
526 
527     if (!InPlt && Out<ELF64BE>::Opd) {
528       // If this is a local call, and we currently have the address of a
529       // function-descriptor, get the underlying code address instead.
530       uint64_t OpdStart = Out<ELF64BE>::Opd->getVA();
531       uint64_t OpdEnd = OpdStart + Out<ELF64BE>::Opd->getSize();
532       bool InOpd = OpdStart <= SA && SA < OpdEnd;
533 
534       if (InOpd)
535         SA = read64be(&Out<ELF64BE>::OpdBuf[SA - OpdStart]);
536     }
537 
538     uint32_t Mask = 0x03FFFFFC;
539     if (!isInt<24>(SA - P))
540       error("Relocation R_PPC64_REL24 overflow");
541     write32be(L, (read32be(L) & ~Mask) | ((SA - P) & Mask));
542 
543     if (InPlt && L + 8 <= BufEnd &&
544         read32be(L + 4) == 0x60000000 /* nop */)
545       write32be(L + 4, 0xe8410028); // ld %r2, 40(%r1)
546     break;
547   }
548   case R_PPC64_REL32:
549     if (!isInt<32>(SA - P))
550       error("Relocation R_PPC64_REL32 overflow");
551     write32be(L, SA - P);
552     break;
553   case R_PPC64_REL64:
554     write64be(L, SA - P);
555     break;
556   case R_PPC64_ADDR64:
557     write64be(L, SA);
558     break;
559   default:
560     error("unrecognized reloc " + Twine(Type));
561   }
562 }
563 
564 PPCTargetInfo::PPCTargetInfo() {
565   // PCRelReloc = FIXME
566   // GotReloc = FIXME
567   PageSize = 65536;
568 }
569 void PPCTargetInfo::writePltEntry(uint8_t *Buf, uint64_t GotEntryAddr,
570                                   uint64_t PltEntryAddr) const {}
571 bool PPCTargetInfo::relocNeedsGot(uint32_t Type, const SymbolBody &S) const {
572   return false;
573 }
574 bool PPCTargetInfo::relocNeedsPlt(uint32_t Type, const SymbolBody &S) const {
575   return false;
576 }
577 void PPCTargetInfo::relocateOne(uint8_t *Buf, uint8_t *BufEnd, const void *RelP,
578                                 uint32_t Type, uint64_t BaseAddr,
579                                 uint64_t SA) const {}
580 
581 AArch64TargetInfo::AArch64TargetInfo() {
582   // PCRelReloc = FIXME
583   // GotReloc = FIXME
584 }
585 void AArch64TargetInfo::writePltEntry(uint8_t *Buf, uint64_t GotEntryAddr,
586                                       uint64_t PltEntryAddr) const {}
587 bool AArch64TargetInfo::relocNeedsGot(uint32_t Type,
588                                       const SymbolBody &S) const {
589   return false;
590 }
591 bool AArch64TargetInfo::relocNeedsPlt(uint32_t Type,
592                                       const SymbolBody &S) const {
593   return false;
594 }
595 
596 static void updateAArch64Adr(uint8_t *L, uint64_t Imm) {
597   uint32_t ImmLo = (Imm & 0x3) << 29;
598   uint32_t ImmHi = ((Imm & 0x1FFFFC) >> 2) << 5;
599   uint64_t Mask = (0x3 << 29) | (0x7FFFF << 5);
600   write32le(L, (read32le(L) & ~Mask) | ImmLo | ImmHi);
601 }
602 
603 // Page(Expr) is the page address of the expression Expr, defined
604 // as (Expr & ~0xFFF). (This applies even if the machine page size
605 // supported by the platform has a different value.)
606 static uint64_t getAArch64Page(uint64_t Expr) {
607   return Expr & (~static_cast<uint64_t>(0xFFF));
608 }
609 
610 void AArch64TargetInfo::relocateOne(uint8_t *Buf, uint8_t *BufEnd,
611                                     const void *RelP, uint32_t Type,
612                                     uint64_t BaseAddr, uint64_t SA) const {
613   typedef ELFFile<ELF64LE>::Elf_Rela Elf_Rela;
614   auto &Rel = *reinterpret_cast<const Elf_Rela *>(RelP);
615 
616   uint8_t *L = Buf + Rel.r_offset;
617   uint64_t P = BaseAddr + Rel.r_offset;
618   switch (Type) {
619   case R_AARCH64_ABS16:
620     if (!isInt<16>(SA))
621       error("Relocation R_AARCH64_ABS16 out of range");
622     write16le(L, SA);
623     break;
624   case R_AARCH64_ABS32:
625     if (!isInt<32>(SA))
626       error("Relocation R_AARCH64_ABS32 out of range");
627     write32le(L, SA);
628     break;
629   case R_AARCH64_ABS64:
630     // No overflow check needed.
631     write64le(L, SA);
632     break;
633   case R_AARCH64_ADD_ABS_LO12_NC:
634     // No overflow check needed.
635     or32le(L, (SA & 0xFFF) << 10);
636     break;
637   case R_AARCH64_ADR_PREL_LO21: {
638     uint64_t X = SA - P;
639     if (!isInt<21>(X))
640       error("Relocation R_AARCH64_ADR_PREL_LO21 out of range");
641     updateAArch64Adr(L, X & 0x1FFFFF);
642     break;
643   }
644   case R_AARCH64_ADR_PREL_PG_HI21: {
645     uint64_t X = getAArch64Page(SA) - getAArch64Page(P);
646     if (!isInt<33>(X))
647       error("Relocation R_AARCH64_ADR_PREL_PG_HI21 out of range");
648     updateAArch64Adr(L, (X >> 12) & 0x1FFFFF); // X[32:12]
649     break;
650   }
651   default:
652     error("unrecognized reloc " + Twine(Type));
653   }
654 }
655 
656 template <class ELFT> MipsTargetInfo<ELFT>::MipsTargetInfo() {
657   // PCRelReloc = FIXME
658   // GotReloc = FIXME
659   PageSize = 65536;
660 }
661 
662 template <class ELFT>
663 void MipsTargetInfo<ELFT>::writePltEntry(uint8_t *Buf, uint64_t GotEntryAddr,
664                                          uint64_t PltEntryAddr) const {}
665 
666 template <class ELFT>
667 bool MipsTargetInfo<ELFT>::relocNeedsGot(uint32_t Type,
668                                          const SymbolBody &S) const {
669   return false;
670 }
671 
672 template <class ELFT>
673 bool MipsTargetInfo<ELFT>::relocNeedsPlt(uint32_t Type,
674                                          const SymbolBody &S) const {
675   return false;
676 }
677 
678 template <class ELFT>
679 void MipsTargetInfo<ELFT>::relocateOne(uint8_t *Buf, uint8_t *BufEnd,
680                                        const void *RelP, uint32_t Type,
681                                        uint64_t BaseAddr, uint64_t SA) const {
682   const bool IsLE = ELFT::TargetEndianness == support::little;
683   typedef typename ELFFile<ELFT>::Elf_Rel Elf_Rel;
684   auto &Rel = *reinterpret_cast<const Elf_Rel *>(RelP);
685 
686   switch (Type) {
687   case R_MIPS_32:
688     add32<IsLE>(Buf + Rel.r_offset, SA);
689     break;
690   default:
691     error("unrecognized reloc " + Twine(Type));
692   }
693 }
694 }
695 }
696