1 //===- PPC.cpp ------------------------------------------------------------===//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
9 #include "OutputSections.h"
11 #include "SyntheticSections.h"
14 #include "lld/Common/ErrorHandler.h"
15 #include "llvm/Support/Endian.h"
18 using namespace llvm::support::endian
;
19 using namespace llvm::ELF
;
21 using namespace lld::elf
;
23 // Undefine the macro predefined by GCC powerpc32.
27 class PPC final
: public TargetInfo
{
30 RelExpr
getRelExpr(RelType type
, const Symbol
&s
,
31 const uint8_t *loc
) const override
;
32 RelType
getDynRel(RelType type
) const override
;
33 int64_t getImplicitAddend(const uint8_t *buf
, RelType type
) const override
;
34 void writeGotHeader(uint8_t *buf
) const override
;
35 void writePltHeader(uint8_t *buf
) const override
{
36 llvm_unreachable("should call writePPC32GlinkSection() instead");
38 void writePlt(uint8_t *buf
, const Symbol
&sym
,
39 uint64_t pltEntryAddr
) const override
{
40 llvm_unreachable("should call writePPC32GlinkSection() instead");
42 void writeIplt(uint8_t *buf
, const Symbol
&sym
,
43 uint64_t pltEntryAddr
) const override
;
44 void writeGotPlt(uint8_t *buf
, const Symbol
&s
) const override
;
45 bool needsThunk(RelExpr expr
, RelType relocType
, const InputFile
*file
,
46 uint64_t branchAddr
, const Symbol
&s
,
47 int64_t a
) const override
;
48 uint32_t getThunkSectionSpacing() const override
;
49 bool inBranchRange(RelType type
, uint64_t src
, uint64_t dst
) const override
;
50 void relocate(uint8_t *loc
, const Relocation
&rel
,
51 uint64_t val
) const override
;
52 RelExpr
adjustTlsExpr(RelType type
, RelExpr expr
) const override
;
53 int getTlsGdRelaxSkip(RelType type
) const override
;
54 void relocateAlloc(InputSectionBase
&sec
, uint8_t *buf
) const override
;
57 void relaxTlsGdToIe(uint8_t *loc
, const Relocation
&rel
, uint64_t val
) const;
58 void relaxTlsGdToLe(uint8_t *loc
, const Relocation
&rel
, uint64_t val
) const;
59 void relaxTlsLdToLe(uint8_t *loc
, const Relocation
&rel
, uint64_t val
) const;
60 void relaxTlsIeToLe(uint8_t *loc
, const Relocation
&rel
, uint64_t val
) const;
64 static uint16_t lo(uint32_t v
) { return v
; }
65 static uint16_t ha(uint32_t v
) { return (v
+ 0x8000) >> 16; }
67 static uint32_t readFromHalf16(const uint8_t *loc
) {
68 return read32(config
->isLE
? loc
: loc
- 2);
71 static void writeFromHalf16(uint8_t *loc
, uint32_t insn
) {
72 write32(config
->isLE
? loc
: loc
- 2, insn
);
75 void elf::writePPC32GlinkSection(uint8_t *buf
, size_t numEntries
) {
76 // Create canonical PLT entries for non-PIE code. Compilers don't generate
77 // non-GOT-non-PLT relocations referencing external functions for -fpie/-fPIE.
78 uint32_t glink
= in
.plt
->getVA(); // VA of .glink
80 for (const Symbol
*sym
: cast
<PPC32GlinkSection
>(*in
.plt
).canonical_plts
) {
81 writePPC32PltCallStub(buf
, sym
->getGotPltVA(), nullptr, 0);
87 // On PPC Secure PLT ABI, bl foo@plt jumps to a call stub, which loads an
88 // absolute address from a specific .plt slot (usually called .got.plt on
89 // other targets) and jumps there.
91 // a) With immediate binding (BIND_NOW), the .plt entry is resolved at load
92 // time. The .glink section is not used.
93 // b) With lazy binding, the .plt entry points to a `b PLTresolve`
94 // instruction in .glink, filled in by PPC::writeGotPlt().
96 // Write N `b PLTresolve` first.
97 for (size_t i
= 0; i
!= numEntries
; ++i
)
98 write32(buf
+ 4 * i
, 0x48000000 | 4 * (numEntries
- i
));
99 buf
+= 4 * numEntries
;
101 // Then write PLTresolve(), which has two forms: PIC and non-PIC. PLTresolve()
102 // computes the PLT index (by computing the distance from the landing b to
103 // itself) and calls _dl_runtime_resolve() (in glibc).
104 uint32_t got
= in
.got
->getVA();
105 const uint8_t *end
= buf
+ 64;
107 uint32_t afterBcl
= 4 * in
.plt
->getNumEntries() + 12;
108 uint32_t gotBcl
= got
+ 4 - (glink
+ afterBcl
);
109 write32(buf
+ 0, 0x3d6b0000 | ha(afterBcl
)); // addis r11,r11,1f-glink@ha
110 write32(buf
+ 4, 0x7c0802a6); // mflr r0
111 write32(buf
+ 8, 0x429f0005); // bcl 20,30,.+4
112 write32(buf
+ 12, 0x396b0000 | lo(afterBcl
)); // 1: addi r11,r11,1b-glink@l
113 write32(buf
+ 16, 0x7d8802a6); // mflr r12
114 write32(buf
+ 20, 0x7c0803a6); // mtlr r0
115 write32(buf
+ 24, 0x7d6c5850); // sub r11,r11,r12
116 write32(buf
+ 28, 0x3d8c0000 | ha(gotBcl
)); // addis 12,12,GOT+4-1b@ha
117 if (ha(gotBcl
) == ha(gotBcl
+ 4)) {
118 write32(buf
+ 32, 0x800c0000 | lo(gotBcl
)); // lwz r0,r12,GOT+4-1b@l(r12)
120 0x818c0000 | lo(gotBcl
+ 4)); // lwz r12,r12,GOT+8-1b@l(r12)
122 write32(buf
+ 32, 0x840c0000 | lo(gotBcl
)); // lwzu r0,r12,GOT+4-1b@l(r12)
123 write32(buf
+ 36, 0x818c0000 | 4); // lwz r12,r12,4(r12)
125 write32(buf
+ 40, 0x7c0903a6); // mtctr 0
126 write32(buf
+ 44, 0x7c0b5a14); // add r0,11,11
127 write32(buf
+ 48, 0x7d605a14); // add r11,0,11
128 write32(buf
+ 52, 0x4e800420); // bctr
131 write32(buf
+ 0, 0x3d800000 | ha(got
+ 4)); // lis r12,GOT+4@ha
132 write32(buf
+ 4, 0x3d6b0000 | ha(-glink
)); // addis r11,r11,-glink@ha
133 if (ha(got
+ 4) == ha(got
+ 8))
134 write32(buf
+ 8, 0x800c0000 | lo(got
+ 4)); // lwz r0,GOT+4@l(r12)
136 write32(buf
+ 8, 0x840c0000 | lo(got
+ 4)); // lwzu r0,GOT+4@l(r12)
137 write32(buf
+ 12, 0x396b0000 | lo(-glink
)); // addi r11,r11,-glink@l
138 write32(buf
+ 16, 0x7c0903a6); // mtctr r0
139 write32(buf
+ 20, 0x7c0b5a14); // add r0,r11,r11
140 if (ha(got
+ 4) == ha(got
+ 8))
141 write32(buf
+ 24, 0x818c0000 | lo(got
+ 8)); // lwz r12,GOT+8@l(r12)
143 write32(buf
+ 24, 0x818c0000 | 4); // lwz r12,4(r12)
144 write32(buf
+ 28, 0x7d605a14); // add r11,r0,r11
145 write32(buf
+ 32, 0x4e800420); // bctr
149 // Pad with nop. They should not be executed.
150 for (; buf
< end
; buf
+= 4)
151 write32(buf
, 0x60000000);
155 copyRel
= R_PPC_COPY
;
156 gotRel
= R_PPC_GLOB_DAT
;
157 pltRel
= R_PPC_JMP_SLOT
;
158 relativeRel
= R_PPC_RELATIVE
;
159 iRelativeRel
= R_PPC_IRELATIVE
;
160 symbolicRel
= R_PPC_ADDR32
;
161 gotHeaderEntriesNum
= 3;
162 gotPltHeaderEntriesNum
= 0;
169 tlsModuleIndexRel
= R_PPC_DTPMOD32
;
170 tlsOffsetRel
= R_PPC_DTPREL32
;
171 tlsGotRel
= R_PPC_TPREL32
;
173 defaultMaxPageSize
= 65536;
174 defaultImageBase
= 0x10000000;
176 write32(trapInstr
.data(), 0x7fe00008);
179 void PPC::writeIplt(uint8_t *buf
, const Symbol
&sym
,
180 uint64_t /*pltEntryAddr*/) const {
181 // In -pie or -shared mode, assume r30 points to .got2+0x8000, and use a
182 // .got2.plt_pic32. thunk.
183 writePPC32PltCallStub(buf
, sym
.getGotPltVA(), sym
.file
, 0x8000);
186 void PPC::writeGotHeader(uint8_t *buf
) const {
187 // _GLOBAL_OFFSET_TABLE_[0] = _DYNAMIC
188 // glibc stores _dl_runtime_resolve in _GLOBAL_OFFSET_TABLE_[1],
189 // link_map in _GLOBAL_OFFSET_TABLE_[2].
190 write32(buf
, mainPart
->dynamic
->getVA());
193 void PPC::writeGotPlt(uint8_t *buf
, const Symbol
&s
) const {
194 // Address of the symbol resolver stub in .glink .
195 write32(buf
, in
.plt
->getVA() + in
.plt
->headerSize
+ 4 * s
.getPltIdx());
198 bool PPC::needsThunk(RelExpr expr
, RelType type
, const InputFile
*file
,
199 uint64_t branchAddr
, const Symbol
&s
, int64_t a
) const {
200 if (type
!= R_PPC_LOCAL24PC
&& type
!= R_PPC_REL24
&& type
!= R_PPC_PLTREL24
)
206 return !PPC::inBranchRange(type
, branchAddr
, s
.getVA(a
));
209 uint32_t PPC::getThunkSectionSpacing() const { return 0x2000000; }
211 bool PPC::inBranchRange(RelType type
, uint64_t src
, uint64_t dst
) const {
212 uint64_t offset
= dst
- src
;
213 if (type
== R_PPC_LOCAL24PC
|| type
== R_PPC_REL24
|| type
== R_PPC_PLTREL24
)
214 return isInt
<26>(offset
);
215 llvm_unreachable("unsupported relocation type used in branch");
218 RelExpr
PPC::getRelExpr(RelType type
, const Symbol
&s
,
219 const uint8_t *loc
) const {
223 case R_PPC_ADDR16_HA
:
224 case R_PPC_ADDR16_HI
:
225 case R_PPC_ADDR16_LO
:
230 case R_PPC_DTPREL16_HA
:
231 case R_PPC_DTPREL16_HI
:
232 case R_PPC_DTPREL16_LO
:
243 case R_PPC_LOCAL24PC
:
247 return R_PPC32_PLTREL
;
248 case R_PPC_GOT_TLSGD16
:
250 case R_PPC_GOT_TLSLD16
:
252 case R_PPC_GOT_TPREL16
:
257 return R_TLSDESC_CALL
;
261 case R_PPC_TPREL16_HA
:
262 case R_PPC_TPREL16_LO
:
263 case R_PPC_TPREL16_HI
:
266 error(getErrorLocation(loc
) + "unknown relocation (" + Twine(type
) +
267 ") against symbol " + toString(s
));
272 RelType
PPC::getDynRel(RelType type
) const {
273 if (type
== R_PPC_ADDR32
)
278 int64_t PPC::getImplicitAddend(const uint8_t *buf
, RelType type
) const {
287 case R_PPC_IRELATIVE
:
291 return SignExtend64
<32>(read32(buf
));
293 internalLinkerError(getErrorLocation(buf
),
294 "cannot read addend for relocation " + toString(type
));
299 static std::pair
<RelType
, uint64_t> fromDTPREL(RelType type
, uint64_t val
) {
300 uint64_t dtpBiasedVal
= val
- 0x8000;
303 return {R_PPC64_ADDR16
, dtpBiasedVal
};
304 case R_PPC_DTPREL16_HA
:
305 return {R_PPC_ADDR16_HA
, dtpBiasedVal
};
306 case R_PPC_DTPREL16_HI
:
307 return {R_PPC_ADDR16_HI
, dtpBiasedVal
};
308 case R_PPC_DTPREL16_LO
:
309 return {R_PPC_ADDR16_LO
, dtpBiasedVal
};
311 return {R_PPC_ADDR32
, dtpBiasedVal
};
317 void PPC::relocate(uint8_t *loc
, const Relocation
&rel
, uint64_t val
) const {
319 std::tie(newType
, val
) = fromDTPREL(rel
.type
, val
);
322 checkIntUInt(loc
, val
, 16, rel
);
326 case R_PPC_GOT_TLSGD16
:
327 case R_PPC_GOT_TLSLD16
:
328 case R_PPC_GOT_TPREL16
:
330 checkInt(loc
, val
, 16, rel
);
333 case R_PPC_ADDR16_HA
:
334 case R_PPC_DTPREL16_HA
:
335 case R_PPC_GOT_TLSGD16_HA
:
336 case R_PPC_GOT_TLSLD16_HA
:
337 case R_PPC_GOT_TPREL16_HA
:
339 case R_PPC_TPREL16_HA
:
340 write16(loc
, ha(val
));
342 case R_PPC_ADDR16_HI
:
343 case R_PPC_DTPREL16_HI
:
344 case R_PPC_GOT_TLSGD16_HI
:
345 case R_PPC_GOT_TLSLD16_HI
:
346 case R_PPC_GOT_TPREL16_HI
:
348 case R_PPC_TPREL16_HI
:
349 write16(loc
, val
>> 16);
351 case R_PPC_ADDR16_LO
:
352 case R_PPC_DTPREL16_LO
:
353 case R_PPC_GOT_TLSGD16_LO
:
354 case R_PPC_GOT_TLSLD16_LO
:
355 case R_PPC_GOT_TPREL16_LO
:
357 case R_PPC_TPREL16_LO
:
365 uint32_t mask
= 0x0000FFFC;
366 checkInt(loc
, val
, 16, rel
);
367 checkAlignment(loc
, val
, 4, rel
);
368 write32(loc
, (read32(loc
) & ~mask
) | (val
& mask
));
373 case R_PPC_LOCAL24PC
:
374 case R_PPC_PLTREL24
: {
375 uint32_t mask
= 0x03FFFFFC;
376 checkInt(loc
, val
, 26, rel
);
377 checkAlignment(loc
, val
, 4, rel
);
378 write32(loc
, (read32(loc
) & ~mask
) | (val
& mask
));
382 llvm_unreachable("unknown relocation");
386 RelExpr
PPC::adjustTlsExpr(RelType type
, RelExpr expr
) const {
387 if (expr
== R_RELAX_TLS_GD_TO_IE
)
388 return R_RELAX_TLS_GD_TO_IE_GOT_OFF
;
389 if (expr
== R_RELAX_TLS_LD_TO_LE
)
390 return R_RELAX_TLS_LD_TO_LE_ABS
;
394 int PPC::getTlsGdRelaxSkip(RelType type
) const {
395 // A __tls_get_addr call instruction is marked with 2 relocations:
397 // R_PPC_TLSGD / R_PPC_TLSLD: marker relocation
398 // R_PPC_REL24: __tls_get_addr
400 // After the relaxation we no longer call __tls_get_addr and should skip both
401 // relocations to not create a false dependence on __tls_get_addr being
403 if (type
== R_PPC_TLSGD
|| type
== R_PPC_TLSLD
)
408 void PPC::relaxTlsGdToIe(uint8_t *loc
, const Relocation
&rel
,
409 uint64_t val
) const {
411 case R_PPC_GOT_TLSGD16
: {
412 // addi rT, rA, x@got@tlsgd --> lwz rT, x@got@tprel(rA)
413 uint32_t insn
= readFromHalf16(loc
);
414 writeFromHalf16(loc
, 0x80000000 | (insn
& 0x03ff0000));
415 relocateNoSym(loc
, R_PPC_GOT_TPREL16
, val
);
419 // bl __tls_get_addr(x@tldgd) --> add r3, r3, r2
420 write32(loc
, 0x7c631214);
423 llvm_unreachable("unsupported relocation for TLS GD to IE relaxation");
427 void PPC::relaxTlsGdToLe(uint8_t *loc
, const Relocation
&rel
,
428 uint64_t val
) const {
430 case R_PPC_GOT_TLSGD16
:
431 // addi r3, r31, x@got@tlsgd --> addis r3, r2, x@tprel@ha
432 writeFromHalf16(loc
, 0x3c620000 | ha(val
));
435 // bl __tls_get_addr(x@tldgd) --> add r3, r3, x@tprel@l
436 write32(loc
, 0x38630000 | lo(val
));
439 llvm_unreachable("unsupported relocation for TLS GD to LE relaxation");
443 void PPC::relaxTlsLdToLe(uint8_t *loc
, const Relocation
&rel
,
444 uint64_t val
) const {
446 case R_PPC_GOT_TLSLD16
:
447 // addi r3, rA, x@got@tlsgd --> addis r3, r2, 0
448 writeFromHalf16(loc
, 0x3c620000);
451 // r3+x@dtprel computes r3+x-0x8000, while we want it to compute r3+x@tprel
452 // = r3+x-0x7000, so add 4096 to r3.
453 // bl __tls_get_addr(x@tlsld) --> addi r3, r3, 4096
454 write32(loc
, 0x38631000);
457 case R_PPC_DTPREL16_HA
:
458 case R_PPC_DTPREL16_HI
:
459 case R_PPC_DTPREL16_LO
:
460 relocate(loc
, rel
, val
);
463 llvm_unreachable("unsupported relocation for TLS LD to LE relaxation");
467 void PPC::relaxTlsIeToLe(uint8_t *loc
, const Relocation
&rel
,
468 uint64_t val
) const {
470 case R_PPC_GOT_TPREL16
: {
471 // lwz rT, x@got@tprel(rA) --> addis rT, r2, x@tprel@ha
472 uint32_t rt
= readFromHalf16(loc
) & 0x03e00000;
473 writeFromHalf16(loc
, 0x3c020000 | rt
| ha(val
));
477 uint32_t insn
= read32(loc
);
478 if (insn
>> 26 != 31)
479 error("unrecognized instruction for IE to LE R_PPC_TLS");
480 // addi rT, rT, x@tls --> addi rT, rT, x@tprel@l
481 unsigned secondaryOp
= (read32(loc
) & 0x000007fe) >> 1;
482 uint32_t dFormOp
= getPPCDFormOp(secondaryOp
);
483 if (dFormOp
== 0) { // Expecting a DS-Form instruction.
484 dFormOp
= getPPCDSFormOp(secondaryOp
);
486 error("unrecognized instruction for IE to LE R_PPC_TLS");
488 write32(loc
, (dFormOp
| (insn
& 0x03ff0000) | lo(val
)));
492 llvm_unreachable("unsupported relocation for TLS IE to LE relaxation");
496 void PPC::relocateAlloc(InputSectionBase
&sec
, uint8_t *buf
) const {
497 uint64_t secAddr
= sec
.getOutputSection()->addr
;
498 if (auto *s
= dyn_cast
<InputSection
>(&sec
))
499 secAddr
+= s
->outSecOff
;
500 for (const Relocation
&rel
: sec
.relocs()) {
501 uint8_t *loc
= buf
+ rel
.offset
;
502 const uint64_t val
= SignExtend64(
503 sec
.getRelocTargetVA(sec
.file
, rel
.type
, rel
.addend
,
504 secAddr
+ rel
.offset
, *rel
.sym
, rel
.expr
),
507 case R_RELAX_TLS_GD_TO_IE_GOT_OFF
:
508 relaxTlsGdToIe(loc
, rel
, val
);
510 case R_RELAX_TLS_GD_TO_LE
:
511 relaxTlsGdToLe(loc
, rel
, val
);
513 case R_RELAX_TLS_LD_TO_LE_ABS
:
514 relaxTlsLdToLe(loc
, rel
, val
);
516 case R_RELAX_TLS_IE_TO_LE
:
517 relaxTlsIeToLe(loc
, rel
, val
);
520 relocate(loc
, rel
, val
);
526 TargetInfo
*elf::getPPCTargetInfo() {