diff --git a/lib/ExecutionEngine/RuntimeDyld/Targets/RuntimeDyldMachOARM.h b/lib/ExecutionEngine/RuntimeDyld/Targets/RuntimeDyldMachOARM.h index 990629de2f1..16a0f6ef2a7 100644 --- a/lib/ExecutionEngine/RuntimeDyld/Targets/RuntimeDyldMachOARM.h +++ b/lib/ExecutionEngine/RuntimeDyld/Targets/RuntimeDyldMachOARM.h @@ -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 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); diff --git a/test/ExecutionEngine/RuntimeDyld/ARM/MachO_Thumb_Relocations.s b/test/ExecutionEngine/RuntimeDyld/ARM/MachO_Thumb_Relocations.s index 489418b7099..e2e6e11e7d9 100644 --- a/test/ExecutionEngine/RuntimeDyld/ARM/MachO_Thumb_Relocations.s +++ b/test/ExecutionEngine/RuntimeDyld/ARM/MachO_Thumb_Relocations.s @@ -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 bar + .globl thumb_caller_thumb_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 16 + .thumb_func thumb_caller_thumb_callee +thumb_caller_thumb_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. -# -# 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: decode_operand(insn3, 0) = stub_addr(MachO_Thumb.o, __text, baz) - (insn3 + 4) -insn3: - bl baz + .globl arm_caller_thumb_callee + .p2align 1 + .code 16 + .thumb_func arm_caller_thumb_callee +arm_caller_thumb_callee: + nop -# 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 + .globl thumb_caller_arm_callee + .p2align 1 + .code 32 +thumb_caller_arm_callee: + nop - .section __DATA,__data - .align 2 -foo: - .long 0 + .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, 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: *{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