Files
bootloader/src/blfwk/StELFFile.h
László Monda e6c1fce5b4 Add KBOOT.
2016-08-10 01:45:15 +02:00

220 lines
8.5 KiB
C++

/*
* Copyright (c) 2013-14, Freescale Semiconductor, Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* o Redistributions of source code must retain the above copyright notice, this list
* of conditions and the following disclaimer.
*
* o Redistributions in binary form must reproduce the above copyright notice, this
* list of conditions and the following disclaimer in the documentation and/or
* other materials provided with the distribution.
*
* o Neither the name of Freescale Semiconductor, Inc. nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#if !defined(_StELFFile_h_)
#define _StELFFile_h_
#include "blfwk/stdafx.h"
#include <string>
#include <vector>
#include <map>
#include <iostream>
#include <stdexcept>
#include "blfwk/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_