Index: lib/ReaderWriter/ELF/ARM/ARMRelocationHandler.cpp =================================================================== --- lib/ReaderWriter/ELF/ARM/ARMRelocationHandler.cpp +++ lib/ReaderWriter/ELF/ARM/ARMRelocationHandler.cpp @@ -16,6 +16,55 @@ using namespace lld; using namespace elf; +#define DECLARE_T(flag) const uint64_t T = flag ? 1 : 0; + +static Reference::Addend readAddend_THM_MOV(const uint8_t *location) { + const auto halfHi = int16_t( + *reinterpret_cast(location)); + const auto halfLo = int16_t( + *reinterpret_cast(location + 2)); + + const int16_t imm8 = halfLo & 0xFF; + const int16_t imm3 = (halfLo >> 12) & 0x7; + + const int16_t imm4 = halfHi & 0xF; + const int16_t bitI = (halfHi >> 10) & 0x1; + + const int16_t result = (imm4 << 12) | (bitI << 11) | (imm3 << 8) | imm8; + return result; +} + +static Reference::Addend readAddend_ARM_MOV(const uint8_t *location) { + const auto value = int32_t( + *reinterpret_cast(location)); + + const int32_t imm12 = value & 0xFFF; + const int32_t imm4 = (value >> 16) & 0xF; + + const int32_t result = (imm4 << 12) | imm12; + return result; +} + +static Reference::Addend readAddend_THM_CALL(const uint8_t *location) { + const auto halfHi = int16_t( + *reinterpret_cast(location)); + const auto halfLo = int16_t( + *reinterpret_cast(location + 2)); + + const int16_t imm10 = halfHi & 0x3FF; + const int16_t bitS = (halfHi >> 10) & 0x1; + + const int16_t imm11 = halfLo & 0x7FF; + const int16_t bitJ2 = (halfLo >> 11) & 0x1; + const int16_t bitI2 = (~(bitJ2 ^ bitS)) & 0x1; + const int16_t bitJ1 = (halfLo >> 13) & 0x1; + const int16_t bitI1 = (~(bitJ1 ^ bitS)) & 0x1; + + const int32_t result = (bitS << 24) | (bitI1 << 23) | (bitI2 << 22) | + (imm10 << 12) | (imm11 << 1); + return llvm::SignExtend64<25>(result); +} + static Reference::Addend readAddend_ARM_CALL(const uint8_t *location) { const auto value = int32_t( *reinterpret_cast(location)); @@ -33,8 +82,18 @@ case R_ARM_ABS32: return int32_t( *reinterpret_cast(location)); + case R_ARM_THM_CALL: + case R_ARM_THM_JUMP24: + return readAddend_THM_CALL(location); case R_ARM_CALL: + case R_ARM_JUMP24: return readAddend_ARM_CALL(location); + case R_ARM_MOVW_ABS_NC: + case R_ARM_MOVT_ABS: + return readAddend_ARM_MOV(location); + case R_ARM_THM_MOVW_ABS_NC: + case R_ARM_THM_MOVT_ABS: + return readAddend_THM_MOV(location); default: return 0; } @@ -48,23 +107,124 @@ ~mask) | (result & mask); } -/// \brief R_ARM_ABS32 - (S + A) | T => S + A +static inline void applyThmReloc(uint8_t *location, uint16_t resHi, + uint16_t resLo, uint16_t maskHi, + uint16_t maskLo = 0xFFFF) { + assert(!(resHi & ~maskHi) && !(resLo & ~maskLo)); + *reinterpret_cast(location) = + (uint16_t(*reinterpret_cast(location)) & + ~maskHi) | (resHi & maskHi); + location += 2; + *reinterpret_cast(location) = + (uint16_t(*reinterpret_cast(location)) & + ~maskLo) | (resLo & maskLo); +} + +/// \brief R_ARM_ABS32 - (S + A) | T static void relocR_ARM_ABS32(uint8_t *location, uint64_t P, uint64_t S, - int64_t A) { - uint32_t result = (uint32_t)(S + A); + int64_t A, bool addressesThumb) { + DECLARE_T(addressesThumb); + uint32_t result = (uint32_t)((S + A) | T); + DEBUG_WITH_TYPE( "ARM", llvm::dbgs() << "\t\tHandle " << LLVM_FUNCTION_NAME << " -"; llvm::dbgs() << " S: 0x" << Twine::utohexstr(S); llvm::dbgs() << " A: 0x" << Twine::utohexstr(A); llvm::dbgs() << " P: 0x" << Twine::utohexstr(P); + llvm::dbgs() << " T: 0x" << Twine::utohexstr(T); llvm::dbgs() << " result: 0x" << Twine::utohexstr(result) << "\n"); applyArmReloc(location, result); } -/// \brief R_ARM_CALL - ((S + A) | T) - P => S + A - P +/// \brief Relocate B/BL instructions. useJs defines whether J1 & J2 are used +static void relocR_ARM_THM_B_L(uint8_t *location, uint32_t result, bool useJs) { + result = (result & 0x01FFFFFE) >> 1; + + const uint16_t imm10 = (result >> 11) & 0x3FF; + const uint16_t bitS = (result >> 23) & 0x1; + const uint16_t resHi = (bitS << 10) | imm10; + + const uint16_t imm11 = result & 0x7FF; + const uint16_t bitJ2 = useJs ? ((result >> 21) & 0x1) : bitS; + const uint16_t bitI2 = (~(bitJ2 ^ bitS)) & 0x1; + const uint16_t bitJ1 = useJs ? ((result >> 22) & 0x1) : bitS; + const uint16_t bitI1 = (~(bitJ1 ^ bitS)) & 0x1; + const uint16_t resLo = (bitI1 << 13) | (bitI2 << 11) | imm11; + + applyThmReloc(location, resHi, resLo, 0x7FF, 0x2FFF); +} + +/// \brief R_ARM_THM_CALL - ((S + A) | T) - P +static void relocR_ARM_THM_CALL(uint8_t *location, uint64_t P, uint64_t S, + int64_t A, bool useJs, bool addressesThumb) { + DECLARE_T(addressesThumb); + const bool exchanges = !addressesThumb; + + if (exchanges) { + P &= ~0x3; // Align(P, 4) by rounding down + } + + uint32_t result = (uint32_t)(((S + A) | T) - P); + + DEBUG_WITH_TYPE( + "ARM", llvm::dbgs() << "\t\tHandle " << LLVM_FUNCTION_NAME << " -"; + llvm::dbgs() << " S: 0x" << Twine::utohexstr(S); + llvm::dbgs() << " A: 0x" << Twine::utohexstr(A); + llvm::dbgs() << " P: 0x" << Twine::utohexstr(P); + llvm::dbgs() << " T: 0x" << Twine::utohexstr(T); + llvm::dbgs() << " result: 0x" << Twine::utohexstr(result) << "\n"); + relocR_ARM_THM_B_L(location, result, useJs); + + if (exchanges) { + applyThmReloc(location, 0, 0, 0, 0x1001); + } +} + +/// \brief R_ARM_THM_JUMP24 - ((S + A) | T) - P +static void relocR_ARM_THM_JUMP24(uint8_t *location, uint64_t P, uint64_t S, + int64_t A, bool addressesThumb) { + DECLARE_T(addressesThumb); + uint32_t result = (uint32_t)(((S + A) | T) - P); + + DEBUG_WITH_TYPE( + "ARM", llvm::dbgs() << "\t\tHandle " << LLVM_FUNCTION_NAME << " -"; + llvm::dbgs() << " S: 0x" << Twine::utohexstr(S); + llvm::dbgs() << " A: 0x" << Twine::utohexstr(A); + llvm::dbgs() << " P: 0x" << Twine::utohexstr(P); + llvm::dbgs() << " T: 0x" << Twine::utohexstr(T); + llvm::dbgs() << " result: 0x" << Twine::utohexstr(result) << "\n"); + relocR_ARM_THM_B_L(location, result, true); +} + +/// \brief R_ARM_CALL - ((S + A) | T) - P static void relocR_ARM_CALL(uint8_t *location, uint64_t P, uint64_t S, - int64_t A) { - uint32_t result = (uint32_t)((S + A) - P); + int64_t A, bool addressesThumb) { + DECLARE_T(addressesThumb); + const bool exchanges = addressesThumb; + + uint32_t result = (uint32_t)(((S + A) | T) - P); + const uint32_t imm24 = (result & 0x03FFFFFC) >> 2; + + DEBUG_WITH_TYPE( + "ARM", llvm::dbgs() << "\t\tHandle " << LLVM_FUNCTION_NAME << " -"; + llvm::dbgs() << " S: 0x" << Twine::utohexstr(S); + llvm::dbgs() << " A: 0x" << Twine::utohexstr(A); + llvm::dbgs() << " P: 0x" << Twine::utohexstr(P); + llvm::dbgs() << " T: 0x" << Twine::utohexstr(T); + llvm::dbgs() << " result: 0x" << Twine::utohexstr(result) << "\n"); + applyArmReloc(location, imm24, 0xFFFFFF); + + if (exchanges) { + const uint32_t bitH = (result & 0x2) >> 1; + applyArmReloc(location, (0xFA | bitH) << 24, 0xFF000000); + } +} + +/// \brief R_ARM_JUMP24 - ((S + A) | T) - P +static void relocR_ARM_JUMP24(uint8_t *location, uint64_t P, uint64_t S, + int64_t A, bool addressesThumb) { + DECLARE_T(addressesThumb); + uint32_t result = (uint32_t)(((S + A) | T) - P); const uint32_t imm24 = (result & 0x03FFFFFC) >> 2; DEBUG_WITH_TYPE( @@ -72,10 +232,96 @@ llvm::dbgs() << " S: 0x" << Twine::utohexstr(S); llvm::dbgs() << " A: 0x" << Twine::utohexstr(A); llvm::dbgs() << " P: 0x" << Twine::utohexstr(P); + llvm::dbgs() << " T: 0x" << Twine::utohexstr(T); llvm::dbgs() << " result: 0x" << Twine::utohexstr(result) << "\n"); applyArmReloc(location, imm24, 0xFFFFFF); } +/// \brief Relocate ARM MOVW/MOVT instructions +static void relocR_ARM_MOV(uint8_t *location, uint32_t result) { + const uint32_t imm12 = result & 0xFFF; + const uint32_t imm4 = (result >> 12) & 0xF; + + applyArmReloc(location, (imm4 << 16) | imm12, 0xF0FFF); +} + +/// \brief R_ARM_MOVW_ABS_NC - (S + A) | T +static void relocR_ARM_MOVW_ABS_NC(uint8_t *location, uint64_t P, uint64_t S, + int64_t A, bool addressesThumb) { + DECLARE_T(addressesThumb); + uint32_t result = (uint32_t)((S + A) | T); + const uint32_t arg = result & 0x0000FFFF; + + DEBUG_WITH_TYPE( + "ARM", llvm::dbgs() << "\t\tHandle " << LLVM_FUNCTION_NAME << " -"; + llvm::dbgs() << " S: 0x" << Twine::utohexstr(S); + llvm::dbgs() << " A: 0x" << Twine::utohexstr(A); + llvm::dbgs() << " P: 0x" << Twine::utohexstr(P); + llvm::dbgs() << " T: 0x" << Twine::utohexstr(T); + llvm::dbgs() << " result: 0x" << Twine::utohexstr(result) << "\n"); + return relocR_ARM_MOV(location, arg); +} + +/// \brief R_ARM_MOVT_ABS - S + A +static void relocR_ARM_MOVT_ABS(uint8_t *location, uint64_t P, uint64_t S, + int64_t A) { + uint32_t result = (uint32_t)(S + A); + const uint32_t arg = (result & 0xFFFF0000) >> 16; + + DEBUG_WITH_TYPE( + "ARM", llvm::dbgs() << "\t\tHandle " << LLVM_FUNCTION_NAME << " -"; + llvm::dbgs() << " S: 0x" << Twine::utohexstr(S); + llvm::dbgs() << " A: 0x" << Twine::utohexstr(A); + llvm::dbgs() << " P: 0x" << Twine::utohexstr(P); + llvm::dbgs() << " result: 0x" << Twine::utohexstr(result) << "\n"); + return relocR_ARM_MOV(location, arg); +} + +/// \brief Relocate Thumb MOVW/MOVT instructions +static void relocR_ARM_THM_MOV(uint8_t *location, uint32_t result) { + const uint16_t imm8 = result & 0xFF; + const uint16_t imm3 = (result >> 8) & 0x7; + const uint16_t resLo = (imm3 << 12) | imm8; + + const uint16_t imm4 = (result >> 12) & 0xF; + const uint16_t bitI = (result >> 11) & 0x1; + const uint16_t resHi = (bitI << 10) | imm4; + + applyThmReloc(location, resHi, resLo, 0x40F, 0x70FF); +} + +/// \brief R_ARM_THM_MOVW_ABS_NC - (S + A) | T +static void relocR_ARM_THM_MOVW_ABS_NC(uint8_t *location, uint64_t P, + uint64_t S, int64_t A, bool addressesThumb) { + DECLARE_T(addressesThumb); + uint32_t result = (uint32_t)((S + A) | T); + const uint32_t arg = result & 0x0000FFFF; + + DEBUG_WITH_TYPE( + "ARM", llvm::dbgs() << "\t\tHandle " << LLVM_FUNCTION_NAME << " -"; + llvm::dbgs() << " S: 0x" << Twine::utohexstr(S); + llvm::dbgs() << " A: 0x" << Twine::utohexstr(A); + llvm::dbgs() << " P: 0x" << Twine::utohexstr(P); + llvm::dbgs() << " T: 0x" << Twine::utohexstr(T); + llvm::dbgs() << " result: 0x" << Twine::utohexstr(result) << "\n"); + return relocR_ARM_THM_MOV(location, arg); +} + +/// \brief R_ARM_THM_MOVT_ABS - S + A +static void relocR_ARM_THM_MOVT_ABS(uint8_t *location, uint64_t P, uint64_t S, + int64_t A) { + uint32_t result = (uint32_t)(S + A); + const uint32_t arg = (result & 0xFFFF0000) >> 16; + + DEBUG_WITH_TYPE( + "ARM", llvm::dbgs() << "\t\tHandle " << LLVM_FUNCTION_NAME << " -"; + llvm::dbgs() << " S: 0x" << Twine::utohexstr(S); + llvm::dbgs() << " A: 0x" << Twine::utohexstr(A); + llvm::dbgs() << " P: 0x" << Twine::utohexstr(P); + llvm::dbgs() << " result: 0x" << Twine::utohexstr(result) << "\n"); + return relocR_ARM_THM_MOV(location, arg); +} + std::error_code ARMTargetRelocationHandler::applyRelocation( ELFWriter &writer, llvm::FileOutputBuffer &buf, const lld::AtomLayout &atom, const Reference &ref) const { @@ -92,14 +338,51 @@ const Reference::Addend addend = readAddend(location, ref.kindValue()); + // Flags that the relocation addresses Thumb instruction + bool addressesThumb = false; + + if (const auto *definedAtom = dyn_cast(ref.target())) { + addressesThumb = (DefinedAtom::codeARMThumb == definedAtom->codeModel()); + } + switch (ref.kindValue()) { case R_ARM_NONE: break; case R_ARM_ABS32: - relocR_ARM_ABS32(location, relocVAddress, targetVAddress, addend); + relocR_ARM_ABS32(location, relocVAddress, targetVAddress, addend, + addressesThumb); + break; + case R_ARM_THM_CALL: + // TODO: consider adding bool variable to disable J1 & J2 for archs + // before ARMv6 + relocR_ARM_THM_CALL(location, relocVAddress, targetVAddress, addend, true, + addressesThumb); break; case R_ARM_CALL: - relocR_ARM_CALL(location, relocVAddress, targetVAddress, addend); + relocR_ARM_CALL(location, relocVAddress, targetVAddress, addend, + addressesThumb); + break; + case R_ARM_JUMP24: + relocR_ARM_JUMP24(location, relocVAddress, targetVAddress, addend, + addressesThumb); + break; + case R_ARM_THM_JUMP24: + relocR_ARM_THM_JUMP24(location, relocVAddress, targetVAddress, addend, + addressesThumb); + break; + case R_ARM_MOVW_ABS_NC: + relocR_ARM_MOVW_ABS_NC(location, relocVAddress, targetVAddress, addend, + addressesThumb); + break; + case R_ARM_MOVT_ABS: + relocR_ARM_MOVT_ABS(location, relocVAddress, targetVAddress, addend); + break; + case R_ARM_THM_MOVW_ABS_NC: + relocR_ARM_THM_MOVW_ABS_NC(location, relocVAddress, targetVAddress, addend, + addressesThumb); + break; + case R_ARM_THM_MOVT_ABS: + relocR_ARM_THM_MOVT_ABS(location, relocVAddress, targetVAddress, addend); break; default: return make_unhandled_reloc_error(); Index: test/elf/ARM/rel-abs32.test =================================================================== --- test/elf/ARM/rel-abs32.test +++ test/elf/ARM/rel-abs32.test @@ -10,7 +10,7 @@ # data main addr content # 0x400084 = 0x400074 + 0x10 # CHECK: SYMBOL TABLE: -# CHECK: 00400074 g F .text 0000001c main +# CHECK: 00400074 g F .text {{[0-9a-f]+}} main # CHECK: 00401000 g .data 00000004 data --- Index: test/elf/ARM/rel-arm-call.test =================================================================== --- test/elf/ARM/rel-arm-call.test +++ test/elf/ARM/rel-arm-call.test @@ -10,8 +10,8 @@ # call site offset PC(arm) _Z1fv addr # 0x400090 + (-0x24) + 0x8 = 0x400074 # CHECK: SYMBOL TABLE: -# CHECK: 00400074 g F .text 00000014 _Z1fv -# CHECK: 00400088 g F .text 00000018 main +# CHECK: 00400074 g F .text {{[0-9a-f]+}} _Z1fv +# CHECK: 00400088 g F .text {{[0-9a-f]+}} main --- FileHeader: Index: test/elf/ARM/rel-arm-jump24.test =================================================================== --- /dev/null +++ test/elf/ARM/rel-arm-jump24.test @@ -0,0 +1,58 @@ +# Check handling of R_ARM_JUMP24 relocation. +# RUN: yaml2obj -format=elf %s > %t-o.o +# RUN: lld -flavor gnu -target arm -m armelf_linux_eabi -Bstatic \ +# RUN: --noinhibit-exec %t-o.o -o %t +# RUN: llvm-objdump -s -t %t | FileCheck %s + +# CHECK: Contents of section .text: +# CHECK: 400094 04b08de2 f5ffffea 0030a0e1 0300a0e1 +# offset = -0x2C ^^ +# call site offset PC(arm) _Z1fv addr +# 0x400098 + (-0x2C) + 0x8 = 0x400074 +# CHECK: SYMBOL TABLE: +# CHECK: 00400074 g F .text {{[0-9a-f]+}} _Z1fv +# CHECK: 00400090 g F .text {{[0-9a-f]+}} main + +--- +FileHeader: + Class: ELFCLASS32 + Data: ELFDATA2LSB + Type: ET_REL + Machine: EM_ARM + Flags: [ EF_ARM_EABI_VER5 ] +Sections: + - Name: .text + Type: SHT_PROGBITS + Flags: [ SHF_ALLOC, SHF_EXECINSTR ] + AddressAlign: 0x0000000000000004 + Content: 04B02DE500B08DE20030A0E30300A0E100D04BE204B09DE41EFF2FE100482DE904B08DE2FEFFFFEA0030A0E10300A0E10088BDE8 + - Name: .rel.text + Type: SHT_REL + Link: .symtab + AddressAlign: 0x0000000000000004 + Info: .text + Relocations: + - Offset: 0x0000000000000024 + Symbol: _Z1fv + Type: R_ARM_JUMP24 + Addend: 0 + - Name: .data + Type: SHT_PROGBITS + Flags: [ SHF_WRITE, SHF_ALLOC ] + AddressAlign: 0x0000000000000001 + Content: '' + - Name: .bss + Type: SHT_NOBITS + Flags: [ SHF_WRITE, SHF_ALLOC ] + AddressAlign: 0x0000000000000001 + Content: '' +Symbols: + Global: + - Name: _Z1fv + Type: STT_FUNC + Section: .text + - Name: main + Type: STT_FUNC + Section: .text + Value: 0x000000000000001C +... Index: test/elf/ARM/rel-arm-mov.test =================================================================== --- /dev/null +++ test/elf/ARM/rel-arm-mov.test @@ -0,0 +1,64 @@ +# Check handling of R_ARM_MOVW_ABS_NC and R_ARM_MOVT_ABS relocation pair. +# RUN: yaml2obj -format=elf %s > %t-o.o +# RUN: lld -flavor gnu -target arm -m armelf_linux_eabi -Bstatic \ +# RUN: --noinhibit-exec %t-o.o -o %t +# RUN: llvm-objdump -s -t %t | FileCheck %s + +# CHECK: Contents of section .text: +# CHECK: 400074 04b02de5 00b08de2 003001e3 403040e3 +# addrL = 0x1000 ^^ +# addrH = 0x40 ^^ +# addrH addrL _ZL5data1 addr +# (0x40 << 16) + 0x1000 = 0x401000 +# CHECK: SYMBOL TABLE: +# CHECK: 00401000 l .bss 00000004 _ZL5data1 +# CHECK: 00400074 g F .text {{[0-9a-f]+}} main + +--- +FileHeader: + Class: ELFCLASS32 + Data: ELFDATA2LSB + Type: ET_REL + Machine: EM_ARM + Flags: [ EF_ARM_EABI_VER5 ] +Sections: + - Name: .text + Type: SHT_PROGBITS + Flags: [ SHF_ALLOC, SHF_EXECINSTR ] + AddressAlign: 0x0000000000000004 + Content: 04B02DE500B08DE2003000E3003040E30A20A0E3002083E50030A0E30300A0E100D04BE204B09DE41EFF2FE1 + - Name: .rel.text + Type: SHT_REL + Link: .symtab + AddressAlign: 0x0000000000000004 + Info: .text + Relocations: + - Offset: 0x0000000000000008 + Symbol: _ZL5data1 + Type: R_ARM_MOVW_ABS_NC + Addend: 0 + - Offset: 0x000000000000000C + Symbol: _ZL5data1 + Type: R_ARM_MOVT_ABS + Addend: 0 + - Name: .data + Type: SHT_PROGBITS + Flags: [ SHF_WRITE, SHF_ALLOC ] + AddressAlign: 0x0000000000000001 + Content: '' + - Name: .bss + Type: SHT_NOBITS + Flags: [ SHF_WRITE, SHF_ALLOC ] + AddressAlign: 0x0000000000000004 + Content: 411C0000 +Symbols: + Local: + - Name: _ZL5data1 + Type: STT_OBJECT + Section: .bss + Size: 0x0000000000000004 + Global: + - Name: main + Type: STT_FUNC + Section: .text +... Index: test/elf/ARM/rel-arm-thm-interwork.test =================================================================== --- /dev/null +++ test/elf/ARM/rel-arm-thm-interwork.test @@ -0,0 +1,123 @@ +# Check ARM <=> Thumb interwork. +# RUN: yaml2obj -format=elf -docnum 1 %s > %t-arm.o +# RUN: yaml2obj -format=elf -docnum 2 %s > %t-thm.o +# RUN: lld -flavor gnu -target arm -m armelf_linux_eabi -Bstatic \ +# RUN: --noinhibit-exec %t-arm.o %t-thm.o -o %t + +# Check R_ARM_CALL veneer to call Thumb code +# RUN: llvm-objdump -s -t %t | FileCheck -check-prefix=ARM-CALL %s + +# ARM-CALL: Contents of section .text: +# ARM-CALL: 400074 00482de9 04b08de2 000000fa 0088bde8 +# offset = 0x0 ^^ +# call site offset PC(arm) _Z2f2v addr +# 0x40007C + 0x0 + 0x8 = 0x400084 +# ARM-CALL: SYMBOL TABLE: +# ARM-CALL: 00400074 g F .text {{[0-9a-f]+}} _Z1fv +# ARM-CALL: 00400084 g F .text {{[0-9a-f]+}} _Z2f2v +# ARM-CALL: 00400090 g F .text {{[0-9a-f]+}} main + +# Check R_ARM_THM_CALL veneer to call ARM code +# RUN: llvm-objdump -s -t %t | FileCheck -check-prefix=THM-CALL %s + +# THM-CALL: Contents of section .text: +# THM-CALL: 400094 00bffff7 eeef0023 184680bd +# offset = -0x24 ^^ +# call site aligned = Align(0x400096, 4) = 0x400094 +# call site aligned offset PC(thm) _Z1fv addr +# 0x400094 + (-0x24) + 0x4 = 0x400074 +# THM-CALL: SYMBOL TABLE: +# THM-CALL: 00400074 g F .text {{[0-9a-f]+}} _Z1fv +# THM-CALL: 00400084 g F .text {{[0-9a-f]+}} _Z2f2v +# THM-CALL: 00400090 g F .text {{[0-9a-f]+}} main + +# arm.o +--- +FileHeader: + Class: ELFCLASS32 + Data: ELFDATA2LSB + Type: ET_REL + Machine: EM_ARM + Flags: [ EF_ARM_EABI_VER5 ] +Sections: + - Name: .text + Type: SHT_PROGBITS + Flags: [ SHF_ALLOC, SHF_EXECINSTR ] + AddressAlign: 0x0000000000000004 + Content: 00482DE904B08DE2FEFFFFEB0088BDE8 + - Name: .rel.text + Type: SHT_REL + Link: .symtab + AddressAlign: 0x0000000000000004 + Info: .text + Relocations: + - Offset: 0x0000000000000008 + Symbol: _Z2f2v + Type: R_ARM_CALL + Addend: 0 + - Name: .data + Type: SHT_PROGBITS + Flags: [ SHF_WRITE, SHF_ALLOC ] + AddressAlign: 0x0000000000000001 + Content: '' + - Name: .bss + Type: SHT_NOBITS + Flags: [ SHF_WRITE, SHF_ALLOC ] + AddressAlign: 0x0000000000000001 + Content: '' +Symbols: + Global: + - Name: _Z1fv + Type: STT_FUNC + Section: .text + Size: 0x0000000000000010 + - Name: _Z2f2v + +# thm.o +--- +FileHeader: + Class: ELFCLASS32 + Data: ELFDATA2LSB + Type: ET_REL + Machine: EM_ARM + Flags: [ EF_ARM_EABI_VER5 ] +Sections: + - Name: .text + Type: SHT_PROGBITS + Flags: [ SHF_ALLOC, SHF_EXECINSTR ] + AddressAlign: 0x0000000000000004 + Content: 80B400AFBD465DF8047B704780B500AF00BFFFF7FEFF0023184680BD + - Name: .rel.text + Type: SHT_REL + Link: .symtab + AddressAlign: 0x0000000000000004 + Info: .text + Relocations: + - Offset: 0x0000000000000012 + Symbol: _Z1fv + Type: R_ARM_THM_CALL + Addend: 0 + - Name: .data + Type: SHT_PROGBITS + Flags: [ SHF_WRITE, SHF_ALLOC ] + AddressAlign: 0x0000000000000001 + Content: '' + - Name: .bss + Type: SHT_NOBITS + Flags: [ SHF_WRITE, SHF_ALLOC ] + AddressAlign: 0x0000000000000001 + Content: '' +Symbols: + Global: + - Name: _Z2f2v + Type: STT_FUNC + Section: .text + Value: 0x0000000000000001 + Size: 0x000000000000000C + - Name: main + Type: STT_FUNC + Section: .text + Value: 0x000000000000000D + Size: 0x0000000000000010 + - Name: _Z1fv +... Index: test/elf/ARM/rel-thm-call.test =================================================================== --- /dev/null +++ test/elf/ARM/rel-thm-call.test @@ -0,0 +1,61 @@ +# Check handling of R_ARM_THM_CALL relocation. +# RUN: yaml2obj -format=elf %s > %t-o.o +# RUN: lld -flavor gnu -target arm -m armelf_linux_eabi -Bstatic \ +# RUN: --noinhibit-exec %t-o.o -o %t +# RUN: llvm-objdump -s -t %t | FileCheck %s + +# CHECK: Contents of section .text: +# CHECK: 400084 fff7f6ff 00231846 80bd00bf +# ^^ offset = -0x14 +# call site offset PC(thm) _Z1fv addr +# 0x400084 + (-0x14) + 0x4 = 0x400074 +# CHECK: SYMBOL TABLE: +# CHECK: 00400074 g F .text {{[0-9a-f]+}} _Z1fv +# CHECK: 00400080 g F .text {{[0-9a-f]+}} main + +--- +FileHeader: + Class: ELFCLASS32 + Data: ELFDATA2LSB + Type: ET_REL + Machine: EM_ARM + Flags: [ EF_ARM_EABI_VER5 ] +Sections: + - Name: .text + Type: SHT_PROGBITS + Flags: [ SHF_ALLOC, SHF_EXECINSTR ] + AddressAlign: 0x0000000000000004 + Content: 80B400AFBD465DF8047B704780B500AFFFF7FEFF0023184680BD00BF + - Name: .rel.text + Type: SHT_REL + Link: .symtab + AddressAlign: 0x0000000000000004 + Info: .text + Relocations: + - Offset: 0x0000000000000010 + Symbol: _Z1fv + Type: R_ARM_THM_CALL + Addend: 0 + - Name: .data + Type: SHT_PROGBITS + Flags: [ SHF_WRITE, SHF_ALLOC ] + AddressAlign: 0x0000000000000001 + Content: '' + - Name: .bss + Type: SHT_NOBITS + Flags: [ SHF_WRITE, SHF_ALLOC ] + AddressAlign: 0x0000000000000001 + Content: '' +Symbols: + Global: + - Name: _Z1fv + Type: STT_FUNC + Section: .text + Value: 0x0000000000000001 + Size: 0x000000000000000C + - Name: main + Type: STT_FUNC + Section: .text + Value: 0x000000000000000D + Size: 0x000000000000000E +... Index: test/elf/ARM/rel-thm-jump24.test =================================================================== --- /dev/null +++ test/elf/ARM/rel-thm-jump24.test @@ -0,0 +1,59 @@ +# Check handling of R_ARM_THM_JUMP24 relocation. +# RUN: yaml2obj -format=elf %s > %t-o.o +# RUN: lld -flavor gnu -target arm -m armelf_linux_eabi -Bstatic \ +# RUN: --noinhibit-exec %t-o.o -o %t +# RUN: llvm-objdump -s -t %t | FileCheck %s + +# CHECK: Contents of section .text: +# CHECK: 400084 80b500af fff7f4bf 03461846 80bd00bf +# ^^ offset = -0x18 +# call site offset PC(thm) _Z1fv addr +# 0x400088 + (-0x18) + 0x4 = 0x400074 +# CHECK: SYMBOL TABLE: +# CHECK: 00400074 g F .text {{[0-9a-f]+}} _Z1fv +# CHECK: 00400084 g F .text {{[0-9a-f]+}} main + +--- +FileHeader: + Class: ELFCLASS32 + Data: ELFDATA2LSB + Type: ET_REL + Machine: EM_ARM + Flags: [ EF_ARM_EABI_VER5 ] +Sections: + - Name: .text + Type: SHT_PROGBITS + Flags: [ SHF_ALLOC, SHF_EXECINSTR ] + AddressAlign: 0x0000000000000004 + Content: 80B400AF00231846BD465DF8047B704780B500AFFFF7FEBF0346184680BD00BF + - Name: .rel.text + Type: SHT_REL + Link: .symtab + AddressAlign: 0x0000000000000004 + Info: .text + Relocations: + - Offset: 0x0000000000000014 + Symbol: _Z1fv + Type: R_ARM_THM_JUMP24 + Addend: 0 + - Name: .data + Type: SHT_PROGBITS + Flags: [ SHF_WRITE, SHF_ALLOC ] + AddressAlign: 0x0000000000000001 + Content: '' + - Name: .bss + Type: SHT_NOBITS + Flags: [ SHF_WRITE, SHF_ALLOC ] + AddressAlign: 0x0000000000000001 + Content: '' +Symbols: + Global: + - Name: _Z1fv + Type: STT_FUNC + Section: .text + Value: 0x0000000000000001 + - Name: main + Type: STT_FUNC + Section: .text + Value: 0x0000000000000011 +... Index: test/elf/ARM/rel-thm-mov.test =================================================================== --- /dev/null +++ test/elf/ARM/rel-thm-mov.test @@ -0,0 +1,70 @@ +# 1. Check handling of R_ARM_THM_MOVW_ABS_NC and R_THM_ARM_MOVT_ABS relocation pair. +# 2. Check that instructions are not cropped for symbols that address Thumb code. +# RUN: yaml2obj -format=elf %s > %t-o.o +# RUN: lld -flavor gnu -target arm -m armelf_linux_eabi -Bstatic \ +# RUN: --noinhibit-exec %t-o.o -o %t +# RUN: llvm-objdump -s -t %t | FileCheck %s +# RUN: llvm-objdump -s -t %t | FileCheck -check-prefix=INSN-CROP %s + +# CHECK: Contents of section .text: +# CHECK: 400074 {{[0-9a-f]+}} 41f20003 c0f24003 0a221a60 +# addrL = 0x1000 ^^ +# addrH = 0x40 ^^ +# addrH addrL _ZL5data1 addr +# (0x40 << 16) + 0x1000 = 0x401000 +# CHECK: SYMBOL TABLE: +# CHECK: 00401000 l .bss 00000004 _ZL5data1 +# CHECK: 00400074 g F .text {{[0-9a-f]+}} main +# +# INSN-CROP: Contents of section .text: +# INSN-CROP: 400074 80b400af + +--- +FileHeader: + Class: ELFCLASS32 + Data: ELFDATA2LSB + Type: ET_REL + Machine: EM_ARM + Flags: [ EF_ARM_EABI_VER5 ] +Sections: + - Name: .text + Type: SHT_PROGBITS + Flags: [ SHF_ALLOC, SHF_EXECINSTR ] + AddressAlign: 0x0000000000000004 + Content: 80B400AF40F20003C0F200030A221A6000231846BD465DF8047B7047 + - Name: .rel.text + Type: SHT_REL + Link: .symtab + AddressAlign: 0x0000000000000004 + Info: .text + Relocations: + - Offset: 0x0000000000000004 + Symbol: _ZL5data1 + Type: R_ARM_THM_MOVW_ABS_NC + Addend: 0 + - Offset: 0x0000000000000008 + Symbol: _ZL5data1 + Type: R_ARM_THM_MOVT_ABS + Addend: 0 + - Name: .data + Type: SHT_PROGBITS + Flags: [ SHF_WRITE, SHF_ALLOC ] + AddressAlign: 0x0000000000000001 + Content: '' + - Name: .bss + Type: SHT_NOBITS + Flags: [ SHF_WRITE, SHF_ALLOC ] + AddressAlign: 0x0000000000000004 + Content: 411C0000 +Symbols: + Local: + - Name: _ZL5data1 + Type: STT_OBJECT + Section: .bss + Size: 0x0000000000000004 + Global: + - Name: main + Type: STT_FUNC + Section: .text + Value: 0x0000000000000001 +...