--- /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;
+}
+