aboutsummaryrefslogtreecommitdiff
path: root/lld/ELF/Arch/PPC.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lld/ELF/Arch/PPC.cpp')
-rw-r--r--lld/ELF/Arch/PPC.cpp19
1 files changed, 15 insertions, 4 deletions
diff --git a/lld/ELF/Arch/PPC.cpp b/lld/ELF/Arch/PPC.cpp
index 87942c1e9245..1b0838456428 100644
--- a/lld/ELF/Arch/PPC.cpp
+++ b/lld/ELF/Arch/PPC.cpp
@@ -278,9 +278,16 @@ RelType PPC::getDynRel(RelType type) const {
int64_t PPC::getImplicitAddend(const uint8_t *buf, RelType type) const {
switch (type) {
case R_PPC_NONE:
+ case R_PPC_GLOB_DAT:
+ case R_PPC_JMP_SLOT:
return 0;
case R_PPC_ADDR32:
case R_PPC_REL32:
+ case R_PPC_RELATIVE:
+ case R_PPC_IRELATIVE:
+ case R_PPC_DTPMOD32:
+ case R_PPC_DTPREL32:
+ case R_PPC_TPREL32:
return SignExtend64<32>(read32(buf));
default:
internalLinkerError(getErrorLocation(buf),
@@ -471,10 +478,14 @@ void PPC::relaxTlsIeToLe(uint8_t *loc, const Relocation &rel,
if (insn >> 26 != 31)
error("unrecognized instruction for IE to LE R_PPC_TLS");
// addi rT, rT, x@tls --> addi rT, rT, x@tprel@l
- uint32_t dFormOp = getPPCDFormOp((read32(loc) & 0x000007fe) >> 1);
- if (dFormOp == 0)
- error("unrecognized instruction for IE to LE R_PPC_TLS");
- write32(loc, (dFormOp << 26) | (insn & 0x03ff0000) | lo(val));
+ unsigned secondaryOp = (read32(loc) & 0x000007fe) >> 1;
+ uint32_t dFormOp = getPPCDFormOp(secondaryOp);
+ if (dFormOp == 0) { // Expecting a DS-Form instruction.
+ dFormOp = getPPCDSFormOp(secondaryOp);
+ if (dFormOp == 0)
+ error("unrecognized instruction for IE to LE R_PPC_TLS");
+ }
+ write32(loc, (dFormOp | (insn & 0x03ff0000) | lo(val)));
break;
}
default: