xref: /netbsd-src/external/bsd/elftosb/dist/common/StELFFile.h (revision 993229b6fea628ff8b1fa09146c80b0cfb2768eb)
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.
ELFVariant()56 	virtual ELFVariant_t ELFVariant() { return m_elfVariant; }
57 
58 	//! \brief Set the ELF format variation to either #eARMVariant or #eGHSVariant.
setELFVariant(ELFVariant_t variant)59 	virtual void setELFVariant(ELFVariant_t variant) { m_elfVariant = variant; }
60 	//@}
61 
62 	//! \name File name
63 	//@{
setName(const std::string & inName)64 	virtual void setName(const std::string & inName) { m_name = inName; }
getName()65 	virtual std::string getName() const { return m_name; }
66 	//@}
67 
68 	//! \name ELF header
69 	//@{
70 	//! \brief Returns the ELF file header.
getFileHeader()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.
getSectionCount()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 
getSectionBegin()83 	inline const_section_iterator getSectionBegin() const { return m_sectionHeaders.begin(); }
getSectionEnd()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.
getSegmentCount()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 
getSegmentBegin()105 	inline const_segment_iterator getSegmentBegin() const { return m_programHeaders.begin(); }
getSegmentEnd()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.
StELFFileException(const std::string & inMessage)193 	StELFFileException(const std::string & inMessage) : std::runtime_error(inMessage) {}
194 };
195 
196 #endif // _StELFFile_h_
197