[ELF2] Handle -m option
Parse and apply emulation given with -m option.
Check input files to match ELF type and machine architecture provided with -m.
Differential Revision: http://reviews.llvm.org/D13055
llvm-svn: 249529
diff --git a/lld/ELF/Driver.cpp b/lld/ELF/Driver.cpp
index fb76f6a..a8170b1 100644
--- a/lld/ELF/Driver.cpp
+++ b/lld/ELF/Driver.cpp
@@ -19,6 +19,7 @@
#include "llvm/Support/Path.h"
using namespace llvm;
+using namespace llvm::ELF;
using namespace lld;
using namespace lld::elf2;
@@ -34,6 +35,30 @@
Driver->link(Args.slice(1));
}
+static void setELFType(StringRef Emul) {
+ if (Emul == "elf_i386") {
+ Config->ElfKind = ELF32LEKind;
+ Config->EMachine = EM_386;
+ return;
+ }
+ if (Emul == "elf_x86_64") {
+ Config->ElfKind = ELF64LEKind;
+ Config->EMachine = EM_X86_64;
+ return;
+ }
+ if (Emul == "elf32ppc") {
+ Config->ElfKind = ELF32BEKind;
+ Config->EMachine = EM_PPC;
+ return;
+ }
+ if (Emul == "elf64ppc") {
+ Config->ElfKind = ELF64BEKind;
+ Config->EMachine = EM_PPC64;
+ return;
+ }
+ error(Twine("Unknown emulation: ") + Emul);
+}
+
// Makes a path by concatenating Dir and File.
// If Dir starts with '=' the result will be preceded by Sysroot,
// which can be set with --sysroot command line switch.
@@ -67,6 +92,28 @@
error(Twine("Unable to find library -l") + Path);
}
+template <template <class> class T>
+std::unique_ptr<ELFFileBase>
+LinkerDriver::createELFInputFile(MemoryBufferRef MB) {
+ std::unique_ptr<ELFFileBase> File = createELFFile<T>(MB);
+ const ELFKind ElfKind = File->getELFKind();
+ const uint16_t EMachine = File->getEMachine();
+
+ // Grab target from the first input file if wasn't set by -m option.
+ if (Config->ElfKind == ELFNoneKind) {
+ Config->ElfKind = ElfKind;
+ Config->EMachine = EMachine;
+ return File;
+ }
+ if (ElfKind == Config->ElfKind && EMachine == Config->EMachine)
+ return File;
+
+ if (const ELFFileBase *First = Symtab.getFirstELF())
+ error(MB.getBufferIdentifier() + " is incompatible with " +
+ First->getName());
+ error(MB.getBufferIdentifier() + " is incompatible with target architecture");
+}
+
// Opens and parses a file. Path has to be resolved already.
// Newly created memory buffers are owned by this driver.
void LinkerDriver::addFile(StringRef Path) {
@@ -85,10 +132,10 @@
Symtab.addFile(make_unique<ArchiveFile>(MBRef));
return;
case file_magic::elf_shared_object:
- Symtab.addFile(createELFFile<SharedFile>(MBRef));
+ Symtab.addFile(createELFInputFile<SharedFile>(MBRef));
return;
default:
- Symtab.addFile(createELFFile<ObjectFile>(MBRef));
+ Symtab.addFile(createELFInputFile<ObjectFile>(MBRef));
}
}
@@ -126,6 +173,9 @@
if (auto *Arg = Args.getLastArg(OPT_soname))
Config->SoName = Arg->getValue();
+ if (auto *Arg = Args.getLastArg(OPT_m))
+ setELFType(Arg->getValue());
+
Config->AllowMultipleDefinition = Args.hasArg(OPT_allow_multiple_definition);
Config->DiscardAll = Args.hasArg(OPT_discard_all);
Config->DiscardLocals = Args.hasArg(OPT_discard_locals);
@@ -185,5 +235,7 @@
case ELF64BEKind:
writeResult<object::ELF64BE>(&Symtab);
return;
+ default:
+ llvm_unreachable("Invalid kind");
}
}