Index: lld/trunk/lib/ReaderWriter/ELF/ARM/ARMRelocationHandler.cpp =================================================================== --- lld/trunk/lib/ReaderWriter/ELF/ARM/ARMRelocationHandler.cpp +++ lld/trunk/lib/ReaderWriter/ELF/ARM/ARMRelocationHandler.cpp @@ -70,6 +70,13 @@ return llvm::SignExtend64<26>(result); } +static Reference::Addend readAddend_THM_JUMP11(const uint8_t *location) { + const auto value = read16le(location); + const uint16_t imm11 = value & 0x7FF; + + return llvm::SignExtend32<12>(imm11 << 1); +} + static Reference::Addend readAddend(const uint8_t *location, Reference::KindValue kindValue) { switch (kindValue) { @@ -78,6 +85,8 @@ case R_ARM_THM_CALL: case R_ARM_THM_JUMP24: return readAddend_THM_CALL(location); + case R_ARM_THM_JUMP11: + return readAddend_THM_JUMP11(location); case R_ARM_CALL: case R_ARM_JUMP24: return readAddend_ARM_CALL(location); @@ -107,6 +116,12 @@ write16le(location, (read16le(location) & ~maskLo) | (resLo & maskLo)); } +static inline void applyThumb16Reloc(uint8_t *location, uint16_t result, + uint16_t mask = 0xFFFF) { + assert(!(result & ~mask)); + write16le(location, (read16le(location) & ~mask) | (result & mask)); +} + /// \brief R_ARM_ABS32 - (S + A) | T static void relocR_ARM_ABS32(uint8_t *location, uint64_t P, uint64_t S, int64_t A, bool addressesThumb) { @@ -123,6 +138,42 @@ applyArmReloc(location, result); } +/// \brief R_ARM_REL32 - ((S + A) | T) - P +static void relocR_ARM_REL32(uint8_t *location, uint64_t P, uint64_t S, + int64_t A, bool addressesThumb) { + uint64_t 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"); + applyArmReloc(location, result); +} + +/// \brief R_ARM_PREL31 - ((S + A) | T) - P +static void relocR_ARM_PREL31(uint8_t *location, uint64_t P, uint64_t S, + int64_t A, bool addressesThumb) { + uint64_t T = addressesThumb; + uint32_t result = (uint32_t)(((S + A) | T) - P); + const uint32_t mask = 0x7FFFFFFF; + uint32_t rel31 = result & mask; + + 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); + llvm::dbgs() << " rel31: 0x" << Twine::utohexstr(rel31) << "\n"); + + applyArmReloc(location, rel31, mask); +} + /// \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; @@ -183,6 +234,24 @@ relocR_ARM_THM_B_L(location, result, true); } +/// \brief R_ARM_THM_JUMP11 - S + A - P +static void relocR_ARM_THM_JUMP11(uint8_t *location, uint64_t P, uint64_t S, + int64_t A) { + uint32_t result = (uint32_t)(S + A - 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() << " result: 0x" << Twine::utohexstr(result) << "\n"); + + //we cut off first bit because it is always 1 according to p. 4.5.3 + result = (result & 0x0FFE) >> 1; + + applyThumb16Reloc(location, result, 0x7FF); +} + /// \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, bool addressesThumb) { @@ -274,7 +343,7 @@ const uint16_t bitI = (result >> 11) & 0x1; const uint16_t resHi = (bitI << 10) | imm4; - applyThmReloc(location, resHi, resLo, 0x40F, 0x70FF); + applyThmReloc(location, resHi, resLo, 0x40F, 0x70FF); } /// \brief R_ARM_THM_MOVW_ABS_NC - (S + A) | T @@ -340,6 +409,10 @@ relocR_ARM_ABS32(location, relocVAddress, targetVAddress, addend, addressesThumb); break; + case R_ARM_REL32: + relocR_ARM_REL32(location, relocVAddress, targetVAddress, addend, + addressesThumb); + break; case R_ARM_THM_CALL: // TODO: consider adding bool variable to disable J1 & J2 for archs // before ARMv6 @@ -358,6 +431,9 @@ relocR_ARM_THM_JUMP24(location, relocVAddress, targetVAddress, addend, addressesThumb); break; + case R_ARM_THM_JUMP11: + relocR_ARM_THM_JUMP11(location, relocVAddress, targetVAddress, addend); + break; case R_ARM_MOVW_ABS_NC: relocR_ARM_MOVW_ABS_NC(location, relocVAddress, targetVAddress, addend, addressesThumb); @@ -372,6 +448,10 @@ case R_ARM_THM_MOVT_ABS: relocR_ARM_THM_MOVT_ABS(location, relocVAddress, targetVAddress, addend); break; + case R_ARM_PREL31: + relocR_ARM_PREL31(location, relocVAddress, targetVAddress, addend, + addressesThumb); + break; default: return make_unhandled_reloc_error(); } Index: lld/trunk/test/elf/ARM/rel-arm-prel31.test =================================================================== --- lld/trunk/test/elf/ARM/rel-arm-prel31.test +++ lld/trunk/test/elf/ARM/rel-arm-prel31.test @@ -0,0 +1,48 @@ +# Check handling of R_ARM_PREL31 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 .ARM.extab: +# CHECK: 4000a4 b1ffff7f +# CHECK: SYMBOL TABLE: +# CHECK: 00000000 *UND* 00000000 +# CHECK: 00400054 g F .text 00000050 __gxx_personality_v0 + +--- +FileHeader: + Class: ELFCLASS32 + Data: ELFDATA2LSB + Type: ET_REL + Machine: EM_ARM + Flags: [ EF_ARM_EABI_VER5 ] +Sections: + - Name: .ARM.extab + Type: SHT_PROGBITS + Flags: [ SHF_ALLOC ] + AddressAlign: 0x4 + Content: 0000000084019701B0B0B008FFFF01080E2432003A040000 + - Name: .rel.ARM.extab + Type: SHT_REL + Link: .symtab + AddressAlign: 0x4 + Info: .ARM.extab + Relocations: + - Offset: 0 + Symbol: __gxx_personality_v0 + Type: R_ARM_PREL31 + - Name: .text + Type: SHT_PROGBITS + Flags: [ SHF_ALLOC, SHF_EXECINSTR ] + AddressAlign: 0x4 + Content: 80B400AF00231846BD465DF8047B704780B582B000AF3B1D1846FFF7FEFFFFF7FEFFFFF7FEFF0420FFF7FEFF0346184601230360002240F20001C0F20001FFF7FEFF3B1D1846FFF7FEFFFFF7FEFF00BF +Symbols: + Local: + Global: + - Name: __gxx_personality_v0 + Type: STT_FUNC + Section: .text + Value: 0x1 +... + Index: lld/trunk/test/elf/ARM/rel-rel32.test =================================================================== --- lld/trunk/test/elf/ARM/rel-rel32.test +++ lld/trunk/test/elf/ARM/rel-rel32.test @@ -0,0 +1,97 @@ +# Check handling of R_ARM_REL32 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-NEXT: 400074 80b400af 880f0000 +# CHECK: SYMBOL TABLE: +# CHECK: 00400074 g F .text 00000004 main +# CHECK: 00401000 g .bss 00000004 _myref + +--- +--- +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: 80B400AF0000000000231846BD465DF8047B7047 + - Name: .rel.text + Type: SHT_REL + Link: .symtab + AddressAlign: 0x0000000000000004 + Info: .text + Relocations: + - Offset: 0x0000000000000004 + Symbol: _myref + Type: R_ARM_REL32 + - 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: '00474343' + - Name: .comment + Type: SHT_PROGBITS + Flags: [ SHF_MERGE, SHF_STRINGS ] + AddressAlign: 0x0000000000000001 + Content: 004743433A202863726F7373746F6F6C2D4E47206C696E61726F2D312E31332E312D342E392D323031342E3039202D204C696E61726F2047434320342E392D323031342E30392920342E392E32203230313430393034202870726572656C656173652900 + - Name: .note.GNU-stack + Type: SHT_PROGBITS + AddressAlign: 0x0000000000000001 + Content: '' + - Name: .ARM.attributes + Type: SHT_ARM_ATTRIBUTES + AddressAlign: 0x0000000000000001 + Content: 4134000000616561626900012A00000005372D4100060A0741080109020A041204140115011703180119011A021B031C011E062201 +Symbols: + Local: + - Name: test.c + Type: STT_FILE + - Name: .text + Type: STT_SECTION + Section: .text + - Name: .data + Type: STT_SECTION + Section: .data + - Name: .bss + Type: STT_SECTION + Section: .bss + - Name: '$d' + Section: .text + Value: 0x0000000000000004 + - Name: '$t' + Section: .text + Value: 0x0000000000000008 + - Name: .note.GNU-stack + Type: STT_SECTION + Section: .note.GNU-stack + - Name: .comment + Type: STT_SECTION + Section: .comment + - Name: .ARM.attributes + Type: STT_SECTION + Section: .ARM.attributes + Global: + - Name: _myref + Type: STT_OBJECT + Section: .bss + Size: 0x0000000000000004 + - Name: main + Type: STT_FUNC + Section: .text + Value: 0x0000000000000001 + Size: 0x0000000000000014 +... Index: lld/trunk/test/elf/ARM/rel-thm-jump11.test =================================================================== --- lld/trunk/test/elf/ARM/rel-thm-jump11.test +++ lld/trunk/test/elf/ARM/rel-thm-jump11.test @@ -0,0 +1,141 @@ +# Check handling of R_ARM_THM_JUMP11 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: 4001a4 0021c7e7 +# CHECK: SYMBOL TABLE: +# CHECK: 00400138 g F .text 00000060 __gnu_h2f_internal +# CHECK: 004001a4 g F .text 00000004 __gnu_h2f_alternative + +--- +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: 70B4020CC0F3C754FF2CC0F3160302F4004080B241D0002C08BF002B3BD0A4F17F0543F4000315F10E0FA8BF41F6FF7209DA15F1190FA3BFA4F166066FF07F42F2406FF07F4212EA03060CD001325208964208BF03EA42021344B3F1807F24BF5B08A4F17E0501B30F2D26DC15F1180F11DB15F10E0FB5BF4FF6F2710E35CFF6FF71AD02B7BF491BAAB2CB40002202EB5333034398B270BC70470029FBD040EA533370BC43F4FC407047102DDEDD6FEAD0336FEAC33398B2EDE740F4F84398B2E9E700BFC0F3842310B4A3F11F040029B4FA84F400F400424FEA541408BF0024C0F309002146140481B943B14203703302EBC35343EA04005DF8044B704760B1B0FA80F3153B98405B42EFE744EA40305DF8044B40F0FF40704720465DF8044B704700BF01216BE70121FEE7002167E70021FEE7 + - Name: .rel.text + Type: SHT_REL + Link: .symtab + AddressAlign: 0x0000000000000004 + Info: .text + Relocations: + - Offset: 0x000000000000012A + Symbol: __gnu_h2f_internal + Type: R_ARM_THM_JUMP11 + - Offset: 0x0000000000000132 + Symbol: __gnu_h2f_internal + Type: R_ARM_THM_JUMP11 + - Name: .text.startup + Type: SHT_PROGBITS + Flags: [ SHF_ALLOC, SHF_EXECINSTR ] + AddressAlign: 0x0000000000000004 + Content: 0020FFF7FEBF00BF + - Name: .rel.text.startup + Type: SHT_REL + Link: .symtab + AddressAlign: 0x0000000000000004 + Info: .text.startup + Relocations: + - Offset: 0x0000000000000002 + Symbol: __gnu_h2f_alternative + Type: R_ARM_THM_JUMP24 + - 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: '' + - Name: .comment + Type: SHT_PROGBITS + Flags: [ SHF_MERGE, SHF_STRINGS ] + AddressAlign: 0x0000000000000001 + Content: 004743433A202863726F7373746F6F6C2D4E47206C696E61726F2D312E31332E312D342E392D323031342E3039202D204C696E61726F2047434320342E392D323031342E30392920342E392E32203230313430393034202870726572656C656173652900 + - Name: .note.GNU-stack + Type: SHT_PROGBITS + AddressAlign: 0x0000000000000001 + Content: '' + - Name: .ARM.attributes + Type: SHT_ARM_ATTRIBUTES + AddressAlign: 0x0000000000000001 + Content: 4134000000616561626900012A00000005372D4100060A0741080109020A041204140115011703180119011A021B031C011E022201 +Symbols: + Local: + - Name: .text + Type: STT_SECTION + Section: .text + - Name: .text.startup + Type: STT_SECTION + Section: .text.startup + - Name: .data + Type: STT_SECTION + Section: .data + - Name: .bss + Type: STT_SECTION + Section: .bss + - Name: .comment + Type: STT_SECTION + Section: .comment + - Name: .note.GNU-stack + Type: STT_SECTION + Section: .note.GNU-stack + - Name: .ARM.attributes + Type: STT_SECTION + Section: .ARM.attributes + - Name: '$t' + Section: .text + - Name: __gnu_f2h_internal + Type: STT_FUNC + Section: .text + Value: 0x0000000000000001 + Size: 0x00000000000000C2 + Global: + - Name: __gnu_f2h_alternative + Type: STT_FUNC + Section: .text + Value: 0x000000000000012D + Size: 0x0000000000000004 + Visibility: STV_HIDDEN + - Name: __gnu_h2f_alternative + Type: STT_FUNC + Section: .text + Value: 0x0000000000000131 + Size: 0x0000000000000004 + Visibility: STV_HIDDEN + - Name: __gnu_h2f_ieee + Type: STT_FUNC + Section: .text + Value: 0x0000000000000129 + Size: 0x0000000000000004 + Visibility: STV_HIDDEN + - Name: main + Type: STT_FUNC + Section: .text.startup + Value: 0x0000000000000001 + Size: 0x0000000000000006 + - Name: __gnu_f2h_ieee + Type: STT_FUNC + Section: .text + Value: 0x0000000000000125 + Size: 0x0000000000000004 + Visibility: STV_HIDDEN + - Name: __gnu_h2f_internal + Type: STT_FUNC + Section: .text + Value: 0x00000000000000C5 + Size: 0x000000000000005E + Visibility: STV_HIDDEN +...