diff --git a/lld/ELF/Config.h b/lld/ELF/Config.h --- a/lld/ELF/Config.h +++ b/lld/ELF/Config.h @@ -187,6 +187,8 @@ bool nostdlib; bool oFormatBinary; bool omagic; + bool optEB = false; + bool optEL = false; bool optimizeBBJumps; bool optRemarksWithHotness; bool picThunk; diff --git a/lld/ELF/Driver.cpp b/lld/ELF/Driver.cpp --- a/lld/ELF/Driver.cpp +++ b/lld/ELF/Driver.cpp @@ -1125,6 +1125,13 @@ config->zWxneeded = hasZOption(args, "wxneeded"); setUnresolvedSymbolPolicy(args); + if (opt::Arg *arg = args.getLastArg(OPT_eb, OPT_el)) { + if (arg->getOption().matches(OPT_eb)) + config->optEB = true; + else + config->optEL = true; + } + for (opt::Arg *arg : args.filtered(OPT_z)) { std::pair option = StringRef(arg->getValue()).split('='); diff --git a/lld/ELF/Options.td b/lld/ELF/Options.td --- a/lld/ELF/Options.td +++ b/lld/ELF/Options.td @@ -159,6 +159,9 @@ "shared object. Implies -Bsymbolic but does not set DF_SYMBOLIC">, MetaVarName<"">; +def eb: F<"EB">, HelpText<"Select the big-endian format in OUTPUT_FORMAT">; +def el: F<"EL">, HelpText<"Select the little-endian format in OUTPUT_FORMAT">; + defm eh_frame_hdr: B<"eh-frame-hdr", "Request creation of .eh_frame_hdr section and PT_GNU_EH_FRAME segment header", "Do not create .eh_frame_hdr section">; @@ -687,8 +690,6 @@ def: F<"warn-execstack">; def: F<"warn-once">; def: F<"warn-shared-textrel">; -def: F<"EB">; -def: F<"EL">; def: JoinedOrSeparate<["-"], "G">; def: F<"Qy">; diff --git a/lld/ELF/ScriptParser.cpp b/lld/ELF/ScriptParser.cpp --- a/lld/ELF/ScriptParser.cpp +++ b/lld/ELF/ScriptParser.cpp @@ -431,13 +431,26 @@ .Default({ELFNoneKind, EM_NONE}); } -// Parse OUTPUT_FORMAT(bfdname) or OUTPUT_FORMAT(bfdname, big, little). -// Currently we ignore big and little parameters. +// Parse OUTPUT_FORMAT(bfdname) or OUTPUT_FORMAT(default, big, little). Choose +// big if -EB is specified, little if -EL is specified, or default if neither is +// specified. void ScriptParser::readOutputFormat() { expect("("); + StringRef s; config->bfdname = unquote(next()); - StringRef s = config->bfdname; + if (!consume(")")) { + expect(","); + s = unquote(next()); + if (config->optEB) + config->bfdname = s; + expect(","); + s = unquote(next()); + if (config->optEL) + config->bfdname = s; + consume(")"); + } + s = config->bfdname; if (s.consume_back("-freebsd")) config->osabi = ELFOSABI_FREEBSD; @@ -448,14 +461,6 @@ config->mipsN32Abi = true; if (config->emachine == EM_MSP430) config->osabi = ELFOSABI_STANDALONE; - - if (consume(")")) - return; - expect(","); - skip(); - expect(","); - skip(); - expect(")"); } void ScriptParser::readPhdrs() { diff --git a/lld/docs/ld.lld.1 b/lld/docs/ld.lld.1 --- a/lld/docs/ld.lld.1 +++ b/lld/docs/ld.lld.1 @@ -161,6 +161,10 @@ (shared object) References to matched non-local STV_DEFAULT symbols shouldn't be bound to definitions within the shared object. Implies .Cm -Bsymbolic but does not set DF_SYMBOLIC +.It Fl -EB +Select the big-endian format in the OUTPUT_FORMAT command. +.It Fl -EL +Select the little-endian format in the OUTPUT_FORMAT command. .It Fl -eh-frame-hdr Request creation of .Li .eh_frame_hdr diff --git a/lld/test/ELF/emulation-aarch64.s b/lld/test/ELF/emulation-aarch64.s --- a/lld/test/ELF/emulation-aarch64.s +++ b/lld/test/ELF/emulation-aarch64.s @@ -23,6 +23,20 @@ # RUN: ld.lld %t.script %t.be.o -o %t3.be # RUN: llvm-readobj --file-headers %t3.be | FileCheck --check-prefixes=AARCH64,BE %s +## Test OUTPUT_FORMAT(default, big, little). +# RUN: echo 'OUTPUT_FORMAT("elf64-littleaarch64", "elf64-bigaarch64", "elf64-littleaarch64")' > %t.script +# RUN: ld.lld -EL -T %t.script %t.o -o %t4.le +# RUN: llvm-readobj --file-headers %t4.le | FileCheck --check-prefixes=AARCH64,LE %s +# RUN: not ld.lld -EB -T %t.script %t.o -o /dev/null 2>&1 | FileCheck --check-prefix=ERR_BE %s + +# RUN: not ld.lld -T %t.script %t.be.o -o /dev/null 2>&1 | FileCheck --check-prefix=ERR_LE %s +# RUN: not ld.lld -EL -T %t.script %t.be.o -o /dev/null 2>&1 | FileCheck --check-prefix=ERR_LE %s +# RUN: ld.lld -EB -T %t.script %t.be.o -o %t4.be +# RUN: llvm-readobj --file-headers %t4.be | FileCheck --check-prefixes=AARCH64,BE %s + +# ERR_LE: error: {{.*}}.o is incompatible with elf64-littleaarch64 +# ERR_BE: error: {{.*}}.o is incompatible with elf64-bigaarch64 + # AARCH64: ElfHeader { # AARCH64-NEXT: Ident { # AARCH64-NEXT: Magic: (7F 45 4C 46) diff --git a/lld/test/ELF/invalid-linkerscript.test b/lld/test/ELF/invalid-linkerscript.test --- a/lld/test/ELF/invalid-linkerscript.test +++ b/lld/test/ELF/invalid-linkerscript.test @@ -51,7 +51,7 @@ # RUN: echo "OUTPUT_FORMAT(x y z)" > %t8 # RUN: not ld.lld %t8 no-such-file 2>&1 | FileCheck -check-prefix=ERR8 %s # RUN: not ld.lld -m elf_amd64 %t8 no-such-file 2>&1 | FileCheck -check-prefix=ERR8 %s -# ERR8: unknown output format name: x +# ERR8: , expected, but got y # ERR8: cannot open no-such-file: # RUN: echo "OUTPUT_FORMAT(elf64-x86-64 y z)" > %t9