[JITLink][MachO][arm64] Mask high bits out of immediate for LDRLiteral19.
authorLang Hames <lhames@gmail.com>
Wed, 13 Oct 2021 04:51:12 +0000 (21:51 -0700)
committerLang Hames <lhames@gmail.com>
Wed, 13 Oct 2021 05:19:47 +0000 (22:19 -0700)
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

llvm/lib/ExecutionEngine/JITLink/MachO_arm64.cpp

index bf81fc4f8db9c285ba477e050ea98af93e8cfaf8..af1d88333c85912f592ee756e763dacea8f2e909 100644 (file)
@@ -627,7 +627,8 @@ private:
       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;