toolsandutils/e32tools/elf2e32/source/pl_elfexecutable.cpp
changeset 0 83f4b4db085c
child 1 d4b442d23379
equal deleted inserted replaced
-1:000000000000 0:83f4b4db085c
       
     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