1 /* 2 * File: StELFFile.h 3 * 4 * Copyright (c) Freescale Semiconductor, Inc. All rights reserved. 5 * See included license file for license details. 6 */ 7 #if !defined(_StELFFile_h_) 8 #define _StELFFile_h_ 9 10 #include "stdafx.h" 11 #include <string> 12 #include <vector> 13 #include <map> 14 #include <iostream> 15 #include <stdexcept> 16 #include "ELF.h" 17 18 //! Variations of the ARM ELF format. 19 typedef enum { 20 eARMVariant = 1, //!< Standard ARM ELF specification. 21 eGHSVariant, //!< Green Hills Software variant. 22 eGCCVariant //!< GNU Compiler Collection variant. 23 } ELFVariant_t; 24 25 //! Possible ARM ELF symbol types. 26 typedef enum { 27 eUnknownSymbol, 28 eARMSymbol, 29 eThumbSymbol, 30 eDataSymbol 31 } ARMSymbolType_t; 32 33 /*! 34 * \brief Parser for Executable and Linking Format (ELF) files. 35 * 36 * The stream passed into the constructor needs to stay open for the life 37 * of the object. This is because calls to getSectionDataAtIndex() and 38 * getSegmentDataAtIndex() read the data directly from the input stream. 39 */ 40 class StELFFile 41 { 42 public: 43 typedef std::vector<Elf32_Shdr>::const_iterator const_section_iterator; 44 typedef std::vector<Elf32_Phdr>::const_iterator const_segment_iterator; 45 46 public: 47 //! \brief Constructor. 48 StELFFile(std::istream & inStream); 49 50 //! \brief Destructor. 51 virtual ~StELFFile(); 52 53 //! \name File format variant 54 //@{ 55 //! \brief Return the ELF format variant to which this file is set. ELFVariant()56 virtual ELFVariant_t ELFVariant() { return m_elfVariant; } 57 58 //! \brief Set the ELF format variation to either #eARMVariant or #eGHSVariant. setELFVariant(ELFVariant_t variant)59 virtual void setELFVariant(ELFVariant_t variant) { m_elfVariant = variant; } 60 //@} 61 62 //! \name File name 63 //@{ setName(const std::string & inName)64 virtual void setName(const std::string & inName) { m_name = inName; } getName()65 virtual std::string getName() const { return m_name; } 66 //@} 67 68 //! \name ELF header 69 //@{ 70 //! \brief Returns the ELF file header. getFileHeader()71 inline const Elf32_Ehdr & getFileHeader() const { return m_header; } 72 //@} 73 74 //! \name Sections 75 //! Methods pertaining to the object file's sections. 76 //@{ 77 //! \brief Returns the number of sections in the file. getSectionCount()78 inline unsigned getSectionCount() const { return static_cast<unsigned>(m_sectionHeaders.size()); } 79 80 //! \brief Returns a reference to section number \a inIndex. 81 const Elf32_Shdr & getSectionAtIndex(unsigned inIndex) const; 82 getSectionBegin()83 inline const_section_iterator getSectionBegin() const { return m_sectionHeaders.begin(); } getSectionEnd()84 inline const_section_iterator getSectionEnd() const { return m_sectionHeaders.end(); } 85 86 //! \brief Returns the index of the section with the name \a inName. 87 unsigned getIndexOfSectionWithName(const std::string & inName); 88 89 //! \brief Returns the data for the section. 90 uint8_t * getSectionDataAtIndex(unsigned inIndex); 91 92 //! \brief Returns the data for the section. 93 uint8_t * getSectionData(const_section_iterator inSection); 94 //@} 95 96 //! \name Segments 97 //! Methods for accessing the file's program headers for segments. 98 //@{ 99 //! \brief Returns the number of segments, or program headers, in the file. getSegmentCount()100 inline unsigned getSegmentCount() const { return static_cast<unsigned>(m_programHeaders.size()); } 101 102 //! \brief Returns a reference to the given segment. 103 const Elf32_Phdr & getSegmentAtIndex(unsigned inIndex) const; 104 getSegmentBegin()105 inline const_segment_iterator getSegmentBegin() const { return m_programHeaders.begin(); } getSegmentEnd()106 inline const_segment_iterator getSegmentEnd() const { return m_programHeaders.end(); } 107 108 //! \brief Returns the data of the specified segment. 109 uint8_t * getSegmentDataAtIndex(unsigned inIndex); 110 111 //! \brief Returns the data of the specified segment. 112 uint8_t * getSegmentData(const_segment_iterator inSegment); 113 //@} 114 115 //! \name String table 116 //! Methods for accessing the string tables. 117 //@{ 118 //! \brief Returns a string from the file's section name string table. 119 std::string getSectionNameAtIndex(unsigned inIndex); 120 121 //! \brief Returns a string from any string table in the object file. 122 std::string getStringAtIndex(unsigned inStringTableSectionIndex, unsigned inStringIndex); 123 //@} 124 125 //! \name Symbol table 126 //! Methods for accessing the object file's symbol table. Currently only 127 //! a single symbol table with the section name ".symtab" is supported. 128 //@{ 129 //! \brief Returns the number of symbols in the default ".symtab" symbol table. 130 unsigned getSymbolCount(); 131 132 //! \brief Returns the symbol with index \a inIndex. 133 const Elf32_Sym & getSymbolAtIndex(unsigned inIndex); 134 135 //! \brief Returns the section index of the string table containing symbol names. 136 unsigned getSymbolNameStringTableIndex() const; 137 138 //! \brief Returns the name of the symbol described by \a inSymbol. 139 std::string getSymbolName(const Elf32_Sym & inSymbol); 140 141 unsigned getIndexOfSymbolAtAddress(uint32_t symbolAddress, bool strict=true); 142 143 ARMSymbolType_t getTypeOfSymbolAtIndex(unsigned symbolIndex); 144 //@} 145 146 //! \name Debugging 147 //@{ 148 void dumpSections(); 149 void dumpSymbolTable(); 150 //@} 151 152 protected: 153 std::istream & m_stream; //!< The source stream for the ELF file. 154 ELFVariant_t m_elfVariant; //!< Variant of the ARM ELF format specification. 155 std::string m_name; //!< File name. (optional) 156 Elf32_Ehdr m_header; //!< The ELF file header. 157 std::vector<Elf32_Shdr> m_sectionHeaders; //!< All of the section headers. 158 std::vector<Elf32_Phdr> m_programHeaders; //!< All of the program headers. 159 unsigned m_symbolTableIndex; //!< Index of ".symtab" section, or #SHN_UNDEF if not present. 160 161 /*! 162 * Little structure containing information about cached section data. 163 */ 164 struct SectionDataInfo 165 { 166 uint8_t * m_data; //!< Pointer to section data. 167 unsigned m_size; //!< Section data size in bytes. 168 bool m_swapped; //!< Has this section been byte swapped yet? Used for symbol table. 169 }; 170 typedef std::map<unsigned, SectionDataInfo> SectionDataMap; 171 SectionDataMap m_sectionDataCache; //!< Cached data of sections. 172 173 //! \brief Reads a section's data either from cache or from disk. 174 SectionDataInfo & getCachedSectionData(unsigned inSectionIndex); 175 176 //! \brief Reads the file, section, and program headers into memory. 177 void readFileHeaders(); 178 179 uint8_t * readSectionData(const Elf32_Shdr & inHeader); 180 uint8_t * readSegmentData(const Elf32_Phdr & inHeader); 181 182 //! \brief Byte swaps the symbol table data into host endianness. 183 void byteSwapSymbolTable(const Elf32_Shdr & header, SectionDataInfo & info); 184 }; 185 186 /*! 187 * \brief Simple exception thrown to indicate an error in the input ELF file format. 188 */ 189 class StELFFileException : public std::runtime_error 190 { 191 public: 192 //! \brief Default constructor. StELFFileException(const std::string & inMessage)193 StELFFileException(const std::string & inMessage) : std::runtime_error(inMessage) {} 194 }; 195 196 #endif // _StELFFile_h_ 197