[lld] r244035 - lld elf2: Diagnose trying to mix incompatible files.

Rafael Espindola rafael.espindola at gmail.com
Wed Aug 5 05:03:35 PDT 2015


Author: rafael
Date: Wed Aug  5 07:03:34 2015
New Revision: 244035

URL: http://llvm.org/viewvc/llvm-project?rev=244035&view=rev
Log:
lld elf2: Diagnose trying to mix incompatible files.

This is also a step in instantiating the writer with the correct template
argument.

Added:
    lld/trunk/test/elf2/incompatible.test
Modified:
    lld/trunk/ELF/InputFiles.cpp
    lld/trunk/ELF/InputFiles.h
    lld/trunk/ELF/SymbolTable.cpp

Modified: lld/trunk/ELF/InputFiles.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/InputFiles.cpp?rev=244035&r1=244034&r2=244035&view=diff
==============================================================================
--- lld/trunk/ELF/InputFiles.cpp (original)
+++ lld/trunk/ELF/InputFiles.cpp Wed Aug  5 07:03:34 2015
@@ -18,6 +18,14 @@ using namespace llvm::ELF;
 using namespace lld;
 using namespace lld::elf2;
 
+template <class ELFT>
+bool ObjectFile<ELFT>::isCompatibleWith(const ObjectFileBase &Other) const {
+  if (kind() != Other.kind())
+    return false;
+  return getObj()->getHeader()->e_machine ==
+         cast<ObjectFile<ELFT>>(Other).getObj()->getHeader()->e_machine;
+}
+
 template <class ELFT> void elf2::ObjectFile<ELFT>::parse() {
   // Parse a memory buffer as a ELF file.
   std::error_code EC;

Modified: lld/trunk/ELF/InputFiles.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/InputFiles.h?rev=244035&r1=244034&r2=244035&view=diff
==============================================================================
--- lld/trunk/ELF/InputFiles.h (original)
+++ lld/trunk/ELF/InputFiles.h Wed Aug  5 07:03:34 2015
@@ -21,7 +21,7 @@ class Chunk;
 // The root class of input files.
 class InputFile {
 public:
-  enum Kind { ObjectKind };
+  enum Kind { Object32LEKind, Object32BEKind, Object64LEKind, Object64BEKind };
   Kind kind() const { return FileKind; }
   virtual ~InputFile() {}
 
@@ -31,6 +31,8 @@ public:
   // Reads a file (constructors don't do that).
   virtual void parse() = 0;
 
+  StringRef getName() const { return MB.getBufferIdentifier(); }
+
 protected:
   explicit InputFile(Kind K, MemoryBufferRef M) : MB(M), FileKind(K) {}
   MemoryBufferRef MB;
@@ -42,12 +44,17 @@ private:
 // .o file.
 class ObjectFileBase : public InputFile {
 public:
-  explicit ObjectFileBase(MemoryBufferRef M) : InputFile(ObjectKind, M) {}
-  static bool classof(const InputFile *F) { return F->kind() == ObjectKind; }
+  explicit ObjectFileBase(Kind K, MemoryBufferRef M) : InputFile(K, M) {}
+  static bool classof(const InputFile *F) {
+    Kind K = F->kind();
+    return K >= Object32LEKind && K <= Object64BEKind;
+  }
 
   ArrayRef<Chunk *> getChunks() { return Chunks; }
   ArrayRef<SymbolBody *> getSymbols() override { return SymbolBodies; }
 
+  virtual bool isCompatibleWith(const ObjectFileBase &Other) const = 0;
+
 protected:
   // List of all chunks defined by this file. This includes both section
   // chunks and non-section chunks for common symbols.
@@ -65,11 +72,26 @@ template <class ELFT> class ObjectFile :
   typedef typename llvm::object::ELFFile<ELFT>::Elf_Sym_Range Elf_Sym_Range;
 
 public:
-  explicit ObjectFile(MemoryBufferRef M) : ObjectFileBase(M) {}
+  bool isCompatibleWith(const ObjectFileBase &Other) const override;
+
+  static Kind getKind() {
+    if (!ELFT::Is64Bits) {
+      if (ELFT::TargetEndianness == llvm::support::little)
+        return Object32LEKind;
+      return Object32BEKind;
+    }
+    if (ELFT::TargetEndianness == llvm::support::little)
+      return Object64LEKind;
+    return Object64BEKind;
+  }
+
+  static bool classof(const InputFile *F) { return F->kind() == getKind(); }
+
+  explicit ObjectFile(MemoryBufferRef M) : ObjectFileBase(getKind(), M) {}
   void parse() override;
 
   // Returns the underying ELF file.
-  llvm::object::ELFFile<ELFT> *getObj() { return ELFObj.get(); }
+  llvm::object::ELFFile<ELFT> *getObj() const { return ELFObj.get(); }
 
 private:
   void initializeChunks();

Modified: lld/trunk/ELF/SymbolTable.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/SymbolTable.cpp?rev=244035&r1=244034&r2=244035&view=diff
==============================================================================
--- lld/trunk/ELF/SymbolTable.cpp (original)
+++ lld/trunk/ELF/SymbolTable.cpp Wed Aug  5 07:03:34 2015
@@ -26,6 +26,12 @@ void SymbolTable::addFile(std::unique_pt
 }
 
 void SymbolTable::addObject(ObjectFileBase *File) {
+  if (!ObjectFiles.empty()) {
+    ObjectFileBase &Old = *ObjectFiles[0];
+    if (!Old.isCompatibleWith(*File))
+      error(Twine(Old.getName() + " is incompatible with " + File->getName()));
+  }
+
   ObjectFiles.emplace_back(File);
   for (SymbolBody *Body : File->getSymbols())
     if (Body->isExternal())

Added: lld/trunk/test/elf2/incompatible.test
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/elf2/incompatible.test?rev=244035&view=auto
==============================================================================
--- lld/trunk/test/elf2/incompatible.test (added)
+++ lld/trunk/test/elf2/incompatible.test Wed Aug  5 07:03:34 2015
@@ -0,0 +1,13 @@
+// RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %ta.o
+// RUN: llvm-mc -filetype=obj -triple=i686-unknown-linux %s -o %tb.o
+// RUN: llvm-mc -filetype=obj -triple=arm-unknown-linux %s -o %tc.o
+
+// 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
+
+// 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
+
+// REQUIRES: x86,arm




More information about the llvm-commits mailing list