Home | History | Annotate | Line # | Download | only in common
      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.
     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 
    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.
    193 	StELFFileException(const std::string & inMessage) : std::runtime_error(inMessage) {}
    194 };
    195 
    196 #endif // _StELFFile_h_
    197