[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