|
1 // Copyright (c) 2004-2009 Nokia Corporation and/or its subsidiary(-ies). |
|
2 // All rights reserved. |
|
3 // This component and the accompanying materials are made available |
|
4 // under the terms of "Eclipse Public License v1.0" |
|
5 // which accompanies this distribution, and is available |
|
6 // at the URL "http://www.eclipse.org/legal/epl-v10.html". |
|
7 // |
|
8 // Initial Contributors: |
|
9 // Nokia Corporation - initial contribution. |
|
10 // |
|
11 // Contributors: |
|
12 // |
|
13 // Description: |
|
14 // Implementation of the Class ElfExecutable for the elf2e32 tool |
|
15 // @internalComponent |
|
16 // @released |
|
17 // |
|
18 // |
|
19 |
|
20 |
|
21 #include "pl_elfexecutable.h" |
|
22 #include "errorhandler.h" |
|
23 #include <stdio.h> |
|
24 #include "parameterlistinterface.h" |
|
25 #include "pl_elfimportrelocation.h" |
|
26 #include "pl_dllsymbol.h" |
|
27 #include "messagehandler.h" |
|
28 #include "pl_elflocalrelocation.h" |
|
29 |
|
30 |
|
31 /** |
|
32 Constructor for class ElfExecutable |
|
33 @param aParameterListInterface - Instance of class ParameterListInterface |
|
34 @internalComponent |
|
35 @released |
|
36 */ |
|
37 ElfExecutable::ElfExecutable(ParameterListInterface *aParameterListInterface) :\ |
|
38 iElfHeader(NULL), \ |
|
39 iEntryPoint(0),\ |
|
40 iProgHeader(NULL), \ |
|
41 iSONameOffset(0) ,\ |
|
42 iSections (NULL) , \ |
|
43 iVersionDef (NULL) , iVerDefCount(0), \ |
|
44 iVersionNeed (NULL) , iVerNeedCount(0), \ |
|
45 iVersionTbl (NULL) ,iRelSize(0),iRelEntSize(0), \ |
|
46 iNRelocs(0), |
|
47 iRel (NULL) ,iRelaSize(0), iRelaEntSize(0), \ |
|
48 iRela(NULL), |
|
49 iStringTable (NULL) , \ |
|
50 iSectionHdrStrTbl(NULL), \ |
|
51 iVerInfo(NULL), iElfDynSym (NULL), \ |
|
52 iSymTab (NULL), \ |
|
53 iStrTab (NULL), \ |
|
54 iLim (NULL), \ |
|
55 iNSymbols(0), \ |
|
56 iHashTbl (NULL) , \ |
|
57 iDynSegmentHdr (NULL) , \ |
|
58 iDataSegmentHdr (NULL) ,iDataSegment(NULL), iDataSegmentSize(0), iDataSegmentIdx(0), \ |
|
59 iCodeSegmentHdr (NULL) , iCodeSegment(NULL), iCodeSegmentSize(0), iCodeSegmentIdx(0), \ |
|
60 iExports (NULL), \ |
|
61 iParameterListInterface(aParameterListInterface),\ |
|
62 iPltGotBase(0), iPltGotLimit(0), iStrTabSz(0), iSymEntSz(0), \ |
|
63 iPltGot(NULL), iPltRel(NULL),iPltRelaSz(0), iPltRela(NULL), iPltRelSz(0) \ |
|
64 |
|
65 { |
|
66 } |
|
67 |
|
68 |
|
69 /** |
|
70 Destructor for class ElfExecutable |
|
71 @internalComponent |
|
72 @released |
|
73 */ |
|
74 ElfExecutable::~ElfExecutable() |
|
75 { |
|
76 delete iExports; |
|
77 delete [] iVerInfo; |
|
78 /* |
|
79 all of these were getting deleted, they are not allocated by |
|
80 ElfExecutable, they simply refer to a linear array of images |
|
81 in an ElfImage, hence they shouldn't be de-allocated |
|
82 |
|
83 delete iRela; |
|
84 delete iPltRel; |
|
85 delete iPltRela; */ |
|
86 |
|
87 iNeeded.clear(); |
|
88 iSymbolTable.clear(); |
|
89 } |
|
90 |
|
91 |
|
92 /** |
|
93 Function to process Elf file |
|
94 @param aElfHdr - pointer to Elf header |
|
95 @return 0 if its valid ELF file |
|
96 @internalComponent |
|
97 @released |
|
98 */ |
|
99 PLUINT32 ElfExecutable::ProcessElfFile(Elf32_Ehdr *aElfHdr) { |
|
100 |
|
101 iElfHeader = aElfHdr; |
|
102 iEntryPoint = aElfHdr->e_entry; |
|
103 |
|
104 ValidateElfFile(); |
|
105 |
|
106 /* A valid ELF file so far..*/ |
|
107 |
|
108 /* Get the Section base..*/ |
|
109 if(iElfHeader->e_shnum) { |
|
110 iSections = ELF_ENTRY_PTR(Elf32_Shdr, iElfHeader, iElfHeader->e_shoff); |
|
111 } |
|
112 |
|
113 /* Get the program header..*/ |
|
114 if(iElfHeader->e_phnum) { |
|
115 iProgHeader = ELF_ENTRY_PTR(Elf32_Phdr, iElfHeader, iElfHeader->e_phoff); |
|
116 } |
|
117 |
|
118 /* Get the section-header-string table..*/ |
|
119 if(iElfHeader->e_shstrndx != SHN_UNDEF) { |
|
120 |
|
121 if(iElfHeader->e_shstrndx > iElfHeader->e_shnum ) { |
|
122 throw ELFFormatError(ELFSHSTRINDEXERROR,iParameterListInterface->ElfInput()); |
|
123 } |
|
124 |
|
125 iSectionHdrStrTbl = ELF_ENTRY_PTR(char, iElfHeader, iSections[iElfHeader->e_shstrndx].sh_offset); |
|
126 } |
|
127 |
|
128 if( iProgHeader ) { |
|
129 PLUINT32 aIdx = 0; |
|
130 |
|
131 while( aIdx < iElfHeader->e_phnum) { |
|
132 switch( iProgHeader[aIdx].p_type ) { |
|
133 case PT_DYNAMIC: |
|
134 { |
|
135 iDynSegmentHdr = &iProgHeader[aIdx]; |
|
136 } |
|
137 break; |
|
138 case PT_LOAD: |
|
139 { |
|
140 if( (iProgHeader[aIdx].p_flags) & (PF_X | PF_ARM_ENTRY) ) { |
|
141 iCodeSegmentHdr = &iProgHeader[aIdx]; |
|
142 iCodeSegmentIdx = aIdx; |
|
143 iCodeSegment = ELF_ENTRY_PTR(char, iElfHeader, iCodeSegmentHdr->p_offset); |
|
144 iCodeSegmentSize = iCodeSegmentHdr->p_filesz; |
|
145 } |
|
146 else if( (iProgHeader[aIdx].p_flags) & (PF_W | PF_R) ) { |
|
147 iDataSegmentHdr = &iProgHeader[aIdx]; |
|
148 iDataSegmentIdx = aIdx; |
|
149 iDataSegment = ELF_ENTRY_PTR(char, iElfHeader, iDataSegmentHdr->p_offset); |
|
150 iDataSegmentSize = iDataSegmentHdr->p_filesz; |
|
151 } |
|
152 } |
|
153 break; |
|
154 default: |
|
155 break; |
|
156 |
|
157 } |
|
158 aIdx++; |
|
159 } |
|
160 |
|
161 if( iDynSegmentHdr ) { |
|
162 ProcessDynamicEntries(); |
|
163 } |
|
164 |
|
165 ProcessSymbols(); |
|
166 ProcessRelocations(); |
|
167 } |
|
168 |
|
169 return 0; |
|
170 } |
|
171 |
|
172 /** |
|
173 Function to Find the Static Symbol Table |
|
174 @internalComponent |
|
175 @released |
|
176 */ |
|
177 void ElfExecutable::FindStaticSymbolTable() |
|
178 { |
|
179 size_t nShdrs = iElfHeader->e_shnum; |
|
180 |
|
181 if (nShdrs) |
|
182 { |
|
183 // Find the static symbol table and string table |
|
184 for (PLUINT32 i = 0; i < nShdrs; i++) |
|
185 { |
|
186 if (iSections[i].sh_type == SHT_SYMTAB) |
|
187 { |
|
188 iSymTab = ELF_ENTRY_PTR(Elf32_Sym, iElfHeader, iSections[i].sh_offset); |
|
189 iLim = ELF_ENTRY_PTR(Elf32_Sym, iSymTab, iSections[i].sh_size); |
|
190 if (iStrTab) break; |
|
191 } |
|
192 else if (iSections[i].sh_type == SHT_STRTAB) |
|
193 { |
|
194 char * aSectionName = iSectionHdrStrTbl + iSections[i].sh_name; |
|
195 if (!strcmp(aSectionName, ".strtab")) |
|
196 { |
|
197 iStrTab = ELF_ENTRY_PTR(char, iElfHeader, iSections[i].sh_offset); |
|
198 if (iSymTab) break; |
|
199 } |
|
200 } |
|
201 } |
|
202 } |
|
203 } |
|
204 |
|
205 /** |
|
206 Function to Find the Comment Section |
|
207 @return aComment - Pointer to Comment Section |
|
208 @internalComponent |
|
209 @released |
|
210 */ |
|
211 char* ElfExecutable::FindCommentSection() |
|
212 { |
|
213 size_t nShdrs = iElfHeader->e_shnum; |
|
214 char *aCommentSection = ".comment"; |
|
215 char *aComment; |
|
216 |
|
217 if (nShdrs) |
|
218 { |
|
219 // find the comment section |
|
220 for (PLUINT32 i = 0; i < nShdrs; i++) |
|
221 { |
|
222 if (iSections[i].sh_type == SHT_PROGBITS) |
|
223 { |
|
224 char * aSectionName = iSectionHdrStrTbl + iSections[i].sh_name; |
|
225 int length = strlen(aCommentSection); |
|
226 if (!strncmp(aSectionName, aCommentSection, length)) |
|
227 { |
|
228 aComment = ELF_ENTRY_PTR(char, iElfHeader, iSections[i].sh_offset); |
|
229 return aComment; |
|
230 } |
|
231 } |
|
232 } |
|
233 } |
|
234 return NULL; |
|
235 } |
|
236 |
|
237 /** |
|
238 Function to process the ARM to Thumb veneers |
|
239 @internalComponent |
|
240 @released |
|
241 */ |
|
242 void ElfExecutable::ProcessVeneers() |
|
243 { |
|
244 if (iSymTab && iStrTab) |
|
245 { |
|
246 ElfRelocations::RelocationList & iLocalCodeRelocs = GetCodeRelocations(); |
|
247 |
|
248 Elf32_Sym *aSymTab = iSymTab; |
|
249 int length = strlen("$Ven$AT$L$$"); |
|
250 |
|
251 // Process the symbol table to find Long ARM to Thumb Veneers |
|
252 // i.e. symbols of the form '$Ven$AT$L$$' |
|
253 for(; aSymTab < iLim; aSymTab++) |
|
254 { |
|
255 if (!aSymTab->st_name) continue; |
|
256 char * aSymName = iStrTab + aSymTab->st_name; |
|
257 Elf32_Sym *aSym; |
|
258 |
|
259 if (!strncmp(aSymName, "$Ven$AT$L$$", length)) |
|
260 { |
|
261 aSym = aSymTab; |
|
262 Elf32_Addr r_offset = aSym->st_value; |
|
263 Elf32_Addr aOffset = r_offset + 4; |
|
264 Elf32_Word aInstruction = FindValueAtLoc(r_offset); |
|
265 bool aRelocEntryFound = false; |
|
266 |
|
267 ElfRelocations::RelocationList::iterator r; |
|
268 for (r = iLocalCodeRelocs.begin(); r != iLocalCodeRelocs.end(); r++) |
|
269 { |
|
270 ElfLocalRelocation * aReloc = *r; |
|
271 // Check if there is a relocation entry for the veneer symbol |
|
272 if (aReloc->iAddr == aOffset) |
|
273 { |
|
274 aRelocEntryFound = true; |
|
275 break; |
|
276 } |
|
277 } |
|
278 |
|
279 Elf32_Word aPointer = FindValueAtLoc(aOffset); |
|
280 |
|
281 /* If the symbol addresses a Thumb instruction, its value is the |
|
282 * address of the instruction with bit zero set (in a |
|
283 * relocatable object, the section offset with bit zero set). |
|
284 * This allows a linker to distinguish ARM and Thumb code symbols |
|
285 * without having to refer to the map. An ARM symbol will always have |
|
286 * an even value, while a Thumb symbol will always have an odd value. |
|
287 * Reference: Section 4.5.3 in Elf for the ARM Architecture Doc |
|
288 * aIsThumbSymbol will be 1 for a thumb symbol and 0 for ARM symbol |
|
289 */ |
|
290 int aIsThumbSymbol = aPointer & 0x1; |
|
291 |
|
292 /* The relocation entry should be generated for the veneer only if |
|
293 * the following three conditions are satisfied: |
|
294 * 1) Check if the instruction at the symbol is as expected |
|
295 * i.e. has the bit pattern 0xe51ff004 == 'LDR pc,[pc,#-4]' |
|
296 * 2) There is no relocation entry generated for the veneer symbol |
|
297 * 3) The instruction in the location provided by the pointer is a thumb symbol |
|
298 */ |
|
299 if (aInstruction == 0xE51FF004 && !aRelocEntryFound && aIsThumbSymbol) |
|
300 { |
|
301 ElfLocalRelocation *aRel; |
|
302 PLUCHAR aType = R_ARM_NONE; |
|
303 |
|
304 aRel = new ElfLocalRelocation(this, aOffset, 0, 0, aType, NULL, ESegmentRO, aSym, false, true); |
|
305 if(aRel) |
|
306 { |
|
307 aRel->Add(); |
|
308 } |
|
309 } |
|
310 } |
|
311 } |
|
312 } |
|
313 } |
|
314 |
|
315 /** |
|
316 Function to find the content of the address passed in |
|
317 @param aOffset - Address |
|
318 @return aLocVal - The content of the address, like instruction or a pointer |
|
319 @internalComponent |
|
320 @released |
|
321 */ |
|
322 Elf32_Word ElfExecutable::FindValueAtLoc(Elf32_Addr aOffset) |
|
323 { |
|
324 Elf32_Phdr *aHdr = Segment(aOffset); |
|
325 PLUINT32 aLoc = aHdr->p_offset + aOffset - aHdr->p_vaddr; |
|
326 Elf32_Word *aLocVal = ELF_ENTRY_PTR(Elf32_Word, iElfHeader, aLoc); |
|
327 return *aLocVal; |
|
328 } |
|
329 |
|
330 /** |
|
331 Function to process Elf symbols |
|
332 @internalComponent |
|
333 @released |
|
334 */ |
|
335 PLUINT32 ElfExecutable::ProcessSymbols(){ |
|
336 PLUINT32 aSymIdx = 0; |
|
337 DllSymbol *aSymbol; |
|
338 char *aDllName; |
|
339 char *aSymName, *aNewSymName; |
|
340 SymbolType aType; |
|
341 |
|
342 while( aSymIdx < iNSymbols ) { |
|
343 |
|
344 aSymName = ELF_ENTRY_PTR(char, iStringTable, iElfDynSym[aSymIdx].st_name ); |
|
345 |
|
346 if( ExportedSymbol( &iElfDynSym[aSymIdx] ) ){ |
|
347 |
|
348 if( FunctionSymbol( &iElfDynSym[aSymIdx] )) |
|
349 aType = SymbolTypeCode; |
|
350 else |
|
351 aType = SymbolTypeData; |
|
352 |
|
353 aSymName = ELF_ENTRY_PTR(char, iStringTable, iElfDynSym[aSymIdx].st_name ); |
|
354 aDllName = iVerInfo[iVersionTbl[aSymIdx]].iLinkAs; |
|
355 aNewSymName = new char[strlen(aSymName)+1]; |
|
356 strcpy(aNewSymName, aSymName); |
|
357 aSymbol = new DllSymbol( aNewSymName, aType, &iElfDynSym[aSymIdx], aSymIdx); |
|
358 aSymbol->SetSymbolSize(iElfDynSym[aSymIdx].st_size); |
|
359 |
|
360 //Putting the symbols into a hash table - Used later while processing relocations |
|
361 iSymbolTable[aSymIdx] = aSymbol ; |
|
362 if( !AddToExports( aDllName, aSymbol )) |
|
363 { |
|
364 //Not a valid export... delete it.. |
|
365 delete aSymbol; |
|
366 } |
|
367 } |
|
368 else if( ImportedSymbol( &iElfDynSym[aSymIdx] ) ){ |
|
369 |
|
370 if( FunctionSymbol( &iElfDynSym[aSymIdx] )) |
|
371 aType = SymbolTypeCode; |
|
372 else |
|
373 aType = SymbolTypeData; |
|
374 |
|
375 aSymName = ELF_ENTRY_PTR(char, iStringTable, iElfDynSym[aSymIdx].st_name ); |
|
376 |
|
377 /* |
|
378 * All imported symbols must be informed via the version needed information. |
|
379 */ |
|
380 if( iVerInfo[iVersionTbl[aSymIdx]].iVerCategory != VER_CAT_NEEDED ) { |
|
381 throw UndefinedSymbolError(UNDEFINEDSYMBOLERROR, iParameterListInterface->ElfInput(), aSymName); |
|
382 } |
|
383 aDllName = iVerInfo[iVersionTbl[aSymIdx]].iLinkAs; |
|
384 //aSymbol = new DllSymbol( aSymName, aType, &iElfDynSym[aSymIdx], aSymIdx); |
|
385 |
|
386 //Putting the symbols into a hash table |
|
387 //iSymbolTable[aSymIdx] = aSymbol ; |
|
388 } |
|
389 aSymIdx++; |
|
390 } |
|
391 |
|
392 return 0; |
|
393 } |
|
394 |
|
395 /** |
|
396 This function Dump all the sections with their section details (i.e., the section name, type, |
|
397 size and linked section if any) |
|
398 @param aFile - ELF file name |
|
399 @internalComponent |
|
400 @released |
|
401 */ |
|
402 void ElfExecutable::DumpElfFile(char* aFile){ |
|
403 aFile = aFile; |
|
404 } |
|
405 |
|
406 |
|
407 /** |
|
408 This function adds exports into the export list |
|
409 @param aDll - Dll name |
|
410 @param aSymbol - Symbol |
|
411 @return |
|
412 @internalComponent |
|
413 @released |
|
414 */ |
|
415 DllSymbol* ElfExecutable::AddToExports(char* aDll, DllSymbol* aSymbol){ |
|
416 if( !iExports ) { |
|
417 iExports = new ElfExports(); |
|
418 } |
|
419 return iExports->Add( aDll, this, aSymbol ); |
|
420 } |
|
421 |
|
422 |
|
423 /** |
|
424 This function adds imports into the map |
|
425 @param aReloc - Instance of class ElfImportRelocation |
|
426 @internalComponent |
|
427 @released |
|
428 */ |
|
429 void ElfExecutable::AddToImports(ElfImportRelocation* aReloc){ |
|
430 SetVersionRecord(aReloc); |
|
431 //char *aDll = iVerInfo[iVersionTbl[aReloc->iSymNdx]].iLinkAs; |
|
432 char *aDll = aReloc->iVerRecord->iLinkAs; |
|
433 iImports.Add( (const char*)aDll, aReloc ); |
|
434 |
|
435 } |
|
436 |
|
437 /** |
|
438 This function adds local relocation into a list |
|
439 @param aReloc - Instance of class ElfImportRelocation |
|
440 @internalComponent |
|
441 @released |
|
442 */ |
|
443 void ElfExecutable::AddToLocalRelocations(ElfRelocation* aReloc) { |
|
444 iLocalRelocations.Add((ElfLocalRelocation*)aReloc); |
|
445 } |
|
446 |
|
447 /** |
|
448 This function records the version of an imported symbol |
|
449 @param aReloc - Instance of class ElfImportRelocation |
|
450 @internalComponent |
|
451 @released |
|
452 */ |
|
453 void ElfExecutable::SetVersionRecord( ElfRelocation* aReloc ) { |
|
454 if( !aReloc ) |
|
455 return; |
|
456 ((ElfImportRelocation*)aReloc)->iVerRecord = &iVerInfo[ iVersionTbl[aReloc->iSymNdx]]; |
|
457 } |
|
458 |
|
459 /** |
|
460 This function validates the ELF file |
|
461 @internalComponent |
|
462 @released |
|
463 */ |
|
464 PLUINT32 ElfExecutable::ValidateElfFile() { |
|
465 |
|
466 /*Check if the ELF-Magic is correct*/ |
|
467 if(!(iElfHeader->e_ident[EI_MAG0] == ELFMAG0) && |
|
468 (iElfHeader->e_ident[EI_MAG1] == ELFMAG1) && |
|
469 (iElfHeader->e_ident[EI_MAG2] == ELFMAG2) && |
|
470 (iElfHeader->e_ident[EI_MAG3] == ELFMAG3) ) { |
|
471 throw ELFFormatError(ELFMAGICERROR, iParameterListInterface->ElfInput()); |
|
472 } |
|
473 |
|
474 /*32-bit ELF file*/ |
|
475 if(iElfHeader->e_ident[EI_CLASS] != ELFCLASS32) { |
|
476 throw ELFFormatError(ELFCLASSERROR, iParameterListInterface->ElfInput()); |
|
477 } |
|
478 |
|
479 /* Check if the ELF file is in Little endian format*/ |
|
480 if(iElfHeader->e_ident[EI_DATA] != ELFDATA2LSB) { |
|
481 throw ELFFormatError(ELFLEERROR, iParameterListInterface->ElfInput()); |
|
482 } |
|
483 |
|
484 /* The ELF executable must be a DLL or an EXE*/ |
|
485 if( iElfHeader->e_type != ET_EXEC && iElfHeader->e_type != ET_DYN) { |
|
486 throw ELFFormatError(ELFEXECUTABLEERROR, iParameterListInterface->ElfInput()); |
|
487 } |
|
488 |
|
489 return 0; |
|
490 } |
|
491 |
|
492 |
|
493 /** |
|
494 This function processes the dynamic table. |
|
495 @internalComponent |
|
496 @released |
|
497 */ |
|
498 PLUINT32 ElfExecutable::ProcessDynamicEntries(){ |
|
499 |
|
500 PLUINT32 aIdx = 0; |
|
501 bool aSONameFound = false; |
|
502 bool aPltRelTypeSeen = false, aJmpRelSeen = false; |
|
503 list<PLUINT32> aNeeded; |
|
504 Elf32_Dyn *aDyn = ELF_ENTRY_PTR(Elf32_Dyn, iElfHeader, iDynSegmentHdr->p_offset); |
|
505 |
|
506 while( aDyn[aIdx].d_tag != DT_NULL ) { |
|
507 switch (aDyn[aIdx].d_tag) { |
|
508 case DT_NEEDED: |
|
509 aNeeded.push_back( aDyn[aIdx].d_val ); |
|
510 break; |
|
511 case DT_HASH: |
|
512 iHashTbl = ELF_ENTRY_PTR(Elf32_HashTable, iElfHeader, aDyn[aIdx].d_val); |
|
513 break; |
|
514 case DT_STRTAB: |
|
515 iStringTable = ELF_ENTRY_PTR(char, iElfHeader, aDyn[aIdx].d_val); |
|
516 break; |
|
517 case DT_SYMTAB: |
|
518 iElfDynSym = ELF_ENTRY_PTR(Elf32_Sym, iElfHeader, aDyn[aIdx].d_val); |
|
519 break; |
|
520 case DT_RELA: |
|
521 iRela = ELF_ENTRY_PTR(Elf32_Rela, iElfHeader, aDyn[aIdx].d_val); |
|
522 break; |
|
523 case DT_RELASZ: |
|
524 iRelaSize = aDyn[aIdx].d_val; |
|
525 break; |
|
526 case DT_RELAENT: |
|
527 iRelaEntSize = aDyn[aIdx].d_val; |
|
528 break; |
|
529 case DT_SONAME: |
|
530 aSONameFound = true; |
|
531 iSONameOffset = aDyn[aIdx].d_val; |
|
532 break; |
|
533 case DT_REL: |
|
534 iRel = ELF_ENTRY_PTR(Elf32_Rel, iElfHeader, aDyn[aIdx].d_val); |
|
535 break; |
|
536 case DT_RELSZ: |
|
537 iRelSize = aDyn[aIdx].d_val; |
|
538 break; |
|
539 case DT_RELENT: |
|
540 iRelEntSize = aDyn[aIdx].d_val; |
|
541 break; |
|
542 case DT_VERSYM: |
|
543 iVersionTbl = ELF_ENTRY_PTR(Elf32_Half, iElfHeader, aDyn[aIdx].d_val); |
|
544 break; |
|
545 case DT_VERDEF: |
|
546 iVersionDef = ELF_ENTRY_PTR(Elf32_Verdef, iElfHeader, aDyn[aIdx].d_val); |
|
547 break; |
|
548 case DT_VERDEFNUM: |
|
549 iVerDefCount = aDyn[aIdx].d_val; |
|
550 break; |
|
551 case DT_VERNEED: |
|
552 iVersionNeed = ELF_ENTRY_PTR(Elf32_Verneed, iElfHeader, aDyn[aIdx].d_val); |
|
553 break; |
|
554 case DT_VERNEEDNUM: |
|
555 iVerNeedCount = aDyn[aIdx].d_val; |
|
556 break; |
|
557 case DT_STRSZ: |
|
558 iStrTabSz = aDyn[aIdx].d_val; |
|
559 break; |
|
560 case DT_SYMENT: |
|
561 iSymEntSz = aDyn[aIdx].d_val; |
|
562 break; |
|
563 case DT_PLTRELSZ: |
|
564 iPltRelSz = aDyn[aIdx].d_val; |
|
565 break; |
|
566 case DT_PLTGOT: |
|
567 iPltGot = ELF_ENTRY_PTR(Elf32_Word, iElfHeader, aDyn[aIdx].d_val); |
|
568 break; |
|
569 case DT_RPATH: |
|
570 break; |
|
571 case DT_SYMBOLIC: |
|
572 break; |
|
573 case DT_INIT: |
|
574 break; |
|
575 case DT_FINI: |
|
576 break; |
|
577 case DT_PLTREL: |
|
578 aPltRelTypeSeen = true; |
|
579 iPltRelType = aDyn[aIdx].d_val; |
|
580 break; |
|
581 case DT_DEBUG: |
|
582 break; |
|
583 case DT_TEXTREL: |
|
584 break; |
|
585 case DT_JMPREL: |
|
586 aJmpRelSeen = true; |
|
587 iJmpRelOffset = aDyn[aIdx].d_val; |
|
588 break; |
|
589 case DT_BIND_NOW: |
|
590 break; |
|
591 case DT_INIT_ARRAY: |
|
592 break; |
|
593 case DT_FINI_ARRAY: |
|
594 break; |
|
595 case DT_INIT_ARRAYSZ: |
|
596 break; |
|
597 case DT_FINI_ARRAYSZ: |
|
598 break; |
|
599 case DT_RELCOUNT: |
|
600 break; |
|
601 case DT_ARM_PLTGOTBASE: |
|
602 iPltGotBase = aDyn[aIdx].d_val; |
|
603 break; |
|
604 case DT_ARM_PLTGOTLIMIT: |
|
605 iPltGotLimit = aDyn[aIdx].d_val; |
|
606 break; |
|
607 case DT_ARM_SYMTABSZ: |
|
608 iNSymbols = aDyn[aIdx].d_val; |
|
609 break; |
|
610 default: |
|
611 //cout << "Unknown entry in dynamic table Tag=0x%x Value=0x%x",aDyn[aIdx].d_tag, aDyn[aIdx].d_val); |
|
612 break; |
|
613 } |
|
614 aIdx++; |
|
615 } |
|
616 |
|
617 //String table is found, so get the strings... |
|
618 if(aSONameFound) { |
|
619 iSOName = ELF_ENTRY_PTR(char, iStringTable, iSONameOffset); |
|
620 } |
|
621 |
|
622 std::list<PLUINT32>::iterator aItr = aNeeded.begin(); |
|
623 char *aStr; |
|
624 for( ; aItr != aNeeded.end();aItr++ ) { |
|
625 aStr = ELF_ENTRY_PTR(char, iStringTable, *aItr); |
|
626 iNeeded.push_back( aStr ); |
|
627 } |
|
628 |
|
629 if(iVerNeedCount || iVerDefCount) { |
|
630 ProcessVerInfo(); |
|
631 } |
|
632 |
|
633 if(iHashTbl) |
|
634 { |
|
635 //The number of symbols should be same as the number of chains in hashtable |
|
636 if (iNSymbols && (iNSymbols != iHashTbl->nChains)) |
|
637 throw ELFFormatError(SYMBOLCOUNTMISMATCHERROR,(char*)iParameterListInterface->ElfInput()); |
|
638 else |
|
639 //The number of symbols is same as the number of chains in hashtable |
|
640 iNSymbols = iHashTbl->nChains; |
|
641 } |
|
642 |
|
643 if( aPltRelTypeSeen && aJmpRelSeen) { |
|
644 |
|
645 if (iPltRelType == DT_REL) |
|
646 { |
|
647 iPltRel = ELF_ENTRY_PTR(Elf32_Rel, iElfHeader, iJmpRelOffset); |
|
648 // check to see if PltRels are included in iRel. If they are |
|
649 // ignore them since we don't care about the distinction |
|
650 if (iRel <= iPltRel && iPltRel < ELF_ENTRY_PTR(Elf32_Rel, iRel, iRelSize)) |
|
651 iPltRel = 0; |
|
652 } |
|
653 else |
|
654 { |
|
655 iPltRela = ELF_ENTRY_PTR(Elf32_Rela, iElfHeader, iJmpRelOffset); |
|
656 // check to see if PltRels are included in iRel. If they are |
|
657 // ignore them since we don't care about the distinction |
|
658 if (iRela <= iPltRela && iPltRela < ELF_ENTRY_PTR(Elf32_Rela, iRela, iRelaSize)) |
|
659 iPltRela = 0; |
|
660 } |
|
661 } |
|
662 |
|
663 return 0; |
|
664 } |
|
665 |
|
666 /** |
|
667 This function processes version information |
|
668 @internalComponent |
|
669 @released |
|
670 */ |
|
671 void ElfExecutable::ProcessVerInfo() { |
|
672 PLUINT32 aSz = iVerNeedCount + iVerDefCount + 1; |
|
673 iVerInfo = new VersionInfo[aSz]; |
|
674 |
|
675 Elf32_Verdef *aDef; |
|
676 Elf32_Verdaux *aDaux; |
|
677 Elf32_Verneed *aNeed; |
|
678 Elf32_Vernaux *aNaux; |
|
679 char *aSoName; |
|
680 char *aLinkAs; |
|
681 |
|
682 aDef = iVersionDef; |
|
683 |
|
684 while( aDef ) { |
|
685 aDaux = ELF_ENTRY_PTR( Elf32_Verdaux, aDef, aDef->vd_aux); |
|
686 aLinkAs = ELF_ENTRY_PTR(char, iStringTable, aDaux->vda_name ); |
|
687 aSoName = iSOName; |
|
688 iVerInfo[aDef->vd_ndx].iLinkAs = aLinkAs; |
|
689 iVerInfo[aDef->vd_ndx].iSOName = aSoName; |
|
690 iVerInfo[aDef->vd_ndx].iVerCategory = VER_CAT_DEFINED; |
|
691 |
|
692 if( !aDef->vd_next ) { |
|
693 break; |
|
694 } |
|
695 aDef = ELF_ENTRY_PTR(Elf32_Verdef, aDef, aDef->vd_next); |
|
696 } |
|
697 |
|
698 aNeed = iVersionNeed; |
|
699 |
|
700 while( aNeed ) { |
|
701 aNaux = ELF_ENTRY_PTR(Elf32_Vernaux, aNeed, aNeed->vn_aux); |
|
702 aLinkAs = ELF_ENTRY_PTR(char, iStringTable, aNaux->vna_name); |
|
703 aSoName = ELF_ENTRY_PTR(char, iStringTable, aNeed->vn_file); |
|
704 |
|
705 iVerInfo[aNaux->vna_other].iLinkAs = aLinkAs; |
|
706 iVerInfo[aNaux->vna_other].iSOName = aSoName; |
|
707 iVerInfo[aNaux->vna_other].iVerCategory = VER_CAT_NEEDED; |
|
708 |
|
709 if( !aNeed->vn_next ) { |
|
710 break; |
|
711 } |
|
712 aNeed = ELF_ENTRY_PTR(Elf32_Verneed, aNeed, aNeed->vn_next); |
|
713 } |
|
714 } |
|
715 |
|
716 /** |
|
717 This function processes Elf relocations |
|
718 @internalComponent |
|
719 @released |
|
720 */ |
|
721 void ElfExecutable::ProcessRelocations(){ |
|
722 ProcessRelocations(iRel, iRelSize); |
|
723 ProcessRelocations(iRela, iRelaSize); |
|
724 ProcessRelocations(iPltRel, iPltRelSz); |
|
725 ProcessRelocations(iPltRela, iPltRelaSz); |
|
726 } |
|
727 |
|
728 /** |
|
729 Template Function to process relocations |
|
730 @param aElfRel - relocation table |
|
731 @param aSize - relocation table size |
|
732 @internalComponent |
|
733 @released |
|
734 */ |
|
735 template <class T> |
|
736 void ElfExecutable::ProcessRelocations(T *aElfRel, size_t aSize){ |
|
737 if( !aElfRel ) |
|
738 return; |
|
739 |
|
740 T * aElfRelLimit = ELF_ENTRY_PTR(T, aElfRel, aSize); |
|
741 |
|
742 PLUINT32 aSymIdx; |
|
743 PLUCHAR aType; |
|
744 ElfRelocation *aRel; |
|
745 bool aImported; |
|
746 Elf32_Word aAddend; |
|
747 |
|
748 while( aElfRel < aElfRelLimit) { |
|
749 |
|
750 aType = ELF32_R_TYPE(aElfRel->r_info ); |
|
751 |
|
752 if(ElfRelocation::ValidRelocEntry(aType)) { |
|
753 |
|
754 aSymIdx = ELF32_R_SYM(aElfRel->r_info); |
|
755 aImported = ImportedSymbol( &iElfDynSym[aSymIdx] ); |
|
756 aAddend = Addend(aElfRel); |
|
757 aRel = ElfRelocation::NewRelocEntry(this, aElfRel->r_offset, aAddend, \ |
|
758 aSymIdx, aType, aElfRel, aImported); |
|
759 |
|
760 if(aRel) { |
|
761 aRel->Add(); |
|
762 } |
|
763 } |
|
764 aElfRel++; |
|
765 } |
|
766 } |
|
767 |
|
768 /** |
|
769 This function finds the addend associated with a relocation entry. |
|
770 @param aRel - relocation entry |
|
771 @return location in the elf image |
|
772 @internalComponent |
|
773 @released |
|
774 */ |
|
775 Elf32_Word ElfExecutable::Addend(Elf32_Rel* aRel) { |
|
776 PLUINT32 aOffset; |
|
777 Elf32_Word *aAddendPlace; |
|
778 Elf32_Phdr *aHdr = Segment(aRel->r_offset); |
|
779 aOffset = aHdr->p_offset + aRel->r_offset - aHdr->p_vaddr; |
|
780 aAddendPlace = ELF_ENTRY_PTR(Elf32_Word, iElfHeader, aOffset); |
|
781 return *aAddendPlace; |
|
782 } |
|
783 |
|
784 /** |
|
785 This function returns the addend for a relocation entry |
|
786 @param aRel - relocation entry |
|
787 @return location in the elf image |
|
788 @internalComponent |
|
789 @released |
|
790 */ |
|
791 Elf32_Word ElfExecutable::Addend(Elf32_Rela* aRel) { |
|
792 return aRel->r_addend; |
|
793 } |
|
794 |
|
795 /** |
|
796 This function gets the version info at an index |
|
797 @param aIndex - index into the version table |
|
798 @return version record |
|
799 @internalComponent |
|
800 @released |
|
801 */ |
|
802 VersionInfo* ElfExecutable::GetVersionInfo(PLUINT32 aIndex){ |
|
803 return &iVerInfo[ iVersionTbl[aIndex]]; |
|
804 } |
|
805 |
|
806 |
|
807 /** |
|
808 This function returns the Dll name in which an imported symbol is |
|
809 defined by looking in the version required section. |
|
810 @param aSymbolIndex - Index of symbol |
|
811 @return Dll name |
|
812 @internalComponent |
|
813 @released |
|
814 */ |
|
815 char* ElfExecutable::SymbolDefinedInDll(PLUINT32 aSymbolIndex){ |
|
816 |
|
817 VersionInfo *aVInfo = GetVersionInfo(aSymbolIndex); |
|
818 return aVInfo ? aVInfo->iLinkAs : NULL; |
|
819 } |
|
820 |
|
821 /** |
|
822 This function returns the DSO(import library) name where the Symbol information can be found. |
|
823 This DSO is then looked up for the ordinal number of this symbol. |
|
824 @param aSymbolIndex - Index of symbol |
|
825 @return DSO name |
|
826 @internalComponent |
|
827 @released |
|
828 */ |
|
829 char* ElfExecutable::SymbolFromDSO(PLUINT32 aSymbolIndex){ |
|
830 |
|
831 VersionInfo *aVInfo = GetVersionInfo(aSymbolIndex); |
|
832 return aVInfo ? aVInfo->iSOName : NULL; |
|
833 } |
|
834 |
|
835 /** |
|
836 This function returns the segment type |
|
837 @param aAddr - Address |
|
838 @return Segment type |
|
839 @internalComponent |
|
840 @released |
|
841 */ |
|
842 ESegmentType ElfExecutable::SegmentType(Elf32_Addr aAddr) { |
|
843 |
|
844 try { |
|
845 Elf32_Phdr *aHdr = Segment(aAddr); |
|
846 if( !aHdr ) |
|
847 return ESegmentUndefined; |
|
848 |
|
849 if( aHdr == iCodeSegmentHdr) |
|
850 return ESegmentRO; |
|
851 else if(aHdr == iDataSegmentHdr) |
|
852 return ESegmentRW; |
|
853 else |
|
854 return ESegmentUndefined; |
|
855 } |
|
856 catch(...) |
|
857 { |
|
858 } |
|
859 |
|
860 return ESegmentUndefined; |
|
861 } |
|
862 |
|
863 /** |
|
864 This function returns the segment type |
|
865 @param aType |
|
866 @return Segment header |
|
867 @internalComponent |
|
868 @released |
|
869 */ |
|
870 Elf32_Phdr* ElfExecutable::Segment(ESegmentType aType) { |
|
871 |
|
872 switch(aType) |
|
873 { |
|
874 case ESegmentRO: |
|
875 return iCodeSegmentHdr; |
|
876 case ESegmentRW: |
|
877 return iDataSegmentHdr; |
|
878 default: |
|
879 return NULL; |
|
880 } |
|
881 } |
|
882 |
|
883 /** |
|
884 Function to get segment header |
|
885 @param aAddr - Address |
|
886 @return Segment header |
|
887 @internalComponent |
|
888 @released |
|
889 */ |
|
890 Elf32_Phdr* ElfExecutable::Segment(Elf32_Addr aAddr) { |
|
891 |
|
892 if(iCodeSegmentHdr) { |
|
893 PLUINT32 aBase = iCodeSegmentHdr->p_vaddr; |
|
894 if( aBase <= aAddr && aAddr < (aBase + iCodeSegmentHdr->p_memsz) ) { |
|
895 return iCodeSegmentHdr; |
|
896 } |
|
897 } |
|
898 if(iDataSegmentHdr) { |
|
899 PLUINT32 aBase = iDataSegmentHdr->p_vaddr; |
|
900 if( aBase <= aAddr && aAddr < (aBase + iDataSegmentHdr->p_memsz) ) { |
|
901 return iDataSegmentHdr; |
|
902 } |
|
903 } |
|
904 |
|
905 throw int(0); |
|
906 } |
|
907 |
|
908 /** |
|
909 Thsi function returns the segment header to which the address refers. |
|
910 @param aAddr - location |
|
911 @return Segment header. |
|
912 @internalComponent |
|
913 @released |
|
914 */ |
|
915 Elf32_Phdr* ElfExecutable::SegmentFromAbs(Elf32_Addr aAddr) { |
|
916 |
|
917 if(iCodeSegmentHdr) { |
|
918 PLUINT32 aBase = iCodeSegmentHdr->p_vaddr; |
|
919 if( aBase <= aAddr && aAddr <= (aBase + iCodeSegmentHdr->p_memsz) ) { |
|
920 return iCodeSegmentHdr; |
|
921 } |
|
922 } |
|
923 if(iDataSegmentHdr) { |
|
924 PLUINT32 aBase = iDataSegmentHdr->p_vaddr; |
|
925 if( aBase <= aAddr && aAddr <= (aBase + iDataSegmentHdr->p_memsz) ) { |
|
926 return iDataSegmentHdr; |
|
927 } |
|
928 } |
|
929 return NULL; |
|
930 } |
|
931 |
|
932 /** |
|
933 This function says if the symbol is global. |
|
934 @param aSym - Symbol |
|
935 @return True if symbol is global, otherwise false |
|
936 @internalComponent |
|
937 @released |
|
938 */ |
|
939 bool ElfExecutable::GlobalSymbol(Elf32_Sym* aSym) |
|
940 { |
|
941 return (ELF32_ST_BIND(aSym->st_info) == STB_GLOBAL); |
|
942 } |
|
943 |
|
944 /** |
|
945 This function says if the symbol is exported. |
|
946 @param aSym - Symbol |
|
947 @return True if symbol is exported, otherwise false |
|
948 @internalComponent |
|
949 @released |
|
950 */ |
|
951 bool ElfExecutable::ExportedSymbol(Elf32_Sym* aSym) |
|
952 { |
|
953 PLUINT32 aIdx = aSym->st_shndx; |
|
954 |
|
955 if(GlobalSymbol(aSym) && VisibleSymbol(aSym) && DefinedSymbol(aSym) && \ |
|
956 (aIdx != SHN_UNDEF) && (FunctionSymbol(aSym) || DataSymbol(aSym) ) && aIdx < SHN_ABS ) |
|
957 return true; |
|
958 return false; |
|
959 } |
|
960 |
|
961 /** |
|
962 This function says if the symbol is imported. |
|
963 @param aSym - Symbol |
|
964 @return True if symbol is imported, otherwise false |
|
965 @internalComponent |
|
966 @released |
|
967 */ |
|
968 bool ElfExecutable::ImportedSymbol(Elf32_Sym* aSym) |
|
969 { |
|
970 PLUINT32 aIdx = aSym->st_shndx; |
|
971 |
|
972 if( (aIdx == SHN_UNDEF) && GlobalSymbol(aSym) && VisibleSymbol(aSym) && (!DefinedSymbol(aSym)) ) |
|
973 return true; |
|
974 return false; |
|
975 } |
|
976 |
|
977 /** |
|
978 This function says if the symbol refers to code or data. |
|
979 @param aSym - Symbol |
|
980 @return True if symbol refers to code, otherwise false |
|
981 @internalComponent |
|
982 @released |
|
983 */ |
|
984 bool ElfExecutable::FunctionSymbol(Elf32_Sym* aSym) |
|
985 { |
|
986 return (STT_FUNC == ELF32_ST_TYPE(aSym->st_info)); |
|
987 } |
|
988 |
|
989 /** |
|
990 This function says if the symbol refers to code or data. |
|
991 @param aSym - Symbol |
|
992 @return True if symbol refers to data, otherwise false |
|
993 @internalComponent |
|
994 @released |
|
995 */ |
|
996 bool ElfExecutable::DataSymbol(Elf32_Sym* aSym) |
|
997 { |
|
998 return (STT_OBJECT == ELF32_ST_TYPE(aSym->st_info)); |
|
999 } |
|
1000 |
|
1001 /** |
|
1002 This function says if the symbol is defined in the Elf executable. |
|
1003 @param aSym - Symbol |
|
1004 @return True if symbol is defined, otherwise false |
|
1005 @internalComponent |
|
1006 @released |
|
1007 */ |
|
1008 bool ElfExecutable::DefinedSymbol(Elf32_Sym* aSym) |
|
1009 { |
|
1010 if( aSym->st_shndx == SHN_UNDEF ) |
|
1011 return false; |
|
1012 ESegmentType aType = SegmentType(aSym->st_value); |
|
1013 return ((aType == ESegmentRO) || (aType == ESegmentRW)); |
|
1014 } |
|
1015 |
|
1016 /** |
|
1017 This function says if the visibility of the symbol is default. |
|
1018 @param aSym - Symbol |
|
1019 @return True if symbol has default visibility, otherwise false |
|
1020 @internalComponent |
|
1021 @released |
|
1022 */ |
|
1023 bool ElfExecutable::VisibleSymbol(Elf32_Sym* aSym) |
|
1024 { |
|
1025 return (STV_DEFAULT == ELF32_ST_VISIBILITY(aSym->st_other) || STV_PROTECTED == ELF32_ST_VISIBILITY(aSym->st_other)); |
|
1026 } |
|
1027 |
|
1028 /** |
|
1029 This function finds symbol using the hash table |
|
1030 @param aName - Symbol name |
|
1031 @return elf symbol. |
|
1032 @internalComponent |
|
1033 @released |
|
1034 */ |
|
1035 Elf32_Sym* ElfExecutable::FindSymbol(char* aName) { |
|
1036 if(!aName ) |
|
1037 return NULL; |
|
1038 |
|
1039 PLULONG aHashVal = Util::elf_hash((const PLUCHAR*) aName ); |
|
1040 |
|
1041 Elf32_Sword* aBuckets = ELF_ENTRY_PTR(Elf32_Sword, iHashTbl, sizeof(Elf32_HashTable) ); |
|
1042 Elf32_Sword* aChains = ELF_ENTRY_PTR(Elf32_Sword, aBuckets, sizeof(Elf32_Sword)*(iHashTbl->nBuckets) ); |
|
1043 |
|
1044 Elf32_Sword aIdx = aHashVal % iHashTbl->nBuckets; |
|
1045 aIdx = aBuckets[aIdx]; |
|
1046 |
|
1047 char *aSymName; |
|
1048 do { |
|
1049 aSymName = ELF_ENTRY_PTR(char, iStringTable, iElfDynSym[aIdx].st_name); |
|
1050 if( !strcmp(aSymName, aName) ) { |
|
1051 return &iElfDynSym[aIdx]; |
|
1052 } |
|
1053 aIdx = aChains[aIdx]; |
|
1054 }while( aIdx > 0 ); |
|
1055 |
|
1056 return NULL; |
|
1057 } |
|
1058 |
|
1059 /** |
|
1060 Function to get symbol name |
|
1061 @param aSymIdx - Index of symbol |
|
1062 @return Symbol name |
|
1063 @internalComponent |
|
1064 @released |
|
1065 */ |
|
1066 char* ElfExecutable::GetSymbolName( PLUINT32 aSymIdx) { |
|
1067 return ELF_ENTRY_PTR(char, iStringTable, iElfDynSym[aSymIdx].st_name); |
|
1068 } |
|
1069 |
|
1070 /** |
|
1071 Function to get symbol ordinal |
|
1072 @param aSymName - Symbol name |
|
1073 @return Symbol ordinal |
|
1074 @internalComponent |
|
1075 @released |
|
1076 */ |
|
1077 PLUINT32 ElfExecutable::GetSymbolOrdinal( char* aSymName) { |
|
1078 Elf32_Sym *aSym = FindSymbol(aSymName); |
|
1079 if( !aSym ) |
|
1080 return (PLUINT32)-1; |
|
1081 return GetSymbolOrdinal( aSym ); |
|
1082 |
|
1083 } |
|
1084 |
|
1085 /** |
|
1086 Function to get symbol ordinal |
|
1087 @param aSym - Symbol |
|
1088 @return Symbol ordinal |
|
1089 @internalComponent |
|
1090 @released |
|
1091 */ |
|
1092 PLUINT32 ElfExecutable::GetSymbolOrdinal( Elf32_Sym* aSym) { |
|
1093 PLUINT32 aOrd = (PLUINT32)-1; |
|
1094 if( aSym->st_shndx == ESegmentRO) { |
|
1095 Elf32_Word *aLocation, aOffset; |
|
1096 |
|
1097 aOffset = iCodeSegmentHdr->p_offset + aSym->st_value - iCodeSegmentHdr->p_vaddr; |
|
1098 aLocation = ELF_ENTRY_PTR(Elf32_Word, iElfHeader, aOffset); |
|
1099 aOrd = *aLocation; |
|
1100 } |
|
1101 return aOrd; |
|
1102 } |
|
1103 |
|
1104 /** |
|
1105 Function to get relocation offset |
|
1106 @param aReloc - Instance of class ElfRelocation |
|
1107 @return offset |
|
1108 @internalComponent |
|
1109 @released |
|
1110 */ |
|
1111 Elf32_Word ElfExecutable::GetRelocationOffset(ElfRelocation * aReloc) |
|
1112 { |
|
1113 Elf32_Phdr * aHdr = Segment(aReloc->iAddr); |
|
1114 unsigned int aOffset = aReloc->iAddr - aHdr->p_vaddr; |
|
1115 return aOffset; |
|
1116 } |
|
1117 |
|
1118 /** |
|
1119 Function to get relocation place address |
|
1120 @param aReloc - Instance of class ElfRelocation |
|
1121 @return address to place relocation |
|
1122 @internalComponent |
|
1123 @released |
|
1124 */ |
|
1125 Elf32_Word * ElfExecutable::GetRelocationPlace(ElfRelocation * aReloc) |
|
1126 { |
|
1127 Elf32_Phdr * aHdr = Segment(aReloc->iAddr); |
|
1128 unsigned int aOffset = aHdr->p_offset + aReloc->iAddr - aHdr->p_vaddr; |
|
1129 Elf32_Word * aPlace = ELF_ENTRY_PTR(Elf32_Word, iElfHeader, aOffset); |
|
1130 return aPlace; |
|
1131 } |
|
1132 |
|
1133 /** |
|
1134 Function to get local relocation |
|
1135 @return local relocation |
|
1136 @internalComponent |
|
1137 @released |
|
1138 */ |
|
1139 ElfRelocations& ElfExecutable::GetLocalRelocations() |
|
1140 { |
|
1141 return iLocalRelocations; |
|
1142 } |
|
1143 |
|
1144 /** |
|
1145 Function to get code relocation |
|
1146 @return code relocation list |
|
1147 @internalComponent |
|
1148 @released |
|
1149 */ |
|
1150 ElfRelocations::RelocationList & ElfExecutable::GetCodeRelocations() |
|
1151 { |
|
1152 return GetLocalRelocations().GetCodeRelocations(); |
|
1153 } |
|
1154 |
|
1155 /** |
|
1156 Function to get data relocation |
|
1157 @return data relocation list |
|
1158 @internalComponent |
|
1159 @released |
|
1160 */ |
|
1161 ElfRelocations::RelocationList & ElfExecutable::GetDataRelocations() |
|
1162 { |
|
1163 return GetLocalRelocations().GetDataRelocations(); |
|
1164 } |
|
1165 |
|
1166 /** |
|
1167 Function to get RO base address |
|
1168 @return RO base virtual address |
|
1169 @internalComponent |
|
1170 @released |
|
1171 */ |
|
1172 Elf32_Word ElfExecutable::GetROBase() |
|
1173 { |
|
1174 if (iCodeSegmentHdr) return iCodeSegmentHdr->p_vaddr; |
|
1175 return 0; |
|
1176 } |
|
1177 |
|
1178 /** |
|
1179 Function to get RO segment |
|
1180 @return code segment |
|
1181 @internalComponent |
|
1182 @released |
|
1183 */ |
|
1184 MemAddr ElfExecutable::GetRawROSegment() |
|
1185 { |
|
1186 return iCodeSegment; |
|
1187 } |
|
1188 |
|
1189 /** |
|
1190 Function to get RW segment virtual address |
|
1191 @return RW base address |
|
1192 @internalComponent |
|
1193 @released |
|
1194 */ |
|
1195 Elf32_Word ElfExecutable::GetRWBase() |
|
1196 { |
|
1197 if (iDataSegmentHdr) return iDataSegmentHdr->p_vaddr; |
|
1198 return 0; |
|
1199 } |
|
1200 |
|
1201 /** |
|
1202 Function to get Raw RW segment |
|
1203 @return data segment address |
|
1204 @internalComponent |
|
1205 @released |
|
1206 */ |
|
1207 MemAddr ElfExecutable::GetRawRWSegment() |
|
1208 { |
|
1209 return iDataSegment; |
|
1210 } |
|
1211 |
|
1212 /** |
|
1213 Function to get RO segment size |
|
1214 @return code segment size |
|
1215 @internalComponent |
|
1216 @released |
|
1217 */ |
|
1218 size_t ElfExecutable::GetROSize() |
|
1219 { |
|
1220 return iCodeSegmentHdr->p_filesz; |
|
1221 } |
|
1222 |
|
1223 /** |
|
1224 Function to get RW segment size |
|
1225 @return data segment size |
|
1226 @internalComponent |
|
1227 @released |
|
1228 */ |
|
1229 size_t ElfExecutable::GetRWSize() |
|
1230 { |
|
1231 if (iDataSegmentHdr) |
|
1232 return iDataSegmentHdr->p_filesz;; |
|
1233 return 0; |
|
1234 } |
|
1235 |
|
1236 /** |
|
1237 Function to get Bss segment size |
|
1238 @return Bss segment size, if data segment, otherwise 0 |
|
1239 @internalComponent |
|
1240 @released |
|
1241 */ |
|
1242 size_t ElfExecutable::GetBssSize() |
|
1243 { |
|
1244 if (iDataSegmentHdr) |
|
1245 return iDataSegmentHdr->p_memsz - iDataSegmentHdr->p_filesz; |
|
1246 return 0; |
|
1247 } |
|
1248 |
|
1249 /** |
|
1250 Function returns entry point location in Elf image. |
|
1251 @return entry point offset if valid, warning if undefined, otherwise throw error |
|
1252 @internalComponent |
|
1253 @released |
|
1254 */ |
|
1255 Elf32_Word ElfExecutable::EntryPointOffset() |
|
1256 { |
|
1257 if (!(iElfHeader->e_entry) && !(iCodeSegmentHdr->p_vaddr)) |
|
1258 { |
|
1259 MessageHandler::GetInstance()->ReportMessage(WARNING, UNDEFINEDENTRYPOINTERROR,(char*)iParameterListInterface->ElfInput()); |
|
1260 return 0; |
|
1261 } |
|
1262 else if (!(iElfHeader->e_entry)) |
|
1263 throw ELFFormatError(ENTRYPOINTNOTSETERROR, (char*)iParameterListInterface->ElfInput()); |
|
1264 else |
|
1265 return iElfHeader->e_entry - iCodeSegmentHdr->p_vaddr; |
|
1266 } |
|
1267 |
|
1268 /** |
|
1269 Function to check exception is present in the Elf image. |
|
1270 @return True if exception present, otherwise false |
|
1271 @internalComponent |
|
1272 @released |
|
1273 */ |
|
1274 bool ElfExecutable::ExeceptionsPresentP() |
|
1275 { |
|
1276 size_t nShdrs = iElfHeader->e_shnum; |
|
1277 if (nShdrs) |
|
1278 { |
|
1279 // Find the exception index table section |
|
1280 Elf32_Shdr * aShdr = ELF_ENTRY_PTR(Elf32_Shdr, iElfHeader, iElfHeader->e_shoff); |
|
1281 char * aShStrTab = ELF_ENTRY_PTR(char, iElfHeader, aShdr[iElfHeader->e_shstrndx].sh_offset); |
|
1282 |
|
1283 for (PLUINT32 i = 0; i < nShdrs; i++) |
|
1284 { |
|
1285 if (aShdr[i].sh_type == SHT_ARM_EXIDX) |
|
1286 { |
|
1287 char * aSectionName = aShStrTab + aShdr[i].sh_name; |
|
1288 if (!strcmp(aSectionName, ".ARM.exidx")) |
|
1289 { |
|
1290 return true; |
|
1291 } |
|
1292 } |
|
1293 } |
|
1294 |
|
1295 } |
|
1296 else |
|
1297 throw ELFFileError(NEEDSECTIONVIEWERROR, (char*)iParameterListInterface->ElfInput()); |
|
1298 |
|
1299 return false; |
|
1300 } |
|
1301 |
|
1302 /** |
|
1303 Function to get the exports in ordinal number order. |
|
1304 @return ordered exports |
|
1305 @internalComponent |
|
1306 @released |
|
1307 */ |
|
1308 ElfExports::ExportList &ElfExecutable::GetExportsInOrdinalOrder() { |
|
1309 return iExports->GetExportsInOrdinalOrder(); |
|
1310 } |
|
1311 |
|
1312 /** |
|
1313 This function looks up for a symbol in the static symbol table. |
|
1314 @return Elf symbol. |
|
1315 @internalComponent |
|
1316 @released |
|
1317 */ |
|
1318 Elf32_Sym * ElfExecutable::LookupStaticSymbol(char * aName) { |
|
1319 size_t nShdrs = iElfHeader->e_shnum; |
|
1320 if (nShdrs) |
|
1321 { |
|
1322 // find the static symbol table and string table |
|
1323 Elf32_Shdr * aShdr = ELF_ENTRY_PTR(Elf32_Shdr, iElfHeader, iElfHeader->e_shoff); |
|
1324 char * aShStrTab = ELF_ENTRY_PTR(char, iElfHeader, aShdr[iElfHeader->e_shstrndx].sh_offset); |
|
1325 Elf32_Sym * aSymTab = 0; |
|
1326 Elf32_Sym * aLim = 0; |
|
1327 char * aStrTab = 0; |
|
1328 for (PLUINT32 i = 0; i < nShdrs; i++) |
|
1329 { |
|
1330 if (aShdr[i].sh_type == SHT_SYMTAB) |
|
1331 { |
|
1332 aSymTab = ELF_ENTRY_PTR(Elf32_Sym, iElfHeader, aShdr[i].sh_offset); |
|
1333 aLim = ELF_ENTRY_PTR(Elf32_Sym, aSymTab, aShdr[i].sh_size); |
|
1334 if (aStrTab) break; |
|
1335 } |
|
1336 else if (aShdr[i].sh_type == SHT_STRTAB) |
|
1337 { |
|
1338 char * aSectionName = aShStrTab + aShdr[i].sh_name; |
|
1339 if (!strcmp(aSectionName, ".strtab")) |
|
1340 { |
|
1341 aStrTab = ELF_ENTRY_PTR(char, iElfHeader, aShdr[i].sh_offset); |
|
1342 if (aSymTab) break; |
|
1343 } |
|
1344 } |
|
1345 } |
|
1346 |
|
1347 /*if(aHashTbl && aSymTab && aStrTab) |
|
1348 { |
|
1349 PLULONG aHashVal = Util::elf_hash((const PLUCHAR*)aName); |
|
1350 Elf32_Sword* aBuckets = ELF_ENTRY_PTR(Elf32_Sword, aHashTbl, sizeof(Elf32_HashTable) ); |
|
1351 Elf32_Sword* aChains = ELF_ENTRY_PTR(Elf32_Sword, aBuckets, sizeof(Elf32_Sword)*(aHashTbl->nBuckets) ); |
|
1352 |
|
1353 PLUINT32 aIdx = aHashVal % aHashTbl->nBuckets; |
|
1354 aIdx = aBuckets[aIdx]; |
|
1355 |
|
1356 char *aSymName; |
|
1357 do { |
|
1358 aSymName = ELF_ENTRY_PTR(char, aStrTab, aSymTab[aIdx].st_name); |
|
1359 if( !strcmp(aSymName, aName) ) { |
|
1360 return &aSymTab[aIdx]; |
|
1361 } |
|
1362 aIdx = aChains[aIdx]; |
|
1363 }while( aIdx > 0 ); |
|
1364 |
|
1365 return NULL; |
|
1366 } |
|
1367 else */ |
|
1368 |
|
1369 if (aSymTab && aStrTab) |
|
1370 { |
|
1371 for(; aSymTab < aLim; aSymTab++) |
|
1372 { |
|
1373 if (!aSymTab->st_name) continue; |
|
1374 char * aSymName = aStrTab + aSymTab->st_name; |
|
1375 if (!strcmp(aSymName, aName)) |
|
1376 return aSymTab; |
|
1377 } |
|
1378 return 0; |
|
1379 } |
|
1380 else |
|
1381 { |
|
1382 throw ELFFileError(NOSTATICSYMBOLSERROR, (char*)iParameterListInterface->ElfInput()); |
|
1383 } |
|
1384 } |
|
1385 else |
|
1386 { |
|
1387 throw ELFFileError(NOSTATICSYMBOLSERROR, (char*)iParameterListInterface->ElfInput()); |
|
1388 } |
|
1389 } |
|
1390 |
|
1391 /** |
|
1392 Function to get imports |
|
1393 @return imports |
|
1394 @internalComponent |
|
1395 @released |
|
1396 */ |
|
1397 ElfImports::ImportMap ElfExecutable::GetImports() { |
|
1398 return iImports.GetImports(); |
|
1399 } |
|
1400 |
|
1401 /** |
|
1402 Function to get exports |
|
1403 @return exports |
|
1404 @internalComponent |
|
1405 @released |
|
1406 */ |
|
1407 ElfExports* ElfExecutable::GetExports() { |
|
1408 return iExports; |
|
1409 } |
|
1410 |
|
1411 /** |
|
1412 Function to get fixup location |
|
1413 @param aReloc - Instance of class ElfLocalRelocation |
|
1414 @param aPlace - |
|
1415 @return addres of position for relocation |
|
1416 @internalComponent |
|
1417 @released |
|
1418 */ |
|
1419 Elf32_Word* ElfExecutable::GetFixupLocation(ElfLocalRelocation* aReloc, Elf32_Addr aPlace) |
|
1420 { |
|
1421 Elf32_Phdr * aPhdr = aReloc->ExportTableReloc() ? |
|
1422 iCodeSegmentHdr : |
|
1423 Segment(aPlace); |
|
1424 Elf32_Word offset = aPhdr->p_offset + aPlace - aPhdr->p_vaddr; |
|
1425 return ELF_ENTRY_PTR(Elf32_Word, iElfHeader, offset); |
|
1426 } |
|
1427 |
|
1428 /** |
|
1429 Function to get the segment type |
|
1430 @param aSym - Symbol |
|
1431 @return Segment type |
|
1432 @internalComponent |
|
1433 @released |
|
1434 */ |
|
1435 ESegmentType ElfExecutable::Segment(Elf32_Sym *aSym) |
|
1436 { |
|
1437 Elf32_Phdr * aHdr; |
|
1438 |
|
1439 try { |
|
1440 |
|
1441 bool limitSymbolFound = false; |
|
1442 |
|
1443 // If Symbol is absolute then assume it came from linker and is a |
|
1444 // limit symbol. |
|
1445 if (aSym->st_shndx == SHN_ABS) |
|
1446 { |
|
1447 aHdr = SegmentFromAbs(aSym->st_value); |
|
1448 } |
|
1449 else |
|
1450 { |
|
1451 if( (iCodeSegmentHdr && aSym->st_value == (iCodeSegmentHdr->p_vaddr + iCodeSegmentHdr->p_memsz)) || |
|
1452 (iDataSegmentHdr && aSym->st_value == (iDataSegmentHdr->p_vaddr + iDataSegmentHdr->p_memsz)) ) |
|
1453 { |
|
1454 //If Symbol is a $$Limit symbol, then consider the open boundary. |
|
1455 String limitstr = iStringTable + aSym->st_name; |
|
1456 if (limitstr.rfind("$$Limit",limitstr.length()) != String::npos) |
|
1457 { |
|
1458 aHdr = SegmentFromAbs(aSym->st_value); |
|
1459 limitSymbolFound = true; |
|
1460 } |
|
1461 } |
|
1462 |
|
1463 if(!limitSymbolFound ) |
|
1464 { |
|
1465 aHdr = Segment(aSym->st_value); |
|
1466 } |
|
1467 |
|
1468 } |
|
1469 |
|
1470 if (aHdr == iCodeSegmentHdr) |
|
1471 { |
|
1472 return ESegmentRO; |
|
1473 } |
|
1474 else if (aHdr == iDataSegmentHdr) |
|
1475 { |
|
1476 return ESegmentRW; |
|
1477 } |
|
1478 } |
|
1479 catch(...) |
|
1480 { |
|
1481 } |
|
1482 return ESegmentUndefined; |
|
1483 } |
|
1484 |