[PATCH] D13055: [ELF2] Handle -m option
Rafael EspĂndola via llvm-commits
llvm-commits at lists.llvm.org
Thu Oct 1 10:20:31 PDT 2015
This patch makes isCompatibleWith redundant and should remove it (See
attached patch).
I think this OK once rebased on top of trunk.
Rui, is this OK with you too?
On 1 October 2015 at 05:09, Denis Protivensky
<dprotivensky at accesssoftek.com> wrote:
> denis-protivensky updated this revision to Diff 36201.
> denis-protivensky marked 2 inline comments as done.
> denis-protivensky added a comment.
>
> Updated:
>
> - Remove FirstOjbName Config variable, use Symtab.getFirstELF()->getName() instead
> - clang-format sources
>
>
> http://reviews.llvm.org/D13055
>
> Files:
> ELF/Config.h
> ELF/Driver.cpp
> ELF/InputFiles.cpp
> ELF/InputFiles.h
> ELF/Options.td
> ELF/SymbolTable.cpp
> test/elf2/basic.s
> test/elf2/emulation.s
> test/elf2/incompatible.s
>
-------------- next part --------------
diff --git a/ELF/Config.h b/ELF/Config.h
index 4935796..c643efd 100644
--- a/ELF/Config.h
+++ b/ELF/Config.h
@@ -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;
@@ -31,6 +40,8 @@ struct Configuration {
bool ExportDynamic;
bool NoInhibitExec;
bool Shared;
+ ELFKind ElfKind = ELFNoneKind;
+ uint16_t EMachine = llvm::ELF::EM_NONE;
};
extern Configuration *Config;
diff --git a/ELF/Driver.cpp b/ELF/Driver.cpp
index 5c65fb7..f1bc62a 100644
--- a/ELF/Driver.cpp
+++ b/ELF/Driver.cpp
@@ -19,6 +19,7 @@
#include "llvm/Support/Path.h"
using namespace llvm;
+using namespace llvm::ELF;
using namespace lld;
using namespace lld::elf2;
@@ -50,6 +51,26 @@ MemoryBufferRef openFile(StringRef Path) {
}
}
+static std::unique_ptr<InputFile> createTargetFile(MemoryBufferRef MB) {
+ std::unique_ptr<InputFile> File = createFile(MB);
+ ELFFileBase *ELFFile = dyn_cast<ELFFileBase>(File.get());
+ if (!ELFFile)
+ return File;
+
+ const ELFKind ElfKind = ELFFile->getELFKind();
+ const uint16_t EMachine = ELFFile->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 nullptr;
+ return File;
+}
+
// 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.
@@ -88,6 +109,30 @@ static bool isLinkerScript(MemoryBufferRef MB) {
return identify_magic(MB.getBuffer()) == file_magic::unknown;
}
+static void applyEmulation(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);
+}
+
void LinkerDriver::link(ArrayRef<const char *> ArgsArr) {
// Parse command line options.
opt::InputArgList Args = Parser.parse(ArgsArr);
@@ -113,6 +158,12 @@ void LinkerDriver::link(ArrayRef<const char *> ArgsArr) {
if (auto *Arg = Args.getLastArg(OPT_entry))
Config->Entry = Arg->getValue();
+ bool HasEmulation = false;
+ if (auto *Arg = Args.getLastArg(OPT_emulation)) {
+ applyEmulation(Arg->getValue());
+ HasEmulation = true;
+ }
+
Config->AllowMultipleDefinition = Args.hasArg(OPT_allow_multiple_definition);
Config->DiscardAll = Args.hasArg(OPT_discard_all);
Config->DiscardLocals = Args.hasArg(OPT_discard_locals);
@@ -134,7 +185,12 @@ void LinkerDriver::link(ArrayRef<const char *> ArgsArr) {
readLinkerScript(&Symtab, MB);
continue;
}
- Symtab.addFile(createFile(MB));
+ if (auto File = createTargetFile(MB))
+ Symtab.addFile(std::move(File));
+ else
+ error(Twine(MB.getBufferIdentifier() + " is incompatible with " +
+ (HasEmulation ? "target architecture"
+ : Symtab.getFirstELF()->getName())));
}
if (Symtab.getObjectFiles().empty())
@@ -155,5 +211,7 @@ void LinkerDriver::link(ArrayRef<const char *> ArgsArr) {
case ELF64BEKind:
writeResult<object::ELF64BE>(&Symtab);
return;
+ default:
+ llvm_unreachable("Invalid kind");
}
}
diff --git a/ELF/InputFiles.cpp b/ELF/InputFiles.cpp
index 93d6230..3b945c9 100644
--- a/ELF/InputFiles.cpp
+++ b/ELF/InputFiles.cpp
@@ -47,13 +47,9 @@ uint16_t ELFFileBase::getEMachine() const {
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 {
diff --git a/ELF/InputFiles.h b/ELF/InputFiles.h
index 1827cc7..1c34402 100644
--- a/ELF/InputFiles.h
+++ b/ELF/InputFiles.h
@@ -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"
@@ -51,8 +52,6 @@ private:
const Kind FileKind;
};
-enum ELFKind { ELF32LEKind, ELF32BEKind, ELF64LEKind, ELF64BEKind };
-
class ELFFileBase : public InputFile {
public:
ELFFileBase(Kind K, ELFKind EKind, MemoryBufferRef M)
@@ -62,7 +61,6 @@ public:
return K == ObjectKind || K == SharedKind;
}
- bool isCompatibleWith(const ELFFileBase &Other) const;
ELFKind getELFKind() const { return EKind; }
uint16_t getEMachine() const;
diff --git a/ELF/Options.td b/ELF/Options.td
index 377691e..83170ac 100644
--- a/ELF/Options.td
+++ b/ELF/Options.td
@@ -18,6 +18,9 @@ def discard_none : Flag<["-"], "discard-none">,
def dynamic_linker : Separate<["-"], "dynamic-linker">,
HelpText<"Which dynamic linker to use">;
+def emulation : Separate<["-"], "m">,
+ HelpText<"Set target emulation">;
+
def entry : Separate<["--", "-"], "entry">, MetaVarName<"<entry>">,
HelpText<"Name of entry point symbol">;
@@ -54,6 +57,5 @@ def as_needed : Flag<["--"], "as-needed">;
def build_id : Flag<["--"], "build-id">;
def eh_frame_hdr : Flag<["--"], "eh-frame-hdr">;
def hash_style : Joined<["--"], "hash-style=">;
-def m : Separate<["-"], "m">;
def no_as_needed : Flag<["--"], "no-as-needed">;
def z : Separate<["-"], "z">;
diff --git a/ELF/SymbolTable.cpp b/ELF/SymbolTable.cpp
index 43b068d..e895154 100644
--- a/ELF/SymbolTable.cpp
+++ b/ELF/SymbolTable.cpp
@@ -98,12 +98,8 @@ template <class ELFT> void SymbolTable::init(uint16_t EMachine) {
}
template <class ELFT> void SymbolTable::addELFFile(ELFFileBase *File) {
- if (const ELFFileBase *Old = getFirstELF()) {
- if (!Old->isCompatibleWith(*File))
- error(Twine(Old->getName() + " is incompatible with " + File->getName()));
- } else {
+ if (!getFirstELF())
init<ELFT>(File->getEMachine());
- }
if (auto *O = dyn_cast<ObjectFileBase>(File)) {
ObjectFiles.emplace_back(O);
@@ -132,6 +128,8 @@ void SymbolTable::addELFFile(ELFFileBase *File) {
case ELF64BEKind:
addELFFile<ELF64BE>(File);
break;
+ default:
+ llvm_unreachable("Invalid kind");
}
}
diff --git a/test/elf2/basic.s b/test/elf2/basic.s
index 1504251..a15f0cb 100644
--- a/test/elf2/basic.s
+++ b/test/elf2/basic.s
@@ -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
diff --git a/test/elf2/emulation.s b/test/elf2/emulation.s
new file mode 100644
index 0000000..5a91487
--- /dev/null
+++ b/test/elf2/emulation.s
@@ -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:
diff --git a/test/elf2/incompatible.s b/test/elf2/incompatible.s
index 46a8df1..995184b 100644
--- a/test/elf2/incompatible.s
+++ b/test/elf2/incompatible.s
@@ -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 target architecture
// REQUIRES: x86,arm
More information about the llvm-commits
mailing list