1 #include <assert.h>
2 #include <string.h>
3 #include <stdexcept>
4 #include "ELF.h"
5 #include "PtrStream.h"
6 
CELF(uint8 * content)7 CELF::CELF(uint8* content)
8     : m_content(content)
9 {
10 	Framework::CPtrStream stream(m_content, -1);
11 
12 	stream.Read(&m_Header, sizeof(ELFHEADER));
13 
14 	if(m_Header.nId[0] != 0x7F || m_Header.nId[1] != 'E' || m_Header.nId[2] != 'L' || m_Header.nId[3] != 'F')
15 	{
16 		throw std::runtime_error("This file isn't a valid ELF file.");
17 	}
18 
19 	if(m_Header.nId[4] != 1 || m_Header.nId[5] != 1)
20 	{
21 		throw std::runtime_error("This ELF file format is not supported. Only 32-bits LSB ordered ELFs are supported.");
22 	}
23 
24 	{
25 		unsigned int nCount = m_Header.nProgHeaderCount;
26 		m_pProgram = new ELFPROGRAMHEADER[nCount];
27 
28 		stream.Seek(m_Header.nProgHeaderStart, Framework::STREAM_SEEK_SET);
29 		for(unsigned int i = 0; i < nCount; i++)
30 		{
31 			stream.Read(&m_pProgram[i], sizeof(ELFPROGRAMHEADER));
32 		}
33 	}
34 
35 	{
36 		unsigned int nCount = m_Header.nSectHeaderCount;
37 		m_pSection = new ELFSECTIONHEADER[nCount];
38 
39 		stream.Seek(m_Header.nSectHeaderStart, Framework::STREAM_SEEK_SET);
40 		for(unsigned int i = 0; i < nCount; i++)
41 		{
42 			stream.Read(&m_pSection[i], sizeof(ELFSECTIONHEADER));
43 		}
44 	}
45 }
46 
~CELF()47 CELF::~CELF()
48 {
49 	delete[] m_pProgram;
50 	delete[] m_pSection;
51 }
52 
GetContent() const53 uint8* CELF::GetContent() const
54 {
55 	return m_content;
56 }
57 
GetHeader() const58 const ELFHEADER& CELF::GetHeader() const
59 {
60 	return m_Header;
61 }
62 
GetSection(unsigned int nIndex)63 ELFSECTIONHEADER* CELF::GetSection(unsigned int nIndex)
64 {
65 	if(nIndex >= m_Header.nSectHeaderCount)
66 	{
67 		return nullptr;
68 	}
69 	return &m_pSection[nIndex];
70 }
71 
GetSectionData(unsigned int nIndex)72 const void* CELF::GetSectionData(unsigned int nIndex)
73 {
74 	auto section = GetSection(nIndex);
75 	if(section == nullptr) return nullptr;
76 	return m_content + section->nOffset;
77 }
78 
GetSectionName(unsigned int sectionIndex)79 const char* CELF::GetSectionName(unsigned int sectionIndex)
80 {
81 	auto stringTableData = reinterpret_cast<const char*>(GetSectionData(m_Header.nSectHeaderStringTableIndex));
82 	if(stringTableData == nullptr) return nullptr;
83 	auto sectionHeader = GetSection(sectionIndex);
84 	if(sectionHeader == nullptr) return nullptr;
85 	return stringTableData + sectionHeader->nStringTableIndex;
86 }
87 
FindSection(const char * requestedSectionName)88 ELFSECTIONHEADER* CELF::FindSection(const char* requestedSectionName)
89 {
90 	auto sectionIndex = FindSectionIndex(requestedSectionName);
91 	if(sectionIndex == 0) return nullptr;
92 	return GetSection(sectionIndex);
93 }
94 
FindSectionIndex(const char * requestedSectionName)95 unsigned int CELF::FindSectionIndex(const char* requestedSectionName)
96 {
97 	auto stringTableData = reinterpret_cast<const char*>(GetSectionData(m_Header.nSectHeaderStringTableIndex));
98 	if(stringTableData == nullptr) return 0;
99 	for(unsigned int i = 0; i < m_Header.nSectHeaderCount; i++)
100 	{
101 		auto sectionHeader = GetSection(i);
102 		auto sectionName = stringTableData + sectionHeader->nStringTableIndex;
103 		if(!strcmp(sectionName, requestedSectionName))
104 		{
105 			return i;
106 		}
107 	}
108 	return 0;
109 }
110 
FindSectionData(const char * requestedSectionName)111 const void* CELF::FindSectionData(const char* requestedSectionName)
112 {
113 	auto section = FindSection(requestedSectionName);
114 	if(section == nullptr) return nullptr;
115 	return m_content + section->nOffset;
116 }
117 
GetProgram(unsigned int nIndex)118 ELFPROGRAMHEADER* CELF::GetProgram(unsigned int nIndex)
119 {
120 	if(nIndex >= m_Header.nProgHeaderCount)
121 	{
122 		return nullptr;
123 	}
124 	return &m_pProgram[nIndex];
125 }
126