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