diff options
| -rw-r--r-- | lld/lib/ReaderWriter/MachO/ArchHandler_arm.cpp | 160 | ||||
| -rw-r--r-- | lld/lib/ReaderWriter/MachO/MachONormalizedFileFromAtoms.cpp | 5 | ||||
| -rw-r--r-- | lld/test/mach-o/arm-interworking.yaml | 361 | ||||
| -rw-r--r-- | lld/test/mach-o/hello-world-armv7.yaml | 103 |
4 files changed, 584 insertions, 45 deletions
diff --git a/lld/lib/ReaderWriter/MachO/ArchHandler_arm.cpp b/lld/lib/ReaderWriter/MachO/ArchHandler_arm.cpp index 9dfab0ea78c..4a775ab0c89 100644 --- a/lld/lib/ReaderWriter/MachO/ArchHandler_arm.cpp +++ b/lld/lib/ReaderWriter/MachO/ArchHandler_arm.cpp @@ -130,13 +130,15 @@ private: static bool isThumbMovt(uint32_t instruction); static bool isArmMovw(uint32_t instruction); static bool isArmMovt(uint32_t instruction); - static int32_t getDisplacementFromThumbBranch(uint32_t instruction); + static int32_t getDisplacementFromThumbBranch(uint32_t instruction, uint32_t); static int32_t getDisplacementFromArmBranch(uint32_t instruction); static uint16_t getWordFromThumbMov(uint32_t instruction); static uint16_t getWordFromArmMov(uint32_t instruction); static uint32_t clearThumbBit(uint32_t value, const Atom *target); - static uint32_t setDisplacementInArmBranch(uint32_t instr, int32_t disp); - static uint32_t setDisplacementInThumbBranch(uint32_t instr, int32_t disp); + static uint32_t setDisplacementInArmBranch(uint32_t instr, int32_t disp, + bool targetIsThumb); + static uint32_t setDisplacementInThumbBranch(uint32_t instr, uint32_t ia, + int32_t disp, bool targetThumb); static uint32_t setWordFromThumbMov(uint32_t instruction, uint16_t word); static uint32_t setWordFromArmMov(uint32_t instruction, uint16_t word); @@ -144,12 +146,14 @@ private: void applyFixupFinal(const Reference &ref, uint8_t *location, uint64_t fixupAddress, uint64_t targetAddress, - uint64_t inAtomAddress, bool &thumbMode); + uint64_t inAtomAddress, bool &thumbMode, + bool targetIsThumb); void applyFixupRelocatable(const Reference &ref, uint8_t *location, uint64_t fixupAddress, uint64_t targetAddress, - uint64_t inAtomAddress, bool &thumbMode); + uint64_t inAtomAddress, bool &thumbMode, + bool targetIsThumb); const bool _swap; }; @@ -256,23 +260,7 @@ bool ArchHandler_arm::isPairedReloc(const Relocation &reloc) { } } -int32_t ArchHandler_arm::getDisplacementFromThumbBranch(uint32_t instruction) { - uint32_t s = (instruction >> 10) & 0x1; - uint32_t j1 = (instruction >> 29) & 0x1; - uint32_t j2 = (instruction >> 27) & 0x1; - uint32_t imm10 = instruction & 0x3FF; - uint32_t imm11 = (instruction >> 16) & 0x7FF; - uint32_t i1 = (j1 == s); - uint32_t i2 = (j2 == s); - uint32_t dis = - (s << 24) | (i1 << 23) | (i2 << 22) | (imm10 << 12) | (imm11 << 1); - int32_t sdis = dis; - if (s) - return (sdis | 0xFE000000); - else - return sdis; -} - +/// Extract displacement from an ARM b/bl/blx instruction. int32_t ArchHandler_arm::getDisplacementFromArmBranch(uint32_t instruction) { // Sign-extend imm24 int32_t displacement = (instruction & 0x00FFFFFF) << 2; @@ -284,18 +272,88 @@ int32_t ArchHandler_arm::getDisplacementFromArmBranch(uint32_t instruction) { return displacement; } +/// Update an ARM b/bl/blx instruction, switching bl <-> blx as needed. uint32_t ArchHandler_arm::setDisplacementInArmBranch(uint32_t instruction, - int32_t displacement) { - // FIXME: handle BLX and out-of-range. + int32_t displacement, + bool targetIsThumb) { + assert((displacement <= 33554428) && (displacement > (-33554432)) + && "arm branch out of range"); + bool is_blx = ((instruction & 0xF0000000) == 0xF0000000); uint32_t newInstruction = (instruction & 0xFF000000); - newInstruction |= ((displacement >> 2) & 0x00FFFFFF); + uint32_t h = 0; + if (targetIsThumb) { + // Force use of BLX. + newInstruction = 0xFA000000; + if (!is_blx) { + bool isConditionalBranch = ((instruction & 0xF0000000) != 0xE0000000); + assert(!isConditionalBranch && "no conditional arm blx"); + bool is_bl = ((instruction & 0xFF000000) == 0xEB000000); + assert(is_bl && "no arm pc-rel BX instruction"); + } + if (displacement & 2) + h = 1; + } + else { + // Force use of B/BL. + if (is_blx) + newInstruction = 0xEB000000; + } + newInstruction |= (h << 24) | ((displacement >> 2) & 0x00FFFFFF); return newInstruction; } +/// Extract displacement from a thumb b/bl/blx instruction. +int32_t ArchHandler_arm::getDisplacementFromThumbBranch(uint32_t instruction, + uint32_t instrAddr) { + bool is_blx = ((instruction & 0xD000F800) == 0xC000F000); + uint32_t s = (instruction >> 10) & 0x1; + uint32_t j1 = (instruction >> 29) & 0x1; + uint32_t j2 = (instruction >> 27) & 0x1; + uint32_t imm10 = instruction & 0x3FF; + uint32_t imm11 = (instruction >> 16) & 0x7FF; + uint32_t i1 = (j1 == s); + uint32_t i2 = (j2 == s); + uint32_t dis = + (s << 24) | (i1 << 23) | (i2 << 22) | (imm10 << 12) | (imm11 << 1); + int32_t sdis = dis; + int32_t result = s ? (sdis | 0xFE000000) : sdis; + if (is_blx && (instrAddr & 0x2)) { + // The thumb blx instruction always has low bit of imm11 as zero. The way + // a 2-byte aligned blx can branch to a 4-byte aligned ARM target is that + // the blx instruction always 4-byte aligns the pc before adding the + // displacement from the blx. We must emulate that when decoding this. + result -= 2; + } + return result; +} + +/// Update a thumb b/bl/blx instruction, switching bl <-> blx as needed. uint32_t ArchHandler_arm::setDisplacementInThumbBranch(uint32_t instruction, - int32_t displacement) { - // FIXME: handle BLX and out-of-range. + uint32_t instrAddr, + int32_t displacement, + bool targetIsThumb) { + assert((displacement <= 16777214) && (displacement > (-16777216)) + && "thumb branch out of range"); + bool is_bl = ((instruction & 0xD000F800) == 0xD000F000); + bool is_blx = ((instruction & 0xD000F800) == 0xC000F000); + bool is_b = ((instruction & 0xD000F800) == 0x9000F000); uint32_t newInstruction = (instruction & 0xF800D000); + if (is_bl || is_blx) { + if (targetIsThumb) { + newInstruction = 0xD000F000; // Use bl + } else { + newInstruction = 0xC000F000; // Use blx + // See note in getDisplacementFromThumbBranch() about blx. + if (instrAddr & 0x2) + displacement += 2; + } + } else if (is_b) { + assert(!targetIsThumb && "no pc-rel thumb branch instruction that " + "switches to arm mode"); + } + else { + llvm_unreachable("thumb branch22 reloc on a non-branch instruction"); + } uint32_t s = (uint32_t)(displacement >> 24) & 0x1; uint32_t i1 = (uint32_t)(displacement >> 23) & 0x1; uint32_t i2 = (uint32_t)(displacement >> 22) & 0x1; @@ -392,19 +450,19 @@ std::error_code ArchHandler_arm::getReferenceInfo( if (E ec = atomFromSymbolIndex(reloc.symbol, target)) return ec; // Instruction contains branch to addend. - displacement = getDisplacementFromThumbBranch(instruction); + displacement = getDisplacementFromThumbBranch(instruction, fixupAddress); *addend = fixupAddress + 4 + displacement; return std::error_code(); case ARM_THUMB_RELOC_BR22 | rPcRel | rLength4: // ex: bl _foo (and _foo is defined) *kind = thumb_b22; - displacement = getDisplacementFromThumbBranch(instruction); + displacement = getDisplacementFromThumbBranch(instruction, fixupAddress); targetAddress = fixupAddress + 4 + displacement; return atomFromAddress(reloc.symbol, targetAddress, target, addend); case ARM_THUMB_RELOC_BR22 | rScattered | rPcRel | rLength4: // ex: bl _foo+4 (and _foo is defined) *kind = thumb_b22; - displacement = getDisplacementFromThumbBranch(instruction); + displacement = getDisplacementFromThumbBranch(instruction, fixupAddress); targetAddress = fixupAddress + 4 + displacement; if (E ec = atomFromAddress(0, reloc.value, target, addend)) return ec; @@ -745,13 +803,14 @@ void ArchHandler_arm::applyFixupFinal(const Reference &ref, uint8_t *location, uint64_t fixupAddress, uint64_t targetAddress, uint64_t inAtomAddress, - bool &thumbMode) { + bool &thumbMode, bool targetIsThumb) { if (ref.kindNamespace() != Reference::KindNamespace::mach_o) return; assert(ref.kindArch() == Reference::KindArch::ARM); int32_t *loc32 = reinterpret_cast<int32_t *>(location); int32_t displacement; uint16_t value16; + uint32_t value32; switch (ref.kindValue()) { case modeThumbCode: thumbMode = true; @@ -764,7 +823,9 @@ void ArchHandler_arm::applyFixupFinal(const Reference &ref, uint8_t *location, case thumb_b22: assert(thumbMode); displacement = (targetAddress - (fixupAddress + 4)) + ref.addend(); - write32(*loc32, _swap, setDisplacementInThumbBranch(*loc32, displacement)); + value32 = setDisplacementInThumbBranch(*loc32, fixupAddress, displacement, + targetIsThumb); + write32(*loc32, _swap, value32); break; case thumb_movw: assert(thumbMode); @@ -789,7 +850,8 @@ void ArchHandler_arm::applyFixupFinal(const Reference &ref, uint8_t *location, case arm_b24: assert(!thumbMode); displacement = (targetAddress - (fixupAddress + 8)) + ref.addend(); - *loc32 = setDisplacementInArmBranch(*loc32, displacement); + value32 = setDisplacementInArmBranch(*loc32, displacement, targetIsThumb); + write32(*loc32, _swap, value32); break; case arm_movw: assert(!thumbMode); @@ -812,7 +874,10 @@ void ArchHandler_arm::applyFixupFinal(const Reference &ref, uint8_t *location, write32(*loc32, _swap, setWordFromArmMov(*loc32, value16)); break; case pointer32: - write32(*loc32, _swap, targetAddress + ref.addend()); + if (targetIsThumb) + write32(*loc32, _swap, targetAddress + ref.addend() + 1); + else + write32(*loc32, _swap, targetAddress + ref.addend()); break; case delta32: write32(*loc32, _swap, targetAddress - fixupAddress + ref.addend()); @@ -839,18 +904,20 @@ void ArchHandler_arm::generateAtomContent(const DefinedAtom &atom, uint32_t offset = ref->offsetInAtom(); const Atom *target = ref->target(); uint64_t targetAddress = 0; - if (isa<DefinedAtom>(target)) + bool targetIsThumb = false; + if (const DefinedAtom *defTarg = dyn_cast<DefinedAtom>(target)) { targetAddress = findAddress(*target); + targetIsThumb = isThumbFunction(*defTarg); + } uint64_t atomAddress = findAddress(atom); uint64_t fixupAddress = atomAddress + offset; if (relocatable) { - applyFixupRelocatable(*ref, &atomContentBuffer[offset], - fixupAddress, targetAddress, - atomAddress, thumbMode); + applyFixupRelocatable(*ref, &atomContentBuffer[offset], fixupAddress, + targetAddress, atomAddress, thumbMode, + targetIsThumb); } else { - applyFixupFinal(*ref, &atomContentBuffer[offset], - fixupAddress, targetAddress, - atomAddress, thumbMode); + applyFixupFinal(*ref, &atomContentBuffer[offset], fixupAddress, + targetAddress, atomAddress, thumbMode, targetIsThumb); } } } @@ -882,11 +949,13 @@ void ArchHandler_arm::applyFixupRelocatable(const Reference &ref, uint64_t fixupAddress, uint64_t targetAddress, uint64_t inAtomAddress, - bool &thumbMode) { + bool &thumbMode, + bool targetIsThumb) { bool useExternalReloc = useExternalRelocationTo(*ref.target()); int32_t *loc32 = reinterpret_cast<int32_t *>(location); int32_t displacement; uint16_t value16; + uint32_t value32; switch (ref.kindValue()) { case modeThumbCode: thumbMode = true; @@ -902,7 +971,9 @@ void ArchHandler_arm::applyFixupRelocatable(const Reference &ref, displacement = (ref.addend() - (fixupAddress + 4)); else displacement = (targetAddress - (fixupAddress + 4)) + ref.addend(); - write32(*loc32, _swap, setDisplacementInThumbBranch(*loc32, displacement)); + value32 = setDisplacementInThumbBranch(*loc32, fixupAddress, displacement, + targetIsThumb); + write32(*loc32, _swap, value32); break; case thumb_movw: assert(thumbMode); @@ -936,7 +1007,8 @@ void ArchHandler_arm::applyFixupRelocatable(const Reference &ref, displacement = (ref.addend() - (fixupAddress + 8)); else displacement = (targetAddress - (fixupAddress + 8)) + ref.addend(); - write32(*loc32, _swap, setDisplacementInArmBranch(*loc32, displacement)); + value32 = setDisplacementInArmBranch(*loc32, displacement, targetIsThumb); + write32(*loc32, _swap, value32); break; case arm_movw: assert(!thumbMode); diff --git a/lld/lib/ReaderWriter/MachO/MachONormalizedFileFromAtoms.cpp b/lld/lib/ReaderWriter/MachO/MachONormalizedFileFromAtoms.cpp index adda9b723d7..e181a212de3 100644 --- a/lld/lib/ReaderWriter/MachO/MachONormalizedFileFromAtoms.cpp +++ b/lld/lib/ReaderWriter/MachO/MachONormalizedFileFromAtoms.cpp @@ -563,7 +563,10 @@ void Util::copySections(NormalizedFile &file) { void Util::copyEntryPointAddress(NormalizedFile &nFile) { if (_context.outputTypeHasEntry()) { - nFile.entryAddress = _atomToAddress[_entryAtom]; + if (_archHandler.isThumbFunction(*_entryAtom)) + nFile.entryAddress = (_atomToAddress[_entryAtom] | 1); + else + nFile.entryAddress = _atomToAddress[_entryAtom]; } } diff --git a/lld/test/mach-o/arm-interworking.yaml b/lld/test/mach-o/arm-interworking.yaml new file mode 100644 index 00000000000..59e311f91b2 --- /dev/null +++ b/lld/test/mach-o/arm-interworking.yaml @@ -0,0 +1,361 @@ +# RUN: lld -flavor darwin -arch armv7 -r -print_atoms %s -o %t | FileCheck %s \ +# RUN: && lld -flavor darwin -arch armv7 -dylib -print_atoms %t -o %t2 | FileCheck %s \ +# RUN: && macho-dump --dump-section-data %t2 | FileCheck -check-prefix=CODE %s +# +# Test thumb and arm branches round trip through -r. +# Test bl/blx instructions are fixed up properly. +# +# + +--- !mach-o +arch: armv7 +file-type: MH_OBJECT +flags: [ MH_SUBSECTIONS_VIA_SYMBOLS ] +sections: + - segment: __TEXT + section: __text + type: S_REGULAR + attributes: [ S_ATTR_PURE_INSTRUCTIONS, S_ATTR_SOME_INSTRUCTIONS ] + alignment: 2 + address: 0x0000000000000000 + content: [ 0xFF, 0xF7, 0xFE, 0xFF, 0xC0, 0x46, 0xFF, 0xF7, + 0xFC, 0xEF, 0xC0, 0x46, 0xFF, 0xF7, 0xF8, 0xEF, + 0xFF, 0xF7, 0xF6, 0xFF, 0xC0, 0x46, 0xFF, 0xF7, + 0xF3, 0xFF, 0xC0, 0x46, 0x00, 0xF0, 0x06, 0xE8, + 0xC0, 0x46, 0x00, 0xF0, 0x03, 0xF8, 0x00, 0xF0, + 0x02, 0xF8, 0x70, 0x47, 0x70, 0x47, 0x70, 0x47 ] + relocations: + - offset: 0x00000026 + type: ARM_THUMB_RELOC_BR22 + length: 2 + pc-rel: true + extern: false + symbol: 1 + - offset: 0x00000022 + type: ARM_THUMB_RELOC_BR22 + length: 2 + pc-rel: true + extern: false + symbol: 1 + - offset: 0x0000001C + type: ARM_THUMB_RELOC_BR22 + length: 2 + pc-rel: true + extern: false + symbol: 1 + - offset: 0x00000016 + type: ARM_THUMB_RELOC_BR22 + length: 2 + pc-rel: true + extern: false + symbol: 1 + - offset: 0x00000010 + type: ARM_THUMB_RELOC_BR22 + length: 2 + pc-rel: true + extern: false + symbol: 1 + - offset: 0x0000000C + type: ARM_THUMB_RELOC_BR22 + length: 2 + pc-rel: true + extern: true + symbol: 5 + - offset: 0x00000006 + type: ARM_THUMB_RELOC_BR22 + length: 2 + pc-rel: true + extern: true + symbol: 5 + - offset: 0x00000000 + type: ARM_THUMB_RELOC_BR22 + length: 2 + pc-rel: true + extern: true + symbol: 4 + - segment: __DATA + section: __data + type: S_REGULAR + attributes: [ ] + address: 0x0000000000000030 + content: [ 0x2D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ] + relocations: + - offset: 0x00000004 + type: ARM_RELOC_VANILLA + length: 2 + pc-rel: false + extern: true + symbol: 4 + - offset: 0x00000000 + type: ARM_RELOC_VANILLA + length: 2 + pc-rel: false + extern: false + symbol: 1 +local-symbols: + - name: _t3 + type: N_SECT + sect: 1 + desc: [ N_ARM_THUMB_DEF ] + value: 0x000000000000002E + - name: _d1 + type: N_SECT + sect: 2 + value: 0x0000000000000030 +global-symbols: + - name: _t1 + type: N_SECT + scope: [ N_EXT ] + sect: 1 + desc: [ N_ARM_THUMB_DEF ] + value: 0x0000000000000000 + - name: _t2 + type: N_SECT + scope: [ N_EXT ] + sect: 1 + desc: [ N_ARM_THUMB_DEF ] + value: 0x000000000000002C +undefined-symbols: + - name: _a1 + type: N_UNDF + scope: [ N_EXT ] + value: 0x0000000000000000 + - name: _a2 + type: N_UNDF + scope: [ N_EXT ] + value: 0x0000000000000000 + +--- !mach-o +arch: armv7 +file-type: MH_OBJECT +flags: [ MH_SUBSECTIONS_VIA_SYMBOLS ] +sections: + - segment: __TEXT + section: __text + type: S_REGULAR + attributes: [ S_ATTR_PURE_INSTRUCTIONS, S_ATTR_SOME_INSTRUCTIONS ] + alignment: 2 + address: 0x0000000000000000 + content: [ 0xFE, 0xFF, 0xFF, 0xEB, 0x02, 0x00, 0x00, 0xFA, + 0xFC, 0xFF, 0xFF, 0xEB, 0xFB, 0xFF, 0xFF, 0xFA, + 0x1E, 0xFF, 0x2F, 0xE1, 0x1E, 0xFF, 0x2F, 0xE1 ] + relocations: + - offset: 0x0000000C + type: ARM_RELOC_BR24 + length: 2 + pc-rel: true + extern: true + symbol: 4 + - offset: 0x00000008 + type: ARM_RELOC_BR24 + length: 2 + pc-rel: true + extern: true + symbol: 3 + - offset: 0x00000004 + type: ARM_RELOC_BR24 + length: 2 + pc-rel: true + extern: false + symbol: 1 + - offset: 0x00000000 + type: ARM_RELOC_BR24 + length: 2 + pc-rel: true + extern: false + symbol: 1 + - segment: __DATA + section: __data + type: S_REGULAR + attributes: [ ] + address: 0x0000000000000018 + content: [ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ] + relocations: + - offset: 0x00000004 + type: ARM_RELOC_VANILLA + length: 2 + pc-rel: false + extern: false + symbol: 1 + - offset: 0x00000000 + type: ARM_RELOC_VANILLA + length: 2 + pc-rel: false + extern: true + symbol: 3 +local-symbols: + - name: _d2 + type: N_SECT + sect: 2 + value: 0x0000000000000018 +global-symbols: + - name: _a1 + type: N_SECT + scope: [ N_EXT ] + sect: 1 + value: 0x0000000000000000 + - name: _a2 + type: N_SECT + scope: [ N_EXT ] + sect: 1 + value: 0x0000000000000014 +undefined-symbols: + - name: _t1 + type: N_UNDF + scope: [ N_EXT ] + value: 0x0000000000000000 + - name: _t2 + type: N_UNDF + scope: [ N_EXT ] + value: 0x0000000000000000 +... + + +# CHECK: defined-atoms: +# CHECK: - name: _d1 +# CHECK: type: data +# CHECK: references: +# CHECK: - kind: pointer32 +# CHECK: offset: 0 +# CHECK: target: _t2 +# CHECK: - kind: pointer32 +# CHECK: offset: 4 +# CHECK: target: _a1 +# CHECK: - name: _d2 +# CHECK: type: data +# CHECK: references: +# CHECK: - kind: pointer32 +# CHECK: offset: 0 +# CHECK: target: _t1 +# CHECK: - kind: pointer32 +# CHECK: offset: 4 +# CHECK: target: _a1 +# CHECK: - name: _t1 +# CHECK: scope: global +# CHECK: references: +# CHECK: - kind: modeThumbCode +# CHECK: offset: 0 +# CHECK: target: _t1 +# CHECK: - kind: thumb_b22 +# CHECK: offset: 0 +# CHECK: target: _a1 +# CHECK: - kind: thumb_b22 +# CHECK: offset: 6 +# CHECK: target: _a2 +# CHECK: - kind: thumb_b22 +# CHECK: offset: 12 +# CHECK: target: _a2 +# CHECK: - kind: thumb_b22 +# CHECK: offset: 16 +# CHECK: target: _t1 +# CHECK: - kind: thumb_b22 +# CHECK: offset: 22 +# CHECK: target: _t1 +# CHECK: - kind: thumb_b22 +# CHECK: offset: 28 +# CHECK: target: _t2 +# CHECK: - kind: thumb_b22 +# CHECK: offset: 34 +# CHECK: target: _t2 +# CHECK: - kind: thumb_b22 +# CHECK: offset: 38 +# CHECK: target: _t3 +# CHECK: - name: _t2 +# CHECK: scope: global +# CHECK: content: [ 70, 47 ] +# CHECK: references: +# CHECK: - kind: modeThumbCode +# CHECK: offset: 0 +# CHECK: target: _t2 +# CHECK: - name: _t3 +# CHECK: content: [ 70, 47 ] +# CHECK: references: +# CHECK: - kind: modeThumbCode +# CHECK: offset: 0 +# CHECK: target: _t3 +# CHECK: - name: _a1 +# CHECK: scope: global +# CHECK: references: +# CHECK: - kind: arm_b24 +# CHECK: offset: 0 +# CHECK: target: _a1 +# CHECK: - kind: arm_b24 +# CHECK: offset: 4 +# CHECK: target: _a2 +# CHECK: - kind: arm_b24 +# CHECK: offset: 8 +# CHECK: target: _t1 +# CHECK: - kind: arm_b24 +# CHECK: offset: 12 +# CHECK: target: _t2 +# CHECK: - name: _a2 +# CHECK: scope: global + + +# CODE: (('section_name', '__text\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00') +# CODE: ('segment_name', '__TEXT\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00') +# CODE: ('_section_data', '00f016e8 c04600f0 1ee8c046 00f01ae8 fff7f6ff c046fff7 f3ffc046 00f006f8 c04600f0 03f800f0 02f87047 70477047 feffffeb 020000eb f0fffffa fafffffa 1eff2fe1 1eff2fe1') +# When we get a good mach-o disassembler the above __text section content check can be change to be symbolic. + +# CODE: (('section_name', '__data\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00') +# CODE: ('segment_name', '__DATA\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00') +# CODE: ('_section_data', '{{[0-9a-f]}}{{[13579bdf]}}{{[0-9a-f]+}} {{[0-9a-f]}}{{[02468ade]}}{{[0-9a-f]+}} {{[0-9a-f]}}{{[13579bdf]}}{{[0-9a-f]+}} {{[0-9a-f]}}{{[02468ade]}}{{[0-9a-f]+}}') +# Verify the low (thumb) bit is set on the first and third pointers but not the second and fourth. + + + +# Input file one: +# +# .align 2 +# .code 16 +# .globl _t1 +# .thumb_func _t1 +#_t1: +# bl _a1 +# nop +# blx _a2 +# nop +# blx _a2 +# bl _t1 +# nop +# bl _t1 +# nop +# blx _t2 +# nop +# blx _t2 +# bx lr +# +# .globl _t2 +# .thumb_func _t2 +#_t2: +# bx lr +# +# .data +#_d1: .long _t2 +# .long _a1 + + + +# Input file two: +# +# .align 2 +# .code 32 +# .globl _a1 +#_a1: +# bl _a1 +# blx _a2 +# bl _t1 +# blx _t2 +# bx lr +# +# .globl _a2 +#_a2: +# bx lr +# +# .data +#_d2: .long _t1 +# .long _a1 + + + +
\ No newline at end of file diff --git a/lld/test/mach-o/hello-world-armv7.yaml b/lld/test/mach-o/hello-world-armv7.yaml new file mode 100644 index 00000000000..ac985b4f19e --- /dev/null +++ b/lld/test/mach-o/hello-world-armv7.yaml @@ -0,0 +1,103 @@ +# RUN: lld -flavor darwin -arch armv7 -ios_version_min 7.0 %s -o %t && \ +# RUN: llvm-nm %t | FileCheck %s +# +# Test that armv7 (thumb) hello-world can be linked into a mach-o executable +# + +--- !mach-o +arch: armv7 +file-type: MH_OBJECT +flags: [ MH_SUBSECTIONS_VIA_SYMBOLS ] +has-UUID: false +OS: unknown +sections: + - segment: __TEXT + section: __text + type: S_REGULAR + attributes: [ S_ATTR_PURE_INSTRUCTIONS, S_ATTR_SOME_INSTRUCTIONS ] + alignment: 2 + address: 0x0000000000000000 + content: [ 0x80, 0xB5, 0x40, 0xF2, 0x06, 0x00, 0x6F, 0x46, + 0xC0, 0xF2, 0x00, 0x00, 0x78, 0x44, 0xFF, 0xF7, + 0xF8, 0xEF, 0x00, 0x20, 0x80, 0xBD ] + relocations: + - offset: 0x0000000E + type: ARM_THUMB_RELOC_BR22 + length: 2 + pc-rel: true + extern: true + symbol: 1 + - offset: 0x00000008 + scattered: true + type: ARM_RELOC_HALF_SECTDIFF + length: 3 + pc-rel: false + value: 0x00000016 + - offset: 0x00000006 + scattered: true + type: ARM_RELOC_PAIR + length: 3 + pc-rel: false + value: 0x0000000C + - offset: 0x00000002 + scattered: true + type: ARM_RELOC_HALF_SECTDIFF + length: 2 + pc-rel: false + value: 0x00000016 + - offset: 0x00000000 + scattered: true + type: ARM_RELOC_PAIR + length: 2 + pc-rel: false + value: 0x0000000C + - segment: __TEXT + section: __cstring + type: S_CSTRING_LITERALS + attributes: [ ] + address: 0x0000000000000016 + content: [ 0x68, 0x65, 0x6C, 0x6C, 0x6F, 0x0A, 0x00 ] +global-symbols: + - name: _main + type: N_SECT + scope: [ N_EXT ] + sect: 1 + desc: [ N_ARM_THUMB_DEF ] + value: 0x0000000000000000 +undefined-symbols: + - name: _printf + type: N_UNDF + scope: [ N_EXT ] + value: 0x0000000000000000 +... + +--- !mach-o +arch: armv7 +file-type: MH_DYLIB +flags: [ ] +install-name: /usr/lib/libSystem.B.dylib +sections: + - segment: __TEXT + section: __text + type: S_REGULAR + attributes: [ S_ATTR_PURE_INSTRUCTIONS, S_ATTR_SOME_INSTRUCTIONS ] + address: 0x0000000000000000 + content: [ 0x55 ] + +global-symbols: + - name: _printf + type: N_SECT + scope: [ N_EXT ] + sect: 1 + value: 0x0000000000000001 + - name: dyld_stub_binder + type: N_SECT + scope: [ N_EXT ] + sect: 1 + value: 0x0000000000000001 + +... + +# CHECK: {{[0-9a-f]+}} T _main +# CHECK: U _printf +# CHECK: U dyld_stub_binder |

