/* * File: StELFFile.h * * Copyright (c) Freescale Semiconductor, Inc. All rights reserved. * See included license file for license details. */ #if !defined(_StELFFile_h_) #define _StELFFile_h_ #include "stdafx.h" #include #include #include #include #include #include "ELF.h" //! Variations of the ARM ELF format. typedef enum { eARMVariant = 1, //!< Standard ARM ELF specification. eGHSVariant, //!< Green Hills Software variant. eGCCVariant //!< GNU Compiler Collection variant. } ELFVariant_t; //! Possible ARM ELF symbol types. typedef enum { eUnknownSymbol, eARMSymbol, eThumbSymbol, eDataSymbol } ARMSymbolType_t; /*! * \brief Parser for Executable and Linking Format (ELF) files. * * The stream passed into the constructor needs to stay open for the life * of the object. This is because calls to getSectionDataAtIndex() and * getSegmentDataAtIndex() read the data directly from the input stream. */ class StELFFile { public: typedef std::vector::const_iterator const_section_iterator; typedef std::vector::const_iterator const_segment_iterator; public: //! \brief Constructor. StELFFile(std::istream & inStream); //! \brief Destructor. virtual ~StELFFile(); //! \name File format variant //@{ //! \brief Return the ELF format variant to which this file is set. virtual ELFVariant_t ELFVariant() { return m_elfVariant; } //! \brief Set the ELF format variation to either #eARMVariant or #eGHSVariant. virtual void setELFVariant(ELFVariant_t variant) { m_elfVariant = variant; } //@} //! \name File name //@{ virtual void setName(const std::string & inName) { m_name = inName; } virtual std::string getName() const { return m_name; } //@} //! \name ELF header //@{ //! \brief Returns the ELF file header. inline const Elf32_Ehdr & getFileHeader() const { return m_header; } //@} //! \name Sections //! Methods pertaining to the object file's sections. //@{ //! \brief Returns the number of sections in the file. inline unsigned getSectionCount() const { return static_cast(m_sectionHeaders.size()); } //! \brief Returns a reference to section number \a inIndex. const Elf32_Shdr & getSectionAtIndex(unsigned inIndex) const; inline const_section_iterator getSectionBegin() const { return m_sectionHeaders.begin(); } inline const_section_iterator getSectionEnd() const { return m_sectionHeaders.end(); } //! \brief Returns the index of the section with the name \a inName. unsigned getIndexOfSectionWithName(const std::string & inName); //! \brief Returns the data for the section. uint8_t * getSectionDataAtIndex(unsigned inIndex); //! \brief Returns the data for the section. uint8_t * getSectionData(const_section_iterator inSection); //@} //! \name Segments //! Methods for accessing the file's program headers for segments. //@{ //! \brief Returns the number of segments, or program headers, in the file. inline unsigned getSegmentCount() const { return static_cast(m_programHeaders.size()); } //! \brief Returns a reference to the given segment. const Elf32_Phdr & getSegmentAtIndex(unsigned inIndex) const; inline const_segment_iterator getSegmentBegin() const { return m_programHeaders.begin(); } inline const_segment_iterator getSegmentEnd() const { return m_programHeaders.end(); } //! \brief Returns the data of the specified segment. uint8_t * getSegmentDataAtIndex(unsigned inIndex); //! \brief Returns the data of the specified segment. uint8_t * getSegmentData(const_segment_iterator inSegment); //@} //! \name String table //! Methods for accessing the string tables. //@{ //! \brief Returns a string from the file's section name string table. std::string getSectionNameAtIndex(unsigned inIndex); //! \brief Returns a string from any string table in the object file. std::string getStringAtIndex(unsigned inStringTableSectionIndex, unsigned inStringIndex); //@} //! \name Symbol table //! Methods for accessing the object file's symbol table. Currently only //! a single symbol table with the section name ".symtab" is supported. //@{ //! \brief Returns the number of symbols in the default ".symtab" symbol table. unsigned getSymbolCount(); //! \brief Returns the symbol with index \a inIndex. const Elf32_Sym & getSymbolAtIndex(unsigned inIndex); //! \brief Returns the section index of the string table containing symbol names. unsigned getSymbolNameStringTableIndex() const; //! \brief Returns the name of the symbol described by \a inSymbol. std::string getSymbolName(const Elf32_Sym & inSymbol); unsigned getIndexOfSymbolAtAddress(uint32_t symbolAddress, bool strict=true); ARMSymbolType_t getTypeOfSymbolAtIndex(unsigned symbolIndex); //@} //! \name Debugging //@{ void dumpSections(); void dumpSymbolTable(); //@} protected: std::istream & m_stream; //!< The source stream for the ELF file. ELFVariant_t m_elfVariant; //!< Variant of the ARM ELF format specification. std::string m_name; //!< File name. (optional) Elf32_Ehdr m_header; //!< The ELF file header. std::vector m_sectionHeaders; //!< All of the section headers. std::vector m_programHeaders; //!< All of the program headers. unsigned m_symbolTableIndex; //!< Index of ".symtab" section, or #SHN_UNDEF if not present. /*! * Little structure containing information about cached section data. */ struct SectionDataInfo { uint8_t * m_data; //!< Pointer to section data. unsigned m_size; //!< Section data size in bytes. bool m_swapped; //!< Has this section been byte swapped yet? Used for symbol table. }; typedef std::map SectionDataMap; SectionDataMap m_sectionDataCache; //!< Cached data of sections. //! \brief Reads a section's data either from cache or from disk. SectionDataInfo & getCachedSectionData(unsigned inSectionIndex); //! \brief Reads the file, section, and program headers into memory. void readFileHeaders(); uint8_t * readSectionData(const Elf32_Shdr & inHeader); uint8_t * readSegmentData(const Elf32_Phdr & inHeader); //! \brief Byte swaps the symbol table data into host endianness. void byteSwapSymbolTable(const Elf32_Shdr & header, SectionDataInfo & info); }; /*! * \brief Simple exception thrown to indicate an error in the input ELF file format. */ class StELFFileException : public std::runtime_error { public: //! \brief Default constructor. StELFFileException(const std::string & inMessage) : std::runtime_error(inMessage) {} }; #endif // _StELFFile_h_