toolsandutils/e32tools/e32image/e32image.cpp
changeset 0 83f4b4db085c
child 10 d4b442d23379
equal deleted inserted replaced
-1:000000000000 0:83f4b4db085c
       
     1 // Copyright (c) 1996-2009 Nokia Corporation and/or its subsidiary(-ies).
       
     2 // All rights reserved.
       
     3 // This component and the accompanying materials are made available
       
     4 // under the terms of "Eclipse Public License v1.0"
       
     5 // which accompanies this distribution, and is available
       
     6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     7 //
       
     8 // Initial Contributors:
       
     9 // Nokia Corporation - initial contribution.
       
    10 //
       
    11 // Contributors:
       
    12 //
       
    13 // Description:
       
    14 // e32tools/e32image/e32image.cpp
       
    15 // Basic operations on E32Image files which are used by ROMBUILD.
       
    16 // These are independent of the original file format from which the
       
    17 // E32Image file was derived.
       
    18 // 
       
    19 //
       
    20 
       
    21 #include <time.h>
       
    22 #include <malloc.h>
       
    23 #include <string.h>
       
    24 #include <stdlib.h>
       
    25 #include "h_utl.h"
       
    26 
       
    27 
       
    28 #if defined (__MSVCDOTNET__) || defined(__TOOLS2__)
       
    29 #include <fstream>
       
    30 #else //!__MSVCDOTNET__
       
    31 #include <fstream.h>
       
    32 #endif //__MSVCDOTNET__
       
    33 
       
    34 #include <assert.h>
       
    35 #ifndef __LINUX__
       
    36   #include <io.h>
       
    37 #endif
       
    38 #include "h_ver.h"
       
    39 
       
    40 // get E32ImageHeader class...
       
    41 #define INCLUDE_E32IMAGEHEADER_IMPLEMENTATION
       
    42 #define RETURN_FAILURE(_r) return (fprintf(stderr, "line %d\n", __LINE__),_r)
       
    43 //#define E32IMAGEHEADER_TRACE(_t) printf _t
       
    44 #include "e32image.h"
       
    45 
       
    46 void DeflateCompress(char* bytes, TInt size, ostream& os);
       
    47 void InflateUnCompress(unsigned char* source, int sourcesize, unsigned char* dest, int destsize);
       
    48 void CompressPages(TUint8 * bytes, TInt size, ostream &os, CBytePair *aBPE);
       
    49 int  DecompressPages(TUint8 * bytes, istream& is, CBytePair *aBPE);
       
    50 
       
    51 // needed by E32ImageHeaderV::ValidateHeader...
       
    52 void Mem::Crc32(TUint32& aCrc, const TAny* aPtr, TInt aLength)
       
    53 	{
       
    54 	HMem::Crc32(aCrc, aPtr, aLength);
       
    55 	}
       
    56 
       
    57 //
       
    58 // E32 Image files
       
    59 //
       
    60 E32ImageFile::E32ImageFile(CBytePair *aBPE)
       
    61 	: iData(NULL), iSize(0), iOrigHdr(NULL), iHdr(NULL), iFileName(NULL)
       
    62 #ifndef __LINUX__
       
    63 	  , iWideFileName(NULL)
       
    64 #endif
       
    65 , iError(0), iSource(EE32Image), iOrigHdrOffsetAdj(0), iExportBitMap(0), iBPE(aBPE)
       
    66 	{
       
    67             if(aBPE == NULL) { 
       
    68                 iOwnBPE = 1;
       
    69                 iBPE = new CBytePair(EFalse);
       
    70             }
       
    71             else {
       
    72                 iOwnBPE = 0;
       
    73                 iBPE = aBPE;
       
    74             }
       
    75         }
       
    76 
       
    77 E32ImageFile::~E32ImageFile()
       
    78 	{
       
    79             if(iOwnBPE == 1) {
       
    80                 delete iBPE;
       
    81             }
       
    82 
       
    83 	free(iData);
       
    84 	delete [] iFileName;
       
    85 #ifndef __LINUX__
       
    86 	delete [] iWideFileName;
       
    87 #endif
       
    88 	if (iHdr && iHdr != iOrigHdr)
       
    89 		delete iHdr;
       
    90 	free(iExportBitMap);
       
    91 	}
       
    92 
       
    93 // dummy implementation
       
    94 TBool E32ImageFile::Translate(const char*, TUint, TBool, TBool)
       
    95 	{
       
    96 	return EFalse;
       
    97 	}
       
    98 
       
    99 Int64 timeToInt64(TInt aTime)
       
   100 	{
       
   101 	aTime-=(30*365*24*60*60+7*24*60*60);	// seconds since midnight Jan 1st, 2000
       
   102 	Int64 daysTo2000AD=730497;
       
   103 	Int64 t=daysTo2000AD*24*3600+aTime;	// seconds since 0000
       
   104 	t=t+3600;								// BST (?)
       
   105 	return t*1000000;						// milliseconds
       
   106 	}
       
   107 
       
   108 class TE32ImageUids : public TCheckedUid
       
   109 	{
       
   110 public:
       
   111 	TE32ImageUids(TUint32 aUid1, TUint32 aUid2, TUint32 aUid3) : TCheckedUid(TUidType(TUid::Uid(aUid1), TUid::Uid(aUid2), TUid::Uid(aUid3))) {}
       
   112 	TUint Check() { return TCheckedUid::Check(); }
       
   113 	};
       
   114 
       
   115 void E32ImageFile::SetDefaultHeader()
       
   116 	{
       
   117 	iHdr = (E32ImageHeaderV*)iOrigHdr;
       
   118 	iHdr->iUid1 = 0;
       
   119 	iHdr->iUid2 = 0;
       
   120 	iHdr->iUid3 = 0;
       
   121 	iHdr->iHeaderCrc = 0;
       
   122 	iHdr->iSignature = 0x434f5045u;
       
   123 	iHdr->iModuleVersion = 0x00010000u;
       
   124 	iHdr->iCompressionType = 0;
       
   125 	iHdr->iToolsVersion = TVersion(MajorVersion, MinorVersion, Build);
       
   126 	Int64 time1(timeToInt64(time(0))); 
       
   127 	iHdr->iTimeLo=(TUint32)time1;
       
   128 	iHdr->iTimeHi=(TUint32)(time1>>32);
       
   129 	iHdr->iFlags = KImageHdrFmt_V;
       
   130 	iHdr->iCodeSize = 0;
       
   131 	iHdr->iDataSize = 0;
       
   132 	iHdr->iHeapSizeMin = 0;
       
   133 	iHdr->iHeapSizeMax = 0;
       
   134 	iHdr->iStackSize = 0;
       
   135 	iHdr->iBssSize = 0;
       
   136 	iHdr->iEntryPoint = 0;
       
   137 	iHdr->iCodeBase = 0;
       
   138 	iHdr->iDataBase = 0;
       
   139 	iHdr->iDllRefTableCount = 0;
       
   140 	iHdr->iExportDirOffset = 0;
       
   141 	iHdr->iExportDirCount = 0;
       
   142 	iHdr->iTextSize = 0;
       
   143 	iHdr->iCodeOffset = 0;
       
   144 	iHdr->iDataOffset = 0;
       
   145 	iHdr->iImportOffset = 0;
       
   146 	iHdr->iCodeRelocOffset = 0;
       
   147 	iHdr->iDataRelocOffset = 0;
       
   148 	iHdr->iProcessPriority = (TUint16)EPriorityForeground;
       
   149 	iHdr->iUncompressedSize = 0;
       
   150 	iHdr->iS.iSecureId = 0;
       
   151 	iHdr->iS.iVendorId = 0;
       
   152 	iHdr->iExceptionDescriptor = 0;
       
   153 	iHdr->iSpare2 = 0;
       
   154 
       
   155 	iHdr->iExportDescSize = 0;
       
   156 	iHdr->iExportDescType = KImageHdr_ExpD_NoHoles;
       
   157 	iHdr->iExportDesc[0] = 0;
       
   158 	}
       
   159 
       
   160 void E32ImageFile::SetCallEntryPoints(TInt aBool)
       
   161 	{
       
   162 
       
   163 	if (aBool)
       
   164 		iHdr->iFlags&=~KImageNoCallEntryPoint;
       
   165 	else
       
   166 		iHdr->iFlags|=KImageNoCallEntryPoint;
       
   167 	}
       
   168 
       
   169 void E32ImageFile::SetFixedAddress(TInt aBool)
       
   170 	{
       
   171 
       
   172 	if (aBool)
       
   173 		iHdr->iFlags|=KImageFixedAddressExe;
       
   174 	else
       
   175 		iHdr->iFlags&=~KImageFixedAddressExe;
       
   176 	}
       
   177 
       
   178 void E32ImageFile::SetPriority(TProcessPriority aPri)
       
   179 	{
       
   180 
       
   181 	iHdr->iProcessPriority = (TUint16)aPri;
       
   182 	}
       
   183 
       
   184 void E32ImageFile::SetCapability(SCapabilitySet& aCapabilities)
       
   185 	{
       
   186 	iHdr->iS.iCaps = aCapabilities;
       
   187 	}
       
   188 
       
   189 void E32ImageFile::SetFPU(unsigned int aFPU)
       
   190 	{
       
   191 	iHdr->iFlags &=~ KImageHWFloatMask;
       
   192 
       
   193 	if (aFPU == 1)
       
   194 		iHdr->iFlags |= KImageHWFloat_VFPv2;
       
   195 	}
       
   196 
       
   197 void E32ImageFile::Adjust(TInt aSize, TBool aAllowShrink)
       
   198 //
       
   199 // Adjust the size of allocated data and fix the member data
       
   200 //
       
   201 	{
       
   202 
       
   203 	TInt asize = ALIGN4(aSize);
       
   204 	if (asize == iSize)
       
   205 		return;
       
   206 	if (iSize == 0)
       
   207 		{
       
   208 		iSize = asize;
       
   209 		iData = (char*)malloc(iSize);
       
   210 		memset(iData, 0, iSize);
       
   211 		}
       
   212 	else if (aAllowShrink || asize > iSize)
       
   213 		{
       
   214 		TInt oldsize = iSize;
       
   215 		iSize = asize;
       
   216 		iData = (char*)realloc(iData, iSize);
       
   217 		if (iSize > oldsize)
       
   218 			memset(iData+oldsize, 0, iSize-oldsize);
       
   219 		}
       
   220 	if (!iData)
       
   221 		iSize = 0;
       
   222 	if (iHdr && iHdr == iOrigHdr)
       
   223 		iHdr = (E32ImageHeaderV*)iData;
       
   224 	iOrigHdr = (E32ImageHeader*)iData;
       
   225 	}
       
   226 
       
   227 TInt E32ImageFile::ReadHeader(ifstream& is)
       
   228 	{
       
   229 	Adjust(sizeof(E32ImageHeader), EFalse);
       
   230 	is.read(iData, sizeof(E32ImageHeader));
       
   231 	TInt hdrsz = iOrigHdr->TotalSize();
       
   232 	if (hdrsz > 0x10000 || hdrsz <= 0)
       
   233 		return KErrCorrupt;	// sanity check
       
   234 	if (hdrsz > (TInt)sizeof(E32ImageHeader))
       
   235 		{
       
   236 		Adjust(hdrsz, EFalse);
       
   237 		is.read(iData+sizeof(E32ImageHeader), hdrsz-sizeof(E32ImageHeader));
       
   238 		}
       
   239 	TUint32 uncompressedSize;
       
   240 	TInt r = iOrigHdr->ValidateHeader(iFileSize,uncompressedSize);
       
   241 	if (r != KErrNone)
       
   242 		{
       
   243 		fprintf(stderr, "Integrity check failed %d\n", r);
       
   244 		return r;
       
   245 		}
       
   246 	iHdr = (E32ImageHeaderV*)iOrigHdr;
       
   247 	return KErrNone;
       
   248 	}
       
   249 
       
   250 void E32ImageFile::SetStackSize(TInt aSize)
       
   251 	{
       
   252 	iHdr->iStackSize=aSize;
       
   253 	}
       
   254 
       
   255 void E32ImageFile::SetHeapSizeMin(TInt aSize)
       
   256 	{
       
   257 	iHdr->iHeapSizeMin=aSize;
       
   258 	}
       
   259 
       
   260 void E32ImageFile::SetHeapSizeMax(TInt aSize)
       
   261 	{
       
   262 	iHdr->iHeapSizeMax=aSize;
       
   263 	}
       
   264 
       
   265 TUint E32ImageFile::TextOffset()
       
   266 //
       
   267 // Return the offset of the text section
       
   268 //
       
   269 	{
       
   270 	return 0;
       
   271 	}
       
   272 
       
   273 TUint E32ImageFile::DataOffset()
       
   274 //
       
   275 // return the offset of the initialised data
       
   276 //
       
   277 	{
       
   278 	return iHdr->iCodeSize;
       
   279 	}
       
   280 
       
   281 TUint E32ImageFile::BssOffset()
       
   282 //
       
   283 // return the offset from the start of code where the bss is linked
       
   284 //
       
   285 	{
       
   286 	return DataOffset()+iHdr->iDataSize;
       
   287 	}
       
   288 
       
   289 
       
   290 TInt E32ImageFile::IsDll()
       
   291 //
       
   292 //
       
   293 //
       
   294 	{
       
   295 	return iHdr->iFlags&KImageDll;
       
   296 	}
       
   297 
       
   298 
       
   299 void E32ImageFile::RelocateSection(char* aPtr, char* aRelocs, TUint aCodeDelta, TUint aDataDelta, char* aImagePtr, TLinAddr** aIATRefs, TBool keepIAT)
       
   300 //
       
   301 // Relocates the section data at aPtr
       
   302 //	
       
   303 	{
       
   304 
       
   305 	TUint codeStart=iHdr->iCodeBase;
       
   306 	TUint codeFinish=codeStart+iHdr->iCodeSize;
       
   307 	TUint iatStart = aIATRefs ? codeStart+iHdr->iTextSize : 0;
       
   308 	TUint iatFinish = aIATRefs ? iatStart+NumberOfImports()*sizeof(TUint) : 0;
       
   309 	char* relocs=aRelocs;
       
   310 	TUint page=0;
       
   311 	TInt size=0;
       
   312 	TInt i=((E32RelocSection *)relocs)->iNumberOfRelocs;
       
   313 	relocs+=sizeof(E32RelocSection);
       
   314 	while (i>0)
       
   315 		{
       
   316 		if (size>0)
       
   317 			{
       
   318 			TUint offset=*(TUint16 *)relocs;
       
   319 			relocs+=2;
       
   320 			if (offset!=0)
       
   321 				{ // its a reloc
       
   322 				TUint va=page+(offset&0x0fff);
       
   323 				TUint relocType=offset&0xf000;
       
   324 				TUint *dataptr=(TUint *)(aPtr+va);
       
   325 				assert((char *)dataptr < aRelocs);
       
   326 				TUint data=*dataptr;
       
   327 				if (relocType == KTextRelocType) 
       
   328 					*dataptr=data+aCodeDelta; // points to text/rdata section
       
   329 				else if (relocType == KDataRelocType)
       
   330 					*dataptr=data+aDataDelta;
       
   331 				else 
       
   332 					{
       
   333 					if (relocType != KInferredRelocType)
       
   334 						Print(EError,"Unrecognized relocation type %x\n",relocType);
       
   335 
       
   336 					if (data>=iatStart && data<iatFinish)
       
   337 						{
       
   338 
       
   339 						TUint iatNum = (data-iatStart)/sizeof(TLinAddr);
       
   340 
       
   341 						// If "keepIAT" is used then the importing instruction must import through the IAT entry,
       
   342 						// but otherwise we change the IAT entry to point to the bit of code doing the importing
       
   343 						// and do the real fix-up later on in TRomBuilderEntry::FixupImports.
       
   344 						// NB: We always want to do this for X86 or data exports dont work.
       
   345 						if (keepIAT || (iHdr->iCpuIdentifier & 0x1000) /*denotes X86*/) 
       
   346 							*dataptr=data+aCodeDelta; 
       
   347 						else 
       
   348 							{
       
   349 							if ((TUint)aIATRefs[iatNum]>65535)
       
   350 								Print(EWarning, "Multiple relocations for IAT entry %d (0x%x, 0x%x)\n",
       
   351 										iatNum, aIATRefs[iatNum], dataptr);
       
   352 							else
       
   353 								aIATRefs[iatNum] = (TLinAddr*)(aImagePtr+va);	// ROM image address of importing pointer					
       
   354 							}
       
   355 						}
       
   356 					else if (data>=codeStart && data<codeFinish)
       
   357 						*dataptr=data+aCodeDelta; // points to text/rdata section
       
   358 					else
       
   359 						*dataptr=data+aDataDelta; // points to data section
       
   360 					}
       
   361 				--i;
       
   362 				}
       
   363 			size-=2;
       
   364 			}
       
   365 		else
       
   366 			{ // next page of relocs
       
   367 			page=*(TUint *)relocs;
       
   368 			relocs+=4;
       
   369 			size=*(TUint *)relocs;
       
   370 			relocs+=4;
       
   371 			size-=8;
       
   372 			}
       
   373 		}
       
   374 	}
       
   375 
       
   376 void E32ImageFile::SetUids(TUid aUid1, TUid aUid2, TUid aUid3)
       
   377 	{
       
   378 	iHdr->iUid1=aUid1.iUid;
       
   379 	iHdr->iUid2=aUid2.iUid;
       
   380 	iHdr->iUid3=aUid3.iUid;
       
   381 	}
       
   382 
       
   383 void E32ImageFile::SetSecureId(TUint32 aId)
       
   384 	{
       
   385 	((E32ImageHeaderV*)iHdr)->iS.iSecureId = aId;
       
   386 	}
       
   387 
       
   388 void E32ImageFile::SetVendorId(TUint32 aId)
       
   389 	{
       
   390 	((E32ImageHeaderV*)iHdr)->iS.iVendorId = aId;
       
   391 	}
       
   392 
       
   393 void E32ImageFile::UpdateHeaderCrc()
       
   394 	{
       
   395 	TE32ImageUids u(iHdr->iUid1, iHdr->iUid2, iHdr->iUid3);
       
   396 	iHdr->iUidChecksum = u.Check();
       
   397 	TInt hdrsz = iHdr->TotalSize();
       
   398 	TInt orighdrsz = iOrigHdr->TotalSize();
       
   399 	iHdr->iUncompressedSize = iSize - orighdrsz;
       
   400 	iHdr->iHeaderCrc = KImageCrcInitialiser;
       
   401 	TUint32 crc = 0;
       
   402 	HMem::Crc32(crc, iHdr, hdrsz);
       
   403 	iHdr->iHeaderCrc = crc;
       
   404 	}
       
   405 
       
   406 TInt E32ImageFile::NumberOfImports()
       
   407 //
       
   408 // Return the number of imports made by this image
       
   409 //
       
   410 	{
       
   411 
       
   412 	if (iHdr->iDllRefTableCount==0 || iHdr->iImportOffset==0)
       
   413 		return 0;
       
   414 
       
   415 	TUint impfmt = iHdr->ImportFormat();
       
   416 	const E32ImportSection* isection = (const E32ImportSection*)(iData + iOrigHdr->iImportOffset);
       
   417 	TInt d;
       
   418 	TInt nImports = 0;
       
   419 	const E32ImportBlock* b = (const E32ImportBlock*)(isection+1);
       
   420 	for (d=0; d<iHdr->iDllRefTableCount; d++)
       
   421 		{
       
   422 		nImports += b->iNumberOfImports;
       
   423 		b = b->NextBlock(impfmt);
       
   424 		}
       
   425 
       
   426 	if (impfmt==KImageImpFmt_PE || impfmt==KImageImpFmt_PE2)
       
   427 		{
       
   428 		TUint *imports=(TUint *)(iData + iOrigHdr->iCodeOffset + iHdr->iTextSize);
       
   429 		TInt i=0;
       
   430 		while (*imports++)
       
   431 			i++;
       
   432 		assert(i==nImports);
       
   433 		}
       
   434 	
       
   435 	return nImports;
       
   436 	}
       
   437 
       
   438 // Work out which exports are missing from the export directory
       
   439 void E32ImageFile::CreateExportBitMap()
       
   440 	{
       
   441 	TInt nexp = iOrigHdr->iExportDirCount;
       
   442 	TInt memsz = (nexp + 7) >> 3;
       
   443 	iExportBitMap = (TUint8*)malloc(memsz);
       
   444 	memset(iExportBitMap, 0xff, memsz);
       
   445 	TUint* exports = (TUint*)(iData + iOrigHdr->iExportDirOffset);
       
   446 	TUint absoluteEntryPoint = iOrigHdr->iEntryPoint + iOrigHdr->iCodeBase;
       
   447 	TUint impfmt = iOrigHdr->ImportFormat();
       
   448 	TUint hdrfmt = iOrigHdr->HeaderFormat();
       
   449 	TUint absentVal = (impfmt == KImageImpFmt_ELF) ? absoluteEntryPoint : iOrigHdr->iEntryPoint;
       
   450 	TInt i;
       
   451 	iMissingExports = 0;
       
   452 	for (i=0; i<nexp; ++i)
       
   453 		{
       
   454 		if (exports[i] == absentVal)
       
   455 			{
       
   456 			iExportBitMap[i>>3] &= ~(1u << (i & 7));
       
   457 			++iMissingExports;
       
   458 			}
       
   459 		}
       
   460 	if (hdrfmt < KImageHdrFmt_V && iMissingExports)
       
   461 		{
       
   462 		fprintf(stderr, "Bad exports\n");
       
   463 		exit(999);
       
   464 		}
       
   465 	}
       
   466 
       
   467 // Append an export description to the E32ImageHeader if necessary
       
   468 void E32ImageFile::AddExportDescription()
       
   469 	{
       
   470 	if (iMissingExports == 0)
       
   471 		return;	// nothing to do
       
   472 	TInt nexp = iOrigHdr->iExportDirCount;
       
   473 	TInt memsz = (nexp + 7) >> 3;	// size of complete bitmap
       
   474 	TInt mbs = (memsz + 7) >> 3;	// size of meta-bitmap
       
   475 	TInt nbytes = 0;
       
   476 	TInt i;
       
   477 	for (i=0; i<memsz; ++i)
       
   478 		if (iExportBitMap[i] != 0xff)
       
   479 			++nbytes;				// number of groups of 8
       
   480 	TUint8 edt = KImageHdr_ExpD_FullBitmap;
       
   481 	TInt extra_space = memsz - 1;
       
   482 	if (mbs + nbytes < memsz)
       
   483 		{
       
   484 		edt = KImageHdr_ExpD_SparseBitmap8;
       
   485 		extra_space = mbs + nbytes - 1;
       
   486 		}
       
   487 	extra_space = (extra_space + sizeof(TUint) - 1) &~ (sizeof(TUint) - 1);
       
   488 	TInt hdrsz = sizeof(E32ImageHeaderV) + extra_space;
       
   489 	iHdr = (E32ImageHeaderV*)malloc(hdrsz);
       
   490 	memcpy(iHdr, iOrigHdr, sizeof(E32ImageHeaderV));
       
   491 	iHdr->iExportDescType = edt;
       
   492 	if (edt == KImageHdr_ExpD_FullBitmap)
       
   493 		{
       
   494 		iHdr->iExportDescSize = (TUint16)memsz;
       
   495 		memcpy(iHdr->iExportDesc, iExportBitMap, memsz);
       
   496 		}
       
   497 	else
       
   498 		{
       
   499 		iHdr->iExportDescSize = (TUint16)(mbs + nbytes);
       
   500 		memset(iHdr->iExportDesc, 0, extra_space + 1);
       
   501 		TUint8* mptr = iHdr->iExportDesc;
       
   502 		TUint8* gptr = mptr + mbs;
       
   503 		for (i=0; i<memsz; ++i)
       
   504 			{
       
   505 			if (iExportBitMap[i] != 0xff)
       
   506 				{
       
   507 				mptr[i>>3] |= (1u << (i&7));
       
   508 				*gptr++ = iExportBitMap[i];
       
   509 				}
       
   510 			}
       
   511 		}
       
   512 	iHdr->iCodeOffset += extra_space;
       
   513 	if (iHdr->iDataOffset)
       
   514 		iHdr->iDataOffset += extra_space;
       
   515 	if (iHdr->iCodeRelocOffset)
       
   516 		iHdr->iCodeRelocOffset += extra_space;
       
   517 	if (iHdr->iDataRelocOffset)
       
   518 		iHdr->iDataRelocOffset += extra_space;
       
   519 	if (iHdr->iImportOffset)
       
   520 		iHdr->iImportOffset += extra_space;
       
   521 	if (iHdr->iExportDirOffset)
       
   522 		iHdr->iExportDirOffset += extra_space;
       
   523 	}
       
   524 
       
   525 // Check the export description is consistent with the export directory
       
   526 TInt E32ImageFile::CheckExportDescription()
       
   527 	{
       
   528 	TUint hdrfmt = iOrigHdr->HeaderFormat();
       
   529 	if (hdrfmt < KImageHdrFmt_V && iMissingExports)
       
   530 		return KErrCorrupt;
       
   531 	if (iHdr->iExportDescType == KImageHdr_ExpD_NoHoles)
       
   532 		{
       
   533 		return iMissingExports ? KErrCorrupt : KErrNone;
       
   534 		}
       
   535 	TInt nexp = iOrigHdr->iExportDirCount;
       
   536 	TInt memsz = (nexp + 7) >> 3;	// size of complete bitmap
       
   537 	TInt mbs = (memsz + 7) >> 3;	// size of meta-bitmap
       
   538 	TInt eds = iHdr->iExportDescSize;
       
   539 	if (iHdr->iExportDescType == KImageHdr_ExpD_FullBitmap)
       
   540 		{
       
   541 		if (eds != memsz)
       
   542 			return KErrCorrupt;
       
   543 		if (memcmp(iHdr->iExportDesc, iExportBitMap, eds) == 0)
       
   544 			return KErrNone;
       
   545 		return KErrCorrupt;
       
   546 		}
       
   547 	if (iHdr->iExportDescType != KImageHdr_ExpD_SparseBitmap8)
       
   548 		return KErrNotSupported;
       
   549 	TInt nbytes = 0;
       
   550 	TInt i;
       
   551 	for (i=0; i<memsz; ++i)
       
   552 		if (iExportBitMap[i] != 0xff)
       
   553 			++nbytes;				// number of groups of 8
       
   554 	TInt exp_extra = mbs + nbytes;
       
   555 	if (eds != exp_extra)
       
   556 		return KErrCorrupt;
       
   557 	const TUint8* mptr = iHdr->iExportDesc;
       
   558 	const TUint8* gptr = mptr + mbs;
       
   559 	for (i=0; i<memsz; ++i)
       
   560 		{
       
   561 		TUint mbit = mptr[i>>3] & (1u << (i&7));
       
   562 		if (iExportBitMap[i] != 0xff)
       
   563 			{
       
   564 			if (!mbit || *gptr++ != iExportBitMap[i])
       
   565 				return KErrCorrupt;
       
   566 			}
       
   567 		else if (mbit)
       
   568 			return KErrCorrupt;
       
   569 		}
       
   570 	return KErrNone;
       
   571 	}
       
   572 
       
   573 
       
   574 TInt E32ImageFile::Validate()
       
   575 	{
       
   576 	TInt orighdrsz = iOrigHdr->TotalSize();
       
   577 	TInt r = iHdr->ValidateWholeImage(iData+orighdrsz,iSize-orighdrsz);
       
   578 	if(r!=KErrNone)
       
   579 		return r;
       
   580 	return r;
       
   581 	}
       
   582 
       
   583 
       
   584 ostream& operator<<(ostream& os, const E32ImageFile& aImage)
       
   585 //
       
   586 // Output an E32ImageFile
       
   587 //
       
   588 	{
       
   589 	E32ImageHeaderV* h = aImage.iHdr;
       
   590 	TUint hdrfmt = h->HeaderFormat();
       
   591 	if (hdrfmt != KImageHdrFmt_V)
       
   592 		return os;	// don't generate old binary formats
       
   593 	TInt hdrsz = h->TotalSize();
       
   594 	TInt orighdrsz = aImage.iOrigHdr->TotalSize();
       
   595 
       
   596 	os.write((const char*)aImage.iHdr, hdrsz);
       
   597 
       
   598 	TUint compression = h->CompressionType();
       
   599 	if (compression == KUidCompressionDeflate)
       
   600 		{
       
   601 		int srcsize = aImage.iSize - orighdrsz;
       
   602 		DeflateCompress(aImage.iData + orighdrsz, srcsize, os);
       
   603 		}
       
   604 	else if (compression == KUidCompressionBytePair)
       
   605 		{
       
   606 		// Compress and write out code part
       
   607 		int srcStart = orighdrsz;
       
   608 		CompressPages( (TUint8*)aImage.iData + srcStart, aImage.iOrigHdr->iCodeSize, os, aImage.iBPE);
       
   609 		
       
   610 		
       
   611 		// Compress and write out data part
       
   612 		srcStart += aImage.iOrigHdr->iCodeSize;
       
   613 		int srcLen = aImage.iSize - srcStart;
       
   614 
       
   615 		CompressPages((TUint8*)aImage.iData + srcStart, srcLen, os, aImage.iBPE);		
       
   616 
       
   617 		}
       
   618 	else if (compression == KFormatNotCompressed)
       
   619 		{
       
   620 		int srcsize = aImage.iSize - orighdrsz;
       
   621 		os.write(aImage.iData + orighdrsz, srcsize); // image not to be compressed
       
   622 		}
       
   623 	return os;
       
   624 	}
       
   625 
       
   626 ifstream& operator>>(ifstream& is, E32ImageFile& aImage)
       
   627 //
       
   628 // Input an E32ImageFile
       
   629 //
       
   630 	{
       
   631 	aImage.iError = aImage.ReadHeader(is);
       
   632 	if (aImage.iError != KErrNone)
       
   633 		return is;
       
   634 	E32ImageHeader* oh = aImage.iOrigHdr;
       
   635 	TInt orighdrsz = oh->TotalSize();
       
   636 	int remainder = aImage.iSize - orighdrsz;
       
   637 	TUint compression = oh->CompressionType();
       
   638 	if (compression == 0)
       
   639 		{
       
   640 		is.read(aImage.iData + orighdrsz, remainder);
       
   641 		}
       
   642 	else if (compression == KUidCompressionDeflate)
       
   643 		{ //Uncompress
       
   644 		aImage.iError = KErrNoMemory;
       
   645 		unsigned int uncompsize = ((E32ImageHeaderComp*)aImage.iOrigHdr)->iUncompressedSize;
       
   646 		aImage.Adjust(uncompsize + orighdrsz);
       
   647 		if (aImage.iData==NULL)
       
   648 			return is;
       
   649 		oh = aImage.iOrigHdr;
       
   650 		unsigned char* compressedData = new unsigned char[remainder];
       
   651 		if (compressedData==NULL)
       
   652 			return is;
       
   653 		is.read(reinterpret_cast<char *>(compressedData), remainder);
       
   654 		unsigned int destsize = uncompsize;
       
   655 		InflateUnCompress( compressedData, remainder, (unsigned char*)(aImage.iData + orighdrsz), destsize);
       
   656 		if (destsize != uncompsize)
       
   657 			Print(EWarning, "Inconsistent sizes discovered during uncompression.\n");
       
   658 		delete [] compressedData;
       
   659 		if ((TUint)orighdrsz > oh->iCodeOffset)
       
   660 			{
       
   661 			// need to adjust code offsets in original
       
   662 			aImage.iOrigHdrOffsetAdj = (TUint)orighdrsz - oh->iCodeOffset;
       
   663 			aImage.OffsetAdjust(oh->iCodeOffset);
       
   664 			aImage.OffsetAdjust(oh->iDataOffset);
       
   665 			aImage.OffsetAdjust(oh->iCodeRelocOffset);
       
   666 			aImage.OffsetAdjust(oh->iDataRelocOffset);
       
   667 			aImage.OffsetAdjust(oh->iImportOffset);
       
   668 			aImage.OffsetAdjust(oh->iExportDirOffset);
       
   669 			}
       
   670 		aImage.iError = KErrNone;
       
   671 		}
       
   672 	else if(compression == KUidCompressionBytePair)
       
   673 	{ // Uncompress
       
   674 		aImage.iError = KErrNoMemory;
       
   675 		unsigned int uncompsize = ((E32ImageHeaderComp*)aImage.iOrigHdr)->iUncompressedSize;
       
   676 		aImage.Adjust(uncompsize + orighdrsz);
       
   677 		if (aImage.iData==NULL)
       
   678 			return is;
       
   679 		oh = aImage.iOrigHdr;
       
   680 
       
   681 		// Read and decompress code part of the image
       
   682 
       
   683 		unsigned int uncompressedCodeSize = DecompressPages((TUint8 *) (aImage.iData + orighdrsz), is, aImage.iBPE);
       
   684 
       
   685 		
       
   686 		// Read and decompress data part of the image
       
   687 
       
   688 		unsigned int uncompressedDataSize = DecompressPages((TUint8 *) (aImage.iData + orighdrsz + uncompressedCodeSize), is, aImage.iBPE);
       
   689 
       
   690 		if (uncompressedCodeSize + uncompressedDataSize != uncompsize)
       
   691 			Print(EWarning, "Inconsistent sizes discovered during uncompression.\n");
       
   692 
       
   693 		if ((TUint)orighdrsz > oh->iCodeOffset)
       
   694 			{
       
   695 			// need to adjust code offsets in original
       
   696 			aImage.iOrigHdrOffsetAdj = (TUint)orighdrsz - oh->iCodeOffset;
       
   697 			aImage.OffsetAdjust(oh->iCodeOffset);
       
   698 			aImage.OffsetAdjust(oh->iDataOffset);
       
   699 			aImage.OffsetAdjust(oh->iCodeRelocOffset);
       
   700 			aImage.OffsetAdjust(oh->iDataRelocOffset);
       
   701 			aImage.OffsetAdjust(oh->iImportOffset);
       
   702 			aImage.OffsetAdjust(oh->iExportDirOffset);
       
   703 			}
       
   704 		aImage.iError = KErrNone;
       
   705 	}
       
   706 	aImage.CreateExportBitMap();
       
   707 	return is;
       
   708 	}
       
   709 
       
   710 TInt E32ImageFile::IsE32ImageFile(char *aFileName)
       
   711 	{
       
   712 
       
   713 #ifdef __LINUX__
       
   714 	E32ImageFile f;
       
   715 	struct stat buf;
       
   716 	if (stat(aFileName, &buf) < 0) 
       
   717 		{
       
   718 		return FALSE;
       
   719 		}
       
   720 	f.iFileSize = buf.st_size;
       
   721 #else
       
   722 	_finddata_t fileinfo;
       
   723 	int ret=_findfirst((char *)aFileName,&fileinfo);
       
   724 	if (ret==-1) 
       
   725 		return FALSE;
       
   726 	E32ImageFile f;
       
   727 	f.iFileSize = fileinfo.size;
       
   728 #endif
       
   729 	ifstream ifile(aFileName, ios::in | ios::binary);
       
   730 	if(!ifile.is_open())
       
   731 		return FALSE;
       
   732 	TInt r = f.ReadHeader(ifile);
       
   733 	ifile.close();
       
   734 	return (r == KErrNone);
       
   735 	}
       
   736 
       
   737 TInt E32ImageFile::IsValid()
       
   738 	{
       
   739 	return (iError == KErrNone);
       
   740 	}
       
   741 
       
   742 TInt E32ImageFile::Open(const char* aFileName)
       
   743 //
       
   744 // Open an E32 Image file
       
   745 //
       
   746 	{
       
   747 #ifdef __LINUX__
       
   748 	struct stat buf;
       
   749 	if (stat(aFileName, &buf) < 0) 
       
   750 		{
       
   751 		Print(EError,"Cannot open %s for input.\n",aFileName);
       
   752 		return 1;
       
   753 		}
       
   754 	iFileSize = buf.st_size;
       
   755 #else
       
   756 	_finddata_t fileinfo;
       
   757 	int ret=_findfirst((char *)aFileName,&fileinfo);
       
   758 	if (ret==-1) 
       
   759 		{
       
   760 		Print(EError,"Cannot open %s for input.\n",aFileName);
       
   761 		return 1;
       
   762 		}
       
   763 	iFileSize = fileinfo.size;
       
   764 #endif
       
   765 	Adjust(iFileSize);
       
   766 	ifstream ifile((char *)aFileName, ios::in | ios::binary);
       
   767 	if(!ifile.is_open())
       
   768 		{
       
   769 		Print(EError,"Cannot open %s for input.\n",aFileName);
       
   770 		return 1;
       
   771 		}
       
   772 	ifile >> *this;
       
   773 	ifile.close();
       
   774 	if (iError != KErrNone)
       
   775 		return iError;
       
   776 	iFileName=strdup((char *)aFileName);
       
   777 	if (iFileName==NULL)
       
   778 		return KErrNoMemory;
       
   779 	return KErrNone;
       
   780 	}
       
   781 
       
   782 #ifndef __LINUX__
       
   783 TInt E32ImageFile::Open(const wchar_t* aFileName)
       
   784 //
       
   785 // Open an E32 Image file
       
   786 //
       
   787 	{
       
   788 	_wfinddata_t fileinfo;
       
   789 	int ret=_wfindfirst(aFileName,&fileinfo);
       
   790 	if (ret==-1) 
       
   791 		{
       
   792 		Print(EError,"Cannot open %ls for input.\n",aFileName);
       
   793 		return 1;
       
   794 		}
       
   795 	iFileSize = fileinfo.size;
       
   796 	Adjust(iFileSize);
       
   797 
       
   798 	FILE* file = _wfopen(aFileName, L"rb");
       
   799 
       
   800 	if(!file)
       
   801 		{
       
   802 		Print(EError,"Cannot open %ls for input.\n",aFileName);
       
   803 		return 1;
       
   804 		}
       
   805 	
       
   806 	#if defined(__TOOLS2__) || defined(__MSVCDOTNET__)
       
   807 	char tmp[100];  				// Convert wide character name to char *, then open a file.
       
   808 	wcstombs(tmp,aFileName,100);
       
   809 	ifstream ifile(tmp, ios::in | ios::binary);
       
   810 	#else
       
   811 	ifstream ifile(fileno(file));
       
   812 	#endif
       
   813 	
       
   814 	if(!ifile.is_open())
       
   815 		{
       
   816 		Print(EError,"Cannot open %ls for input,\n",aFileName);
       
   817 		return 1;
       
   818 		}
       
   819 		
       
   820 	ifile >> *this;
       
   821 	ifile.close();
       
   822 	fclose(file);
       
   823 	if (iError != KErrNone)
       
   824 		return iError;
       
   825 	iWideFileName=wcsdup(aFileName);
       
   826 	if (iWideFileName==NULL)
       
   827 		return KErrNoMemory;
       
   828 	return KErrNone;
       
   829 	}
       
   830 #endif
       
   831 
       
   832 TUint E32ImageFile::VaOfOrdinal(TUint aOrdinal)
       
   833 // return the offset of the exported symbol
       
   834 	{
       
   835 	TUint* exportdir = (TUint*)(iData + iOrigHdr->iExportDirOffset);
       
   836 	return exportdir[aOrdinal-KOrdinalBase];
       
   837 	}
       
   838 
       
   839 // Determine the type of entry point in this module and set the flags
       
   840 // in the E32Image header accordingly.
       
   841 TInt E32ImageFile::DetermineEntryPointType()
       
   842 	{
       
   843 	TUint cpu = iHdr->CpuIdentifier();
       
   844 	if (cpu != ECpuArmV4 && cpu != ECpuArmV5)
       
   845 		return KErrNone;	// if not ARM, leave EPT as 0
       
   846 	TUint epOffset = iHdr->iEntryPoint;
       
   847 	if (epOffset & 3)
       
   848 		return KErrNone;	// if entry point not 4 byte aligned, must be old style
       
   849 	TUint fileOffset = epOffset + iHdr->iCodeOffset;
       
   850 	if (fileOffset+4 > (TUint)iSize)
       
   851 		return KErrCorrupt;	// entry point is past the end of the file??
       
   852 	TInt ept = 0;			// old style if first instruction not recognised
       
   853 	unsigned char* p = (unsigned char*)iData + fileOffset + 4;
       
   854 	TUint32 x = *--p;
       
   855 	x<<=8;
       
   856 	x|=*--p;
       
   857 	x<<=8;
       
   858 	x|=*--p;
       
   859 	x<<=8;
       
   860 	x|=*--p;
       
   861 	if ((x & 0xffffff00) == 0xe31f0000)
       
   862 		{
       
   863 		// starts with tst pc, #n - new entry point
       
   864 		ept = (x & 0xff) + 1;
       
   865 		}
       
   866 	if (ept>7)
       
   867 		return KErrNotSupported;
       
   868 	iHdr->iFlags |= (ept<<KImageEptShift);
       
   869 	return KErrNone;
       
   870 	}
       
   871