toolsandutils/e32tools/elf2e32/source/e32imagefile.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 e32 image creation and dump for elf2e32 tool
       
    15 // @internalComponent
       
    16 // @released
       
    17 // 
       
    18 //
       
    19 
       
    20 #include "pl_elfexecutable.h"
       
    21 
       
    22 // get E32ImageHeader class...
       
    23 #define INCLUDE_E32IMAGEHEADER_IMPLEMENTATION
       
    24 #define RETURN_FAILURE(_r) return (fprintf(stderr, "line %d\n", __LINE__),_r)
       
    25 //#define E32IMAGEHEADER_TRACE(_t) printf _t
       
    26 #include "e32imagefile.h"
       
    27 
       
    28 #include "pl_elfimportrelocation.h"
       
    29 #include "pl_elflocalrelocation.h"
       
    30 #include "pl_elfimports.h"
       
    31 #include "elffilesupplied.h"
       
    32 #include "pl_dllsymbol.h"
       
    33 #include "h_ver.h"
       
    34 #include "checksum.h"
       
    35 #include "errorhandler.h"
       
    36 
       
    37 #include <string>
       
    38 #include <vector>
       
    39 #include <cassert>
       
    40 #include <iostream>
       
    41 #ifndef __LINUX__ 
       
    42     #include <io.h>
       
    43 #else
       
    44     #include <time.h>
       
    45 #endif 
       
    46 #include <time.h>
       
    47 #include <stdio.h>
       
    48 
       
    49 using namespace std;
       
    50 
       
    51 template <class T> inline T Align(T v, size_t s)
       
    52 {
       
    53 	unsigned int inc = s-1;
       
    54 	unsigned int mask = ~inc;
       
    55 	unsigned int val = (unsigned int)v;
       
    56 	unsigned int res = (val+inc) & mask;
       
    57 	return (T)res;
       
    58 }
       
    59 
       
    60 // Need a default constructor for TVersion, but don't want all the other stuff in h_utl.cpp
       
    61 /**
       
    62 Default constructor for TVersion class.
       
    63 @internalComponent
       
    64 @released
       
    65 */
       
    66 TVersion::TVersion(){}
       
    67 
       
    68 /**
       
    69 Constructor for TVersion class.
       
    70 @internalComponent
       
    71 @released
       
    72 */
       
    73 TVersion::TVersion(TInt aMajor, TInt aMinor, TInt aBuild): 
       
    74 	iMajor((TInt8)aMajor), iMinor((TInt8)aMinor), iBuild((TInt16)aBuild)
       
    75 {
       
    76 }
       
    77 
       
    78 
       
    79 /**
       
    80 Constructor for E32ImageChunkDesc class.
       
    81 @internalComponent
       
    82 @released
       
    83 */
       
    84 E32ImageChunkDesc::E32ImageChunkDesc(char * aData, size_t aSize, size_t aOffset, char * aDoc):
       
    85 	iData(aData), iSize(aSize), iOffset(aOffset), iDoc(aDoc)
       
    86 {
       
    87 }
       
    88 
       
    89 /**
       
    90 Destructor for E32ImageChunkDesc class.
       
    91 @internalComponent
       
    92 @released
       
    93 */
       
    94 E32ImageChunkDesc::~E32ImageChunkDesc()
       
    95 {
       
    96 }
       
    97 
       
    98 /**
       
    99 This function writes its data in the buffer.
       
   100 @param aPlace - a location in the buffer
       
   101 @internalComponent
       
   102 @released
       
   103 */
       
   104 void E32ImageChunkDesc::Write(char * aPlace)
       
   105 {
       
   106 	memcpy(aPlace+iOffset, iData, iSize);
       
   107 }
       
   108 
       
   109 /**
       
   110 Constructor for E32ImageChunks class.
       
   111 @internalComponent
       
   112 @released
       
   113 */
       
   114 E32ImageChunks::E32ImageChunks(): 
       
   115 	iOffset(0)
       
   116 {
       
   117 }
       
   118 
       
   119 /**
       
   120 Destructor for E32ImageChunks class.
       
   121 @internalComponent
       
   122 @released
       
   123 */
       
   124 E32ImageChunks::~E32ImageChunks()
       
   125 {	
       
   126  	if(iChunks.size())
       
   127  	{
       
   128  		ChunkList::iterator aItr = iChunks.begin();
       
   129  		ChunkList::iterator last = iChunks.end();
       
   130  		E32ImageChunkDesc *temp;
       
   131  
       
   132  		while( aItr != last)
       
   133  		{
       
   134  			temp = *aItr;
       
   135  			aItr++;
       
   136  			delete temp;
       
   137  		}
       
   138  	}
       
   139 }
       
   140 
       
   141 /**
       
   142 This function creates and adds a chunk into a list.
       
   143 @param aData - input buffer
       
   144 @param asize - size of the input buffer
       
   145 @param aOffset - byte offset of this chunk from the 1 byte in e32 image file.
       
   146 @param aDoc - name of the chunk
       
   147 @internalComponent
       
   148 @released
       
   149 */
       
   150 void E32ImageChunks::AddChunk(char * aData, size_t aSize, size_t aOffset, char * aDoc)
       
   151 {
       
   152 	E32ImageChunkDesc * aChunk = new E32ImageChunkDesc(aData, aSize, aOffset, aDoc);
       
   153 	iChunks.push_back(aChunk);
       
   154 	iOffset += Align(aSize, sizeof(TUint32));
       
   155 }
       
   156 
       
   157 /**
       
   158 This function returns the list of chunks.
       
   159 @internalComponent
       
   160 @released
       
   161 */
       
   162 E32ImageChunks::ChunkList & E32ImageChunks::GetChunks()
       
   163 {
       
   164 	return iChunks;
       
   165 }
       
   166 
       
   167 /**
       
   168 This function returns the current offset pointing to the last chunk that
       
   169 was added into the list of chunks.
       
   170 @internalComponent
       
   171 @released
       
   172 */
       
   173 size_t E32ImageChunks::GetOffset()
       
   174 {
       
   175 	return iOffset;
       
   176 }
       
   177 
       
   178 /**
       
   179 This function sets the current offset pointing to the last chunk that 
       
   180 was added into the list of chunks.
       
   181 @internalComponent
       
   182 @released
       
   183 */
       
   184 void E32ImageChunks::SetOffset(size_t aOffset)
       
   185 {
       
   186 	iOffset = aOffset;
       
   187 }
       
   188 
       
   189 /**
       
   190 Constructor for E32ImageFile class.
       
   191 @internalComponent
       
   192 @released
       
   193 */
       
   194 E32ImageFile::E32ImageFile(const char * aFileName, ElfExecutable * aExecutable, ElfFileSupplied *aUseCase) :
       
   195 	iFileName(aFileName), 
       
   196 	iE32Image(0),
       
   197 	iExportBitMap(0),
       
   198 	iElfExecutable(aExecutable), 
       
   199 	iData(0),
       
   200 	iUseCase(aUseCase),
       
   201 	iHdr(0),
       
   202 	iHdrSize(sizeof(E32ImageHeaderV)),
       
   203 	iImportSection(0), 
       
   204 	iImportSectionSize(0),
       
   205 	iCodeRelocs(0), 
       
   206 	iCodeRelocsSize(0),
       
   207 	iDataRelocs(0), 
       
   208 	iDataRelocsSize(0),
       
   209 	iExportOffset(0),
       
   210 	iLayoutDone(false), 
       
   211 	iMissingExports(0),
       
   212 	iSymNameOffset(0)
       
   213 {
       
   214 }
       
   215 
       
   216 /**
       
   217 This function generates the E32 image.
       
   218 @internalComponent
       
   219 @released
       
   220 */
       
   221 void E32ImageFile::GenerateE32Image()
       
   222 {
       
   223 	if( iUseCase->GetNamedSymLookup() ){
       
   224 		ProcessSymbolInfo();
       
   225 	}
       
   226 	ProcessImports();
       
   227 	ProcessRelocations();
       
   228 	ConstructImage();
       
   229 }
       
   230 
       
   231 /**
       
   232 This function processes the import map by looking into the dso files
       
   233 from which the symbols are imported. It also fetches the ordinal numbers
       
   234 for the corresponding symbols.
       
   235 @internalComponent
       
   236 @released
       
   237 */
       
   238 void E32ImageFile::ProcessImports()
       
   239 {
       
   240 	string aStrTab;
       
   241 	vector<int> aStrTabOffsets;
       
   242 	int aNumDlls = 0;
       
   243 	int aNumImports = 0;
       
   244 	bool aNamedLookup = iUseCase->GetNamedSymLookup();
       
   245 	TUint aImportTabEntryPos = 0;
       
   246 
       
   247 	ElfImports::ImportMap aImportMap = iElfExecutable->GetImports();
       
   248 	ElfImports::ImportMap::iterator p;
       
   249 
       
   250 	// First set up the string table and record offsets into string table of each 
       
   251 	// LinkAs name.
       
   252 	for (p = aImportMap.begin(); p != aImportMap.end(); p++)
       
   253 	{
       
   254 		ElfImports::RelocationList & aImports = (*p).second;
       
   255 		char* aLinkAs = aImports[0]->iVerRecord->iLinkAs;
       
   256 
       
   257 		aStrTabOffsets.push_back(aStrTab.size()); // 
       
   258 		string s = aLinkAs;
       
   259 		aStrTab.insert(aStrTab.end(),s.begin(),s.end());
       
   260 		aStrTab.insert(aStrTab.end(),0);
       
   261 		aNumDlls++;
       
   262 		aNumImports += aImports.size();
       
   263 	}
       
   264 	
       
   265 	iNumDlls = aNumDlls;
       
   266 	iNumImports = aNumImports;
       
   267 
       
   268 	// Now we can figure out the size of everything
       
   269 	size_t aImportSectionSize = sizeof(E32ImportSection) + 
       
   270 								(sizeof(E32ImportBlock) * aNumDlls) +
       
   271 								(sizeof(unsigned int) * aNumImports);
       
   272  
       
   273 	vector<Elf32_Word> aImportSection;
       
   274 
       
   275 	// This is the 'E32ImportSection' header - fill with 0 for the moment
       
   276 	aImportSection.push_back(0);
       
   277 
       
   278 	if( aNamedLookup ) {
       
   279 		// These are the 0th ordinals imported into the import table, one
       
   280 		// entry for each DLL.
       
   281 		aImportSectionSize += (sizeof(unsigned int) * aNumDlls);
       
   282 	}
       
   283 	// Now fill in the E32ImportBlocks
       
   284 	int idx = 0;
       
   285 	char * aDsoName;
       
   286 	for (p = aImportMap.begin(); p != aImportMap.end(); p++, idx++)
       
   287 	{
       
   288 		ElfImports::RelocationList & aImports = (*p).second;
       
   289 		aDsoName = aImports[0]->iVerRecord->iSOName;
       
   290 
       
   291 		//const char * aDSO = FindDSO((*p).first);
       
   292 		const char * aDSO = FindDSO(aDsoName);
       
   293 
       
   294 		aImportSection.push_back(aStrTabOffsets[idx] + aImportSectionSize); 
       
   295 		int nImports = aImports.size();
       
   296 
       
   297 		// Take the additional 0th ordinal import into account
       
   298 		if( aNamedLookup )
       
   299 			nImports++;
       
   300 		aImportSection.push_back(nImports);
       
   301 
       
   302 		size_t aSize;
       
   303 		Elf32_Ehdr * aElfFile = 0;
       
   304 		ReadInputELFFile(aDSO, aSize, aElfFile);
       
   305 
       
   306 		ElfExecutable aElfExecutable(NULL);//(aElfFile, aSize);
       
   307 		aElfExecutable.ProcessElfFile(aElfFile);
       
   308 
       
   309 		ElfImports::RelocationList::iterator q;
       
   310 		for (q = aImports.begin(); q != aImports.end(); q++)
       
   311 		{
       
   312 			ElfImportRelocation * aReloc = *q;
       
   313 			char * aSymName = iElfExecutable->GetSymbolName(aReloc->iSymNdx);
       
   314 			unsigned int aOrdinal = aElfExecutable.GetSymbolOrdinal(aSymName);
       
   315 			
       
   316 			//check the reloc refers to Code Segment
       
   317 			try
       
   318 			{
       
   319 				if (iElfExecutable->SegmentType(aReloc->iAddr) != ESegmentRO)
       
   320 				{
       
   321 					throw ImportRelocationError(ILLEGALEXPORTFROMDATASEGMENT, aSymName, iElfExecutable->iParameterListInterface->ElfInput());
       
   322 				}
       
   323 			}
       
   324 			/**This catch block introduced here is to avoid deleting partially constructed object(s).
       
   325 			Otherwise global catch block will delete the partially constructed object(s) and the tool will crash.
       
   326 			*/
       
   327 			catch(ErrorHandler& aError)
       
   328 			{
       
   329 				aError.Report();
       
   330 				exit(EXIT_FAILURE);
       
   331 			}
       
   332 				
       
   333 			Elf32_Word aRelocOffset = iElfExecutable->GetRelocationOffset(aReloc);
       
   334 			aImportSection.push_back(aRelocOffset);
       
   335 
       
   336 			Elf32_Word * aRelocPlace = iElfExecutable->GetRelocationPlace(aReloc);
       
   337 			if (aOrdinal > 0xFFFF)
       
   338 			{
       
   339 			}
       
   340 			if (aReloc->iAddend > 0xFFFF)
       
   341 			{
       
   342 			}
       
   343 			* aRelocPlace = (aReloc->iAddend<<16) | aOrdinal;
       
   344 		}
       
   345 
       
   346 		if( aNamedLookup ) {
       
   347 			aImportTabEntryPos = aImportSection.size();
       
   348 			// Keep track of the location of the entry
       
   349 			iImportTabLocations.push_back(aImportTabEntryPos);
       
   350 			// Put the entry as 0 now, which shall be updated 
       
   351 			aImportSection.push_back(0);
       
   352 		}
       
   353 
       
   354 		delete [] ((char*)aElfFile);
       
   355 	}
       
   356 
       
   357 	assert(aImportSectionSize == aImportSection.size() * sizeof(Elf32_Word));
       
   358 
       
   359 	size_t aTotalSize = Align(aImportSectionSize + aStrTab.size(), sizeof(Elf32_Word));
       
   360 
       
   361 	// Fill in the section header now we have the correct value.
       
   362 	aImportSection[0] = aTotalSize;
       
   363 
       
   364 	// Now construct the unified section
       
   365 	iImportSectionSize = aTotalSize;
       
   366 	iImportSection = (uint32 *)new char[aTotalSize];
       
   367 	memset(iImportSection, 0, aTotalSize);
       
   368 	memcpy(iImportSection, aImportSection.begin(), aImportSectionSize);
       
   369 	char * strTab = ((char *)iImportSection) + aImportSectionSize;
       
   370 	memcpy(strTab, aStrTab.data(), aStrTab.size());
       
   371 
       
   372 }
       
   373 
       
   374 
       
   375 /**
       
   376 This function checks if a DSO file exists.
       
   377 @param aPath - DSO file name.
       
   378 @internalComponent
       
   379 @released
       
   380 */
       
   381 static bool ProbePath(string & aPath)
       
   382 {
       
   383 	ifstream aInput;
       
   384 	const char * p = aPath.c_str();
       
   385 	aInput.open(p);
       
   386 	if (aInput.is_open())
       
   387 	{
       
   388 		aInput.close();
       
   389 		return true;
       
   390 	}
       
   391 	else
       
   392 	{
       
   393 		return false;
       
   394 	}
       
   395 }
       
   396 
       
   397 /**
       
   398 This function allocates space for a DSO file name.
       
   399 @param aPath - DSO file name
       
   400 @internalComponent
       
   401 @released
       
   402 */
       
   403 const char * AllocatePath(string & aPath)
       
   404 {
       
   405 	const char * p = aPath.c_str();
       
   406 	size_t len = aPath.size();
       
   407 	char * result = new char[len+1];
       
   408 	strcpy(result, p);
       
   409 	return (const char *)result;
       
   410 }
       
   411 
       
   412 /**
       
   413 This function searches for a DSO in the libpath specified.
       
   414 @param aName - DSO file name
       
   415 @internalComponent
       
   416 @released
       
   417 */
       
   418 const char * E32ImageFile::FindDSO(const char * aName)
       
   419 {
       
   420 	string aDSOName(aName);
       
   421 	string aDSOPath(aName);
       
   422 
       
   423 	const char *aNewDsoName;
       
   424 
       
   425 	if (ProbePath(aDSOName))
       
   426 	{
       
   427 		aNewDsoName = AllocatePath(aDSOName);
       
   428 		cleanupStack.push_back((char*)aNewDsoName);
       
   429 		return aNewDsoName;
       
   430 	}
       
   431 
       
   432 	ParameterListInterface::LibSearchPaths & paths = iUseCase->GetLibSearchPaths();
       
   433 	ParameterListInterface::LibSearchPaths::iterator p = paths.begin();
       
   434 	for (; p != paths.end(); p++)
       
   435 	{
       
   436 		string path(*p);
       
   437 		char dir = iUseCase->GetDirectorySeparator();
       
   438 		aDSOPath.erase();
       
   439 		aDSOPath.insert(aDSOPath.end(), path.begin(), path.end());
       
   440 		aDSOPath.insert(aDSOPath.end(), dir);
       
   441 		aDSOPath.insert(aDSOPath.end(), aDSOName.begin(), aDSOName.end());
       
   442 		if (ProbePath(aDSOPath))
       
   443 		{
       
   444 			aNewDsoName = AllocatePath(aDSOPath);
       
   445 			cleanupStack.push_back((char*)aNewDsoName);
       
   446 			return aNewDsoName;
       
   447 		}
       
   448 	}
       
   449 	throw ELFFileError(DSONOTFOUNDERROR,(char*)aName);
       
   450 }
       
   451 
       
   452 void E32ImageFile::ReadInputELFFile(const char * aName, size_t & aFileSize, Elf32_Ehdr * & aELFFile )
       
   453 {
       
   454 	ifstream aInput;
       
   455 	aInput.open(aName, ifstream::binary|ifstream::in);
       
   456 	if (aInput.is_open()) 
       
   457 	{
       
   458 		aInput.seekg(0,ios::end);
       
   459 		aFileSize = (unsigned int) aInput.tellg();
       
   460 		aInput.seekg(0,ios::beg);
       
   461 		aELFFile = (Elf32_Ehdr *)new char [aFileSize];
       
   462 		aInput.read((char *)aELFFile, aFileSize);
       
   463 		aInput.close();
       
   464 	} 
       
   465 	else
       
   466 	{
       
   467 		throw FileError(FILEOPENERROR,(char*)aName);
       
   468 	}
       
   469 }
       
   470 
       
   471 /**
       
   472 This function processes relocations.
       
   473 @internalComponent
       
   474 @released
       
   475 */
       
   476 void E32ImageFile::ProcessRelocations()
       
   477 {
       
   478 	ProcessCodeRelocations();
       
   479 	ProcessDataRelocations();
       
   480 }
       
   481 
       
   482 /**
       
   483 This function processes Code relocations.
       
   484 @internalComponent
       
   485 @released
       
   486 */
       
   487 void E32ImageFile::ProcessCodeRelocations()
       
   488 {
       
   489 	CreateRelocations(iElfExecutable->GetCodeRelocations(), iCodeRelocs, iCodeRelocsSize);
       
   490 }
       
   491 
       
   492 /**
       
   493 This function processes Data relocations.
       
   494 @internalComponent
       
   495 @released
       
   496 */
       
   497 void E32ImageFile::ProcessDataRelocations()
       
   498 {
       
   499 	CreateRelocations(iElfExecutable->GetDataRelocations(), iDataRelocs, iDataRelocsSize);
       
   500 }
       
   501 
       
   502 /**
       
   503 This function creates Code and Data relocations from the corresponding
       
   504 ELF form to E32 form.
       
   505 @internalComponent
       
   506 @released
       
   507 */
       
   508 void E32ImageFile::CreateRelocations(ElfRelocations::RelocationList & aRelocList, char * & aRelocs, size_t & aRelocsSize)
       
   509 {
       
   510 	size_t rsize = RelocationsSize(aRelocList);
       
   511 	if (rsize)
       
   512 	{
       
   513 		aRelocsSize = Align(rsize + sizeof(E32RelocSection), sizeof(uint32));
       
   514 
       
   515 		uint32 aBase = (*aRelocList.begin())->iSegment->p_vaddr;
       
   516 		//add for cleanup to be done later..
       
   517 		cleanupStack.push_back(aRelocs);
       
   518 		aRelocs =	new char [aRelocsSize];
       
   519 		memset(aRelocs, 0, aRelocsSize);
       
   520 		E32RelocSection * aRelocSection = (E32RelocSection * )aRelocs;
       
   521 
       
   522 		uint16 * data = (uint16 *)(aRelocSection + 1);
       
   523 		E32RelocPageDesc * startofblock = (E32RelocPageDesc *)data;
       
   524 
       
   525 		int page = -1;
       
   526 		int pagesize = sizeof(E32RelocPageDesc);
       
   527 		ElfRelocations::RelocationList::iterator r;
       
   528 		for (r = aRelocList.begin(); r != aRelocList.end(); r++)
       
   529 		{
       
   530 			ElfLocalRelocation * aReloc = *r;
       
   531 			int p = aReloc->iAddr & 0xfffff000;
       
   532 			if (page != p)
       
   533 			{
       
   534 				if (pagesize%4 != 0)
       
   535 				{
       
   536 					*data++ = 0;
       
   537 					pagesize += sizeof(uint16);
       
   538 				}
       
   539 				if (page == -1) page = p;
       
   540 				startofblock->aOffset = page - aBase;
       
   541 				startofblock->aSize = pagesize;
       
   542 				pagesize = sizeof(E32RelocPageDesc);
       
   543 				page = p;
       
   544 				startofblock = (E32RelocPageDesc *)data;
       
   545 				data = (uint16 *)(startofblock + 1);
       
   546 			}
       
   547 			uint16 relocType = aReloc->Fixup();
       
   548 			*data++ = (uint16)((aReloc->iAddr & 0xfff) | relocType);
       
   549 			pagesize += sizeof(uint16);
       
   550 		}
       
   551 		if (pagesize%4 != 0)
       
   552 		{
       
   553 			*data++ = 0;
       
   554 			pagesize += sizeof(uint16);
       
   555 		}
       
   556 		startofblock->aOffset = page - aBase;
       
   557 		startofblock->aSize = pagesize;
       
   558 		((E32RelocSection *)aRelocs)->iNumberOfRelocs = aRelocList.size();
       
   559 		((E32RelocSection *)aRelocs)->iSize = rsize;
       
   560 
       
   561 	}
       
   562 }
       
   563 
       
   564 /**
       
   565 This function calculates the relocation taking into consideration
       
   566 the page boundaries if they are crossed. The relocations are
       
   567 sorted.
       
   568 @param aRelocList - relocations found in the Elf file.
       
   569 @internalComponent
       
   570 @released
       
   571 */
       
   572 size_t E32ImageFile::RelocationsSize(ElfRelocations::RelocationList & aRelocList)
       
   573 {
       
   574 	size_t bytecount = 0;
       
   575 	int page = -1;
       
   576 	ElfRelocations::RelocationList::iterator r;
       
   577 	for (r = aRelocList.begin(); r != aRelocList.end(); r++)
       
   578 	{
       
   579 		ElfLocalRelocation * aReloc = *r;
       
   580 		int p = aReloc->iAddr & 0xfffff000;
       
   581 		if (page != p)
       
   582 			{
       
   583 			if (bytecount%4 != 0)
       
   584 				bytecount += sizeof(uint16);
       
   585 			bytecount += sizeof(E32RelocPageDesc); // page, block size
       
   586 			page = p;
       
   587 			}
       
   588 		bytecount += sizeof(uint16);
       
   589 		}
       
   590 	if (bytecount%4 != 0)
       
   591 		bytecount += sizeof(uint16);
       
   592 	return bytecount;
       
   593 }
       
   594 
       
   595 /**
       
   596 This function returns the E32 interpretation for an Elf relocation type.
       
   597 @param aReloc - relocation entry.
       
   598 @internalComponent
       
   599 @released
       
   600 */
       
   601 E32ImageFile::uint16 E32ImageFile::GetE32RelocType(ElfRelocation * aReloc)
       
   602 {
       
   603 	ESegmentType aSegType = aReloc->iSegmentType; // iElfExecutable->SegmentType(aReloc->iSymbol->st_value);
       
   604 	switch (aSegType)
       
   605 	{
       
   606 	case ESegmentRO:
       
   607 		return KTextRelocType;
       
   608 	case ESegmentRW:
       
   609 		return KDataRelocType;
       
   610 	default:
       
   611 		break;
       
   612 	};
       
   613 
       
   614 	// maybe this should be an error
       
   615 	return KInferredRelocType;
       
   616 }
       
   617 
       
   618 /**
       
   619 This function constructs the E32 image.
       
   620 @internalComponent
       
   621 @released
       
   622 */
       
   623 void E32ImageFile::ConstructImage()
       
   624 {
       
   625 	InitE32ImageHeader();
       
   626 	ComputeE32ImageLayout();
       
   627 	FinalizeE32Image();
       
   628 	AllocateE32Image();
       
   629 }
       
   630 
       
   631 /**
       
   632 This function calculates the timestamp.
       
   633 @param aTime
       
   634 @internalComponent
       
   635 @released
       
   636 */
       
   637 Int64 timeToInt64(TInt aTime)
       
   638 {
       
   639 	aTime-=(30*365*24*60*60+7*24*60*60);	// seconds since midnight Jan 1st, 2000
       
   640 	Int64 daysTo2000AD=730497;
       
   641 	Int64 t=daysTo2000AD*24*3600+aTime;	// seconds since 0000
       
   642 	t=t+3600;								// BST (?)
       
   643 	return t*1000000;						// milliseconds
       
   644 }
       
   645 
       
   646 /**
       
   647 This function returns the E32 image header size.
       
   648 @internalComponent
       
   649 @released
       
   650 */
       
   651 size_t E32ImageFile::GetE32ImageHeaderSize()
       
   652 {
       
   653 	return sizeof(E32ImageHeaderV);
       
   654 }
       
   655 
       
   656 /**
       
   657 This function returns the extended E32 image header size.
       
   658 @internalComponent
       
   659 @released
       
   660 */
       
   661 size_t E32ImageFile::GetExtendedE32ImageHeaderSize()
       
   662 {
       
   663 	return iHdrSize;
       
   664 }
       
   665 
       
   666 /**
       
   667 This function sets the extended E32 image header size.
       
   668 @internalComponent
       
   669 @released
       
   670 */
       
   671 void E32ImageFile::SetExtendedE32ImageHeaderSize(size_t aSize)
       
   672 {
       
   673 	iHdrSize = aSize;
       
   674 }
       
   675 
       
   676 /**
       
   677 This function initialises the E32 image header fields.
       
   678 @internalComponent
       
   679 @released
       
   680 */
       
   681 void E32ImageFile::InitE32ImageHeader()
       
   682 {
       
   683 	iHdr = iUseCase->AllocateE32ImageHeader();
       
   684 	
       
   685 	iHdr->iUid1 = 0;
       
   686 	iHdr->iUid2 = 0;
       
   687 	iHdr->iUid3 = 0;
       
   688 	iHdr->iHeaderCrc = 0;
       
   689 	iHdr->iSignature = 0x434f5045u;
       
   690 	iHdr->iModuleVersion = 0x00010000u;
       
   691 	iHdr->iCompressionType = 0;
       
   692 	iHdr->iToolsVersion = TVersion(MajorVersion, MinorVersion, Build);
       
   693 	Int64 ltime(timeToInt64(time(0)));
       
   694 	iHdr->iTimeLo=(uint32)ltime;
       
   695 	iHdr->iTimeHi=(uint32)(ltime>>32);
       
   696 	iHdr->iFlags = KImageHdrFmt_V;
       
   697 	// Confusingly, CodeSize means everything except writable data
       
   698 	iHdr->iCodeSize = 0;
       
   699 	iHdr->iDataSize = iElfExecutable->GetRWSize();
       
   700 	iHdr->iHeapSizeMin = 0;
       
   701 	iHdr->iHeapSizeMax = 0;
       
   702 	iHdr->iStackSize = 0;
       
   703 	iHdr->iBssSize = iElfExecutable->GetBssSize();
       
   704 	iHdr->iEntryPoint = 0;
       
   705 	iHdr->iCodeBase = iElfExecutable->GetROBase();
       
   706 	iHdr->iDataBase = iElfExecutable->GetRWBase();
       
   707 	iHdr->iDllRefTableCount = iNumDlls;
       
   708 	iHdr->iExportDirOffset = 0;
       
   709 	iHdr->iExportDirCount = iUseCase->GetNumExports();
       
   710 	iHdr->iTextSize = iElfExecutable->GetROSize();
       
   711 	iHdr->iCodeOffset = 0;
       
   712 	iHdr->iDataOffset = 0;
       
   713 	iHdr->iImportOffset = 0;
       
   714 	iHdr->iCodeRelocOffset = 0;
       
   715 	iHdr->iDataRelocOffset = 0;
       
   716 	iHdr->iProcessPriority = (uint16)EPriorityForeground;
       
   717 	iHdr->iUncompressedSize = 0;
       
   718 	iHdr->iS.iSecureId = 0;
       
   719 	iHdr->iS.iVendorId = 0;
       
   720 	iHdr->iExceptionDescriptor = 0;
       
   721 	iHdr->iSpare2 = 0;
       
   722 
       
   723 	iHdr->iExportDescSize = iUseCase->GetExportDescSize();
       
   724 	iHdr->iExportDescType = iUseCase->GetExportDescType();
       
   725 	if (iHdr->iExportDescSize == 0) iHdr->iExportDesc[0] = 0;
       
   726 
       
   727 }
       
   728 
       
   729 /**
       
   730 This function creates the E32 image layout.
       
   731 @internalComponent
       
   732 @released
       
   733 */
       
   734 void E32ImageFile::ComputeE32ImageLayout()
       
   735 {
       
   736 	// E32Image header
       
   737 	iChunks.AddChunk((char *)iHdr, Align(GetExtendedE32ImageHeaderSize(), sizeof(uint32)), 0, "Image Header");
       
   738 
       
   739 	uint32 endOfHeader = iChunks.GetOffset();
       
   740 	
       
   741 		// Code section
       
   742 	iHdr->iCodeOffset = iChunks.GetOffset();
       
   743 	iChunks.AddChunk(iElfExecutable->GetRawROSegment(), iElfExecutable->GetROSize(), iHdr->iCodeOffset, "Code Section"); 
       
   744 	
       
   745 	// Exports Next - then we can set up CodeSize
       
   746 	// Call out to the use case so it can decide how we do this
       
   747 	// record exporttable offset for default case
       
   748 
       
   749 	bool aSymLkupEnabled = iUseCase->GetNamedSymLookup();
       
   750 	// The export table is required either when:
       
   751 	//	a. there are exported symbols
       
   752 	//	b. symbol lookup is enabled - because this table also indicates the dependencies
       
   753 	bool aExportTableNeeded = (iHdr->iExportDirCount || aSymLkupEnabled) ? 1 : 0;
       
   754 
       
   755 	iExportOffset = iChunks.GetOffset() + 4;
       
   756 	iHdr->iExportDirOffset = aExportTableNeeded ? iUseCase->GetExportOffset() : 0;
       
   757 	if ( aExportTableNeeded && iUseCase->AllocateExportTableP())
       
   758 		iChunks.AddChunk(iUseCase->GetExportTable(), iUseCase->GetExportTableSize(), iChunks.GetOffset(), "Export Table");
       
   759 
       
   760 	// Symbol info next
       
   761 	if( aSymLkupEnabled ){
       
   762 		E32EpocExpSymInfoHdr* aSymHdrInfo = (E32EpocExpSymInfoHdr*)CreateSymbolInfo(iChunks.GetOffset());
       
   763 		if( aSymHdrInfo )
       
   764 			iChunks.AddChunk( (char*)aSymHdrInfo, aSymHdrInfo->iSize, iChunks.GetOffset(), "Symbol Info" );
       
   765 	}
       
   766 
       
   767 	// CodeSize is current offset - endof header offset
       
   768 	iHdr->iTextSize = iHdr->iCodeSize = iChunks.GetOffset() - endOfHeader;
       
   769 
       
   770 	// Data section
       
   771 	if (iElfExecutable->GetRWSize())
       
   772 	{
       
   773 		iHdr->iDataOffset = iChunks.GetOffset();
       
   774 		iChunks.AddChunk(iElfExecutable->GetRawRWSegment(), iElfExecutable->GetRWSize(), iHdr->iDataOffset, "Data Section");
       
   775 	}
       
   776 	
       
   777 	// Import Section
       
   778 	if (iImportSectionSize)
       
   779 	{
       
   780 		iHdr->iImportOffset = iChunks.GetOffset();
       
   781 		iChunks.AddChunk((char *)iImportSection, iImportSectionSize, iHdr->iImportOffset, "Import Section");
       
   782 	}
       
   783 
       
   784 	// Code relocs
       
   785 	if (iCodeRelocsSize)
       
   786 	{
       
   787 		iHdr->iCodeRelocOffset = iChunks.GetOffset();
       
   788 		iChunks.AddChunk((char *)iCodeRelocs, iCodeRelocsSize, iHdr->iCodeRelocOffset, "Code Relocs");
       
   789 	}
       
   790 
       
   791 	// Data relocs
       
   792 	if (iDataRelocsSize)
       
   793 	{
       
   794 		iHdr->iDataRelocOffset = iChunks.GetOffset();
       
   795 		iChunks.AddChunk((char *)iDataRelocs, iDataRelocsSize, iHdr->iDataRelocOffset, "Data Relocs");
       
   796 	}
       
   797 
       
   798 	iLayoutDone = true;
       
   799 }
       
   800 
       
   801 /**
       
   802 This function returns the byte offset in the E32 image from where the
       
   803 export table starts.
       
   804 @internalComponent
       
   805 @released
       
   806 */
       
   807 size_t E32ImageFile::GetExportOffset()
       
   808 {
       
   809 	return iExportOffset;
       
   810 }
       
   811 
       
   812 /**
       
   813 This function returns E32 image size.
       
   814 @internalComponent
       
   815 @released
       
   816 */
       
   817 size_t E32ImageFile::GetE32ImageSize()
       
   818 {
       
   819 	assert(iLayoutDone);
       
   820 	return iChunks.GetOffset();
       
   821 
       
   822 }
       
   823 
       
   824 /**
       
   825 This function creates the export bitmap also replacing the absent symbols 
       
   826 with the entry point functions.
       
   827 @internalComponent
       
   828 @released
       
   829 */
       
   830 void E32ImageFile::CreateExportBitMap()
       
   831 {
       
   832 	int nexp = iUseCase->GetNumExports();
       
   833 	size_t memsz = (nexp + 7) >> 3;
       
   834 	iExportBitMap = new uint8[memsz];
       
   835 	memset(iExportBitMap, 0xff, memsz);
       
   836 	// skip header
       
   837 	uint32 * exports = ((uint32 *)iUseCase->GetExportTable()) + 1;
       
   838 	uint32 absentVal = EntryPointOffset() + iElfExecutable->GetROBase();
       
   839 	iMissingExports = 0;
       
   840 	for (int i=0; i<nexp; ++i)
       
   841 	{
       
   842 		if (exports[i] == absentVal)
       
   843 		{
       
   844 			iExportBitMap[i>>3] &= ~(1u << (i & 7));
       
   845 			++iMissingExports;
       
   846 		}
       
   847 	}
       
   848 }
       
   849 
       
   850 /**
       
   851 This function creates export desription for the absent symbols.
       
   852 @internalComponent
       
   853 @released
       
   854 */
       
   855 void E32ImageFile::AddExportDescription()
       
   856 {
       
   857 	CreateExportBitMap();
       
   858 	if (iMissingExports == 0)
       
   859 		return;	// nothing to do
       
   860 
       
   861 	int nexp = iUseCase->GetNumExports();
       
   862 	size_t memsz = (nexp + 7) >> 3;	// size of complete bitmap
       
   863 	size_t mbs = (memsz + 7) >> 3;	// size of meta-bitmap
       
   864 	size_t nbytes = 0;
       
   865 	unsigned int i;
       
   866 	for (i=0; i<memsz; ++i)
       
   867 		if (iExportBitMap[i] != 0xff)
       
   868 			++nbytes;				// number of groups of 8
       
   869 	uint8 edt = KImageHdr_ExpD_FullBitmap;
       
   870 	uint32 extra_space = memsz - 1;
       
   871 	if (mbs + nbytes < memsz)
       
   872 	{
       
   873 		edt = KImageHdr_ExpD_SparseBitmap8;
       
   874 		extra_space = mbs + nbytes - 1;
       
   875 	}
       
   876 	extra_space = (extra_space + sizeof(uint32) - 1) &~ (sizeof(uint32) - 1);
       
   877 
       
   878 	iHdr->iExportDescType = edt;
       
   879 	if (edt == KImageHdr_ExpD_FullBitmap)
       
   880 	{
       
   881 		iHdr->iExportDescSize = (uint16)memsz;
       
   882 		iHdr->iExportDesc[0] = iExportBitMap[0];
       
   883 		uint8 * aDesc = new uint8[extra_space];
       
   884 		memset(aDesc, 0, extra_space);
       
   885 		memcpy(aDesc, &iExportBitMap[1], memsz-1);
       
   886 		iChunks.AddChunk((char *)aDesc,extra_space, iChunks.GetOffset(), "Export Description");
       
   887 	}
       
   888 	else
       
   889 	{
       
   890 		iHdr->iExportDescSize = (uint16)(mbs + nbytes);
       
   891 		uint8 * aBuf = new uint8[extra_space + 1];
       
   892 		memset(aBuf , 0, extra_space + 1);
       
   893 		TUint8* mptr = aBuf;
       
   894 		TUint8* gptr = mptr + mbs;
       
   895 		for (i=0; i<memsz; ++i)
       
   896 		{
       
   897 			if (iExportBitMap[i] != 0xff)
       
   898 			{
       
   899 				mptr[i>>3] |= (1u << (i&7));
       
   900 				*gptr++ = iExportBitMap[i];
       
   901 			}
       
   902 		}
       
   903 		iHdr->iExportDesc[0] = aBuf[0];
       
   904 		uint8 * aDesc = new uint8[extra_space];
       
   905 		memcpy(aDesc, aBuf+1, extra_space);
       
   906 		delete[] aBuf;
       
   907 		iChunks.AddChunk((char *)aDesc,extra_space, iChunks.GetOffset(), "Export Description");
       
   908 	}
       
   909 }
       
   910 
       
   911 /**
       
   912 This function sets the fields of the E32 image.
       
   913 @internalComponent
       
   914 @released
       
   915 */
       
   916 void E32ImageFile::FinalizeE32Image()
       
   917 {
       
   918 	// Arrange a header for this E32 Image
       
   919 	iHdr->iCpuIdentifier = GetCpuIdentifier();
       
   920 	// Import format is ELF-derived
       
   921 	iHdr->iFlags |= KImageImpFmt_ELF;
       
   922 	// ABI is ARM EABI
       
   923 	iHdr->iFlags |= KImageABI_EABI;
       
   924 	iHdr->iFlags |= KImageEpt_Eka2;
       
   925 
       
   926 	bool isDllp = iUseCase->ImageIsDll();
       
   927 	if (isDllp)
       
   928 	{
       
   929 		iHdr->iFlags |= KImageDll;
       
   930 		if (iHdr->iDataSize && !iUseCase->AllowDllData())
       
   931 			throw ELFFileError(DLLHASINITIALISEDDATAERROR, (char*)iUseCase->InputElfFileName());
       
   932 
       
   933 		if (iHdr->iBssSize  && !iUseCase->AllowDllData())
       
   934 			throw ELFFileError(DLLHASUNINITIALISEDDATAERROR, (char*)iUseCase->InputElfFileName());
       
   935 
       
   936 	}
       
   937 
       
   938 	iHdr->iHeapSizeMin = iUseCase->HeapCommittedSize();
       
   939 	iHdr->iHeapSizeMax = iUseCase->HeapReservedSize();
       
   940 	iHdr->iStackSize = iUseCase->StackCommittedSize();
       
   941 
       
   942 
       
   943 	iHdr->iEntryPoint = EntryPointOffset();
       
   944 
       
   945 	EEntryPointStatus r = ValidateEntryPoint();
       
   946 	if (r == EEntryPointCorrupt)
       
   947 		throw ELFFileError(ENTRYPOINTCORRUPTERROR, (char*)iUseCase->InputElfFileName());
       
   948 	else if (r == EEntryPointNotSupported)
       
   949 		throw ELFFileError(ENTRYPOINTNOTSUPPORTEDERROR, (char*)iUseCase->InputElfFileName());
       
   950 
       
   951 	SetUpExceptions();
       
   952 	SetUids();
       
   953 	SetSecureId();
       
   954 	SetVendorId();
       
   955 	SetCallEntryPoints();
       
   956 	SetCapability();
       
   957 	SetPriority(isDllp);
       
   958 	SetFixedAddress(isDllp);
       
   959 	SetVersion();
       
   960 	SetCompressionType();
       
   961 	SetFPU();
       
   962 
       
   963 	SetPaged();
       
   964 
       
   965 	SetSymbolLookup();
       
   966 	SetDebuggable();
       
   967 	SetSmpSafe();
       
   968 	UpdateHeaderCrc();
       
   969 }
       
   970 
       
   971 /**
       
   972 This function returns the CPU identifier for the E32 image header.
       
   973 @internalComponent
       
   974 @released
       
   975 */
       
   976 E32ImageFile::uint16 E32ImageFile::GetCpuIdentifier()
       
   977 {
       
   978 	return (uint16)ECpuArmV5;
       
   979 }
       
   980 
       
   981 /**
       
   982 This function returns the entry point of the E32 image .
       
   983 @internalComponent
       
   984 @released
       
   985 */
       
   986 E32ImageFile::uint32 E32ImageFile::EntryPointOffset()
       
   987 {
       
   988 	return iElfExecutable->EntryPointOffset();
       
   989 }
       
   990 
       
   991 /**
       
   992 This function validates the entry point of the E32 image .
       
   993 @internalComponent
       
   994 @released
       
   995 */
       
   996 E32ImageFile::EEntryPointStatus E32ImageFile::ValidateEntryPoint()
       
   997 {
       
   998 	uint32 epOffset = iHdr->iEntryPoint;
       
   999 	if (epOffset & 3)
       
  1000 		return EEntryPointOK;	// if entry point not 4 byte aligned, must be old style
       
  1001 	uint32 fileOffset = epOffset + iElfExecutable->iCodeSegmentHdr->p_offset;
       
  1002 	if (fileOffset+4 > iChunks.GetOffset())
       
  1003 		return EEntryPointCorrupt;	// entry point is past the end of the file??
       
  1004 	int ept = 0;			// old style if first instruction not recognised
       
  1005 	uint8 * p = ELF_ENTRY_PTR(uint8, iElfExecutable->iElfHeader, fileOffset + 4);
       
  1006 	uint32 x = *--p;
       
  1007 	x<<=8;
       
  1008 	x|=*--p;
       
  1009 	x<<=8;
       
  1010 	x|=*--p;
       
  1011 	x<<=8;
       
  1012 	x|=*--p;
       
  1013 	if ((x & 0xffffff00) == 0xe31f0000)
       
  1014 	{
       
  1015 		// starts with tst pc, #n - new entry point
       
  1016 		ept = (x & 0xff) + 1;
       
  1017 	}
       
  1018 	if (ept>7)
       
  1019 		return EEntryPointNotSupported;
       
  1020 	iHdr->iFlags |= (ept<<KImageEptShift);
       
  1021 	return EEntryPointOK;
       
  1022 }
       
  1023 
       
  1024 /**
       
  1025 This function sets the exciption descriptor in the E32 image .
       
  1026 @internalComponent
       
  1027 @released
       
  1028 */
       
  1029 void E32ImageFile::SetUpExceptions()
       
  1030 {
       
  1031 	char * aExDescName = "Symbian$$CPP$$Exception$$Descriptor";
       
  1032 	Elf32_Sym * aSym = iElfExecutable->LookupStaticSymbol(aExDescName);
       
  1033 	if (aSym)
       
  1034 	{
       
  1035 		uint32 aSymVaddr = aSym->st_value;
       
  1036 		uint32 aROBase = iElfExecutable->GetROBase();
       
  1037 		uint32 aROSize = iElfExecutable->GetROSize();
       
  1038 		//check its in RO segment
       
  1039 		if (aSymVaddr < aROBase || aSymVaddr >= (aROBase + aROSize))
       
  1040 		{
       
  1041 			throw ELFFileError(EXCEPTIONDESCRIPTOROUTSIDEROERROR,(char*)iUseCase->InputElfFileName());
       
  1042 		}
       
  1043 		// Set bottom bit so 0 in header slot means an old binary.
       
  1044 		// The decriptor is always aligned on a 4 byte boundary.
       
  1045 		iHdr->iExceptionDescriptor = (aSymVaddr - aROBase) | 0x00000001;
       
  1046 	}	
       
  1047 }
       
  1048 
       
  1049 /**
       
  1050 This function sets the UIDs of the E32 image .
       
  1051 @internalComponent
       
  1052 @released
       
  1053 */
       
  1054 void E32ImageFile::SetUids()
       
  1055 {
       
  1056 	iHdr->iUid1=iUseCase->GetUid1();
       
  1057 	iHdr->iUid2=iUseCase->GetUid2();
       
  1058 	iHdr->iUid3=iUseCase->GetUid3();
       
  1059 }
       
  1060 
       
  1061 /**
       
  1062 This function sets the secure ID of the E32 image as passed in the command line.
       
  1063 @internalComponent
       
  1064 @released
       
  1065 */
       
  1066 void E32ImageFile::SetSecureId()
       
  1067 {
       
  1068 	if (iUseCase->GetSecureIdOption())
       
  1069 		iHdr->iS.iSecureId = iUseCase->GetSecureId();
       
  1070 	else
       
  1071 		iHdr->iS.iSecureId = iUseCase->GetUid3();
       
  1072 }
       
  1073 
       
  1074 /**
       
  1075 This function sets the vendor Id of the E32 image as passed in command line.
       
  1076 @internalComponent
       
  1077 @released
       
  1078 */
       
  1079 void E32ImageFile::SetVendorId()
       
  1080 {
       
  1081 	iHdr->iS.iVendorId = iUseCase->GetVendorId();
       
  1082 }
       
  1083 
       
  1084 /**
       
  1085 This function sets the call entry point of the E32 image .
       
  1086 @internalComponent
       
  1087 @released
       
  1088 */
       
  1089 void E32ImageFile::SetCallEntryPoints()
       
  1090 {
       
  1091 	if (iUseCase->GetCallEntryPoints())
       
  1092 		iHdr->iFlags|=KImageNoCallEntryPoint;
       
  1093 	else
       
  1094 		iHdr->iFlags&=~KImageNoCallEntryPoint;
       
  1095 }
       
  1096 
       
  1097 /**
       
  1098 This function sets the capcbility of the E32 image as specified in the command line.
       
  1099 @internalComponent
       
  1100 @released
       
  1101 */
       
  1102 void E32ImageFile::SetCapability()
       
  1103 {
       
  1104 	iHdr->iS.iCaps = iUseCase->GetCapability();
       
  1105 }
       
  1106 
       
  1107 /**
       
  1108 This function sets the priority of the E32 exe.
       
  1109 @internalComponent
       
  1110 @released
       
  1111 */
       
  1112 void E32ImageFile::SetPriority(bool isDllp)
       
  1113 {
       
  1114 	if (iUseCase->GetPriority())
       
  1115 	{
       
  1116 		if (isDllp)
       
  1117 		{
       
  1118 			cerr << "Warning: Cannot set priority of a DLL." << endl;
       
  1119 		}
       
  1120 		else
       
  1121 			iHdr->iProcessPriority = (unsigned short)iUseCase->GetPriority();
       
  1122 	}
       
  1123 }
       
  1124 
       
  1125 /**
       
  1126 This function sets the fixed address flag of the E32 image .
       
  1127 @internalComponent
       
  1128 @released
       
  1129 */
       
  1130 void E32ImageFile::SetFixedAddress(bool isDllp)
       
  1131 {
       
  1132 	if (iUseCase->GetFixedAddress())
       
  1133 	{
       
  1134 		if (isDllp)
       
  1135 		{
       
  1136 			cerr << "Warning: Cannot set fixed address for DLL." << endl;
       
  1137 		}
       
  1138 		else
       
  1139 			iHdr->iFlags|=KImageFixedAddressExe;
       
  1140 	}
       
  1141 	else
       
  1142 		iHdr->iFlags&=~KImageFixedAddressExe;
       
  1143 }
       
  1144 
       
  1145 /**
       
  1146 This function sets the version of the E32 image .
       
  1147 @internalComponent
       
  1148 @released
       
  1149 */
       
  1150 void E32ImageFile::SetVersion()
       
  1151 {
       
  1152 	iHdr->iModuleVersion = iUseCase->GetVersion();
       
  1153 }
       
  1154 
       
  1155 /**
       
  1156 This function sets the compression type of the E32 image .
       
  1157 @internalComponent
       
  1158 @released
       
  1159 */
       
  1160 void E32ImageFile::SetCompressionType()
       
  1161 {
       
  1162 	if(iUseCase->GetCompress())
       
  1163 		iHdr->iCompressionType = iUseCase->GetCompressionMethod();
       
  1164 	else
       
  1165 		iHdr->iCompressionType = KFormatNotCompressed;
       
  1166 
       
  1167 }
       
  1168 
       
  1169 /**
       
  1170 This function sets the FPU type that the E32 image targets .
       
  1171 @internalComponent
       
  1172 @released
       
  1173 */
       
  1174 void E32ImageFile::SetFPU()
       
  1175 {
       
  1176 	iHdr->iFlags &=~ KImageHWFloatMask;
       
  1177 
       
  1178 	if (iUseCase->GetFPU() == 1)
       
  1179 		iHdr->iFlags |= KImageHWFloat_VFPv2;
       
  1180 }
       
  1181 
       
  1182 /**
       
  1183 This function sets the paging attribute in the E32 image.
       
  1184 @internalComponent
       
  1185 @released
       
  1186 */
       
  1187 void E32ImageFile::SetPaged()
       
  1188 {
       
  1189 	// Code paging.
       
  1190 
       
  1191 	if ( iUseCase->IsCodePaged() )
       
  1192 	{
       
  1193 		iHdr->iFlags |= KImageCodePaged;
       
  1194 		iHdr->iFlags &= ~KImageCodeUnpaged;
       
  1195 	}
       
  1196 	else if ( iUseCase->IsCodeUnpaged() )
       
  1197 	{
       
  1198 		iHdr->iFlags |= KImageCodeUnpaged;
       
  1199 		iHdr->iFlags &= ~KImageCodePaged;
       
  1200 	}
       
  1201 	else if ( iUseCase->IsCodeDefaultPaged() )
       
  1202 	{
       
  1203 		iHdr->iFlags &= ~KImageCodePaged;
       
  1204 		iHdr->iFlags &= ~KImageCodeUnpaged;
       
  1205 	}
       
  1206 
       
  1207 	// Data paging.
       
  1208 
       
  1209 	if ( iUseCase->IsDataPaged() )
       
  1210 	{
       
  1211 		iHdr->iFlags |=  KImageDataPaged;
       
  1212 		iHdr->iFlags &= ~KImageDataUnpaged;
       
  1213 	}
       
  1214 	else if ( iUseCase->IsDataUnpaged() )
       
  1215 	{
       
  1216 		iHdr->iFlags |=  KImageDataUnpaged;
       
  1217 		iHdr->iFlags &= ~KImageDataPaged;
       
  1218 	}
       
  1219 	else if ( iUseCase->IsDataDefaultPaged() )
       
  1220 	{
       
  1221 		iHdr->iFlags &= ~KImageDataPaged;
       
  1222 		iHdr->iFlags &= ~KImageDataUnpaged;
       
  1223 	}
       
  1224 }
       
  1225 
       
  1226 /**
       
  1227 This function sets the Debuggable attribute in the E32 image.
       
  1228 @internalComponent
       
  1229 @released
       
  1230 */
       
  1231 void E32ImageFile::SetDebuggable()
       
  1232 {
       
  1233 	if (iUseCase->IsDebuggable() == true)
       
  1234 	{
       
  1235 		iHdr->iFlags |= KImageDebuggable;
       
  1236 	}
       
  1237 	else
       
  1238 	{
       
  1239 		iHdr->iFlags &= ~KImageDebuggable;
       
  1240 	}
       
  1241 }
       
  1242 
       
  1243 
       
  1244 void E32ImageFile::SetSmpSafe()
       
  1245 {
       
  1246 	if ( iUseCase->IsSmpSafe() )
       
  1247 	{
       
  1248 		iHdr->iFlags |= KImageSMPSafe;
       
  1249 	}
       
  1250 	else
       
  1251 	{
       
  1252 		iHdr->iFlags &= ~KImageSMPSafe;
       
  1253 	}
       
  1254 }
       
  1255 
       
  1256 /**
       
  1257 This function sets the named symol-lookup attribute in the E32 image.
       
  1258 @internalComponent
       
  1259 @released
       
  1260 */
       
  1261 void E32ImageFile::SetSymbolLookup()
       
  1262 {
       
  1263 	if(iUseCase->GetNamedSymLookup())
       
  1264 	{
       
  1265 		iHdr->iFlags |= KImageNmdExpData;
       
  1266 	}
       
  1267 	else
       
  1268 	{
       
  1269 		iHdr->iFlags &= ~KImageNmdExpData;
       
  1270 	}
       
  1271 }
       
  1272 
       
  1273 /**
       
  1274 Class for Uids.
       
  1275 @internalComponent
       
  1276 @released
       
  1277 */
       
  1278 class TE32ImageUids
       
  1279 {
       
  1280 public:
       
  1281 	TE32ImageUids(TUint32 aUid1, TUint32 aUid2, TUint32 aUid3);
       
  1282 	void Set(const TUidType& aUidType);
       
  1283 	TUint Check() { return ((checkSum(((TUint8*)this)+1)<<16)|checkSum(this));}
       
  1284 private:
       
  1285 	TUidType iType;
       
  1286 	TUint iCheck;
       
  1287 
       
  1288 };
       
  1289 
       
  1290 /**
       
  1291 Constructor for TE32ImageUids.
       
  1292 @internalComponent
       
  1293 @released
       
  1294 */
       
  1295 TE32ImageUids::TE32ImageUids(TUint32 aUid1, TUint32 aUid2, TUint32 aUid3)
       
  1296 {
       
  1297 	Set(TUidType(TUid::Uid(aUid1), TUid::Uid(aUid2), TUid::Uid(aUid3)));
       
  1298 }
       
  1299 
       
  1300 /**
       
  1301 This function sets the Uid.
       
  1302 @internalComponent
       
  1303 @released
       
  1304 */
       
  1305 void TE32ImageUids::Set(const TUidType& aUidType)
       
  1306 {
       
  1307     iType=aUidType;
       
  1308     iCheck=Check();
       
  1309 }
       
  1310 
       
  1311 /**
       
  1312 Default constructor for TUidType class.
       
  1313 @internalComponent
       
  1314 @released
       
  1315 */
       
  1316 TUidType::TUidType()
       
  1317 {
       
  1318 	memset(this, 0, sizeof(TUidType));
       
  1319 }
       
  1320 
       
  1321 /**
       
  1322 Constructor for TUidType class.
       
  1323 @internalComponent
       
  1324 @released
       
  1325 */
       
  1326 TUidType::TUidType(TUid aUid1,TUid aUid2,TUid aUid3)
       
  1327 {
       
  1328 	iUid[0]=aUid1;
       
  1329 	iUid[1]=aUid2;
       
  1330 	iUid[2]=aUid3;
       
  1331 }
       
  1332 
       
  1333 // needed by E32ImageHeaderV::ValidateHeader...
       
  1334 TCheckedUid::TCheckedUid(const TUidType& aUidType)
       
  1335 	{
       
  1336     iType = aUidType;
       
  1337     iCheck = ((TE32ImageUids*)this)->Check();
       
  1338 	}
       
  1339 
       
  1340 // needed by E32ImageHeaderV::ValidateHeader...
       
  1341 void Mem::Crc32(TUint32& aCrc, const TAny* aPtr, TInt aLength)
       
  1342 	{
       
  1343 	::Crc32(aCrc, aPtr, aLength);
       
  1344 	}
       
  1345 
       
  1346 /**
       
  1347 This function updates the CRC of the E32 Image.
       
  1348 @internalComponent
       
  1349 @released
       
  1350 */
       
  1351 void E32ImageFile::UpdateHeaderCrc()
       
  1352 {
       
  1353 	TE32ImageUids u(iHdr->iUid1, iHdr->iUid2, iHdr->iUid3);
       
  1354 	iHdr->iUidChecksum = u.Check();
       
  1355 	TInt hdrsz = GetExtendedE32ImageHeaderSize();
       
  1356 	iHdr->iUncompressedSize = iChunks.GetOffset() - Align(GetExtendedE32ImageHeaderSize(), sizeof(uint32));
       
  1357 	iHdr->iHeaderCrc = KImageCrcInitialiser;
       
  1358 	uint32 crc = 0;
       
  1359 	Crc32(crc, iHdr, hdrsz);
       
  1360 	iHdr->iHeaderCrc = crc;
       
  1361 }
       
  1362 
       
  1363 /**
       
  1364 This function creates a buffer and writes all the data into the buffer.
       
  1365 @internalComponent
       
  1366 @released
       
  1367 */
       
  1368 void E32ImageFile::AllocateE32Image()
       
  1369 {
       
  1370 	size_t aImageSize = iChunks.GetOffset();
       
  1371 	iE32Image = new char[aImageSize];
       
  1372 	memset(iE32Image, 0, aImageSize);
       
  1373 
       
  1374 	E32ImageChunks::ChunkList aChunkList = iChunks.GetChunks();
       
  1375 	E32ImageChunks::ChunkList::iterator p;
       
  1376 	for(p = aChunkList.begin(); p != aChunkList.end(); p++)
       
  1377 	{
       
  1378 		(*p)->Write(iE32Image);
       
  1379 	}
       
  1380 
       
  1381 	E32ImageHeaderV* header = (E32ImageHeaderV*)iE32Image;
       
  1382 	TInt headerSize = header->TotalSize();
       
  1383 	if(KErrNone!=header->ValidateWholeImage(iE32Image+headerSize,GetE32ImageSize()-headerSize))
       
  1384 		throw InvalidE32ImageError(VALIDATIONERROR, (char*)iUseCase->OutputE32FileName());
       
  1385 }
       
  1386 
       
  1387 /**
       
  1388 This function deflates the compressed data.
       
  1389 @param bytes
       
  1390 @param size
       
  1391 @param os
       
  1392 @internalComponent
       
  1393 @released
       
  1394 */
       
  1395 void DeflateCompress(char* bytes, size_t size, ofstream & os);
       
  1396 
       
  1397 /**
       
  1398 This function Paged Pack the compressed data.
       
  1399 @param bytes
       
  1400 @param size
       
  1401 @param os
       
  1402 @internalComponent
       
  1403 @released
       
  1404 */
       
  1405 void CompressPages(TUint8 * bytes, TInt size, ofstream& os);
       
  1406 
       
  1407 
       
  1408 /**
       
  1409 This function writes into the final E32 image file.
       
  1410 @param aName - E32 image file name
       
  1411 @internalComponent
       
  1412 @released
       
  1413 */
       
  1414 bool E32ImageFile::WriteImage(const char * aName)
       
  1415 {
       
  1416 	ofstream *os = new ofstream();
       
  1417 	os->open(aName, ofstream::binary|ofstream::out);
       
  1418 
       
  1419 	if (os->is_open()) 
       
  1420 	{
       
  1421 		uint32 compression = iHdr->CompressionType();
       
  1422 		if (compression == KUidCompressionDeflate)
       
  1423 		{
       
  1424 			size_t aHeaderSize = GetExtendedE32ImageHeaderSize();
       
  1425 			size_t aBodySize = GetE32ImageSize() - aHeaderSize;
       
  1426 			os->write(iE32Image, aHeaderSize);
       
  1427 			DeflateCompress(iE32Image + aHeaderSize, aBodySize, *os);
       
  1428 		}
       
  1429 		else if (compression == KUidCompressionBytePair)
       
  1430 		{
       
  1431 			size_t aHeaderSize = GetExtendedE32ImageHeaderSize();
       
  1432 			os->write(iE32Image, aHeaderSize);
       
  1433 			
       
  1434 			// Compress and write out code part
       
  1435 			int srcStart = GetExtendedE32ImageHeaderSize();
       
  1436 			CompressPages( (TUint8*)iE32Image + srcStart, iHdr->iCodeSize, *os);
       
  1437 			
       
  1438 			
       
  1439 			// Compress and write out data part
       
  1440 			srcStart += iHdr->iCodeSize;
       
  1441 			int srcLen = GetE32ImageSize() - srcStart;
       
  1442 			
       
  1443 			CompressPages((TUint8*)iE32Image + srcStart, srcLen, *os);		
       
  1444 
       
  1445 		}
       
  1446 		else if (compression == 0)
       
  1447 		{
       
  1448 			os->write(iE32Image, GetE32ImageSize()); // image not compressed
       
  1449 		}
       
  1450 
       
  1451 	} 
       
  1452 	else
       
  1453 	{
       
  1454 		throw FileError(FILEOPENERROR,(char*)aName);
       
  1455 	}
       
  1456 	os->close();
       
  1457 	if(os!=NULL)
       
  1458 	{
       
  1459 	delete os;
       
  1460 	os = NULL;
       
  1461 	}
       
  1462 	return true;
       
  1463 }
       
  1464 
       
  1465 
       
  1466 /**
       
  1467 Constructor for E32ImageFile class.
       
  1468 @internalComponent
       
  1469 @released
       
  1470 */
       
  1471 E32ImageFile::E32ImageFile(): iFileName(NULL), iE32Image(NULL),iExportBitMap(0),cleanupStack(0),  iData(NULL),iHdr(NULL),iImportSection(0), iSize(0), iOrigHdr(NULL),  iError(0), iSource(EE32Image), iOrigHdrOffsetAdj(0)  
       
  1472 {
       
  1473 	
       
  1474 };
       
  1475 
       
  1476 /**
       
  1477 Destructor for E32ImageFile class.
       
  1478 @internalComponent
       
  1479 @released
       
  1480 */
       
  1481 E32ImageFile::~E32ImageFile()
       
  1482 {
       
  1483 	delete[] iData;
       
  1484 	if (iHdr && iHdr != iOrigHdr)
       
  1485 		delete iHdr;
       
  1486 
       
  1487 	delete [] iExportBitMap;
       
  1488 	delete [] iE32Image;
       
  1489 	delete [] iImportSection;
       
  1490 
       
  1491  	std::vector<char*>::iterator aPos;
       
  1492  	char *aPtr;
       
  1493  	aPos = cleanupStack.begin();
       
  1494  	while( aPos != cleanupStack.end() )
       
  1495  	{
       
  1496  		aPtr = *aPos;
       
  1497  		delete [] aPtr;
       
  1498  		aPos++;
       
  1499  	}
       
  1500 	
       
  1501 }
       
  1502 
       
  1503 /**
       
  1504 Adjust the size of allocated data and fix the member data
       
  1505 @internalComponent
       
  1506 @released
       
  1507 */
       
  1508 void E32ImageFile::Adjust(TInt aSize, TBool aAllowShrink)
       
  1509 {
       
  1510 	TInt asize = ((aSize+0x3)&0xfffffffc);
       
  1511 
       
  1512 	if (asize == iSize)
       
  1513 		return;
       
  1514 
       
  1515 	if (iSize == 0)
       
  1516 	{
       
  1517 		iSize = asize;
       
  1518 		iData = new char[iSize];
       
  1519 		memset(iData, 0, iSize);
       
  1520 	}
       
  1521 	else if (aAllowShrink || asize > iSize)
       
  1522 	{
       
  1523 		TInt oldsize = iSize;
       
  1524 		iSize = asize;
       
  1525 		iData = (char*)realloc(iData, iSize);
       
  1526 		
       
  1527 		if (iSize > oldsize)
       
  1528 			memset(iData+oldsize, 0, iSize-oldsize);
       
  1529 	}
       
  1530 	
       
  1531 	if (!iData)
       
  1532 		iSize = 0;
       
  1533 	
       
  1534 	if (iHdr && iHdr == iOrigHdr)
       
  1535 		iHdr = (E32ImageHeaderV*)iData;
       
  1536 	
       
  1537 	iOrigHdr = (E32ImageHeader*)iData;
       
  1538 }
       
  1539 
       
  1540 /**
       
  1541 Read the E32 image.
       
  1542 @param is - input stream
       
  1543 @internalComponent
       
  1544 @released
       
  1545 */
       
  1546 TInt E32ImageFile::ReadHeader(ifstream& is)
       
  1547 {
       
  1548 	Adjust(sizeof(E32ImageHeader), EFalse);
       
  1549 	is.read(iData, sizeof(E32ImageHeader));
       
  1550 	TInt hdrsz = iOrigHdr->TotalSize();
       
  1551 	
       
  1552 	if (hdrsz > 0x10000)
       
  1553 		return KErrCorrupt;	// sanity check
       
  1554 	
       
  1555 	if (hdrsz > (TInt)sizeof(E32ImageHeader))
       
  1556 	{
       
  1557 		Adjust(hdrsz, EFalse);
       
  1558 		is.read(iData+sizeof(E32ImageHeader), hdrsz-sizeof(E32ImageHeader));
       
  1559 	}
       
  1560 
       
  1561 	TUint32 uncompressedSize;
       
  1562 	TInt r = iOrigHdr->ValidateHeader(iFileSize,uncompressedSize);
       
  1563 	
       
  1564 	if (r != KErrNone)
       
  1565 	{
       
  1566 		fprintf(stderr, "Integrity check failed %d\n", r);
       
  1567 		return r;
       
  1568 	}
       
  1569 	
       
  1570 	iHdr = (E32ImageHeaderV*)iOrigHdr;
       
  1571 	return KErrNone;
       
  1572 }
       
  1573 
       
  1574 /**
       
  1575 Return the offset of the text section
       
  1576 @internalComponent
       
  1577 @released
       
  1578 */
       
  1579 TUint E32ImageFile::TextOffset()
       
  1580 {
       
  1581 	return 0;
       
  1582 }
       
  1583 
       
  1584 /**
       
  1585 Return the offset of the data section
       
  1586 @internalComponent
       
  1587 @released
       
  1588 */
       
  1589 TUint E32ImageFile::DataOffset()
       
  1590 {
       
  1591 	return iHdr->iCodeSize;
       
  1592 }
       
  1593 
       
  1594 /**
       
  1595 Return the offset of the bss section
       
  1596 @internalComponent
       
  1597 @released
       
  1598 */
       
  1599 TUint E32ImageFile::BssOffset()
       
  1600 {
       
  1601 	return DataOffset()+iHdr->iDataSize;
       
  1602 }
       
  1603 
       
  1604 
       
  1605 /**
       
  1606 This function creates the bitmap after reading the E32 image file
       
  1607 @internalComponent
       
  1608 @released
       
  1609 */
       
  1610 void E32ImageFile::E32ImageExportBitMap()
       
  1611 {
       
  1612 	TInt nexp = iOrigHdr->iExportDirCount;
       
  1613 	TInt memsz = (nexp + 7) >> 3;
       
  1614 	iExportBitMap = new TUint8[memsz];
       
  1615 	memset(iExportBitMap, 0xff, memsz);
       
  1616 	TUint* exports = (TUint*)(iData + iOrigHdr->iExportDirOffset);
       
  1617 	TUint absoluteEntryPoint = iOrigHdr->iEntryPoint + iOrigHdr->iCodeBase;
       
  1618 	TUint impfmt = iOrigHdr->ImportFormat();
       
  1619 	TUint hdrfmt = iOrigHdr->HeaderFormat();
       
  1620 	TUint absentVal = (impfmt == KImageImpFmt_ELF) ? absoluteEntryPoint : iOrigHdr->iEntryPoint;
       
  1621 	TInt i;
       
  1622 	iMissingExports = 0;
       
  1623 	
       
  1624 	for (i=0; i<nexp; ++i)
       
  1625 	{
       
  1626 		if (exports[i] == absentVal)
       
  1627 		{
       
  1628 			iExportBitMap[i>>3] &= ~(1u << (i & 7));
       
  1629 			++iMissingExports;
       
  1630 		}
       
  1631 	}
       
  1632 	
       
  1633 	if (hdrfmt < KImageHdrFmt_V && iMissingExports)
       
  1634 	{
       
  1635 		fprintf(stderr, "Bad exports\n");
       
  1636 		exit(999);
       
  1637 	}
       
  1638 }
       
  1639 
       
  1640 /**
       
  1641 This function creates the export description after reading the E32 image file
       
  1642 @internalComponent
       
  1643 @released
       
  1644 */
       
  1645 TInt E32ImageFile::CheckExportDescription()
       
  1646 {
       
  1647 	TUint hdrfmt = iOrigHdr->HeaderFormat();
       
  1648 	if (hdrfmt < KImageHdrFmt_V && iMissingExports)
       
  1649 		return KErrCorrupt;
       
  1650 	
       
  1651 	if (iHdr->iExportDescType == KImageHdr_ExpD_NoHoles)
       
  1652 	{
       
  1653 		return iMissingExports ? KErrCorrupt : KErrNone;
       
  1654 	}
       
  1655 	
       
  1656 	TInt nexp = iOrigHdr->iExportDirCount;
       
  1657 	TInt memsz = (nexp + 7) >> 3;	// size of complete bitmap
       
  1658 	TInt mbs = (memsz + 7) >> 3;	// size of meta-bitmap
       
  1659 	TInt eds = iHdr->iExportDescSize;
       
  1660 	
       
  1661 	if (iHdr->iExportDescType == KImageHdr_ExpD_FullBitmap)
       
  1662 	{
       
  1663 		if (eds != memsz)
       
  1664 			return KErrCorrupt;
       
  1665 		if (memcmp(iHdr->iExportDesc, iExportBitMap, eds) == 0)
       
  1666 			return KErrNone;
       
  1667 		return KErrCorrupt;
       
  1668 	}
       
  1669 	
       
  1670 	if (iHdr->iExportDescType != KImageHdr_ExpD_SparseBitmap8)
       
  1671 		return KErrNotSupported;
       
  1672 	
       
  1673 	TInt nbytes = 0;
       
  1674 	TInt i;
       
  1675 	for (i=0; i<memsz; ++i)
       
  1676 		if (iExportBitMap[i] != 0xff)
       
  1677 			++nbytes;				// number of groups of 8
       
  1678 	
       
  1679 	TInt exp_extra = mbs + nbytes;
       
  1680 	if (eds != exp_extra)
       
  1681 		return KErrCorrupt;
       
  1682 	
       
  1683 	const TUint8* mptr = iHdr->iExportDesc;
       
  1684 	const TUint8* gptr = mptr + mbs;
       
  1685 	for (i=0; i<memsz; ++i)
       
  1686 	{
       
  1687 		TUint mbit = mptr[i>>3] & (1u << (i&7));
       
  1688 		if (iExportBitMap[i] != 0xff)
       
  1689 		{
       
  1690 			if (!mbit || *gptr++ != iExportBitMap[i])
       
  1691 				return KErrCorrupt;
       
  1692 		}
       
  1693 		else if (mbit)
       
  1694 			return KErrCorrupt;
       
  1695 	}
       
  1696 	
       
  1697 	return KErrNone;
       
  1698 }
       
  1699 
       
  1700 
       
  1701 int  DecompressPages(TUint8 * bytes, ifstream& is);
       
  1702 
       
  1703 
       
  1704 /**
       
  1705 This function creates the E32 image reading from the file
       
  1706 @param is
       
  1707 @param aImage
       
  1708 @internalComponent
       
  1709 @released
       
  1710 */
       
  1711 ifstream& operator>>(ifstream& is, E32ImageFile& aImage)
       
  1712 {
       
  1713 	aImage.iError = aImage.ReadHeader(is);
       
  1714 	if (aImage.iError != KErrNone)
       
  1715 		return is;
       
  1716 	
       
  1717 	E32ImageHeader* oh = aImage.iOrigHdr;
       
  1718 	TInt orighdrsz = oh->TotalSize();
       
  1719 	int remainder = aImage.iSize - orighdrsz;
       
  1720 	TUint compression = oh->CompressionType();
       
  1721 	if (compression == 0)
       
  1722 	{
       
  1723 		is.read(aImage.iData + orighdrsz, remainder);
       
  1724 	}
       
  1725 	else if (compression == KUidCompressionDeflate)
       
  1726 	{ //Uncompress
       
  1727 		aImage.iError = KErrNoMemory;
       
  1728 		unsigned int uncompsize = ((E32ImageHeaderComp*)aImage.iOrigHdr)->iUncompressedSize;
       
  1729 		aImage.Adjust(uncompsize + orighdrsz);
       
  1730 		
       
  1731 		if (aImage.iData==NULL)
       
  1732 			return is;
       
  1733 		
       
  1734 		oh = aImage.iOrigHdr;
       
  1735 		
       
  1736 		unsigned char* compressedData = new unsigned char[remainder];
       
  1737 		if (compressedData==NULL)
       
  1738 			return is;
       
  1739 		
       
  1740 		is.read(reinterpret_cast<char *>(compressedData), remainder);
       
  1741 		unsigned int destsize = uncompsize;
       
  1742 		InflateUnCompress( compressedData, remainder, (unsigned char*)(aImage.iData + orighdrsz), destsize);
       
  1743 		
       
  1744 		if (destsize != uncompsize)
       
  1745 			MessageHandler::GetInstance()->ReportMessage(WARNING, HUFFMANINCONSISTENTSIZEERROR);
       
  1746 		
       
  1747 		delete [] compressedData;
       
  1748 		
       
  1749 		if ((TUint)orighdrsz > oh->iCodeOffset)
       
  1750 		{
       
  1751 			// need to adjust code offsets in original
       
  1752 			aImage.iOrigHdrOffsetAdj = (TUint)orighdrsz - oh->iCodeOffset;
       
  1753 			aImage.OffsetAdjust(oh->iCodeOffset);
       
  1754 			aImage.OffsetAdjust(oh->iDataOffset);
       
  1755 			aImage.OffsetAdjust(oh->iCodeRelocOffset);
       
  1756 			aImage.OffsetAdjust(oh->iDataRelocOffset);
       
  1757 			aImage.OffsetAdjust(oh->iImportOffset);
       
  1758 			aImage.OffsetAdjust(oh->iExportDirOffset);
       
  1759 		}
       
  1760 		aImage.iError = KErrNone;
       
  1761 	}
       
  1762 	else if(compression == KUidCompressionBytePair)
       
  1763 	{ // Uncompress
       
  1764 		aImage.iError = KErrNoMemory;
       
  1765 		unsigned int uncompsize = ((E32ImageHeaderComp*)aImage.iOrigHdr)->iUncompressedSize;
       
  1766 		aImage.Adjust(uncompsize + orighdrsz);
       
  1767 		if (aImage.iData==NULL)
       
  1768 			return is;
       
  1769 		oh = aImage.iOrigHdr;
       
  1770 
       
  1771 		// Read and decompress code part of the image
       
  1772 
       
  1773 		unsigned int uncompressedCodeSize = DecompressPages((TUint8 *) (aImage.iData + orighdrsz), is);
       
  1774 
       
  1775 		
       
  1776 		// Read and decompress data part of the image
       
  1777 
       
  1778 		unsigned int uncompressedDataSize = DecompressPages((TUint8 *) (aImage.iData + orighdrsz + uncompressedCodeSize), is);
       
  1779 
       
  1780 		if (uncompressedCodeSize + uncompressedDataSize != uncompsize)
       
  1781 			MessageHandler::GetInstance()->ReportMessage(WARNING, BYTEPAIRINCONSISTENTSIZEERROR);
       
  1782 
       
  1783 		if ((TUint)orighdrsz > oh->iCodeOffset)
       
  1784 			{
       
  1785 			// need to adjust code offsets in original
       
  1786 			aImage.iOrigHdrOffsetAdj = (TUint)orighdrsz - oh->iCodeOffset;
       
  1787 			aImage.OffsetAdjust(oh->iCodeOffset);
       
  1788 			aImage.OffsetAdjust(oh->iDataOffset);
       
  1789 			aImage.OffsetAdjust(oh->iCodeRelocOffset);
       
  1790 			aImage.OffsetAdjust(oh->iDataRelocOffset);
       
  1791 			aImage.OffsetAdjust(oh->iImportOffset);
       
  1792 			aImage.OffsetAdjust(oh->iExportDirOffset);
       
  1793 			}
       
  1794 		aImage.iError = KErrNone;
       
  1795 	}
       
  1796 	aImage.E32ImageExportBitMap();
       
  1797 
       
  1798 	return is;
       
  1799 }
       
  1800 #ifdef __LINUX__ 
       
  1801 #include <sys/stat.h>
       
  1802 /**
       
  1803 Simple function uses stdlib fstat to obtain the size of the file. 
       
  1804 @param aFileName - e32 image file name
       
  1805 @internalComponent
       
  1806 @released
       
  1807 */ 
       
  1808 int GetFileSize(const char* aFileName) {
       
  1809     // Open the file the old-fashioned way :-)
       
  1810     struct stat fileInfo; 
       
  1811     if(stat(aFileName,&fileInfo)!=0) {
       
  1812         throw FileError(FILEOPENERROR,(char *)aFileName);
       
  1813     }
       
  1814     off_t fileSize = fileInfo.st_size;
       
  1815     return fileSize; 
       
  1816 }
       
  1817 #else 
       
  1818 int GetFileSize(const char* aFileName) {
       
  1819     _finddata_t fileinfo;
       
  1820 	int ret=_findfirst((char *)aFileName,&fileinfo);
       
  1821 	if (ret==-1) 
       
  1822 	{
       
  1823 		throw FileError(FILEOPENERROR,(char *)aFileName);
       
  1824 	}
       
  1825     return fileinfo.size; 
       
  1826 }
       
  1827 #endif
       
  1828 
       
  1829 
       
  1830 /**
       
  1831 This function opens the  e32 image file.
       
  1832 @param aFileName - e32 image file name
       
  1833 @internalComponent
       
  1834 @released
       
  1835 */
       
  1836 TInt E32ImageFile::Open(const char* aFileName)
       
  1837 {
       
  1838 	iFileSize = GetFileSize(aFileName);
       
  1839 	
       
  1840 	Adjust(iFileSize);
       
  1841 	ifstream ifile((char *)aFileName, ios::in | ios::binary);
       
  1842 	if(!ifile.is_open())
       
  1843 	{
       
  1844 		throw FileError(FILEOPENERROR,(char *)aFileName);
       
  1845 	}
       
  1846 	ifile >> *this;
       
  1847 	ifile.close();
       
  1848 
       
  1849 	if (iError != KErrNone)
       
  1850 		return iError;
       
  1851 	
       
  1852 	return KErrNone;
       
  1853 }
       
  1854 
       
  1855 void E32ImageFile::ProcessSymbolInfo() {
       
  1856 	
       
  1857 	Elf32_Addr aPlace = iUseCase->GetExportTableAddress() - 4;// This location points to 0th ord.
       
  1858 	// Create a relocation entry for the 0th ordinal.
       
  1859 	ElfLocalRelocation *aRel = new ElfLocalRelocation(iElfExecutable, aPlace, 0, 0, R_ARM_ABS32, \
       
  1860 		NULL, ESegmentRO, NULL, false);
       
  1861 	aRel->Add();
       
  1862 
       
  1863 	aPlace += iUseCase->GetExportTableSize();// aPlace now points to the symInfo
       
  1864 	uint32 *aZerothOrd = (uint32*)iUseCase->GetExportTable();
       
  1865 	*aZerothOrd = aPlace;
       
  1866 	aPlace += sizeof(E32EpocExpSymInfoHdr);// aPlace now points to the symbol address
       
  1867 											// which is just after the syminfo header.
       
  1868 	if(!iElfExecutable->iExports)
       
  1869 		return;
       
  1870 
       
  1871 	// Donot disturb the internal list sorting.
       
  1872 	ElfExports::ExportList aList = iElfExecutable->iExports->GetExports(false);
       
  1873 
       
  1874 	ElfExports::ExportList::iterator aIter = aList.begin();
       
  1875 	DllSymbol *aSym;
       
  1876 	TUint aAlign, aNameLen;
       
  1877 
       
  1878 	
       
  1879 	char aPad[] = {'\0', '\0', '\0', '\0'};
       
  1880 
       
  1881 
       
  1882 	while ( aIter != aList.end() ) {
       
  1883 		aSym = *aIter;
       
  1884 		iSymAddrTab.push_back(aSym->iElfSym->st_value);
       
  1885 		// The symbol names always start at a 4-byte aligned offset.
       
  1886 		iSymNameOffset = iSymbolNames.size() >> 2;
       
  1887 		iSymNameOffTab.push_back(iSymNameOffset);
       
  1888 
       
  1889 		iSymbolNames += aSym->SymbolName();
       
  1890 		iSymbolNames += '\0';
       
  1891 		aNameLen = iSymbolNames.size();
       
  1892 		aAlign = Align(aNameLen, sizeof(int));
       
  1893 		aAlign = aAlign - aNameLen;
       
  1894 		if(aAlign % 4){
       
  1895 			iSymbolNames.append(aPad, aAlign);
       
  1896 		}
       
  1897 		//Create a relocation entry...
       
  1898 		aRel = new ElfLocalRelocation(iElfExecutable, aPlace, 0, 0, R_ARM_ABS32, NULL,\
       
  1899 			ESegmentRO, aSym->iElfSym, false);
       
  1900 		aPlace += sizeof(uint32);
       
  1901 		aRel->Add();
       
  1902 		aIter++;
       
  1903 	}
       
  1904 }
       
  1905 
       
  1906 char* E32ImageFile::CreateSymbolInfo(size_t aBaseOffset) {
       
  1907 	E32EpocExpSymInfoHdr aSymInf;
       
  1908 	uint32 aSizeofNames, aSize;
       
  1909 
       
  1910 	SetSymInfo(aSymInf);
       
  1911 	if( aSymInf.iFlags & 1) {
       
  1912 		aSizeofNames = sizeof(uint32);
       
  1913 	}
       
  1914 	else {
       
  1915 		aSizeofNames = sizeof(uint16);
       
  1916 	}
       
  1917 
       
  1918 	aSize = aSymInf.iSize;
       
  1919 
       
  1920 	char* aInfo = new char[aSize];
       
  1921 	memset(aInfo, 0, aSize);
       
  1922 	memcpy(aInfo, (void*)&aSymInf, sizeof(aSymInf));
       
  1923 
       
  1924 	TUint aPos = aSymInf.iSymbolTblOffset;
       
  1925 	memcpy(aInfo+aPos, iSymAddrTab.begin(), iSymAddrTab.size()*sizeof(uint32));
       
  1926 
       
  1927 	aPos += iSymAddrTab.size()*aSizeofNames;
       
  1928 	aPos += iSymNameOffTab.size()*aSizeofNames;
       
  1929 	aPos = Align(aPos, sizeof(uint32));
       
  1930 
       
  1931 	std::vector<uint32>::iterator Iter = iSymNameOffTab.begin();
       
  1932 	TInt aOffLen = 2;
       
  1933 	if(aSymInf.iFlags & 1)
       
  1934 		aOffLen=4;
       
  1935 	while(Iter != iSymNameOffTab.end()){
       
  1936 		memcpy( ((void*)(aInfo+aPos)), ((void*)Iter), aOffLen);
       
  1937 		aPos += aOffLen;
       
  1938 		Iter++;
       
  1939 	}
       
  1940 
       
  1941 	aPos = aSymInf.iStringTableOffset;
       
  1942 	memcpy(aInfo+aPos, iSymbolNames.begin(), iSymbolNames.size());
       
  1943 
       
  1944 	// At the end, the dependencies are listed. They remain zeroes and shall be fixed up
       
  1945 	// while relocating.
       
  1946 
       
  1947 	// Update the import table to have offsets to ordinal zero entries
       
  1948 	uint32 *aLocation, aOffset;
       
  1949 	uint32 *aImportTab = iImportSection;
       
  1950 
       
  1951 	std::vector<int>::iterator aIter = iImportTabLocations.begin();
       
  1952 	aOffset = aBaseOffset - iHdr->iCodeOffset;// This gives the offset of syminfo table base
       
  1953 										// wrt the code section start
       
  1954 	aOffset += aSymInf.iDepDllZeroOrdTableOffset; // This points to the ordinal zero offset table now
       
  1955 	while( aIter != iImportTabLocations.end()) {
       
  1956 		aLocation = (aImportTab + *aIter);
       
  1957 		*aLocation = aOffset;
       
  1958 		aOffset += sizeof(uint32);
       
  1959 		aIter++;
       
  1960 	}
       
  1961 
       
  1962 	return aInfo;
       
  1963 }
       
  1964 
       
  1965 void E32ImageFile::SetSymInfo(E32EpocExpSymInfoHdr& aSymInfo)
       
  1966 {
       
  1967 	uint32 aSize = sizeof(E32EpocExpSymInfoHdr);
       
  1968 	memset(&aSymInfo, 0, aSize);
       
  1969 
       
  1970 	uint16 aNSymbols = (uint16) iSymAddrTab.size();
       
  1971 	aSymInfo.iSymCount = aNSymbols;
       
  1972 	aSymInfo.iSymbolTblOffset = aSize;
       
  1973 	aSize += aNSymbols * sizeof(uint32); // Symbol addresses
       
  1974 	TUint aNameTabSz = iSymbolNames.size();
       
  1975 	TInt aSizeofNames;
       
  1976 
       
  1977 	if( iSymNameOffset < 0xffff) {
       
  1978 		aSizeofNames = sizeof(uint16);
       
  1979 		aSymInfo.iFlags &= ~1;//reset the 0th bit
       
  1980 	}
       
  1981 	else {
       
  1982 		aSizeofNames = sizeof(uint32);
       
  1983 		aSymInfo.iFlags |= 1;//set the 0th bit
       
  1984 	}
       
  1985 	aSize += Align((aNSymbols * aSizeofNames), sizeof(uint32)); // Symbol name offsets
       
  1986 	aSymInfo.iStringTableOffset = aSize;
       
  1987 	aSize += aNameTabSz; // Symbol names in string tab
       
  1988 	aSymInfo.iStringTableSz = aNameTabSz;
       
  1989 	aSymInfo.iDepDllZeroOrdTableOffset = aSize;
       
  1990 	aSymInfo.iDllCount = iNumDlls ;
       
  1991 	aSize += iNumDlls * sizeof(uint32); // Dependency list - ordinal zero placeholder
       
  1992 	aSymInfo.iSize = aSize;
       
  1993 }
       
  1994