--- a/imgtools/imglib/e32image/e32image.cpp Wed Jun 16 16:51:40 2010 +0300
+++ b/imgtools/imglib/e32image/e32image.cpp Wed Jun 23 16:56:47 2010 +0800
@@ -1,861 +1,842 @@
-/*
-* Copyright (c) 1996-2009 Nokia Corporation and/or its subsidiary(-ies).
-* All rights reserved.
-* This component and the accompanying materials are made available
-* under the terms of the License "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:
-* e32tools/e32image/e32image.cpp
-* Basic operations on E32Image files which are used by ROMBUILD.
-* These are independent of the original file format from which the
-* E32Image file was derived.
-*
-*/
-
-
-#include <time.h>
-#include <malloc.h>
-#include <string.h>
-#include <stdlib.h>
-#include "h_utl.h"
-
-
-#if defined (__MSVCDOTNET__) || defined(__TOOLS2__)
-#include <fstream>
-#else //!__MSVCDOTNET__
-#include <fstream.h>
-#endif //__MSVCDOTNET__
-
-#include <assert.h>
-#ifndef __LINUX__
- #include <io.h>
-#endif
-#include "h_ver.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 "e32image.h"
-
-void DeflateCompress(char* bytes, TInt size, ostream& os);
-void InflateUnCompress(unsigned char* source, int sourcesize, unsigned char* dest, int destsize);
-void CompressPages(TUint8 * bytes, TInt size, ostream &os, CBytePair *aBPE);
-int DecompressPages(TUint8 * bytes, istream& is, CBytePair *aBPE);
-
-// needed by E32ImageHeaderV::ValidateHeader...
-void Mem::Crc32(TUint32& aCrc, const TAny* aPtr, TInt aLength)
- {
- HMem::Crc32(aCrc, aPtr, aLength);
- }
-
-//
-// E32 Image files
-//
-E32ImageFile::E32ImageFile(CBytePair *aBPE)
- : iData(NULL), iSize(0), iOrigHdr(NULL), iHdr(NULL), iFileName(NULL)
-#ifndef __LINUX__
- , iWideFileName(NULL)
-#endif
-, iError(0), iSource(EE32Image), iOrigHdrOffsetAdj(0), iExportBitMap(0), iBPE(aBPE)
- {
- }
-
-E32ImageFile::~E32ImageFile()
- {
- free(iData);
- delete [] iFileName;
-#ifndef __LINUX__
- delete [] iWideFileName;
-#endif
- if (iHdr && iHdr != iOrigHdr)
- delete iHdr;
- free(iExportBitMap);
- }
-
-// dummy implementation
-TBool E32ImageFile::Translate(const char*, TUint, TBool, TBool)
- {
- return EFalse;
- }
-
-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
- }
-
-class TE32ImageUids : public TCheckedUid
- {
-public:
- TE32ImageUids(TUint32 aUid1, TUint32 aUid2, TUint32 aUid3) : TCheckedUid(TUidType(TUid::Uid(aUid1), TUid::Uid(aUid2), TUid::Uid(aUid3))) {}
- TUint Check() { return TCheckedUid::Check(); }
- };
-
-void E32ImageFile::SetDefaultHeader()
- {
- iHdr = (E32ImageHeaderV*)iOrigHdr;
- 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 time1(timeToInt64(time(0)));
- iHdr->iTimeLo=(TUint32)time1;
- iHdr->iTimeHi=(TUint32)(time1>>32);
- iHdr->iFlags = KImageHdrFmt_V;
- iHdr->iCodeSize = 0;
- iHdr->iDataSize = 0;
- iHdr->iHeapSizeMin = 0;
- iHdr->iHeapSizeMax = 0;
- iHdr->iStackSize = 0;
- iHdr->iBssSize = 0;
- iHdr->iEntryPoint = 0;
- iHdr->iCodeBase = 0;
- iHdr->iDataBase = 0;
- iHdr->iDllRefTableCount = 0;
- iHdr->iExportDirOffset = 0;
- iHdr->iExportDirCount = 0;
- iHdr->iTextSize = 0;
- iHdr->iCodeOffset = 0;
- iHdr->iDataOffset = 0;
- iHdr->iImportOffset = 0;
- iHdr->iCodeRelocOffset = 0;
- iHdr->iDataRelocOffset = 0;
- iHdr->iProcessPriority = (TUint16)EPriorityForeground;
- iHdr->iUncompressedSize = 0;
- iHdr->iS.iSecureId = 0;
- iHdr->iS.iVendorId = 0;
- iHdr->iExceptionDescriptor = 0;
- iHdr->iSpare2 = 0;
-
- iHdr->iExportDescSize = 0;
- iHdr->iExportDescType = KImageHdr_ExpD_NoHoles;
- iHdr->iExportDesc[0] = 0;
- }
-
-void E32ImageFile::SetCallEntryPoints(TInt aBool)
- {
-
- if (aBool)
- iHdr->iFlags&=~KImageNoCallEntryPoint;
- else
- iHdr->iFlags|=KImageNoCallEntryPoint;
- }
-
-void E32ImageFile::SetFixedAddress(TInt aBool)
- {
-
- if (aBool)
- iHdr->iFlags|=KImageFixedAddressExe;
- else
- iHdr->iFlags&=~KImageFixedAddressExe;
- }
-
-void E32ImageFile::SetPriority(TProcessPriority aPri)
- {
-
- iHdr->iProcessPriority = (TUint16)aPri;
- }
-
-void E32ImageFile::SetCapability(SCapabilitySet& aCapabilities)
- {
- iHdr->iS.iCaps = aCapabilities;
- }
-
-void E32ImageFile::SetFPU(unsigned int aFPU)
- {
- iHdr->iFlags &=~ KImageHWFloatMask;
-
- if (aFPU == 1)
- iHdr->iFlags |= KImageHWFloat_VFPv2;
- }
-
-void E32ImageFile::Adjust(TInt aSize, TBool aAllowShrink)
-//
-// Adjust the size of allocated data and fix the member data
-//
- {
-
- TInt asize = ALIGN4(aSize);
- if (asize == iSize)
- return;
- if (iSize == 0)
- {
- iSize = asize;
- iData = (char*)malloc(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;
- }
-
-TInt E32ImageFile::ReadHeader(ifstream& is)
- {
- Adjust(sizeof(E32ImageHeader), EFalse);
- is.read(iData, sizeof(E32ImageHeader));
- TInt hdrsz = iOrigHdr->TotalSize();
- if (hdrsz > 0x10000 || hdrsz <= 0)
- 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;
- }
-
-void E32ImageFile::SetStackSize(TInt aSize)
- {
- iHdr->iStackSize=aSize;
- }
-
-void E32ImageFile::SetHeapSizeMin(TInt aSize)
- {
- iHdr->iHeapSizeMin=aSize;
- }
-
-void E32ImageFile::SetHeapSizeMax(TInt aSize)
- {
- iHdr->iHeapSizeMax=aSize;
- }
-
-TUint E32ImageFile::TextOffset()
-//
-// Return the offset of the text section
-//
- {
- return 0;
- }
-
-TUint E32ImageFile::DataOffset()
-//
-// return the offset of the initialised data
-//
- {
- return iHdr->iCodeSize;
- }
-
-TUint E32ImageFile::BssOffset()
-//
-// return the offset from the start of code where the bss is linked
-//
- {
- return DataOffset()+iHdr->iDataSize;
- }
-
-
-TInt E32ImageFile::IsDll()
-//
-//
-//
- {
- return iHdr->iFlags&KImageDll;
- }
-
-
-void E32ImageFile::RelocateSection(char* aPtr, char* aRelocs, TUint aCodeDelta, TUint aDataDelta, char* aImagePtr, TLinAddr** aIATRefs, TBool keepIAT)
-//
-// Relocates the section data at aPtr
-//
- {
-
- TUint codeStart=iHdr->iCodeBase;
- TUint codeFinish=codeStart+iHdr->iCodeSize;
- TUint iatStart = aIATRefs ? codeStart+iHdr->iTextSize : 0;
- TUint iatFinish = aIATRefs ? iatStart+NumberOfImports()*sizeof(TUint) : 0;
- char* relocs=aRelocs;
- TUint page=0;
- TInt size=0;
- TInt i=((E32RelocSection *)relocs)->iNumberOfRelocs;
- relocs+=sizeof(E32RelocSection);
- while (i>0)
- {
- if (size>0)
- {
- TUint offset=*(TUint16 *)relocs;
- relocs+=2;
- if (offset!=0)
- { // its a reloc
- TUint va=page+(offset&0x0fff);
- TUint relocType=offset&0xf000;
- TUint *dataptr=(TUint *)(aPtr+va);
- assert((char *)dataptr < aRelocs);
- TUint data=*dataptr;
- if (relocType == KTextRelocType)
- *dataptr=data+aCodeDelta; // points to text/rdata section
- else if (relocType == KDataRelocType)
- *dataptr=data+aDataDelta;
- else
- {
- if (relocType != KInferredRelocType)
- Print(EError,"Unrecognized relocation type %x\n",relocType);
-
- if (data>=iatStart && data<iatFinish)
- {
-
- TUint iatNum = (data-iatStart)/sizeof(TLinAddr);
-
- // If "keepIAT" is used then the importing instruction must import through the IAT entry,
- // but otherwise we change the IAT entry to point to the bit of code doing the importing
- // and do the real fix-up later on in TRomBuilderEntry::FixupImports.
- // NB: We always want to do this for X86 or data exports dont work.
- if (keepIAT || (iHdr->iCpuIdentifier & 0x1000) /*denotes X86*/)
- *dataptr=data+aCodeDelta;
- else
- {
- if ((TUint)aIATRefs[iatNum]>65535)
- Print(EWarning, "Multiple relocations for IAT entry %d (0x%x, 0x%x)\n",
- iatNum, aIATRefs[iatNum], dataptr);
- else
- aIATRefs[iatNum] = (TLinAddr*)(aImagePtr+va); // ROM image address of importing pointer
- }
- }
- else if (data>=codeStart && data<codeFinish)
- *dataptr=data+aCodeDelta; // points to text/rdata section
- else
- *dataptr=data+aDataDelta; // points to data section
- }
- --i;
- }
- size-=2;
- }
- else
- { // next page of relocs
- page=*(TUint *)relocs;
- relocs+=4;
- size=*(TUint *)relocs;
- relocs+=4;
- size-=8;
- }
- }
- }
-
-void E32ImageFile::SetUids(TUid aUid1, TUid aUid2, TUid aUid3)
- {
- iHdr->iUid1=aUid1.iUid;
- iHdr->iUid2=aUid2.iUid;
- iHdr->iUid3=aUid3.iUid;
- }
-
-void E32ImageFile::SetSecureId(TUint32 aId)
- {
- ((E32ImageHeaderV*)iHdr)->iS.iSecureId = aId;
- }
-
-void E32ImageFile::SetVendorId(TUint32 aId)
- {
- ((E32ImageHeaderV*)iHdr)->iS.iVendorId = aId;
- }
-
-void E32ImageFile::UpdateHeaderCrc()
- {
- TE32ImageUids u(iHdr->iUid1, iHdr->iUid2, iHdr->iUid3);
- iHdr->iUidChecksum = u.Check();
- TInt hdrsz = iHdr->TotalSize();
- TInt orighdrsz = iOrigHdr->TotalSize();
- iHdr->iUncompressedSize = iSize - orighdrsz;
- iHdr->iHeaderCrc = KImageCrcInitialiser;
- TUint32 crc = 0;
- HMem::Crc32(crc, iHdr, hdrsz);
- iHdr->iHeaderCrc = crc;
- }
-
-TInt E32ImageFile::NumberOfImports()
-//
-// Return the number of imports made by this image
-//
- {
-
- if (iHdr->iDllRefTableCount==0 || iHdr->iImportOffset==0)
- return 0;
-
- TUint impfmt = iHdr->ImportFormat();
- const E32ImportSection* isection = (const E32ImportSection*)(iData + iOrigHdr->iImportOffset);
- TInt d;
- TInt nImports = 0;
- const E32ImportBlock* b = (const E32ImportBlock*)(isection+1);
- for (d=0; d<iHdr->iDllRefTableCount; d++)
- {
- nImports += b->iNumberOfImports;
- b = b->NextBlock(impfmt);
- }
-
- if (impfmt==KImageImpFmt_PE || impfmt==KImageImpFmt_PE2)
- {
- TUint *imports=(TUint *)(iData + iOrigHdr->iCodeOffset + iHdr->iTextSize);
- TInt i=0;
- while (*imports++)
- i++;
- assert(i==nImports);
- }
-
- return nImports;
- }
-
-// Work out which exports are missing from the export directory
-void E32ImageFile::CreateExportBitMap()
- {
- TInt nexp = iOrigHdr->iExportDirCount;
- TInt memsz = (nexp + 7) >> 3;
- iExportBitMap = (TUint8*)malloc(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);
- }
- }
-
-// Append an export description to the E32ImageHeader if necessary
-void E32ImageFile::AddExportDescription()
- {
- if (iMissingExports == 0)
- return; // nothing to do
- TInt nexp = iOrigHdr->iExportDirCount;
- TInt memsz = (nexp + 7) >> 3; // size of complete bitmap
- TInt mbs = (memsz + 7) >> 3; // size of meta-bitmap
- TInt nbytes = 0;
- TInt i;
- for (i=0; i<memsz; ++i)
- if (iExportBitMap[i] != 0xff)
- ++nbytes; // number of groups of 8
- TUint8 edt = KImageHdr_ExpD_FullBitmap;
- TInt extra_space = memsz - 1;
- if (mbs + nbytes < memsz)
- {
- edt = KImageHdr_ExpD_SparseBitmap8;
- extra_space = mbs + nbytes - 1;
- }
- extra_space = (extra_space + sizeof(TUint) - 1) &~ (sizeof(TUint) - 1);
- TInt hdrsz = sizeof(E32ImageHeaderV) + extra_space;
- iHdr = (E32ImageHeaderV*)malloc(hdrsz);
- memcpy(iHdr, iOrigHdr, sizeof(E32ImageHeaderV));
- iHdr->iExportDescType = edt;
- if (edt == KImageHdr_ExpD_FullBitmap)
- {
- iHdr->iExportDescSize = (TUint16)memsz;
- memcpy(iHdr->iExportDesc, iExportBitMap, memsz);
- }
- else
- {
- iHdr->iExportDescSize = (TUint16)(mbs + nbytes);
- memset(iHdr->iExportDesc, 0, extra_space + 1);
- TUint8* mptr = iHdr->iExportDesc;
- TUint8* gptr = mptr + mbs;
- for (i=0; i<memsz; ++i)
- {
- if (iExportBitMap[i] != 0xff)
- {
- mptr[i>>3] |= (1u << (i&7));
- *gptr++ = iExportBitMap[i];
- }
- }
- }
- iHdr->iCodeOffset += extra_space;
- if (iHdr->iDataOffset)
- iHdr->iDataOffset += extra_space;
- if (iHdr->iCodeRelocOffset)
- iHdr->iCodeRelocOffset += extra_space;
- if (iHdr->iDataRelocOffset)
- iHdr->iDataRelocOffset += extra_space;
- if (iHdr->iImportOffset)
- iHdr->iImportOffset += extra_space;
- if (iHdr->iExportDirOffset)
- iHdr->iExportDirOffset += extra_space;
- }
-
-// Check the export description is consistent with the export directory
-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;
- }
-
-
-TInt E32ImageFile::Validate()
- {
- TInt orighdrsz = iOrigHdr->TotalSize();
- TInt r = iHdr->ValidateWholeImage(iData+orighdrsz,iSize-orighdrsz);
- if(r!=KErrNone)
- return r;
- return r;
- }
-
-
-ostream& operator<<(ostream& os, const E32ImageFile& aImage)
-//
-// Output an E32ImageFile
-//
- {
- E32ImageHeaderV* h = aImage.iHdr;
- TUint hdrfmt = h->HeaderFormat();
- if (hdrfmt != KImageHdrFmt_V)
- return os; // don't generate old binary formats
- TInt hdrsz = h->TotalSize();
- TInt orighdrsz = aImage.iOrigHdr->TotalSize();
-
- os.write((const char*)aImage.iHdr, hdrsz);
-
- TUint compression = h->CompressionType();
- if (compression == KUidCompressionDeflate)
- {
- int srcsize = aImage.iSize - orighdrsz;
- DeflateCompress(aImage.iData + orighdrsz, srcsize, os);
- }
- else if (compression == KUidCompressionBytePair)
- {
- // Compress and write out code part
- int srcStart = orighdrsz;
- CompressPages( (TUint8*)aImage.iData + srcStart, aImage.iOrigHdr->iCodeSize, os, aImage.iBPE);
-
-
- // Compress and write out data part
- srcStart += aImage.iOrigHdr->iCodeSize;
- int srcLen = aImage.iSize - srcStart;
-
- CompressPages((TUint8*)aImage.iData + srcStart, srcLen, os, aImage.iBPE);
-
- }
- else if (compression == KFormatNotCompressed)
- {
- int srcsize = aImage.iSize - orighdrsz;
- os.write(aImage.iData + orighdrsz, srcsize); // image not to be compressed
- }
- return os;
- }
-
-ifstream& operator>>(ifstream& is, E32ImageFile& aImage)
-//
-// Input an E32ImageFile
-//
- {
- 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)
- Print(EWarning, "Inconsistent sizes discovered during uncompression.\n");
- 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, aImage.iBPE);
-
-
- // Read and decompress data part of the image
-
- unsigned int uncompressedDataSize = DecompressPages((TUint8 *) (aImage.iData + orighdrsz + uncompressedCodeSize), is, aImage.iBPE);
-
- if (uncompressedCodeSize + uncompressedDataSize != uncompsize)
- Print(EWarning, "Inconsistent sizes discovered during uncompression.\n");
-
- 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.CreateExportBitMap();
- return is;
- }
-
-TInt E32ImageFile::IsE32ImageFile(char *aFileName)
- {
-
-#ifdef __LINUX__
- E32ImageFile f;
- struct stat buf;
- if (stat(aFileName, &buf) < 0)
- {
- return FALSE;
- }
- f.iFileSize = buf.st_size;
-#else
- _finddata_t fileinfo;
- int ret=_findfirst((char *)aFileName,&fileinfo);
- if (ret==-1)
- return FALSE;
- E32ImageFile f;
- f.iFileSize = fileinfo.size;
-#endif
- ifstream ifile(aFileName, ios::in | ios::binary);
- if(!ifile.is_open())
- return FALSE;
- TInt r = f.ReadHeader(ifile);
- ifile.close();
- return (r == KErrNone);
- }
-
-TInt E32ImageFile::IsValid()
- {
- return (iError == KErrNone);
- }
-
-TInt E32ImageFile::Open(const char* aFileName)
-//
-// Open an E32 Image file
-//
- {
-#ifdef __LINUX__
- struct stat buf;
- if (stat(aFileName, &buf) < 0)
- {
- Print(EError,"Cannot open %s for input.\n",aFileName);
- return 1;
- }
- iFileSize = buf.st_size;
-#else
- _finddata_t fileinfo;
- int ret=_findfirst((char *)aFileName,&fileinfo);
- if (ret==-1)
- {
- Print(EError,"Cannot open %s for input.\n",aFileName);
- return 1;
- }
- iFileSize = fileinfo.size;
-#endif
- Adjust(iFileSize);
- ifstream ifile((char *)aFileName, ios::in | ios::binary);
- if(!ifile.is_open())
- {
- Print(EError,"Cannot open %s for input.\n",aFileName);
- return 1;
- }
- ifile >> *this;
- ifile.close();
- if (iError != KErrNone)
- return iError;
- iFileName=strdup((char *)aFileName);
- if (iFileName==NULL)
- return KErrNoMemory;
- return KErrNone;
- }
-
-#ifndef __LINUX__
-TInt E32ImageFile::Open(const wchar_t* aFileName)
-//
-// Open an E32 Image file
-//
- {
- _wfinddata_t fileinfo;
- int ret=_wfindfirst(aFileName,&fileinfo);
- if (ret==-1)
- {
- Print(EError,"Cannot open %ls for input.\n",aFileName);
- return 1;
- }
- iFileSize = fileinfo.size;
- Adjust(iFileSize);
-
- FILE* file = _wfopen(aFileName, L"rb");
-
- if(!file)
- {
- Print(EError,"Cannot open %ls for input.\n",aFileName);
- return 1;
- }
-
- #if defined(__TOOLS2__) || defined(__MSVCDOTNET__)
- char tmp[100]; // Convert wide character name to char *, then open a file.
- wcstombs(tmp,aFileName,100);
- ifstream ifile(tmp, ios::in | ios::binary);
- #else
- ifstream ifile(fileno(file));
- #endif
-
- if(!ifile.is_open())
- {
- Print(EError,"Cannot open %ls for input,\n",aFileName);
- return 1;
- }
-
- ifile >> *this;
- ifile.close();
- fclose(file);
- if (iError != KErrNone)
- return iError;
- iWideFileName=wcsdup(aFileName);
- if (iWideFileName==NULL)
- return KErrNoMemory;
- return KErrNone;
- }
-#endif
-
-TUint E32ImageFile::VaOfOrdinal(TUint aOrdinal)
-// return the offset of the exported symbol
- {
- TUint* exportdir = (TUint*)(iData + iOrigHdr->iExportDirOffset);
- return exportdir[aOrdinal-KOrdinalBase];
- }
-
-// Determine the type of entry point in this module and set the flags
-// in the E32Image header accordingly.
-TInt E32ImageFile::DetermineEntryPointType()
- {
- TUint cpu = iHdr->CpuIdentifier();
- if (cpu != ECpuArmV4 && cpu != ECpuArmV5)
- return KErrNone; // if not ARM, leave EPT as 0
- TUint epOffset = iHdr->iEntryPoint;
- if (epOffset & 3)
- return KErrNone; // if entry point not 4 byte aligned, must be old style
- TUint fileOffset = epOffset + iHdr->iCodeOffset;
- if (fileOffset+4 > (TUint)iSize)
- return KErrCorrupt; // entry point is past the end of the file??
- TInt ept = 0; // old style if first instruction not recognised
- unsigned char* p = (unsigned char*)iData + fileOffset + 4;
- TUint32 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 KErrNotSupported;
- iHdr->iFlags |= (ept<<KImageEptShift);
- return KErrNone;
- }
-
+/*
+* Copyright (c) 1996-2009 Nokia Corporation and/or its subsidiary(-ies).
+* All rights reserved.
+* This component and the accompanying materials are made available
+* under the terms of the License "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:
+* e32tools/e32image/e32image.cpp
+* Basic operations on E32Image files which are used by ROMBUILD.
+* These are independent of the original file format from which the
+* E32Image file was derived.
+*
+*/
+
+#include "h_utl.h"
+#include <time.h>
+#include <malloc.h>
+#include <string.h>
+#include <stdlib.h>
+
+
+
+
+#if defined(__TOOLS2__) || defined(__MSVCDOTNET__)
+#define IOS_BASE ios_base
+#include <fstream>
+#else
+#define IOS_BASE ios
+#include <fstream.h>
+#endif
+#include <assert.h>
+#ifndef __LINUX__
+ #include <io.h>
+#endif
+#include "h_ver.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 "e32image.h"
+
+void DeflateCompress(char* bytes, TInt size, ostream& os);
+void InflateUnCompress(unsigned char* source, int sourcesize, unsigned char* dest, int destsize);
+void CompressPages(TUint8 * bytes, TInt size, ostream &os, CBytePair *aBPE);
+int DecompressPages(TUint8 * bytes, istream& is, CBytePair *aBPE);
+
+// needed by E32ImageHeaderV::ValidateHeader...
+void Mem::Crc32(TUint32& aCrc, const TAny* aPtr, TInt aLength)
+ {
+ HMem::Crc32(aCrc, aPtr, aLength);
+ }
+
+//
+// E32 Image files
+//
+E32ImageFile::E32ImageFile(CBytePair *aBPE)
+ : iData(NULL), iSize(0), iOrigHdr(NULL), iHdr(NULL), iFileName(NULL)
+#ifndef __LINUX__
+ , iWideFileName(NULL)
+#endif
+, iError(0), iSource(EE32Image), iOrigHdrOffsetAdj(0), iExportBitMap(0), iBPE(aBPE)
+ {
+}
+
+E32ImageFile::~E32ImageFile(){
+ if(iData){
+ free(iData);
+ iData = 0 ;
+ }
+ if (iHdr && iHdr != iOrigHdr){
+ delete iHdr;
+ iHdr = 0 ;
+ }
+ if(iExportBitMap){
+ delete []iExportBitMap;
+ iExportBitMap = 0 ;
+ }
+ if(iFileName){
+ delete []iFileName ;
+ iFileName = 0;
+ }
+#ifndef __LINUX__
+ if(iWideFileName){
+ delete []iWideFileName ;
+ iWideFileName = 0;
+ }
+#endif
+}
+
+// dummy implementation
+TBool E32ImageFile::Translate(const char*, TUint, TBool, TBool)
+ {
+ return EFalse;
+ }
+
+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
+ }
+
+class TE32ImageUids : public TCheckedUid
+ {
+public:
+ TE32ImageUids(TUint32 aUid1, TUint32 aUid2, TUint32 aUid3) : TCheckedUid(TUidType(TUid::Uid(aUid1), TUid::Uid(aUid2), TUid::Uid(aUid3))) {}
+ TUint Check() { return TCheckedUid::Check(); }
+ };
+
+void E32ImageFile::SetDefaultHeader()
+ {
+ iHdr = (E32ImageHeaderV*)iOrigHdr;
+ 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 time1(timeToInt64(time(0)));
+ iHdr->iTimeLo=(TUint32)time1;
+ iHdr->iTimeHi=(TUint32)(time1>>32);
+ iHdr->iFlags = KImageHdrFmt_V;
+ iHdr->iCodeSize = 0;
+ iHdr->iDataSize = 0;
+ iHdr->iHeapSizeMin = 0;
+ iHdr->iHeapSizeMax = 0;
+ iHdr->iStackSize = 0;
+ iHdr->iBssSize = 0;
+ iHdr->iEntryPoint = 0;
+ iHdr->iCodeBase = 0;
+ iHdr->iDataBase = 0;
+ iHdr->iDllRefTableCount = 0;
+ iHdr->iExportDirOffset = 0;
+ iHdr->iExportDirCount = 0;
+ iHdr->iTextSize = 0;
+ iHdr->iCodeOffset = 0;
+ iHdr->iDataOffset = 0;
+ iHdr->iImportOffset = 0;
+ iHdr->iCodeRelocOffset = 0;
+ iHdr->iDataRelocOffset = 0;
+ iHdr->iProcessPriority = (TUint16)EPriorityForeground;
+ iHdr->iUncompressedSize = 0;
+ iHdr->iS.iSecureId = 0;
+ iHdr->iS.iVendorId = 0;
+ iHdr->iExceptionDescriptor = 0;
+ iHdr->iSpare2 = 0;
+
+ iHdr->iExportDescSize = 0;
+ iHdr->iExportDescType = KImageHdr_ExpD_NoHoles;
+ iHdr->iExportDesc[0] = 0;
+ }
+
+void E32ImageFile::SetCallEntryPoints(TInt aBool)
+ {
+
+ if (aBool)
+ iHdr->iFlags&=~KImageNoCallEntryPoint;
+ else
+ iHdr->iFlags|=KImageNoCallEntryPoint;
+ }
+
+void E32ImageFile::SetFixedAddress(TInt aBool)
+ {
+
+ if (aBool)
+ iHdr->iFlags|=KImageFixedAddressExe;
+ else
+ iHdr->iFlags&=~KImageFixedAddressExe;
+ }
+
+void E32ImageFile::SetPriority(TProcessPriority aPri)
+ {
+
+ iHdr->iProcessPriority = (TUint16)aPri;
+ }
+
+void E32ImageFile::SetCapability(SCapabilitySet& aCapabilities)
+ {
+ iHdr->iS.iCaps = aCapabilities;
+ }
+
+void E32ImageFile::SetFPU(unsigned int aFPU)
+ {
+ iHdr->iFlags &=~ KImageHWFloatMask;
+
+ if (aFPU == 1)
+ iHdr->iFlags |= KImageHWFloat_VFPv2;
+ }
+
+void E32ImageFile::Adjust(TInt aSize, TBool aAllowShrink)
+//
+// Adjust the size of allocated data and fix the member data
+//
+ {
+
+ TInt asize = ALIGN4(aSize);
+ if (asize == iSize)
+ return;
+ if (iSize == 0)
+ {
+ iSize = asize;
+ iData = (char*)malloc(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;
+ }
+
+TInt E32ImageFile::ReadHeader(ifstream& is)
+ {
+ Adjust(sizeof(E32ImageHeader), EFalse);
+ is.read(iData, sizeof(E32ImageHeader));
+ TInt hdrsz = iOrigHdr->TotalSize();
+ if (hdrsz > 0x10000 || hdrsz <= 0)
+ 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;
+ }
+
+void E32ImageFile::SetStackSize(TInt aSize)
+ {
+ iHdr->iStackSize=aSize;
+ }
+
+void E32ImageFile::SetHeapSizeMin(TInt aSize)
+ {
+ iHdr->iHeapSizeMin=aSize;
+ }
+
+void E32ImageFile::SetHeapSizeMax(TInt aSize)
+ {
+ iHdr->iHeapSizeMax=aSize;
+ }
+
+TUint E32ImageFile::TextOffset()
+//
+// Return the offset of the text section
+//
+ {
+ return 0;
+ }
+
+TUint E32ImageFile::DataOffset()
+//
+// return the offset of the initialised data
+//
+ {
+ return iHdr->iCodeSize;
+ }
+
+TUint E32ImageFile::BssOffset()
+//
+// return the offset from the start of code where the bss is linked
+//
+ {
+ return DataOffset()+iHdr->iDataSize;
+ }
+
+
+TInt E32ImageFile::IsDll()
+//
+//
+//
+ {
+ return iHdr->iFlags&KImageDll;
+ }
+
+
+void E32ImageFile::RelocateSection(char* aPtr, char* aRelocs, TUint aCodeDelta, TUint aDataDelta, char* aImagePtr, TLinAddr** aIATRefs, TBool keepIAT)
+//
+// Relocates the section data at aPtr
+//
+ {
+
+ TUint codeStart=iHdr->iCodeBase;
+ TUint codeFinish=codeStart+iHdr->iCodeSize;
+ TUint iatStart = aIATRefs ? codeStart+iHdr->iTextSize : 0;
+ TUint iatFinish = aIATRefs ? iatStart+NumberOfImports()*sizeof(TUint) : 0;
+ char* relocs=aRelocs;
+ TUint page=0;
+ TInt size=0;
+ TInt i=((E32RelocSection *)relocs)->iNumberOfRelocs;
+ relocs+=sizeof(E32RelocSection);
+ while (i>0)
+ {
+ if (size>0)
+ {
+ TUint offset=*(TUint16 *)relocs;
+ relocs+=2;
+ if (offset!=0)
+ { // its a reloc
+ TUint va=page+(offset&0x0fff);
+ TUint relocType=offset&0xf000;
+ TUint *dataptr=(TUint *)(aPtr+va);
+ assert((char *)dataptr < aRelocs);
+ TUint data=*dataptr;
+ if (relocType == KTextRelocType)
+ *dataptr=data+aCodeDelta; // points to text/rdata section
+ else if (relocType == KDataRelocType)
+ *dataptr=data+aDataDelta;
+ else
+ {
+ if (relocType != KInferredRelocType)
+ Print(EError,"Unrecognized relocation type %x\n",relocType);
+
+ if (data>=iatStart && data<iatFinish)
+ {
+
+ TUint iatNum = (data-iatStart)/sizeof(TLinAddr);
+
+ // If "keepIAT" is used then the importing instruction must import through the IAT entry,
+ // but otherwise we change the IAT entry to point to the bit of code doing the importing
+ // and do the real fix-up later on in TRomBuilderEntry::FixupImports.
+ // NB: We always want to do this for X86 or data exports dont work.
+ if (keepIAT || (iHdr->iCpuIdentifier & 0x1000) /*denotes X86*/)
+ *dataptr=data+aCodeDelta;
+ else
+ {
+ if ((TUint)aIATRefs[iatNum]>65535)
+ Print(EWarning, "Multiple relocations for IAT entry %d (0x%x, 0x%x)\n",
+ iatNum, aIATRefs[iatNum], dataptr);
+ else
+ aIATRefs[iatNum] = (TLinAddr*)(aImagePtr+va); // ROM image address of importing pointer
+ }
+ }
+ else if (data>=codeStart && data<codeFinish)
+ *dataptr=data+aCodeDelta; // points to text/rdata section
+ else
+ *dataptr=data+aDataDelta; // points to data section
+ }
+ --i;
+ }
+ size-=2;
+ }
+ else
+ { // next page of relocs
+ page=*(TUint *)relocs;
+ relocs+=4;
+ size=*(TUint *)relocs;
+ relocs+=4;
+ size-=8;
+ }
+ }
+ }
+
+void E32ImageFile::SetUids(TUid aUid1, TUid aUid2, TUid aUid3)
+ {
+ iHdr->iUid1=aUid1.iUid;
+ iHdr->iUid2=aUid2.iUid;
+ iHdr->iUid3=aUid3.iUid;
+ }
+
+void E32ImageFile::SetSecureId(TUint32 aId)
+ {
+ ((E32ImageHeaderV*)iHdr)->iS.iSecureId = aId;
+ }
+
+void E32ImageFile::SetVendorId(TUint32 aId)
+ {
+ ((E32ImageHeaderV*)iHdr)->iS.iVendorId = aId;
+ }
+
+void E32ImageFile::UpdateHeaderCrc()
+ {
+ TE32ImageUids u(iHdr->iUid1, iHdr->iUid2, iHdr->iUid3);
+ iHdr->iUidChecksum = u.Check();
+ TInt hdrsz = iHdr->TotalSize();
+ TInt orighdrsz = iOrigHdr->TotalSize();
+ iHdr->iUncompressedSize = iSize - orighdrsz;
+ iHdr->iHeaderCrc = KImageCrcInitialiser;
+ TUint32 crc = 0;
+ HMem::Crc32(crc, iHdr, hdrsz);
+ iHdr->iHeaderCrc = crc;
+ }
+
+TInt E32ImageFile::NumberOfImports()
+//
+// Return the number of imports made by this image
+//
+ {
+
+ if (iHdr->iDllRefTableCount==0 || iHdr->iImportOffset==0)
+ return 0;
+
+ TUint impfmt = iHdr->ImportFormat();
+ const E32ImportSection* isection = (const E32ImportSection*)(iData + iOrigHdr->iImportOffset);
+ TInt d;
+ TInt nImports = 0;
+ const E32ImportBlock* b = (const E32ImportBlock*)(isection+1);
+ for (d=0; d<iHdr->iDllRefTableCount; d++)
+ {
+ nImports += b->iNumberOfImports;
+ b = b->NextBlock(impfmt);
+ }
+
+ if (impfmt==KImageImpFmt_PE || impfmt==KImageImpFmt_PE2)
+ {
+ TUint *imports=(TUint *)(iData + iOrigHdr->iCodeOffset + iHdr->iTextSize);
+ TInt i=0;
+ while (*imports++)
+ i++;
+ assert(i==nImports);
+ }
+
+ return nImports;
+ }
+
+// Work out which exports are missing from the export directory
+void E32ImageFile::CreateExportBitMap()
+ {
+ 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);
+ }
+ }
+
+// Append an export description to the E32ImageHeader if necessary
+void E32ImageFile::AddExportDescription()
+ {
+ if (iMissingExports == 0)
+ return; // nothing to do
+ TInt nexp = iOrigHdr->iExportDirCount;
+ TInt memsz = (nexp + 7) >> 3; // size of complete bitmap
+ TInt mbs = (memsz + 7) >> 3; // size of meta-bitmap
+ TInt nbytes = 0;
+ TInt i;
+ for (i=0; i<memsz; ++i)
+ if (iExportBitMap[i] != 0xff)
+ ++nbytes; // number of groups of 8
+ TUint8 edt = KImageHdr_ExpD_FullBitmap;
+ TInt extra_space = memsz - 1;
+ if (mbs + nbytes < memsz)
+ {
+ edt = KImageHdr_ExpD_SparseBitmap8;
+ extra_space = mbs + nbytes - 1;
+ }
+ extra_space = (extra_space + sizeof(TUint) - 1) &~ (sizeof(TUint) - 1);
+ TInt hdrsz = sizeof(E32ImageHeaderV) + extra_space;
+ iHdr = (E32ImageHeaderV*)malloc(hdrsz);
+ memcpy(iHdr, iOrigHdr, sizeof(E32ImageHeaderV));
+ iHdr->iExportDescType = edt;
+ if (edt == KImageHdr_ExpD_FullBitmap)
+ {
+ iHdr->iExportDescSize = (TUint16)memsz;
+ memcpy(iHdr->iExportDesc, iExportBitMap, memsz);
+ }
+ else
+ {
+ iHdr->iExportDescSize = (TUint16)(mbs + nbytes);
+ memset(iHdr->iExportDesc, 0, extra_space + 1);
+ TUint8* mptr = iHdr->iExportDesc;
+ TUint8* gptr = mptr + mbs;
+ for (i=0; i<memsz; ++i)
+ {
+ if (iExportBitMap[i] != 0xff)
+ {
+ mptr[i>>3] |= (1u << (i&7));
+ *gptr++ = iExportBitMap[i];
+ }
+ }
+ }
+ iHdr->iCodeOffset += extra_space;
+ if (iHdr->iDataOffset)
+ iHdr->iDataOffset += extra_space;
+ if (iHdr->iCodeRelocOffset)
+ iHdr->iCodeRelocOffset += extra_space;
+ if (iHdr->iDataRelocOffset)
+ iHdr->iDataRelocOffset += extra_space;
+ if (iHdr->iImportOffset)
+ iHdr->iImportOffset += extra_space;
+ if (iHdr->iExportDirOffset)
+ iHdr->iExportDirOffset += extra_space;
+ }
+
+// Check the export description is consistent with the export directory
+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;
+ }
+
+
+TInt E32ImageFile::Validate()
+ {
+ TInt orighdrsz = iOrigHdr->TotalSize();
+ TInt r = iHdr->ValidateWholeImage(iData+orighdrsz,iSize-orighdrsz);
+ if(r!=KErrNone)
+ return r;
+ return r;
+ }
+
+
+ostream& operator<<(ostream& os, const E32ImageFile& aImage)
+//
+// Output an E32ImageFile
+//
+ {
+ E32ImageHeaderV* h = aImage.iHdr;
+ TUint hdrfmt = h->HeaderFormat();
+ if (hdrfmt != KImageHdrFmt_V)
+ return os; // don't generate old binary formats
+ TInt hdrsz = h->TotalSize();
+ TInt orighdrsz = aImage.iOrigHdr->TotalSize();
+
+ os.write((const char*)aImage.iHdr, hdrsz);
+
+ TUint compression = h->CompressionType();
+ if (compression == KUidCompressionDeflate)
+ {
+ int srcsize = aImage.iSize - orighdrsz;
+ DeflateCompress(aImage.iData + orighdrsz, srcsize, os);
+ }
+ else if (compression == KUidCompressionBytePair)
+ {
+ // Compress and write out code part
+ int srcStart = orighdrsz;
+ CompressPages( (TUint8*)aImage.iData + srcStart, aImage.iOrigHdr->iCodeSize, os, aImage.iBPE);
+
+
+ // Compress and write out data part
+ srcStart += aImage.iOrigHdr->iCodeSize;
+ int srcLen = aImage.iSize - srcStart;
+
+ CompressPages((TUint8*)aImage.iData + srcStart, srcLen, os, aImage.iBPE);
+
+ }
+ else if (compression == KFormatNotCompressed)
+ {
+ int srcsize = aImage.iSize - orighdrsz;
+ os.write(aImage.iData + orighdrsz, srcsize); // image not to be compressed
+ }
+ return os;
+ }
+
+ifstream& operator>>(ifstream& is, E32ImageFile& aImage)
+//
+// Input an E32ImageFile
+//
+ {
+ 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)
+ Print(EWarning, "Inconsistent sizes discovered during uncompression.\n");
+ 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, aImage.iBPE);
+
+
+ // Read and decompress data part of the image
+
+ unsigned int uncompressedDataSize = DecompressPages((TUint8 *) (aImage.iData + orighdrsz + uncompressedCodeSize), is, aImage.iBPE);
+
+ if (uncompressedCodeSize + uncompressedDataSize != uncompsize)
+ Print(EWarning, "Inconsistent sizes discovered during uncompression.\n");
+
+ 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.CreateExportBitMap();
+ return is;
+ }
+
+TInt E32ImageFile::IsE32ImageFile(const char *aFileName) {
+
+ ifstream ifile(aFileName, IOS_BASE::in | IOS_BASE::binary);
+ if(!ifile.is_open())
+ return FALSE;
+ E32ImageFile f;
+ ifile.seekg(0,IOS_BASE::end);
+ f.iFileSize = ifile.tellg();
+ ifile.seekg(0,IOS_BASE::beg);
+ TInt r = f.ReadHeader(ifile);
+ ifile.close();
+ return (r == KErrNone);
+}
+
+
+//
+// Open an E32 Image file
+//
+TInt E32ImageFile::Open(const char* aFileName) {
+ ifstream ifile(aFileName, IOS_BASE::in | IOS_BASE::binary);
+ if(!ifile.is_open()) {
+ Print(EError,"Cannot open %s for input.\n",aFileName);
+ return 1;
+ }
+ ifile.seekg(0,IOS_BASE::end);
+ iFileSize = ifile.tellg();
+ ifile.seekg(0,IOS_BASE::beg);
+ Adjust(iFileSize);
+ ifile >> *this;
+ ifile.close();
+ if (iError != KErrNone)
+ return iError;
+ size_t len = strlen(aFileName) + 1;
+ iFileName = new char[len] ;
+ memcpy(iFileName ,aFileName,len);
+ return KErrNone;
+}
+
+#ifndef __LINUX__
+TInt E32ImageFile::Open(const wchar_t* aFileName)
+//
+// Open an E32 Image file
+//
+ {
+ _wfinddata_t fileinfo;
+ int ret=_wfindfirst((wchar_t*)aFileName,&fileinfo);
+ if (ret==-1)
+ {
+ Print(EError,"Cannot open %ls for input.\n",aFileName);
+ return 1;
+ }
+ iFileSize = fileinfo.size;
+ Adjust(iFileSize);
+
+ FILE* file = _wfopen(aFileName, L"rb");
+
+ if(!file)
+ {
+ Print(EError,"Cannot open %ls for input.\n",aFileName);
+ return 1;
+ }
+
+ #if defined(__TOOLS2__) || defined(__MSVCDOTNET__)
+ char tmp[100]; // Convert wide character name to char *, then open a file.
+ wcstombs(tmp,aFileName,100);
+ ifstream ifile(tmp, ios::in | ios::binary);
+ #else
+ ifstream ifile(fileno(file));
+ #endif
+
+ if(!ifile.is_open())
+ {
+ Print(EError,"Cannot open %ls for input,\n",aFileName);
+ return 1;
+ }
+
+ ifile >> *this;
+ ifile.close();
+ fclose(file);
+ if (iError != KErrNone)
+ return iError;
+ iWideFileName=wcsdup(aFileName);
+ if (iWideFileName==NULL)
+ return KErrNoMemory;
+ return KErrNone;
+ }
+#endif
+
+TUint E32ImageFile::VaOfOrdinal(TUint aOrdinal){
+// return the offset of the exported symbol
+
+ TUint* exportdir = (TUint*)(iData + iOrigHdr->iExportDirOffset);
+ return exportdir[aOrdinal-KOrdinalBase];
+}
+
+// Determine the type of entry point in this module and set the flags
+// in the E32Image header accordingly.
+TInt E32ImageFile::DetermineEntryPointType()
+ {
+ TUint cpu = iHdr->CpuIdentifier();
+ if (cpu != ECpuArmV4 && cpu != ECpuArmV5)
+ return KErrNone; // if not ARM, leave EPT as 0
+ TUint epOffset = iHdr->iEntryPoint;
+ if (epOffset & 3)
+ return KErrNone; // if entry point not 4 byte aligned, must be old style
+ TUint fileOffset = epOffset + iHdr->iCodeOffset;
+ if (fileOffset+4 > (TUint)iSize)
+ return KErrCorrupt; // entry point is past the end of the file??
+ TInt ept = 0; // old style if first instruction not recognised
+ unsigned char* p = (unsigned char*)iData + fileOffset + 4;
+ TUint32 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 KErrNotSupported;
+ iHdr->iFlags |= (ept<<KImageEptShift);
+ return KErrNone;
+ }
+