diff -r 59148e28d9f6 -r 626366955efb toolsandutils/e32tools/elf2e32/source/pl_elfexecutable.cpp --- 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 -#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 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::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 -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; -} -