Index: include/lld/ReaderWriter/ELFLinkingContext.h =================================================================== --- include/lld/ReaderWriter/ELFLinkingContext.h +++ include/lld/ReaderWriter/ELFLinkingContext.h @@ -22,6 +22,7 @@ #include "llvm/ADT/Triple.h" #include "llvm/Object/ELF.h" #include "llvm/Support/ELF.h" +#include "llvm/Option/Arg.h" #include #include #include @@ -276,6 +277,10 @@ script::Sema &linkerScriptSema() { return _linkerScriptSema; } const script::Sema &linkerScriptSema() const { return _linkerScriptSema; } + // Apply target specific command line arg + virtual void applyTargetSpecificArgument(const llvm::opt::Arg &arg, + raw_ostream &diag); + protected: ELFLinkingContext(llvm::Triple triple, std::unique_ptr targetHandler) Index: lib/Driver/GnuLdDriver.cpp =================================================================== --- lib/Driver/GnuLdDriver.cpp +++ lib/Driver/GnuLdDriver.cpp @@ -424,6 +424,11 @@ diag << "warning: ignoring unknown argument: " << unknownArg->getValue() << "\n"; + // Process target specific arguments. + for (auto arg : *parsedArgs) + if (arg->getOption().matches(OPT_grp_targetopts)) + ctx->applyTargetSpecificArgument(*arg, diag); + // Set sys root path. if (auto *arg = parsedArgs->getLastArg(OPT_sysroot)) ctx->setSysroot(arg->getValue()); Index: lib/Driver/GnuLdOptions.td =================================================================== --- lib/Driver/GnuLdOptions.td +++ lib/Driver/GnuLdOptions.td @@ -302,6 +302,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/ARMLinkingContext.h =================================================================== --- lib/ReaderWriter/ELF/ARM/ARMLinkingContext.h +++ lib/ReaderWriter/ELF/ARM/ARMLinkingContext.h @@ -44,6 +44,16 @@ return false; } } + + bool target1Rel() const { return _target1Rel; } + void setTarget1Rel(bool value) { _target1Rel = value; } + + // Apply target specific command line arg + void applyTargetSpecificArgument(const llvm::opt::Arg &arg, + raw_ostream &diag) override; + +private: + bool _target1Rel; }; // Special methods to check code model of atoms. Index: lib/ReaderWriter/ELF/ARM/ARMLinkingContext.cpp =================================================================== --- lib/ReaderWriter/ELF/ARM/ARMLinkingContext.cpp +++ lib/ReaderWriter/ELF/ARM/ARMLinkingContext.cpp @@ -24,7 +24,8 @@ elf::ARMLinkingContext::ARMLinkingContext(llvm::Triple triple) : ELFLinkingContext(triple, std::unique_ptr( - new ARMTargetHandler(*this))) {} + new ARMTargetHandler(*this))), + _target1Rel(false) {} void elf::ARMLinkingContext::addPasses(PassManager &pm) { auto pass = createARMRelocationPass(*this); @@ -33,6 +34,22 @@ ELFLinkingContext::addPasses(pm); } +void elf::ARMLinkingContext::applyTargetSpecificArgument( + const llvm::opt::Arg &arg, raw_ostream &diag) { + if (arg.getOption().getName() == "arm-target1-rel") + { + setTarget1Rel(true); + return; + } + if (arg.getOption().getName() == "arm-target1-abs") + { + setTarget1Rel(false); + return; + } + + ELFLinkingContext::applyTargetSpecificArgument(arg, diag); +} + bool elf::isARMCode(const DefinedAtom *atom) { return isARMCode(atom->codeModel()); } Index: lib/ReaderWriter/ELF/ARM/ARMRelocationHandler.h =================================================================== --- lib/ReaderWriter/ELF/ARM/ARMRelocationHandler.h +++ lib/ReaderWriter/ELF/ARM/ARMRelocationHandler.h @@ -21,8 +21,10 @@ class ARMTargetRelocationHandler final : public TargetRelocationHandler { public: - ARMTargetRelocationHandler(ARMTargetLayout &layout) - : _armLayout(layout) {} + ARMTargetRelocationHandler(ARMTargetLayout &layout, + ARMLinkingContext &context) + : _armLayout(layout), + _armContext(context) {} std::error_code applyRelocation(ELFWriter &, llvm::FileOutputBuffer &, const lld::AtomLayout &, @@ -30,6 +32,7 @@ private: ARMTargetLayout &_armLayout; + ARMLinkingContext &_armContext; }; } // end namespace elf Index: lib/ReaderWriter/ELF/ARM/ARMRelocationHandler.cpp =================================================================== --- lib/ReaderWriter/ELF/ARM/ARMRelocationHandler.cpp +++ lib/ReaderWriter/ELF/ARM/ARMRelocationHandler.cpp @@ -82,6 +82,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: @@ -543,6 +544,14 @@ relocR_ARM_REL32(location, relocVAddress, targetVAddress, addend, addressesThumb); break; + case R_ARM_TARGET1: + if (_armContext.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.cpp =================================================================== --- lib/ReaderWriter/ELF/ARM/ARMTargetHandler.cpp +++ lib/ReaderWriter/ELF/ARM/ARMTargetHandler.cpp @@ -18,7 +18,7 @@ ARMTargetHandler::ARMTargetHandler(ARMLinkingContext &ctx) : _ctx(ctx), _armTargetLayout(new ARMTargetLayout(ctx)), _armRelocationHandler( - new ARMTargetRelocationHandler(*_armTargetLayout.get())) {} + new ARMTargetRelocationHandler(*_armTargetLayout.get(), ctx)) {} void ARMTargetHandler::registerRelocationNames(Registry ®istry) { registry.addKindTable(Reference::KindNamespace::ELF, Reference::KindArch::ARM, Index: lib/ReaderWriter/ELF/ELFLinkingContext.cpp =================================================================== --- lib/ReaderWriter/ELF/ELFLinkingContext.cpp +++ lib/ReaderWriter/ELF/ELFLinkingContext.cpp @@ -250,4 +250,11 @@ _resolver = std::move(resolver); } +// Apply target specific command line arg +void ELFLinkingContext::applyTargetSpecificArgument(const llvm::opt::Arg &arg, + raw_ostream &diag) { + diag << "warning: ignoring unknown target specific argument: " + << arg.getOption().getPrefixedName() << "\n"; +} + } // end namespace lld 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 unknown target specific argument: --arm-target1-rel