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