Negative deltas for LDRLiteral19 have their high bits set. If these bits aren't
masked out then they will overwrite other instruction bits, leading to a bogus
encoding.
This long-standing relocation bug was exposed by
e50aea58d59, "[JITLink][ORC]
Major JITLinkMemoryManager refactor.", which caused memory layouts to be
reordered, which in turn lead to a previously unseen negative delta. (Unseen
because LDRLiteral19s were only created in JITLink passes where they always
pointed at segments that were layed-out-after in the old layout).
No testcase yet: Our existing regression test infrastructure is good at checking
that operand bits are correct, but provides no easy way to test for bad opcode
bits. I'll have a think about the right way to approach this.
https://llvm.org/PR52153
if (Delta < -(1 << 20) || Delta > ((1 << 20) - 1))
return makeTargetOutOfRangeError(G, B, E);
- uint32_t EncodedImm = (static_cast<uint32_t>(Delta) >> 2) << 5;
+ uint32_t EncodedImm =
+ ((static_cast<uint32_t>(Delta) >> 2) & 0x7ffff) << 5;
uint32_t FixedInstr = RawInstr | EncodedImm;
*(ulittle32_t *)FixupPtr = FixedInstr;
break;