//===- ELFReader.h --------------------------------------------------------===// // // The MCLinker Project // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// #ifndef MCLD_ELF_READER_INTERFACE_H #define MCLD_ELF_READER_INTERFACE_H #ifdef ENABLE_UNITTEST #include <gtest.h> #endif #include <llvm/ADT/StringRef.h> #include <llvm/Support/ELF.h> #include <llvm/Support/Host.h> #include <mcld/MC/MCLDInfo.h> #include <mcld/MC/MCLDInput.h> #include <mcld/MC/MCLinker.h> #include <mcld/LD/Fragment.h> #include <mcld/LD/FillFragment.h> #include <mcld/LD/AlignFragment.h> #include <mcld/LD/RegionFragment.h> #include <mcld/LD/ResolveInfo.h> #include <mcld/LD/LDContext.h> #include <mcld/Target/GNULDBackend.h> #include <mcld/Support/MemoryRegion.h> #include <mcld/Support/MsgHandling.h> namespace mcld { /** \class ELFReaderIF * \brief ELFReaderIF provides common interface for all kind of ELF readers. */ class ELFReaderIF { public: ELFReaderIF(GNULDBackend& pBackend) : m_Backend(pBackend) { } virtual ~ELFReaderIF() { } /// ELFHeaderSize - return the size of the ELFHeader virtual size_t getELFHeaderSize() const = 0; /// isELF - is this a ELF file virtual bool isELF(void* pELFHeader) const = 0; /// isMyEndian - is this ELF file in the same endian to me? virtual bool isMyEndian(void* pELFHeader) const = 0; /// isMyMachine - is this ELF file generated for the same machine. virtual bool isMyMachine(void* pELFHeader) const = 0; /// fileType - the file type of this file virtual MCLDFile::Type fileType(void* pELFHeader) const = 0; /// target - the target backend GNULDBackend& target() { return m_Backend; } /// target - the target backend const GNULDBackend& target() const { return m_Backend; } /// readSectionHeaders - read ELF section header table and create LDSections virtual bool readSectionHeaders(Input& pInput, MCLinker& pLinker, void* pELFHeader) const = 0; /// readRegularSection - read a regular section and create fragments. virtual bool readRegularSection(Input& pInput, MCLinker& pLinker, LDSection& pSectHdr) const = 0; /// readRegularSection - read a target section and create fragments. virtual bool readTargetSection(Input& pInput, MCLinker& pLinker, LDSection& pSectHdr) = 0; /// readSymbols - read ELF symbols and create LDSymbol virtual bool readSymbols(Input& pInput, MCLinker& pLinker, const MemoryRegion& pRegion, const char* StrTab) const = 0; /// readSymbol - read a symbol from the given Input and index in symtab /// This is used to get the signature of a group section. virtual ResolveInfo* readSymbol(Input& pInput, LDSection& pSymTab, MCLDInfo& pLDInfo, uint32_t pSymIdx) const = 0; /// readRela - read ELF rela and create Relocation virtual bool readRela(Input& pInput, MCLinker& pLinker, LDSection& pSection, const MemoryRegion& pRegion) const = 0; /// readRel - read ELF rel and create Relocation virtual bool readRel(Input& pInput, MCLinker& pLinker, LDSection& pSection, const MemoryRegion& pRegion) const = 0; bool readEhFrame(Input& pInput, MCLinker& pLinker, LDSection& pSection) const; /// readDynamic - read ELF .dynamic in input dynobj virtual bool readDynamic(Input& pInput) const = 0; protected: /// LinkInfo - some section needs sh_link and sh_info, remember them. struct LinkInfo { LDSection* section; uint32_t sh_link; uint32_t sh_info; }; typedef std::vector<LinkInfo> LinkInfoList; protected: LDFileFormat::Kind getLDSectionKind(uint32_t pType, const char* pName) const; ResolveInfo::Type getSymType(uint8_t pInfo, uint16_t pShndx) const; ResolveInfo::Desc getSymDesc(uint16_t pShndx, const Input& pInput) const; ResolveInfo::Binding getSymBinding(uint8_t pBinding, uint16_t pShndx, uint8_t pVisibility) const; uint64_t getSymValue(uint64_t pValue, uint16_t pShndx, const Input& pInput) const; FragmentRef* getSymFragmentRef(Input& pInput, MCLinker& pLinker, uint16_t pShndx, uint32_t pOffset) const; ResolveInfo::Visibility getSymVisibility(uint8_t pVis) const; private: GNULDBackend& m_Backend; }; /** \class ELFReader * \brief ELFReader is a template scaffolding for partial specification. */ template<size_t BIT, bool LITTLEENDIAN> class ELFReader { }; /** \class ELFReader<32, true> * \brief ELFReader<32, true> is a 32-bit, little endian ELFReader. */ template<> class ELFReader<32, true> : public ELFReaderIF { public: typedef llvm::ELF::Elf32_Ehdr ELFHeader; typedef llvm::ELF::Elf32_Shdr SectionHeader; typedef llvm::ELF::Elf32_Sym Symbol; typedef llvm::ELF::Elf32_Rel Rel; typedef llvm::ELF::Elf32_Rela Rela; public: inline ELFReader(GNULDBackend& pBackend); inline ~ELFReader(); /// ELFHeaderSize - return the size of the ELFHeader inline size_t getELFHeaderSize() const { return sizeof(ELFHeader); } /// isELF - is this a ELF file inline bool isELF(void* pELFHeader) const; /// isMyEndian - is this ELF file in the same endian to me? inline bool isMyEndian(void* pELFHeader) const; /// isMyMachine - is this ELF file generated for the same machine. inline bool isMyMachine(void* pELFHeader) const; /// fileType - the file type of this file inline MCLDFile::Type fileType(void* pELFHeader) const; /// readSectionHeaders - read ELF section header table and create LDSections inline bool readSectionHeaders(Input& pInput, MCLinker& pLinker, void* pELFHeader) const; /// readRegularSection - read a regular section and create fragments. inline bool readRegularSection(Input& pInput, MCLinker& pLinker, LDSection& pInputSectHdr) const; /// readRegularSection - read a target section and create fragments. inline bool readTargetSection(Input& pInput, MCLinker& pLinker, LDSection& pInputSectHdr); /// readSymbols - read ELF symbols and create LDSymbol inline bool readSymbols(Input& pInput, MCLinker& pLinker, const MemoryRegion& pRegion, const char* StrTab) const; /// readSymbol - read a symbol from the given Input and index in symtab /// This is used to get the signature of a group section. inline ResolveInfo* readSymbol(Input& pInput, LDSection& pSymTab, MCLDInfo& pLDInfo, uint32_t pSymIdx) const; /// readRela - read ELF rela and create Relocation inline bool readRela(Input& pInput, MCLinker& pLinker, LDSection& pSection, const MemoryRegion& pRegion) const; /// readRel - read ELF rel and create Relocation inline bool readRel(Input& pInput, MCLinker& pLinker, LDSection& pSection, const MemoryRegion& pRegion) const; /// readDynamic - read ELF .dynamic in input dynobj inline bool readDynamic(Input& pInput) const; }; #include "ELFReader.tcc" } // namespace of mcld #endif