Add a non-templated ELFObjectFileBase class.

Use it to implement some ELF only virtual interfaces instead of using error
prone series of dyn_casts.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@215838 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Rafael Espindola 2014-08-17 17:52:10 +00:00
parent 4c511cd88f
commit db7cdc8eb0
2 changed files with 40 additions and 61 deletions

View File

@ -35,8 +35,21 @@
namespace llvm { namespace llvm {
namespace object { namespace object {
template <class ELFT> class ELFObjectFileBase : public ObjectFile {
class ELFObjectFile : public ObjectFile { protected:
ELFObjectFileBase(unsigned int Type, std::unique_ptr<MemoryBuffer> Source);
public:
virtual std::error_code getRelocationAddend(DataRefImpl Rel,
int64_t &Res) const = 0;
virtual std::pair<symbol_iterator, symbol_iterator>
getELFDynamicSymbolIterators() const = 0;
virtual std::error_code getSymbolVersion(SymbolRef Symb, StringRef &Version,
bool &IsDefault) const = 0;
};
template <class ELFT> class ELFObjectFile : public ELFObjectFileBase {
public: public:
LLVM_ELF_IMPORT_TYPES_ELFT(ELFT) LLVM_ELF_IMPORT_TYPES_ELFT(ELFT)
@ -186,9 +199,10 @@ public:
section_iterator section_begin() const override; section_iterator section_begin() const override;
section_iterator section_end() const override; section_iterator section_end() const override;
std::error_code getRelocationAddend(DataRefImpl Rel, int64_t &Res) const; std::error_code getRelocationAddend(DataRefImpl Rel,
int64_t &Res) const override;
std::error_code getSymbolVersion(SymbolRef Symb, StringRef &Version, std::error_code getSymbolVersion(SymbolRef Symb, StringRef &Version,
bool &IsDefault) const; bool &IsDefault) const override;
uint8_t getBytesInAddress() const override; uint8_t getBytesInAddress() const override;
StringRef getFileFormatName() const override; StringRef getFileFormatName() const override;
@ -207,6 +221,9 @@ public:
return v->getType() == getELFType(ELFT::TargetEndianness == support::little, return v->getType() == getELFType(ELFT::TargetEndianness == support::little,
ELFT::Is64Bits); ELFT::Is64Bits);
} }
std::pair<symbol_iterator, symbol_iterator>
getELFDynamicSymbolIterators() const override;
}; };
// Use an alignment of 2 for the typedefs since that is the worst case for // Use an alignment of 2 for the typedefs since that is the worst case for
@ -780,7 +797,8 @@ ELFObjectFile<ELFT>::getRela(DataRefImpl Rela) const {
template <class ELFT> template <class ELFT>
ELFObjectFile<ELFT>::ELFObjectFile(std::unique_ptr<MemoryBuffer> Object, ELFObjectFile<ELFT>::ELFObjectFile(std::unique_ptr<MemoryBuffer> Object,
std::error_code &EC) std::error_code &EC)
: ObjectFile(getELFType(static_cast<endianness>(ELFT::TargetEndianness) == : ELFObjectFileBase(
getELFType(static_cast<endianness>(ELFT::TargetEndianness) ==
support::little, support::little,
ELFT::Is64Bits), ELFT::Is64Bits),
std::move(Object)), std::move(Object)),
@ -921,73 +939,30 @@ unsigned ELFObjectFile<ELFT>::getArch() const {
} }
} }
/// FIXME: Maybe we should have a base ElfObjectFile that is not a template template <class ELFT>
/// and make these member functions? std::pair<symbol_iterator, symbol_iterator>
ELFObjectFile<ELFT>::getELFDynamicSymbolIterators() const {
return std::make_pair(dynamic_symbol_begin(), dynamic_symbol_end());
}
inline std::error_code getELFRelocationAddend(const RelocationRef R, inline std::error_code getELFRelocationAddend(const RelocationRef R,
int64_t &Addend) { int64_t &Addend) {
const ObjectFile *Obj = R.getObjectFile(); const ObjectFile *Obj = R.getObjectFile();
DataRefImpl DRI = R.getRawDataRefImpl(); DataRefImpl DRI = R.getRawDataRefImpl();
// Little-endian 32-bit return cast<ELFObjectFileBase>(Obj)->getRelocationAddend(DRI, Addend);
if (const ELF32LEObjectFile *ELFObj = dyn_cast<ELF32LEObjectFile>(Obj))
return ELFObj->getRelocationAddend(DRI, Addend);
// Big-endian 32-bit
if (const ELF32BEObjectFile *ELFObj = dyn_cast<ELF32BEObjectFile>(Obj))
return ELFObj->getRelocationAddend(DRI, Addend);
// Little-endian 64-bit
if (const ELF64LEObjectFile *ELFObj = dyn_cast<ELF64LEObjectFile>(Obj))
return ELFObj->getRelocationAddend(DRI, Addend);
// Big-endian 64-bit
if (const ELF64BEObjectFile *ELFObj = dyn_cast<ELF64BEObjectFile>(Obj))
return ELFObj->getRelocationAddend(DRI, Addend);
llvm_unreachable("Object passed to getELFRelocationAddend() is not ELF");
} }
inline std::pair<symbol_iterator, symbol_iterator> inline std::pair<symbol_iterator, symbol_iterator>
getELFDynamicSymbolIterators(SymbolicFile *Obj) { getELFDynamicSymbolIterators(SymbolicFile *Obj) {
if (const ELF32LEObjectFile *ELF = dyn_cast<ELF32LEObjectFile>(Obj)) return cast<ELFObjectFileBase>(Obj)->getELFDynamicSymbolIterators();
return std::make_pair(ELF->dynamic_symbol_begin(),
ELF->dynamic_symbol_end());
if (const ELF64LEObjectFile *ELF = dyn_cast<ELF64LEObjectFile>(Obj))
return std::make_pair(ELF->dynamic_symbol_begin(),
ELF->dynamic_symbol_end());
if (const ELF32BEObjectFile *ELF = dyn_cast<ELF32BEObjectFile>(Obj))
return std::make_pair(ELF->dynamic_symbol_begin(),
ELF->dynamic_symbol_end());
if (const ELF64BEObjectFile *ELF = cast<ELF64BEObjectFile>(Obj))
return std::make_pair(ELF->dynamic_symbol_begin(),
ELF->dynamic_symbol_end());
llvm_unreachable(
"Object passed to getELFDynamicSymbolIterators() is not ELF");
} }
/// This is a generic interface for retrieving GNU symbol version
/// information from an ELFObjectFile.
inline std::error_code GetELFSymbolVersion(const ObjectFile *Obj, inline std::error_code GetELFSymbolVersion(const ObjectFile *Obj,
const SymbolRef &Sym, const SymbolRef &Sym,
StringRef &Version, StringRef &Version,
bool &IsDefault) { bool &IsDefault) {
// Little-endian 32-bit return cast<ELFObjectFileBase>(Obj)
if (const ELF32LEObjectFile *ELFObj = dyn_cast<ELF32LEObjectFile>(Obj)) ->getSymbolVersion(Sym, Version, IsDefault);
return ELFObj->getSymbolVersion(Sym, Version, IsDefault);
// Big-endian 32-bit
if (const ELF32BEObjectFile *ELFObj = dyn_cast<ELF32BEObjectFile>(Obj))
return ELFObj->getSymbolVersion(Sym, Version, IsDefault);
// Little-endian 64-bit
if (const ELF64LEObjectFile *ELFObj = dyn_cast<ELF64LEObjectFile>(Obj))
return ELFObj->getSymbolVersion(Sym, Version, IsDefault);
// Big-endian 64-bit
if (const ELF64BEObjectFile *ELFObj = dyn_cast<ELF64BEObjectFile>(Obj))
return ELFObj->getSymbolVersion(Sym, Version, IsDefault);
llvm_unreachable("Object passed to GetELFSymbolVersion() is not ELF");
} }
} }
} }

View File

@ -17,6 +17,10 @@
namespace llvm { namespace llvm {
using namespace object; using namespace object;
ELFObjectFileBase::ELFObjectFileBase(unsigned int Type,
std::unique_ptr<MemoryBuffer> Source)
: ObjectFile(Type, std::move(Source)) {}
ErrorOr<std::unique_ptr<ObjectFile>> ErrorOr<std::unique_ptr<ObjectFile>>
ObjectFile::createELFObjectFile(std::unique_ptr<MemoryBuffer> &Obj) { ObjectFile::createELFObjectFile(std::unique_ptr<MemoryBuffer> &Obj) {
std::pair<unsigned char, unsigned char> Ident = std::pair<unsigned char, unsigned char> Ident =