xref: /llvm-project-15.0.7/lld/ELF/Arch/PPC64.cpp (revision f489e2bf)
1 //===- PPC64.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 #include "Symbols.h"
11 #include "SyntheticSections.h"
12 #include "Target.h"
13 #include "lld/Common/ErrorHandler.h"
14 #include "llvm/Support/Endian.h"
15 
16 using namespace llvm;
17 using namespace llvm::object;
18 using namespace llvm::support::endian;
19 using namespace llvm::ELF;
20 using namespace lld;
21 using namespace lld::elf;
22 
23 static uint64_t PPC64TocOffset = 0x8000;
24 
25 uint64_t elf::getPPC64TocBase() {
26   // The TOC consists of sections .got, .toc, .tocbss, .plt in that order. The
27   // TOC starts where the first of these sections starts. We always create a
28   // .got when we see a relocation that uses it, so for us the start is always
29   // the .got.
30   uint64_t TocVA = InX::Got->getVA();
31 
32   // Per the ppc64-elf-linux ABI, The TOC base is TOC value plus 0x8000
33   // thus permitting a full 64 Kbytes segment. Note that the glibc startup
34   // code (crt1.o) assumes that you can get from the TOC base to the
35   // start of the .toc section with only a single (signed) 16-bit relocation.
36   return TocVA + PPC64TocOffset;
37 }
38 
39 namespace {
40 class PPC64 final : public TargetInfo {
41 public:
42   PPC64();
43   uint32_t calcEFlags() const override;
44   RelExpr getRelExpr(RelType Type, const Symbol &S,
45                      const uint8_t *Loc) const override;
46   void writePltHeader(uint8_t *Buf) const override;
47   void writePlt(uint8_t *Buf, uint64_t GotPltEntryAddr, uint64_t PltEntryAddr,
48                 int32_t Index, unsigned RelOff) const override;
49   void relocateOne(uint8_t *Loc, RelType Type, uint64_t Val) const override;
50   void writeGotHeader(uint8_t *Buf) const override;
51   bool needsThunk(RelExpr Expr, RelType Type, const InputFile *File,
52                   uint64_t BranchAddr, const Symbol &S) const override;
53 };
54 } // namespace
55 
56 // Relocation masks following the #lo(value), #hi(value), #ha(value),
57 // #higher(value), #highera(value), #highest(value), and #highesta(value)
58 // macros defined in section 4.5.1. Relocation Types of the PPC-elf64abi
59 // document.
60 static uint16_t applyPPCLo(uint64_t V) { return V; }
61 static uint16_t applyPPCHi(uint64_t V) { return V >> 16; }
62 static uint16_t applyPPCHa(uint64_t V) { return (V + 0x8000) >> 16; }
63 static uint16_t applyPPCHigher(uint64_t V) { return V >> 32; }
64 static uint16_t applyPPCHighera(uint64_t V) { return (V + 0x8000) >> 32; }
65 static uint16_t applyPPCHighest(uint64_t V) { return V >> 48; }
66 static uint16_t applyPPCHighesta(uint64_t V) { return (V + 0x8000) >> 48; }
67 
68 PPC64::PPC64() {
69   GotRel = R_PPC64_GLOB_DAT;
70   PltRel = R_PPC64_JMP_SLOT;
71   RelativeRel = R_PPC64_RELATIVE;
72   GotEntrySize = 8;
73   PltEntrySize = 4;
74   GotPltEntrySize = 8;
75   GotBaseSymInGotPlt = false;
76   GotBaseSymOff = 0x8000;
77   GotHeaderEntriesNum = 1;
78   GotPltHeaderEntriesNum = 2;
79   PltHeaderSize = 60;
80   NeedsThunks = true;
81 
82   // We need 64K pages (at least under glibc/Linux, the loader won't
83   // set different permissions on a finer granularity than that).
84   DefaultMaxPageSize = 65536;
85 
86   // The PPC64 ELF ABI v1 spec, says:
87   //
88   //   It is normally desirable to put segments with different characteristics
89   //   in separate 256 Mbyte portions of the address space, to give the
90   //   operating system full paging flexibility in the 64-bit address space.
91   //
92   // And because the lowest non-zero 256M boundary is 0x10000000, PPC64 linkers
93   // use 0x10000000 as the starting address.
94   DefaultImageBase = 0x10000000;
95 
96   TrapInstr =
97       (Config->IsLE == sys::IsLittleEndianHost) ? 0x7fe00008 : 0x0800e07f;
98 }
99 
100 static uint32_t getEFlags(InputFile *File) {
101   // Get the e_flag from the input file and issue an error if incompatible
102   // e_flag encountered.
103   uint32_t EFlags;
104   switch (Config->EKind) {
105   case ELF64BEKind:
106     EFlags = cast<ObjFile<ELF64BE>>(File)->getObj().getHeader()->e_flags;
107     break;
108   case ELF64LEKind:
109     EFlags = cast<ObjFile<ELF64LE>>(File)->getObj().getHeader()->e_flags;
110     break;
111   default:
112     llvm_unreachable("unknown Config->EKind");
113   }
114   if (EFlags > 2) {
115     error("incompatible e_flags: " +  toString(File));
116     return 0;
117   }
118   return EFlags;
119 }
120 
121 uint32_t PPC64::calcEFlags() const {
122   assert(!ObjectFiles.empty());
123 
124   uint32_t NonZeroFlag;
125   for (InputFile *F : makeArrayRef(ObjectFiles)) {
126     NonZeroFlag = getEFlags(F);
127     if (NonZeroFlag)
128       break;
129   }
130 
131   // Verify that all input files have either the same e_flags, or zero.
132   for (InputFile *F : makeArrayRef(ObjectFiles)) {
133     uint32_t Flag = getEFlags(F);
134     if (Flag == 0 || Flag == NonZeroFlag)
135       continue;
136     error(toString(F) + ": ABI version " + Twine(Flag) +
137           " is not compatible with ABI version " + Twine(NonZeroFlag) +
138           " output");
139     return 0;
140   }
141 
142   if (NonZeroFlag == 1) {
143     error("PPC64 V1 ABI not supported");
144     return 0;
145   }
146 
147   return 2;
148 }
149 
150 RelExpr PPC64::getRelExpr(RelType Type, const Symbol &S,
151                           const uint8_t *Loc) const {
152   switch (Type) {
153   case R_PPC64_TOC16:
154   case R_PPC64_TOC16_DS:
155   case R_PPC64_TOC16_HA:
156   case R_PPC64_TOC16_HI:
157   case R_PPC64_TOC16_LO:
158   case R_PPC64_TOC16_LO_DS:
159     return R_GOTREL;
160   case R_PPC64_TOC:
161     return R_PPC_TOC;
162   case R_PPC64_REL24:
163     return R_PPC_CALL_PLT;
164   case R_PPC64_REL16_LO:
165   case R_PPC64_REL16_HA:
166     return R_PC;
167   default:
168     return R_ABS;
169   }
170 }
171 
172 void PPC64::writeGotHeader(uint8_t *Buf) const {
173   write64(Buf, getPPC64TocBase());
174 }
175 
176 void PPC64::writePltHeader(uint8_t *Buf) const {
177   // The generic resolver stub goes first.
178   write32(Buf +  0, 0x7c0802a6); // mflr r0
179   write32(Buf +  4, 0x429f0005); // bcl  20,4*cr7+so,8 <_glink+0x8>
180   write32(Buf +  8, 0x7d6802a6); // mflr r11
181   write32(Buf + 12, 0x7c0803a6); // mtlr r0
182   write32(Buf + 16, 0x7d8b6050); // subf r12, r11, r12
183   write32(Buf + 20, 0x380cffcc); // subi r0,r12,52
184   write32(Buf + 24, 0x7800f082); // srdi r0,r0,62,2
185   write32(Buf + 28, 0xe98b002c); // ld   r12,44(r11)
186   write32(Buf + 32, 0x7d6c5a14); // add  r11,r12,r11
187   write32(Buf + 36, 0xe98b0000); // ld   r12,0(r11)
188   write32(Buf + 40, 0xe96b0008); // ld   r11,8(r11)
189   write32(Buf + 44, 0x7d8903a6); // mtctr   r12
190   write32(Buf + 48, 0x4e800420); // bctr
191 
192   // The 'bcl' instruction will set the link register to the address of the
193   // following instruction ('mflr r11'). Here we store the offset from that
194   // instruction  to the first entry in the GotPlt section.
195   int64_t GotPltOffset = InX::GotPlt->getVA() - (InX::Plt->getVA() + 8);
196   write64(Buf + 52, GotPltOffset);
197 }
198 
199 void PPC64::writePlt(uint8_t *Buf, uint64_t GotPltEntryAddr,
200                      uint64_t PltEntryAddr, int32_t Index,
201                      unsigned RelOff) const {
202  int32_t Offset = PltHeaderSize + Index * PltEntrySize;
203  // bl __glink_PLTresolve
204  write32(Buf, 0x48000000 | ((-Offset) & 0x03FFFFFc));
205 }
206 
207 static std::pair<RelType, uint64_t> toAddr16Rel(RelType Type, uint64_t Val) {
208   uint64_t V = Val - PPC64TocOffset;
209   switch (Type) {
210   case R_PPC64_TOC16:
211     return {R_PPC64_ADDR16, V};
212   case R_PPC64_TOC16_DS:
213     return {R_PPC64_ADDR16_DS, V};
214   case R_PPC64_TOC16_HA:
215     return {R_PPC64_ADDR16_HA, V};
216   case R_PPC64_TOC16_HI:
217     return {R_PPC64_ADDR16_HI, V};
218   case R_PPC64_TOC16_LO:
219     return {R_PPC64_ADDR16_LO, V};
220   case R_PPC64_TOC16_LO_DS:
221     return {R_PPC64_ADDR16_LO_DS, V};
222   default:
223     return {Type, Val};
224   }
225 }
226 
227 void PPC64::relocateOne(uint8_t *Loc, RelType Type, uint64_t Val) const {
228   // For a TOC-relative relocation, proceed in terms of the corresponding
229   // ADDR16 relocation type.
230   std::tie(Type, Val) = toAddr16Rel(Type, Val);
231 
232   switch (Type) {
233   case R_PPC64_ADDR14: {
234     checkAlignment(Loc, Val, 4, Type);
235     // Preserve the AA/LK bits in the branch instruction
236     uint8_t AALK = Loc[3];
237     write16(Loc + 2, (AALK & 3) | (Val & 0xfffc));
238     break;
239   }
240   case R_PPC64_ADDR16:
241     checkInt(Loc, Val, 16, Type);
242     write16(Loc, Val);
243     break;
244   case R_PPC64_ADDR16_DS:
245     checkInt(Loc, Val, 16, Type);
246     write16(Loc, (read16(Loc) & 3) | (Val & ~3));
247     break;
248   case R_PPC64_ADDR16_HA:
249   case R_PPC64_REL16_HA:
250     write16(Loc, applyPPCHa(Val));
251     break;
252   case R_PPC64_ADDR16_HI:
253   case R_PPC64_REL16_HI:
254     write16(Loc, applyPPCHi(Val));
255     break;
256   case R_PPC64_ADDR16_HIGHER:
257     write16(Loc, applyPPCHigher(Val));
258     break;
259   case R_PPC64_ADDR16_HIGHERA:
260     write16(Loc, applyPPCHighera(Val));
261     break;
262   case R_PPC64_ADDR16_HIGHEST:
263     write16(Loc, applyPPCHighest(Val));
264     break;
265   case R_PPC64_ADDR16_HIGHESTA:
266     write16(Loc, applyPPCHighesta(Val));
267     break;
268   case R_PPC64_ADDR16_LO:
269   case R_PPC64_REL16_LO:
270     write16(Loc, applyPPCLo(Val));
271     break;
272   case R_PPC64_ADDR16_LO_DS:
273     write16(Loc, (read16(Loc) & 3) | (applyPPCLo(Val) & ~3));
274     break;
275   case R_PPC64_ADDR32:
276   case R_PPC64_REL32:
277     checkInt(Loc, Val, 32, Type);
278     write32(Loc, Val);
279     break;
280   case R_PPC64_ADDR64:
281   case R_PPC64_REL64:
282   case R_PPC64_TOC:
283     write64(Loc, Val);
284     break;
285   case R_PPC64_REL24: {
286     uint32_t Mask = 0x03FFFFFC;
287     checkInt(Loc, Val, 24, Type);
288     write32(Loc, (read32(Loc) & ~Mask) | (Val & Mask));
289     break;
290   }
291   default:
292     error(getErrorLocation(Loc) + "unrecognized reloc " + Twine(Type));
293   }
294 }
295 
296 bool PPC64::needsThunk(RelExpr Expr, RelType Type, const InputFile *File,
297                        uint64_t BranchAddr, const Symbol &S) const {
298   // If a function is in the plt it needs to be called through
299   // a call stub.
300   return Type == R_PPC64_REL24 && S.isInPlt();
301 }
302 
303 TargetInfo *elf::getPPC64TargetInfo() {
304   static PPC64 Target;
305   return &Target;
306 }
307