e32tools/elf2e32/source/e32imagefile.cpp
changeset 0 044383f39525
child 590 360bd6b35136
child 606 30b30f9da0b7
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/e32tools/elf2e32/source/e32imagefile.cpp	Tue Oct 27 16:36:35 2009 +0000
@@ -0,0 +1,1994 @@
+// Copyright (c) 2004-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+// Implementation of e32 image creation and dump for elf2e32 tool
+// @internalComponent
+// @released
+// 
+//
+
+#include "pl_elfexecutable.h"
+
+// get E32ImageHeader class...
+#define INCLUDE_E32IMAGEHEADER_IMPLEMENTATION
+#define RETURN_FAILURE(_r) return (fprintf(stderr, "line %d\n", __LINE__),_r)
+//#define E32IMAGEHEADER_TRACE(_t) printf _t
+#include "e32imagefile.h"
+
+#include "pl_elfimportrelocation.h"
+#include "pl_elflocalrelocation.h"
+#include "pl_elfimports.h"
+#include "elffilesupplied.h"
+#include "pl_dllsymbol.h"
+#include "h_ver.h"
+#include "checksum.h"
+#include "errorhandler.h"
+
+#include <string>
+#include <vector>
+#include <cassert>
+#include <iostream>
+#ifndef __LINUX__ 
+    #include <io.h>
+#else
+    #include <time.h>
+#endif 
+#include <time.h>
+#include <stdio.h>
+
+using namespace std;
+
+template <class T> inline T Align(T v, size_t s)
+{
+	unsigned int inc = s-1;
+	unsigned int mask = ~inc;
+	unsigned int val = (unsigned int)v;
+	unsigned int res = (val+inc) & mask;
+	return (T)res;
+}
+
+// Need a default constructor for TVersion, but don't want all the other stuff in h_utl.cpp
+/**
+Default constructor for TVersion class.
+@internalComponent
+@released
+*/
+TVersion::TVersion(){}
+
+/**
+Constructor for TVersion class.
+@internalComponent
+@released
+*/
+TVersion::TVersion(TInt aMajor, TInt aMinor, TInt aBuild): 
+	iMajor((TInt8)aMajor), iMinor((TInt8)aMinor), iBuild((TInt16)aBuild)
+{
+}
+
+
+/**
+Constructor for E32ImageChunkDesc class.
+@internalComponent
+@released
+*/
+E32ImageChunkDesc::E32ImageChunkDesc(char * aData, size_t aSize, size_t aOffset, char * aDoc):
+	iData(aData), iSize(aSize), iOffset(aOffset), iDoc(aDoc)
+{
+}
+
+/**
+Destructor for E32ImageChunkDesc class.
+@internalComponent
+@released
+*/
+E32ImageChunkDesc::~E32ImageChunkDesc()
+{
+}
+
+/**
+This function writes its data in the buffer.
+@param aPlace - a location in the buffer
+@internalComponent
+@released
+*/
+void E32ImageChunkDesc::Write(char * aPlace)
+{
+	memcpy(aPlace+iOffset, iData, iSize);
+}
+
+/**
+Constructor for E32ImageChunks class.
+@internalComponent
+@released
+*/
+E32ImageChunks::E32ImageChunks(): 
+	iOffset(0)
+{
+}
+
+/**
+Destructor for E32ImageChunks class.
+@internalComponent
+@released
+*/
+E32ImageChunks::~E32ImageChunks()
+{	
+ 	if(iChunks.size())
+ 	{
+ 		ChunkList::iterator aItr = iChunks.begin();
+ 		ChunkList::iterator last = iChunks.end();
+ 		E32ImageChunkDesc *temp;
+ 
+ 		while( aItr != last)
+ 		{
+ 			temp = *aItr;
+ 			aItr++;
+ 			delete temp;
+ 		}
+ 	}
+}
+
+/**
+This function creates and adds a chunk into a list.
+@param aData - input buffer
+@param asize - size of the input buffer
+@param aOffset - byte offset of this chunk from the 1 byte in e32 image file.
+@param aDoc - name of the chunk
+@internalComponent
+@released
+*/
+void E32ImageChunks::AddChunk(char * aData, size_t aSize, size_t aOffset, char * aDoc)
+{
+	E32ImageChunkDesc * aChunk = new E32ImageChunkDesc(aData, aSize, aOffset, aDoc);
+	iChunks.push_back(aChunk);
+	iOffset += Align(aSize, sizeof(TUint32));
+}
+
+/**
+This function returns the list of chunks.
+@internalComponent
+@released
+*/
+E32ImageChunks::ChunkList & E32ImageChunks::GetChunks()
+{
+	return iChunks;
+}
+
+/**
+This function returns the current offset pointing to the last chunk that
+was added into the list of chunks.
+@internalComponent
+@released
+*/
+size_t E32ImageChunks::GetOffset()
+{
+	return iOffset;
+}
+
+/**
+This function sets the current offset pointing to the last chunk that 
+was added into the list of chunks.
+@internalComponent
+@released
+*/
+void E32ImageChunks::SetOffset(size_t aOffset)
+{
+	iOffset = aOffset;
+}
+
+/**
+Constructor for E32ImageFile class.
+@internalComponent
+@released
+*/
+E32ImageFile::E32ImageFile(const char * aFileName, ElfExecutable * aExecutable, ElfFileSupplied *aUseCase) :
+	iFileName(aFileName), 
+	iE32Image(0),
+	iExportBitMap(0),
+	iElfExecutable(aExecutable), 
+	iData(0),
+	iUseCase(aUseCase),
+	iHdr(0),
+	iHdrSize(sizeof(E32ImageHeaderV)),
+	iImportSection(0), 
+	iImportSectionSize(0),
+	iCodeRelocs(0), 
+	iCodeRelocsSize(0),
+	iDataRelocs(0), 
+	iDataRelocsSize(0),
+	iExportOffset(0),
+	iLayoutDone(false), 
+	iMissingExports(0),
+	iSymNameOffset(0)
+{
+}
+
+/**
+This function generates the E32 image.
+@internalComponent
+@released
+*/
+void E32ImageFile::GenerateE32Image()
+{
+	if( iUseCase->GetNamedSymLookup() ){
+		ProcessSymbolInfo();
+	}
+	ProcessImports();
+	ProcessRelocations();
+	ConstructImage();
+}
+
+/**
+This function processes the import map by looking into the dso files
+from which the symbols are imported. It also fetches the ordinal numbers
+for the corresponding symbols.
+@internalComponent
+@released
+*/
+void E32ImageFile::ProcessImports()
+{
+	string aStrTab;
+	vector<int> aStrTabOffsets;
+	int aNumDlls = 0;
+	int aNumImports = 0;
+	bool aNamedLookup = iUseCase->GetNamedSymLookup();
+	TUint aImportTabEntryPos = 0;
+
+	ElfImports::ImportMap aImportMap = iElfExecutable->GetImports();
+	ElfImports::ImportMap::iterator p;
+
+	// First set up the string table and record offsets into string table of each 
+	// LinkAs name.
+	for (p = aImportMap.begin(); p != aImportMap.end(); p++)
+	{
+		ElfImports::RelocationList & aImports = (*p).second;
+		char* aLinkAs = aImports[0]->iVerRecord->iLinkAs;
+
+		aStrTabOffsets.push_back(aStrTab.size()); // 
+		string s = aLinkAs;
+		aStrTab.insert(aStrTab.end(),s.begin(),s.end());
+		aStrTab.insert(aStrTab.end(),0);
+		aNumDlls++;
+		aNumImports += aImports.size();
+	}
+	
+	iNumDlls = aNumDlls;
+	iNumImports = aNumImports;
+
+	// Now we can figure out the size of everything
+	size_t aImportSectionSize = sizeof(E32ImportSection) + 
+								(sizeof(E32ImportBlock) * aNumDlls) +
+								(sizeof(unsigned int) * aNumImports);
+ 
+	vector<Elf32_Word> aImportSection;
+
+	// This is the 'E32ImportSection' header - fill with 0 for the moment
+	aImportSection.push_back(0);
+
+	if( aNamedLookup ) {
+		// These are the 0th ordinals imported into the import table, one
+		// entry for each DLL.
+		aImportSectionSize += (sizeof(unsigned int) * aNumDlls);
+	}
+	// Now fill in the E32ImportBlocks
+	int idx = 0;
+	char * aDsoName;
+	for (p = aImportMap.begin(); p != aImportMap.end(); p++, idx++)
+	{
+		ElfImports::RelocationList & aImports = (*p).second;
+		aDsoName = aImports[0]->iVerRecord->iSOName;
+
+		//const char * aDSO = FindDSO((*p).first);
+		const char * aDSO = FindDSO(aDsoName);
+
+		aImportSection.push_back(aStrTabOffsets[idx] + aImportSectionSize); 
+		int nImports = aImports.size();
+
+		// Take the additional 0th ordinal import into account
+		if( aNamedLookup )
+			nImports++;
+		aImportSection.push_back(nImports);
+
+		size_t aSize;
+		Elf32_Ehdr * aElfFile = 0;
+		ReadInputELFFile(aDSO, aSize, aElfFile);
+
+		ElfExecutable aElfExecutable(NULL);//(aElfFile, aSize);
+		aElfExecutable.ProcessElfFile(aElfFile);
+
+		ElfImports::RelocationList::iterator q;
+		for (q = aImports.begin(); q != aImports.end(); q++)
+		{
+			ElfImportRelocation * aReloc = *q;
+			char * aSymName = iElfExecutable->GetSymbolName(aReloc->iSymNdx);
+			unsigned int aOrdinal = aElfExecutable.GetSymbolOrdinal(aSymName);
+			
+			//check the reloc refers to Code Segment
+			try
+			{
+				if (iElfExecutable->SegmentType(aReloc->iAddr) != ESegmentRO)
+				{
+					throw ImportRelocationError(ILLEGALEXPORTFROMDATASEGMENT, aSymName, iElfExecutable->iParameterListInterface->ElfInput());
+				}
+			}
+			/**This catch block introduced here is to avoid deleting partially constructed object(s).
+			Otherwise global catch block will delete the partially constructed object(s) and the tool will crash.
+			*/
+			catch(ErrorHandler& aError)
+			{
+				aError.Report();
+				exit(EXIT_FAILURE);
+			}
+				
+			Elf32_Word aRelocOffset = iElfExecutable->GetRelocationOffset(aReloc);
+			aImportSection.push_back(aRelocOffset);
+
+			Elf32_Word * aRelocPlace = iElfExecutable->GetRelocationPlace(aReloc);
+			if (aOrdinal > 0xFFFF)
+			{
+			}
+			if (aReloc->iAddend > 0xFFFF)
+			{
+			}
+			* aRelocPlace = (aReloc->iAddend<<16) | aOrdinal;
+		}
+
+		if( aNamedLookup ) {
+			aImportTabEntryPos = aImportSection.size();
+			// Keep track of the location of the entry
+			iImportTabLocations.push_back(aImportTabEntryPos);
+			// Put the entry as 0 now, which shall be updated 
+			aImportSection.push_back(0);
+		}
+
+		delete [] ((char*)aElfFile);
+	}
+
+	assert(aImportSectionSize == aImportSection.size() * sizeof(Elf32_Word));
+
+	size_t aTotalSize = Align(aImportSectionSize + aStrTab.size(), sizeof(Elf32_Word));
+
+	// Fill in the section header now we have the correct value.
+	aImportSection[0] = aTotalSize;
+
+	// Now construct the unified section
+	iImportSectionSize = aTotalSize;
+	iImportSection = (uint32 *)new char[aTotalSize];
+	memset(iImportSection, 0, aTotalSize);
+	memcpy(iImportSection, aImportSection.begin(), aImportSectionSize);
+	char * strTab = ((char *)iImportSection) + aImportSectionSize;
+	memcpy(strTab, aStrTab.data(), aStrTab.size());
+
+}
+
+
+/**
+This function checks if a DSO file exists.
+@param aPath - DSO file name.
+@internalComponent
+@released
+*/
+static bool ProbePath(string & aPath)
+{
+	ifstream aInput;
+	const char * p = aPath.c_str();
+	aInput.open(p);
+	if (aInput.is_open())
+	{
+		aInput.close();
+		return true;
+	}
+	else
+	{
+		return false;
+	}
+}
+
+/**
+This function allocates space for a DSO file name.
+@param aPath - DSO file name
+@internalComponent
+@released
+*/
+const char * AllocatePath(string & aPath)
+{
+	const char * p = aPath.c_str();
+	size_t len = aPath.size();
+	char * result = new char[len+1];
+	strcpy(result, p);
+	return (const char *)result;
+}
+
+/**
+This function searches for a DSO in the libpath specified.
+@param aName - DSO file name
+@internalComponent
+@released
+*/
+const char * E32ImageFile::FindDSO(const char * aName)
+{
+	string aDSOName(aName);
+	string aDSOPath(aName);
+
+	const char *aNewDsoName;
+
+	if (ProbePath(aDSOName))
+	{
+		aNewDsoName = AllocatePath(aDSOName);
+		cleanupStack.push_back((char*)aNewDsoName);
+		return aNewDsoName;
+	}
+
+	ParameterListInterface::LibSearchPaths & paths = iUseCase->GetLibSearchPaths();
+	ParameterListInterface::LibSearchPaths::iterator p = paths.begin();
+	for (; p != paths.end(); p++)
+	{
+		string path(*p);
+		char dir = iUseCase->GetDirectorySeparator();
+		aDSOPath.erase();
+		aDSOPath.insert(aDSOPath.end(), path.begin(), path.end());
+		aDSOPath.insert(aDSOPath.end(), dir);
+		aDSOPath.insert(aDSOPath.end(), aDSOName.begin(), aDSOName.end());
+		if (ProbePath(aDSOPath))
+		{
+			aNewDsoName = AllocatePath(aDSOPath);
+			cleanupStack.push_back((char*)aNewDsoName);
+			return aNewDsoName;
+		}
+	}
+	throw ELFFileError(DSONOTFOUNDERROR,(char*)aName);
+}
+
+void E32ImageFile::ReadInputELFFile(const char * aName, size_t & aFileSize, Elf32_Ehdr * & aELFFile )
+{
+	ifstream aInput;
+	aInput.open(aName, ifstream::binary|ifstream::in);
+	if (aInput.is_open()) 
+	{
+		aInput.seekg(0,ios::end);
+		aFileSize = (unsigned int) aInput.tellg();
+		aInput.seekg(0,ios::beg);
+		aELFFile = (Elf32_Ehdr *)new char [aFileSize];
+		aInput.read((char *)aELFFile, aFileSize);
+		aInput.close();
+	} 
+	else
+	{
+		throw FileError(FILEOPENERROR,(char*)aName);
+	}
+}
+
+/**
+This function processes relocations.
+@internalComponent
+@released
+*/
+void E32ImageFile::ProcessRelocations()
+{
+	ProcessCodeRelocations();
+	ProcessDataRelocations();
+}
+
+/**
+This function processes Code relocations.
+@internalComponent
+@released
+*/
+void E32ImageFile::ProcessCodeRelocations()
+{
+	CreateRelocations(iElfExecutable->GetCodeRelocations(), iCodeRelocs, iCodeRelocsSize);
+}
+
+/**
+This function processes Data relocations.
+@internalComponent
+@released
+*/
+void E32ImageFile::ProcessDataRelocations()
+{
+	CreateRelocations(iElfExecutable->GetDataRelocations(), iDataRelocs, iDataRelocsSize);
+}
+
+/**
+This function creates Code and Data relocations from the corresponding
+ELF form to E32 form.
+@internalComponent
+@released
+*/
+void E32ImageFile::CreateRelocations(ElfRelocations::RelocationList & aRelocList, char * & aRelocs, size_t & aRelocsSize)
+{
+	size_t rsize = RelocationsSize(aRelocList);
+	if (rsize)
+	{
+		aRelocsSize = Align(rsize + sizeof(E32RelocSection), sizeof(uint32));
+
+		uint32 aBase = (*aRelocList.begin())->iSegment->p_vaddr;
+		//add for cleanup to be done later..
+		cleanupStack.push_back(aRelocs);
+		aRelocs =	new char [aRelocsSize];
+		memset(aRelocs, 0, aRelocsSize);
+		E32RelocSection * aRelocSection = (E32RelocSection * )aRelocs;
+
+		uint16 * data = (uint16 *)(aRelocSection + 1);
+		E32RelocPageDesc * startofblock = (E32RelocPageDesc *)data;
+
+		int page = -1;
+		int pagesize = sizeof(E32RelocPageDesc);
+		ElfRelocations::RelocationList::iterator r;
+		for (r = aRelocList.begin(); r != aRelocList.end(); r++)
+		{
+			ElfLocalRelocation * aReloc = *r;
+			int p = aReloc->iAddr & 0xfffff000;
+			if (page != p)
+			{
+				if (pagesize%4 != 0)
+				{
+					*data++ = 0;
+					pagesize += sizeof(uint16);
+				}
+				if (page == -1) page = p;
+				startofblock->aOffset = page - aBase;
+				startofblock->aSize = pagesize;
+				pagesize = sizeof(E32RelocPageDesc);
+				page = p;
+				startofblock = (E32RelocPageDesc *)data;
+				data = (uint16 *)(startofblock + 1);
+			}
+			uint16 relocType = aReloc->Fixup();
+			*data++ = (uint16)((aReloc->iAddr & 0xfff) | relocType);
+			pagesize += sizeof(uint16);
+		}
+		if (pagesize%4 != 0)
+		{
+			*data++ = 0;
+			pagesize += sizeof(uint16);
+		}
+		startofblock->aOffset = page - aBase;
+		startofblock->aSize = pagesize;
+		((E32RelocSection *)aRelocs)->iNumberOfRelocs = aRelocList.size();
+		((E32RelocSection *)aRelocs)->iSize = rsize;
+
+	}
+}
+
+/**
+This function calculates the relocation taking into consideration
+the page boundaries if they are crossed. The relocations are
+sorted.
+@param aRelocList - relocations found in the Elf file.
+@internalComponent
+@released
+*/
+size_t E32ImageFile::RelocationsSize(ElfRelocations::RelocationList & aRelocList)
+{
+	size_t bytecount = 0;
+	int page = -1;
+	ElfRelocations::RelocationList::iterator r;
+	for (r = aRelocList.begin(); r != aRelocList.end(); r++)
+	{
+		ElfLocalRelocation * aReloc = *r;
+		int p = aReloc->iAddr & 0xfffff000;
+		if (page != p)
+			{
+			if (bytecount%4 != 0)
+				bytecount += sizeof(uint16);
+			bytecount += sizeof(E32RelocPageDesc); // page, block size
+			page = p;
+			}
+		bytecount += sizeof(uint16);
+		}
+	if (bytecount%4 != 0)
+		bytecount += sizeof(uint16);
+	return bytecount;
+}
+
+/**
+This function returns the E32 interpretation for an Elf relocation type.
+@param aReloc - relocation entry.
+@internalComponent
+@released
+*/
+E32ImageFile::uint16 E32ImageFile::GetE32RelocType(ElfRelocation * aReloc)
+{
+	ESegmentType aSegType = aReloc->iSegmentType; // iElfExecutable->SegmentType(aReloc->iSymbol->st_value);
+	switch (aSegType)
+	{
+	case ESegmentRO:
+		return KTextRelocType;
+	case ESegmentRW:
+		return KDataRelocType;
+	default:
+		break;
+	};
+
+	// maybe this should be an error
+	return KInferredRelocType;
+}
+
+/**
+This function constructs the E32 image.
+@internalComponent
+@released
+*/
+void E32ImageFile::ConstructImage()
+{
+	InitE32ImageHeader();
+	ComputeE32ImageLayout();
+	FinalizeE32Image();
+	AllocateE32Image();
+}
+
+/**
+This function calculates the timestamp.
+@param aTime
+@internalComponent
+@released
+*/
+Int64 timeToInt64(TInt aTime)
+{
+	aTime-=(30*365*24*60*60+7*24*60*60);	// seconds since midnight Jan 1st, 2000
+	Int64 daysTo2000AD=730497;
+	Int64 t=daysTo2000AD*24*3600+aTime;	// seconds since 0000
+	t=t+3600;								// BST (?)
+	return t*1000000;						// milliseconds
+}
+
+/**
+This function returns the E32 image header size.
+@internalComponent
+@released
+*/
+size_t E32ImageFile::GetE32ImageHeaderSize()
+{
+	return sizeof(E32ImageHeaderV);
+}
+
+/**
+This function returns the extended E32 image header size.
+@internalComponent
+@released
+*/
+size_t E32ImageFile::GetExtendedE32ImageHeaderSize()
+{
+	return iHdrSize;
+}
+
+/**
+This function sets the extended E32 image header size.
+@internalComponent
+@released
+*/
+void E32ImageFile::SetExtendedE32ImageHeaderSize(size_t aSize)
+{
+	iHdrSize = aSize;
+}
+
+/**
+This function initialises the E32 image header fields.
+@internalComponent
+@released
+*/
+void E32ImageFile::InitE32ImageHeader()
+{
+	iHdr = iUseCase->AllocateE32ImageHeader();
+	
+	iHdr->iUid1 = 0;
+	iHdr->iUid2 = 0;
+	iHdr->iUid3 = 0;
+	iHdr->iHeaderCrc = 0;
+	iHdr->iSignature = 0x434f5045u;
+	iHdr->iModuleVersion = 0x00010000u;
+	iHdr->iCompressionType = 0;
+	iHdr->iToolsVersion = TVersion(MajorVersion, MinorVersion, Build);
+	Int64 ltime(timeToInt64(time(0)));
+	iHdr->iTimeLo=(uint32)ltime;
+	iHdr->iTimeHi=(uint32)(ltime>>32);
+	iHdr->iFlags = KImageHdrFmt_V;
+	// Confusingly, CodeSize means everything except writable data
+	iHdr->iCodeSize = 0;
+	iHdr->iDataSize = iElfExecutable->GetRWSize();
+	iHdr->iHeapSizeMin = 0;
+	iHdr->iHeapSizeMax = 0;
+	iHdr->iStackSize = 0;
+	iHdr->iBssSize = iElfExecutable->GetBssSize();
+	iHdr->iEntryPoint = 0;
+	iHdr->iCodeBase = iElfExecutable->GetROBase();
+	iHdr->iDataBase = iElfExecutable->GetRWBase();
+	iHdr->iDllRefTableCount = iNumDlls;
+	iHdr->iExportDirOffset = 0;
+	iHdr->iExportDirCount = iUseCase->GetNumExports();
+	iHdr->iTextSize = iElfExecutable->GetROSize();
+	iHdr->iCodeOffset = 0;
+	iHdr->iDataOffset = 0;
+	iHdr->iImportOffset = 0;
+	iHdr->iCodeRelocOffset = 0;
+	iHdr->iDataRelocOffset = 0;
+	iHdr->iProcessPriority = (uint16)EPriorityForeground;
+	iHdr->iUncompressedSize = 0;
+	iHdr->iS.iSecureId = 0;
+	iHdr->iS.iVendorId = 0;
+	iHdr->iExceptionDescriptor = 0;
+	iHdr->iSpare2 = 0;
+
+	iHdr->iExportDescSize = iUseCase->GetExportDescSize();
+	iHdr->iExportDescType = iUseCase->GetExportDescType();
+	if (iHdr->iExportDescSize == 0) iHdr->iExportDesc[0] = 0;
+
+}
+
+/**
+This function creates the E32 image layout.
+@internalComponent
+@released
+*/
+void E32ImageFile::ComputeE32ImageLayout()
+{
+	// E32Image header
+	iChunks.AddChunk((char *)iHdr, Align(GetExtendedE32ImageHeaderSize(), sizeof(uint32)), 0, "Image Header");
+
+	uint32 endOfHeader = iChunks.GetOffset();
+	
+		// Code section
+	iHdr->iCodeOffset = iChunks.GetOffset();
+	iChunks.AddChunk(iElfExecutable->GetRawROSegment(), iElfExecutable->GetROSize(), iHdr->iCodeOffset, "Code Section"); 
+	
+	// Exports Next - then we can set up CodeSize
+	// Call out to the use case so it can decide how we do this
+	// record exporttable offset for default case
+
+	bool aSymLkupEnabled = iUseCase->GetNamedSymLookup();
+	// The export table is required either when:
+	//	a. there are exported symbols
+	//	b. symbol lookup is enabled - because this table also indicates the dependencies
+	bool aExportTableNeeded = (iHdr->iExportDirCount || aSymLkupEnabled) ? 1 : 0;
+
+	iExportOffset = iChunks.GetOffset() + 4;
+	iHdr->iExportDirOffset = aExportTableNeeded ? iUseCase->GetExportOffset() : 0;
+	if ( aExportTableNeeded && iUseCase->AllocateExportTableP())
+		iChunks.AddChunk(iUseCase->GetExportTable(), iUseCase->GetExportTableSize(), iChunks.GetOffset(), "Export Table");
+
+	// Symbol info next
+	if( aSymLkupEnabled ){
+		E32EpocExpSymInfoHdr* aSymHdrInfo = (E32EpocExpSymInfoHdr*)CreateSymbolInfo(iChunks.GetOffset());
+		if( aSymHdrInfo )
+			iChunks.AddChunk( (char*)aSymHdrInfo, aSymHdrInfo->iSize, iChunks.GetOffset(), "Symbol Info" );
+	}
+
+	// CodeSize is current offset - endof header offset
+	iHdr->iTextSize = iHdr->iCodeSize = iChunks.GetOffset() - endOfHeader;
+
+	// Data section
+	if (iElfExecutable->GetRWSize())
+	{
+		iHdr->iDataOffset = iChunks.GetOffset();
+		iChunks.AddChunk(iElfExecutable->GetRawRWSegment(), iElfExecutable->GetRWSize(), iHdr->iDataOffset, "Data Section");
+	}
+	
+	// Import Section
+	if (iImportSectionSize)
+	{
+		iHdr->iImportOffset = iChunks.GetOffset();
+		iChunks.AddChunk((char *)iImportSection, iImportSectionSize, iHdr->iImportOffset, "Import Section");
+	}
+
+	// Code relocs
+	if (iCodeRelocsSize)
+	{
+		iHdr->iCodeRelocOffset = iChunks.GetOffset();
+		iChunks.AddChunk((char *)iCodeRelocs, iCodeRelocsSize, iHdr->iCodeRelocOffset, "Code Relocs");
+	}
+
+	// Data relocs
+	if (iDataRelocsSize)
+	{
+		iHdr->iDataRelocOffset = iChunks.GetOffset();
+		iChunks.AddChunk((char *)iDataRelocs, iDataRelocsSize, iHdr->iDataRelocOffset, "Data Relocs");
+	}
+
+	iLayoutDone = true;
+}
+
+/**
+This function returns the byte offset in the E32 image from where the
+export table starts.
+@internalComponent
+@released
+*/
+size_t E32ImageFile::GetExportOffset()
+{
+	return iExportOffset;
+}
+
+/**
+This function returns E32 image size.
+@internalComponent
+@released
+*/
+size_t E32ImageFile::GetE32ImageSize()
+{
+	assert(iLayoutDone);
+	return iChunks.GetOffset();
+
+}
+
+/**
+This function creates the export bitmap also replacing the absent symbols 
+with the entry point functions.
+@internalComponent
+@released
+*/
+void E32ImageFile::CreateExportBitMap()
+{
+	int nexp = iUseCase->GetNumExports();
+	size_t memsz = (nexp + 7) >> 3;
+	iExportBitMap = new uint8[memsz];
+	memset(iExportBitMap, 0xff, memsz);
+	// skip header
+	uint32 * exports = ((uint32 *)iUseCase->GetExportTable()) + 1;
+	uint32 absentVal = EntryPointOffset() + iElfExecutable->GetROBase();
+	iMissingExports = 0;
+	for (int i=0; i<nexp; ++i)
+	{
+		if (exports[i] == absentVal)
+		{
+			iExportBitMap[i>>3] &= ~(1u << (i & 7));
+			++iMissingExports;
+		}
+	}
+}
+
+/**
+This function creates export desription for the absent symbols.
+@internalComponent
+@released
+*/
+void E32ImageFile::AddExportDescription()
+{
+	CreateExportBitMap();
+	if (iMissingExports == 0)
+		return;	// nothing to do
+
+	int nexp = iUseCase->GetNumExports();
+	size_t memsz = (nexp + 7) >> 3;	// size of complete bitmap
+	size_t mbs = (memsz + 7) >> 3;	// size of meta-bitmap
+	size_t nbytes = 0;
+	unsigned int i;
+	for (i=0; i<memsz; ++i)
+		if (iExportBitMap[i] != 0xff)
+			++nbytes;				// number of groups of 8
+	uint8 edt = KImageHdr_ExpD_FullBitmap;
+	uint32 extra_space = memsz - 1;
+	if (mbs + nbytes < memsz)
+	{
+		edt = KImageHdr_ExpD_SparseBitmap8;
+		extra_space = mbs + nbytes - 1;
+	}
+	extra_space = (extra_space + sizeof(uint32) - 1) &~ (sizeof(uint32) - 1);
+
+	iHdr->iExportDescType = edt;
+	if (edt == KImageHdr_ExpD_FullBitmap)
+	{
+		iHdr->iExportDescSize = (uint16)memsz;
+		iHdr->iExportDesc[0] = iExportBitMap[0];
+		uint8 * aDesc = new uint8[extra_space];
+		memset(aDesc, 0, extra_space);
+		memcpy(aDesc, &iExportBitMap[1], memsz-1);
+		iChunks.AddChunk((char *)aDesc,extra_space, iChunks.GetOffset(), "Export Description");
+	}
+	else
+	{
+		iHdr->iExportDescSize = (uint16)(mbs + nbytes);
+		uint8 * aBuf = new uint8[extra_space + 1];
+		memset(aBuf , 0, extra_space + 1);
+		TUint8* mptr = aBuf;
+		TUint8* gptr = mptr + mbs;
+		for (i=0; i<memsz; ++i)
+		{
+			if (iExportBitMap[i] != 0xff)
+			{
+				mptr[i>>3] |= (1u << (i&7));
+				*gptr++ = iExportBitMap[i];
+			}
+		}
+		iHdr->iExportDesc[0] = aBuf[0];
+		uint8 * aDesc = new uint8[extra_space];
+		memcpy(aDesc, aBuf+1, extra_space);
+		delete[] aBuf;
+		iChunks.AddChunk((char *)aDesc,extra_space, iChunks.GetOffset(), "Export Description");
+	}
+}
+
+/**
+This function sets the fields of the E32 image.
+@internalComponent
+@released
+*/
+void E32ImageFile::FinalizeE32Image()
+{
+	// Arrange a header for this E32 Image
+	iHdr->iCpuIdentifier = GetCpuIdentifier();
+	// Import format is ELF-derived
+	iHdr->iFlags |= KImageImpFmt_ELF;
+	// ABI is ARM EABI
+	iHdr->iFlags |= KImageABI_EABI;
+	iHdr->iFlags |= KImageEpt_Eka2;
+
+	bool isDllp = iUseCase->ImageIsDll();
+	if (isDllp)
+	{
+		iHdr->iFlags |= KImageDll;
+		if (iHdr->iDataSize && !iUseCase->AllowDllData())
+			throw ELFFileError(DLLHASINITIALISEDDATAERROR, (char*)iUseCase->InputElfFileName());
+
+		if (iHdr->iBssSize  && !iUseCase->AllowDllData())
+			throw ELFFileError(DLLHASUNINITIALISEDDATAERROR, (char*)iUseCase->InputElfFileName());
+
+	}
+
+	iHdr->iHeapSizeMin = iUseCase->HeapCommittedSize();
+	iHdr->iHeapSizeMax = iUseCase->HeapReservedSize();
+	iHdr->iStackSize = iUseCase->StackCommittedSize();
+
+
+	iHdr->iEntryPoint = EntryPointOffset();
+
+	EEntryPointStatus r = ValidateEntryPoint();
+	if (r == EEntryPointCorrupt)
+		throw ELFFileError(ENTRYPOINTCORRUPTERROR, (char*)iUseCase->InputElfFileName());
+	else if (r == EEntryPointNotSupported)
+		throw ELFFileError(ENTRYPOINTNOTSUPPORTEDERROR, (char*)iUseCase->InputElfFileName());
+
+	SetUpExceptions();
+	SetUids();
+	SetSecureId();
+	SetVendorId();
+	SetCallEntryPoints();
+	SetCapability();
+	SetPriority(isDllp);
+	SetFixedAddress(isDllp);
+	SetVersion();
+	SetCompressionType();
+	SetFPU();
+
+	SetPaged();
+
+	SetSymbolLookup();
+	SetDebuggable();
+	SetSmpSafe();
+	UpdateHeaderCrc();
+}
+
+/**
+This function returns the CPU identifier for the E32 image header.
+@internalComponent
+@released
+*/
+E32ImageFile::uint16 E32ImageFile::GetCpuIdentifier()
+{
+	return (uint16)ECpuArmV5;
+}
+
+/**
+This function returns the entry point of the E32 image .
+@internalComponent
+@released
+*/
+E32ImageFile::uint32 E32ImageFile::EntryPointOffset()
+{
+	return iElfExecutable->EntryPointOffset();
+}
+
+/**
+This function validates the entry point of the E32 image .
+@internalComponent
+@released
+*/
+E32ImageFile::EEntryPointStatus E32ImageFile::ValidateEntryPoint()
+{
+	uint32 epOffset = iHdr->iEntryPoint;
+	if (epOffset & 3)
+		return EEntryPointOK;	// if entry point not 4 byte aligned, must be old style
+	uint32 fileOffset = epOffset + iElfExecutable->iCodeSegmentHdr->p_offset;
+	if (fileOffset+4 > iChunks.GetOffset())
+		return EEntryPointCorrupt;	// entry point is past the end of the file??
+	int ept = 0;			// old style if first instruction not recognised
+	uint8 * p = ELF_ENTRY_PTR(uint8, iElfExecutable->iElfHeader, fileOffset + 4);
+	uint32 x = *--p;
+	x<<=8;
+	x|=*--p;
+	x<<=8;
+	x|=*--p;
+	x<<=8;
+	x|=*--p;
+	if ((x & 0xffffff00) == 0xe31f0000)
+	{
+		// starts with tst pc, #n - new entry point
+		ept = (x & 0xff) + 1;
+	}
+	if (ept>7)
+		return EEntryPointNotSupported;
+	iHdr->iFlags |= (ept<<KImageEptShift);
+	return EEntryPointOK;
+}
+
+/**
+This function sets the exciption descriptor in the E32 image .
+@internalComponent
+@released
+*/
+void E32ImageFile::SetUpExceptions()
+{
+	char * aExDescName = "Symbian$$CPP$$Exception$$Descriptor";
+	Elf32_Sym * aSym = iElfExecutable->LookupStaticSymbol(aExDescName);
+	if (aSym)
+	{
+		uint32 aSymVaddr = aSym->st_value;
+		uint32 aROBase = iElfExecutable->GetROBase();
+		uint32 aROSize = iElfExecutable->GetROSize();
+		//check its in RO segment
+		if (aSymVaddr < aROBase || aSymVaddr >= (aROBase + aROSize))
+		{
+			throw ELFFileError(EXCEPTIONDESCRIPTOROUTSIDEROERROR,(char*)iUseCase->InputElfFileName());
+		}
+		// Set bottom bit so 0 in header slot means an old binary.
+		// The decriptor is always aligned on a 4 byte boundary.
+		iHdr->iExceptionDescriptor = (aSymVaddr - aROBase) | 0x00000001;
+	}	
+}
+
+/**
+This function sets the UIDs of the E32 image .
+@internalComponent
+@released
+*/
+void E32ImageFile::SetUids()
+{
+	iHdr->iUid1=iUseCase->GetUid1();
+	iHdr->iUid2=iUseCase->GetUid2();
+	iHdr->iUid3=iUseCase->GetUid3();
+}
+
+/**
+This function sets the secure ID of the E32 image as passed in the command line.
+@internalComponent
+@released
+*/
+void E32ImageFile::SetSecureId()
+{
+	if (iUseCase->GetSecureIdOption())
+		iHdr->iS.iSecureId = iUseCase->GetSecureId();
+	else
+		iHdr->iS.iSecureId = iUseCase->GetUid3();
+}
+
+/**
+This function sets the vendor Id of the E32 image as passed in command line.
+@internalComponent
+@released
+*/
+void E32ImageFile::SetVendorId()
+{
+	iHdr->iS.iVendorId = iUseCase->GetVendorId();
+}
+
+/**
+This function sets the call entry point of the E32 image .
+@internalComponent
+@released
+*/
+void E32ImageFile::SetCallEntryPoints()
+{
+	if (iUseCase->GetCallEntryPoints())
+		iHdr->iFlags|=KImageNoCallEntryPoint;
+	else
+		iHdr->iFlags&=~KImageNoCallEntryPoint;
+}
+
+/**
+This function sets the capcbility of the E32 image as specified in the command line.
+@internalComponent
+@released
+*/
+void E32ImageFile::SetCapability()
+{
+	iHdr->iS.iCaps = iUseCase->GetCapability();
+}
+
+/**
+This function sets the priority of the E32 exe.
+@internalComponent
+@released
+*/
+void E32ImageFile::SetPriority(bool isDllp)
+{
+	if (iUseCase->GetPriority())
+	{
+		if (isDllp)
+		{
+			cerr << "Warning: Cannot set priority of a DLL." << endl;
+		}
+		else
+			iHdr->iProcessPriority = (unsigned short)iUseCase->GetPriority();
+	}
+}
+
+/**
+This function sets the fixed address flag of the E32 image .
+@internalComponent
+@released
+*/
+void E32ImageFile::SetFixedAddress(bool isDllp)
+{
+	if (iUseCase->GetFixedAddress())
+	{
+		if (isDllp)
+		{
+			cerr << "Warning: Cannot set fixed address for DLL." << endl;
+		}
+		else
+			iHdr->iFlags|=KImageFixedAddressExe;
+	}
+	else
+		iHdr->iFlags&=~KImageFixedAddressExe;
+}
+
+/**
+This function sets the version of the E32 image .
+@internalComponent
+@released
+*/
+void E32ImageFile::SetVersion()
+{
+	iHdr->iModuleVersion = iUseCase->GetVersion();
+}
+
+/**
+This function sets the compression type of the E32 image .
+@internalComponent
+@released
+*/
+void E32ImageFile::SetCompressionType()
+{
+	if(iUseCase->GetCompress())
+		iHdr->iCompressionType = iUseCase->GetCompressionMethod();
+	else
+		iHdr->iCompressionType = KFormatNotCompressed;
+
+}
+
+/**
+This function sets the FPU type that the E32 image targets .
+@internalComponent
+@released
+*/
+void E32ImageFile::SetFPU()
+{
+	iHdr->iFlags &=~ KImageHWFloatMask;
+
+	if (iUseCase->GetFPU() == 1)
+		iHdr->iFlags |= KImageHWFloat_VFPv2;
+}
+
+/**
+This function sets the paging attribute in the E32 image.
+@internalComponent
+@released
+*/
+void E32ImageFile::SetPaged()
+{
+	// Code paging.
+
+	if ( iUseCase->IsCodePaged() )
+	{
+		iHdr->iFlags |= KImageCodePaged;
+		iHdr->iFlags &= ~KImageCodeUnpaged;
+	}
+	else if ( iUseCase->IsCodeUnpaged() )
+	{
+		iHdr->iFlags |= KImageCodeUnpaged;
+		iHdr->iFlags &= ~KImageCodePaged;
+	}
+	else if ( iUseCase->IsCodeDefaultPaged() )
+	{
+		iHdr->iFlags &= ~KImageCodePaged;
+		iHdr->iFlags &= ~KImageCodeUnpaged;
+	}
+
+	// Data paging.
+
+	if ( iUseCase->IsDataPaged() )
+	{
+		iHdr->iFlags |=  KImageDataPaged;
+		iHdr->iFlags &= ~KImageDataUnpaged;
+	}
+	else if ( iUseCase->IsDataUnpaged() )
+	{
+		iHdr->iFlags |=  KImageDataUnpaged;
+		iHdr->iFlags &= ~KImageDataPaged;
+	}
+	else if ( iUseCase->IsDataDefaultPaged() )
+	{
+		iHdr->iFlags &= ~KImageDataPaged;
+		iHdr->iFlags &= ~KImageDataUnpaged;
+	}
+}
+
+/**
+This function sets the Debuggable attribute in the E32 image.
+@internalComponent
+@released
+*/
+void E32ImageFile::SetDebuggable()
+{
+	if (iUseCase->IsDebuggable() == true)
+	{
+		iHdr->iFlags |= KImageDebuggable;
+	}
+	else
+	{
+		iHdr->iFlags &= ~KImageDebuggable;
+	}
+}
+
+
+void E32ImageFile::SetSmpSafe()
+{
+	if ( iUseCase->IsSmpSafe() )
+	{
+		iHdr->iFlags |= KImageSMPSafe;
+	}
+	else
+	{
+		iHdr->iFlags &= ~KImageSMPSafe;
+	}
+}
+
+/**
+This function sets the named symol-lookup attribute in the E32 image.
+@internalComponent
+@released
+*/
+void E32ImageFile::SetSymbolLookup()
+{
+	if(iUseCase->GetNamedSymLookup())
+	{
+		iHdr->iFlags |= KImageNmdExpData;
+	}
+	else
+	{
+		iHdr->iFlags &= ~KImageNmdExpData;
+	}
+}
+
+/**
+Class for Uids.
+@internalComponent
+@released
+*/
+class TE32ImageUids
+{
+public:
+	TE32ImageUids(TUint32 aUid1, TUint32 aUid2, TUint32 aUid3);
+	void Set(const TUidType& aUidType);
+	TUint Check() { return ((checkSum(((TUint8*)this)+1)<<16)|checkSum(this));}
+private:
+	TUidType iType;
+	TUint iCheck;
+
+};
+
+/**
+Constructor for TE32ImageUids.
+@internalComponent
+@released
+*/
+TE32ImageUids::TE32ImageUids(TUint32 aUid1, TUint32 aUid2, TUint32 aUid3)
+{
+	Set(TUidType(TUid::Uid(aUid1), TUid::Uid(aUid2), TUid::Uid(aUid3)));
+}
+
+/**
+This function sets the Uid.
+@internalComponent
+@released
+*/
+void TE32ImageUids::Set(const TUidType& aUidType)
+{
+    iType=aUidType;
+    iCheck=Check();
+}
+
+/**
+Default constructor for TUidType class.
+@internalComponent
+@released
+*/
+TUidType::TUidType()
+{
+	memset(this, 0, sizeof(TUidType));
+}
+
+/**
+Constructor for TUidType class.
+@internalComponent
+@released
+*/
+TUidType::TUidType(TUid aUid1,TUid aUid2,TUid aUid3)
+{
+	iUid[0]=aUid1;
+	iUid[1]=aUid2;
+	iUid[2]=aUid3;
+}
+
+// needed by E32ImageHeaderV::ValidateHeader...
+TCheckedUid::TCheckedUid(const TUidType& aUidType)
+	{
+    iType = aUidType;
+    iCheck = ((TE32ImageUids*)this)->Check();
+	}
+
+// needed by E32ImageHeaderV::ValidateHeader...
+void Mem::Crc32(TUint32& aCrc, const TAny* aPtr, TInt aLength)
+	{
+	::Crc32(aCrc, aPtr, aLength);
+	}
+
+/**
+This function updates the CRC of the E32 Image.
+@internalComponent
+@released
+*/
+void E32ImageFile::UpdateHeaderCrc()
+{
+	TE32ImageUids u(iHdr->iUid1, iHdr->iUid2, iHdr->iUid3);
+	iHdr->iUidChecksum = u.Check();
+	TInt hdrsz = GetExtendedE32ImageHeaderSize();
+	iHdr->iUncompressedSize = iChunks.GetOffset() - Align(GetExtendedE32ImageHeaderSize(), sizeof(uint32));
+	iHdr->iHeaderCrc = KImageCrcInitialiser;
+	uint32 crc = 0;
+	Crc32(crc, iHdr, hdrsz);
+	iHdr->iHeaderCrc = crc;
+}
+
+/**
+This function creates a buffer and writes all the data into the buffer.
+@internalComponent
+@released
+*/
+void E32ImageFile::AllocateE32Image()
+{
+	size_t aImageSize = iChunks.GetOffset();
+	iE32Image = new char[aImageSize];
+	memset(iE32Image, 0, aImageSize);
+
+	E32ImageChunks::ChunkList aChunkList = iChunks.GetChunks();
+	E32ImageChunks::ChunkList::iterator p;
+	for(p = aChunkList.begin(); p != aChunkList.end(); p++)
+	{
+		(*p)->Write(iE32Image);
+	}
+
+	E32ImageHeaderV* header = (E32ImageHeaderV*)iE32Image;
+	TInt headerSize = header->TotalSize();
+	if(KErrNone!=header->ValidateWholeImage(iE32Image+headerSize,GetE32ImageSize()-headerSize))
+		throw InvalidE32ImageError(VALIDATIONERROR, (char*)iUseCase->OutputE32FileName());
+}
+
+/**
+This function deflates the compressed data.
+@param bytes
+@param size
+@param os
+@internalComponent
+@released
+*/
+void DeflateCompress(char* bytes, size_t size, ofstream & os);
+
+/**
+This function Paged Pack the compressed data.
+@param bytes
+@param size
+@param os
+@internalComponent
+@released
+*/
+void CompressPages(TUint8 * bytes, TInt size, ofstream& os);
+
+
+/**
+This function writes into the final E32 image file.
+@param aName - E32 image file name
+@internalComponent
+@released
+*/
+bool E32ImageFile::WriteImage(const char * aName)
+{
+	ofstream *os = new ofstream();
+	os->open(aName, ofstream::binary|ofstream::out);
+
+	if (os->is_open()) 
+	{
+		uint32 compression = iHdr->CompressionType();
+		if (compression == KUidCompressionDeflate)
+		{
+			size_t aHeaderSize = GetExtendedE32ImageHeaderSize();
+			size_t aBodySize = GetE32ImageSize() - aHeaderSize;
+			os->write(iE32Image, aHeaderSize);
+			DeflateCompress(iE32Image + aHeaderSize, aBodySize, *os);
+		}
+		else if (compression == KUidCompressionBytePair)
+		{
+			size_t aHeaderSize = GetExtendedE32ImageHeaderSize();
+			os->write(iE32Image, aHeaderSize);
+			
+			// Compress and write out code part
+			int srcStart = GetExtendedE32ImageHeaderSize();
+			CompressPages( (TUint8*)iE32Image + srcStart, iHdr->iCodeSize, *os);
+			
+			
+			// Compress and write out data part
+			srcStart += iHdr->iCodeSize;
+			int srcLen = GetE32ImageSize() - srcStart;
+			
+			CompressPages((TUint8*)iE32Image + srcStart, srcLen, *os);		
+
+		}
+		else if (compression == 0)
+		{
+			os->write(iE32Image, GetE32ImageSize()); // image not compressed
+		}
+
+	} 
+	else
+	{
+		throw FileError(FILEOPENERROR,(char*)aName);
+	}
+	os->close();
+	if(os!=NULL)
+	{
+	delete os;
+	os = NULL;
+	}
+	return true;
+}
+
+
+/**
+Constructor for E32ImageFile class.
+@internalComponent
+@released
+*/
+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)  
+{
+	
+};
+
+/**
+Destructor for E32ImageFile class.
+@internalComponent
+@released
+*/
+E32ImageFile::~E32ImageFile()
+{
+	delete[] iData;
+	if (iHdr && iHdr != iOrigHdr)
+		delete iHdr;
+
+	delete [] iExportBitMap;
+	delete [] iE32Image;
+	delete [] iImportSection;
+
+ 	std::vector<char*>::iterator aPos;
+ 	char *aPtr;
+ 	aPos = cleanupStack.begin();
+ 	while( aPos != cleanupStack.end() )
+ 	{
+ 		aPtr = *aPos;
+ 		delete [] aPtr;
+ 		aPos++;
+ 	}
+	
+}
+
+/**
+Adjust the size of allocated data and fix the member data
+@internalComponent
+@released
+*/
+void E32ImageFile::Adjust(TInt aSize, TBool aAllowShrink)
+{
+	TInt asize = ((aSize+0x3)&0xfffffffc);
+
+	if (asize == iSize)
+		return;
+
+	if (iSize == 0)
+	{
+		iSize = asize;
+		iData = new char[iSize];
+		memset(iData, 0, iSize);
+	}
+	else if (aAllowShrink || asize > iSize)
+	{
+		TInt oldsize = iSize;
+		iSize = asize;
+		iData = (char*)realloc(iData, iSize);
+		
+		if (iSize > oldsize)
+			memset(iData+oldsize, 0, iSize-oldsize);
+	}
+	
+	if (!iData)
+		iSize = 0;
+	
+	if (iHdr && iHdr == iOrigHdr)
+		iHdr = (E32ImageHeaderV*)iData;
+	
+	iOrigHdr = (E32ImageHeader*)iData;
+}
+
+/**
+Read the E32 image.
+@param is - input stream
+@internalComponent
+@released
+*/
+TInt E32ImageFile::ReadHeader(ifstream& is)
+{
+	Adjust(sizeof(E32ImageHeader), EFalse);
+	is.read(iData, sizeof(E32ImageHeader));
+	TInt hdrsz = iOrigHdr->TotalSize();
+	
+	if (hdrsz > 0x10000)
+		return KErrCorrupt;	// sanity check
+	
+	if (hdrsz > (TInt)sizeof(E32ImageHeader))
+	{
+		Adjust(hdrsz, EFalse);
+		is.read(iData+sizeof(E32ImageHeader), hdrsz-sizeof(E32ImageHeader));
+	}
+
+	TUint32 uncompressedSize;
+	TInt r = iOrigHdr->ValidateHeader(iFileSize,uncompressedSize);
+	
+	if (r != KErrNone)
+	{
+		fprintf(stderr, "Integrity check failed %d\n", r);
+		return r;
+	}
+	
+	iHdr = (E32ImageHeaderV*)iOrigHdr;
+	return KErrNone;
+}
+
+/**
+Return the offset of the text section
+@internalComponent
+@released
+*/
+TUint E32ImageFile::TextOffset()
+{
+	return 0;
+}
+
+/**
+Return the offset of the data section
+@internalComponent
+@released
+*/
+TUint E32ImageFile::DataOffset()
+{
+	return iHdr->iCodeSize;
+}
+
+/**
+Return the offset of the bss section
+@internalComponent
+@released
+*/
+TUint E32ImageFile::BssOffset()
+{
+	return DataOffset()+iHdr->iDataSize;
+}
+
+
+/**
+This function creates the bitmap after reading the E32 image file
+@internalComponent
+@released
+*/
+void E32ImageFile::E32ImageExportBitMap()
+{
+	TInt nexp = iOrigHdr->iExportDirCount;
+	TInt memsz = (nexp + 7) >> 3;
+	iExportBitMap = new TUint8[memsz];
+	memset(iExportBitMap, 0xff, memsz);
+	TUint* exports = (TUint*)(iData + iOrigHdr->iExportDirOffset);
+	TUint absoluteEntryPoint = iOrigHdr->iEntryPoint + iOrigHdr->iCodeBase;
+	TUint impfmt = iOrigHdr->ImportFormat();
+	TUint hdrfmt = iOrigHdr->HeaderFormat();
+	TUint absentVal = (impfmt == KImageImpFmt_ELF) ? absoluteEntryPoint : iOrigHdr->iEntryPoint;
+	TInt i;
+	iMissingExports = 0;
+	
+	for (i=0; i<nexp; ++i)
+	{
+		if (exports[i] == absentVal)
+		{
+			iExportBitMap[i>>3] &= ~(1u << (i & 7));
+			++iMissingExports;
+		}
+	}
+	
+	if (hdrfmt < KImageHdrFmt_V && iMissingExports)
+	{
+		fprintf(stderr, "Bad exports\n");
+		exit(999);
+	}
+}
+
+/**
+This function creates the export description after reading the E32 image file
+@internalComponent
+@released
+*/
+TInt E32ImageFile::CheckExportDescription()
+{
+	TUint hdrfmt = iOrigHdr->HeaderFormat();
+	if (hdrfmt < KImageHdrFmt_V && iMissingExports)
+		return KErrCorrupt;
+	
+	if (iHdr->iExportDescType == KImageHdr_ExpD_NoHoles)
+	{
+		return iMissingExports ? KErrCorrupt : KErrNone;
+	}
+	
+	TInt nexp = iOrigHdr->iExportDirCount;
+	TInt memsz = (nexp + 7) >> 3;	// size of complete bitmap
+	TInt mbs = (memsz + 7) >> 3;	// size of meta-bitmap
+	TInt eds = iHdr->iExportDescSize;
+	
+	if (iHdr->iExportDescType == KImageHdr_ExpD_FullBitmap)
+	{
+		if (eds != memsz)
+			return KErrCorrupt;
+		if (memcmp(iHdr->iExportDesc, iExportBitMap, eds) == 0)
+			return KErrNone;
+		return KErrCorrupt;
+	}
+	
+	if (iHdr->iExportDescType != KImageHdr_ExpD_SparseBitmap8)
+		return KErrNotSupported;
+	
+	TInt nbytes = 0;
+	TInt i;
+	for (i=0; i<memsz; ++i)
+		if (iExportBitMap[i] != 0xff)
+			++nbytes;				// number of groups of 8
+	
+	TInt exp_extra = mbs + nbytes;
+	if (eds != exp_extra)
+		return KErrCorrupt;
+	
+	const TUint8* mptr = iHdr->iExportDesc;
+	const TUint8* gptr = mptr + mbs;
+	for (i=0; i<memsz; ++i)
+	{
+		TUint mbit = mptr[i>>3] & (1u << (i&7));
+		if (iExportBitMap[i] != 0xff)
+		{
+			if (!mbit || *gptr++ != iExportBitMap[i])
+				return KErrCorrupt;
+		}
+		else if (mbit)
+			return KErrCorrupt;
+	}
+	
+	return KErrNone;
+}
+
+
+int  DecompressPages(TUint8 * bytes, ifstream& is);
+
+
+/**
+This function creates the E32 image reading from the file
+@param is
+@param aImage
+@internalComponent
+@released
+*/
+ifstream& operator>>(ifstream& is, E32ImageFile& aImage)
+{
+	aImage.iError = aImage.ReadHeader(is);
+	if (aImage.iError != KErrNone)
+		return is;
+	
+	E32ImageHeader* oh = aImage.iOrigHdr;
+	TInt orighdrsz = oh->TotalSize();
+	int remainder = aImage.iSize - orighdrsz;
+	TUint compression = oh->CompressionType();
+	if (compression == 0)
+	{
+		is.read(aImage.iData + orighdrsz, remainder);
+	}
+	else if (compression == KUidCompressionDeflate)
+	{ //Uncompress
+		aImage.iError = KErrNoMemory;
+		unsigned int uncompsize = ((E32ImageHeaderComp*)aImage.iOrigHdr)->iUncompressedSize;
+		aImage.Adjust(uncompsize + orighdrsz);
+		
+		if (aImage.iData==NULL)
+			return is;
+		
+		oh = aImage.iOrigHdr;
+		
+		unsigned char* compressedData = new unsigned char[remainder];
+		if (compressedData==NULL)
+			return is;
+		
+		is.read(reinterpret_cast<char *>(compressedData), remainder);
+		unsigned int destsize = uncompsize;
+		InflateUnCompress( compressedData, remainder, (unsigned char*)(aImage.iData + orighdrsz), destsize);
+		
+		if (destsize != uncompsize)
+			MessageHandler::GetInstance()->ReportMessage(WARNING, HUFFMANINCONSISTENTSIZEERROR);
+		
+		delete [] compressedData;
+		
+		if ((TUint)orighdrsz > oh->iCodeOffset)
+		{
+			// need to adjust code offsets in original
+			aImage.iOrigHdrOffsetAdj = (TUint)orighdrsz - oh->iCodeOffset;
+			aImage.OffsetAdjust(oh->iCodeOffset);
+			aImage.OffsetAdjust(oh->iDataOffset);
+			aImage.OffsetAdjust(oh->iCodeRelocOffset);
+			aImage.OffsetAdjust(oh->iDataRelocOffset);
+			aImage.OffsetAdjust(oh->iImportOffset);
+			aImage.OffsetAdjust(oh->iExportDirOffset);
+		}
+		aImage.iError = KErrNone;
+	}
+	else if(compression == KUidCompressionBytePair)
+	{ // Uncompress
+		aImage.iError = KErrNoMemory;
+		unsigned int uncompsize = ((E32ImageHeaderComp*)aImage.iOrigHdr)->iUncompressedSize;
+		aImage.Adjust(uncompsize + orighdrsz);
+		if (aImage.iData==NULL)
+			return is;
+		oh = aImage.iOrigHdr;
+
+		// Read and decompress code part of the image
+
+		unsigned int uncompressedCodeSize = DecompressPages((TUint8 *) (aImage.iData + orighdrsz), is);
+
+		
+		// Read and decompress data part of the image
+
+		unsigned int uncompressedDataSize = DecompressPages((TUint8 *) (aImage.iData + orighdrsz + uncompressedCodeSize), is);
+
+		if (uncompressedCodeSize + uncompressedDataSize != uncompsize)
+			MessageHandler::GetInstance()->ReportMessage(WARNING, BYTEPAIRINCONSISTENTSIZEERROR);
+
+		if ((TUint)orighdrsz > oh->iCodeOffset)
+			{
+			// need to adjust code offsets in original
+			aImage.iOrigHdrOffsetAdj = (TUint)orighdrsz - oh->iCodeOffset;
+			aImage.OffsetAdjust(oh->iCodeOffset);
+			aImage.OffsetAdjust(oh->iDataOffset);
+			aImage.OffsetAdjust(oh->iCodeRelocOffset);
+			aImage.OffsetAdjust(oh->iDataRelocOffset);
+			aImage.OffsetAdjust(oh->iImportOffset);
+			aImage.OffsetAdjust(oh->iExportDirOffset);
+			}
+		aImage.iError = KErrNone;
+	}
+	aImage.E32ImageExportBitMap();
+
+	return is;
+}
+#ifdef __LINUX__ 
+#include <sys/stat.h>
+/**
+Simple function uses stdlib fstat to obtain the size of the file. 
+@param aFileName - e32 image file name
+@internalComponent
+@released
+*/ 
+int GetFileSize(const char* aFileName) {
+    // Open the file the old-fashioned way :-)
+    struct stat fileInfo; 
+    if(stat(aFileName,&fileInfo)!=0) {
+        throw FileError(FILEOPENERROR,(char *)aFileName);
+    }
+    off_t fileSize = fileInfo.st_size;
+    return fileSize; 
+}
+#else 
+int GetFileSize(const char* aFileName) {
+    _finddata_t fileinfo;
+	int ret=_findfirst((char *)aFileName,&fileinfo);
+	if (ret==-1) 
+	{
+		throw FileError(FILEOPENERROR,(char *)aFileName);
+	}
+    return fileinfo.size; 
+}
+#endif
+
+
+/**
+This function opens the  e32 image file.
+@param aFileName - e32 image file name
+@internalComponent
+@released
+*/
+TInt E32ImageFile::Open(const char* aFileName)
+{
+	iFileSize = GetFileSize(aFileName);
+	
+	Adjust(iFileSize);
+	ifstream ifile((char *)aFileName, ios::in | ios::binary);
+	if(!ifile.is_open())
+	{
+		throw FileError(FILEOPENERROR,(char *)aFileName);
+	}
+	ifile >> *this;
+	ifile.close();
+
+	if (iError != KErrNone)
+		return iError;
+	
+	return KErrNone;
+}
+
+void E32ImageFile::ProcessSymbolInfo() {
+	
+	Elf32_Addr aPlace = iUseCase->GetExportTableAddress() - 4;// This location points to 0th ord.
+	// Create a relocation entry for the 0th ordinal.
+	ElfLocalRelocation *aRel = new ElfLocalRelocation(iElfExecutable, aPlace, 0, 0, R_ARM_ABS32, \
+		NULL, ESegmentRO, NULL, false);
+	aRel->Add();
+
+	aPlace += iUseCase->GetExportTableSize();// aPlace now points to the symInfo
+	uint32 *aZerothOrd = (uint32*)iUseCase->GetExportTable();
+	*aZerothOrd = aPlace;
+	aPlace += sizeof(E32EpocExpSymInfoHdr);// aPlace now points to the symbol address
+											// which is just after the syminfo header.
+	if(!iElfExecutable->iExports)
+		return;
+
+	// Donot disturb the internal list sorting.
+	ElfExports::ExportList aList = iElfExecutable->iExports->GetExports(false);
+
+	ElfExports::ExportList::iterator aIter = aList.begin();
+	DllSymbol *aSym;
+	TUint aAlign, aNameLen;
+
+	
+	char aPad[] = {'\0', '\0', '\0', '\0'};
+
+
+	while ( aIter != aList.end() ) {
+		aSym = *aIter;
+		iSymAddrTab.push_back(aSym->iElfSym->st_value);
+		// The symbol names always start at a 4-byte aligned offset.
+		iSymNameOffset = iSymbolNames.size() >> 2;
+		iSymNameOffTab.push_back(iSymNameOffset);
+
+		iSymbolNames += aSym->SymbolName();
+		iSymbolNames += '\0';
+		aNameLen = iSymbolNames.size();
+		aAlign = Align(aNameLen, sizeof(int));
+		aAlign = aAlign - aNameLen;
+		if(aAlign % 4){
+			iSymbolNames.append(aPad, aAlign);
+		}
+		//Create a relocation entry...
+		aRel = new ElfLocalRelocation(iElfExecutable, aPlace, 0, 0, R_ARM_ABS32, NULL,\
+			ESegmentRO, aSym->iElfSym, false);
+		aPlace += sizeof(uint32);
+		aRel->Add();
+		aIter++;
+	}
+}
+
+char* E32ImageFile::CreateSymbolInfo(size_t aBaseOffset) {
+	E32EpocExpSymInfoHdr aSymInf;
+	uint32 aSizeofNames, aSize;
+
+	SetSymInfo(aSymInf);
+	if( aSymInf.iFlags & 1) {
+		aSizeofNames = sizeof(uint32);
+	}
+	else {
+		aSizeofNames = sizeof(uint16);
+	}
+
+	aSize = aSymInf.iSize;
+
+	char* aInfo = new char[aSize];
+	memset(aInfo, 0, aSize);
+	memcpy(aInfo, (void*)&aSymInf, sizeof(aSymInf));
+
+	TUint aPos = aSymInf.iSymbolTblOffset;
+	memcpy(aInfo+aPos, iSymAddrTab.begin(), iSymAddrTab.size()*sizeof(uint32));
+
+	aPos += iSymAddrTab.size()*aSizeofNames;
+	aPos += iSymNameOffTab.size()*aSizeofNames;
+	aPos = Align(aPos, sizeof(uint32));
+
+	std::vector<uint32>::iterator Iter = iSymNameOffTab.begin();
+	TInt aOffLen = 2;
+	if(aSymInf.iFlags & 1)
+		aOffLen=4;
+	while(Iter != iSymNameOffTab.end()){
+		memcpy( ((void*)(aInfo+aPos)), ((void*)Iter), aOffLen);
+		aPos += aOffLen;
+		Iter++;
+	}
+
+	aPos = aSymInf.iStringTableOffset;
+	memcpy(aInfo+aPos, iSymbolNames.begin(), iSymbolNames.size());
+
+	// At the end, the dependencies are listed. They remain zeroes and shall be fixed up
+	// while relocating.
+
+	// Update the import table to have offsets to ordinal zero entries
+	uint32 *aLocation, aOffset;
+	uint32 *aImportTab = iImportSection;
+
+	std::vector<int>::iterator aIter = iImportTabLocations.begin();
+	aOffset = aBaseOffset - iHdr->iCodeOffset;// This gives the offset of syminfo table base
+										// wrt the code section start
+	aOffset += aSymInf.iDepDllZeroOrdTableOffset; // This points to the ordinal zero offset table now
+	while( aIter != iImportTabLocations.end()) {
+		aLocation = (aImportTab + *aIter);
+		*aLocation = aOffset;
+		aOffset += sizeof(uint32);
+		aIter++;
+	}
+
+	return aInfo;
+}
+
+void E32ImageFile::SetSymInfo(E32EpocExpSymInfoHdr& aSymInfo)
+{
+	uint32 aSize = sizeof(E32EpocExpSymInfoHdr);
+	memset(&aSymInfo, 0, aSize);
+
+	uint16 aNSymbols = (uint16) iSymAddrTab.size();
+	aSymInfo.iSymCount = aNSymbols;
+	aSymInfo.iSymbolTblOffset = aSize;
+	aSize += aNSymbols * sizeof(uint32); // Symbol addresses
+	TUint aNameTabSz = iSymbolNames.size();
+	TInt aSizeofNames;
+
+	if( iSymNameOffset < 0xffff) {
+		aSizeofNames = sizeof(uint16);
+		aSymInfo.iFlags &= ~1;//reset the 0th bit
+	}
+	else {
+		aSizeofNames = sizeof(uint32);
+		aSymInfo.iFlags |= 1;//set the 0th bit
+	}
+	aSize += Align((aNSymbols * aSizeofNames), sizeof(uint32)); // Symbol name offsets
+	aSymInfo.iStringTableOffset = aSize;
+	aSize += aNameTabSz; // Symbol names in string tab
+	aSymInfo.iStringTableSz = aNameTabSz;
+	aSymInfo.iDepDllZeroOrdTableOffset = aSize;
+	aSymInfo.iDllCount = iNumDlls ;
+	aSize += iNumDlls * sizeof(uint32); // Dependency list - ordinal zero placeholder
+	aSymInfo.iSize = aSize;
+}
+