Index: ELF/Driver.cpp =================================================================== --- ELF/Driver.cpp +++ ELF/Driver.cpp @@ -468,15 +468,6 @@ if (!RPaths.empty()) Config->RPath = llvm::join(RPaths.begin(), RPaths.end(), ":"); - if (auto *Arg = Args.getLastArg(OPT_m)) { - // Parse ELF{32,64}{LE,BE} and CPU type. - StringRef S = Arg->getValue(); - std::tie(Config->EKind, Config->EMachine, Config->OSABI) = - parseEmulation(S); - Config->MipsN32Abi = (S == "elf32btsmipn32" || S == "elf32ltsmipn32"); - Config->Emulation = S; - } - Config->AllowMultipleDefinition = Args.hasArg(OPT_allow_multiple_definition); Config->Bsymbolic = Args.hasArg(OPT_Bsymbolic); Config->BsymbolicFunctions = Args.hasArg(OPT_Bsymbolic_functions); @@ -509,6 +500,7 @@ Config->WarnCommon = Args.hasArg(OPT_warn_common); Config->DynamicLinker = getString(Args, OPT_dynamic_linker); + Config->Emulation = getString(Args, OPT_m); Config->Entry = getString(Args, OPT_entry); Config->Fini = getString(Args, OPT_fini, "_fini"); Config->Init = getString(Args, OPT_init, "_init"); @@ -695,11 +687,18 @@ error("no input files"); } -// If -m was not given, infer it from object files. void LinkerDriver::inferMachineType() { - if (Config->EKind != ELFNoneKind) - return; + // Take machine type from emulation first. That is done early so + // we are able to report wrong emulation values if any. + if (!Config->Emulation.empty()) { + std::tie(Config->EKind, Config->EMachine, Config->OSABI) = + parseEmulation(Config->Emulation); + Config->MipsN32Abi = Config->Emulation == "elf32btsmipn32" || + Config->Emulation == "elf32ltsmipn32"; + } + // Machine type from objects has a priority over values specified by -m, + // try to override values found above. for (InputFile *F : Files) { if (F->EKind == ELFNoneKind) continue; @@ -709,7 +708,9 @@ Config->MipsN32Abi = Config->EMachine == EM_MIPS && isMipsN32Abi(F); return; } - error("target emulation unknown: -m or at least one .o file required"); + + if (Config->EKind == ELFNoneKind) + error("target emulation unknown: -m or at least one .o file required"); } // Parse -z max-page-size=. The default value is defined by Index: ELF/SymbolTable.cpp =================================================================== --- ELF/SymbolTable.cpp +++ ELF/SymbolTable.cpp @@ -43,10 +43,7 @@ return true; } - if (!Config->Emulation.empty()) - error(toString(F) + " is incompatible with " + Config->Emulation); - else - error(toString(F) + " is incompatible with " + toString(Config->FirstElf)); + error(toString(F) + " is incompatible with " + toString(Config->FirstElf)); return false; } Index: test/ELF/driver.test =================================================================== --- test/ELF/driver.test +++ test/ELF/driver.test @@ -5,9 +5,9 @@ # UNKNOWN: unknown argument: --unknown1 # UNKNOWN: unknown argument: --unknown2 -# UNKNOWN: unknown emulation: foo # UNKNOWN: cannot open /no/such/file # UNKNOWN: unable to find library -lnosuchlib +# UNKNOWN: unknown emulation: foo # RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t # RUN: not ld.lld %t -o /no/such/file 2>&1 | FileCheck -check-prefix=MISSING %s Index: test/ELF/emulation-override.s =================================================================== --- test/ELF/emulation-override.s +++ test/ELF/emulation-override.s @@ -0,0 +1,16 @@ +# REQUIRES: x86 +# RUN: llvm-mc -filetype=obj -triple=i686-unknown-linux %s -o %t.o + +## Show target output without emulation. +# RUN: ld.lld %t.o -o %t1 +# RUN: llvm-readobj %t1 | FileCheck %s +# CHECK: Format: ELF32-i386 +# CHECK-NEXT: Arch: i386 + +## Check that we are able to apply elf_x86_64 emulation for i386 object. +# RUN: ld.lld -m elf_x86_64 %t.o -o %t2 +# RUN: llvm-readobj -program-headers %t2 | FileCheck %s + +.globl _start +_start: + nop Index: test/ELF/emulation.s =================================================================== --- test/ELF/emulation.s +++ test/ELF/emulation.s @@ -4,8 +4,6 @@ # RUN: ld.lld %tx64 -o %t3x64 # RUN: llvm-readobj -file-headers %t3x64 | FileCheck --check-prefix=AMD64 %s # RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t.sysv -# RUN: ld.lld -m elf_amd64_fbsd %t.sysv -o %t.freebsd -# RUN: llvm-readobj -file-headers %t.freebsd | FileCheck --check-prefix=AMD64 %s # AMD64: ElfHeader { # AMD64-NEXT: Ident { # AMD64-NEXT: Magic: (7F 45 4C 46) @@ -32,6 +30,35 @@ # AMD64-NEXT: StringTableSectionIndex: # AMD64-NEXT: } +## Emulation is overriden by machine type from object file. +# RUN: ld.lld -m elf_amd64_fbsd %t.sysv -o %t.freebsd +# RUN: llvm-readobj -file-headers %t.freebsd | FileCheck --check-prefix=AMD64-OVERRIDE %s +# AMD64-OVERRIDE: ElfHeader { +# AMD64-OVERRIDE-NEXT: Ident { +# AMD64-OVERRIDE-NEXT: Magic: (7F 45 4C 46) +# AMD64-OVERRIDE-NEXT: Class: 64-bit (0x2) +# AMD64-OVERRIDE-NEXT: DataEncoding: LittleEndian (0x1) +# AMD64-OVERRIDE-NEXT: FileVersion: 1 +# AMD64-OVERRIDE-NEXT: OS/ABI: SystemV (0x0) +# AMD64-OVERRIDE-NEXT: ABIVersion: 0 +# AMD64-OVERRIDE-NEXT: Unused: (00 00 00 00 00 00 00) +# AMD64-OVERRIDE-NEXT: } +# AMD64-OVERRIDE-NEXT: Type: Executable (0x2) +# AMD64-OVERRIDE-NEXT: Machine: EM_X86_64 (0x3E) +# AMD64-OVERRIDE-NEXT: Version: 1 +# AMD64-OVERRIDE-NEXT: Entry: +# AMD64-OVERRIDE-NEXT: ProgramHeaderOffset: 0x40 +# AMD64-OVERRIDE-NEXT: SectionHeaderOffset: +# AMD64-OVERRIDE-NEXT: Flags [ (0x0) +# AMD64-OVERRIDE-NEXT: ] +# AMD64-OVERRIDE-NEXT: HeaderSize: 64 +# AMD64-OVERRIDE-NEXT: ProgramHeaderEntrySize: 56 +# AMD64-OVERRIDE-NEXT: ProgramHeaderCount: +# AMD64-OVERRIDE-NEXT: SectionHeaderEntrySize: 64 +# AMD64-OVERRIDE-NEXT: SectionHeaderCount: +# AMD64-OVERRIDE-NEXT: StringTableSectionIndex: +# AMD64-OVERRIDE-NEXT: } + # RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %tx64 # RUN: ld.lld -m elf_x86_64 %tx64 -o %t2x64 # RUN: llvm-readobj -file-headers %t2x64 | FileCheck --check-prefix=X86-64 %s Index: test/ELF/incompatible.s =================================================================== --- test/ELF/incompatible.s +++ test/ELF/incompatible.s @@ -23,27 +23,6 @@ // RUN: FileCheck --check-prefix=SO-AND-C %s // SO-AND-C: c.o is incompatible with {{.*}}i686.so -// RUN: not ld.lld -m elf64ppc %ta.o -o %t 2>&1 | \ -// RUN: FileCheck --check-prefix=A-ONLY %s -// A-ONLY: a.o is incompatible with elf64ppc - -// RUN: not ld.lld -m elf64ppc %tb.o -o %t 2>&1 | \ -// RUN: FileCheck --check-prefix=B-ONLY %s -// B-ONLY: b.o is incompatible with elf64ppc - -// RUN: not ld.lld -m elf64ppc %tc.o -o %t 2>&1 | \ -// RUN: FileCheck --check-prefix=C-ONLY %s -// C-ONLY: c.o is incompatible with elf64ppc - -// RUN: not ld.lld -m elf_i386 %tc.o %ti686.so -o %t 2>&1 | \ -// RUN: FileCheck --check-prefix=C-AND-SO-I386 %s -// C-AND-SO-I386: c.o is incompatible with elf_i386 - -// RUN: not ld.lld -m elf_i386 %ti686.so %tc.o -o %t 2>&1 | \ -// RUN: FileCheck --check-prefix=SO-AND-C-I386 %s -// SO-AND-C-I386: c.o is incompatible with elf_i386 - - // We used to fail to identify this incompatibility and crash trying to // read a 64 bit file as a 32 bit one. // RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %p/Inputs/archive2.s -o %ta.o Index: test/ELF/mips-n32-emul.s =================================================================== --- test/ELF/mips-n32-emul.s +++ test/ELF/mips-n32-emul.s @@ -1,14 +0,0 @@ -# Check that LLD shows an error when N32 ABI emulation argument -# is combined with non-N32 ABI object files. - -# RUN: llvm-mc -filetype=obj -triple=mips-unknown-linux %s -o %t.o -# RUN: not ld.lld -m elf32btsmipn32 %t.o -o %t.exe 2>&1 | FileCheck %s - -# REQUIRES: mips - - .text - .global __start -__start: - nop - -# CHECK: error: {{.*}}mips-n32-emul.s.tmp.o is incompatible with elf32btsmipn32