197 lines
7.1 KiB
C++
197 lines
7.1 KiB
C++
/*
|
|
* 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 <string>
|
|
#include <vector>
|
|
#include <map>
|
|
#include <iostream>
|
|
#include <stdexcept>
|
|
#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<Elf32_Shdr>::const_iterator const_section_iterator;
|
|
typedef std::vector<Elf32_Phdr>::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<unsigned>(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<unsigned>(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<Elf32_Shdr> m_sectionHeaders; //!< All of the section headers.
|
|
std::vector<Elf32_Phdr> 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<unsigned, SectionDataInfo> 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_
|