[lld] r249968 - Detect incompatible files when one of them comes from an archive.

Rafael Espindola via llvm-commits llvm-commits at lists.llvm.org
Sat Oct 10 20:36:50 PDT 2015


Author: rafael
Date: Sat Oct 10 22:36:49 2015
New Revision: 249968

URL: http://llvm.org/viewvc/llvm-project?rev=249968&view=rev
Log:
Detect incompatible files when one of them comes from an archive.

Modified:
    lld/trunk/ELF/Config.h
    lld/trunk/ELF/Driver.cpp
    lld/trunk/ELF/InputFiles.h
    lld/trunk/ELF/SymbolTable.cpp
    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=249968&r1=249967&r2=249968&view=diff
==============================================================================
--- lld/trunk/ELF/Config.h (original)
+++ lld/trunk/ELF/Config.h Sat Oct 10 22:36:49 2015
@@ -32,6 +32,7 @@ struct Configuration {
   SymbolBody *EntrySym = nullptr;
   llvm::StringRef DynamicLinker;
   llvm::StringRef Entry;
+  llvm::StringRef Emulation;
   llvm::StringRef Fini;
   llvm::StringRef Init;
   llvm::StringRef OutputFile;

Modified: lld/trunk/ELF/Driver.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Driver.cpp?rev=249968&r1=249967&r2=249968&view=diff
==============================================================================
--- lld/trunk/ELF/Driver.cpp (original)
+++ lld/trunk/ELF/Driver.cpp Sat Oct 10 22:36:49 2015
@@ -38,6 +38,7 @@ void lld::elf2::link(ArrayRef<const char
 }
 
 static std::pair<ELFKind, uint16_t> parseEmulation(StringRef S) {
+  Config->Emulation = S;
   if (S == "elf32btsmip") return {ELF32BEKind, EM_MIPS};
   if (S == "elf32ltsmip") return {ELF32LEKind, EM_MIPS};
   if (S == "elf32ppc")    return {ELF32BEKind, EM_PPC};
@@ -196,33 +197,6 @@ void LinkerDriver::createFiles(opt::Inpu
 
   if (Files.empty())
     error("no input files.");
-
-  // Set machine type if -m is not given.
-  if (Config->ElfKind == ELFNoneKind) {
-    for (std::unique_ptr<InputFile> &File : Files) {
-      auto *F = dyn_cast<ELFFileBase>(File.get());
-      if (!F)
-        continue;
-      Config->ElfKind = F->getELFKind();
-      Config->EMachine = F->getEMachine();
-      break;
-    }
-  }
-
-  // Check if all files are for the same machine type.
-  for (std::unique_ptr<InputFile> &File : Files) {
-    auto *F = dyn_cast<ELFFileBase>(File.get());
-    if (!F)
-      continue;
-    if (F->getELFKind() == Config->ElfKind &&
-        F->getEMachine() == Config->EMachine)
-      continue;
-    StringRef A = F->getName();
-    StringRef B = Files[0]->getName();
-    if (auto *Arg = Args.getLastArg(OPT_m))
-      B = Arg->getValue();
-    error(A + " is incompatible with " + B);
-  }
 }
 
 template <class ELFT> void LinkerDriver::link(opt::InputArgList &Args) {

Modified: lld/trunk/ELF/InputFiles.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/InputFiles.h?rev=249968&r1=249967&r2=249968&view=diff
==============================================================================
--- lld/trunk/ELF/InputFiles.h (original)
+++ lld/trunk/ELF/InputFiles.h Sat Oct 10 22:36:49 2015
@@ -234,17 +234,27 @@ std::unique_ptr<ELFFileBase> createELFFi
   if (Type.second != ELF::ELFDATA2LSB && Type.second != ELF::ELFDATA2MSB)
     error("Invalid data encoding: " + MB.getBufferIdentifier());
 
+  std::unique_ptr<ELFFileBase> Ret;
   if (Type.first == ELF::ELFCLASS32) {
     if (Type.second == ELF::ELFDATA2LSB)
-      return make_unique<T<object::ELF32LE>>(MB);
-    return make_unique<T<object::ELF32BE>>(MB);
-  }
-  if (Type.first == ELF::ELFCLASS64) {
+      Ret.reset(new T<object::ELF32LE>(MB));
+    else
+      Ret.reset(new T<object::ELF32BE>(MB));
+  } else if (Type.first == ELF::ELFCLASS64) {
     if (Type.second == ELF::ELFDATA2LSB)
-      return make_unique<T<object::ELF64LE>>(MB);
-    return make_unique<T<object::ELF64BE>>(MB);
+      Ret.reset(new T<object::ELF64LE>(MB));
+    else
+      Ret.reset(new T<object::ELF64BE>(MB));
+  } else {
+    error("Invalid file class: " + MB.getBufferIdentifier());
+  }
+
+  if (Config->ElfKind == ELFNoneKind) {
+    Config->ElfKind = Ret->getELFKind();
+    Config->EMachine = Ret->getEMachine();
   }
-  error("Invalid file class: " + MB.getBufferIdentifier());
+
+  return Ret;
 }
 
 } // namespace elf2

Modified: lld/trunk/ELF/SymbolTable.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/SymbolTable.cpp?rev=249968&r1=249967&r2=249968&view=diff
==============================================================================
--- lld/trunk/ELF/SymbolTable.cpp (original)
+++ lld/trunk/ELF/SymbolTable.cpp Sat Oct 10 22:36:49 2015
@@ -28,6 +28,18 @@ template <class ELFT> bool SymbolTable<E
 
 template <class ELFT>
 void SymbolTable<ELFT>::addFile(std::unique_ptr<InputFile> File) {
+
+  if (auto *E = dyn_cast<ELFFileBase>(File.get())) {
+    if (E->getELFKind() != Config->ElfKind ||
+        E->getEMachine() != Config->EMachine) {
+      StringRef A = E->getName();
+      StringRef B = Config->Emulation;
+      if (B.empty())
+        B = getFirstELF()->getName();
+      error(A + " is incompatible with " + B);
+    }
+  }
+
   if (auto *AF = dyn_cast<ArchiveFile>(File.get())) {
     ArchiveFiles.emplace_back(std::move(File));
     AF->parse();

Modified: lld/trunk/test/elf2/incompatible.s
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/elf2/incompatible.s?rev=249968&r1=249967&r2=249968&view=diff
==============================================================================
--- lld/trunk/test/elf2/incompatible.s (original)
+++ lld/trunk/test/elf2/incompatible.s Sat Oct 10 22:36:49 2015
@@ -43,4 +43,16 @@
 // 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
+// RUN: llvm-ar rc %t.a %ta.o
+// RUN: llvm-mc -filetype=obj -triple=i686-linux %s -o %tb.o
+// RUN: not ld.lld2 %t.a %tb.o 2>&1 | FileCheck --check-prefix=ARCHIVE %s
+// ARCHIVE: a.o is incompatible with {{.*}}b.o
+.global _start
+_start:
+        .long foo
+
 // REQUIRES: x86,arm




More information about the llvm-commits mailing list