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. 19typedef 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. 26typedef 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 */ 40class StELFFile 41{ 42public: 43 typedef std::vector<Elf32_Shdr>::const_iterator const_section_iterator; 44 typedef std::vector<Elf32_Phdr>::const_iterator const_segment_iterator; 45 46public: 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. 56 virtual ELFVariant_t ELFVariant() { return m_elfVariant; } 57 58 //! \brief Set the ELF format variation to either #eARMVariant or #eGHSVariant. 59 virtual void setELFVariant(ELFVariant_t variant) { m_elfVariant = variant; } 60 //@} 61 62 //! \name File name 63 //@{ 64 virtual void setName(const std::string & inName) { m_name = inName; } 65 virtual std::string getName() const { return m_name; } 66 //@} 67 68 //! \name ELF header 69 //@{ 70 //! \brief Returns the ELF file header. 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. 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 83 inline const_section_iterator getSectionBegin() const { return m_sectionHeaders.begin(); } 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. 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 105 inline const_segment_iterator getSegmentBegin() const { return m_programHeaders.begin(); } 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 152protected: 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 */ 189class StELFFileException : public std::runtime_error 190{ 191public: 192 //! \brief Default constructor. 193 StELFFileException(const std::string & inMessage) : std::runtime_error(inMessage) {} 194}; 195 196#endif // _StELFFile_h_ 197