[RuntimeDyld][MachO] Properly handle thumb to thumb calls within a section.
authorLang Hames <lhames@gmail.com>
Wed, 9 May 2018 01:38:13 +0000 (01:38 +0000)
committerLang Hames <lhames@gmail.com>
Wed, 9 May 2018 01:38:13 +0000 (01:38 +0000)
Previously thumb bits were only checked for external relocations (thumb to arm
code and vice-versa). This patch adds detection for thumb callees in the same
section asthe (also thumb) caller.

The MachO/Thumb test case is updated to cover this, and redundant checks
(handled by the MachO/ARM test) are removed.

llvm-svn: 331838

llvm/lib/ExecutionEngine/RuntimeDyld/Targets/RuntimeDyldMachOARM.h
llvm/test/ExecutionEngine/RuntimeDyld/ARM/MachO_Thumb_Relocations.s

index 990629d..16a0f6e 100644 (file)
@@ -47,6 +47,18 @@ public:
     return Addr;
   }
 
+  bool isAddrTargetThumb(unsigned SectionID, uint64_t Offset) {
+    auto TargetObjAddr = Sections[SectionID].getObjAddress() + Offset;
+    for (auto &KV : GlobalSymbolTable) {
+      auto &Entry = KV.second;
+      auto SymbolObjAddr =
+          Sections[Entry.getSectionID()].getObjAddress() + Entry.getOffset();
+      if (TargetObjAddr == SymbolObjAddr)
+        return (Entry.getFlags().getTargetFlags() & ARMJITSymbolFlags::Thumb);
+    }
+    return false;
+  }
+
   Expected<int64_t> decodeAddend(const RelocationEntry &RE) const {
     const SectionEntry &Section = Sections[RE.SectionID];
     uint8_t *LocalAddress = Section.getAddressWithOffset(RE.Offset);
@@ -161,12 +173,18 @@ public:
     // the value as being a thumb stub: we don't want to mix it up with an ARM
     // stub targeting the same function.
     if (RE.RelType == MachO::ARM_THUMB_RELOC_BR22)
-      Value.IsStubThumb = TargetIsLocalThumbFunc;
+      Value.IsStubThumb = true;
 
     if (RE.IsPCRel)
       makeValueAddendPCRel(Value, RelI,
                            (RE.RelType == MachO::ARM_THUMB_RELOC_BR22) ? 4 : 8);
 
+    // If this is a non-external branch target check whether Value points to a
+    // thumb func.
+    if (!Value.SymbolName && (RelType == MachO::ARM_RELOC_BR24 ||
+                              RelType == MachO::ARM_THUMB_RELOC_BR22))
+      RE.IsTargetThumbFunc = isAddrTargetThumb(Value.SectionID, Value.Offset);
+
     if (RE.RelType == MachO::ARM_RELOC_BR24 ||
         RE.RelType == MachO::ARM_THUMB_RELOC_BR22)
       processBranchRelocation(RE, Value, Stubs);
index 489418b..e2e6e11 100644 (file)
@@ -5,48 +5,57 @@
         .section        __TEXT,__text,regular,pure_instructions
         .syntax unified
 
-# Add 'aaa' to the common symbols to make sure 'baz' isn't at the start of the
-# section. This ensures that we test VANILLA relocation addends correctly.
-        .comm   aaa, 4, 2
-        .comm   baz, 4, 2
+        .globl  thumb_caller_thumb_callee
+        .p2align        1
+        .code   16
+        .thumb_func     thumb_caller_thumb_callee
+thumb_caller_thumb_callee:
+        nop
 
+        .globl  arm_caller_thumb_callee
+        .p2align        1
+        .code   16
+        .thumb_func     arm_caller_thumb_callee
+arm_caller_thumb_callee:
+        nop
 
-        .globl  bar
+        .globl  thumb_caller_arm_callee
         .p2align        1
-        .code   16                      @ @bar
-        .thumb_func     bar
-
-bar:
-# Check lower 16-bits of section difference relocation
-# rtdyld-check: decode_operand(insn1, 1) = (foo-(nextPC+8))[15:0]
-insn1:
-        movw    r0, :lower16:(foo-(nextPC+8))
-# Check upper 16-bits of section difference relocation
-# rtdyld-check: decode_operand(insn2, 2) = (foo-(nextPC+8))[31:16]
-insn2:
-        movt    r0, :upper16:(foo-(nextPC+8))
-nextPC:
+        .code   32
+thumb_caller_arm_callee:
         nop
 
-# Check stub generation for external symbols by referencing a common symbol, 'baz'.
-# Check both the content of the stub, and the reference to the stub.
-# Stub should contain '0xf000f8df' (ldr.w pc, [pc]), followed by the target.
+        .globl  thumb_caller
+        .p2align        1
+        .code   16
+        .thumb_func     thumb_caller
+thumb_caller:
+        nop
+
+# Check that stubs for thumb callers use thumb code (not arm), and that thumb
+# callees have the low bit set on their addresses.
 #
-# rtdyld-check: *{4}(stub_addr(MachO_Thumb.o, __text, baz)) = 0xf000f8df
-# rtdyld-check: *{4}(stub_addr(MachO_Thumb.o, __text, baz) + 4) = baz
+# rtdyld-check: *{4}(stub_addr(MachO_Thumb.o, __text, thumb_caller_thumb_callee)) = 0xf000f8df
+# rtdyld-check: *{4}(stub_addr(MachO_Thumb.o, __text, thumb_caller_thumb_callee) + 4) = (thumb_caller_thumb_callee | 0x1)
+        bl thumb_caller_thumb_callee
+
+# Check that arm callees do not have the low bit set on their addresses.
 #
-# rtdyld-check: decode_operand(insn3, 0) = stub_addr(MachO_Thumb.o, __text, baz) - (insn3 + 4)
-insn3:
-        bl      baz
-
-# Check stub generation for internal symbols by referencing 'bar'.
-# rtdyld-check: *{4}(stub_addr(MachO_Thumb.o, __text, bar) + 4) = bar & 0xfffffffffffffffe
-insn4:
-        bl      bar
-
-        .section       __DATA,__data
-       .align  2
-foo:
-       .long   0
+# rtdyld-check: *{4}(stub_addr(MachO_Thumb.o, __text, thumb_caller_arm_callee)) = 0xf000f8df
+# rtdyld-check: *{4}(stub_addr(MachO_Thumb.o, __text, thumb_caller_arm_callee) + 4) = thumb_caller_arm_callee
+        bl thumb_caller_arm_callee
+
+        .globl  arm_caller
+        .p2align        2
+        .code   32
+arm_caller:
+        nop
+
+# Check that stubs for arm callers use arm code (not thumb), and that thumb
+# callees have the low bit set on their addresses.
+# rtdyld-check: *{4}(stub_addr(MachO_Thumb.o, __text, arm_caller_thumb_callee)) = 0xe51ff004
+# rtdyld-check: *{4}(stub_addr(MachO_Thumb.o, __text, arm_caller_thumb_callee) + 4) = (arm_caller_thumb_callee | 0x1)
+        bl      arm_caller_thumb_callee
+        nop
 
 .subsections_via_symbols