ELF: Remove ELFT and LinkingContext template parameters from ELFReader.

Previously, ELFReader takes three template arguments: EFLT,
LinkingContextT and FileT. FileT is itself templated.
So it was a bit complicated. Maybe too much.

Most architectures don't actually need to be parameterized for ELFT.
For example, x86 is always ELF32LE and x86-64 is ELF64LE.
However, because ELFReader requires a ELFT argument, we needed
to parameterize a class even if not needed.

This patch removes the parameter from the class. So now we can
de-templatize such classes (I didn't do that in this patch, though).

This patch also removes ContextT parameter since it didn't have to be
passed as a template argument.

llvm-svn: 234853
This commit is contained in:
Rui Ueyama 2015-04-14 04:53:57 +00:00
parent acdee690c8
commit 7bda84d25e
27 changed files with 165 additions and 70 deletions

View File

@ -106,6 +106,7 @@ public:
uint16_t getOutputELFType() const { return _outputELFType; }
uint16_t getOutputMachine() const;
bool mergeCommonStrings() const { return _mergeCommonStrings; }
virtual int getMachineType() const = 0;
virtual uint64_t getBaseAddress() const { return _baseAddress; }
virtual void setBaseAddress(uint64_t address) { _baseAddress = address; }

View File

@ -24,7 +24,7 @@ enum {
class AArch64LinkingContext final : public ELFLinkingContext {
public:
static const int machine = llvm::ELF::EM_AARCH64;
int getMachineType() const override { return llvm::ELF::EM_AARCH64; }
AArch64LinkingContext(llvm::Triple);
void addPasses(PassManager &) override;

View File

@ -20,8 +20,8 @@ namespace elf {
class AArch64LinkingContext;
class AArch64TargetHandler final : public TargetHandler {
typedef ELFReader<ELF64LE, AArch64LinkingContext, ELFFile> ObjReader;
typedef ELFReader<ELF64LE, AArch64LinkingContext, DynamicFile> DSOReader;
typedef ELFReader<ELFFile<ELF64LE>> ObjReader;
typedef ELFReader<DynamicFile<ELF64LE>> DSOReader;
public:
AArch64TargetHandler(AArch64LinkingContext &ctx);

View File

@ -55,7 +55,7 @@ template <class ELFT> class ARMELFFile : public ELFFile<ELFT> {
typedef llvm::object::Elf_Rel_Impl<ELFT, false> Elf_Rel;
public:
ARMELFFile(std::unique_ptr<MemoryBuffer> mb, ARMLinkingContext &ctx)
ARMELFFile(std::unique_ptr<MemoryBuffer> mb, ELFLinkingContext &ctx)
: ELFFile<ELFT>(std::move(mb), ctx) {}
protected:

View File

@ -19,7 +19,7 @@ namespace elf {
class ARMLinkingContext final : public ELFLinkingContext {
public:
static const int machine = llvm::ELF::EM_ARM;
int getMachineType() const override { return llvm::ELF::EM_ARM; }
ARMLinkingContext(llvm::Triple);
void addPasses(PassManager &) override;

View File

@ -59,8 +59,8 @@ private:
};
class ARMTargetHandler final : public TargetHandler {
typedef ELFReader<ELF32LE, ARMLinkingContext, ARMELFFile> ObjReader;
typedef ELFReader<ELF32LE, ARMLinkingContext, DynamicFile> DSOReader;
typedef ELFReader<ARMELFFile<ELF32LE>> ObjReader;
typedef ELFReader<DynamicFile<ELF32LE>> DSOReader;
public:
ARMTargetHandler(ARMLinkingContext &ctx);

View File

@ -2,6 +2,7 @@ add_llvm_library(lldELF
DynamicFile.cpp
ELFFile.cpp
ELFLinkingContext.cpp
FileCommon.cpp
Reader.cpp
Writer.cpp
LINK_LIBS

View File

@ -8,6 +8,7 @@
//===----------------------------------------------------------------------===//
#include "DynamicFile.h"
#include "FileCommon.h"
#include "lld/ReaderWriter/ELFLinkingContext.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/Object/ELF.h"
@ -29,6 +30,12 @@ DynamicFile<ELFT>::DynamicFile(std::unique_ptr<MemoryBuffer> mb,
: SharedLibraryFile(mb->getBufferIdentifier()), _mb(std::move(mb)),
_ctx(ctx), _useShlibUndefines(ctx.useShlibUndefines()) {}
template <typename ELFT>
std::error_code DynamicFile<ELFT>::isCompatible(const MemoryBuffer &mb,
ELFLinkingContext &ctx) {
return lld::elf::isCompatible<ELFT>(mb, ctx);
}
template <class ELFT>
const SharedLibraryAtom *DynamicFile<ELFT>::exports(StringRef name,
bool dataSymbolOnly) const {

View File

@ -26,6 +26,9 @@ public:
DynamicFile(std::unique_ptr<MemoryBuffer> mb, ELFLinkingContext &ctx);
static std::error_code isCompatible(const MemoryBuffer &mb,
ELFLinkingContext &ctx);
const SharedLibraryAtom *exports(StringRef name,
bool dataSymbolOnly) const override;

View File

@ -8,6 +8,7 @@
//===----------------------------------------------------------------------===//
#include "ELFFile.h"
#include "FileCommon.h"
#include "llvm/ADT/STLExtras.h"
namespace lld {
@ -26,6 +27,12 @@ ELFFile<ELFT>::ELFFile(std::unique_ptr<MemoryBuffer> mb, ELFLinkingContext &ctx)
_doStringsMerge(ctx.mergeCommonStrings()),
_useWrap(ctx.wrapCalls().size()), _ctx(ctx) {}
template <typename ELFT>
std::error_code ELFFile<ELFT>::isCompatible(const MemoryBuffer &mb,
ELFLinkingContext &ctx) {
return lld::elf::isCompatible<ELFT>(mb, ctx);
}
template <typename ELFT>
Atom *ELFFile<ELFT>::findAtom(const Elf_Sym *sourceSym,
const Elf_Sym *targetSym) {

View File

@ -11,6 +11,7 @@
#define LLD_READER_WRITER_ELF_FILE_H
#include "Atoms.h"
#include "FileCommon.h"
#include "llvm/ADT/MapVector.h"
#include <map>
#include <unordered_map>
@ -89,6 +90,9 @@ public:
ELFFile(StringRef name, ELFLinkingContext &ctx);
ELFFile(std::unique_ptr<MemoryBuffer> mb, ELFLinkingContext &ctx);
static std::error_code isCompatible(const MemoryBuffer &mb,
ELFLinkingContext &ctx);
static bool canParse(file_magic magic) {
return magic == file_magic::elf_relocatable;
}
@ -334,6 +338,8 @@ protected:
return nullptr;
}
static bool isCompatible(unsigned char size, unsigned char endian);
llvm::BumpPtrAllocator _readerStorage;
std::unique_ptr<llvm::object::ELFFile<ELFT> > _objFile;

View File

@ -20,60 +20,25 @@
namespace lld {
namespace elf {
template <typename ELFT, typename ContextT, template <typename> class FileT>
class ELFReader : public Reader {
template <typename FileT> class ELFReader : public Reader {
public:
typedef llvm::object::Elf_Ehdr_Impl<ELFT> Elf_Ehdr;
ELFReader(ContextT &ctx) : _ctx(ctx) {}
ELFReader(ELFLinkingContext &ctx) : _ctx(ctx) {}
bool canParse(file_magic magic, const MemoryBuffer &mb) const override {
return (FileT<ELFT>::canParse(magic) &&
elfHeader(mb)->e_machine == ContextT::machine);
return FileT::canParse(magic);
}
std::error_code
loadFile(std::unique_ptr<MemoryBuffer> mb, const class Registry &,
std::vector<std::unique_ptr<File>> &result) const override {
const Elf_Ehdr *hdr = elfHeader(*mb);
if (auto ec = _ctx.mergeHeaderFlags(hdr->getFileClass(), hdr->e_flags))
if (std::error_code ec = FileT::isCompatible(*mb, _ctx))
return ec;
result.push_back(createELF(std::move(mb)));
result.push_back(llvm::make_unique<FileT>(std::move(mb), _ctx));
return std::error_code();
}
private:
/// Create an object depending on the runtime attributes and alignment
/// of an ELF file.
std::unique_ptr<File> createELF(std::unique_ptr<MemoryBuffer> mb) const {
using namespace llvm::ELF;
using namespace llvm::support;
if (uintptr_t(mb->getBufferStart()) & 1)
llvm_unreachable("Invalid alignment for ELF file!");
unsigned char size;
unsigned char endian;
std::tie(size, endian) = llvm::object::getElfArchType(mb->getBuffer());
File *file = nullptr;
if (size == ELFCLASS32 && endian == ELFDATA2LSB) {
file = new FileT<ELF32LE>(std::move(mb), _ctx);
} else if (size == ELFCLASS32 && endian == ELFDATA2MSB) {
file = new FileT<ELF32BE>(std::move(mb), _ctx);
} else if (size == ELFCLASS64 && endian == ELFDATA2LSB) {
file = new FileT<ELF64LE>(std::move(mb), _ctx);
} else if (size == ELFCLASS64 && endian == ELFDATA2MSB) {
file = new FileT<ELF64BE>(std::move(mb), _ctx);
}
if (!file)
llvm_unreachable("Invalid ELF type!");
return std::unique_ptr<File>(file);
}
static const Elf_Ehdr *elfHeader(const MemoryBuffer &buf) {
return reinterpret_cast<const Elf_Ehdr *>(buf.getBuffer().data());
}
ContextT &_ctx;
ELFLinkingContext &_ctx;
};
} // namespace elf

View File

@ -0,0 +1,63 @@
//===- lib/ReaderWriter/ELF/FileCommon.cpp --------------------------------===//
//
// The LLVM Linker
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#include "ELFFile.h"
#include "FileCommon.h"
using namespace llvm::ELF;
namespace lld {
namespace elf {
template <>
std::error_code checkCompatibility<ELF32LE>(unsigned char size,
unsigned char endian) {
if (size == ELFCLASS64)
return make_dynamic_error_code("ELF32 expected, but got ELF64");
if (endian == ELFDATA2MSB)
return make_dynamic_error_code(
"Little endian files are expected, but got a big endian file.");
return std::error_code();
}
template <>
std::error_code checkCompatibility<ELF32BE>(unsigned char size,
unsigned char endian) {
if (size == ELFCLASS64)
return make_dynamic_error_code("ELF32 expected, but got ELF64");
if (endian == ELFDATA2LSB)
return make_dynamic_error_code(
"Big endian files are expected, but got a little endian file.");
return std::error_code();
}
template <>
std::error_code checkCompatibility<ELF64LE>(unsigned char size,
unsigned char endian) {
if (size == ELFCLASS32)
return make_dynamic_error_code("ELF64 expected, but got ELF32");
if (endian == ELFDATA2MSB)
return make_dynamic_error_code(
"Little endian files are expected, but got a big endian file.");
return std::error_code();
}
template <>
std::error_code checkCompatibility<ELF64BE>(unsigned char size,
unsigned char endian) {
if (size == ELFCLASS32)
return make_dynamic_error_code("ELF64 expected, but got ELF32");
if (endian == ELFDATA2LSB)
return make_dynamic_error_code(
"Big endian files are expected, but got a little endian file.");
return std::error_code();
}
} // end namespace elf
} // end namespace lld

View File

@ -0,0 +1,48 @@
//===- lib/ReaderWriter/ELF/FileCommon.h ----------------------------------===//
//
// The LLVM Linker
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#ifndef LLD_READER_WRITER_ELF_FILE_COMMON_H
#define LLD_READER_WRITER_ELF_FILE_COMMON_H
#include "lld/ReaderWriter/ELFLinkingContext.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/ELF.h"
namespace lld {
namespace elf {
template <class ELFT>
std::error_code checkCompatibility(unsigned char size, unsigned char endian);
template <typename ELFT>
std::error_code isCompatible(const MemoryBuffer &mb, ELFLinkingContext &ctx) {
typedef llvm::object::Elf_Ehdr_Impl<ELFT> Elf_Ehdr;
if (uintptr_t(mb.getBufferStart()) & 1)
return make_dynamic_error_code("invalid alignment");
auto *hdr = reinterpret_cast<const Elf_Ehdr *>(mb.getBuffer().data());
if (hdr->e_machine != ctx.getMachineType())
return make_dynamic_error_code("incompatible machine type");
unsigned char size;
unsigned char endian;
std::tie(size, endian) = llvm::object::getElfArchType(mb.getBuffer());
if (std::error_code ec = checkCompatibility<ELFT>(size, endian))
return ec;
if (auto ec = ctx.mergeHeaderFlags(hdr->getFileClass(), hdr->e_flags))
return ec;
return std::error_code();
}
} // end namespace elf
} // end namespace lld
#endif

View File

@ -108,7 +108,7 @@ template <class ELFT> class HexagonELFFile : public ELFFile<ELFT> {
typedef llvm::object::Elf_Shdr_Impl<ELFT> Elf_Shdr;
public:
HexagonELFFile(std::unique_ptr<MemoryBuffer> mb, HexagonLinkingContext &ctx)
HexagonELFFile(std::unique_ptr<MemoryBuffer> mb, ELFLinkingContext &ctx)
: ELFFile<ELFT>(std::move(mb), ctx) {}
bool isCommonSymbol(const Elf_Sym *symbol) const override {

View File

@ -20,7 +20,7 @@ namespace elf {
class HexagonLinkingContext final : public ELFLinkingContext {
public:
static const int machine = llvm::ELF::EM_HEXAGON;
int getMachineType() const override { return llvm::ELF::EM_HEXAGON; }
HexagonLinkingContext(llvm::Triple triple);
void addPasses(PassManager &) override;

View File

@ -109,8 +109,8 @@ private:
/// \brief TargetHandler for Hexagon
class HexagonTargetHandler final : public TargetHandler {
typedef ELFReader<ELF32LE, HexagonLinkingContext, HexagonELFFile> ObjReader;
typedef ELFReader<ELF32LE, HexagonLinkingContext, DynamicFile> ELFDSOReader;
typedef ELFReader<HexagonELFFile<ELF32LE>> ObjReader;
typedef ELFReader<DynamicFile<ELF32LE>> ELFDSOReader;
public:
HexagonTargetHandler(HexagonLinkingContext &targetInfo);

View File

@ -88,7 +88,7 @@ private:
template <class ELFT> class MipsELFFile : public ELFFile<ELFT> {
public:
MipsELFFile(std::unique_ptr<MemoryBuffer> mb, MipsLinkingContext &ctx)
MipsELFFile(std::unique_ptr<MemoryBuffer> mb, ELFLinkingContext &ctx)
: ELFFile<ELFT>(std::move(mb), ctx) {}
bool isPIC() const {

View File

@ -66,11 +66,6 @@ uint32_t MipsELFFlagsMerger::getMergedELFFlags() const { return _flags; }
std::error_code MipsELFFlagsMerger::mergeHeaderFlags(uint8_t newClass,
uint32_t newFlags) {
// Check bitness.
if (_is64Bit != (newClass == ELFCLASS64))
return make_dynamic_error_code(
"Bitness is incompatible with that of the selected target");
// We support two ABI: O32 and N64. The last one does not have
// the corresponding ELF flag.
uint32_t inAbi = newFlags & EF_MIPS_ABI;

View File

@ -39,7 +39,7 @@ enum {
class MipsLinkingContext final : public ELFLinkingContext {
public:
static const int machine = llvm::ELF::EM_MIPS;
int getMachineType() const override { return llvm::ELF::EM_MIPS; }
MipsLinkingContext(llvm::Triple triple);
std::error_code mergeHeaderFlags(uint8_t fileClass, uint64_t flags) override;

View File

@ -22,8 +22,8 @@ namespace elf {
/// \brief TargetHandler for Mips
template <class ELFT> class MipsTargetHandler final : public TargetHandler {
typedef ELFReader<ELFT, MipsLinkingContext, MipsELFFile> ObjReader;
typedef ELFReader<ELFT, MipsLinkingContext, DynamicFile> DSOReader;
typedef ELFReader<MipsELFFile<ELFT>> ObjReader;
typedef ELFReader<DynamicFile<ELFT>> DSOReader;
public:
MipsTargetHandler(MipsLinkingContext &ctx)

View File

@ -19,7 +19,7 @@ namespace elf {
class X86LinkingContext final : public ELFLinkingContext {
public:
static std::unique_ptr<ELFLinkingContext> create(llvm::Triple);
static const int machine = llvm::ELF::EM_386;
int getMachineType() const override { return llvm::ELF::EM_386; }
X86LinkingContext(llvm::Triple);
void registerRelocationNames(Registry &r) override;

View File

@ -20,8 +20,8 @@ namespace elf {
class X86LinkingContext;
class X86TargetHandler final : public TargetHandler {
typedef ELFReader<ELF32LE, X86LinkingContext, ELFFile> ObjReader;
typedef ELFReader<ELF32LE, X86LinkingContext, DynamicFile> DSOReader;
typedef ELFReader<ELFFile<ELF32LE>> ObjReader;
typedef ELFReader<DynamicFile<ELF32LE>> DSOReader;
public:
X86TargetHandler(X86LinkingContext &ctx);

View File

@ -30,7 +30,7 @@ protected:
public:
static std::unique_ptr<ELFLinkingContext> create(llvm::Triple);
static const int machine = llvm::ELF::EM_X86_64;
int getMachineType() const override { return llvm::ELF::EM_X86_64; }
X86_64LinkingContext(llvm::Triple);
void addPasses(PassManager &) override;

View File

@ -58,9 +58,8 @@ private:
};
class X86_64TargetHandler : public TargetHandler {
typedef llvm::object::ELFType<llvm::support::little, 2, true> ELFT;
typedef ELFReader<ELFT, X86_64LinkingContext, ELFFile> ObjReader;
typedef ELFReader<ELFT, X86_64LinkingContext, DynamicFile> DSOReader;
typedef ELFReader<ELFFile<ELF64LE>> ObjReader;
typedef ELFReader<DynamicFile<ELF64LE>> DSOReader;
public:
X86_64TargetHandler(X86_64LinkingContext &ctx);

View File

@ -6,7 +6,7 @@
# RUN: not lld -flavor gnu -target mips64el -shared -o %t.so \
# RUN: %t-32.o %t-64.o 2>&1 | FileCheck %s
# CHECK: Bitness is incompatible with that of the selected target
# CHECK: ELF64 expected, but got ELF32
# 32.o
---

View File

@ -6,7 +6,7 @@
# RUN: not lld -flavor gnu -target mipsel -shared -o %t.so \
# RUN: %t-32.o %t-64.o 2>&1 | FileCheck %s
# CHECK: Bitness is incompatible with that of the selected target
# CHECK: ELF32 expected, but got ELF64
# 32.o
---