1 /*========================== begin_copyright_notice ============================
2
3 Copyright (C) 2017-2021 Intel Corporation
4
5 SPDX-License-Identifier: MIT
6
7 ============================= end_copyright_notice ===========================*/
8
9 #include "ElfWriter.h"
10 #include "secure_mem.h" // needed for memcpy_s on linux/android
11 #include <cstring>
12
13 namespace CLElfLib
14 {
15 /******************************************************************************\
16 Constructor: CElfWriter::CElfWriter
17 \******************************************************************************/
CElfWriter(E_EH_TYPE type,E_EH_MACHINE machine,Elf64_Xword flags)18 CElfWriter::CElfWriter(
19 E_EH_TYPE type,
20 E_EH_MACHINE machine,
21 Elf64_Xword flags )
22 {
23 m_type = type;
24 m_machine = machine;
25 m_flags = flags;
26 m_dataSize = 0;
27 m_numSections = 0;
28 m_stringTableSize = 0;
29 }
30
31 /******************************************************************************\
32 Destructor: CElfWriter::~CElfWriter
33 \******************************************************************************/
~CElfWriter()34 CElfWriter::~CElfWriter()
35 {
36 SSectionNode* pNode = NULL;
37
38 // Walk through the section nodes
39 while( m_nodeQueue.empty() == false )
40 {
41 pNode = m_nodeQueue.front();
42 m_nodeQueue.pop();
43
44 // delete the node and it's data
45 if( pNode )
46 {
47 if( pNode->pData )
48 {
49 delete[] pNode->pData;
50 pNode->pData = NULL;
51 }
52
53 delete pNode;
54 }
55 }
56 }
57
58 /******************************************************************************\
59 Member Function: CElfWriter::Create
60 \******************************************************************************/
Create(E_EH_TYPE type,E_EH_MACHINE machine,Elf64_Xword flags)61 CElfWriter* CElfWriter::Create(
62 E_EH_TYPE type,
63 E_EH_MACHINE machine,
64 Elf64_Xword flags )
65 {
66 CElfWriter* pWriter = new CElfWriter(
67 type, machine, flags );
68
69 if( ( pWriter ) && ( pWriter->Initialize() != SUCCESS ) )
70 {
71 Delete( pWriter );
72 }
73
74 return pWriter;
75 }
76
77 /******************************************************************************\
78 Member Function: CElfWriter::Delete
79 \******************************************************************************/
Delete(CElfWriter * & pWriter)80 void CElfWriter::Delete(
81 CElfWriter* &pWriter )
82 {
83 if( pWriter )
84 {
85 delete pWriter;
86 pWriter = NULL;
87 }
88 }
89
90 /******************************************************************************\
91 Member Function: CElfWriter::AddSection
92 \******************************************************************************/
AddSection(SSectionNode * pSectionNode)93 E_RETVAL CElfWriter::AddSection(
94 SSectionNode* pSectionNode )
95 {
96 E_RETVAL retVal = SUCCESS;
97 SSectionNode* pNode = NULL;
98 size_t nameSize = 0;
99 unsigned int dataSize = 0;
100
101 // The section header must be non-NULL
102 if( pSectionNode )
103 {
104 pNode = new SSectionNode();
105
106 if( !pNode )
107 {
108 retVal = OUT_OF_MEMORY;
109 }
110 }
111 else
112 {
113 retVal = FAILURE;
114 }
115
116 if( retVal == SUCCESS )
117 {
118 pNode->Flags = pSectionNode->Flags;
119 pNode->Type = pSectionNode->Type;
120
121 nameSize = pSectionNode->Name.size() + 1;
122 dataSize = pSectionNode->DataSize;
123
124 pNode->Name = pSectionNode->Name;
125
126 // ok to have NULL data
127 if( dataSize > 0 )
128 {
129 pNode->pData = new char[dataSize];
130
131 if( pNode->pData )
132 {
133 memcpy_s( pNode->pData, dataSize, pSectionNode->pData, dataSize );
134 pNode->DataSize = dataSize;
135 }
136 else
137 {
138 retVal = OUT_OF_MEMORY;
139 }
140 }
141
142 if( retVal == SUCCESS )
143 {
144 // push the node onto the queue
145 m_nodeQueue.push( pNode );
146
147 // increment the sizes for each section
148 m_dataSize += dataSize;
149 m_stringTableSize += nameSize;
150 m_numSections++;
151 }
152 else
153 {
154 // cleanup allocations
155 if( pNode )
156 {
157 if( pNode->pData )
158 {
159 delete[] pNode->pData;
160 pNode->pData = NULL;
161 }
162
163 delete pNode;
164 }
165 }
166 }
167
168 return retVal;
169 }
170
171 /******************************************************************************\
172 Member Function: CElfWriter::ResolveBinary
173 \******************************************************************************/
ResolveBinary(char * const pBinary,size_t & binarySize)174 E_RETVAL CElfWriter::ResolveBinary(
175 char* const pBinary,
176 size_t& binarySize )
177 {
178 E_RETVAL retVal = SUCCESS;
179 SSectionNode* pNode = NULL;
180 SElf64SectionHeader* pCurSectionHeader = NULL;
181 char* pData = NULL;
182 char* pStringTable = NULL;
183 char* pCurString = NULL;
184
185 m_totalBinarySize =
186 sizeof( SElf64Header ) +
187 ( ( m_numSections + 1 ) * sizeof( SElf64SectionHeader ) ) + // +1 to account for string table entry
188 m_dataSize +
189 m_stringTableSize;
190
191 if( pBinary )
192 {
193 // get a pointer to the first section header
194 pCurSectionHeader = (SElf64SectionHeader*)( pBinary + sizeof( SElf64Header ) );
195
196 // get a pointer to the data
197 pData = pBinary +
198 sizeof( SElf64Header ) +
199 ( ( m_numSections + 1 ) * sizeof( SElf64SectionHeader ) ); // +1 to account for string table entry
200
201
202 // get a pointer to the string table
203 pStringTable = pBinary + sizeof( SElf64Header ) +
204 ( ( m_numSections + 1 ) * sizeof( SElf64SectionHeader ) ) + // +1 to account for string table entry
205 m_dataSize ;
206
207 pCurString = pStringTable;
208
209 // Walk through the section nodes
210 while( m_nodeQueue.empty() == false )
211 {
212 pNode = m_nodeQueue.front();
213
214 if( pNode )
215 {
216 m_nodeQueue.pop();
217
218 // Copy data into the section header
219 memset( pCurSectionHeader, 0, sizeof( SElf64SectionHeader ) );
220 pCurSectionHeader->Type = pNode->Type;
221 pCurSectionHeader->Flags = pNode->Flags;
222 pCurSectionHeader->DataSize = pNode->DataSize;
223 pCurSectionHeader->DataOffset = pData - pBinary;
224 pCurSectionHeader->Name = (Elf64_Word)( pCurString - pStringTable );
225 pCurSectionHeader = (SElf64SectionHeader*)(
226 (unsigned char*)pCurSectionHeader + sizeof( SElf64SectionHeader ) );
227
228 // copy the data, move the data pointer
229 memcpy_s( pData, pNode->DataSize, pNode->pData, pNode->DataSize );
230 pData += pNode->DataSize;
231
232 // copy the name into the string table, move the string pointer
233 if ( pNode->Name.size() > 0 )
234 {
235 memcpy_s( pCurString, pNode->Name.size(), pNode->Name.c_str(), pNode->Name.size() );
236 pCurString += pNode->Name.size();
237 }
238 *(pCurString++) = '\0';
239
240 // delete the node and it's data
241 if( pNode )
242 {
243 if( pNode->pData )
244 {
245 delete[] pNode->pData;
246 pNode->pData = NULL;
247 }
248
249 delete pNode;
250 }
251 }
252 }
253
254 // add the string table section header
255 SElf64SectionHeader stringSectionHeader = { 0 };
256 stringSectionHeader.Type = SH_TYPE_STR_TBL;
257 stringSectionHeader.Flags = 0;
258 stringSectionHeader.DataOffset = pStringTable - pBinary;
259 stringSectionHeader.DataSize = m_stringTableSize;
260 stringSectionHeader.Name = 0;
261
262 // Copy into the last section header
263 memcpy_s( pCurSectionHeader, sizeof( SElf64SectionHeader ),
264 &stringSectionHeader, sizeof( SElf64SectionHeader ) );
265
266 // Add to our section number
267 m_numSections++;
268
269 // patch up the ELF header
270 retVal = PatchElfHeader( pBinary );
271 }
272
273 if( retVal == SUCCESS )
274 {
275 binarySize = m_totalBinarySize;
276 }
277
278 return retVal;
279 }
280
281 /******************************************************************************\
282 Member Function: CElfWriter::Initialize
283 \******************************************************************************/
Initialize()284 E_RETVAL CElfWriter::Initialize()
285 {
286 E_RETVAL retVal = SUCCESS;
287 SSectionNode emptySection;
288
289 // Add an empty section 0 (points to "no-bits")
290 AddSection( &emptySection );
291
292 return retVal;
293 }
294
295 /******************************************************************************\
296 Member Function: CElfWriter::PatchElfHeader
297 \******************************************************************************/
PatchElfHeader(char * const pBinary)298 E_RETVAL CElfWriter::PatchElfHeader( char* const pBinary )
299 {
300 E_RETVAL retVal = SUCCESS;
301 SElf64Header* pElfHeader = (SElf64Header*)pBinary;
302
303 if( pElfHeader )
304 {
305 // Setup the identity
306 memset( pElfHeader, 0x00, sizeof( SElf64Header ) );
307 pElfHeader->Identity[ID_IDX_MAGIC0] = ELF_MAG0;
308 pElfHeader->Identity[ID_IDX_MAGIC1] = ELF_MAG1;
309 pElfHeader->Identity[ID_IDX_MAGIC2] = ELF_MAG2;
310 pElfHeader->Identity[ID_IDX_MAGIC3] = ELF_MAG3;
311 pElfHeader->Identity[ID_IDX_CLASS] = EH_CLASS_64;
312 pElfHeader->Identity[ID_IDX_VERSION] = EH_VERSION_CURRENT;
313
314 // Add other non-zero info
315 pElfHeader->Type = m_type;
316 pElfHeader->Machine = m_machine;
317 pElfHeader->Flags = (unsigned int)m_flags;
318 pElfHeader->ElfHeaderSize = sizeof( SElf64Header );
319 pElfHeader->SectionHeaderEntrySize = sizeof( SElf64SectionHeader );
320 pElfHeader->NumSectionHeaderEntries = (Elf64_Short)m_numSections;
321 pElfHeader->SectionHeadersOffset = (unsigned int)( sizeof( SElf64Header ) );
322 pElfHeader->SectionNameTableIndex = m_numSections-1; // last index
323 }
324
325 return retVal;
326 }
327
328 } // namespace OclElfLib
329