[RuntimeDyld][MachO] Properly handle thumb to thumb calls within a section.

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
This commit is contained in:
Lang Hames 2018-05-09 01:38:13 +00:00
parent f5611cc773
commit cc9d8f83c8
2 changed files with 66 additions and 39 deletions

View 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);

View 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 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