[lld] r249529 - [ELF2] Handle -m option

Denis Protivensky via llvm-commits llvm-commits at lists.llvm.org
Wed Oct 7 02:13:04 PDT 2015


Author: denis-protivensky
Date: Wed Oct  7 04:13:03 2015
New Revision: 249529

URL: http://llvm.org/viewvc/llvm-project?rev=249529&view=rev
Log:
[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

Added:
    lld/trunk/test/elf2/emulation.s
Modified:
    lld/trunk/ELF/Config.h
    lld/trunk/ELF/Driver.cpp
    lld/trunk/ELF/Driver.h
    lld/trunk/ELF/InputFiles.cpp
    lld/trunk/ELF/InputFiles.h
    lld/trunk/ELF/Options.td
    lld/trunk/ELF/SymbolTable.cpp
    lld/trunk/test/elf2/basic.s
    lld/trunk/test/elf2/incompatible.s

Modified: lld/trunk/ELF/Config.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Config.h?rev=249529&r1=249528&r2=249529&view=diff
==============================================================================
--- lld/trunk/ELF/Config.h (original)
+++ lld/trunk/ELF/Config.h Wed Oct  7 04:13:03 2015
@@ -11,12 +11,21 @@
 #define LLD_ELF_CONFIG_H
 
 #include "llvm/ADT/StringRef.h"
+#include "llvm/Support/ELF.h"
 
 #include <vector>
 
 namespace lld {
 namespace elf2 {
 
+enum ELFKind {
+  ELFNoneKind,
+  ELF32LEKind,
+  ELF32BEKind,
+  ELF64LEKind,
+  ELF64BEKind
+};
+
 struct Configuration {
   llvm::StringRef DynamicLinker;
   llvm::StringRef Entry;
@@ -38,6 +47,8 @@ struct Configuration {
   bool Shared;
   bool Static = false;
   bool WholeArchive = false;
+  ELFKind ElfKind = ELFNoneKind;
+  uint16_t EMachine = llvm::ELF::EM_NONE;
 };
 
 extern Configuration *Config;

Modified: lld/trunk/ELF/Driver.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Driver.cpp?rev=249529&r1=249528&r2=249529&view=diff
==============================================================================
--- lld/trunk/ELF/Driver.cpp (original)
+++ lld/trunk/ELF/Driver.cpp Wed Oct  7 04:13:03 2015
@@ -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 @@ void lld::elf2::link(ArrayRef<const char
   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 @@ static std::string searchLibrary(StringR
   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 @@ void LinkerDriver::addFile(StringRef Pat
     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 @@ void LinkerDriver::link(ArrayRef<const c
   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 @@ void LinkerDriver::link(ArrayRef<const c
   case ELF64BEKind:
     writeResult<object::ELF64BE>(&Symtab);
     return;
+  default:
+    llvm_unreachable("Invalid kind");
   }
 }

Modified: lld/trunk/ELF/Driver.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Driver.h?rev=249529&r1=249528&r2=249529&view=diff
==============================================================================
--- lld/trunk/ELF/Driver.h (original)
+++ lld/trunk/ELF/Driver.h Wed Oct  7 04:13:03 2015
@@ -38,6 +38,9 @@ public:
   void addFile(StringRef Path);
 
 private:
+  template <template <class> class T>
+  std::unique_ptr<ELFFileBase> createELFInputFile(MemoryBufferRef MB);
+
   SymbolTable Symtab;
   ArgParser Parser;
   std::vector<std::unique_ptr<MemoryBuffer>> OwningMBs;

Modified: lld/trunk/ELF/InputFiles.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/InputFiles.cpp?rev=249529&r1=249528&r2=249529&view=diff
==============================================================================
--- lld/trunk/ELF/InputFiles.cpp (original)
+++ lld/trunk/ELF/InputFiles.cpp Wed Oct  7 04:13:03 2015
@@ -38,13 +38,9 @@ uint16_t ELFFileBase::getEMachine() cons
     return ::getEMachine<ELF64BE>(*this);
   case ELF64LEKind:
     return ::getEMachine<ELF64LE>(*this);
+  default:
+    llvm_unreachable("Invalid kind");
   }
-  llvm_unreachable("Invalid kind");
-}
-
-bool ELFFileBase::isCompatibleWith(const ELFFileBase &Other) const {
-  return getELFKind() == Other.getELFKind() &&
-         getEMachine() == Other.getEMachine();
 }
 
 namespace {

Modified: lld/trunk/ELF/InputFiles.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/InputFiles.h?rev=249529&r1=249528&r2=249529&view=diff
==============================================================================
--- lld/trunk/ELF/InputFiles.h (original)
+++ lld/trunk/ELF/InputFiles.h Wed Oct  7 04:13:03 2015
@@ -10,6 +10,7 @@
 #ifndef LLD_ELF_INPUT_FILES_H
 #define LLD_ELF_INPUT_FILES_H
 
+#include "Config.h"
 #include "InputSection.h"
 #include "Error.h"
 #include "Symbols.h"
@@ -49,8 +50,6 @@ private:
   const Kind FileKind;
 };
 
-enum ELFKind { ELF32LEKind, ELF32BEKind, ELF64LEKind, ELF64BEKind };
-
 class ELFFileBase : public InputFile {
 public:
   ELFFileBase(Kind K, ELFKind EKind, MemoryBufferRef M)
@@ -60,7 +59,6 @@ public:
     return K == ObjectKind || K == SharedKind;
   }
 
-  bool isCompatibleWith(const ELFFileBase &Other) const;
   ELFKind getELFKind() const { return EKind; }
 
   uint16_t getEMachine() const;

Modified: lld/trunk/ELF/Options.td
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Options.td?rev=249529&r1=249528&r2=249529&view=diff
==============================================================================
--- lld/trunk/ELF/Options.td (original)
+++ lld/trunk/ELF/Options.td Wed Oct  7 04:13:03 2015
@@ -47,6 +47,9 @@ def init : Separate<["-"], "init">, Meta
 def l : Joined<["-"], "l">, MetaVarName<"<libName>">,
   HelpText<"Root name of library to use">;
 
+def m : Separate<["-"], "m">,
+  HelpText<"Set target emulation">;
+
 def no_allow_shlib_undefined : Flag<["--"], "no-allow-shlib-undefined">;
 
 def no_whole_archive : Flag<["--"], "no-whole-archive">,
@@ -105,7 +108,6 @@ def eh_frame_hdr : Flag<["--"], "eh-fram
 def end_group : Flag<["--"], "end-group">;
 def gc_sections : Flag<["--"], "gc-sections">;
 def hash_style : Joined<["--"], "hash-style=">;
-def m : Separate<["-"], "m">;
 def no_add_needed : Flag<["--"], "no-add-needed">;
 def no_as_needed : Flag<["--"], "no-as-needed">;
 def no_fatal_warnings : Flag<["--"], "no-fatal-warnings">;

Modified: lld/trunk/ELF/SymbolTable.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/SymbolTable.cpp?rev=249529&r1=249528&r2=249529&view=diff
==============================================================================
--- lld/trunk/ELF/SymbolTable.cpp (original)
+++ lld/trunk/ELF/SymbolTable.cpp Wed Oct  7 04:13:03 2015
@@ -84,6 +84,8 @@ void SymbolTable::addUndefinedSym(String
   case ELF64BEKind:
     addUndefinedSym<ELF64BE>(Name);
     break;
+  default:
+    llvm_unreachable("Invalid kind");
   }
 }
 
@@ -138,9 +140,6 @@ template <class ELFT> void SymbolTable::
 
 template <class ELFT> void SymbolTable::addELFFile(ELFFileBase *File) {
   const ELFFileBase *Old = getFirstELF();
-  if (Old && !Old->isCompatibleWith(*File))
-    error(Twine(Old->getName() + " is incompatible with " + File->getName()));
-
   if (auto *O = dyn_cast<ObjectFileBase>(File))
     ObjectFiles.emplace_back(O);
   else if (auto *S = dyn_cast<SharedFile<ELFT>>(File))
@@ -174,6 +173,8 @@ void SymbolTable::addELFFile(ELFFileBase
   case ELF64BEKind:
     addELFFile<ELF64BE>(File);
     break;
+  default:
+    llvm_unreachable("Invalid kind");
   }
 }
 

Modified: lld/trunk/test/elf2/basic.s
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/elf2/basic.s?rev=249529&r1=249528&r2=249529&view=diff
==============================================================================
--- lld/trunk/test/elf2/basic.s (original)
+++ lld/trunk/test/elf2/basic.s Wed Oct  7 04:13:03 2015
@@ -205,3 +205,6 @@ _start:
 # RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t
 # RUN: not lld -flavor gnu2 %t %t -o %t2 2>&1 | FileCheck --check-prefix=DUP %s
 # DUP: duplicate symbol: _start in {{.*}} and {{.*}}
+
+# RUN: not lld -flavor gnu2 %t -o %t -m wrong_emul 2>&1 | FileCheck --check-prefix=UNKNOWN_EMUL %s
+# UNKNOWN_EMUL: Unknown emulation: wrong_emul

Added: lld/trunk/test/elf2/emulation.s
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/elf2/emulation.s?rev=249529&view=auto
==============================================================================
--- lld/trunk/test/elf2/emulation.s (added)
+++ lld/trunk/test/elf2/emulation.s Wed Oct  7 04:13:03 2015
@@ -0,0 +1,128 @@
+# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %tx64
+# RUN: lld -flavor gnu2 -m elf_x86_64 %tx64 -o %t2x64
+# RUN: llvm-readobj -file-headers %t2x64 | FileCheck --check-prefix=X86-64 %s
+# RUN: lld -flavor gnu2 %tx64 -o %t3x64
+# RUN: llvm-readobj -file-headers %t3x64 | FileCheck --check-prefix=X86-64 %s
+# X86-64:      ElfHeader {
+# X86-64-NEXT:   Ident {
+# X86-64-NEXT:     Magic: (7F 45 4C 46)
+# X86-64-NEXT:     Class: 64-bit (0x2)
+# X86-64-NEXT:     DataEncoding: LittleEndian (0x1)
+# X86-64-NEXT:     FileVersion: 1
+# X86-64-NEXT:     OS/ABI: SystemV (0x0)
+# X86-64-NEXT:     ABIVersion: 0
+# X86-64-NEXT:     Unused: (00 00 00 00 00 00 00)
+# X86-64-NEXT:   }
+# X86-64-NEXT:   Type: Executable (0x2)
+# X86-64-NEXT:   Machine: EM_X86_64 (0x3E)
+# X86-64-NEXT:   Version: 1
+# X86-64-NEXT:   Entry: 0x11000
+# X86-64-NEXT:   ProgramHeaderOffset: 0x40
+# X86-64-NEXT:   SectionHeaderOffset: 0x1060
+# X86-64-NEXT:   Flags [ (0x0)
+# X86-64-NEXT:   ]
+# X86-64-NEXT:   HeaderSize: 64
+# X86-64-NEXT:   ProgramHeaderEntrySize: 56
+# X86-64-NEXT:   ProgramHeaderCount: 1
+# X86-64-NEXT:   SectionHeaderEntrySize: 64
+# X86-64-NEXT:   SectionHeaderCount: 6
+# X86-64-NEXT:    StringTableSectionIndex: 5
+# X86-64-NEXT: }
+
+# RUN: llvm-mc -filetype=obj -triple=i686-unknown-linux %s -o %tx86
+# RUN: lld -flavor gnu2 -m elf_i386 %tx86 -o %t2x86
+# RUN: llvm-readobj -file-headers %t2x86 | FileCheck --check-prefix=X86 %s
+# RUN: lld -flavor gnu2 %tx86 -o %t3x86
+# RUN: llvm-readobj -file-headers %t3x86 | FileCheck --check-prefix=X86 %s
+# X86:      ElfHeader {
+# X86-NEXT:   Ident {
+# X86-NEXT:     Magic: (7F 45 4C 46)
+# X86-NEXT:     Class: 32-bit (0x1)
+# X86-NEXT:     DataEncoding: LittleEndian (0x1)
+# X86-NEXT:     FileVersion: 1
+# X86-NEXT:     OS/ABI: SystemV (0x0)
+# X86-NEXT:     ABIVersion: 0
+# X86-NEXT:     Unused: (00 00 00 00 00 00 00)
+# X86-NEXT:   }
+# X86-NEXT:   Type: Executable (0x2)
+# X86-NEXT:   Machine: EM_386 (0x3)
+# X86-NEXT:   Version: 1
+# X86-NEXT:   Entry: 0x11000
+# X86-NEXT:   ProgramHeaderOffset: 0x34
+# X86-NEXT:   SectionHeaderOffset: 0x104C
+# X86-NEXT:   Flags [ (0x0)
+# X86-NEXT:   ]
+# X86-NEXT:   HeaderSize: 52
+# X86-NEXT:   ProgramHeaderEntrySize: 32
+# X86-NEXT:   ProgramHeaderCount: 1
+# X86-NEXT:   SectionHeaderEntrySize: 40
+# X86-NEXT:   SectionHeaderCount: 6
+# X86-NEXT:    StringTableSectionIndex: 5
+# X86-NEXT: }
+
+# RUN: llvm-mc -filetype=obj -triple=powerpc64-unknown-linux %s -o %tppc64
+# RUN: lld -flavor gnu2 -m elf64ppc %tppc64 -o %t2ppc64
+# RUN: llvm-readobj -file-headers %t2ppc64 | FileCheck --check-prefix=PPC64 %s
+# RUN: lld -flavor gnu2 %tppc64 -o %t3ppc64
+# RUN: llvm-readobj -file-headers %t3ppc64 | FileCheck --check-prefix=PPC64 %s
+# PPC64:      ElfHeader {
+# PPC64-NEXT:   Ident {
+# PPC64-NEXT:     Magic: (7F 45 4C 46)
+# PPC64-NEXT:     Class: 64-bit (0x2)
+# PPC64-NEXT:     DataEncoding: BigEndian (0x2)
+# PPC64-NEXT:     FileVersion: 1
+# PPC64-NEXT:     OS/ABI: SystemV (0x0)
+# PPC64-NEXT:     ABIVersion: 0
+# PPC64-NEXT:     Unused: (00 00 00 00 00 00 00)
+# PPC64-NEXT:   }
+# PPC64-NEXT:   Type: Executable (0x2)
+# PPC64-NEXT:   Machine: EM_PPC64 (0x15)
+# PPC64-NEXT:   Version: 1
+# PPC64-NEXT:   Entry: 0x11000
+# PPC64-NEXT:   ProgramHeaderOffset: 0x40
+# PPC64-NEXT:   SectionHeaderOffset: 0x1060
+# PPC64-NEXT:   Flags [ (0x0)
+# PPC64-NEXT:   ]
+# PPC64-NEXT:   HeaderSize: 64
+# PPC64-NEXT:   ProgramHeaderEntrySize: 56
+# PPC64-NEXT:   ProgramHeaderCount: 1
+# PPC64-NEXT:   SectionHeaderEntrySize: 64
+# PPC64-NEXT:   SectionHeaderCount: 6
+# PPC64-NEXT:    StringTableSectionIndex: 5
+# PPC64-NEXT: }
+
+# RUN: llvm-mc -filetype=obj -triple=powerpc-unknown-linux %s -o %tppc
+# RUN: lld -flavor gnu2 -m elf32ppc %tppc -o %t2ppc
+# RUN: llvm-readobj -file-headers %t2ppc | FileCheck --check-prefix=PPC %s
+# RUN: lld -flavor gnu2 %tppc -o %t3ppc
+# RUN: llvm-readobj -file-headers %t3ppc | FileCheck --check-prefix=PPC %s
+# PPC:      ElfHeader {
+# PPC-NEXT:   Ident {
+# PPC-NEXT:     Magic: (7F 45 4C 46)
+# PPC-NEXT:     Class: 32-bit (0x1)
+# PPC-NEXT:     DataEncoding: BigEndian (0x2)
+# PPC-NEXT:     FileVersion: 1
+# PPC-NEXT:     OS/ABI: SystemV (0x0)
+# PPC-NEXT:     ABIVersion: 0
+# PPC-NEXT:     Unused: (00 00 00 00 00 00 00)
+# PPC-NEXT:   }
+# PPC-NEXT:   Type: Executable (0x2)
+# PPC-NEXT:   Machine: EM_PPC (0x14)
+# PPC-NEXT:   Version: 1
+# PPC-NEXT:   Entry: 0x11000
+# PPC-NEXT:   ProgramHeaderOffset: 0x34
+# PPC-NEXT:   SectionHeaderOffset: 0x104C
+# PPC-NEXT:   Flags [ (0x0)
+# PPC-NEXT:   ]
+# PPC-NEXT:   HeaderSize: 52
+# PPC-NEXT:   ProgramHeaderEntrySize: 32
+# PPC-NEXT:   ProgramHeaderCount: 1
+# PPC-NEXT:   SectionHeaderEntrySize: 40
+# PPC-NEXT:   SectionHeaderCount: 6
+# PPC-NEXT:    StringTableSectionIndex: 5
+# PPC-NEXT: }
+
+# REQUIRES: x86,ppc
+
+.globl _start;
+_start:

Modified: lld/trunk/test/elf2/incompatible.s
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/elf2/incompatible.s?rev=249529&r1=249528&r2=249529&view=diff
==============================================================================
--- lld/trunk/test/elf2/incompatible.s (original)
+++ lld/trunk/test/elf2/incompatible.s Wed Oct  7 04:13:03 2015
@@ -5,22 +5,42 @@
 
 // RUN: not lld -flavor gnu2 %ta.o %tb.o -o %t 2>&1 | \
 // RUN:   FileCheck --check-prefix=A-AND-B %s
-// A-AND-B: a.o is incompatible with {{.*}}b.o
+// A-AND-B: b.o is incompatible with {{.*}}a.o
 
 // RUN: not lld -flavor gnu2 %tb.o %tc.o -o %t 2>&1 | \
 // RUN:   FileCheck --check-prefix=B-AND-C %s
-// B-AND-C: b.o is incompatible with {{.*}}c.o
+// B-AND-C: c.o is incompatible with {{.*}}b.o
 
 // RUN: not lld -flavor gnu2 %ta.o %ti686.so -o %t 2>&1 | \
 // RUN:   FileCheck --check-prefix=A-AND-SO %s
-// A-AND-SO: a.o is incompatible with {{.*}}i686.so
+// A-AND-SO: i686.so is incompatible with {{.*}}a.o
 
 // RUN: not lld -flavor gnu2 %tc.o %ti686.so -o %t 2>&1 | \
 // RUN:   FileCheck --check-prefix=C-AND-SO %s
-// C-AND-SO: c.o is incompatible with {{.*}}i686.so
+// C-AND-SO: i686.so is incompatible with {{.*}}c.o
 
 // RUN: not lld -flavor gnu2 %ti686.so %tc.o -o %t 2>&1 | \
 // RUN:   FileCheck --check-prefix=SO-AND-C %s
-// SO-AND-C: i686.so is incompatible with {{.*}}c.o
+// SO-AND-C: c.o is incompatible with {{.*}}i686.so
+
+// RUN: not lld -flavor gnu2 -m elf64ppc %ta.o -o %t 2>&1 | \
+// RUN:   FileCheck --check-prefix=A-ONLY %s
+// A-ONLY: a.o is incompatible with target architecture
+
+// RUN: not lld -flavor gnu2 -m elf64ppc %tb.o -o %t 2>&1 | \
+// RUN:   FileCheck --check-prefix=B-ONLY %s
+// B-ONLY: b.o is incompatible with target architecture
+
+// RUN: not lld -flavor gnu2 -m elf64ppc %tc.o -o %t 2>&1 | \
+// RUN:   FileCheck --check-prefix=C-ONLY %s
+// C-ONLY: c.o is incompatible with target architecture
+
+// RUN: not lld -flavor gnu2 -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 target architecture
+
+// RUN: not lld -flavor gnu2 -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 {{.*}}i686.so
 
 // REQUIRES: x86,arm




More information about the llvm-commits mailing list