Index: ELF/Config.h =================================================================== --- ELF/Config.h +++ ELF/Config.h @@ -75,7 +75,6 @@ llvm::StringMap SectionStartMap; llvm::StringRef DynamicLinker; llvm::StringRef Entry; - llvm::StringRef Emulation; llvm::StringRef Fini; llvm::StringRef Init; llvm::StringRef LTOAAPipeline; @@ -85,6 +84,7 @@ llvm::StringRef SoName; llvm::StringRef Sysroot; llvm::StringSet<> RetainSymbolsFile; + std::pair Emulation; std::string RPath; std::vector VersionDefinitions; std::vector AuxiliaryList; Index: ELF/Driver.cpp =================================================================== --- ELF/Driver.cpp +++ ELF/Driver.cpp @@ -65,15 +65,19 @@ } // Parses a linker -m option. -static std::tuple parseEmulation(StringRef Emul) { - uint8_t OSABI = 0; +static void parseEmulation(StringRef Emul) { + if (Emul.empty()) + return; + StringRef S = Emul; if (S.endswith("_fbsd")) { S = S.drop_back(5); - OSABI = ELFOSABI_FREEBSD; + Config->OSABI = ELFOSABI_FREEBSD; } - std::pair Ret = + Config->MipsN32Abi = Emul == "elf32btsmipn32" || Emul == "elf32ltsmipn32"; + + Config->Emulation = StringSwitch>(S) .Cases("aarch64elf", "aarch64linux", {ELF64LEKind, EM_AARCH64}) .Case("armelf_linux_eabi", {ELF32LEKind, EM_ARM}) @@ -91,13 +95,12 @@ .Case("elf_iamcu", {ELF32LEKind, EM_IAMCU}) .Default({ELFNoneKind, EM_NONE}); - if (Ret.first == ELFNoneKind) { + if (Config->Emulation.first == ELFNoneKind) { if (S == "i386pe" || S == "i386pep" || S == "thumb2pe") error("Windows targets are not supported on the ELF frontend: " + Emul); else error("unknown emulation: " + Emul); } - return std::make_tuple(Ret.first, Ret.second, OSABI); } // Returns slices of MB by parsing MB as an archive file. @@ -468,15 +471,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); @@ -547,6 +541,8 @@ Config->Target2 = getTarget2Option(Args); Config->UnresolvedSymbols = getUnresolvedSymbolOption(Args); + parseEmulation(getString(Args, OPT_m)); + if (Args.hasArg(OPT_print_map)) Config->MapFile = "-"; @@ -697,21 +693,39 @@ error("no input files"); } -// If -m was not given, infer it from object files. void LinkerDriver::inferMachineType() { - if (Config->EKind != ELFNoneKind) - return; - + // We want to try infer machine type from inputs. + // If we have a success, -m option is ignored (except OSABI value). for (InputFile *F : Files) { if (F->EKind == ELFNoneKind) continue; Config->EKind = F->EKind; Config->EMachine = F->EMachine; - Config->OSABI = F->OSABI; Config->MipsN32Abi = Config->EMachine == EM_MIPS && isMipsN32Abi(F); + // But if we already have ABI set, we keep it. That allows to keep + // ELFOSABI_FREEBSD flag set from -m. + if (!Config->OSABI) + Config->OSABI = F->OSABI; + return; + } + + // If we have at least one archive, -m is ignored and we require + // to have at least one ELF input file. + bool HasArchive = llvm::find_if(Files, [](InputFile *F) { + return F->kind() == InputFile::ArchiveKind; + }) != Files.end(); + if (HasArchive) { + error("target unknown: at least one ELF file required"); return; } - error("target emulation unknown: -m or at least one .o file required"); + + // If all our inputs are binaries or bitcode files, + // and we have no known machine type at this point, + // apply the emulation. + Config->EKind = Config->Emulation.first; + Config->EMachine = Config->Emulation.second; + if (Config->EKind == ELFNoneKind) + error("target emulation unknown: -m is 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/emulation-archive.s =================================================================== --- test/ELF/emulation-archive.s +++ test/ELF/emulation-archive.s @@ -0,0 +1,8 @@ +# REQUIRES: x86 +# RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t +# RUN: llvm-ar rcs %tar %t + +# RUN: not ld.lld %tar -o %tout 2>&1 | FileCheck %s +# CHECK: target unknown: at least one ELF file required + +# RUN: not ld.lld -m elf_x86_64 %tar -o %tout 2>&1 | FileCheck %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/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 Index: test/ELF/no-obj.s =================================================================== --- test/ELF/no-obj.s +++ test/ELF/no-obj.s @@ -2,7 +2,7 @@ // RUN: llvm-ar rcs %t.a %t.o // RUN: not ld.lld -o %t2 -u _start %t.a 2>&1 | FileCheck %s -// CHECK: target emulation unknown: -m or at least one .o file required +// CHECK: target unknown: at least one ELF file required .global _start _start: