Index: include/lld/ReaderWriter/ELFLinkingContext.h =================================================================== --- include/lld/ReaderWriter/ELFLinkingContext.h +++ include/lld/ReaderWriter/ELFLinkingContext.h @@ -302,6 +302,10 @@ script::Sema &linkerScriptSema() { return _linkerScriptSema; } const script::Sema &linkerScriptSema() const { return _linkerScriptSema; } + // Set R_ARM_TARGET1 relocation behaviour + bool armTarget1Rel() const { return _armTarget1Rel; } + void setArmTarget1Rel(bool value) { _armTarget1Rel = value; } + protected: ELFLinkingContext(llvm::Triple triple, std::unique_ptr handler) : _triple(triple), _targetHandler(std::move(handler)) {} @@ -327,6 +331,7 @@ bool _stripSymbols = false; bool _alignSegments = true; bool _collectStats = false; + bool _armTarget1Rel = false; uint64_t _maxPageSize = 0x1000; OutputMagic _outputMagic; Index: lib/Driver/GnuLdDriver.cpp =================================================================== --- lib/Driver/GnuLdDriver.cpp +++ lib/Driver/GnuLdDriver.cpp @@ -543,6 +543,25 @@ if (auto *arg = parsedArgs->getLastArg(OPT_output_filetype)) ctx->setOutputFileType(arg->getValue()); + // Process ELF/ARM specific options + bool hasArmTarget1Rel = parsedArgs->hasArg(OPT_arm_target1_rel); + bool hasArmTarget1Abs = parsedArgs->hasArg(OPT_arm_target1_abs); + if (triple.getArch() == llvm::Triple::arm) { + if (hasArmTarget1Rel && hasArmTarget1Abs) { + diag << "error: options --arm-target1-rel and --arm-target1-abs" + " can't be used together.\n"; + return false; + } else if (hasArmTarget1Rel || hasArmTarget1Abs) { + ctx->setArmTarget1Rel(hasArmTarget1Rel && !hasArmTarget1Abs); + } + } else if (hasArmTarget1Rel) { + diag << "warning: ignoring unsupported ARM/ELF specific argument: " + << "--arm-target1-rel\n"; + } else if (hasArmTarget1Abs) { + diag << "warning: ignoring unsupported ARM/ELF specific argument: " + << "--arm-target1-abs\n"; + } + for (auto *arg : parsedArgs->filtered(OPT_L)) ctx->addSearchPath(arg->getValue()); Index: lib/Driver/GnuLdOptions.td =================================================================== --- lib/Driver/GnuLdOptions.td +++ lib/Driver/GnuLdOptions.td @@ -313,6 +313,16 @@ Alias; //===----------------------------------------------------------------------===// +/// Target Specific Options +//===----------------------------------------------------------------------===// +def grp_targetopts : OptionGroup<"opts">, + HelpText<"ARCH SPECIFIC OPTIONS">; +def arm_target1_rel : Flag<["--"], "arm-target1-rel">, + Group, HelpText<"Interpret R_ARM_TARGET1 as R_ARM_REL32">; +def arm_target1_abs : Flag<["--"], "arm-target1-abs">, + Group, HelpText<"Interpret R_ARM_TARGET1 as R_ARM_ABS32">; + +//===----------------------------------------------------------------------===// /// Ignored options //===----------------------------------------------------------------------===// def grp_ignored: OptionGroup<"ignored">, Index: lib/ReaderWriter/ELF/ARM/ARMRelocationHandler.cpp =================================================================== --- lib/ReaderWriter/ELF/ARM/ARMRelocationHandler.cpp +++ lib/ReaderWriter/ELF/ARM/ARMRelocationHandler.cpp @@ -84,6 +84,7 @@ switch (kindValue) { case R_ARM_ABS32: case R_ARM_REL32: + case R_ARM_TARGET1: case R_ARM_GOT_BREL: case R_ARM_BASE_PREL: case R_ARM_TLS_IE32: @@ -529,6 +530,14 @@ relocR_ARM_REL32(location, relocVAddress, targetVAddress, addend, addressesThumb); break; + case R_ARM_TARGET1: + if (_armLayout.target1Rel()) + relocR_ARM_REL32(location, relocVAddress, targetVAddress, addend, + addressesThumb); + else + 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 Index: lib/ReaderWriter/ELF/ARM/ARMTargetHandler.h =================================================================== --- lib/ReaderWriter/ELF/ARM/ARMTargetHandler.h +++ lib/ReaderWriter/ELF/ARM/ARMTargetHandler.h @@ -45,6 +45,8 @@ llvm_unreachable("TLS segment not found"); } + bool target1Rel() const { return _ctx.armTarget1Rel(); } + private: // TCB block size of the TLS. enum { TCB_SIZE = 0x8 }; Index: test/elf/ARM/rel-target1.test =================================================================== --- /dev/null +++ test/elf/ARM/rel-target1.test @@ -0,0 +1,116 @@ +# Check handling of R_ARM_TARGET1 relocation. +# +# 1. R_ARM_TARGET1 is equal to R_ARM_ABS32 +# RUN: yaml2obj -format=elf -docnum 1 %s > %t-abs32.o +# RUN: lld -flavor gnu -target arm -m armelf_linux_eabi -Bstatic \ +# RUN: --noinhibit-exec --arm-target1-abs %t-abs32.o -o %t-abs32 +# RUN: llvm-objdump -s -t %t-abs32 | FileCheck -check-prefix=CHECK-ABS32 %s +# +# CHECK-ABS32: Contents of section .data: +# CHECK-ABS32-NEXT: 401000 84004000 +# CHECK-ABS32: SYMBOL TABLE: +# CHECK-ABS32: 00400074 g F .text {{[0-9a-f]+}} main +# CHECK-ABS32: 00401000 g .data 00000004 data +# +# 2. R_ARM_TARGET1 is equal to R_ARM_REL32 +# Check handling of R_ARM_REL32 relocation. +# RUN: yaml2obj -format=elf %s -docnum 2 > %t-rel32.o +# RUN: lld -flavor gnu -target arm -m armelf_linux_eabi -Bstatic \ +# RUN: --noinhibit-exec --arm-target1-rel %t-rel32.o -o %t-rel32 +# RUN: llvm-objdump -s -t %t-rel32 | FileCheck -check-prefix=CHECK-REL32 %s +# +# CHECK-REL32: Contents of section .text: +# CHECK-REL32-NEXT: 400074 {{[0-9a-f]+}} 880fff00 +# CHECK-REL32: SYMBOL TABLE: +# CHECK-REL32: 00400074 g F .text {{[0-9a-f]+}} main +# CHECK-REL32: 00401000 g .bss {{[0-9a-f]+}} _myref + +# abs32.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: 04B02DE500B08DE20030A0E30300A0E100D04BE204B09DE41EFF2FE1 + - Name: .data + Type: SHT_PROGBITS + Flags: [ SHF_WRITE, SHF_ALLOC ] + AddressAlign: 0x0000000000000004 + Content: '10000000' + - Name: .rel.data + Type: SHT_REL + Link: .symtab + AddressAlign: 0x0000000000000004 + Info: .data + Relocations: + - Offset: 0x0000000000000000 + Symbol: main + Type: R_ARM_TARGET1 + Addend: 0 + - Name: .bss + Type: SHT_NOBITS + Flags: [ SHF_WRITE, SHF_ALLOC ] + AddressAlign: 0x0000000000000001 + Content: '' +Symbols: + Global: + - Name: main + Type: STT_FUNC + Section: .text + Size: 0x000000000000001C + - Name: data + Type: STT_OBJECT + Section: .data + Size: 0x0000000000000004 +# rel32.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: 80B400AF0000FF0000231846BD465DF8047B7047 + - Name: .rel.text + Type: SHT_REL + Link: .symtab + AddressAlign: 0x0000000000000004 + Info: .text + Relocations: + - Offset: 0x0000000000000004 + Symbol: _myref + Type: R_ARM_TARGET1 + - 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: '' +Symbols: + Global: + - Name: _myref + Type: STT_OBJECT + Section: .bss + Size: 0x0000000000000004 + - Name: main + Type: STT_FUNC + Section: .text + Value: 0x0000000000000001 + Size: 0x0000000000000014 +... Index: test/elf/options/target-specific-args.test =================================================================== --- /dev/null +++ test/elf/options/target-specific-args.test @@ -0,0 +1,5 @@ +# Test of target specific options +# RUN: lld -flavor gnu -target x86_64 --arm-target1-rel \ +# RUN: %p/../Inputs/foo.o.x86-64 --noinhibit-exec -o %t 2>&1 | FileCheck %s + +# CHECK: warning: ignoring unsupported ARM/ELF specific argument: --arm-target1-rel