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