toolsandutils/e32tools/elftools/elftran/elf_dlld.cpp
changeset 0 83f4b4db085c
child 1 d4b442d23379
equal deleted inserted replaced
-1:000000000000 0:83f4b4db085c
       
     1 // Copyright (c) 2001-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 // ELFDLLD.CPP
       
    15 // 
       
    16 //
       
    17 
       
    18 
       
    19 #include <string.h>
       
    20 #include <stdlib.h>
       
    21 #include <e32std.h>
       
    22 #include <e32std_private.h>
       
    23 #include <tools/elfdefs.h>
       
    24 #include "elfdll.h"
       
    25 #include "elffile.h"
       
    26 #include "h_utl.h"
       
    27 #include <e32ldr.h>
       
    28 
       
    29 ELFFile::ELFDllData::ELFDllData(ELFFile * f) :
       
    30         iElfFile(f), iDynStrTab(0), iDynStrTabSize(0), iDynSymTab(0),
       
    31 		iSymSize(0), iRela(0), iRelaSz(0), iRelaEnt(0), 
       
    32 		iRel(0), iRelSz(0), iRelEnt(0),
       
    33 		iHashTable(0),iDllHead(0), iDllTail(0), 
       
    34 		iNumberOfImports(0), iNumberOfExports(0), iNumberOfImportDlls(0),
       
    35 		iStringTableSize(0), iNumberOfRelocs(0), iNumberOfCodeRelocs(0), 
       
    36 		iNumberOfDataRelocs(0), iNamedLookupEnabled(0), iNamedExportSymbolHead(0), 
       
    37 		iNamedExportCount(0), iSymStringTableSize(0),iStringNameOffset(0), iOrdZeroRec(0), 
       
    38 		iDepRecords(0), iDepRecordsTail(0),iNeededDllNames(0),
       
    39 		iNeededDllNamesTail(0)
       
    40 		{
       
    41 		}
       
    42 
       
    43 ELFFile::ELFDllData::~ELFDllData()
       
    44 	{
       
    45 		delete iOrdZeroRec;
       
    46 		delete iDepRecords;
       
    47 		delete iNeededDllNames;
       
    48 	}
       
    49 
       
    50 TBool ELFFile::ELFDllData::Init()
       
    51 	{
       
    52 	// process imported symbols
       
    53 	// There will be at least one relocation (assumed to be Elf32_Rel) for each such symbol.
       
    54 	// S iterate over relocations looking for DLL symbols and add them to the record of
       
    55 	// of import info.
       
    56 	TInt nrelocs = iRelSz/iRelEnt;
       
    57 	TInt SrcSegIdx = -1;
       
    58 	TInt errors = 0;
       
    59 
       
    60 	for (TInt idx = 0; idx < nrelocs; idx++)
       
    61 			{
       
    62 			Elf32_Rel * rel = &iRel[idx];
       
    63 			TUint relType = ELF32_R_TYPE(rel->r_info);
       
    64 
       
    65 			if (relType == R_ARM_ABS32)      
       
    66 					{	
       
    67 					TInt symIdx = ELF32_R_SYM(rel->r_info);
       
    68 					Elf32_Sym * sym = &iDynSymTab[symIdx];
       
    69 					DllSymbol * dllSym = DllSymbolP(sym);
       
    70 					if (dllSym) 
       
    71 							{
       
    72 							dllSym->iRel = rel;
       
    73 							dllSym->iSegment = iElfFile->GetSegment(SrcSegIdx);
       
    74 							if (!AddSymbol(dllSym)) return EFalse;
       
    75 							}
       
    76 					else errors++;
       
    77 					}
       
    78 			else if (relType == R_ARM_RABS32)
       
    79 					{
       
    80 					iNumberOfRelocs++;
       
    81 					if (iElfFile->CodeSegmentP(SrcSegIdx)) iNumberOfCodeRelocs++;
       
    82 					else iNumberOfDataRelocs++;
       
    83 					}
       
    84 			else if (relType == R_ARM_RBASE)
       
    85 				    {
       
    86 					SrcSegIdx = ELF32_R_SYM(rel->r_info);
       
    87 					if (SrcSegIdx) SrcSegIdx--;
       
    88 					}
       
    89 			else 
       
    90 				    {
       
    91 					// Gives error with all other Relocation types..
       
    92 					TInt symIdx = ELF32_R_SYM(rel->r_info);
       
    93 					Elf32_Sym * s = &iDynSymTab[symIdx];
       
    94 					char * symName = ELFADDR(char,iDynStrTab,s->st_name);
       
    95 					Print(EPeError, "Unresolved symbol: %s\n", symName);
       
    96 					errors++;
       
    97 					}
       
    98 			}
       
    99 	// Set up export info
       
   100 	if (InitExportInfo())
       
   101 	       {
       
   102 	       TText * sym = (TText *)"_E32Startup";
       
   103 	       // If _E32Startup is defined then this is not a DLL
       
   104 	       iImageIsDll = !iElfFile->SymbolPresent(sym);
       
   105 	       }
       
   106 	if (errors > 0) return EFalse;
       
   107 	return ETrue;
       
   108 	}
       
   109 
       
   110 TBool ELFFile::ELFDllData::ParseDllSymbol(Elf32_Sym * s, char *& dll, TUint& len, TInt& ord)
       
   111     {
       
   112 	char * sym = ELFADDR(char,iDynStrTab,s->st_name);
       
   113 	if (!strncmp(sym, DLLSYMPREFIX, strlen(DLLSYMPREFIX)))
       
   114 			{
       
   115 			dll = sym + strlen(DLLSYMPREFIX);
       
   116 			TUint lim = strlen(dll);
       
   117 			TUint index = strcspn(dll, DLLSYMPREFIX0);
       
   118 			if ((index + strlen(DLLSYMSUFFIX)) < lim)
       
   119 					{
       
   120 					len = index;
       
   121 					char * dllSuffix = dll+index;
       
   122 					char * match = DLLSYMSUFFIX;
       
   123 					int suflen = strlen(DLLSYMSUFFIX);
       
   124 					if (!strncmp(dllSuffix, match, suflen))
       
   125 							{
       
   126 							char * ordString = dll+index+suflen;
       
   127 							char * final;
       
   128 							TUint X = strtoul(ordString, &final, ORDBASE);
       
   129 							if (ordString != final)
       
   130 									{
       
   131 									ord = (TInt)X;
       
   132 									return ETrue;
       
   133 									}
       
   134 			     
       
   135 							}
       
   136 					}
       
   137 			}
       
   138 	dll = 0;
       
   139 	len = 0;
       
   140 	ord = -1;
       
   141 	return EFalse;
       
   142 	}
       
   143 
       
   144 ELFFile::ELFDllData::DllSymbol * ELFFile::ELFDllData::DllSymbolP(Elf32_Sym * s)
       
   145     {
       
   146 	char * dllName;
       
   147 	TUint nameLen;
       
   148 	TInt symOrd;
       
   149 	if (ParseDllSymbol(s, dllName, nameLen, symOrd))
       
   150 	       {
       
   151 	       DllSymbol * ds = new DllSymbol(dllName, nameLen, symOrd);
       
   152 	       if (ds) return ds;
       
   153 	       Print(EPeError, "Out of memory.\n");
       
   154 	       return NULL;
       
   155 	       }
       
   156 	// If we get here its not a valid 'dll symbol' and so it is an unresolved symbol
       
   157 	char * sym = ELFADDR(char,iDynStrTab,s->st_name);
       
   158 	Print(EPeError, "Unresolved symbol: %s\n", sym);
       
   159     return NULL;
       
   160 	}
       
   161 
       
   162 TBool ELFFile::ELFDllData::AddSymbol(ELFFile::ELFDllData::DllSymbol * s)
       
   163     {
       
   164 	DllRec * aDll = NULL;
       
   165      
       
   166 	for (DllRec * r = iDllHead; r != NULL; r = r->iNext)
       
   167 			{
       
   168 			if (!strncmp(s->iDll, r->iName, s->iLen))
       
   169 					{
       
   170 					aDll = r;
       
   171 					break;
       
   172 					}
       
   173 			}
       
   174 	if (aDll)
       
   175 			{
       
   176 		    iNumberOfImports++;
       
   177 		    aDll->AddSymbol(s);
       
   178 			return ETrue;
       
   179 			}
       
   180 	else
       
   181 			{
       
   182 			aDll = new DllRec(s->iDll, s->iLen, s);
       
   183 			if (aDll)
       
   184 					{
       
   185 					if (!iDllHead) 
       
   186 							{
       
   187 							iDllHead = iDllTail = aDll;
       
   188 							}
       
   189 					else
       
   190 							{
       
   191 							iDllTail->iNext = aDll;
       
   192 							iDllTail = aDll;
       
   193 							}
       
   194 					iStringTableSize += (s->iLen + 1);
       
   195 	      			iNumberOfImportDlls++;
       
   196 					iNumberOfImports++;
       
   197 					return ETrue;
       
   198 					}
       
   199 			else
       
   200 					{
       
   201 					Print(EPeError, "Out of memory.\n");
       
   202 					return EFalse;
       
   203 					}
       
   204 			}
       
   205 	}
       
   206 
       
   207 void ELFFile::ELFDllData::DllRec::AddSymbol(ELFFile::ELFDllData::DllSymbol * s)
       
   208 	{
       
   209 	nImports++;
       
   210     iTail->iNext = s;
       
   211     iTail = s;
       
   212     }
       
   213 
       
   214 static unsigned long elf_hash(const unsigned char *name)
       
   215     {
       
   216     unsigned long h, g;
       
   217     for (h = 0; *name != 0; ++name)
       
   218 	        {
       
   219 			h = (h << 4) + *name;
       
   220 			g = h & 0xf0000000;
       
   221 			if (g != 0) h ^= g >> 24;
       
   222 			h &= ~g;
       
   223 			}
       
   224 	return h;
       
   225     }
       
   226 
       
   227 Elf32_Word ELFFile::ELFDllData::FindSymbolIndex(TText * s)
       
   228     {
       
   229 	TUint h = elf_hash(s);
       
   230 	TUint nb = iHashTable[0].nBuckets;
       
   231 	TUint probe = h%nb;
       
   232 	Elf32_Sword * bucket = ELFADDR(Elf32_Sword, iHashTable, sizeof(Elf32_HashTable));
       
   233 	Elf32_Sword * chain = ELFADDR(Elf32_Sword, bucket, nb * sizeof(Elf32_Sword));
       
   234 	Elf32_Sword idx = bucket[probe];
       
   235 
       
   236 	do 	
       
   237 			{
       
   238 			if (!strcmp(ELFADDR(char, iDynStrTab, iDynSymTab[idx].st_name), (char *)s)) return idx;
       
   239 			idx = chain[idx];
       
   240 			} while (idx > 0);
       
   241 	if (idx == 0) idx = -1;
       
   242 	return idx;
       
   243 	}
       
   244 
       
   245 TBool ELFFile::ELFDllData::InitExportInfo()
       
   246 	{
       
   247 	memset(&iSymInfoHdr, 0, sizeof(iSymInfoHdr));
       
   248 	TText * exp = (TText *)EXPORTTABLENAME;
       
   249 	if ((iExportTableSymIdx = FindSymbolIndex(exp)) != -1)
       
   250 			{
       
   251 			TText * exps = (TText *)EXPORTTABLESIZENAME;
       
   252 			iExportTableSizeSymIdx = FindSymbolIndex(exps);
       
   253 			//TUint offset = iDynSymTab[iExportTableSizeSymIdx].st_value - (TUint)code;
       
   254 			Elf32_Word * pNumberOfExports = iElfFile->CodePtrFromAddr(iDynSymTab[iExportTableSizeSymIdx].st_value);
       
   255 			iNumberOfExports = * pNumberOfExports;
       
   256 			iImageIsDll = ETrue;
       
   257 			return ETrue;
       
   258 			}
       
   259 	else iImageIsDll = EFalse;
       
   260 	return EFalse;
       
   261 	}
       
   262 
       
   263 TInt ELFFile::ELFDllData::NumberOfImports(void)
       
   264     {
       
   265 	return iNumberOfImports;
       
   266 	}
       
   267 
       
   268 TInt ELFFile::ELFDllData::NumberOfExports(void)
       
   269     {
       
   270 	return iNumberOfExports;
       
   271 	}
       
   272 
       
   273 TInt ELFFile::ELFDllData::NumberOfImportDlls(void)
       
   274     {
       
   275 	return iNumberOfImportDlls;
       
   276 	}
       
   277 
       
   278 TInt ELFFile::ELFDllData::NumberOfRelocs()
       
   279 	{
       
   280 	return iNumberOfRelocs;
       
   281 	}
       
   282 
       
   283 char * ELFFile::ELFDllData::CreateImportSection(TInt &aSize)
       
   284 	{
       
   285 	if (!iNumberOfImports)
       
   286 			{
       
   287 			aSize = 0;
       
   288 			return 0;
       
   289 			}
       
   290 
       
   291 	TInt byteSize = sizeof(E32ImportSection) + 
       
   292 	                (sizeof(E32ImportBlock) * iNumberOfImportDlls) +
       
   293 					(sizeof(TUint) * iNumberOfImports) +
       
   294 					iStringTableSize;
       
   295 	if(iNamedLookupEnabled)
       
   296 	{
       
   297 		// 0th ordinal of each DLL imported from.
       
   298 		byteSize += (sizeof(TUint) * iNumberOfImportDlls);
       
   299 	}
       
   300 	char * newSection = new char[byteSize];
       
   301 
       
   302 	if (!newSection)
       
   303 	       {
       
   304 	       Print(EPeError, "Failed to allocate new import section.\n");
       
   305 	       aSize = 0;
       
   306 	       return 0;
       
   307 	       }
       
   308 
       
   309 	((E32ImportSection *)newSection)->iSize = byteSize;
       
   310 
       
   311 	// used to point to current ImportBlock
       
   312 	E32ImportBlock * bp = ELFADDR(E32ImportBlock, newSection, sizeof(E32ImportSection));
       
   313 	// used to point to current import relocation entry
       
   314 	TUint * rp;
       
   315 	// used to point to current location in string table
       
   316 	char * sp = ELFADDR(char, newSection, (byteSize - iStringTableSize));
       
   317 	OrdZeroRecord *aDep = iDepRecords;
       
   318 
       
   319 	for (DllRec * dll = iDllHead; dll != NULL ; dll = dll->iNext, bp = (E32ImportBlock *)rp )
       
   320 	        {
       
   321 			// set up the offset from E32ImportBlock.iOffsetOfDllName to the
       
   322 			// corresponding  string table location
       
   323 			bp->iOffsetOfDllName = (sp - (char *)newSection);
       
   324 			bp->iNumberOfImports = dll->nImports;
       
   325 			if(iNamedLookupEnabled)
       
   326 			{
       
   327 				bp->iNumberOfImports++;
       
   328 			}
       
   329 
       
   330 			// copy the DLL name to the string table
       
   331 			memcpy(sp , dll->iName, dll->iLen);
       
   332 			sp[dll->iLen] = 0;
       
   333 			sp = sp + dll->iLen + 1;
       
   334 
       
   335 			// sort out the import 'relocs'
       
   336 			rp = ELFADDR(TUint, bp, sizeof(E32ImportBlock));
       
   337 		
       
   338 			for (DllSymbol * sym = dll->iHead; sym != NULL; sym = sym->iNext, rp++)
       
   339 				    {
       
   340 					Elf32_Phdr * segment = sym->iSegment;
       
   341 					Elf32_Addr segBase = segment->p_vaddr;
       
   342 
       
   343 					// sanity check: segment should be the code segment
       
   344 					if (!iElfFile->CodeSegmentP(segment))
       
   345 							{
       
   346 							Print(EPeError, "Import relocation does not refer to code segment.\n");
       
   347 							aSize = 0;
       
   348 							return 0;
       
   349 							}
       
   350 
       
   351 					// This field is misnamed because it is actually given as a virtual address in 
       
   352 					// dynamic relocations
       
   353 					Elf32_Addr dynOffset = sym->iRel->r_offset;
       
   354 					//So this is the 'real' offset of the reloc in  the segment in which it occurs
       
   355 					Elf32_Addr segOffset = dynOffset - segBase;
       
   356 					TUint * relocAddr = ELFADDR(TUint, iElfFile->ELFFileBase(), (segment->p_offset + segOffset));
       
   357 					// The only non-zero reloc vals we expect are for vtables.
       
   358 					// We store there reloc offset in the top 16 bits of the 'reloc info'.
       
   359 					// NB the ELF reloc values should only ever be multiples of 4. So we could optimize here,
       
   360 					// but we won't.
       
   361 					TUint relocVal = *relocAddr;
       
   362 					TUint importOrdinal = sym->iOrd;
       
   363 					if (relocVal > 0xFFFF)
       
   364 							Print(EPeError, "ELF relocation exceeds E32Image limit of 64K.\n");
       
   365 					if (importOrdinal > 0xFFFF)
       
   366 							Print(EPeError, "Import ordinal exceeds E32Image limit of 64K.\n");
       
   367    
       
   368    					*rp = segOffset;
       
   369    			
       
   370    					// eek !! surgery on the code segment....
       
   371 					*relocAddr = (relocVal<<16) | importOrdinal;
       
   372 					}
       
   373 			
       
   374 				if(iNamedLookupEnabled)
       
   375 				{
       
   376 					aDep = FindDependency(dll->iName, dll->iLen);
       
   377 					if( aDep )
       
   378 					{
       
   379 						*rp = aDep->iOffset;
       
   380 						rp++;
       
   381 					}
       
   382 				}
       
   383 			}
       
   384 	
       
   385 	aSize = byteSize;
       
   386 	return newSection;
       
   387 	}
       
   388 
       
   389 TUint ELFFile::ELFDllData::GetExportTableOffset(void)
       
   390     {
       
   391 	Elf32_Sym * et = &iDynSymTab[iExportTableSymIdx];
       
   392 	Elf32_Phdr * segment = iElfFile->GetSegment(et->st_shndx - 1);
       
   393 	
       
   394 	return et->st_value - segment->p_vaddr;
       
   395 	}
       
   396 
       
   397 TBool ELFFile::ELFDllData::GetRelocs(Elf32_Rel **aCodeRelocs, Elf32_Rel **aDataRelocs)
       
   398 	//	
       
   399 	// load the relocs from the reloc section into relocation and relocsection arrays
       
   400 	//
       
   401 	{
       
   402 	TInt nrelocs = iRelSz/iRelEnt;
       
   403 
       
   404 	TInt SrcSegIdx = -1;
       
   405 
       
   406 	for (TInt idx = 0, cidx = 0, didx = 0; idx < nrelocs; idx++)
       
   407 	        {
       
   408 			Elf32_Rel * rel = &iRel[idx];
       
   409 
       
   410 			if (ELF32_R_TYPE(rel->r_info) == R_ARM_RABS32)
       
   411 					{
       
   412 					if (iElfFile->CodeSegmentP(SrcSegIdx))
       
   413 							aCodeRelocs[cidx++]=rel;
       
   414 					else if (iElfFile->DataSegmentP(SrcSegIdx))
       
   415 							aDataRelocs[didx++]=rel;
       
   416 					}
       
   417 			else if (ELF32_R_TYPE(rel->r_info) == R_ARM_RBASE)
       
   418 					{
       
   419 					SrcSegIdx = ELF32_R_SYM(rel->r_info);
       
   420 					if (!(iElfFile->CodeSegmentP(SrcSegIdx-1) || iElfFile->DataSegmentP(SrcSegIdx-1)))
       
   421 							{
       
   422 							Print(EPeError, "Source segment for relocations is neither Code or Data.\n");
       
   423 							return EFalse;
       
   424 							}
       
   425 					SrcSegIdx--;
       
   426 					}
       
   427 			}
       
   428 	if(!iNamedLookupEnabled)
       
   429 		return ETrue;
       
   430 
       
   431 	// Add the 0th ordinal of this binary - The relocation info is already setup.
       
   432 	aCodeRelocs[cidx++] = &iOrdZeroRec->iReloc;
       
   433 
       
   434 	// add relocation entries for each of the symbols
       
   435 	NamedExportSymbol *aSym = iNamedExportSymbolHead;
       
   436 	while(aSym)
       
   437 	{
       
   438 		// The symbol name info is part of the code section hence all relocations
       
   439 		// are collected as part of Code relocations.
       
   440 		aCodeRelocs[cidx++] = &aSym->iReloc;
       
   441 		aSym = aSym->Next();
       
   442 	}
       
   443 
       
   444 	// Since we have added a few relocations, lets make sure
       
   445 	// they are still sorted on addresses they refer to.
       
   446 	
       
   447 	//Sorting the code relocs
       
   448 	TInt aIdx1, aIdx2;
       
   449 	Elf32_Rel *aTmp;
       
   450 	for (aIdx1 = 0; aIdx1 < cidx; aIdx1++) {
       
   451 		for (aIdx2 = aIdx1; aIdx2 < cidx; aIdx2++) {
       
   452 			if(aCodeRelocs[aIdx1]->r_offset > aCodeRelocs[aIdx2]->r_offset) {
       
   453 				aTmp = aCodeRelocs[aIdx2];
       
   454 				aCodeRelocs[aIdx2] = aCodeRelocs[aIdx1];
       
   455 				aCodeRelocs[aIdx1] = aTmp;
       
   456 			}
       
   457 		}
       
   458 	}
       
   459 	
       
   460 	//Sorting the data relocs
       
   461 	for (aIdx1 = 0; aIdx1 < didx; aIdx1++) {
       
   462 		for (aIdx2 = aIdx1; aIdx2 < didx; aIdx2++) {
       
   463 			if(aDataRelocs[aIdx1]->r_offset > aDataRelocs[aIdx2]->r_offset) {
       
   464 				aTmp = aDataRelocs[aIdx2];
       
   465 				aDataRelocs[aIdx2] = aDataRelocs[aIdx1];
       
   466 				aDataRelocs[aIdx1] = aTmp;
       
   467 			}
       
   468 		}
       
   469 	}
       
   470 
       
   471 	return ETrue;
       
   472 	}
       
   473 
       
   474 NamedExportSymbol::NamedExportSymbol(char* aName, Elf32_Addr aValue) : \
       
   475 	iSymbolName(aName), iValue(aValue), iNext(NULL)
       
   476 {
       
   477 }
       
   478 
       
   479 TBool ELFFile::ELFDllData::CreateSymLookupTable()
       
   480 {
       
   481 	if( !SetupSymbolValues() )
       
   482 		return FALSE;
       
   483 
       
   484 	if( !SetupSymbolNames() )
       
   485 		return FALSE;
       
   486 
       
   487 	return TRUE;
       
   488 }
       
   489 
       
   490 TBool ELFFile::ELFDllData::SetupSymbolValues()
       
   491 {
       
   492 	NamedExportSymbol *aSym, *aPrevSym;
       
   493 
       
   494 	if( iExportTableSymIdx == -1 || iExportTableSizeSymIdx == -1)
       
   495 		return FALSE;
       
   496 
       
   497 	// Fetch the 'export table' symbol from the dynamic symbol table.
       
   498 	Elf32_Sym *aElfExpTbl = &iDynSymTab[iExportTableSymIdx];
       
   499 
       
   500 	// Fetch the 'export table size' symbol from the dynamic symbol table.
       
   501 	Elf32_Sym *aElfExpTblSz = &iDynSymTab[iExportTableSizeSymIdx];
       
   502 
       
   503 	if((aElfExpTbl->st_value - aElfExpTblSz->st_value) != 4)
       
   504 	{
       
   505 		// Check that the word prior to the export table is not the export table size
       
   506 		// This is to make sure that there is space for the 0th ordinal and
       
   507 		// we dont overwrite the 'export table size' entry.
       
   508 		iNamedLookupEnabled = 1;
       
   509 	}
       
   510 	else 
       
   511 		return FALSE;
       
   512 
       
   513 	// Fetch the export table contents
       
   514 	Elf32_Word * aExpEntries = iElfFile->CodePtrFromAddr(aElfExpTbl->st_value);
       
   515 
       
   516 	if(!aExpEntries)
       
   517 		return FALSE;
       
   518 
       
   519 	aSym = aPrevSym = NULL;
       
   520 	TInt idx;
       
   521 	// Create symbols corresponding to export table entries.
       
   522 	for(idx = 0;  idx < iNumberOfExports; idx++)
       
   523 	{
       
   524 		//Symbols marked Absent are ignored.
       
   525 		if( aExpEntries[idx] == iElfFile->iEntryPoint)
       
   526 			continue;
       
   527 
       
   528 		aSym = new NamedExportSymbol(0, aExpEntries[idx]);
       
   529 		iNamedExportCount++;
       
   530 		if(aPrevSym)
       
   531 		{
       
   532 			aPrevSym->Next(aSym);
       
   533 		}
       
   534 		else
       
   535 		{
       
   536 			iNamedExportSymbolHead = aSym;
       
   537 		}
       
   538 
       
   539 		aPrevSym = aSym;
       
   540 	}
       
   541 
       
   542 	return TRUE;
       
   543 }
       
   544 
       
   545 TBool ELFFile::ELFDllData::SetupSymbolNames()
       
   546 {
       
   547 	char *aSymName = NULL;
       
   548 	NamedExportSymbol *aSym;
       
   549 	TUint aDynSymbolTblCount = iHashTable->nChains;
       
   550 	TInt aCount = 0;
       
   551 	TInt aCodeSegIdx = iElfFile->CodeSegmentIndex() + 1;
       
   552 	TInt aDataSegIdx = iElfFile->DataSegmentIndex() + 1;
       
   553 
       
   554 	// Traverse the dynamic symbol table
       
   555 	for(TUint idx = 0; idx < aDynSymbolTblCount; idx++)
       
   556 	{
       
   557 		//Consider only the the defined symbols
       
   558 		if( ELF32_ST_TYPE(iDynSymTab[idx].st_info) == STT_OBJECT || 
       
   559 			ELF32_ST_TYPE(iDynSymTab[idx].st_info) == STT_FUNC )
       
   560 		{
       
   561 			aSym = iNamedExportSymbolHead;
       
   562 			while(aSym)
       
   563 			{
       
   564 				// Name already set
       
   565 				if(aSym->Name())
       
   566 				{
       
   567 					aSym = aSym->Next();
       
   568 					continue;
       
   569 				}
       
   570 				Elf32_Addr aAddr = aSym->Value();
       
   571 
       
   572 				// If the exported symbol and the dynamic symbol table entry have the 
       
   573 				// same values, setup the name
       
   574 				if(iDynSymTab[idx].st_value == aAddr)
       
   575 				{
       
   576 					aSymName = ELFADDR(char, iDynStrTab, iDynSymTab[idx].st_name);
       
   577 					aSym->Name(aSymName);
       
   578 					
       
   579 					if(iElfFile->CodeSegmentP (iElfFile->GetSegmentFromAddr(aAddr)) ) {
       
   580 						aSym->iReloc.r_info = aCodeSegIdx << 8 | R_ARM_RABS32;
       
   581 						aSym->iSymRelocType = KTextRelocType;
       
   582 					}
       
   583 					else {
       
   584 						aSym->iReloc.r_info = aDataSegIdx << 8 | R_ARM_RABS32;
       
   585 						aSym->iSymRelocType = KDataRelocType;
       
   586 					}
       
   587 					
       
   588 					iNumberOfCodeRelocs++;
       
   589 					iNumberOfRelocs++;
       
   590 
       
   591 					// The offset to the name is always 4 byte aligned.
       
   592 					iStringNameOffset = iSymStringTableSize >> 2;
       
   593 					aSym->NameOffset( iSymStringTableSize );
       
   594 					// These are NULL-terminated strings
       
   595 					iSymStringTableSize += (strlen(aSymName) + 1);
       
   596 					iSymStringTableSize = ALIGN4(iSymStringTableSize);
       
   597 
       
   598 					aCount++;
       
   599 					break;
       
   600 				}
       
   601 				aSym = aSym->Next();
       
   602 			}
       
   603 		}
       
   604 	}
       
   605 
       
   606 	if(aCount != iNamedExportCount)
       
   607 		return FALSE;
       
   608 
       
   609 	// Sort symbols on their names...
       
   610 	if(iNamedExportCount > 1)
       
   611 	{
       
   612 		NamedExportSymbol **aTmpStart = &iNamedExportSymbolHead;
       
   613 		Sort(aTmpStart, iNamedExportSymbolHead);
       
   614 	}
       
   615 
       
   616 	return TRUE;
       
   617 }
       
   618 
       
   619 void ELFFile::ELFDllData::SetLookupTblBase(TInt aBaseOffset)
       
   620 {
       
   621 	Elf32_Addr	aBaseAddr = iElfFile->iLinkedBase + iElfFile->GetCodeSize();
       
   622 
       
   623 	Elf32_Addr	aAddr;
       
   624 
       
   625 	// setup relocations of each of the exported symbols.
       
   626 	aAddr = aBaseAddr + iSymInfoHdr.iSymbolTblOffset;
       
   627 	NamedExportSymbol *aSym = iNamedExportSymbolHead;
       
   628 	while(aSym)
       
   629 	{
       
   630 		aSym->iReloc.r_offset = aAddr;
       
   631 		aAddr += sizeof(Elf32_Addr);
       
   632 		aSym = aSym->Next();
       
   633 	}
       
   634 
       
   635 	// setup relocations for the 0th ordinal of this binary. 
       
   636 
       
   637 	iOrdZeroRec = new OrdZeroRecord(0);
       
   638 	Elf32_Sym * et = &iDynSymTab[iExportTableSymIdx];
       
   639 	iOrdZeroRec->iReloc.r_offset = et->st_value - 4; // The word prior ro the first entry
       
   640 											// of the export table is the 0th ordinal entry.
       
   641 
       
   642 	//At the 0th ordinal, write the address of the start of symbol info	
       
   643 	TUint32 aZeroOrdOff = et->st_value - 4 - iElfFile->iLinkedBase;
       
   644 	aZeroOrdOff += (iElfFile->GetSegment(et->st_shndx - 1))->p_offset;
       
   645 	TUint32 *aZeroOrdLocation = ELFADDR(TUint32, iElfFile->ELFFileBase(), aZeroOrdOff);
       
   646 	*aZeroOrdLocation = aBaseAddr;
       
   647 
       
   648 	iOrdZeroRec->iReloc.r_info = ELF32_R_INFO(et->st_shndx, R_ARM_RABS32);
       
   649 	iNumberOfCodeRelocs++;
       
   650 	iNumberOfRelocs++;
       
   651 
       
   652 	TInt aOffset = aBaseOffset + iSymInfoHdr.iDepDllZeroOrdTableOffset;
       
   653 
       
   654 	OrdZeroRecord *aDepRecord = iDepRecords;
       
   655 
       
   656 	while( aDepRecord )
       
   657 	{
       
   658 		// Setup the offset - This offset (relative code segment) is filled in the 
       
   659 		// import table to point to this dependency record.
       
   660 		aDepRecord->iOffset = aOffset;
       
   661 
       
   662 		aOffset += 4;
       
   663 		aDepRecord = aDepRecord->iNext;
       
   664 	}
       
   665 }
       
   666 
       
   667 TBool ELFFile::ELFDllData::AddToDependency(TUint aOff)
       
   668 {
       
   669 	// Add the name found in DT_NEEDED into a list.
       
   670 	// The dynamic string table might not have been found in dynamic table yet.
       
   671 	// So store the offset (wrt base of dynamic string table) for now.
       
   672 	NeededDLLsList *aNeeded = new NeededDLLsList(aOff);
       
   673 	if(!aNeeded)
       
   674 		return FALSE;
       
   675 
       
   676 	if ( iNeededDllNames ) {
       
   677 	 iNeededDllNamesTail->iNext= aNeeded;
       
   678 	 iNeededDllNamesTail = aNeeded; 
       
   679 	}
       
   680 	else {
       
   681 		iNeededDllNames = iNeededDllNamesTail = aNeeded;
       
   682 	}
       
   683 	
       
   684 	return TRUE;
       
   685 }
       
   686 
       
   687 TBool ELFFile::ELFDllData::CreateDependency()
       
   688 {
       
   689 	OrdZeroRecord *aDep;
       
   690 	NeededDLLsList *aNeeded = iNeededDllNames;
       
   691 	char *aDllName = NULL;
       
   692 	DllRec *aRec;
       
   693 	TInt aNeededFound;
       
   694 
       
   695 	for(aNeededFound = 0; (aNeededFound < iNumberOfImportDlls) && aNeeded;)
       
   696 	{
       
   697 		aRec = 0;
       
   698 		while(aNeeded) {
       
   699 			aDllName = iDynStrTab + aNeeded->iOffset;
       
   700 			// aNeeded is just a guess that this binary might be dependent on aDllName
       
   701 			// Search through the import table to find if the guess was correct.
       
   702 			aRec = SearchImports(aDllName);
       
   703 			if(aRec && FindDependency(aRec->iName, aRec->iLen) == NULL) {
       
   704 				// Check if aDllName is listed in import table and it
       
   705 				// not added already in the depedency records.
       
   706 				aNeededFound++;
       
   707 				break;
       
   708 			}
       
   709 			// Bad guess...go to the next aNeeded
       
   710 			aNeeded = aNeeded->iNext;
       
   711 		}
       
   712 
       
   713 		if( !aRec )
       
   714 			return FALSE;
       
   715 
       
   716 		aDep = new OrdZeroRecord(aDllName);
       
   717 		if(!iDepRecords)
       
   718 		{
       
   719 			iDepRecords = iDepRecordsTail = aDep;
       
   720 		}
       
   721 		else
       
   722 		{
       
   723 			iDepRecordsTail->iNext = aDep;
       
   724 			iDepRecordsTail = aDep;
       
   725 		}
       
   726 		aNeeded = aNeeded->iNext;
       
   727 	}
       
   728 
       
   729 	return (aNeededFound == iNumberOfImportDlls);
       
   730 }
       
   731 
       
   732 ELFFile::ELFDllData::DllRec* ELFFile::ELFDllData::SearchImports(char *aName)
       
   733 {
       
   734 	DllRec *aRec = iDllHead;
       
   735 	while (aRec)
       
   736 	{
       
   737 		if(strncmp(aRec->iName, aName, aRec->iLen) == 0)
       
   738 			return aRec;
       
   739 		aRec = aRec->iNext;
       
   740 	}
       
   741 	return NULL;
       
   742 }
       
   743 
       
   744 OrdZeroRecord* ELFFile::ELFDllData::FindDependency(char* aName, TUint aLen)
       
   745 {
       
   746 	OrdZeroRecord* aDep = iDepRecords;
       
   747 	while(aDep)
       
   748 	{
       
   749 		if(strncmp(aName, aDep->iName, aLen) == 0)
       
   750 			return aDep;
       
   751 		aDep = aDep->iNext;
       
   752 	}
       
   753 	return NULL;
       
   754 }
       
   755 
       
   756 void ELFFile::ELFDllData::GetExportSymInfoHeader(E32EpocExpSymInfoHdr& aSymInfoHdr)
       
   757 {
       
   758 	memcpy(&aSymInfoHdr, &iSymInfoHdr, sizeof(E32EpocExpSymInfoHdr));
       
   759 }
       
   760 
       
   761 void ELFFile::ELFDllData::SetExportSymInfo()
       
   762 {
       
   763 	iSymInfoHdr.iSymCount = (TUint16)iNamedExportCount;
       
   764 	iSymInfoHdr.iSymbolTblOffset = sizeof(E32EpocExpSymInfoHdr);
       
   765 	iSymInfoHdr.iStringTableSz = iSymStringTableSize;
       
   766 	TInt aSymTabSz;
       
   767 	if( iStringNameOffset > 0xffff){
       
   768 		iSymInfoHdr.iFlags = KNameLookupOffsetFlag32;  // Flag indicating 32 bit offsets 
       
   769 													   // for symbol names
       
   770 		aSymTabSz = iNamedExportCount* sizeof(TUint32);// symbol addresses
       
   771 		aSymTabSz += iNamedExportCount* sizeof(TUint32);// symbol name 32-bit offsets
       
   772 	}
       
   773 	else
       
   774 	{
       
   775 		iSymInfoHdr.iFlags &= ~KNameLookupOffsetFlag32;// Flag indicating 16-bit offsets 
       
   776 													   // for symbol names
       
   777 		aSymTabSz = iNamedExportCount* sizeof(TUint32);	// symbol addresses
       
   778 		aSymTabSz += iNamedExportCount* sizeof(TUint16);// symbol name 16-bit offsets
       
   779 		aSymTabSz = ALIGN4(aSymTabSz);
       
   780 	}
       
   781 	iSymInfoHdr.iStringTableOffset = iSymInfoHdr.iSymbolTblOffset + aSymTabSz;
       
   782 	iSymInfoHdr.iDllCount = iNumberOfImportDlls;
       
   783 	iSymInfoHdr.iDepDllZeroOrdTableOffset = iSymInfoHdr.iStringTableOffset + \
       
   784 								iSymInfoHdr.iStringTableSz;
       
   785 
       
   786 	iSymInfoHdr.iSize = iSymInfoHdr.iDepDllZeroOrdTableOffset + \
       
   787 						iSymInfoHdr.iDllCount * sizeof(Elf32_Addr);
       
   788 }
       
   789 
       
   790 TUint ELFFile::ELFDllData::GetSymLookupSection(char* aBuff)
       
   791 {
       
   792 	if( !iNamedLookupEnabled)
       
   793 		return 0;
       
   794 
       
   795 	memcpy(aBuff, &iSymInfoHdr, sizeof(iSymInfoHdr));
       
   796 	
       
   797 	// Name offsets start after the end of symbol addresses.
       
   798 	TUint32 aNameOffsetStart = iSymInfoHdr.iSymbolTblOffset + \
       
   799 								iNamedExportCount* sizeof(TUint32);
       
   800 																
       
   801 	TUint32 *aAddrPtr = (TUint32*)(aBuff + iSymInfoHdr.iSymbolTblOffset);
       
   802 	TUint32 aStringTabOff = 0;
       
   803 	char *aStringTab = aBuff + iSymInfoHdr.iStringTableOffset;//Start of the string table.
       
   804 	NamedExportSymbol *aSym = iNamedExportSymbolHead;
       
   805 	while(aSym)
       
   806 	{
       
   807 		*aAddrPtr = aSym->Value();
       
   808 		aStringTabOff = aSym->NameOffset(); // Get the offset of symbol name (which is wrt 
       
   809 											// string table base).
       
   810 		if( iSymInfoHdr.iFlags & KNameLookupOffsetFlag32 )
       
   811 		{
       
   812 			TUint32 *aNameOffPtr = (TUint32*)(aBuff + aNameOffsetStart);
       
   813 			*aNameOffPtr = (aStringTabOff >> 2);//write the offset of the name
       
   814 			strcpy(aStringTab + aStringTabOff, aSym->Name());//write the symbol name
       
   815 			aNameOffsetStart +=4;
       
   816 		}
       
   817 		else
       
   818 		{
       
   819 			TUint16 *aNameOffPtr = (TUint16*)(aBuff + aNameOffsetStart);
       
   820 			*aNameOffPtr = (TUint16)(aStringTabOff >> 2);//write the offset of the name
       
   821 			strcpy(aStringTab + aStringTabOff, aSym->Name());//write the symbol name
       
   822 			aNameOffsetStart +=2;
       
   823 		}
       
   824 		aAddrPtr++;
       
   825 		aSym = aSym->Next();
       
   826 	}
       
   827 
       
   828 	OrdZeroRecord *aRec = iDepRecords;
       
   829 	TUint32* aDepsTable = (TUint32*)(aBuff + iSymInfoHdr.iDepDllZeroOrdTableOffset);
       
   830 	while(aRec)
       
   831 	{
       
   832 		*aDepsTable++ = 0;
       
   833 		aRec = aRec->iNext;
       
   834 	}
       
   835 	return iSymInfoHdr.iSize;
       
   836 }
       
   837 
       
   838 void ELFFile::ELFDllData::Sort(NamedExportSymbol** aDstList, NamedExportSymbol* aSrcList)
       
   839 {
       
   840 	NamedExportSymbol *aSym = aSrcList;
       
   841 	NamedExportSymbol **aSymbols = new NamedExportSymbol*[iNamedExportCount];
       
   842 	
       
   843 	TInt pos;
       
   844 	for (pos = 0; pos < iNamedExportCount; pos++) {
       
   845 		aSymbols[pos] = aSym;
       
   846 		aSym = aSym->Next();
       
   847 	}
       
   848 	
       
   849 	NamedExportSymbol **aResult = new NamedExportSymbol*[iNamedExportCount];
       
   850 	MergeSort(aResult, aSymbols);
       
   851 	iNamedExportSymbolHead = aResult[0];
       
   852 	for (pos = 0; pos < iNamedExportCount; pos++) {
       
   853 		aSym = aResult[pos];
       
   854 		if( pos == iNamedExportCount-1)
       
   855 			aSym->Next(NULL);
       
   856 		else
       
   857 			aSym->Next(aResult[pos+1]);
       
   858 	}
       
   859 	*aDstList = aResult[0];
       
   860 	delete [] aResult;
       
   861 	delete [] aSymbols;
       
   862 }
       
   863 
       
   864 void ELFFile::ELFDllData::MergeSort(NamedExportSymbol** aDstList, NamedExportSymbol** aSrcList)
       
   865 {
       
   866 	MergeSort(aDstList, aSrcList, 0, iNamedExportCount);
       
   867 }
       
   868 
       
   869 void ELFFile::ELFDllData::MergeSort(NamedExportSymbol** aDstList, NamedExportSymbol** aSrcList, \
       
   870 									TUint aLeft, TUint aRight)
       
   871 {
       
   872 	if( (aRight - aLeft) <= 1)
       
   873 		return;
       
   874 
       
   875 	TUint aSize = aRight - aLeft;
       
   876 	TUint aCenter = aLeft + aSize/2;
       
   877 
       
   878 	MergeSort(aDstList, aSrcList, aLeft, aCenter);
       
   879 	MergeSort(aDstList, aSrcList, aCenter, aRight);
       
   880 
       
   881 	TUint aLPos, aRPos, aCnt;
       
   882 	aLPos = aLeft;
       
   883 	aRPos = aCenter;
       
   884 	for(aCnt = 0; aCnt < aSize; aCnt++)
       
   885 	{
       
   886 		if( (aLPos < aCenter) &&
       
   887 			(aRPos == aRight || (strcmp(aSrcList[aLPos]->Name(), aSrcList[aRPos]->Name()) < 0) )
       
   888 		  )
       
   889 		{
       
   890 			// Compare the left half with the right and add the lesser one.
       
   891 			// The comparision is done on the topmost element on each half.
       
   892 			// if aRPos is past the last element of the right half, the left element has 
       
   893 			// nothing to compare with. Just add it to the result list.
       
   894 			aDstList[aCnt] = aSrcList[aLPos];
       
   895 			aLPos++;
       
   896 		}
       
   897 		else
       
   898 		{
       
   899 			// Add the greater one into the list.
       
   900 			// if aLPos is past the element at the center, it anyway belongs to the
       
   901 			// right half. Add it to the result list.
       
   902 			aDstList[aCnt] = aSrcList[aRPos];
       
   903 			aRPos++;
       
   904 		}
       
   905 	}
       
   906 
       
   907 	// Once the sublist is sorted, put it back to the source list
       
   908 	// so that the parent has its left and right sublists are sorted.
       
   909 	for(aCnt = 0; aCnt < aSize; aCnt++)
       
   910 	{
       
   911 		aSrcList[aLeft+aCnt] = aDstList[aCnt];
       
   912 	}
       
   913 }
       
   914