--- a/toolsandutils/e32tools/elf2e32/source/pl_elfexecutable.cpp Fri Jun 25 18:24:47 2010 +0100
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,1484 +0,0 @@
-// Copyright (c) 2004-2009 Nokia Corporation and/or its subsidiary(-ies).
-// All rights reserved.
-// This component and the accompanying materials are made available
-// under the terms of "Eclipse Public License v1.0"
-// which accompanies this distribution, and is available
-// at the URL "http://www.eclipse.org/legal/epl-v10.html".
-//
-// Initial Contributors:
-// Nokia Corporation - initial contribution.
-//
-// Contributors:
-//
-// Description:
-// Implementation of the Class ElfExecutable for the elf2e32 tool
-// @internalComponent
-// @released
-//
-//
-
-
-#include "pl_elfexecutable.h"
-#include "errorhandler.h"
-#include <stdio.h>
-#include "parameterlistinterface.h"
-#include "pl_elfimportrelocation.h"
-#include "pl_dllsymbol.h"
-#include "messagehandler.h"
-#include "pl_elflocalrelocation.h"
-
-
-/**
-Constructor for class ElfExecutable
-@param aParameterListInterface - Instance of class ParameterListInterface
-@internalComponent
-@released
-*/
-ElfExecutable::ElfExecutable(ParameterListInterface *aParameterListInterface) :\
- iElfHeader(NULL), \
- iEntryPoint(0),\
- iProgHeader(NULL), \
- iSONameOffset(0) ,\
- iSections (NULL) , \
- iVersionDef (NULL) , iVerDefCount(0), \
- iVersionNeed (NULL) , iVerNeedCount(0), \
- iVersionTbl (NULL) ,iRelSize(0),iRelEntSize(0), \
- iNRelocs(0),
- iRel (NULL) ,iRelaSize(0), iRelaEntSize(0), \
- iRela(NULL),
- iStringTable (NULL) , \
- iSectionHdrStrTbl(NULL), \
- iVerInfo(NULL), iElfDynSym (NULL), \
- iSymTab (NULL), \
- iStrTab (NULL), \
- iLim (NULL), \
- iNSymbols(0), \
- iHashTbl (NULL) , \
- iDynSegmentHdr (NULL) , \
- iDataSegmentHdr (NULL) ,iDataSegment(NULL), iDataSegmentSize(0), iDataSegmentIdx(0), \
- iCodeSegmentHdr (NULL) , iCodeSegment(NULL), iCodeSegmentSize(0), iCodeSegmentIdx(0), \
- iExports (NULL), \
- iParameterListInterface(aParameterListInterface),\
- iPltGotBase(0), iPltGotLimit(0), iStrTabSz(0), iSymEntSz(0), \
- iPltGot(NULL), iPltRel(NULL),iPltRelaSz(0), iPltRela(NULL), iPltRelSz(0) \
-
-{
-}
-
-
-/**
-Destructor for class ElfExecutable
-@internalComponent
-@released
-*/
-ElfExecutable::~ElfExecutable()
-{
- delete iExports;
- delete [] iVerInfo;
- /*
- all of these were getting deleted, they are not allocated by
- ElfExecutable, they simply refer to a linear array of images
- in an ElfImage, hence they shouldn't be de-allocated
-
- delete iRela;
- delete iPltRel;
- delete iPltRela; */
-
- iNeeded.clear();
- iSymbolTable.clear();
-}
-
-
-/**
-Function to process Elf file
-@param aElfHdr - pointer to Elf header
-@return 0 if its valid ELF file
-@internalComponent
-@released
-*/
-PLUINT32 ElfExecutable::ProcessElfFile(Elf32_Ehdr *aElfHdr) {
-
- iElfHeader = aElfHdr;
- iEntryPoint = aElfHdr->e_entry;
-
- ValidateElfFile();
-
- /* A valid ELF file so far..*/
-
- /* Get the Section base..*/
- if(iElfHeader->e_shnum) {
- iSections = ELF_ENTRY_PTR(Elf32_Shdr, iElfHeader, iElfHeader->e_shoff);
- }
-
- /* Get the program header..*/
- if(iElfHeader->e_phnum) {
- iProgHeader = ELF_ENTRY_PTR(Elf32_Phdr, iElfHeader, iElfHeader->e_phoff);
- }
-
- /* Get the section-header-string table..*/
- if(iElfHeader->e_shstrndx != SHN_UNDEF) {
-
- if(iElfHeader->e_shstrndx > iElfHeader->e_shnum ) {
- throw ELFFormatError(ELFSHSTRINDEXERROR,iParameterListInterface->ElfInput());
- }
-
- iSectionHdrStrTbl = ELF_ENTRY_PTR(char, iElfHeader, iSections[iElfHeader->e_shstrndx].sh_offset);
- }
-
- if( iProgHeader ) {
- PLUINT32 aIdx = 0;
-
- while( aIdx < iElfHeader->e_phnum) {
- switch( iProgHeader[aIdx].p_type ) {
- case PT_DYNAMIC:
- {
- iDynSegmentHdr = &iProgHeader[aIdx];
- }
- break;
- case PT_LOAD:
- {
- if( (iProgHeader[aIdx].p_flags) & (PF_X | PF_ARM_ENTRY) ) {
- iCodeSegmentHdr = &iProgHeader[aIdx];
- iCodeSegmentIdx = aIdx;
- iCodeSegment = ELF_ENTRY_PTR(char, iElfHeader, iCodeSegmentHdr->p_offset);
- iCodeSegmentSize = iCodeSegmentHdr->p_filesz;
- }
- else if( (iProgHeader[aIdx].p_flags) & (PF_W | PF_R) ) {
- iDataSegmentHdr = &iProgHeader[aIdx];
- iDataSegmentIdx = aIdx;
- iDataSegment = ELF_ENTRY_PTR(char, iElfHeader, iDataSegmentHdr->p_offset);
- iDataSegmentSize = iDataSegmentHdr->p_filesz;
- }
- }
- break;
- default:
- break;
-
- }
- aIdx++;
- }
-
- if( iDynSegmentHdr ) {
- ProcessDynamicEntries();
- }
-
- ProcessSymbols();
- ProcessRelocations();
- }
-
- return 0;
-}
-
-/**
-Function to Find the Static Symbol Table
-@internalComponent
-@released
-*/
-void ElfExecutable::FindStaticSymbolTable()
-{
- size_t nShdrs = iElfHeader->e_shnum;
-
- if (nShdrs)
- {
- // Find the static symbol table and string table
- for (PLUINT32 i = 0; i < nShdrs; i++)
- {
- if (iSections[i].sh_type == SHT_SYMTAB)
- {
- iSymTab = ELF_ENTRY_PTR(Elf32_Sym, iElfHeader, iSections[i].sh_offset);
- iLim = ELF_ENTRY_PTR(Elf32_Sym, iSymTab, iSections[i].sh_size);
- if (iStrTab) break;
- }
- else if (iSections[i].sh_type == SHT_STRTAB)
- {
- char * aSectionName = iSectionHdrStrTbl + iSections[i].sh_name;
- if (!strcmp(aSectionName, ".strtab"))
- {
- iStrTab = ELF_ENTRY_PTR(char, iElfHeader, iSections[i].sh_offset);
- if (iSymTab) break;
- }
- }
- }
- }
-}
-
-/**
-Function to Find the Comment Section
-@return aComment - Pointer to Comment Section
-@internalComponent
-@released
-*/
-char* ElfExecutable::FindCommentSection()
-{
- size_t nShdrs = iElfHeader->e_shnum;
- char *aCommentSection = ".comment";
- char *aComment;
-
- if (nShdrs)
- {
- // find the comment section
- for (PLUINT32 i = 0; i < nShdrs; i++)
- {
- if (iSections[i].sh_type == SHT_PROGBITS)
- {
- char * aSectionName = iSectionHdrStrTbl + iSections[i].sh_name;
- int length = strlen(aCommentSection);
- if (!strncmp(aSectionName, aCommentSection, length))
- {
- aComment = ELF_ENTRY_PTR(char, iElfHeader, iSections[i].sh_offset);
- return aComment;
- }
- }
- }
- }
- return NULL;
-}
-
-/**
-Function to process the ARM to Thumb veneers
-@internalComponent
-@released
-*/
-void ElfExecutable::ProcessVeneers()
-{
- if (iSymTab && iStrTab)
- {
- ElfRelocations::RelocationList & iLocalCodeRelocs = GetCodeRelocations();
-
- Elf32_Sym *aSymTab = iSymTab;
- int length = strlen("$Ven$AT$L$$");
-
- // Process the symbol table to find Long ARM to Thumb Veneers
- // i.e. symbols of the form '$Ven$AT$L$$'
- for(; aSymTab < iLim; aSymTab++)
- {
- if (!aSymTab->st_name) continue;
- char * aSymName = iStrTab + aSymTab->st_name;
- Elf32_Sym *aSym;
-
- if (!strncmp(aSymName, "$Ven$AT$L$$", length))
- {
- aSym = aSymTab;
- Elf32_Addr r_offset = aSym->st_value;
- Elf32_Addr aOffset = r_offset + 4;
- Elf32_Word aInstruction = FindValueAtLoc(r_offset);
- bool aRelocEntryFound = false;
-
- ElfRelocations::RelocationList::iterator r;
- for (r = iLocalCodeRelocs.begin(); r != iLocalCodeRelocs.end(); r++)
- {
- ElfLocalRelocation * aReloc = *r;
- // Check if there is a relocation entry for the veneer symbol
- if (aReloc->iAddr == aOffset)
- {
- aRelocEntryFound = true;
- break;
- }
- }
-
- Elf32_Word aPointer = FindValueAtLoc(aOffset);
-
- /* If the symbol addresses a Thumb instruction, its value is the
- * address of the instruction with bit zero set (in a
- * relocatable object, the section offset with bit zero set).
- * This allows a linker to distinguish ARM and Thumb code symbols
- * without having to refer to the map. An ARM symbol will always have
- * an even value, while a Thumb symbol will always have an odd value.
- * Reference: Section 4.5.3 in Elf for the ARM Architecture Doc
- * aIsThumbSymbol will be 1 for a thumb symbol and 0 for ARM symbol
- */
- int aIsThumbSymbol = aPointer & 0x1;
-
- /* The relocation entry should be generated for the veneer only if
- * the following three conditions are satisfied:
- * 1) Check if the instruction at the symbol is as expected
- * i.e. has the bit pattern 0xe51ff004 == 'LDR pc,[pc,#-4]'
- * 2) There is no relocation entry generated for the veneer symbol
- * 3) The instruction in the location provided by the pointer is a thumb symbol
- */
- if (aInstruction == 0xE51FF004 && !aRelocEntryFound && aIsThumbSymbol)
- {
- ElfLocalRelocation *aRel;
- PLUCHAR aType = R_ARM_NONE;
-
- aRel = new ElfLocalRelocation(this, aOffset, 0, 0, aType, NULL, ESegmentRO, aSym, false, true);
- if(aRel)
- {
- aRel->Add();
- }
- }
- }
- }
- }
-}
-
-/**
-Function to find the content of the address passed in
-@param aOffset - Address
-@return aLocVal - The content of the address, like instruction or a pointer
-@internalComponent
-@released
-*/
-Elf32_Word ElfExecutable::FindValueAtLoc(Elf32_Addr aOffset)
-{
- Elf32_Phdr *aHdr = Segment(aOffset);
- PLUINT32 aLoc = aHdr->p_offset + aOffset - aHdr->p_vaddr;
- Elf32_Word *aLocVal = ELF_ENTRY_PTR(Elf32_Word, iElfHeader, aLoc);
- return *aLocVal;
-}
-
-/**
-Function to process Elf symbols
-@internalComponent
-@released
-*/
-PLUINT32 ElfExecutable::ProcessSymbols(){
- PLUINT32 aSymIdx = 0;
- DllSymbol *aSymbol;
- char *aDllName;
- char *aSymName, *aNewSymName;
- SymbolType aType;
-
- while( aSymIdx < iNSymbols ) {
-
- aSymName = ELF_ENTRY_PTR(char, iStringTable, iElfDynSym[aSymIdx].st_name );
-
- if( ExportedSymbol( &iElfDynSym[aSymIdx] ) ){
-
- if( FunctionSymbol( &iElfDynSym[aSymIdx] ))
- aType = SymbolTypeCode;
- else
- aType = SymbolTypeData;
-
- aSymName = ELF_ENTRY_PTR(char, iStringTable, iElfDynSym[aSymIdx].st_name );
- aDllName = iVerInfo[iVersionTbl[aSymIdx]].iLinkAs;
- aNewSymName = new char[strlen(aSymName)+1];
- strcpy(aNewSymName, aSymName);
- aSymbol = new DllSymbol( aNewSymName, aType, &iElfDynSym[aSymIdx], aSymIdx);
- aSymbol->SetSymbolSize(iElfDynSym[aSymIdx].st_size);
-
- //Putting the symbols into a hash table - Used later while processing relocations
- iSymbolTable[aSymIdx] = aSymbol ;
- if( !AddToExports( aDllName, aSymbol ))
- {
- //Not a valid export... delete it..
- delete aSymbol;
- }
- }
- else if( ImportedSymbol( &iElfDynSym[aSymIdx] ) ){
-
- if( FunctionSymbol( &iElfDynSym[aSymIdx] ))
- aType = SymbolTypeCode;
- else
- aType = SymbolTypeData;
-
- aSymName = ELF_ENTRY_PTR(char, iStringTable, iElfDynSym[aSymIdx].st_name );
-
- /*
- * All imported symbols must be informed via the version needed information.
- */
- if( iVerInfo[iVersionTbl[aSymIdx]].iVerCategory != VER_CAT_NEEDED ) {
- throw UndefinedSymbolError(UNDEFINEDSYMBOLERROR, iParameterListInterface->ElfInput(), aSymName);
- }
- aDllName = iVerInfo[iVersionTbl[aSymIdx]].iLinkAs;
- //aSymbol = new DllSymbol( aSymName, aType, &iElfDynSym[aSymIdx], aSymIdx);
-
- //Putting the symbols into a hash table
- //iSymbolTable[aSymIdx] = aSymbol ;
- }
- aSymIdx++;
- }
-
- return 0;
-}
-
-/**
-This function Dump all the sections with their section details (i.e., the section name, type,
-size and linked section if any)
-@param aFile - ELF file name
-@internalComponent
-@released
-*/
-void ElfExecutable::DumpElfFile(char* aFile){
- aFile = aFile;
-}
-
-
-/**
-This function adds exports into the export list
-@param aDll - Dll name
-@param aSymbol - Symbol
-@return
-@internalComponent
-@released
-*/
-DllSymbol* ElfExecutable::AddToExports(char* aDll, DllSymbol* aSymbol){
- if( !iExports ) {
- iExports = new ElfExports();
- }
- return iExports->Add( aDll, this, aSymbol );
-}
-
-
-/**
-This function adds imports into the map
-@param aReloc - Instance of class ElfImportRelocation
-@internalComponent
-@released
-*/
-void ElfExecutable::AddToImports(ElfImportRelocation* aReloc){
- SetVersionRecord(aReloc);
- //char *aDll = iVerInfo[iVersionTbl[aReloc->iSymNdx]].iLinkAs;
- char *aDll = aReloc->iVerRecord->iLinkAs;
- iImports.Add( (const char*)aDll, aReloc );
-
-}
-
-/**
-This function adds local relocation into a list
-@param aReloc - Instance of class ElfImportRelocation
-@internalComponent
-@released
-*/
-void ElfExecutable::AddToLocalRelocations(ElfRelocation* aReloc) {
- iLocalRelocations.Add((ElfLocalRelocation*)aReloc);
-}
-
-/**
-This function records the version of an imported symbol
-@param aReloc - Instance of class ElfImportRelocation
-@internalComponent
-@released
-*/
-void ElfExecutable::SetVersionRecord( ElfRelocation* aReloc ) {
- if( !aReloc )
- return;
- ((ElfImportRelocation*)aReloc)->iVerRecord = &iVerInfo[ iVersionTbl[aReloc->iSymNdx]];
-}
-
-/**
-This function validates the ELF file
-@internalComponent
-@released
-*/
-PLUINT32 ElfExecutable::ValidateElfFile() {
-
- /*Check if the ELF-Magic is correct*/
- if(!(iElfHeader->e_ident[EI_MAG0] == ELFMAG0) &&
- (iElfHeader->e_ident[EI_MAG1] == ELFMAG1) &&
- (iElfHeader->e_ident[EI_MAG2] == ELFMAG2) &&
- (iElfHeader->e_ident[EI_MAG3] == ELFMAG3) ) {
- throw ELFFormatError(ELFMAGICERROR, iParameterListInterface->ElfInput());
- }
-
- /*32-bit ELF file*/
- if(iElfHeader->e_ident[EI_CLASS] != ELFCLASS32) {
- throw ELFFormatError(ELFCLASSERROR, iParameterListInterface->ElfInput());
- }
-
- /* Check if the ELF file is in Little endian format*/
- if(iElfHeader->e_ident[EI_DATA] != ELFDATA2LSB) {
- throw ELFFormatError(ELFLEERROR, iParameterListInterface->ElfInput());
- }
-
- /* The ELF executable must be a DLL or an EXE*/
- if( iElfHeader->e_type != ET_EXEC && iElfHeader->e_type != ET_DYN) {
- throw ELFFormatError(ELFEXECUTABLEERROR, iParameterListInterface->ElfInput());
- }
-
- return 0;
-}
-
-
-/**
-This function processes the dynamic table.
-@internalComponent
-@released
-*/
-PLUINT32 ElfExecutable::ProcessDynamicEntries(){
-
- PLUINT32 aIdx = 0;
- bool aSONameFound = false;
- bool aPltRelTypeSeen = false, aJmpRelSeen = false;
- list<PLUINT32> aNeeded;
- Elf32_Dyn *aDyn = ELF_ENTRY_PTR(Elf32_Dyn, iElfHeader, iDynSegmentHdr->p_offset);
-
- while( aDyn[aIdx].d_tag != DT_NULL ) {
- switch (aDyn[aIdx].d_tag) {
- case DT_NEEDED:
- aNeeded.push_back( aDyn[aIdx].d_val );
- break;
- case DT_HASH:
- iHashTbl = ELF_ENTRY_PTR(Elf32_HashTable, iElfHeader, aDyn[aIdx].d_val);
- break;
- case DT_STRTAB:
- iStringTable = ELF_ENTRY_PTR(char, iElfHeader, aDyn[aIdx].d_val);
- break;
- case DT_SYMTAB:
- iElfDynSym = ELF_ENTRY_PTR(Elf32_Sym, iElfHeader, aDyn[aIdx].d_val);
- break;
- case DT_RELA:
- iRela = ELF_ENTRY_PTR(Elf32_Rela, iElfHeader, aDyn[aIdx].d_val);
- break;
- case DT_RELASZ:
- iRelaSize = aDyn[aIdx].d_val;
- break;
- case DT_RELAENT:
- iRelaEntSize = aDyn[aIdx].d_val;
- break;
- case DT_SONAME:
- aSONameFound = true;
- iSONameOffset = aDyn[aIdx].d_val;
- break;
- case DT_REL:
- iRel = ELF_ENTRY_PTR(Elf32_Rel, iElfHeader, aDyn[aIdx].d_val);
- break;
- case DT_RELSZ:
- iRelSize = aDyn[aIdx].d_val;
- break;
- case DT_RELENT:
- iRelEntSize = aDyn[aIdx].d_val;
- break;
- case DT_VERSYM:
- iVersionTbl = ELF_ENTRY_PTR(Elf32_Half, iElfHeader, aDyn[aIdx].d_val);
- break;
- case DT_VERDEF:
- iVersionDef = ELF_ENTRY_PTR(Elf32_Verdef, iElfHeader, aDyn[aIdx].d_val);
- break;
- case DT_VERDEFNUM:
- iVerDefCount = aDyn[aIdx].d_val;
- break;
- case DT_VERNEED:
- iVersionNeed = ELF_ENTRY_PTR(Elf32_Verneed, iElfHeader, aDyn[aIdx].d_val);
- break;
- case DT_VERNEEDNUM:
- iVerNeedCount = aDyn[aIdx].d_val;
- break;
- case DT_STRSZ:
- iStrTabSz = aDyn[aIdx].d_val;
- break;
- case DT_SYMENT:
- iSymEntSz = aDyn[aIdx].d_val;
- break;
- case DT_PLTRELSZ:
- iPltRelSz = aDyn[aIdx].d_val;
- break;
- case DT_PLTGOT:
- iPltGot = ELF_ENTRY_PTR(Elf32_Word, iElfHeader, aDyn[aIdx].d_val);
- break;
- case DT_RPATH:
- break;
- case DT_SYMBOLIC:
- break;
- case DT_INIT:
- break;
- case DT_FINI:
- break;
- case DT_PLTREL:
- aPltRelTypeSeen = true;
- iPltRelType = aDyn[aIdx].d_val;
- break;
- case DT_DEBUG:
- break;
- case DT_TEXTREL:
- break;
- case DT_JMPREL:
- aJmpRelSeen = true;
- iJmpRelOffset = aDyn[aIdx].d_val;
- break;
- case DT_BIND_NOW:
- break;
- case DT_INIT_ARRAY:
- break;
- case DT_FINI_ARRAY:
- break;
- case DT_INIT_ARRAYSZ:
- break;
- case DT_FINI_ARRAYSZ:
- break;
- case DT_RELCOUNT:
- break;
- case DT_ARM_PLTGOTBASE:
- iPltGotBase = aDyn[aIdx].d_val;
- break;
- case DT_ARM_PLTGOTLIMIT:
- iPltGotLimit = aDyn[aIdx].d_val;
- break;
- case DT_ARM_SYMTABSZ:
- iNSymbols = aDyn[aIdx].d_val;
- break;
- default:
- //cout << "Unknown entry in dynamic table Tag=0x%x Value=0x%x",aDyn[aIdx].d_tag, aDyn[aIdx].d_val);
- break;
- }
- aIdx++;
- }
-
- //String table is found, so get the strings...
- if(aSONameFound) {
- iSOName = ELF_ENTRY_PTR(char, iStringTable, iSONameOffset);
- }
-
- std::list<PLUINT32>::iterator aItr = aNeeded.begin();
- char *aStr;
- for( ; aItr != aNeeded.end();aItr++ ) {
- aStr = ELF_ENTRY_PTR(char, iStringTable, *aItr);
- iNeeded.push_back( aStr );
- }
-
- if(iVerNeedCount || iVerDefCount) {
- ProcessVerInfo();
- }
-
- if(iHashTbl)
- {
- //The number of symbols should be same as the number of chains in hashtable
- if (iNSymbols && (iNSymbols != iHashTbl->nChains))
- throw ELFFormatError(SYMBOLCOUNTMISMATCHERROR,(char*)iParameterListInterface->ElfInput());
- else
- //The number of symbols is same as the number of chains in hashtable
- iNSymbols = iHashTbl->nChains;
- }
-
- if( aPltRelTypeSeen && aJmpRelSeen) {
-
- if (iPltRelType == DT_REL)
- {
- iPltRel = ELF_ENTRY_PTR(Elf32_Rel, iElfHeader, iJmpRelOffset);
- // check to see if PltRels are included in iRel. If they are
- // ignore them since we don't care about the distinction
- if (iRel <= iPltRel && iPltRel < ELF_ENTRY_PTR(Elf32_Rel, iRel, iRelSize))
- iPltRel = 0;
- }
- else
- {
- iPltRela = ELF_ENTRY_PTR(Elf32_Rela, iElfHeader, iJmpRelOffset);
- // check to see if PltRels are included in iRel. If they are
- // ignore them since we don't care about the distinction
- if (iRela <= iPltRela && iPltRela < ELF_ENTRY_PTR(Elf32_Rela, iRela, iRelaSize))
- iPltRela = 0;
- }
- }
-
- return 0;
-}
-
-/**
-This function processes version information
-@internalComponent
-@released
-*/
-void ElfExecutable::ProcessVerInfo() {
- PLUINT32 aSz = iVerNeedCount + iVerDefCount + 1;
- iVerInfo = new VersionInfo[aSz];
-
- Elf32_Verdef *aDef;
- Elf32_Verdaux *aDaux;
- Elf32_Verneed *aNeed;
- Elf32_Vernaux *aNaux;
- char *aSoName;
- char *aLinkAs;
-
- aDef = iVersionDef;
-
- while( aDef ) {
- aDaux = ELF_ENTRY_PTR( Elf32_Verdaux, aDef, aDef->vd_aux);
- aLinkAs = ELF_ENTRY_PTR(char, iStringTable, aDaux->vda_name );
- aSoName = iSOName;
- iVerInfo[aDef->vd_ndx].iLinkAs = aLinkAs;
- iVerInfo[aDef->vd_ndx].iSOName = aSoName;
- iVerInfo[aDef->vd_ndx].iVerCategory = VER_CAT_DEFINED;
-
- if( !aDef->vd_next ) {
- break;
- }
- aDef = ELF_ENTRY_PTR(Elf32_Verdef, aDef, aDef->vd_next);
- }
-
- aNeed = iVersionNeed;
-
- while( aNeed ) {
- aNaux = ELF_ENTRY_PTR(Elf32_Vernaux, aNeed, aNeed->vn_aux);
- aLinkAs = ELF_ENTRY_PTR(char, iStringTable, aNaux->vna_name);
- aSoName = ELF_ENTRY_PTR(char, iStringTable, aNeed->vn_file);
-
- iVerInfo[aNaux->vna_other].iLinkAs = aLinkAs;
- iVerInfo[aNaux->vna_other].iSOName = aSoName;
- iVerInfo[aNaux->vna_other].iVerCategory = VER_CAT_NEEDED;
-
- if( !aNeed->vn_next ) {
- break;
- }
- aNeed = ELF_ENTRY_PTR(Elf32_Verneed, aNeed, aNeed->vn_next);
- }
-}
-
-/**
-This function processes Elf relocations
-@internalComponent
-@released
-*/
-void ElfExecutable::ProcessRelocations(){
- ProcessRelocations(iRel, iRelSize);
- ProcessRelocations(iRela, iRelaSize);
- ProcessRelocations(iPltRel, iPltRelSz);
- ProcessRelocations(iPltRela, iPltRelaSz);
-}
-
-/**
-Template Function to process relocations
-@param aElfRel - relocation table
-@param aSize - relocation table size
-@internalComponent
-@released
-*/
-template <class T>
-void ElfExecutable::ProcessRelocations(T *aElfRel, size_t aSize){
- if( !aElfRel )
- return;
-
- T * aElfRelLimit = ELF_ENTRY_PTR(T, aElfRel, aSize);
-
- PLUINT32 aSymIdx;
- PLUCHAR aType;
- ElfRelocation *aRel;
- bool aImported;
- Elf32_Word aAddend;
-
- while( aElfRel < aElfRelLimit) {
-
- aType = ELF32_R_TYPE(aElfRel->r_info );
-
- if(ElfRelocation::ValidRelocEntry(aType)) {
-
- aSymIdx = ELF32_R_SYM(aElfRel->r_info);
- aImported = ImportedSymbol( &iElfDynSym[aSymIdx] );
- aAddend = Addend(aElfRel);
- aRel = ElfRelocation::NewRelocEntry(this, aElfRel->r_offset, aAddend, \
- aSymIdx, aType, aElfRel, aImported);
-
- if(aRel) {
- aRel->Add();
- }
- }
- aElfRel++;
- }
-}
-
-/**
-This function finds the addend associated with a relocation entry.
-@param aRel - relocation entry
-@return location in the elf image
-@internalComponent
-@released
-*/
-Elf32_Word ElfExecutable::Addend(Elf32_Rel* aRel) {
- PLUINT32 aOffset;
- Elf32_Word *aAddendPlace;
- Elf32_Phdr *aHdr = Segment(aRel->r_offset);
- aOffset = aHdr->p_offset + aRel->r_offset - aHdr->p_vaddr;
- aAddendPlace = ELF_ENTRY_PTR(Elf32_Word, iElfHeader, aOffset);
- return *aAddendPlace;
-}
-
-/**
-This function returns the addend for a relocation entry
-@param aRel - relocation entry
-@return location in the elf image
-@internalComponent
-@released
-*/
-Elf32_Word ElfExecutable::Addend(Elf32_Rela* aRel) {
- return aRel->r_addend;
-}
-
-/**
-This function gets the version info at an index
-@param aIndex - index into the version table
-@return version record
-@internalComponent
-@released
-*/
-VersionInfo* ElfExecutable::GetVersionInfo(PLUINT32 aIndex){
- return &iVerInfo[ iVersionTbl[aIndex]];
-}
-
-
-/**
-This function returns the Dll name in which an imported symbol is
-defined by looking in the version required section.
-@param aSymbolIndex - Index of symbol
-@return Dll name
-@internalComponent
-@released
-*/
-char* ElfExecutable::SymbolDefinedInDll(PLUINT32 aSymbolIndex){
-
- VersionInfo *aVInfo = GetVersionInfo(aSymbolIndex);
- return aVInfo ? aVInfo->iLinkAs : NULL;
-}
-
-/**
-This function returns the DSO(import library) name where the Symbol information can be found.
-This DSO is then looked up for the ordinal number of this symbol.
-@param aSymbolIndex - Index of symbol
-@return DSO name
-@internalComponent
-@released
-*/
-char* ElfExecutable::SymbolFromDSO(PLUINT32 aSymbolIndex){
-
- VersionInfo *aVInfo = GetVersionInfo(aSymbolIndex);
- return aVInfo ? aVInfo->iSOName : NULL;
-}
-
-/**
-This function returns the segment type
-@param aAddr - Address
-@return Segment type
-@internalComponent
-@released
-*/
-ESegmentType ElfExecutable::SegmentType(Elf32_Addr aAddr) {
-
- try {
- Elf32_Phdr *aHdr = Segment(aAddr);
- if( !aHdr )
- return ESegmentUndefined;
-
- if( aHdr == iCodeSegmentHdr)
- return ESegmentRO;
- else if(aHdr == iDataSegmentHdr)
- return ESegmentRW;
- else
- return ESegmentUndefined;
- }
- catch(...)
- {
- }
-
- return ESegmentUndefined;
-}
-
-/**
-This function returns the segment type
-@param aType
-@return Segment header
-@internalComponent
-@released
-*/
-Elf32_Phdr* ElfExecutable::Segment(ESegmentType aType) {
-
- switch(aType)
- {
- case ESegmentRO:
- return iCodeSegmentHdr;
- case ESegmentRW:
- return iDataSegmentHdr;
- default:
- return NULL;
- }
-}
-
-/**
-Function to get segment header
-@param aAddr - Address
-@return Segment header
-@internalComponent
-@released
-*/
-Elf32_Phdr* ElfExecutable::Segment(Elf32_Addr aAddr) {
-
- if(iCodeSegmentHdr) {
- PLUINT32 aBase = iCodeSegmentHdr->p_vaddr;
- if( aBase <= aAddr && aAddr < (aBase + iCodeSegmentHdr->p_memsz) ) {
- return iCodeSegmentHdr;
- }
- }
- if(iDataSegmentHdr) {
- PLUINT32 aBase = iDataSegmentHdr->p_vaddr;
- if( aBase <= aAddr && aAddr < (aBase + iDataSegmentHdr->p_memsz) ) {
- return iDataSegmentHdr;
- }
- }
-
- throw int(0);
-}
-
-/**
-Thsi function returns the segment header to which the address refers.
-@param aAddr - location
-@return Segment header.
-@internalComponent
-@released
-*/
-Elf32_Phdr* ElfExecutable::SegmentFromAbs(Elf32_Addr aAddr) {
-
- if(iCodeSegmentHdr) {
- PLUINT32 aBase = iCodeSegmentHdr->p_vaddr;
- if( aBase <= aAddr && aAddr <= (aBase + iCodeSegmentHdr->p_memsz) ) {
- return iCodeSegmentHdr;
- }
- }
- if(iDataSegmentHdr) {
- PLUINT32 aBase = iDataSegmentHdr->p_vaddr;
- if( aBase <= aAddr && aAddr <= (aBase + iDataSegmentHdr->p_memsz) ) {
- return iDataSegmentHdr;
- }
- }
- return NULL;
-}
-
-/**
-This function says if the symbol is global.
-@param aSym - Symbol
-@return True if symbol is global, otherwise false
-@internalComponent
-@released
-*/
-bool ElfExecutable::GlobalSymbol(Elf32_Sym* aSym)
-{
- return (ELF32_ST_BIND(aSym->st_info) == STB_GLOBAL);
-}
-
-/**
-This function says if the symbol is exported.
-@param aSym - Symbol
-@return True if symbol is exported, otherwise false
-@internalComponent
-@released
-*/
-bool ElfExecutable::ExportedSymbol(Elf32_Sym* aSym)
-{
- PLUINT32 aIdx = aSym->st_shndx;
-
- if(GlobalSymbol(aSym) && VisibleSymbol(aSym) && DefinedSymbol(aSym) && \
- (aIdx != SHN_UNDEF) && (FunctionSymbol(aSym) || DataSymbol(aSym) ) && aIdx < SHN_ABS )
- return true;
- return false;
-}
-
-/**
-This function says if the symbol is imported.
-@param aSym - Symbol
-@return True if symbol is imported, otherwise false
-@internalComponent
-@released
-*/
-bool ElfExecutable::ImportedSymbol(Elf32_Sym* aSym)
-{
- PLUINT32 aIdx = aSym->st_shndx;
-
- if( (aIdx == SHN_UNDEF) && GlobalSymbol(aSym) && VisibleSymbol(aSym) && (!DefinedSymbol(aSym)) )
- return true;
- return false;
-}
-
-/**
-This function says if the symbol refers to code or data.
-@param aSym - Symbol
-@return True if symbol refers to code, otherwise false
-@internalComponent
-@released
-*/
-bool ElfExecutable::FunctionSymbol(Elf32_Sym* aSym)
-{
- return (STT_FUNC == ELF32_ST_TYPE(aSym->st_info));
-}
-
-/**
-This function says if the symbol refers to code or data.
-@param aSym - Symbol
-@return True if symbol refers to data, otherwise false
-@internalComponent
-@released
-*/
-bool ElfExecutable::DataSymbol(Elf32_Sym* aSym)
-{
- return (STT_OBJECT == ELF32_ST_TYPE(aSym->st_info));
-}
-
-/**
-This function says if the symbol is defined in the Elf executable.
-@param aSym - Symbol
-@return True if symbol is defined, otherwise false
-@internalComponent
-@released
-*/
-bool ElfExecutable::DefinedSymbol(Elf32_Sym* aSym)
-{
- if( aSym->st_shndx == SHN_UNDEF )
- return false;
- ESegmentType aType = SegmentType(aSym->st_value);
- return ((aType == ESegmentRO) || (aType == ESegmentRW));
-}
-
-/**
-This function says if the visibility of the symbol is default.
-@param aSym - Symbol
-@return True if symbol has default visibility, otherwise false
-@internalComponent
-@released
-*/
-bool ElfExecutable::VisibleSymbol(Elf32_Sym* aSym)
-{
- return (STV_DEFAULT == ELF32_ST_VISIBILITY(aSym->st_other) || STV_PROTECTED == ELF32_ST_VISIBILITY(aSym->st_other));
-}
-
-/**
-This function finds symbol using the hash table
-@param aName - Symbol name
-@return elf symbol.
-@internalComponent
-@released
-*/
-Elf32_Sym* ElfExecutable::FindSymbol(char* aName) {
- if(!aName )
- return NULL;
-
- PLULONG aHashVal = Util::elf_hash((const PLUCHAR*) aName );
-
- Elf32_Sword* aBuckets = ELF_ENTRY_PTR(Elf32_Sword, iHashTbl, sizeof(Elf32_HashTable) );
- Elf32_Sword* aChains = ELF_ENTRY_PTR(Elf32_Sword, aBuckets, sizeof(Elf32_Sword)*(iHashTbl->nBuckets) );
-
- Elf32_Sword aIdx = aHashVal % iHashTbl->nBuckets;
- aIdx = aBuckets[aIdx];
-
- char *aSymName;
- do {
- aSymName = ELF_ENTRY_PTR(char, iStringTable, iElfDynSym[aIdx].st_name);
- if( !strcmp(aSymName, aName) ) {
- return &iElfDynSym[aIdx];
- }
- aIdx = aChains[aIdx];
- }while( aIdx > 0 );
-
- return NULL;
-}
-
-/**
-Function to get symbol name
-@param aSymIdx - Index of symbol
-@return Symbol name
-@internalComponent
-@released
-*/
-char* ElfExecutable::GetSymbolName( PLUINT32 aSymIdx) {
- return ELF_ENTRY_PTR(char, iStringTable, iElfDynSym[aSymIdx].st_name);
-}
-
-/**
-Function to get symbol ordinal
-@param aSymName - Symbol name
-@return Symbol ordinal
-@internalComponent
-@released
-*/
-PLUINT32 ElfExecutable::GetSymbolOrdinal( char* aSymName) {
- Elf32_Sym *aSym = FindSymbol(aSymName);
- if( !aSym )
- return (PLUINT32)-1;
- return GetSymbolOrdinal( aSym );
-
-}
-
-/**
-Function to get symbol ordinal
-@param aSym - Symbol
-@return Symbol ordinal
-@internalComponent
-@released
-*/
-PLUINT32 ElfExecutable::GetSymbolOrdinal( Elf32_Sym* aSym) {
- PLUINT32 aOrd = (PLUINT32)-1;
- if( aSym->st_shndx == ESegmentRO) {
- Elf32_Word *aLocation, aOffset;
-
- aOffset = iCodeSegmentHdr->p_offset + aSym->st_value - iCodeSegmentHdr->p_vaddr;
- aLocation = ELF_ENTRY_PTR(Elf32_Word, iElfHeader, aOffset);
- aOrd = *aLocation;
- }
- return aOrd;
-}
-
-/**
-Function to get relocation offset
-@param aReloc - Instance of class ElfRelocation
-@return offset
-@internalComponent
-@released
-*/
-Elf32_Word ElfExecutable::GetRelocationOffset(ElfRelocation * aReloc)
-{
- Elf32_Phdr * aHdr = Segment(aReloc->iAddr);
- unsigned int aOffset = aReloc->iAddr - aHdr->p_vaddr;
- return aOffset;
-}
-
-/**
-Function to get relocation place address
-@param aReloc - Instance of class ElfRelocation
-@return address to place relocation
-@internalComponent
-@released
-*/
-Elf32_Word * ElfExecutable::GetRelocationPlace(ElfRelocation * aReloc)
-{
- Elf32_Phdr * aHdr = Segment(aReloc->iAddr);
- unsigned int aOffset = aHdr->p_offset + aReloc->iAddr - aHdr->p_vaddr;
- Elf32_Word * aPlace = ELF_ENTRY_PTR(Elf32_Word, iElfHeader, aOffset);
- return aPlace;
-}
-
-/**
-Function to get local relocation
-@return local relocation
-@internalComponent
-@released
-*/
-ElfRelocations& ElfExecutable::GetLocalRelocations()
-{
- return iLocalRelocations;
-}
-
-/**
-Function to get code relocation
-@return code relocation list
-@internalComponent
-@released
-*/
-ElfRelocations::RelocationList & ElfExecutable::GetCodeRelocations()
-{
- return GetLocalRelocations().GetCodeRelocations();
-}
-
-/**
-Function to get data relocation
-@return data relocation list
-@internalComponent
-@released
-*/
-ElfRelocations::RelocationList & ElfExecutable::GetDataRelocations()
-{
- return GetLocalRelocations().GetDataRelocations();
-}
-
-/**
-Function to get RO base address
-@return RO base virtual address
-@internalComponent
-@released
-*/
-Elf32_Word ElfExecutable::GetROBase()
-{
- if (iCodeSegmentHdr) return iCodeSegmentHdr->p_vaddr;
- return 0;
-}
-
-/**
-Function to get RO segment
-@return code segment
-@internalComponent
-@released
-*/
-MemAddr ElfExecutable::GetRawROSegment()
-{
- return iCodeSegment;
-}
-
-/**
-Function to get RW segment virtual address
-@return RW base address
-@internalComponent
-@released
-*/
-Elf32_Word ElfExecutable::GetRWBase()
-{
- if (iDataSegmentHdr) return iDataSegmentHdr->p_vaddr;
- return 0;
-}
-
-/**
-Function to get Raw RW segment
-@return data segment address
-@internalComponent
-@released
-*/
-MemAddr ElfExecutable::GetRawRWSegment()
-{
- return iDataSegment;
-}
-
-/**
-Function to get RO segment size
-@return code segment size
-@internalComponent
-@released
-*/
-size_t ElfExecutable::GetROSize()
-{
- return iCodeSegmentHdr->p_filesz;
-}
-
-/**
-Function to get RW segment size
-@return data segment size
-@internalComponent
-@released
-*/
-size_t ElfExecutable::GetRWSize()
-{
- if (iDataSegmentHdr)
- return iDataSegmentHdr->p_filesz;;
- return 0;
-}
-
-/**
-Function to get Bss segment size
-@return Bss segment size, if data segment, otherwise 0
-@internalComponent
-@released
-*/
-size_t ElfExecutable::GetBssSize()
-{
- if (iDataSegmentHdr)
- return iDataSegmentHdr->p_memsz - iDataSegmentHdr->p_filesz;
- return 0;
-}
-
-/**
-Function returns entry point location in Elf image.
-@return entry point offset if valid, warning if undefined, otherwise throw error
-@internalComponent
-@released
-*/
-Elf32_Word ElfExecutable::EntryPointOffset()
-{
- if (!(iElfHeader->e_entry) && !(iCodeSegmentHdr->p_vaddr))
- {
- MessageHandler::GetInstance()->ReportMessage(WARNING, UNDEFINEDENTRYPOINTERROR,(char*)iParameterListInterface->ElfInput());
- return 0;
- }
- else if (!(iElfHeader->e_entry))
- throw ELFFormatError(ENTRYPOINTNOTSETERROR, (char*)iParameterListInterface->ElfInput());
- else
- return iElfHeader->e_entry - iCodeSegmentHdr->p_vaddr;
-}
-
-/**
-Function to check exception is present in the Elf image.
-@return True if exception present, otherwise false
-@internalComponent
-@released
-*/
-bool ElfExecutable::ExeceptionsPresentP()
-{
- size_t nShdrs = iElfHeader->e_shnum;
- if (nShdrs)
- {
- // Find the exception index table section
- Elf32_Shdr * aShdr = ELF_ENTRY_PTR(Elf32_Shdr, iElfHeader, iElfHeader->e_shoff);
- char * aShStrTab = ELF_ENTRY_PTR(char, iElfHeader, aShdr[iElfHeader->e_shstrndx].sh_offset);
-
- for (PLUINT32 i = 0; i < nShdrs; i++)
- {
- if (aShdr[i].sh_type == SHT_ARM_EXIDX)
- {
- char * aSectionName = aShStrTab + aShdr[i].sh_name;
- if (!strcmp(aSectionName, ".ARM.exidx"))
- {
- return true;
- }
- }
- }
-
- }
- else
- throw ELFFileError(NEEDSECTIONVIEWERROR, (char*)iParameterListInterface->ElfInput());
-
- return false;
-}
-
-/**
-Function to get the exports in ordinal number order.
-@return ordered exports
-@internalComponent
-@released
-*/
-ElfExports::ExportList &ElfExecutable::GetExportsInOrdinalOrder() {
- return iExports->GetExportsInOrdinalOrder();
-}
-
-/**
-This function looks up for a symbol in the static symbol table.
-@return Elf symbol.
-@internalComponent
-@released
-*/
-Elf32_Sym * ElfExecutable::LookupStaticSymbol(char * aName) {
- size_t nShdrs = iElfHeader->e_shnum;
- if (nShdrs)
- {
- // find the static symbol table and string table
- Elf32_Shdr * aShdr = ELF_ENTRY_PTR(Elf32_Shdr, iElfHeader, iElfHeader->e_shoff);
- char * aShStrTab = ELF_ENTRY_PTR(char, iElfHeader, aShdr[iElfHeader->e_shstrndx].sh_offset);
- Elf32_Sym * aSymTab = 0;
- Elf32_Sym * aLim = 0;
- char * aStrTab = 0;
- for (PLUINT32 i = 0; i < nShdrs; i++)
- {
- if (aShdr[i].sh_type == SHT_SYMTAB)
- {
- aSymTab = ELF_ENTRY_PTR(Elf32_Sym, iElfHeader, aShdr[i].sh_offset);
- aLim = ELF_ENTRY_PTR(Elf32_Sym, aSymTab, aShdr[i].sh_size);
- if (aStrTab) break;
- }
- else if (aShdr[i].sh_type == SHT_STRTAB)
- {
- char * aSectionName = aShStrTab + aShdr[i].sh_name;
- if (!strcmp(aSectionName, ".strtab"))
- {
- aStrTab = ELF_ENTRY_PTR(char, iElfHeader, aShdr[i].sh_offset);
- if (aSymTab) break;
- }
- }
- }
-
- /*if(aHashTbl && aSymTab && aStrTab)
- {
- PLULONG aHashVal = Util::elf_hash((const PLUCHAR*)aName);
- Elf32_Sword* aBuckets = ELF_ENTRY_PTR(Elf32_Sword, aHashTbl, sizeof(Elf32_HashTable) );
- Elf32_Sword* aChains = ELF_ENTRY_PTR(Elf32_Sword, aBuckets, sizeof(Elf32_Sword)*(aHashTbl->nBuckets) );
-
- PLUINT32 aIdx = aHashVal % aHashTbl->nBuckets;
- aIdx = aBuckets[aIdx];
-
- char *aSymName;
- do {
- aSymName = ELF_ENTRY_PTR(char, aStrTab, aSymTab[aIdx].st_name);
- if( !strcmp(aSymName, aName) ) {
- return &aSymTab[aIdx];
- }
- aIdx = aChains[aIdx];
- }while( aIdx > 0 );
-
- return NULL;
- }
- else */
-
- if (aSymTab && aStrTab)
- {
- for(; aSymTab < aLim; aSymTab++)
- {
- if (!aSymTab->st_name) continue;
- char * aSymName = aStrTab + aSymTab->st_name;
- if (!strcmp(aSymName, aName))
- return aSymTab;
- }
- return 0;
- }
- else
- {
- throw ELFFileError(NOSTATICSYMBOLSERROR, (char*)iParameterListInterface->ElfInput());
- }
- }
- else
- {
- throw ELFFileError(NOSTATICSYMBOLSERROR, (char*)iParameterListInterface->ElfInput());
- }
-}
-
-/**
-Function to get imports
-@return imports
-@internalComponent
-@released
-*/
-ElfImports::ImportMap ElfExecutable::GetImports() {
- return iImports.GetImports();
-}
-
-/**
-Function to get exports
-@return exports
-@internalComponent
-@released
-*/
-ElfExports* ElfExecutable::GetExports() {
- return iExports;
-}
-
-/**
-Function to get fixup location
-@param aReloc - Instance of class ElfLocalRelocation
-@param aPlace -
-@return addres of position for relocation
-@internalComponent
-@released
-*/
-Elf32_Word* ElfExecutable::GetFixupLocation(ElfLocalRelocation* aReloc, Elf32_Addr aPlace)
-{
- Elf32_Phdr * aPhdr = aReloc->ExportTableReloc() ?
- iCodeSegmentHdr :
- Segment(aPlace);
- Elf32_Word offset = aPhdr->p_offset + aPlace - aPhdr->p_vaddr;
- return ELF_ENTRY_PTR(Elf32_Word, iElfHeader, offset);
-}
-
-/**
-Function to get the segment type
-@param aSym - Symbol
-@return Segment type
-@internalComponent
-@released
-*/
-ESegmentType ElfExecutable::Segment(Elf32_Sym *aSym)
-{
- Elf32_Phdr * aHdr;
-
- try {
-
- bool limitSymbolFound = false;
-
- // If Symbol is absolute then assume it came from linker and is a
- // limit symbol.
- if (aSym->st_shndx == SHN_ABS)
- {
- aHdr = SegmentFromAbs(aSym->st_value);
- }
- else
- {
- if( (iCodeSegmentHdr && aSym->st_value == (iCodeSegmentHdr->p_vaddr + iCodeSegmentHdr->p_memsz)) ||
- (iDataSegmentHdr && aSym->st_value == (iDataSegmentHdr->p_vaddr + iDataSegmentHdr->p_memsz)) )
- {
- //If Symbol is a $$Limit symbol, then consider the open boundary.
- String limitstr = iStringTable + aSym->st_name;
- if (limitstr.rfind("$$Limit",limitstr.length()) != String::npos)
- {
- aHdr = SegmentFromAbs(aSym->st_value);
- limitSymbolFound = true;
- }
- }
-
- if(!limitSymbolFound )
- {
- aHdr = Segment(aSym->st_value);
- }
-
- }
-
- if (aHdr == iCodeSegmentHdr)
- {
- return ESegmentRO;
- }
- else if (aHdr == iDataSegmentHdr)
- {
- return ESegmentRW;
- }
- }
- catch(...)
- {
- }
- return ESegmentUndefined;
-}
-