diff options
| -rw-r--r-- | lld/ELF/InputFiles.cpp | 8 | ||||
| -rw-r--r-- | lld/ELF/InputFiles.h | 32 | ||||
| -rw-r--r-- | lld/ELF/SymbolTable.cpp | 6 | ||||
| -rw-r--r-- | lld/test/elf2/incompatible.test | 13 |
4 files changed, 54 insertions, 5 deletions
diff --git a/lld/ELF/InputFiles.cpp b/lld/ELF/InputFiles.cpp index ca491435703..2b117140749 100644 --- a/lld/ELF/InputFiles.cpp +++ b/lld/ELF/InputFiles.cpp @@ -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; diff --git a/lld/ELF/InputFiles.h b/lld/ELF/InputFiles.h index b3f02f3995f..f498416b772 100644 --- a/lld/ELF/InputFiles.h +++ b/lld/ELF/InputFiles.h @@ -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 : public ObjectFileBase { 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(); diff --git a/lld/ELF/SymbolTable.cpp b/lld/ELF/SymbolTable.cpp index b9880985b2b..c7b0e088756 100644 --- a/lld/ELF/SymbolTable.cpp +++ b/lld/ELF/SymbolTable.cpp @@ -26,6 +26,12 @@ void SymbolTable::addFile(std::unique_ptr<InputFile> File) { } 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()) diff --git a/lld/test/elf2/incompatible.test b/lld/test/elf2/incompatible.test new file mode 100644 index 00000000000..e541b596e7f --- /dev/null +++ b/lld/test/elf2/incompatible.test @@ -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 |

