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(Ctx
&ctx
, const uint8_t *loc
) {
68 return read32(ctx
, ctx
.arg
.isLE
? loc
: loc
- 2);
71 static void writeFromHalf16(Ctx
&ctx
, uint8_t *loc
, uint32_t insn
) {
72 write32(ctx
, ctx
.arg
.isLE
? loc
: loc
- 2, insn
);
75 void elf::writePPC32GlinkSection(Ctx
&ctx
, 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
= ctx
.in
.plt
->getVA(); // VA of .glink
80 for (const Symbol
*sym
:
81 cast
<PPC32GlinkSection
>(*ctx
.in
.plt
).canonical_plts
) {
82 writePPC32PltCallStub(ctx
, buf
, sym
->getGotPltVA(ctx
), nullptr, 0);
88 // On PPC Secure PLT ABI, bl foo@plt jumps to a call stub, which loads an
89 // absolute address from a specific .plt slot (usually called .got.plt on
90 // other targets) and jumps there.
92 // a) With immediate binding (BIND_NOW), the .plt entry is resolved at load
93 // time. The .glink section is not used.
94 // b) With lazy binding, the .plt entry points to a `b PLTresolve`
95 // instruction in .glink, filled in by PPC::writeGotPlt().
97 // Write N `b PLTresolve` first.
98 for (size_t i
= 0; i
!= numEntries
; ++i
)
99 write32(ctx
, buf
+ 4 * i
, 0x48000000 | 4 * (numEntries
- i
));
100 buf
+= 4 * numEntries
;
102 // Then write PLTresolve(), which has two forms: PIC and non-PIC. PLTresolve()
103 // computes the PLT index (by computing the distance from the landing b to
104 // itself) and calls _dl_runtime_resolve() (in glibc).
105 uint32_t got
= ctx
.in
.got
->getVA();
106 const uint8_t *end
= buf
+ 64;
108 uint32_t afterBcl
= 4 * ctx
.in
.plt
->getNumEntries() + 12;
109 uint32_t gotBcl
= got
+ 4 - (glink
+ afterBcl
);
110 write32(ctx
, buf
+ 0,
111 0x3d6b0000 | ha(afterBcl
)); // addis r11,r11,1f-glink@ha
112 write32(ctx
, buf
+ 4, 0x7c0802a6); // mflr r0
113 write32(ctx
, buf
+ 8, 0x429f0005); // bcl 20,30,.+4
114 write32(ctx
, buf
+ 12,
115 0x396b0000 | lo(afterBcl
)); // 1: addi r11,r11,1b-glink@l
116 write32(ctx
, buf
+ 16, 0x7d8802a6); // mflr r12
117 write32(ctx
, buf
+ 20, 0x7c0803a6); // mtlr r0
118 write32(ctx
, buf
+ 24, 0x7d6c5850); // sub r11,r11,r12
119 write32(ctx
, buf
+ 28, 0x3d8c0000 | ha(gotBcl
)); // addis 12,12,GOT+4-1b@ha
120 if (ha(gotBcl
) == ha(gotBcl
+ 4)) {
121 write32(ctx
, buf
+ 32,
122 0x800c0000 | lo(gotBcl
)); // lwz r0,r12,GOT+4-1b@l(r12)
123 write32(ctx
, buf
+ 36,
124 0x818c0000 | lo(gotBcl
+ 4)); // lwz r12,r12,GOT+8-1b@l(r12)
126 write32(ctx
, buf
+ 32,
127 0x840c0000 | lo(gotBcl
)); // lwzu r0,r12,GOT+4-1b@l(r12)
128 write32(ctx
, buf
+ 36, 0x818c0000 | 4); // lwz r12,r12,4(r12)
130 write32(ctx
, buf
+ 40, 0x7c0903a6); // mtctr 0
131 write32(ctx
, buf
+ 44, 0x7c0b5a14); // add r0,11,11
132 write32(ctx
, buf
+ 48, 0x7d605a14); // add r11,0,11
133 write32(ctx
, buf
+ 52, 0x4e800420); // bctr
136 write32(ctx
, buf
+ 0, 0x3d800000 | ha(got
+ 4)); // lis r12,GOT+4@ha
137 write32(ctx
, buf
+ 4, 0x3d6b0000 | ha(-glink
)); // addis r11,r11,-glink@ha
138 if (ha(got
+ 4) == ha(got
+ 8))
139 write32(ctx
, buf
+ 8, 0x800c0000 | lo(got
+ 4)); // lwz r0,GOT+4@l(r12)
141 write32(ctx
, buf
+ 8, 0x840c0000 | lo(got
+ 4)); // lwzu r0,GOT+4@l(r12)
142 write32(ctx
, buf
+ 12, 0x396b0000 | lo(-glink
)); // addi r11,r11,-glink@l
143 write32(ctx
, buf
+ 16, 0x7c0903a6); // mtctr r0
144 write32(ctx
, buf
+ 20, 0x7c0b5a14); // add r0,r11,r11
145 if (ha(got
+ 4) == ha(got
+ 8))
146 write32(ctx
, buf
+ 24, 0x818c0000 | lo(got
+ 8)); // lwz r12,GOT+8@l(r12)
148 write32(ctx
, buf
+ 24, 0x818c0000 | 4); // lwz r12,4(r12)
149 write32(ctx
, buf
+ 28, 0x7d605a14); // add r11,r0,r11
150 write32(ctx
, buf
+ 32, 0x4e800420); // bctr
154 // Pad with nop. They should not be executed.
155 for (; buf
< end
; buf
+= 4)
156 write32(ctx
, buf
, 0x60000000);
159 PPC::PPC(Ctx
&ctx
) : TargetInfo(ctx
) {
160 copyRel
= R_PPC_COPY
;
161 gotRel
= R_PPC_GLOB_DAT
;
162 pltRel
= R_PPC_JMP_SLOT
;
163 relativeRel
= R_PPC_RELATIVE
;
164 iRelativeRel
= R_PPC_IRELATIVE
;
165 symbolicRel
= R_PPC_ADDR32
;
166 gotHeaderEntriesNum
= 3;
167 gotPltHeaderEntriesNum
= 0;
174 tlsModuleIndexRel
= R_PPC_DTPMOD32
;
175 tlsOffsetRel
= R_PPC_DTPREL32
;
176 tlsGotRel
= R_PPC_TPREL32
;
178 defaultMaxPageSize
= 65536;
179 defaultImageBase
= 0x10000000;
181 write32(ctx
, trapInstr
.data(), 0x7fe00008);
184 void PPC::writeIplt(uint8_t *buf
, const Symbol
&sym
,
185 uint64_t /*pltEntryAddr*/) const {
186 // In -pie or -shared mode, assume r30 points to .got2+0x8000, and use a
187 // .got2.plt_pic32. thunk.
188 writePPC32PltCallStub(ctx
, buf
, sym
.getGotPltVA(ctx
), sym
.file
, 0x8000);
191 void PPC::writeGotHeader(uint8_t *buf
) const {
192 // _GLOBAL_OFFSET_TABLE_[0] = _DYNAMIC
193 // glibc stores _dl_runtime_resolve in _GLOBAL_OFFSET_TABLE_[1],
194 // link_map in _GLOBAL_OFFSET_TABLE_[2].
195 write32(ctx
, buf
, ctx
.mainPart
->dynamic
->getVA());
198 void PPC::writeGotPlt(uint8_t *buf
, const Symbol
&s
) const {
199 // Address of the symbol resolver stub in .glink .
201 ctx
.in
.plt
->getVA() + ctx
.in
.plt
->headerSize
+ 4 * s
.getPltIdx(ctx
));
204 bool PPC::needsThunk(RelExpr expr
, RelType type
, const InputFile
*file
,
205 uint64_t branchAddr
, const Symbol
&s
, int64_t a
) const {
206 if (type
!= R_PPC_LOCAL24PC
&& type
!= R_PPC_REL24
&& type
!= R_PPC_PLTREL24
)
212 return !PPC::inBranchRange(type
, branchAddr
, s
.getVA(ctx
, a
));
215 uint32_t PPC::getThunkSectionSpacing() const { return 0x2000000; }
217 bool PPC::inBranchRange(RelType type
, uint64_t src
, uint64_t dst
) const {
218 uint64_t offset
= dst
- src
;
219 if (type
== R_PPC_LOCAL24PC
|| type
== R_PPC_REL24
|| type
== R_PPC_PLTREL24
)
220 return isInt
<26>(offset
);
221 llvm_unreachable("unsupported relocation type used in branch");
224 RelExpr
PPC::getRelExpr(RelType type
, const Symbol
&s
,
225 const uint8_t *loc
) const {
229 case R_PPC_ADDR16_HA
:
230 case R_PPC_ADDR16_HI
:
231 case R_PPC_ADDR16_LO
:
236 case R_PPC_DTPREL16_HA
:
237 case R_PPC_DTPREL16_HI
:
238 case R_PPC_DTPREL16_LO
:
249 case R_PPC_LOCAL24PC
:
253 return RE_PPC32_PLTREL
;
254 case R_PPC_GOT_TLSGD16
:
256 case R_PPC_GOT_TLSLD16
:
258 case R_PPC_GOT_TPREL16
:
263 return R_TLSDESC_CALL
;
267 case R_PPC_TPREL16_HA
:
268 case R_PPC_TPREL16_LO
:
269 case R_PPC_TPREL16_HI
:
272 Err(ctx
) << getErrorLoc(ctx
, loc
) << "unknown relocation (" << type
.v
273 << ") against symbol " << &s
;
278 RelType
PPC::getDynRel(RelType type
) const {
279 if (type
== R_PPC_ADDR32
)
284 int64_t PPC::getImplicitAddend(const uint8_t *buf
, RelType type
) const {
293 case R_PPC_IRELATIVE
:
297 return SignExtend64
<32>(read32(ctx
, buf
));
299 InternalErr(ctx
, buf
) << "cannot read addend for relocation " << type
;
304 static std::pair
<RelType
, uint64_t> fromDTPREL(RelType type
, uint64_t val
) {
305 uint64_t dtpBiasedVal
= val
- 0x8000;
308 return {R_PPC64_ADDR16
, dtpBiasedVal
};
309 case R_PPC_DTPREL16_HA
:
310 return {R_PPC_ADDR16_HA
, dtpBiasedVal
};
311 case R_PPC_DTPREL16_HI
:
312 return {R_PPC_ADDR16_HI
, dtpBiasedVal
};
313 case R_PPC_DTPREL16_LO
:
314 return {R_PPC_ADDR16_LO
, dtpBiasedVal
};
316 return {R_PPC_ADDR32
, dtpBiasedVal
};
322 void PPC::relocate(uint8_t *loc
, const Relocation
&rel
, uint64_t val
) const {
324 std::tie(newType
, val
) = fromDTPREL(rel
.type
, val
);
327 checkIntUInt(ctx
, loc
, val
, 16, rel
);
328 write16(ctx
, loc
, val
);
331 case R_PPC_GOT_TLSGD16
:
332 case R_PPC_GOT_TLSLD16
:
333 case R_PPC_GOT_TPREL16
:
335 checkInt(ctx
, loc
, val
, 16, rel
);
336 write16(ctx
, loc
, val
);
338 case R_PPC_ADDR16_HA
:
339 case R_PPC_DTPREL16_HA
:
340 case R_PPC_GOT_TLSGD16_HA
:
341 case R_PPC_GOT_TLSLD16_HA
:
342 case R_PPC_GOT_TPREL16_HA
:
344 case R_PPC_TPREL16_HA
:
345 write16(ctx
, loc
, ha(val
));
347 case R_PPC_ADDR16_HI
:
348 case R_PPC_DTPREL16_HI
:
349 case R_PPC_GOT_TLSGD16_HI
:
350 case R_PPC_GOT_TLSLD16_HI
:
351 case R_PPC_GOT_TPREL16_HI
:
353 case R_PPC_TPREL16_HI
:
354 write16(ctx
, loc
, val
>> 16);
356 case R_PPC_ADDR16_LO
:
357 case R_PPC_DTPREL16_LO
:
358 case R_PPC_GOT_TLSGD16_LO
:
359 case R_PPC_GOT_TLSLD16_LO
:
360 case R_PPC_GOT_TPREL16_LO
:
362 case R_PPC_TPREL16_LO
:
363 write16(ctx
, loc
, val
);
367 write32(ctx
, loc
, val
);
370 uint32_t mask
= 0x0000FFFC;
371 checkInt(ctx
, loc
, val
, 16, rel
);
372 checkAlignment(ctx
, loc
, val
, 4, rel
);
373 write32(ctx
, loc
, (read32(ctx
, loc
) & ~mask
) | (val
& mask
));
378 case R_PPC_LOCAL24PC
:
379 case R_PPC_PLTREL24
: {
380 uint32_t mask
= 0x03FFFFFC;
381 checkInt(ctx
, loc
, val
, 26, rel
);
382 checkAlignment(ctx
, loc
, val
, 4, rel
);
383 write32(ctx
, loc
, (read32(ctx
, loc
) & ~mask
) | (val
& mask
));
387 llvm_unreachable("unknown relocation");
391 RelExpr
PPC::adjustTlsExpr(RelType type
, RelExpr expr
) const {
392 if (expr
== R_RELAX_TLS_GD_TO_IE
)
393 return R_RELAX_TLS_GD_TO_IE_GOT_OFF
;
394 if (expr
== R_RELAX_TLS_LD_TO_LE
)
395 return R_RELAX_TLS_LD_TO_LE_ABS
;
399 int PPC::getTlsGdRelaxSkip(RelType type
) const {
400 // A __tls_get_addr call instruction is marked with 2 relocations:
402 // R_PPC_TLSGD / R_PPC_TLSLD: marker relocation
403 // R_PPC_REL24: __tls_get_addr
405 // After the relaxation we no longer call __tls_get_addr and should skip both
406 // relocations to not create a false dependence on __tls_get_addr being
408 if (type
== R_PPC_TLSGD
|| type
== R_PPC_TLSLD
)
413 void PPC::relaxTlsGdToIe(uint8_t *loc
, const Relocation
&rel
,
414 uint64_t val
) const {
416 case R_PPC_GOT_TLSGD16
: {
417 // addi rT, rA, x@got@tlsgd --> lwz rT, x@got@tprel(rA)
418 uint32_t insn
= readFromHalf16(ctx
, loc
);
419 writeFromHalf16(ctx
, loc
, 0x80000000 | (insn
& 0x03ff0000));
420 relocateNoSym(loc
, R_PPC_GOT_TPREL16
, val
);
424 // bl __tls_get_addr(x@tldgd) --> add r3, r3, r2
425 write32(ctx
, loc
, 0x7c631214);
428 llvm_unreachable("unsupported relocation for TLS GD to IE relaxation");
432 void PPC::relaxTlsGdToLe(uint8_t *loc
, const Relocation
&rel
,
433 uint64_t val
) const {
435 case R_PPC_GOT_TLSGD16
:
436 // addi r3, r31, x@got@tlsgd --> addis r3, r2, x@tprel@ha
437 writeFromHalf16(ctx
, loc
, 0x3c620000 | ha(val
));
440 // bl __tls_get_addr(x@tldgd) --> add r3, r3, x@tprel@l
441 write32(ctx
, loc
, 0x38630000 | lo(val
));
444 llvm_unreachable("unsupported relocation for TLS GD to LE relaxation");
448 void PPC::relaxTlsLdToLe(uint8_t *loc
, const Relocation
&rel
,
449 uint64_t val
) const {
451 case R_PPC_GOT_TLSLD16
:
452 // addi r3, rA, x@got@tlsgd --> addis r3, r2, 0
453 writeFromHalf16(ctx
, loc
, 0x3c620000);
456 // r3+x@dtprel computes r3+x-0x8000, while we want it to compute r3+x@tprel
457 // = r3+x-0x7000, so add 4096 to r3.
458 // bl __tls_get_addr(x@tlsld) --> addi r3, r3, 4096
459 write32(ctx
, loc
, 0x38631000);
462 case R_PPC_DTPREL16_HA
:
463 case R_PPC_DTPREL16_HI
:
464 case R_PPC_DTPREL16_LO
:
465 relocate(loc
, rel
, val
);
468 llvm_unreachable("unsupported relocation for TLS LD to LE relaxation");
472 void PPC::relaxTlsIeToLe(uint8_t *loc
, const Relocation
&rel
,
473 uint64_t val
) const {
475 case R_PPC_GOT_TPREL16
: {
476 // lwz rT, x@got@tprel(rA) --> addis rT, r2, x@tprel@ha
477 uint32_t rt
= readFromHalf16(ctx
, loc
) & 0x03e00000;
478 writeFromHalf16(ctx
, loc
, 0x3c020000 | rt
| ha(val
));
482 uint32_t insn
= read32(ctx
, loc
);
483 if (insn
>> 26 != 31)
484 ErrAlways(ctx
) << "unrecognized instruction for IE to LE R_PPC_TLS";
485 // addi rT, rT, x@tls --> addi rT, rT, x@tprel@l
486 unsigned secondaryOp
= (read32(ctx
, loc
) & 0x000007fe) >> 1;
487 uint32_t dFormOp
= getPPCDFormOp(secondaryOp
);
488 if (dFormOp
== 0) { // Expecting a DS-Form instruction.
489 dFormOp
= getPPCDSFormOp(secondaryOp
);
491 ErrAlways(ctx
) << "unrecognized instruction for IE to LE R_PPC_TLS";
493 write32(ctx
, loc
, (dFormOp
| (insn
& 0x03ff0000) | lo(val
)));
497 llvm_unreachable("unsupported relocation for TLS IE to LE relaxation");
501 void PPC::relocateAlloc(InputSectionBase
&sec
, uint8_t *buf
) const {
502 uint64_t secAddr
= sec
.getOutputSection()->addr
;
503 if (auto *s
= dyn_cast
<InputSection
>(&sec
))
504 secAddr
+= s
->outSecOff
;
505 for (const Relocation
&rel
: sec
.relocs()) {
506 uint8_t *loc
= buf
+ rel
.offset
;
508 SignExtend64(sec
.getRelocTargetVA(ctx
, rel
, secAddr
+ rel
.offset
), 32);
510 case R_RELAX_TLS_GD_TO_IE_GOT_OFF
:
511 relaxTlsGdToIe(loc
, rel
, val
);
513 case R_RELAX_TLS_GD_TO_LE
:
514 relaxTlsGdToLe(loc
, rel
, val
);
516 case R_RELAX_TLS_LD_TO_LE_ABS
:
517 relaxTlsLdToLe(loc
, rel
, val
);
519 case R_RELAX_TLS_IE_TO_LE
:
520 relaxTlsIeToLe(loc
, rel
, val
);
523 relocate(loc
, rel
, val
);
529 void elf::setPPCTargetInfo(Ctx
&ctx
) { ctx
.target
.reset(new PPC(ctx
)); }