[llvm-branch-commits] [lld] [ELF][PowerPC] Don't assume TOC pointer is valid in IPLT entries (PR #207555)
Jessica Clarke via llvm-branch-commits
llvm-branch-commits at lists.llvm.org
Thu Jul 23 10:53:10 PDT 2026
================
@@ -1326,34 +1327,52 @@ void elf::writePPC32PltCallStub(Ctx &ctx, uint8_t *buf, uint64_t gotPltVA,
return;
}
uint32_t offset;
- if (addend >= 0x8000) {
+ uint32_t reg;
+ if (!addend) {
+ // We're a (position-independent) IPLT entry, so cannot assume anything
+ // about what value the caller left in r30 as this could be an indirect
+ // call.
+ write32(ctx, buf + 0, 0x7c0802a6); // mflr r0
+ write32(ctx, buf + 4, 0x429f0005); // bcl 20, 31, 1f
+ write32(ctx, buf + 8, 0x7d6802a6); // 1: mflr r11
+ write32(ctx, buf + 12, 0x7c0803a6); // mtlr r0
+ offset = gotPltVA - p - 8;
+ reg = 11;
+ buf += 16;
+ p += 16;
----------------
jrtc27 wrote:
i.e.:
```diff
diff --git a/lld/ELF/Thunks.cpp b/lld/ELF/Thunks.cpp
index eea74903b211..c9cbe95fced8 100644
--- a/lld/ELF/Thunks.cpp
+++ b/lld/ELF/Thunks.cpp
@@ -1328,6 +1328,7 @@ void elf::writePPC32PltCallStub(Ctx &ctx, uint8_t *buf, uint64_t p,
}
uint32_t offset;
uint32_t reg;
+ uint64_t written = 0;
if (!addend) {
// We're a (position-independent) IPLT entry, so cannot assume anything
// about what value the caller left in r30 as this could be an indirect
@@ -1338,8 +1339,7 @@ void elf::writePPC32PltCallStub(Ctx &ctx, uint8_t *buf, uint64_t p,
write32(ctx, buf + 12, 0x7c0803a6); // mtlr r0
offset = gotPltVA - p - 8;
reg = 11;
- buf += 16;
- p += 16;
+ written = 16;
} else if (*addend >= 0x8000) {
// The stub loads an address relative to r30 (.got2+Addend). Addend is
// almost always 0x8000. The address of .got2 is different in another object
@@ -1356,17 +1356,17 @@ void elf::writePPC32PltCallStub(Ctx &ctx, uint8_t *buf, uint64_t p,
}
uint16_t ha = (offset + 0x8000) >> 16, l = (uint16_t)offset;
if (ha == 0) {
- write32(ctx, buf + 0,
- 0x81600000 | (reg << 16) | l); // lwz r11,l(r[11|30])
- write32(ctx, buf + 4, 0x7d6903a6); // mtctr r11
- write32(ctx, buf + 8, 0x4e800420); // bctr
- write32(ctx, buf + 12, 0x60000000); // nop
+ write32(ctx, buf + written + 0,
+ 0x81600000 | (reg << 16) | l); // lwz r11,l(r[11|30])
+ write32(ctx, buf + written + 4, 0x7d6903a6); // mtctr r11
+ write32(ctx, buf + written + 8, 0x4e800420); // bctr
+ write32(ctx, buf + written + 12, 0x60000000); // nop
} else {
- write32(ctx, buf + 0,
- 0x3d600000 | (reg << 16) | ha); // addis r11,r[11|30],ha
- write32(ctx, buf + 4, 0x816b0000 | l); // lwz r11,l(r11)
- write32(ctx, buf + 8, 0x7d6903a6); // mtctr r11
- write32(ctx, buf + 12, 0x4e800420); // bctr
+ write32(ctx, buf + written + 0,
+ 0x3d600000 | (reg << 16) | ha); // addis r11,r[11|30],ha
+ write32(ctx, buf + written + 4, 0x816b0000 | l); // lwz r11,l(r11)
+ write32(ctx, buf + written + 8, 0x7d6903a6); // mtctr r11
+ write32(ctx, buf + written + 12, 0x4e800420); // bctr
}
}
```
https://github.com/llvm/llvm-project/pull/207555
More information about the llvm-branch-commits
mailing list