os/kernelhwsrv/userlibandfileserver/fileserver/sfile/sf_lepoc.cpp
author sl
Tue, 10 Jun 2014 14:32:02 +0200
changeset 1 260cb5ec6c19
permissions -rw-r--r--
Update contrib.
     1 // Copyright (c) 1995-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 the License "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 // f32\sfile\sf_lepoc.cpp
    15 // 
    16 //
    17 
    18 #include "sf_std.h"
    19 
    20 #include <e32std.h>
    21 #include <e32std_private.h>
    22 #include <e32base.h>
    23 #include <e32base_private.h>
    24 #include <e32math.h>
    25 #include <e32svr.h>
    26 #include <e32ver.h>
    27 #include <e32hal.h>
    28 #include <u32exec.h>
    29 #define INCLUDE_E32IMAGEHEADER_IMPLEMENTATION
    30 #include "sf_ldr.h"
    31 #include <f32image.h>
    32 #include "sf_image.h"
    33 #include <e32uid.h>
    34 #include <e32rom.h>
    35 #include "sf_cache.h"
    36 
    37 #include "sf_pgcompr.h"
    38 
    39 _LIT(KLitFinderInconsistent, "LDR-FINDER-INC");
    40 _LIT(KLitSysBinError, "LDR-SYS\\BIN ERR");
    41 _LIT8(KSysBin,":\\sys\\bin\\");
    42 
    43 #ifdef _DEBUG
    44 
    45 enum TLdrEpocPanic
    46 	{
    47 	EFuaiNoFixupTable = 0x10,
    48 	EBcbmNotCodePaged = 0x20,
    49 	ELfiCodePagingNotSupported = 0x30,
    50 	EFprUnexpectedFixup = 0x40,
    51 	};
    52 
    53 static void Panic(TLdrEpocPanic aPanic)
    54 	{
    55 	_LIT(KPanicCat, "LDR-PNC");
    56 	User::Panic(KPanicCat, aPanic);
    57 	}
    58 
    59 extern TRequestStatus* ProcessDestructStatPtr;
    60 extern TBool ProcessCreated;
    61 
    62 #endif
    63 
    64 extern void DumpImageHeader(const E32ImageHeader*);
    65 extern TDriveCacheHeader* gDriveFileNamesCache[];
    66 
    67 TBuf8<KMaxPath> gLoadeePath;
    68 TUint NextCodeSegId;
    69 
    70 const TInt KMaxHeaderSize = sizeof(E32ImageHeaderV) + 65536/8;
    71 
    72 
    73 #ifdef __X86__
    74 extern TInt UseFloppy;
    75 #endif
    76 
    77 
    78 
    79 // -------- demand paging --------
    80 
    81 /** Page size as a power of two. */
    82 const TUint32 KPageSizeShift = 12;
    83 /** Page size, as defined for code relocations.  This same page size is used for demand paging. */
    84 const TUint32 KPageSize = 1<<KPageSizeShift;
    85 /** Apply this mask to an address to get the page offset. */
    86 const TUint32 KPageOffsetMask = KPageSize - 1;
    87 
    88 /**
    89 Calculate the number of pages required to contain the supplied number of bytes.
    90 
    91 @param	aSizeInBytes	Size of are which has to be contained in whole blocks.
    92 @return					Number of KPageSize pages required to contain area.
    93 */
    94 inline TInt SizeToPageCount(TInt aSizeInBytes)
    95 	{
    96 	return (aSizeInBytes + KPageOffsetMask) >> KPageSizeShift;
    97 	}
    98 
    99 
   100 /**
   101 Allocate a block which indexes the reallocations by page.  This can be used for demand paging.
   102 
   103 @param	aSection			Pointer to relocation section to process.
   104 @param	aAreaSize			Size in bytes of area described by reloc section.
   105 @param  aLoadAddress		Address of relocation section in memory
   106 @param	aProcessedBlock		On success (return == KErrNone) this is set to the processed
   107 							relocation section which is allocated on the current thread's heap.
   108 							The caller takes ownership.  The contents are undefined on failure.
   109 @return						KErrNoMemory if could not allocate memory for processed block
   110 							and auxiliary structures; KErrNone otherwise.
   111  */
   112 TInt E32Image::AllocateRelocationData(E32RelocSection* aSection, TUint32 aAreaSize, TUint32 aLoadAddress, TUint32*& aProcessedBlock)
   113 	{
   114 	__IF_DEBUG(Printf("AllocateRelocationData"));
   115 
   116 	TUint32 sectionSize = aSection->iSize;
   117 	TUint32 numRelocs = aSection->iNumberOfRelocs;
   118 	TInt pageCount = SizeToPageCount(aAreaSize);
   119 
   120 	// The file format documentation (SOSI ch10) does not guarantee that each page has
   121 	// relocation information, or that the pages are listed in order, so store them in
   122 	// page order here.
   123 	
   124 	TUint8** subBlocks = (TUint8**)User::AllocZ(sizeof(TUint8*)*pageCount);
   125 	if(subBlocks == 0)
   126 		return KErrNoMemory;
   127 
   128 	const TUint8* subBlockPtr = (TUint8*)(aSection+1);
   129 	while(sectionSize > 0)
   130 		{
   131 		TUint32 pageOffset = *(TUint32*)(subBlockPtr);
   132 		TUint32 subBlockSize = *(TUint32*)(subBlockPtr+4);
   133 
   134 		subBlocks[pageOffset >> KPageSizeShift] = (TUint8*)subBlockPtr;
   135 		
   136 		sectionSize -= subBlockSize;
   137 		subBlockPtr += subBlockSize;	// move to next sub-block
   138 		}
   139 
   140 	// now have each relocation page in memory, build lookup table	
   141 	TUint32 indexSize = (pageCount + 1) * sizeof(TUint32);	// include sentinel
   142 	TUint32 totalRelocations = numRelocs;
   143 	iCodeRelocTableSize = indexSize + totalRelocations * sizeof(TUint16);
   144 	TUint8* table = (TUint8*) User::Alloc(iCodeRelocTableSize);
   145 
   146 	if(table == 0)
   147 		{
   148 		User::Free(subBlocks);
   149 		return KErrNoMemory;
   150 		}
   151 
   152 	// where sub-block positions are written to in the table
   153 	TUint32* destSubBlock = (TUint32*)table;
   154 	// where entries are written to in the table
   155 	TUint16* destEntry = (TUint16*)(table + indexSize);
   156 
   157 	TInt i;
   158 	for(i = 0; i < pageCount; ++i)
   159 		{
   160 		*destSubBlock++ = TUint32(destEntry) - TUint32(table);
   161 		
   162 		// see if a relocation page was defined for this page
   163 		const TUint8* subBlock = subBlocks[i];
   164 		if(subBlock == 0)
   165 			continue;
   166 		
   167 		// get number of entries in this sub-block, including padding
   168 		TUint32 sbEntryCount;
   169 		TUint32 pageOffset = *(TUint32*)subBlock;	// offset of page from start of section
   170 		sbEntryCount = *(TUint32*)(subBlock + 4);	// sub-block size
   171 		sbEntryCount -= 8;							// exclude sub-block header
   172 		sbEntryCount /= 2;							// each entry is two bytes
   173 		const TUint16* srcEntry = (TUint16*)(subBlock + 8);
   174 		 
   175 		while(sbEntryCount--)
   176 			{
   177 			TUint16 entry = *srcEntry++;
   178 			if(entry==0)		// ignore null padding values
   179 				continue;
   180 
   181 			// Replace inferred fixup type with actual fixup type
   182 			TUint type = entry & 0xf000;
   183 			if(type==KInferredRelocType)
   184 				{
   185 				TUint32* ptr = (TUint32*)(aLoadAddress + pageOffset + (entry & 0x0fff));
   186 				TUint32 word = *ptr;
   187 				type = (TUint(word - iHeader->iCodeBase) < TUint(iHeader->iCodeSize)) ? KTextRelocType : KDataRelocType;
   188 				entry = (entry & 0x0fff) | type;
   189 				}
   190 			
   191 			*destEntry++ = entry;
   192 			}
   193 		}
   194 	
   195 	// sentinel entry marks the byte following last sub-block in table
   196 	// This gives the size of the last processed sub-block.
   197 	*destSubBlock = TUint32(destEntry) - TUint32(table);
   198 
   199 	aProcessedBlock = (TUint32*) table;
   200 	User::Free(subBlocks);
   201 
   202 #ifdef _DEBUG
   203 	__IF_DEBUG(Printf("processed reloc table (size=%d,pageCount=%d)", iCodeRelocTableSize, pageCount));
   204 
   205 	// dump the import fixup table if loader tracing enabled
   206 	const TUint16* table16 = (const TUint16*)table;
   207 	const TInt halfWordsInTable = iCodeRelocTableSize / 2;
   208 	for(i = 0; i < halfWordsInTable; i += 4)
   209 		{
   210 		__IF_DEBUG(Printf(
   211 			"reloc %04x: %04x %04x %04x %04x",
   212 			i * 2, table16[i+0], table16[i+1], table16[i+2], table16[i+3]));
   213 		}
   214 #endif
   215 	return KErrNone;
   216 	}
   217 
   218 
   219 /*******************************************************************************
   220  * These functions run in supervisor mode since they require access to the
   221  * chunks of the newly-created process or DLL while they are still in the
   222  * home section.
   223  ******************************************************************************/
   224 
   225 /**
   226 Vector which ::ExecuteInSupervisorMode invokes.
   227 */
   228 TInt (*ExecuteInSupervisorModeVector)(TSupervisorFunction, TAny*);
   229 
   230 /**
   231 Executute aFunction in supervisor mode (if the memory model requires this.)
   232 */
   233 TInt ExecuteInSupervisorMode(TSupervisorFunction aFunction, TAny* aParameter)
   234 	{
   235 	return(*ExecuteInSupervisorModeVector)(aFunction, aParameter);
   236 	}
   237 
   238 /**
   239 Implementation of ::ExecuteInSupervisorMode which actually executes the
   240 function in user mode.
   241 */
   242 TInt UserModeExecuteInSupervisorMode(TSupervisorFunction aFunction, TAny* aParameter)
   243 	{
   244 	return (*aFunction)(aParameter);
   245 	}
   246 
   247 /**
   248 Decide whether any Loader code actually needs to execute in supervisor mode
   249 and set ::ExecuteInSupervisorModeVector so that invocations of ::ExecuteInSupervisorMode
   250 call the appropriate function.
   251 */
   252 void InitExecuteInSupervisorMode()
   253 	{
   254 	// work out if we need to really 'execute in supervisor mode'...
   255 	TUint32 memModelAttrs = (TUint32)UserSvr::HalFunction(EHalGroupKernel, EKernelHalMemModelInfo, NULL, NULL);
   256 	TUint32 memModel = memModelAttrs & EMemModelTypeMask;
   257 	if(memModel==EMemModelTypeFlexible)
   258 		{
   259 		// we can do everything user side...
   260 		ExecuteInSupervisorModeVector = UserModeExecuteInSupervisorMode;
   261 		gExecutesInSupervisorMode = EFalse;
   262 		}
   263 	else
   264 		{
   265 		// we need to go kernel side...
   266 		ExecuteInSupervisorModeVector = UserSvr::ExecuteInSupervisorMode;
   267 		gExecutesInSupervisorMode = ETrue;
   268 		}
   269 	}
   270 
   271 
   272 /**
   273 Arguments for svRelocateSection.
   274 
   275 The relocation information (at iRelocsBuf) has list sub blocks, each referring to a 4kB
   276 page within the section. See E32RelocBlock.
   277 */
   278 struct SRelocateSectionInfo
   279 	{
   280 	E32Image* iImage;		///< The executable being relocated.
   281 	TUint8* iRelocsBuf;		///< Pointer to relocation info.
   282 	TUint32 iNumRelocs;		///< Total number of relocations to apply.
   283 	TUint32 iLoadAddress; 	///< Virtual address where section is currently located in memory.
   284 	};
   285 
   286 /**
   287 Apply relocations to a code or data section.
   288 
   289 @param aPtr Pointer to SRelocateSectionInfo.
   290 */
   291 TInt svRelocateSection(TAny* aPtr)
   292 	{
   293 	SRelocateSectionInfo& info=*(SRelocateSectionInfo*)aPtr;
   294 
   295 	E32Image& img = *(E32Image*)info.iImage;
   296 	TUint8* relocs = info.iRelocsBuf;
   297 	TUint32 numRelocs = info.iNumRelocs;
   298 	TUint32 loadAddress = info.iLoadAddress;
   299 
   300 	TUint32 codeStart = img.iHeader->iCodeBase;
   301 	TUint32 codeFinish = codeStart+img.iHeader->iCodeSize;
   302 	TUint32 codeDelta = img.iCodeDelta;
   303 	TUint32 dataDelta = img.iDataDelta;
   304 
   305 	while(numRelocs>0)
   306 		{
   307 		TUint32 pageAddress = ((TUint32*)relocs)[0];
   308 		TUint32 pageSize = ((TUint32*)relocs)[1];
   309 		TUint8* relocsEnd = relocs+pageSize;
   310 		relocs += 8;
   311 
   312 		while(relocs<relocsEnd)
   313 			{
   314 			TUint16 relocOffset = *(TUint16*)relocs;
   315 			relocs += 2;
   316 			if(!relocOffset)
   317 				continue;
   318 
   319 			TUint32 offset = pageAddress+(TUint32)(relocOffset&0x0fff);
   320 			TUint32* destPtr = (TUint32*)(loadAddress+offset);
   321 			TUint16 relocType = relocOffset&0xf000;
   322 
   323 			TUint32 relocAddr = *destPtr;
   324 			if(relocType==KTextRelocType)
   325 				relocAddr += codeDelta; // points to text/rdata section
   326 			else if(relocType==KDataRelocType)
   327 				relocAddr += dataDelta; // points to data section
   328 			else if (relocAddr>=codeStart && relocAddr<codeFinish)
   329 				relocAddr += codeDelta; // points to text/rdata section
   330 			else
   331 				relocAddr += dataDelta; // points to data section
   332 			*destPtr = relocAddr;
   333 
   334 			--numRelocs;
   335 			}
   336 		}
   337 	return 0;
   338 	}
   339 
   340 
   341 /**
   342 Fix up the export directory
   343 Only performed on PE images.  ELF image's exports are marked
   344 as relocatable and therefore relocated by svRelocateSection when the 
   345 text section is relocated up
   346 */
   347 TInt svRelocateExports(TAny* aPtr)
   348 	{
   349 	E32Image* pI=(E32Image*)aPtr;
   350 	TUint32* destExport=(TUint32*)pI->iExportDirLoad;
   351 	TInt i=pI->iExportDirCount;
   352 	TUint32 codeBase=pI->iCodeRunAddress;
   353 	while (i-->0)
   354 		*destExport+++=codeBase;
   355 	return 0;
   356 	}
   357 
   358 
   359 struct SFixupImportAddressesInfo
   360 	{
   361 	TUint32* iIat;
   362 	TUint32* iExportDir;
   363 	TUint32 iExportDirEntryDelta;
   364 	TInt iNumImports;
   365 	E32Image* iExporter;
   366 	/**
   367 	For demand paging, this points to the buffer which is populated
   368 	so each page can be fixed up as it is loaded in.
   369 	*/
   370 	TUint64* iFixup64;
   371 	// For ElfDerived...
   372 	TUint32 iCodeLoadAddress;
   373 	TUint32* iImportOffsetList;
   374 	};
   375 
   376 
   377 /**
   378 Fix up the import address table, used for 'PE derived' executables.
   379 @param aPtr Pointer to function arguments (SFixupImportAddressesInfo structure).
   380 			SFixupImportAddressesInfo::iIat is updated by this function.
   381 */
   382 TInt svFixupImportAddresses(TAny* aPtr)
   383 	{
   384 	SFixupImportAddressesInfo& info = *(SFixupImportAddressesInfo*)aPtr;
   385 
   386 	TUint32 maxOrdinal = (TUint32)info.iExporter->iExportDirCount;
   387 	TUint32 absentOrdinal = (TUint32)info.iExporter->iFileEntryPoint;
   388 
   389 	TUint32* exp_dir = info.iExportDir - KOrdinalBase; // address of 0th ordinal
   390 	TUint32 exp_delta = info.iExportDirEntryDelta;
   391 
   392 	TUint32* iat = info.iIat;
   393 	TUint32* iatE = iat+info.iNumImports;
   394 	for(; iat<iatE; ++iat)
   395 		{
   396 		TUint32 imp = *iat;
   397 		if(imp>maxOrdinal)
   398 			return KErrNotSupported;
   399 
   400 		TUint32 writeValue;
   401 		if(imp==0 && !(info.iExporter->iAttr&ECodeSegAttNmdExpData))
   402 			{
   403 			// attempt to import ordinal zero (symbol name data) from an executable
   404 			// which doesn't export this information, use NULL for imported value in this case...
   405 			writeValue = NULL;
   406 			}
   407 		else
   408 			{
   409 			// get imported value from exporter...
   410 			TUint32 exp_addr = exp_dir[imp];
   411 			if(exp_addr==0 || exp_addr==absentOrdinal)
   412 				return KErrNotSupported;
   413 			writeValue = exp_addr + exp_delta;
   414 			}
   415 
   416 		// if not code paging then directly fix up the import...
   417 		if (info.iFixup64 == 0)
   418 			*iat = writeValue;
   419 		else
   420 		// ...otherwise defer until the page is fixed up
   421 			{
   422 			TUint64 iat64 = reinterpret_cast<TUint64>(iat);
   423 			*info.iFixup64++ = (iat64 << 32) | writeValue;
   424 			}
   425 		}
   426 
   427 	info.iIat = iat;
   428 	return KErrNone;
   429 	}
   430 
   431 
   432 /**
   433 Fix up the import addresses, used for 'elf derived' executables.
   434 @param aPtr Pointer to function arguments (SFixupImportAddressesInfo structure).
   435 */
   436 TInt svElfDerivedFixupImportAddresses(TAny* aPtr)
   437 	{
   438 	SFixupImportAddressesInfo& info = *(SFixupImportAddressesInfo*)aPtr;
   439 	TUint32 maxOrdinal = (TUint32)info.iExporter->iExportDirCount;
   440 	TUint32 absentOrdinal = (TUint32)info.iExporter->iFileEntryPoint;
   441 
   442 	TUint32* exp_dir = info.iExportDir - KOrdinalBase; // address of 0th ordinal
   443 	TUint32 exp_delta = info.iExportDirEntryDelta;
   444 	TUint32 code = info.iCodeLoadAddress;
   445 
   446 	TUint32* iol = info.iImportOffsetList;
   447 	TUint32* iolE = iol+info.iNumImports;
   448 	for(; iol<iolE; ++iol)
   449 		{
   450 		TUint32* impPtr = (TUint32*)(code+*iol);
   451 		TUint32 impd = *impPtr;
   452 		TUint32 imp = impd & 0xffff;
   453 		TUint32 offset = impd >> 16;
   454 		if(imp>maxOrdinal)
   455 			return KErrNotSupported;
   456 
   457 		TUint32 writeValue;
   458 		if(imp==0 && !(info.iExporter->iAttr&ECodeSegAttNmdExpData))
   459 			{
   460 			// attempt to import ordinal zero (symbol name data) from an executable
   461 			// which doesn't export this information, use NULL for imported value in this case...
   462 			writeValue = NULL;
   463 			}
   464 		else
   465 			{
   466 			// get imported value from exporter...
   467 			TUint32 exp_addr = exp_dir[imp];
   468 			if(exp_addr==0 || exp_addr==absentOrdinal)
   469 				return KErrNotSupported;
   470 			writeValue = exp_addr + exp_delta + offset;
   471 			}
   472 
   473 		// if not code paging then directly fix up the import...
   474 		if (info.iFixup64 == 0)
   475 			*impPtr = writeValue;
   476 		// ...otherwise defer until the page is fixed up
   477 		else
   478 			{
   479 			TUint64 impPtr64 = reinterpret_cast<TUint64>(impPtr);
   480 			*info.iFixup64++ = (impPtr64 << 32) | writeValue;
   481 			}
   482 		}
   483 	return KErrNone;
   484 	}
   485 
   486 
   487 /**
   488 Wrapper for memory copy arguments.
   489 */
   490 struct SCopyDataInfo
   491 	{
   492 	TAny* iDest;
   493 	const TAny* iSource;
   494 	TInt iNumberOfBytes;
   495 	};
   496 
   497 
   498 /**
   499 Copies word aligned memory.
   500 @param aPtr Pointer to function arguments (SCopyDataInfo structure).
   501 */
   502 TInt svWordCopy(TAny* aPtr)
   503 	{
   504 	SCopyDataInfo& info=*(SCopyDataInfo*)aPtr;
   505 	return (TInt) Mem::Move(info.iDest, info.iSource, info.iNumberOfBytes);
   506 	}
   507 
   508 
   509 /**
   510 Copies memory.
   511 @param aPtr Pointer to function arguments (SCopyDataInfo structure).
   512 */
   513 TInt svMemCopy(TAny* aPtr)
   514 	{
   515 	SCopyDataInfo& info=*(SCopyDataInfo*)aPtr;
   516 	return (TInt) Mem::Copy(info.iDest, info.iSource, info.iNumberOfBytes);
   517 	}
   518 
   519 
   520 /**
   521 Argument for svElfDerivedGetImportInfo.
   522 */
   523 struct SGetImportDataInfo
   524 	{
   525 	TInt iCount;					// number to extract
   526 	TUint32* iDest;					// destination address for data
   527 	TUint32 iCodeLoadAddress;		// address where code has been loaded
   528 	TUint32* iImportOffsetList;		// pointer to list of import offsets in E32ImportBlock
   529 	};
   530 
   531 /**
   532 Extract import ordinals/data
   533 @param aPtr Pointer to function arguments (SGetImportDataInfo structure).
   534 */
   535 TInt svElfDerivedGetImportInfo(TAny* aPtr)
   536 	{
   537 	SGetImportDataInfo& info = *(SGetImportDataInfo*)aPtr;
   538 	TInt count = info.iCount;
   539 	TUint32* dest = info.iDest;
   540 	TUint32 code = info.iCodeLoadAddress;
   541 	TUint32* iol = info.iImportOffsetList;
   542 
   543 	TUint32* iolEnd = iol+count;
   544 	while(iol<iolEnd)
   545 		*dest++ = *(TUint32*)(code + *iol++);
   546 		
   547 	return 0;
   548 	}
   549 
   550 /*******************************************************************************
   551  * End of supervisor mode functions
   552  ******************************************************************************/
   553 
   554 
   555 /*******************************************************************************
   556  * RImageInfo
   557  ******************************************************************************/
   558 RImageInfo::RImageInfo()
   559 	{
   560 	memclr(this, sizeof(RImageInfo));
   561 	}
   562 
   563 void RImageInfo::Close()
   564 	{
   565 	iFile.Close();
   566 	delete iHeader;
   567 	iHeader=NULL;
   568 	gFileDataAllocator.Free(iFileData);
   569 	iFileData=NULL;
   570 	}
   571 
   572 void RImageInfo::Accept(RImageInfo& aInfo)
   573 	{
   574 	Close();
   575 	wordmove(this, &aInfo, sizeof(RImageInfo));
   576 	memclr(&aInfo.iFile, (_FOFF(RImageInfo,iFileSize) - _FOFF(RImageInfo,iFile)) );
   577 	}
   578 
   579 /*******************************************************************************
   580  * EPOC executable file finders
   581  ******************************************************************************/
   582 RImageFinder::RImageFinder()
   583 	:	iNameMatches(0), iUidFail(0), iCapFail(0), iMajorVersionFail(0), iImportFail(0),
   584 		iCurrentVersion(KModuleVersionNull), iCurrentDrive(0), iFindExact(0), iNewValid(0),
   585 		iReq(0), iExisting(0)
   586 	{
   587 	}
   588 
   589 TInt RImageFinder::Set(const RLdrReq& aReq)
   590 	{
   591 	iReq = &aReq;
   592 	TInt l = aReq.iFileNameInfo.BaseLen() + aReq.iFileNameInfo.ExtLen();
   593 	if (l > KMaxProcessName)
   594 		return KErrBadName;
   595 	aReq.iFileNameInfo.GetName(iRootName, TFileNameInfo::EIncludeBaseExt);
   596 	return KErrNone;
   597 	}
   598 
   599 void RImageFinder::Close()
   600 	{
   601 	iNew.Close();
   602 	}
   603 
   604 _LIT8(KDefaultPathSysBin, "sys\\bin");
   605 _LIT8(KDefaultPathSysBin2, "?:\\sys\\bin");
   606 _LIT8(KDefaultExePath, "sys\\bin;system\\bin;system\\programs;system\\libs");
   607 _LIT8(KDefaultDllPath, "sys\\bin;system\\bin;system\\libs");
   608 _LIT8(KDefaultExePath2, "?:\\sys\\bin;?:\\system\\bin;?:\\system\\programs;?:\\system\\libs");
   609 _LIT8(KDefaultDllPath2, "?:\\sys\\bin;?:\\system\\bin;?:\\system\\libs");
   610 
   611 TInt RImageFinder::Search()
   612 	{
   613 	__LDRTRACE(iReq->Dump(">RImageFinder::Search"));
   614 	TBool exe = (iReq->iRequestedUids[0] == KExecutableImageUid);
   615 	const TFileNameInfo& fi = iReq->iFileNameInfo;
   616 	TInt r = KErrNone;
   617 	if (fi.PathLen())
   618 		{
   619 		// path specified, so only look there
   620 		TPtrC8 drive_and_path(fi.DriveAndPath());
   621 		r = Search(&drive_and_path, 0);
   622 		}
   623 	else
   624 		{
   625 		TInt drv = -1;
   626 		if (fi.DriveLen())
   627 			{
   628 			// drive specified
   629 			drv = (*iReq->iFileName)[0];
   630 			}
   631 		// if a search path is specified look there
   632 		if (iReq->iPath)
   633 			r = Search(iReq->iPath, drv);
   634 		if (r == KErrNoMemory) // ignore other errors as they are a potential denial of service
   635 			{
   636 			__LDRTRACE(Dump("<RImageFinder::Search", r));
   637 			return r;
   638 			}
   639 		const TDesC8* defpath;
   640 		if(PlatSec::ConfigSetting(PlatSec::EPlatSecEnforceSysBin))
   641 			defpath = (drv<0) ? &KDefaultPathSysBin() : &KDefaultPathSysBin2();
   642 		else
   643 			{
   644 			if (drv<0)
   645 				defpath = exe ? &KDefaultExePath() : &KDefaultDllPath();
   646 			else
   647 				defpath = exe ? &KDefaultExePath2() : &KDefaultDllPath2();
   648 			}
   649 		r = Search(defpath, drv);
   650 		}
   651 	if (r == KErrNoMemory)  // ignore other errors as they are a potential denial of service
   652 		{
   653 		__LDRTRACE(Dump("<RImageFinder::Search", r));
   654 		return r;
   655 		}
   656 	if (iExisting || iNewValid)
   657 		r = KErrNone;			// found something suitable
   658 	else if (!iNameMatches)
   659 		r = KErrNotFound;		// nothing matched requested name
   660 	else if (iImportFail || iMajorVersionFail)
   661 		r = KErrNotSupported;	// something failed only on missing imports or version
   662 	else if (iCapFail)
   663 		r = KErrPermissionDenied;	// something failed capability check
   664 	else if (iUidFail)
   665 		r = KErrNotSupported;	// something failed UID check
   666 	else
   667 		r = KErrCorrupt;		// a file had the correct name but was not a valid E32Image file
   668 	__LDRTRACE(Dump("<RImageFinder::Search", r));
   669 	return r;
   670 	}
   671 
   672 TInt RImageFinder::Search(const TDesC8* aPath, TInt aDrive)
   673 	{
   674 	__IF_DEBUG(Printf(">Path %S Drive %02x", aPath, aDrive));
   675 	TInt ppos = 0;
   676 	TInt plen = aPath->Length();
   677 	while (ppos < plen)
   678 		{
   679 		TPtrC8 remain(aPath->Mid(ppos));
   680 		TInt pel = remain.Locate(';');
   681 		if (pel < 0)
   682 			{
   683 			pel = remain.Length();
   684 			ppos += pel;
   685 			}
   686 		else
   687 			{
   688 			ppos += pel + 1;
   689 			}
   690 		if (pel == 0)
   691 			continue;
   692 		TBool alldrives = EFalse;
   693 		if (pel<2 || remain[1]!=':')
   694 			alldrives = ETrue;
   695 		else if (remain[0]!='?')
   696 			aDrive = remain[0];
   697 		TInt drive = EDriveY;
   698 		if (!alldrives && RFs::CharToDrive(TChar(aDrive), drive)!=KErrNone)
   699 			continue;
   700 		iCurrentDrive = (TUint8)drive;
   701 		TInt startpos = alldrives ? 0 : 2;
   702 		iCurrentPath.Set(remain.Mid(startpos, pel - startpos));
   703 		do	{
   704 			TInt r;
   705 #ifdef __X86__
   706 			if (alldrives && iCurrentDrive<=EDriveB && iCurrentDrive!=UseFloppy)
   707 				goto bypass_drive;
   708 #endif
   709 			r = SearchSingleDir();
   710 			if (r == KErrNoMemory) // ignore other errors as they are a potential denial of service
   711 				{
   712 				__IF_DEBUG(Printf("OOM!"));
   713 				return r;
   714 				}
   715 #ifdef __X86__
   716 bypass_drive:
   717 #endif
   718 			if (!iCurrentDrive--)
   719 				iCurrentDrive = EDriveZ;
   720 			} while(alldrives && iCurrentDrive != EDriveY);
   721 		}
   722 	__IF_DEBUG(Printf("<Path %S Drive %02x", aPath, aDrive));
   723 	return KErrNone;
   724 	}
   725 
   726 // Can't be looking for main loadee here, so iReq->iImporter is never NULL
   727 // Also gExeAttr must be set up
   728 TInt RImageFinder::SearchExisting(const RImageArray& aArray)
   729 	{
   730 	__IF_DEBUG(Printf(">RImageFinder::SearchExisting"));
   731 	TUint required_abi = gExeAttr & ECodeSegAttABIMask;
   732 	TInt first, last, i;
   733 	aArray.Find(iRootName, first, last);
   734 	for (i=first; i<last; ++i)
   735 		{
   736 		E32Image* e = aArray[i];
   737 		if (CheckUids(e->iUids, iReq->iRequestedUids) != KErrNone)
   738 			continue;
   739 		if (iReq->CheckSecInfo(e->iS) != KErrNone)
   740 			continue;
   741 		TInt action = DetailedCompareVersions(e->iModuleVersion, iReq->iRequestedVersion, iCurrentVersion, EFalse);
   742 		if (action == EAction_Skip)
   743 			continue;
   744 		if (action == EAction_CheckImports || action == EAction_CheckLastImport)
   745 			{
   746 			// Never optimistically link to something with a different ABI
   747 			if ((e->iAttr & ECodeSegAttABIMask) != required_abi)
   748 				continue;
   749 			TInt r = CheckRequiredImports(iReq->iImporter, e, action);
   750 			if (r != KErrNone)
   751 				{
   752 				if (r != KErrNotSupported)
   753 					return r;
   754 				continue;
   755 				}
   756 			}
   757 		iExisting = e;
   758 		iCurrentVersion = e->iModuleVersion;
   759 		}
   760 	__IF_DEBUG(Printf("<RImageFinder::SearchExisting"));
   761 	return KErrNone;
   762 	}
   763 
   764 // Called for each file found with matching root name but which is not a valid E32ImageFile
   765 void RImageFinder::RecordCorruptFile()
   766 	{
   767 	__IF_DEBUG(Printf("RImageFinder::RecordCorruptFile"));
   768 	++iNameMatches;
   769 	}
   770 
   771 // Called for each valid E32Image file found with matching root name
   772 TInt RImageFinder::Try(RImageInfo& aInfo, const TDesC8& aRootName, const TDesC8& aDriveAndPath)
   773 	{
   774 	__IF_DEBUG(Printf(">RImageFinder::Try %S%S", &aDriveAndPath, &aRootName));
   775 	__IF_DEBUG(Printf(">MA:%08x MV:%08x RV:%08x CV:%08x", aInfo.iAttr, aInfo.iModuleVersion, iReq->iRequestedVersion, iCurrentVersion));
   776 	++iNameMatches;
   777 	if (iFindExact)
   778 		{
   779 		if ( ((aInfo.iAttr & ECodeSegAttExpVer) && aInfo.iModuleVersion==iReq->iRequestedVersion)
   780 			|| (!(aInfo.iAttr & ECodeSegAttExpVer) && iReq->iRequestedVersion==KModuleVersionWild)
   781 			)
   782 			{
   783 			__IF_DEBUG(Printf("<RImageFinder::Try Exact Match Found"));
   784 			iNewValid = 1;
   785 			iNew.Accept(aInfo);
   786 			SetName(aRootName, aDriveAndPath);
   787 			return KErrCompletion;
   788 			}
   789 		return KErrNotFound;
   790 		}
   791 	TUint required_abi = gExeAttr & ECodeSegAttABIMask;
   792 	TBool abi_mismatch = ((aInfo.iAttr & ECodeSegAttABIMask)!=required_abi);
   793 	TInt32* uid = (TInt32*)&iReq->iRequestedUids;
   794 	TBool dll_wanted = (uid[0] == KDynamicLibraryUidValue);
   795 	if (CheckUids(*(TUidType*)aInfo.iUid, iReq->iRequestedUids) != KErrNone)
   796 		{
   797 		++iUidFail;
   798 		__IF_DEBUG(Printf("<RImageFinder::Try UIDFAIL"));
   799 		return KErrNotFound;
   800 		}
   801 	if (iReq->CheckSecInfo(aInfo.iS) != KErrNone)
   802 		{
   803 		++iCapFail;
   804 		__IF_DEBUG(Printf("<RImageFinder::Try CAPFAIL"));
   805 		return KErrNotFound;
   806 		}
   807 	TInt action = DetailedCompareVersions(aInfo.iModuleVersion, iReq->iRequestedVersion, iCurrentVersion, !iReq->iImporter);
   808 	if (action == EAction_Skip)
   809 		{
   810 		if (DetailedCompareVersions(aInfo.iModuleVersion, iReq->iRequestedVersion) == EVersion_MajorSmaller)
   811 			++iMajorVersionFail;
   812 		__IF_DEBUG(Printf("<RImageFinder::Try VERFAIL"));
   813 		return KErrNotFound;
   814 		}
   815 	if (action == EAction_CheckImports || action == EAction_CheckLastImport)
   816 		{
   817 		// If we get here, can't be main loadee so gExeAttr must be valid
   818 		// Never optimistically link to something with a different ABI
   819 		if (abi_mismatch || CheckRequiredImports(iReq->iImporter, aInfo, action)!=KErrNone)
   820 			{
   821 			__IF_DEBUG(Printf("<RImageFinder::Try IMPFAIL"));
   822 			++iImportFail;
   823 			return KErrNotFound;
   824 			}
   825 		}
   826 	if (!iReq->iImporter && dll_wanted && abi_mismatch)
   827 		{
   828 		// Dynamically loading a DLL - ABI must match loading process
   829 		__IF_DEBUG(Printf("<RImageFinder::Try ABIFAIL"));
   830 		++iImportFail;
   831 		return KErrNotFound;
   832 		}
   833 	if(PlatSec::ConfigSetting(PlatSec::EPlatSecEnforceSysBin))
   834 		{
   835 		TChar driveLetter;
   836 		TInt driveNumber;
   837 		TInt r;
   838 		driveLetter=(TChar)aDriveAndPath[0];
   839 		RFs::CharToDrive(driveLetter,driveNumber);
   840 		TDriveCacheHeader* pDH=gDriveFileNamesCache[driveNumber];
   841 		TUint driveAtt=0;
   842 		if(pDH)
   843 			driveAtt=pDH->iDriveAtt;
   844 		else
   845 			{
   846 			TDriveInfo driveInfo;
   847 			if ((r=gTheLoaderFs.Drive(driveInfo,driveNumber)) != KErrNone)
   848 				{
   849 				__IF_DEBUG(Printf("<RImageFinder::Try DINFFAIL"));
   850 				++iImportFail;
   851 				return r;
   852 				}
   853 			driveAtt=driveInfo.iDriveAtt;
   854 			}
   855 
   856 		if(driveAtt & KDriveAttRemovable)
   857 			{
   858 			__IF_DEBUG(Printf("** RImageFinder::Try %S%S is on a removable drive", &aDriveAndPath, &aRootName));
   859 			// If the cache says we already checked the hash of this file, accept it without checking again
   860 			// as any *legitimate* change to the file would've triggered the cache to be rebuilt.
   861 			if (!(aInfo.iCacheStatus & TImageInfo::EHashChecked))
   862 				{
   863 				//We have to pass aDriveAndPath as aInfo may not contain Drive
   864 				TRAP(r,CompareHashL(aInfo, aDriveAndPath));
   865 				if (r == KErrNoMemory)
   866 					return r;
   867 				if(r!=KErrNone)
   868 					{
   869 					__IF_DEBUG(Printf("<RImageFinder::Try Compare Hash Failed"));
   870 					iCapFail++;
   871 					return r;
   872 					}
   873 				aInfo.iCacheStatus |= TImageInfo::EHashChecked;
   874 				}
   875 			else
   876 				{
   877 				// We've skipped hash checking as an optimisation, however someone could potentially have
   878 				// used external hardware to switch the data on the card since the cached hash check. Setting
   879 				// this mark means that if we actually load the file, we'll hash it then; but if it turns out
   880 				// to be already loaded, we can save the effort.
   881 				aInfo.iNeedHashCheck = 1;
   882 				}
   883 			}
   884 		}
   885 	iExisting = NULL;
   886 	iNew.Accept(aInfo);
   887 	iNewValid = 1;
   888 	iCurrentVersion = aInfo.iModuleVersion;
   889 	SetName(aRootName, aDriveAndPath);
   890 	__IF_DEBUG(Printf("<MV:%08x RV:%08x CV:%08x", aInfo.iModuleVersion, iReq->iRequestedVersion, iCurrentVersion));
   891 	__IF_DEBUG(Printf("<RImageFinder::Try OK"));
   892 	return KErrNone;
   893 	}
   894 
   895 void RImageFinder::CompareHashL(RImageInfo& aInfo, const TDesC8& aDriveAndPath)
   896 //
   897 //	Calculate hash and compare after checking if one already exists in c:/system/caps
   898 //
   899 	{
   900 	__IF_DEBUG(Printf(">RImageFinder::CompareHashL"));
   901 	
   902 	TInt extraFlag = 0;
   903 	TBuf8<KMaxFileName*sizeof(TText)> fileName;
   904 	TFileNameInfo fni = iReq->iFileNameInfo;
   905 	if (aInfo.iAttr & ECodeSegAttExpVer)
   906 		{
   907 		fni.iVersion = aInfo.iModuleVersion;
   908 		extraFlag = TFileNameInfo::EForceVer;				
   909 		}
   910 	
   911 	TFileName hashname(KSysHash);
   912     hashname[0] = (TUint8) RFs::GetSystemDriveChar();
   913 	fileName.SetLength(0);
   914 	fni.GetName(fileName, TFileNameInfo::EIncludeBaseExt | extraFlag);
   915 	hashname.Append(fileName.Expand());
   916 
   917 	RFile fHash;
   918 	CleanupClosePushL(fHash);
   919 
   920 	__IF_DEBUG(Printf("RImageFinder::CompareHashL opening hash file %S ", &hashname));
   921 	User::LeaveIfError(fHash.Open(gTheLoaderFs,hashname,EFileRead|EFileReadDirectIO));
   922 
   923 	TBuf8<SHA1_HASH> installhash;
   924 	User::LeaveIfError(fHash.Read(installhash));
   925 	CleanupStack::PopAndDestroy(1);
   926 
   927 	// if we get this far, we have loaded a valid hash, so calculate the file's hash
   928 
   929 	CSHA1* hasher=CSHA1::NewL(); 
   930 	CleanupStack::PushL(hasher);
   931 
   932 	fileName.Copy(aDriveAndPath);
   933 	fni.GetName(fileName, TFileNameInfo::EIncludeBaseExt | extraFlag);
   934 
   935 	CleanupClosePushL(aInfo.iFile);
   936 	TBool b = aInfo.FileOpened();
   937 	if(!b)		
   938 		{
   939 		__IF_DEBUG(Printf("RImageFinder::CompareHashL opening the file %S", &fileName));
   940 		User::LeaveIfError(aInfo.iFile.Open(gTheLoaderFs, fileName.Expand(), EFileRead|EFileReadDirectIO));
   941 		}
   942 	
   943 	__IF_DEBUG(Printf("RImageFinder::CompareHashL calculate hash"));
   944 	TInt size;
   945 	User::LeaveIfError(aInfo.iFile.Size(size));
   946 	aInfo.iFileData = (TUint8*)gFileDataAllocator.Alloc(size);
   947 	if (aInfo.iFileData)
   948 		aInfo.iFileSize = size;
   949 	else
   950 		User::Leave(KErrNoMemory);
   951 	TPtr8 filedata(aInfo.iFileData, size);
   952 	User::LeaveIfError(aInfo.iFile.Read(0, filedata, size));
   953 	if (filedata.Length() != size)
   954 		User::Leave(KErrCorrupt);
   955 	CleanupStack::PopAndDestroy(1);	//the file handle only->aInfo.iFile.Close();
   956 	hasher->Update(filedata);
   957 		
   958 	TBuf8<SHA1_HASH> hash;
   959 	hash=hasher->Final(); 
   960 
   961 
   962 	__IF_DEBUG(Printf("RImageFinder::CompareHashL comparing hashes..."));
   963 	if(0 != hash.Compare(installhash))
   964 		User::Leave(KErrPermissionDenied);
   965 	CleanupStack::PopAndDestroy(1);
   966 	
   967 	// if we get this far the hash has passed and the file has been closed
   968 	// but some of the RImageInfo parameters will've been initialised by the cache
   969 	// and may be lies if we're being attacked, so compare them to be sure
   970 
   971 	// if we already had the header, throw it away: it's from untrusted data
   972 	if (aInfo.iHeader)
   973 		{
   974 		delete aInfo.iHeader;
   975 		aInfo.iHeader = NULL;
   976 		}
   977 
   978 	// make the header and validate the cached parameters against it
   979 	User::LeaveIfError(E32ImageHeader::New(aInfo.iHeader, aInfo.iFileData, aInfo.iFileSize));
   980 
   981 	SSecurityInfo secinfo;
   982 	aInfo.iHeader->GetSecurityInfo(secinfo);
   983 	TUint32 attr = (aInfo.iHeader->iFlags & ECodeSegAttFixed) | aInfo.iHeader->ABI();
   984 	if(aInfo.iHeader->iFlags&KImageNmdExpData)
   985 		attr |= ECodeSegAttNmdExpData;
   986 	if (Mem::Compare((TUint8*)aInfo.iUid, sizeof(aInfo.iUid), (TUint8*)&aInfo.iHeader->iUid1, sizeof(aInfo.iUid))
   987 			|| aInfo.iModuleVersion != aInfo.iHeader->ModuleVersion()
   988 			|| Mem::Compare((TUint8*)&aInfo.iS, sizeof(aInfo.iS), (TUint8*)&secinfo, sizeof(secinfo))
   989 			|| (aInfo.iAttr & ~ECodeSegAttExpVer) != attr)
   990 		User::Leave(KErrPermissionDenied);
   991 
   992 	__IF_DEBUG(Printf("<RImageFinder::CompareHashL passed"));
   993 	}
   994 
   995 void RImageFinder::SetName(const TDesC8& aRootName, const TDesC8& aDriveAndPath)
   996 	{
   997 	iNewFileName = aDriveAndPath;
   998 	iNewFileName.Append(aRootName);
   999 	}
  1000 
  1001 RImageArray::RImageArray()
  1002 	:	RPointerArray<E32Image>(8, 2*256)
  1003 	{
  1004 	}
  1005 
  1006 TInt RImageArray::Add(E32Image* aImage)
  1007 	{
  1008 	return InsertInOrderAllowRepeats(aImage, &E32Image::Order);
  1009 	}
  1010 
  1011 void RImageArray::Find(const TDesC8& aRootName, TInt& aFirst, TInt& aLast) const
  1012 	{
  1013 	TCodeSegCreateInfo name;
  1014 	name.iFileName.Copy(aRootName);
  1015 	name.iRootNameOffset = 0;
  1016 	name.iRootNameLength = aRootName.Length();
  1017 	aFirst = SpecificFindInOrder((const E32Image*)&name, &E32Image::Order, EArrayFindMode_First);
  1018 	aLast = aFirst;
  1019 	if (aFirst >= 0)
  1020 		aLast = SpecificFindInOrder((const E32Image*)&name, &E32Image::Order, EArrayFindMode_Last);
  1021 	}
  1022 
  1023 E32Image* RImageArray::Find(const TRomImageHeader* a) const
  1024 	{
  1025 	TInt c = Count();
  1026 	if (!c)
  1027 		return NULL;
  1028 	E32Image* const * ee = &(*this)[0];
  1029 	E32Image* const * eE = ee + c;
  1030 	for (; ee<eE && (*ee)->iRomImageHeader != a; ++ee) {}
  1031 	return (ee<eE) ? *ee : NULL;
  1032 	}
  1033 
  1034 TInt E32Image::LoadProcess(const RLdrReq& aReq)
  1035 	{
  1036 	__LDRTRACE(aReq.Dump("E32Image::LoadProcess"));
  1037 
  1038 	RImageFinder finder;
  1039 	TInt r = finder.Set(aReq);
  1040 	if (r == KErrNone)
  1041 		r = finder.Search();
  1042 	if (r!=KErrNone)
  1043 		{
  1044 		finder.Close();
  1045 		return r;
  1046 		}
  1047 	r = Construct(finder);	// needs to find it if it's already loaded
  1048 	finder.Close();
  1049 	if (r!=KErrNone)
  1050 		{
  1051 		return r;
  1052 		}
  1053 	if (iIsDll)
  1054 		return KErrNotSupported;
  1055 	r = aReq.iMsg->Client((RThread&)aReq.iClientThread);
  1056 	if (r!=KErrNone)
  1057 		{
  1058 		return r;
  1059 		}
  1060 	iClientHandle=aReq.iClientThread.Handle();
  1061 	
  1062 	if(iStackSize < aReq.iMinStackSize)
  1063 		iStackSize=aReq.iMinStackSize;		// If the process required larger stack than the default.
  1064 
  1065 	//initialise to zero
  1066 #ifdef _DEBUG
  1067 	iDestructStat = ProcessDestructStatPtr;
  1068 #endif
  1069 	iDebugAttributes = 0;
  1070 	if (iRomImageHeader)
  1071 		{
  1072 		if (iRomImageHeader->iFlags & KRomImageDebuggable)
  1073 			iDebugAttributes |= EDebugAllowed;
  1074 		}
  1075 	else if (iHeader)
  1076 		{
  1077 		if (iHeader->iFlags & KImageDebuggable)
  1078 			iDebugAttributes |= EDebugAllowed;
  1079 		}
  1080 	
  1081 	// Get the data paging flags and pass to the kernel.
  1082 	__ASSERT_COMPILE(EDataPagingUnspecified == 0);
  1083 	if (iRomImageHeader)
  1084 		{
  1085 		TUint dataPaging = iRomImageHeader->iFlags & KRomImageDataPagingMask;
  1086 		if (dataPaging == KRomImageDataPagingMask)
  1087 			RETURN_FAILURE(KErrCorrupt);
  1088 		if (dataPaging == KRomImageFlagDataPaged)
  1089 			iFlags |= EDataPaged;
  1090 		if (dataPaging == KRomImageFlagDataUnpaged)
  1091 			iFlags |= EDataUnpaged;
  1092 		}
  1093 	else if (iHeader)
  1094 		{
  1095 		TUint dataPaging = iHeader->iFlags & KImageDataPagingMask;
  1096 		if (dataPaging == KImageDataPagingMask)
  1097 			RETURN_FAILURE(KErrCorrupt);
  1098 		if (dataPaging == KImageDataPaged)
  1099 			iFlags |= EDataPaged;
  1100 		if (dataPaging == KImageDataUnpaged)
  1101 			iFlags |= EDataUnpaged;
  1102 		}
  1103 		
  1104 	r=E32Loader::ProcessCreate(*this, aReq.iCmd);
  1105 	__IF_DEBUG(Printf("Done E32Loader::ProcessCreate %d",r));
  1106 	if (r!=KErrNone)
  1107 		{
  1108 		return r;
  1109 		}
  1110 #ifdef _DEBUG
  1111 	ProcessCreated = ETrue;
  1112 #endif
  1113 	iClientProcessHandle=iProcessHandle;
  1114 	if (!iAlreadyLoaded)
  1115 		{
  1116 		gExeCodeSeg=iHandle;	// implicitly linked DLLs must load into the new process
  1117 		gExeAttr=iAttr;
  1118 		if (!iRomImageHeader)
  1119 			r=LoadToRam();
  1120 		if (r==KErrNone)
  1121 			r=ProcessImports();	// this sets up gLoadeePath
  1122 		}
  1123 	// transfers ownership of clamp handle to codeseg; nulls handle if successful
  1124 	if (r==KErrNone)
  1125 		{
  1126 		r=E32Loader::ProcessLoaded(*this);
  1127 		if ((r==KErrNone) && iUseCodePaging)
  1128 			{
  1129 			iFileClamp.iCookie[0]=0;// null handle to indicate 
  1130 			iFileClamp.iCookie[1]=0;// transfer of ownership of clamp handle to proc's codeseg
  1131 			}
  1132 		}
  1133 	__IF_DEBUG(Printf("Done E32Image::LoadProcess %d",r));
  1134 	return r;
  1135 	}
  1136 
  1137 // Load a code segment, plus all imports if main loadee
  1138 TInt E32Image::LoadCodeSeg(const RLdrReq& aReq)
  1139 	{
  1140 	__LDRTRACE(aReq.Dump(">E32Image::LoadCodeSeg"));
  1141 
  1142 #ifdef __X86__
  1143 	if (iMain==this && iClientProcessHandle)
  1144 		{
  1145 		RProcess p;
  1146 		p.SetHandle(iClientProcessHandle);
  1147 		TFileName f(p.FileName());
  1148 		if (f.Length()>=2 && f[1]==':')
  1149 			{
  1150 			TInt d = f[0];
  1151 			if (d=='a' || d=='A')
  1152 				UseFloppy = EDriveA;
  1153 			else if (d=='b' || d=='B')
  1154 				UseFloppy = EDriveB;
  1155 			}
  1156 		}
  1157 #endif
  1158 
  1159 	RImageFinder finder;
  1160 	TInt r = finder.Set(aReq);
  1161 	if (r == KErrNone)
  1162 		r = finder.Search();
  1163 	if (r!=KErrNone)
  1164 		{
  1165 		finder.Close();
  1166 		return r;
  1167 		}
  1168 	return DoLoadCodeSeg(aReq, finder);
  1169 	}
  1170 
  1171 // Load a code segment, plus all imports if main loadee
  1172 TInt E32Image::DoLoadCodeSeg(const RLdrReq& aReq, RImageFinder& aFinder)
  1173 	{
  1174 	__LDRTRACE(aReq.Dump(">E32Image::DoLoadCodeSeg"));
  1175 
  1176 	TInt r = Construct(aFinder);	// needs to find it if it's already loaded
  1177 	aFinder.Close();
  1178 	if (r!=KErrNone)
  1179 		{
  1180 		return r;
  1181 		}
  1182 	__IF_DEBUG(Printf("epv=%x, fep=%x, codesize=%x, textsize=%x, uid3=%x",iEntryPtVeneer,iFileEntryPoint,iCodeSize,iTextSize,iUids[2]));
  1183 	__IF_DEBUG(Printf("attr=%08x, gExeAttr=%08x",iAttr,gExeAttr));
  1184 
  1185 	// If EXE and not main loadee, EXE code segment must be the same as the client process or newly loaded process
  1186 	if (gExeCodeSeg && !iIsDll && iMain!=this && iHandle!=gExeCodeSeg)
  1187 		return KErrNotSupported;
  1188 
  1189 	// If DLL and main loadee, ABI must match the process
  1190 	if (iIsDll && iMain==this && (iAttr & ECodeSegAttABIMask)!=(gExeAttr & ECodeSegAttABIMask) )
  1191 		return KErrNotSupported;
  1192 
  1193 	// code segment already loaded
  1194 	if (iAlreadyLoaded || (iMain!=this && AlwaysLoaded()) )
  1195 		return KErrNone;
  1196 
  1197 	__IF_DEBUG(Printf("CodeSeg create"));
  1198 	r=E32Loader::CodeSegCreate(*this);
  1199 	if (r!=KErrNone)
  1200 		return r;
  1201 	
  1202 	iCloseCodeSeg=iHandle;	// so new code segment is removed if the load fails
  1203 	if (!iRomImageHeader)
  1204 		r=LoadToRam();
  1205 	if (r==KErrNone)
  1206 		{
  1207 		iCloseCodeSeg=NULL;
  1208 		if (iMain==this)
  1209 			{
  1210 			r=ProcessImports();	// this sets up gLoadeePath
  1211 			// transfers ownership of clamp handle to codeseg; nulls handle if successful
  1212 			if (r==KErrNone)
  1213 				{
  1214 				r=E32Loader::CodeSegLoaded(*this);
  1215 				if ((r==KErrNone) && iUseCodePaging)
  1216 					{
  1217 					iFileClamp.iCookie[0]=0;// null handle to indicate 
  1218 					iFileClamp.iCookie[1]=0;// transfer of ownership of clamp handle to codeseg
  1219 					}
  1220 				}
  1221 			}
  1222 		}
  1223 
  1224 	__IF_DEBUG(Printf("<DoLoadCodeSeg, r=%d, iIsDll=%d",r,iIsDll));
  1225 	return r;
  1226 	}
  1227 
  1228 // Load a ROM XIP code segment as part of another load
  1229 TInt E32Image::DoLoadCodeSeg(const TRomImageHeader& a)
  1230 	{
  1231 	__IF_DEBUG(Printf("E32Image::DoLoadCodeSeg ROM XIP @%08x",&a));
  1232 	
  1233 	Construct(a);
  1234 	if (AlwaysLoaded())
  1235 		{
  1236 		GetRomFileName();
  1237 		return KErrNone;
  1238 		}
  1239 	TInt r=CheckRomXIPAlreadyLoaded();
  1240 	if (r!=KErrNone || iAlreadyLoaded)
  1241 		{
  1242 		return r;
  1243 		}
  1244 	GetRomFileName();
  1245 	r=E32Loader::CodeSegCreate(*this);
  1246 
  1247 	__IF_DEBUG(Printf("<DoLoadCodeSeg, r=%d",r));
  1248 	return r;
  1249 	}
  1250 
  1251 /******************************************************************************
  1252  * EPOC specific E32Image functions
  1253  ******************************************************************************/
  1254 
  1255 /**
  1256 Construct an image object which represents an XIP ROM executable.
  1257 */
  1258 void E32Image::Construct(const TRomImageHeader& a)
  1259 	{
  1260 	__IF_DEBUG(Printf("E32Image::Construct ROM %08x",&a));
  1261 
  1262 	iRomImageHeader = &a;
  1263 	iUids = *(const TUidType*)&a.iUid1;
  1264 	iS = a.iS;
  1265 	iCodeSize = a.iCodeSize;
  1266 	iTextSize = a.iTextSize;
  1267 	iDataSize = a.iDataSize;
  1268 	iBssSize = a.iBssSize;
  1269 	iTotalDataSize = a.iTotalDataSize;
  1270 	iEntryPtVeneer = 0;
  1271 	iFileEntryPoint = a.iEntryPoint;
  1272 	iDepCount = a.iDllRefTable ? a.iDllRefTable->iNumberOfEntries : 0;
  1273 	iExportDir = a.iExportDir;
  1274 	iExportDirCount = a.iExportDirCount;
  1275 	iCodeLoadAddress = (TUint32)&a;
  1276 	iDataRunAddress = a.iDataBssLinearBase;	// for fixed processes
  1277 	iHeapSizeMin = a.iHeapSizeMin;
  1278 	iHeapSizeMax = a.iHeapSizeMax;
  1279 	iStackSize = a.iStackSize;
  1280 	iPriority = a.iPriority;
  1281 	iIsDll = (a.iFlags & KImageDll)!=0;
  1282 	if(iExportDirCount)
  1283 		iExportDirLoad = iExportDir;
  1284 
  1285 	// setup attributes...
  1286 	iAttr &= ~(ECodeSegAttKernel|ECodeSegAttGlobal|ECodeSegAttFixed|ECodeSegAttABIMask|ECodeSegAttNmdExpData);
  1287 	if(a.iFlags&KRomImageFlagsKernelMask)
  1288 		iAttr |= ECodeSegAttKernel;
  1289 	else
  1290 		iAttr |= ECodeSegAttGlobal;
  1291 	if(a.iFlags&KRomImageFlagFixedAddressExe)
  1292 		iAttr |= ECodeSegAttFixed;
  1293 	iAttr |= (a.iFlags & KRomImageABIMask);
  1294 	if(a.iFlags&KRomImageNmdExpData)
  1295 		iAttr |= ECodeSegAttNmdExpData;
  1296 	if(a.iFlags&KRomImageSMPSafe)
  1297 		iAttr |= ECodeSegAttSMPSafe;
  1298 	
  1299 	iExceptionDescriptor = a.iExceptionDescriptor;
  1300 	}
  1301 
  1302 
  1303 TBool E32Image::AlwaysLoaded()
  1304 	{
  1305 	// If loaded from ROM and EXE or DLL with no static data or extension or variant, don't need code segment
  1306 	TBool r=EFalse;
  1307 	__IF_DEBUG(Printf(">E32Image::AlwaysLoaded %08x",iRomImageHeader));
  1308 	if (iRomImageHeader)
  1309 		{
  1310 		if (iIsDll && (iRomImageHeader->iFlags & KRomImageFlagDataPresent)==0)
  1311 			r=ETrue;
  1312 		}
  1313 	__IF_DEBUG(Printf("<E32Image::AlwaysLoaded %x",r));
  1314 	return r;
  1315 	}
  1316 
  1317 
  1318 void E32Image::GetRomFileName()
  1319 	{
  1320 	TBuf8<KMaxFileName> fn = _S8("z:\\");
  1321 	TFileNameInfo fni;
  1322 	TPtr8 path_and_name(((TText8*)fn.Ptr())+3, 0, KMaxFileName-3);
  1323 	const TRomDir& rootdir = *(const TRomDir*)UserSvr::RomRootDirectoryAddress();
  1324 	if (!TraverseDirs(rootdir, iRomImageHeader, path_and_name))
  1325 		*(const TAny**)1=iRomImageHeader;	// DIE!
  1326 	fn.SetLength(path_and_name.Length()+3);
  1327 	fni.Set(fn, 0);
  1328 	iFileName.Zero();
  1329 	fni.GetName(iFileName, TFileNameInfo::EIncludeDrivePathBaseExt);
  1330 	if (fni.VerLen())
  1331 		iAttr |= ECodeSegAttExpVer;
  1332 	iRootNameOffset = fni.iBasePos;
  1333 	iRootNameLength = fni.BaseLen() + fni.ExtLen();
  1334 	iExtOffset = iFileName.Length() - fni.ExtLen();
  1335 	__IF_DEBUG(Printf("GetRomFileName(%08x)->%S,%d,%d,%d Attr %08x",iRomImageHeader,&iFileName,iRootNameOffset,iRootNameLength,iExtOffset,iAttr));
  1336 	}
  1337 
  1338 
  1339 /**
  1340 Starting from aDir, search for XIP executable specified by aHdr.
  1341 If found, return true and set aName to file path and name, (will cause descriptor panics if max size of aName isn't big enough.)
  1342 If not found, return false.
  1343 */
  1344 TBool E32Image::TraverseDirs(const TRomDir& aDir, const TRomImageHeader* aHdr, TDes8& aName)
  1345 	{
  1346 	const TRomEntry* pE=&aDir.iEntry;
  1347 	const TRomEntry* pEnd=(const TRomEntry*)((TUint8*)pE+aDir.iSize);
  1348 	while(pE<pEnd)
  1349 		{
  1350 		if ( (pE->iAtt & KEntryAttXIP) && (pE->iAddressLin==(TLinAddr)aHdr) )
  1351 			{
  1352 			// ROM XIP file found
  1353 			aName.Copy(TPtrC16((const TText*)pE->iName, pE->iNameLength));
  1354 			return ETrue;
  1355 			}
  1356 		if (pE->iAtt & KEntryAttDir)
  1357 			{
  1358 			// subdirectory found
  1359 			const TRomDir& subdir = *(const TRomDir*)pE->iAddressLin;
  1360 			TText8* p = (TText8*)aName.Ptr();
  1361 			TInt m = aName.MaxLength();
  1362 			TInt nl = pE->iNameLength;
  1363 			TPtr8 ptr(p+nl+1, 0, m-nl-1);
  1364 			if (TraverseDirs(subdir, aHdr, ptr))
  1365 				{
  1366 				// match found in subdirectory
  1367 				aName.SetLength(ptr.Length()+nl+1);
  1368 				const TText* s = (const TText*)pE->iName;
  1369 				p[nl]='\\';
  1370 				while (nl--)
  1371 					*p++ = (TText8)*s++;
  1372 				return ETrue;
  1373 				}
  1374 			}
  1375 		TInt entry_size = KRomEntrySize + pE->iNameLength*sizeof(TText);
  1376 		entry_size = (entry_size+sizeof(TInt)-1)&~(sizeof(TInt)-1);
  1377 		pE=(const TRomEntry*)((TUint8*)pE+entry_size);
  1378 		}
  1379 	return EFalse;
  1380 	}
  1381 
  1382 
  1383 /**
  1384 Read data from a file.
  1385 */
  1386 TInt FileRead(RFile& aFile, TUint8* aDest, TInt aSize)
  1387 	{
  1388 	TPtr8 p(aDest,aSize,aSize);
  1389 	TInt r = aFile.Read(p,aSize);
  1390 	if(r==KErrNone && p.Size()!=aSize)
  1391 		RETURN_FAILURE(KErrCorrupt);
  1392 	return r;
  1393 	}
  1394 
  1395 
  1396 /**
  1397 Construct a new image header by reading a file. File must not be XIP.
  1398 */
  1399 TInt E32ImageHeader::New(E32ImageHeader*& aHdr, RFile& aFile)
  1400 	{
  1401 	aHdr = NULL;
  1402 
  1403 	TInt fileSize;
  1404 	TInt r = aFile.Size(fileSize);
  1405 	if(r!=KErrNone)
  1406 		return r;
  1407 
  1408 	E32ImageHeaderV tempHeader;
  1409 	r = FileRead(aFile, (TUint8*)&tempHeader, sizeof(tempHeader));
  1410 	if(r!=KErrNone)
  1411 		return r;
  1412 
  1413 	TUint headerSize = tempHeader.TotalSize();
  1414 	if(headerSize<sizeof(tempHeader) || headerSize>TUint(KMaxHeaderSize))
  1415 		RETURN_FAILURE(KErrCorrupt);
  1416 
  1417 	E32ImageHeaderV* header = (E32ImageHeaderV*)User::Alloc(headerSize);
  1418 	if(!header)
  1419 		return KErrNoMemory;
  1420 
  1421 	wordmove(header, &tempHeader, sizeof(tempHeader));
  1422 	if(headerSize>sizeof(tempHeader))
  1423 		r = FileRead(aFile, ((TUint8*)header)+sizeof(tempHeader), headerSize-sizeof(tempHeader));
  1424 
  1425 	if(r==KErrNone)
  1426 		r = header->ValidateAndAdjust(fileSize);
  1427 
  1428 	if(r==KErrNone)
  1429 		aHdr = header;
  1430 	else
  1431 		delete header;
  1432 
  1433 	return r;
  1434 	}
  1435 
  1436 
  1437 /**
  1438 Construct a new image header using data from the supplied buffer.
  1439 */
  1440 TInt E32ImageHeader::New(E32ImageHeader*& aHdr, TUint8* aFileData, TUint32 aFileSize)
  1441 	{
  1442 	aHdr = NULL;
  1443 
  1444 	E32ImageHeaderV& tempHeader = *(E32ImageHeaderV*)aFileData;
  1445 
  1446 	if(aFileSize<sizeof(tempHeader))
  1447 		RETURN_FAILURE(KErrCorrupt); // too small to contain a header
  1448 
  1449 	TUint headerSize = tempHeader.TotalSize();
  1450 	if(headerSize<sizeof(tempHeader) || headerSize>TUint(KMaxHeaderSize))
  1451 		RETURN_FAILURE(KErrCorrupt);
  1452 	if(headerSize>aFileSize)
  1453 		RETURN_FAILURE(KErrCorrupt);
  1454 
  1455 	E32ImageHeaderV* header = (E32ImageHeaderV*)User::Alloc(headerSize);
  1456 	if(!header)
  1457 		return KErrNoMemory;
  1458 
  1459 	wordmove(header, &tempHeader, headerSize);
  1460 
  1461 	TInt r = header->ValidateAndAdjust(aFileSize);
  1462 	if(r==KErrNone)
  1463 		aHdr = header;
  1464 	else
  1465 		delete header;
  1466 
  1467 	return r;
  1468 	}
  1469 
  1470 
  1471 /**
  1472 Validate header, then adjust:
  1473 - iUncompressedSize to contain size of data even when file is not compressed.
  1474 - Platform security capability to include all disabled capabilities and exclude invalid ones.
  1475 
  1476 @param aFileSize Total size of the file containing the image data.
  1477 */
  1478 TInt E32ImageHeaderV::ValidateAndAdjust(TUint32 aFileSize)
  1479 	{
  1480 	// check header is valid...
  1481 	TUint32 uncompressedSize;
  1482 	TInt r = ValidateHeader(aFileSize,uncompressedSize);
  1483 	if(r!=KErrNone)
  1484 		return r;
  1485 
  1486 	// set size of data when uncompressed...
  1487 	iUncompressedSize = uncompressedSize;
  1488 
  1489 	// override capabilities in image to conform to system wide configuration...
  1490 	for(TInt i=0; i<SCapabilitySet::ENCapW; i++)
  1491 		{
  1492 		iS.iCaps[i] |= DisabledCapabilities[i];
  1493 		iS.iCaps[i] &= AllCapabilities[i];
  1494 		}
  1495 
  1496 	return KErrNone;
  1497 	}
  1498 
  1499 
  1500 TInt E32Image::Construct(RImageFinder& aFinder)
  1501 	{
  1502 	__IF_DEBUG(Printf("E32Image::iMain=%08x", iMain));
  1503 	__LDRTRACE(aFinder.Dump(">E32Image::Construct", 0));
  1504 	__ASSERT_ALWAYS(aFinder.iNewValid, User::Panic(KLitFinderInconsistent, 0));
  1505 
  1506 	// fallback security check to ensure we don't try and load an executable from an insecure location...
  1507 	if(PlatSec::ConfigSetting(PlatSec::EPlatSecEnforceSysBin))
  1508 		{
  1509 		__ASSERT_ALWAYS(aFinder.iNewFileName.Length()>=11, User::Panic(KLitSysBinError, 0));
  1510 		__ASSERT_ALWAYS(KSysBin().CompareF(TPtrC8(aFinder.iNewFileName.Ptr()+1,10))==0, User::Panic(KLitSysBinError, 1));
  1511 		}
  1512 
  1513 	TInt r = KErrNone;
  1514 
  1515 	// setup file name info...
  1516 	iFileName.Copy(aFinder.iNewFileName);
  1517 	TFileNameInfo fi;
  1518 	fi.Set(iFileName, 0);
  1519 	iRootNameOffset = fi.iBasePos;
  1520 	iRootNameLength = fi.iLen - fi.iBasePos;
  1521 	iExtOffset = fi.iExtPos;
  1522 
  1523 	// setup version...
  1524 	iAttr |= aFinder.iNew.iAttr & ECodeSegAttExpVer;
  1525 	iModuleVersion = aFinder.iNew.iModuleVersion;
  1526 
  1527 	if(aFinder.iNew.iRomImageHeader)
  1528 		{
  1529 		// we're 'loading' an XIP executable from ROM...
  1530 		Construct(*aFinder.iNew.iRomImageHeader);
  1531 		if(!AlwaysLoaded() || iMain==this)
  1532 			r = CheckRomXIPAlreadyLoaded();
  1533 		return r;
  1534 		}
  1535 
  1536 	// setup more image info...
  1537 	iAttr |= aFinder.iNew.iAttr & (ECodeSegAttFixed|ECodeSegAttABIMask|ECodeSegAttNmdExpData);
  1538 	iUids = *(const TUidType*)&aFinder.iNew.iUid;
  1539 	iIsDll = !(iUids[0].iUid == KExecutableImageUidValue);
  1540 	iS = aFinder.iNew.iS;
  1541 
  1542 	// check if executable has already been loaded...
  1543 	r = CheckAlreadyLoaded();
  1544 	if(r!=KErrNone)
  1545 		return r;
  1546 
  1547 	// if we are going to need to load it...
  1548 	if(!iAlreadyLoaded || !iIsDll)
  1549 		{
  1550 		if (aFinder.iNew.iNeedHashCheck)
  1551 			{
  1552 			// we need to check the file hash; the check in RImageFinder::Try
  1553 			// was skipped based on the cache. If it fails here, though, someone
  1554 			// is tampering with us and we can just fail the load.
  1555 			TRAP(r,aFinder.CompareHashL(aFinder.iNew, fi.DriveAndPath()));
  1556 			if (r != KErrNone)
  1557 				return r;
  1558 			}
  1559 
  1560 		if(aFinder.iNew.iFileData)
  1561 			{
  1562 			// take ownership of the file data aFinder has already read in...
  1563 			iFileData = aFinder.iNew.iFileData;
  1564 			aFinder.iNew.iFileData = NULL;
  1565 			iFileSize = aFinder.iNew.iFileSize;
  1566 			}
  1567 		else if(aFinder.iNew.FileOpened())
  1568 			{
  1569 			// take ownership of the file handle that aFinder has already opened...
  1570 			iFile = aFinder.iNew.iFile;
  1571 			memclr(&aFinder.iNew.iFile, sizeof(RFile));
  1572 			}
  1573 		else
  1574 			{
  1575 			// no resource obtained from aFinder, so create a file handle for ourselves...
  1576 			r = OpenFile();
  1577 			if(r!=KErrNone)
  1578 				return r;
  1579 			}
  1580 
  1581 		// take ownership of header...
  1582 		iHeader = aFinder.iNew.iHeader;
  1583 		aFinder.iNew.iHeader = NULL;
  1584 
  1585 		// if there wast't a header, then create one now...
  1586 		if(!iHeader)
  1587 			{
  1588 			if(iFileData)
  1589 				r = E32ImageHeader::New(iHeader, iFileData, iFileSize);
  1590 			else
  1591 				r = E32ImageHeader::New(iHeader, iFile);
  1592 			if(r!=KErrNone)
  1593 				return r;
  1594 			}
  1595 
  1596 		// setup info needed for process creation...
  1597 		iHeapSizeMin = iHeader->iHeapSizeMin;
  1598 		iHeapSizeMax = iHeader->iHeapSizeMax;
  1599 		iStackSize = iHeader->iStackSize;
  1600 		iPriority = iHeader->ProcessPriority();
  1601 		}
  1602 
  1603 	// if already loaded...
  1604 	if(iAlreadyLoaded)
  1605 		return KErrNone; // nothing more to do
  1606 
  1607 	// setup info needed to load an executable...
  1608 	iDepCount = iHeader->iDllRefTableCount;
  1609 	iExportDirCount = iHeader->iExportDirCount;
  1610 	iExportDir = iHeader->iExportDirOffset-iHeader->iCodeOffset;
  1611 	iTextSize = iHeader->iTextSize;
  1612 	iCodeSize = iHeader->iCodeSize;
  1613 	__IF_DEBUG(Printf("Code + const %x",iCodeSize));
  1614 	iDataSize = iHeader->iDataSize;
  1615 	__IF_DEBUG(Printf("Data %x",iDataSize));
  1616 	iBssSize = iHeader->iBssSize;
  1617 	__IF_DEBUG(Printf("Bss %x",iBssSize));
  1618 	iTotalDataSize = iDataSize+iBssSize;
  1619 
  1620 	iFileEntryPoint = iHeader->iEntryPoint;	// just an offset at this stage
  1621 	iEntryPtVeneer = 0;
  1622 	iExceptionDescriptor = iHeader->ExceptionDescriptor();
  1623 	if(iHeader->iExportDirOffset)
  1624 		iExportDirLoad = iExportDir;		// only set this if not already loaded
  1625 
  1626 	// initialise the SMP safe flag from the image header
  1627 	// this will get cleared during ProcessImports if any import is not SMP safe
  1628 	if(iHeader->iFlags & KImageSMPSafe)
  1629 		iAttr |= ECodeSegAttSMPSafe;
  1630 	else
  1631 		{
  1632 		__IF_DEBUG(Printf("%S is not marked SMP safe", &iFileName));
  1633 		iAttr &= ~ECodeSegAttSMPSafe;
  1634 		}
  1635 
  1636 	// check if executable is to be demand paged...
  1637 	r = ShouldBeCodePaged(iUseCodePaging);
  1638 	__IF_DEBUG(Printf("ShouldBeCodePaged r=%d,iUseCodePaging=%d", r, iUseCodePaging));
  1639 	if(iUseCodePaging==EFalse || r!=KErrNone)
  1640 		return r;
  1641 
  1642 	// image needs demand paging, create the additional information needed for this...
  1643 
  1644 	// read compression info...
  1645 	iCompressionType = iHeader->iCompressionType;
  1646 	r = LoadCompressionData();
  1647 	if(r==KErrNotSupported)
  1648 		{
  1649 		// Compression type not supported, so just load executable as normal, (without paging)...
  1650 		iUseCodePaging = EFalse;
  1651 		return KErrNone;
  1652 		}
  1653 	else if (r!=KErrNone)
  1654 		return r;
  1655 
  1656 	// clamp file so it doesn't get modified whilst it is being demand paged...
  1657 	r = iFileClamp.Clamp(iFile);
  1658 	// The clamp API will return KErrNotSupported if the media is removable: 
  1659 	// this implies that paging is not possible but the binary can still be loaded
  1660 	if (r != KErrNone)
  1661 		{
  1662 		iUseCodePaging = EFalse;
  1663 		return r == KErrNotSupported ? KErrNone : r;
  1664 		}
  1665 
  1666 	// get blockmap data which indicates location of media where file contents are stored...
  1667 	r = BuildCodeBlockMap();
  1668 	__IF_DEBUG(Printf("BuildCodeBlockMap r=%d", r));
  1669 	if(r==KErrNotSupported)
  1670 		{
  1671 		// media doesn't support demand paging, so just load executable as normal, (without paging)...
  1672 		iUseCodePaging = EFalse;
  1673 		iFileClamp.Close(gTheLoaderFs);
  1674 		r = KErrNone;
  1675 		}
  1676 
  1677 	return r;
  1678 	}
  1679 
  1680 
  1681 TInt E32Image::CheckRomXIPAlreadyLoaded()
  1682 	{
  1683 	__IF_DEBUG(Printf("ROM XIP %08x CheckAlreadyLoaded",iRomImageHeader));
  1684 	TFindCodeSeg find;
  1685 	find.iRomImgHdr=iRomImageHeader;
  1686 	E32Loader::CodeSegDeferDeletes();
  1687 	TAny* h=NULL;
  1688 	TInt r=KErrNone;
  1689 	E32Loader::CodeSegNext(h, find);
  1690 	if (h)
  1691 		{
  1692 		iHandle=h;
  1693 		r=E32Loader::CodeSegOpen(h, iClientProcessHandle);
  1694 		if (r==KErrNone)
  1695 			E32Loader::CodeSegInfo(iHandle, *this);
  1696 		}
  1697 	E32Loader::CodeSegEndDeferDeletes();
  1698 	if (iHandle && r==KErrNone)
  1699 		{
  1700 		iAlreadyLoaded=ETrue;
  1701 		__IF_DEBUG(Printf("ROM XIP %08x already loaded", iHandle));
  1702 		}
  1703 	__IF_DEBUG(Printf("ROM XIP CheckAlreadyLoaded returns %d",r));
  1704 	return r;
  1705 	}
  1706 
  1707 
  1708 /**
  1709 Read the E32Image file into its code and data chunks, relocating them
  1710 as necessary.
  1711 Create a dll reference table from the names of dlls referenced.
  1712 Fix up the import address table and the export table for real addresses.
  1713 */
  1714 TInt E32Image::LoadToRam()
  1715 	{
  1716 	__IF_DEBUG(Printf("E32Image::LoadToRam %S",&iFileName));
  1717 
  1718 	// offset of data after code which will be erad into iRestOfFileData...
  1719 	iConversionOffset = iHeader->iCodeOffset + iHeader->iCodeSize;
  1720 
  1721 	// calculate sizes...
  1722 	TUint totalSize = ((E32ImageHeaderV*)iHeader)->iUncompressedSize;
  1723 	TUint remainder = totalSize-iConversionOffset;
  1724 	if(remainder>totalSize)
  1725 		RETURN_FAILURE(KErrCorrupt); // Fuzzer can't trigger this because header validation prevents it
  1726 
  1727 	iRestOfFileData = (TUint8*)User::Alloc(remainder);
  1728 	if(!iRestOfFileData)
  1729 		return KErrNoMemory;
  1730 	iRestOfFileSize = remainder;
  1731 
  1732 	TInt r = LoadFile(); // Read everything in
  1733 	if(r!=KErrNone)
  1734 		return r;
  1735 
  1736 	__IF_DEBUG(Printf("iHeader->iCodeRelocOffset %d",iHeader->iCodeRelocOffset));
  1737 	r = ((E32ImageHeaderV*)iHeader)->ValidateRelocations(iRestOfFileData,iRestOfFileSize,iHeader->iCodeRelocOffset,iHeader->iCodeSize,iCodeRelocSection);
  1738 	if(r!=KErrNone)
  1739 		return r;
  1740 
  1741 	__IF_DEBUG(Printf("iHeader->iDataRelocOffset %d",iHeader->iDataRelocOffset));
  1742 	r = ((E32ImageHeaderV*)iHeader)->ValidateRelocations(iRestOfFileData,iRestOfFileSize,iHeader->iDataRelocOffset,iHeader->iDataSize,iDataRelocSection);
  1743 	if(r!=KErrNone)
  1744 		return r;
  1745 		
  1746 	iCodeDelta = iCodeRunAddress-iHeader->iCodeBase;
  1747 	iDataDelta = iDataRunAddress-iHeader->iDataBase;
  1748 	
  1749 	if(r==KErrNone)
  1750 	   	r = RelocateCode();
  1751 	if(r==KErrNone)
  1752 		r = LoadAndRelocateData();
  1753 	if(r==KErrNone)
  1754     	r = ReadImportData();
  1755 
  1756 	return r;
  1757 	}
  1758 
  1759 
  1760 TInt E32Image::ShouldBeCodePaged(TBool& aPage)
  1761 /**
  1762 	Determine whether this binary should be paged.  Some of this
  1763 	function is unimplemented because it requires the media pageable
  1764 	attribute
  1765 
  1766 	@param	aPage			On success, this variable is set to
  1767 							whether the binary should be paged.  Its
  1768 							value is undefined if the return code is
  1769 							not KErrNone.
  1770 	@return					Symbian OS error code.
  1771 
  1772 	See S3.1.3.2 of PREQ1110 Design Sketch.
  1773  */
  1774 	{
  1775 	aPage = EFalse;
  1776 
  1777 	// kernel and global dlls can't be paged...
  1778 	if(iAttr&(ECodeSegAttKernel|ECodeSegAttGlobal))
  1779 		return KErrNone;
  1780 
  1781 	// 1. if paging policy is NOPAGING then executable is unpaged
  1782 	TUint32 policy = E32Loader::PagingPolicy();
  1783 
  1784 	__IF_DEBUG(Printf("sbcp,policy=0x%x", policy));
  1785 	if (policy == EKernelConfigCodePagingPolicyNoPaging)
  1786 		return KErrNone;
  1787 
  1788 	// 2. if executable is on media without Pageable Media Attribute then unpaged
  1789 	// 3. if executable is on removable media then unpaged
  1790 	//	both superseded by the BlockMap API
  1791 
  1792 	// 3a. if executable has already been loaded into RAM for tamperproofing then
  1793 	//     it can't be paged
  1794 	if (iFileData != NULL)
  1795 		return KErrNone;
  1796 
  1797 	// 4. if not compressed with bytepair or uncompressed then unpaged
  1798 	__IF_DEBUG(Printf("sbcp,iHeader=0x%08x", iHeader));
  1799 	TUint32 comp = iHeader->CompressionType();
  1800 	__IF_DEBUG(Printf("sbcp,comp=0x%x", comp));
  1801 	if (comp != KUidCompressionBytePair && comp != KFormatNotCompressed)
  1802 		return KErrNone;
  1803 
  1804 	aPage = ETrue;
  1805 
  1806 	// 5. if policy is ALWAYSPAGE then page
  1807 	if (policy == EKernelConfigCodePagingPolicyAlwaysPage)
  1808 		return KErrNone;
  1809 
  1810 	// 6. 
  1811 	TUint KPagedMask = (KImageCodePaged | KImageCodeUnpaged);
  1812 	TUint pagedFlags = iHeader->iFlags & KPagedMask;
  1813 	__IF_DEBUG(Printf("sbcp,iHeader->iFlags=0x%x,pagedFlags=0x%x", iHeader->iFlags, pagedFlags));
  1814 
  1815 	// if KImageCodePaged and KImageCodeUnpaged flags present then corrupt
  1816 	if (pagedFlags == KPagedMask)
  1817 		RETURN_FAILURE(KErrCorrupt);
  1818 
  1819 	// if KImageCodePaged set in executable then page
  1820 	if (pagedFlags == KImageCodePaged)
  1821 		return KErrNone;
  1822 
  1823 	// if KImageCodeUnpaged set in executable then do not page
  1824 	if (pagedFlags == KImageCodeUnpaged)
  1825 		{
  1826 		aPage = EFalse;
  1827 		return KErrNone;
  1828 		}
  1829 
  1830 	// 7. otherwise (neither paged nor unpaged set) use paging policy
  1831 
  1832 	// policy must be EKernelConfigCodePagingPolicyDefaultUnpaged or EKernelConfigCodePagingPolicyDefaultPaged
  1833 	aPage = (policy == EKernelConfigCodePagingPolicyDefaultPaged);
  1834 	return KErrNone;
  1835 	}
  1836 
  1837 TInt E32Image::BuildCodeBlockMap()
  1838 /**
  1839 	Use the block map API to build an array of TBlockMapInfo
  1840 	objects which the kernel can use to page in code as required.
  1841 
  1842 	@return					Symbian OS error code.  KErrNotSupported means the
  1843 							Block Map functionality does not support paging from
  1844 							the binary's location.
  1845  */
  1846 	{
  1847 	__IF_DEBUG(Printf("BuildCodeBlockMap,iCodeStartInFile=%d,iCodeLengthInFile=%d", iCodeStartInFile, iCodeLengthInFile));
  1848 
  1849 	__ASSERT_DEBUG(iUseCodePaging, Panic(EBcbmNotCodePaged));
  1850 
  1851 	// do nothing if no code section
  1852 	if (iCodeLengthInFile == 0)
  1853 		return KErrNone;
  1854 
  1855 	// RFile::BlockMap populates an instance of this object.  Need to
  1856 	// retain information such as granularity which applies to all entries.
  1857 	SBlockMapInfo bmi;
  1858 
  1859 	TInt curEntriesSize = 0;
  1860 	TUint8* entries8 = 0;		// points to heap cell containing TBlockMapEntryBase array
  1861 
  1862 	TInt64 bmPos = 0;
  1863 	TInt64 bmEnd = iCodeStartInFile + iCodeLengthInFile;
  1864 	TInt r;
  1865 	do
  1866 		{
  1867 		__IF_DEBUG(Printf("lfbpu:BlockMap,in,bmPos=%ld,bmEnd=%ld", bmPos, bmEnd));
  1868 		r = iFile.BlockMap(bmi, bmPos, bmEnd, EBlockMapUsagePaging);	// updates bmPos to end of mapped range
  1869 		__IF_DEBUG(
  1870 			Printf("lfbpu:BlockMap,out,r=%d,bmPos=%ld,bmEnd=%ld,maplen=%d(%d)",
  1871 			r, bmPos, bmEnd, bmi.iMap.Length(), bmi.iMap.Length() / sizeof(TBlockMapEntryBase)));
  1872 		__IF_DEBUG(
  1873 			Printf("lfbpu:BlockMap,out,iBlockGranularity=%u,iBlockStartOffset=%u,iStartBlockAddress=%ld,iLocalDriveNumber=%d",
  1874 			bmi.iBlockGranularity, bmi.iBlockStartOffset, bmi.iStartBlockAddress, bmi.iLocalDriveNumber));
  1875 		if (r != KErrNone && r != KErrCompletion)
  1876 			break;
  1877 
  1878 		// Copy info the first time round as this gets overwritten on subsequent passes
  1879 		if (curEntriesSize == 0)
  1880 			iCodeBlockMapCommon = bmi;	// slices the SBlockMapCommon subclass data
  1881 		
  1882 		// grow the buffer which contains the entries
  1883 		TInt newEntriesSize = bmi.iMap.Length();
  1884 		TInt newArraySize = curEntriesSize + newEntriesSize;
  1885 		TUint8* newEntries8 = (TUint8*) User::ReAlloc(entries8, newArraySize);
  1886 		if (newEntries8 == 0)
  1887 			{
  1888 			r = KErrNoMemory;
  1889 			break;
  1890 			}
  1891 		entries8 = newEntries8;
  1892 
  1893 #ifdef _DEBUG
  1894 		// dump the newly-returned block entries
  1895 		for (TInt i = 0; i < newEntriesSize; i += sizeof(TBlockMapEntryBase))
  1896 			{
  1897 			const TBlockMapEntryBase& bme = *reinterpret_cast<const TBlockMapEntryBase*>(bmi.iMap.Ptr() + i);
  1898 			__IF_DEBUG(Printf("lfbpu:bme,iNumberOfBlocks=%d,iStartBlock=%d", bme.iNumberOfBlocks, bme.iStartBlock));
  1899 			}
  1900 #endif
  1901 
  1902 		// append the new entries to the array.
  1903 		Mem::Copy(entries8 + curEntriesSize, bmi.iMap.Ptr(), newEntriesSize);
  1904 		curEntriesSize = newArraySize;
  1905 		} while (r != KErrCompletion);
  1906 
  1907 	// r == KErrCompletion when mapped code section range
  1908 	if (r != KErrCompletion)
  1909 		{
  1910 		User::Free(entries8);
  1911 		return r;
  1912 		}
  1913 	
  1914 #ifdef _DEBUG
  1915 	// dump the block map table
  1916 	__IF_DEBUG(Printf("lfbpu:endbme,r=%d,curEntriesSize=%d", r, curEntriesSize));
  1917 	for (TInt i = 0; i < curEntriesSize; i += 8)
  1918 		{
  1919 		__IF_DEBUG(Printf(
  1920 			"entries[0x%08x], %02x %02x %02x %02x %02x %02x %02x %02x",
  1921 			entries8[i+0], entries8[i+1], entries8[i+2], entries8[i+3],
  1922 			entries8[i+4], entries8[i+5], entries8[i+6], entries8[i+7]));
  1923 		}
  1924 #endif
  1925 
  1926 	iCodeBlockMapEntries = reinterpret_cast<TBlockMapEntryBase*>(entries8);
  1927 	iCodeBlockMapEntriesSize = curEntriesSize;
  1928 
  1929 	return KErrNone;
  1930 	}
  1931 
  1932 
  1933 /**
  1934 Get the compression data relevant to demand paging
  1935 */
  1936 TInt E32Image::LoadCompressionData()
  1937 	{
  1938 	__IF_DEBUG(Printf("E32Image::LoadCompressionData %S 0x%08x",&iFileName,iHeader->CompressionType()));
  1939 
  1940 	TUint compression = iHeader->CompressionType();
  1941 
  1942 	TInt r = KErrNone;
  1943 	if(compression==KFormatNotCompressed)
  1944 		{
  1945 		r = LoadCompressionDataNoCompress();
  1946 		}
  1947 	else if(compression==KUidCompressionBytePair)
  1948 		{
  1949 		TRAP(r,LoadCompressionDataBytePairUnpakL());
  1950 		}
  1951 	else
  1952 		{
  1953 		r = KErrNotSupported;
  1954 		}
  1955 
  1956 	__IF_DEBUG(Printf("E32Image::LoadCompressionData exiting %S r=%d",&iFileName,r));
  1957 	return r;	
  1958 	}
  1959 
  1960 
  1961 TInt E32Image::LoadCompressionDataNoCompress()
  1962 	{
  1963 	__IF_DEBUG(Printf("E32Image::LoadCompressionDataNoCompress %S",&iFileName));
  1964 	if (iHeader->iCodeSize)
  1965 		{
  1966 		iCodeStartInFile = iHeader->iCodeOffset;
  1967 		iCodeLengthInFile = iCodeSize;
  1968 		}
  1969 	return KErrNone;
  1970 	}
  1971 
  1972 
  1973 void E32Image::LoadCompressionDataBytePairUnpakL()
  1974 	{
  1975 	__IF_DEBUG(Printf("E32Image::LoadCompressionDataBytePairUnpakL %S",&iFileName));
  1976 
  1977 	if (iFileData)
  1978 		User::Leave(KErrNotSupported); // if the file data has been loaded into RAM we can't page it!
  1979 
  1980 	TInt pos = iHeader->TotalSize();
  1981 	User::LeaveIfError(iFile.Seek(ESeekStart,pos)); // Start at beginning of compressed data
  1982 
  1983 	CBytePairReader* reader = CBytePairFileReader::NewLC(iFile);
  1984 
  1985 	if (iHeader->iCodeSize)
  1986 		{
  1987 		__IF_DEBUG(Printf("Code & const size %x",iCodeSize));
  1988 		__IF_DEBUG(Printf("Code & const offset %x",iHeader->iCodeOffset));
  1989 		__IF_DEBUG(Printf("Code & const dest %x",iCodeLoadAddress));
  1990 		
  1991 		TInt pageCount;
  1992 		reader->GetPageOffsetsL(pos, pageCount, iCodePageOffsets);
  1993 
  1994 #ifdef _DEBUG
  1995 		for (TInt i = 0; i <= pageCount; ++i)
  1996 			{
  1997 			__IF_DEBUG(Printf("lfbpu:raw iCodePageOffsets[%d] = %d", i, iCodePageOffsets[i]));
  1998 			}
  1999 #endif
  2000 
  2001 		// record the code start position in the file and its compressed length
  2002 		// so BuildCodeBlockMap can construct a block map for the kernel if this
  2003 		// file is demand paged.
  2004 		iCodeStartInFile = iCodePageOffsets[0];
  2005 		iCodeLengthInFile = iCodePageOffsets[pageCount] - iCodePageOffsets[0];
  2006 		}
  2007 		
  2008 	CleanupStack::PopAndDestroy(reader);
  2009 	}
  2010 
  2011 
  2012 /**
  2013 Read all image data into memory, decompressing it using the method indicated in the image header..
  2014 If code isn't being demand paged the code part is read into #iCodeLoadAddress.
  2015 The rest of the file data after the code part is read into #iRestOfFileData.
  2016 */
  2017 TInt E32Image::LoadFile()
  2018 	{
  2019 	__IF_DEBUG(Printf("E32Image::LoadFile %S 0x%08x",&iFileName,iHeader->CompressionType()));
  2020 
  2021 	TUint compression = iHeader->CompressionType();
  2022 
  2023 	TInt r=KErrNone;
  2024 	if(compression==KFormatNotCompressed)
  2025 		{
  2026 		r = LoadFileNoCompress();
  2027 		CHECK_FAILURE(r); // Fuzzer can't trigger this because it only happens on file i/o error
  2028 		}
  2029 	else if(compression==KUidCompressionDeflate)
  2030 		{
  2031 		TRAP(r,LoadFileInflateL());
  2032 		CHECK_FAILURE(r);
  2033 		}
  2034 	else if(compression==KUidCompressionBytePair)
  2035 		{
  2036 		TRAP(r,LoadFileBytePairUnpakL());
  2037 		CHECK_FAILURE(r);
  2038 		}
  2039 	else
  2040 		{
  2041 		r = KErrNotSupported;
  2042 		CHECK_FAILURE(r); // Fuzzer can't trigger this because header validation ensures compression type is OK
  2043 		}
  2044 
  2045 	// we're done with the file contents now, free up memory before resolving imports
  2046 	if(iFileData)
  2047 		{
  2048 		gFileDataAllocator.Free(iFileData);
  2049 		iFileData=NULL;
  2050 		}
  2051 
  2052 	__IF_DEBUG(Printf("E32Image::LoadFile exiting %S r=%d",&iFileName,r));
  2053 	return r;
  2054 	}
  2055 
  2056 
  2057 /**
  2058 Read data from the image's file (or the preloaded data at #iFileData if present).
  2059 */
  2060 TInt E32Image::Read(TUint aPos, TUint8* aDest, TUint aSize, TBool aSvPerms)
  2061 	{
  2062 	TPtr8 p(aDest,aSize,aSize);
  2063 	if(iFileData)
  2064 		{
  2065 		// get data from pre-loaded image data...
  2066 		if(aPos+aSize>iFileSize)
  2067 			RETURN_FAILURE(KErrCorrupt); // Fuzzer can't trigger this because earlier validation prevents sizes being wrong
  2068 		if (aSvPerms)
  2069 			WordCopy(aDest,iFileData+aPos,aSize);
  2070 		else
  2071 			p.Copy(iFileData+aPos,aSize);
  2072 		}
  2073 	else
  2074 		{
  2075 		// get data from file...
  2076 		TInt r = iFile.Read(aPos,p,aSize);
  2077 		if(r!=KErrNone)
  2078 			return r;
  2079 		}
  2080 
  2081 	// check we got the amount of data requested...
  2082 	if(TUint(p.Length())!=aSize)
  2083 		{
  2084 		__IF_DEBUG(Printf("E32Image::Read() Expected:%d, read:%d", aSize, p.Length() ));
  2085 		RETURN_FAILURE(KErrCorrupt); // Fuzzer can't trigger this because requires file length to change during load
  2086 		}
  2087 
  2088 	return KErrNone;
  2089 	}
  2090 
  2091 
  2092 /**
  2093 Read all image data into memory.
  2094 If code isn't being demand paged the code part is read into #iCodeLoadAddress.
  2095 The rest of the file data after the code part is read into #iRestOfFileData.
  2096 */
  2097 TInt E32Image::LoadFileNoCompress()
  2098 	{
  2099 	__IF_DEBUG(Printf("E32Image::LoadFileNoCompress exiting %S",&iFileName));
  2100 	TInt r = KErrNone;
  2101 	
  2102 	if(iHeader->iCodeSize && !iUseCodePaging)
  2103 		{
  2104 		__IF_DEBUG(Printf("Code & const size %x",iCodeSize));
  2105 		__IF_DEBUG(Printf("Code & const offset %x",iHeader->iCodeOffset));
  2106 		__IF_DEBUG(Printf("Code & const dest %x",iCodeLoadAddress));
  2107 		r = Read(iHeader->iCodeOffset, (TText8*)iCodeLoadAddress, iCodeSize, ETrue);
  2108 		if(r!=KErrNone)
  2109 			return r;
  2110 		}
  2111 
  2112 	if(iRestOfFileSize)
  2113 		r = Read(iConversionOffset, iRestOfFileData, iRestOfFileSize);
  2114 	
  2115 	return r;
  2116 	}
  2117 
  2118 
  2119 void FileCleanup(TAny* aPtr)
  2120 	{
  2121 	TFileInput* f=(TFileInput*)aPtr;
  2122 	f->Cancel();
  2123 	delete f;
  2124 	}
  2125 
  2126 /**
  2127 Read all image data into memory, decompressing it using the Inflate method.
  2128 If code isn't being demand paged the code part is read into #iCodeLoadAddress.
  2129 The rest of the file data after the code part is read into #iRestOfFileData.
  2130 */
  2131 void E32Image::LoadFileInflateL()
  2132 	{
  2133 	__IF_DEBUG(Printf("E32Image::LoadFileInflateL %S",&iFileName));
  2134 	__ASSERT_DEBUG(!iUseCodePaging, Panic(ELfiCodePagingNotSupported));
  2135 	
  2136 	TInt pos = iHeader->TotalSize();
  2137 	TBitInput* file;
  2138 	if(iFileData)
  2139 		{
  2140 		if(pos < 0)
  2141 			User::Leave(KErrArgument);
  2142 		file = new (ELeave) TBitInput(iFileData, iFileSize*8, pos*8);
  2143 		CleanupStack::PushL(file);
  2144 		}
  2145 	else
  2146 		{
  2147 		User::LeaveIfError(iFile.Seek(ESeekStart,pos)); // Start at beginning of compressed data
  2148 		file = new (ELeave) TFileInput(iFile);
  2149 		CleanupStack::PushL(TCleanupItem(&FileCleanup,file));
  2150 		}
  2151 
  2152 	CInflater* inflater=CInflater::NewLC(*file);
  2153 	
  2154 	if(iHeader->iCodeSize)
  2155 		{
  2156 		__IF_DEBUG(Printf("Code & const size %x",iCodeSize));
  2157 		__IF_DEBUG(Printf("Code & const offset %x",iHeader->iCodeOffset));
  2158 		__IF_DEBUG(Printf("Code & const dest %x",iCodeLoadAddress));
  2159 
  2160 		TInt count = inflater->ReadL((TUint8*)iCodeLoadAddress,iCodeSize,&WordCopy);
  2161 		if(count!=iCodeSize)
  2162 			User::Leave(KErrCorrupt);
  2163 		}
  2164 
  2165 	if(iRestOfFileSize)
  2166 		{
  2167 		TUint32 count = inflater->ReadL(iRestOfFileData,iRestOfFileSize,&Mem::Copy);
  2168 		if(count!=iRestOfFileSize)
  2169 			User::Leave(KErrCorrupt);
  2170 		}
  2171 
  2172 	CleanupStack::PopAndDestroy(2,file);
  2173 	}
  2174 	
  2175 
  2176 /**
  2177 Read all image data into memory, decompressing it using the BytePair method.
  2178 If code isn't being demand paged the code part is read into #iCodeLoadAddress.
  2179 The rest of the file data after the code part is read into #iRestOfFileData.
  2180 */
  2181 void E32Image::LoadFileBytePairUnpakL()
  2182 	{
  2183 	__IF_DEBUG(Printf("E32Image::LoadFileBytePairUnpak %S",&iFileName));
  2184 
  2185 	// code starts after header
  2186 	TInt pos = iHeader->TotalSize();
  2187 
  2188 	CBytePairReader* reader;
  2189 	if(iFileData)
  2190 		reader = CBytePairReader::NewLC(iFileData+pos, iFileSize-pos);
  2191 	else
  2192 		{
  2193 		iFile.Seek(ESeekStart, pos);
  2194 		reader = CBytePairFileReader::NewLC(iFile);
  2195 		}
  2196 
  2197 	TBool codeLoaded = false;
  2198 	if(iHeader->iCodeSize && !iUseCodePaging)
  2199 		{
  2200 		__IF_DEBUG(Printf("Code & const size %x",iCodeSize));
  2201 		__IF_DEBUG(Printf("Code & const offset %x",iHeader->iCodeOffset));
  2202 		__IF_DEBUG(Printf("Code & const dest %x",iCodeLoadAddress));
  2203 
  2204 		TUint32 bytes = reader->DecompressPagesL((TUint8*)iCodeLoadAddress,iCodeSize,&WordCopy);
  2205 
  2206 		__IF_DEBUG(Printf("bytes:%x",bytes));
  2207 		if((TInt)bytes!=iCodeSize)
  2208 			User::Leave(KErrCorrupt);
  2209 
  2210 		codeLoaded = true;
  2211 		}
  2212 	
  2213 	if(iRestOfFileSize)
  2214 		{
  2215 		if(!codeLoaded)
  2216 			{
  2217 			// skip past code part of file...
  2218 			TInt pageCount = (iCodeSize + KPageOffsetMask) >> KPageSizeShift;
  2219 		
  2220 			TInt pos = 	KIndexTableHeaderSize
  2221 					+	pageCount * sizeof(TUint16)
  2222 					+   iCodeLengthInFile;
  2223 	 
  2224 			__IF_DEBUG(Printf("lfpbu:pos=%x", pos));
  2225 			reader->SeekForwardL(pos);
  2226 			}
  2227 		
  2228 		__IF_DEBUG(Printf("  iRestOfFileSize==%x, iRestOfFileData==%x", iRestOfFileSize, iRestOfFileData));
  2229 		
  2230 		TUint32 bytes = reader->DecompressPagesL(iRestOfFileData,iRestOfFileSize,NULL);
  2231 		__IF_DEBUG(Printf("bytes:%x",bytes));
  2232 		if(bytes!=iRestOfFileSize)
  2233 			User::Leave(KErrCorrupt);
  2234 		}
  2235 		
  2236 	CleanupStack::PopAndDestroy(reader);
  2237 	}
  2238 
  2239 
  2240 /**
  2241 Relocate code.
  2242 */
  2243 TInt E32Image::RelocateCode()
  2244 	{
  2245 	if(iHeader->iExportDirOffset)
  2246 		iExportDirLoad += iCodeLoadAddress;	// only for RAM modules which are not already loaded
  2247 
  2248 	__IF_DEBUG(Printf("**EntryPointVeneer %08x FileEntryPoint %08x",iEntryPtVeneer,iFileEntryPoint));
  2249 	__IF_DEBUG(Printf("**ExportDir load@%08x run@%08x",iExportDirLoad,iExportDir));
  2250 	TInt r = KErrNone;	
  2251 	if(iHeader->iCodeRelocOffset)
  2252 		{
  2253 		__IF_DEBUG(Printf("Relocate code & const"));
  2254 
  2255 		if(!iUseCodePaging)
  2256 			r = RelocateSection(iCodeRelocSection, iCodeLoadAddress);
  2257 		else
  2258 			{
  2259 			r = AllocateRelocationData(iCodeRelocSection, iHeader->iCodeSize, iCodeLoadAddress, iCodeRelocTable);
  2260 			iExportDirEntryDelta = iCodeDelta; // so exports get relocated
  2261 			}
  2262 		}
  2263 
  2264 	if(r==KErrNone)
  2265 		r = RelocateExports();
  2266 
  2267 	if(r==KErrNone)
  2268 		{
  2269 		// put a unique ID into the third word after the entry point
  2270 
  2271 		// address for ID...
  2272 		TLinAddr csid_addr = iFileEntryPoint+KCodeSegIdOffset-iCodeRunAddress+iCodeLoadAddress;
  2273 		__IF_DEBUG(Printf("csid_addr %08x", csid_addr));
  2274 
  2275 		// get existing ID...
  2276 		TUint x;
  2277 		WordCopy(&x, (const TAny*)csid_addr, sizeof(x));
  2278 		if(x==0)
  2279 			{
  2280 			// generate next ID...
  2281 			if(++NextCodeSegId == 0xffffffffu)
  2282 				Fault(ELdrCsIdWrap);
  2283 			__IF_DEBUG(Printf("NextCSID %08x", NextCodeSegId));
  2284 			// store ID...
  2285 			if(!iUseCodePaging)
  2286 				WordCopy((TAny*)csid_addr, &NextCodeSegId, sizeof(NextCodeSegId));
  2287 			else
  2288 				{
  2289 				// demand paged code needs modifying when paged in, so add ID as a new 'fixup'...
  2290 				TUint64* fixup = ExpandFixups(1);
  2291 				if(!fixup)
  2292 					r = KErrNoMemory;
  2293 				else
  2294 					*fixup = MAKE_TUINT64(csid_addr,NextCodeSegId);
  2295 				}
  2296 			}
  2297 		}
  2298 
  2299 	return r;
  2300 	}
  2301 
  2302 
  2303 /**
  2304 Copy the data section from buffer #iRestOfFileData to the memory allocated at #iDataLoadAddress.
  2305 Then relocate this data ready for use at the executables run addresses.
  2306 */
  2307 TInt E32Image::LoadAndRelocateData()
  2308 	{
  2309 	__IF_DEBUG(Printf("E32Image::LoadAndRelocateData %S",&iFileName));
  2310 	if(!iHeader->iDataOffset)
  2311 		return KErrNone; // do data section
  2312 
  2313 	// copy data...
  2314 	__IF_DEBUG(Printf("Read Data: size %x->%08x",iDataSize,iDataLoadAddress));
  2315 	TUint32 bufferOffset=iHeader->iDataOffset-iConversionOffset;
  2316 	TUint8* source=iRestOfFileData+bufferOffset;
  2317 	MemCopy((TText8*)iDataLoadAddress,source,iDataSize);
  2318 
  2319 	// relocate data...
  2320 	__IF_DEBUG(Printf("Relocate data section"));
  2321 	__IF_DEBUG(Printf("iDataRelocOffset %08x",iHeader->iDataRelocOffset));
  2322 	TInt r = KErrNone;	
  2323 	if(iHeader->iDataRelocOffset)
  2324 		r = RelocateSection(iDataRelocSection, iDataLoadAddress);
  2325 
  2326 	return r;
  2327 	}
  2328 
  2329 
  2330 /**
  2331 Copies data from aDestination to aSource by running in supervisor mode.
  2332 aDest, aSource & aNumberOfBytes must be word aligned.
  2333 */
  2334 TUint8* E32Image::WordCopy(TAny* aDestination, const TAny* aSource, TInt aNumberOfBytes)
  2335 	{
  2336 	aNumberOfBytes &= ~3; // Avoid panics for corrupt data which is not word size
  2337 	SCopyDataInfo info = {aDestination,aSource, aNumberOfBytes};
  2338 	return (TUint8*) ExecuteInSupervisorMode(&svWordCopy, &info);
  2339 	}
  2340 
  2341 
  2342 /**
  2343 Copies data from aDestination to aSource by running in supervisor mode.
  2344 */
  2345 TUint8* E32Image::MemCopy(TAny* aDestination, const TAny* aSource, TInt aNumberOfBytes)
  2346 	{
  2347 	SCopyDataInfo info={aDestination,aSource, aNumberOfBytes};
  2348 	return (TUint8*) ExecuteInSupervisorMode(&svMemCopy, &info);
  2349 	}
  2350 
  2351 
  2352 /**
  2353 Relocate a section, applying relocations for run addresses to values currently at their load addresses.
  2354 */
  2355 TInt E32Image::RelocateSection(E32RelocSection* aSection, TUint32 aLoadAddress)
  2356 	{
  2357 	if(!aSection)
  2358 		return KErrNone;
  2359 
  2360 	__IF_DEBUG(Printf("Relocate: NRelocs:%08x LoadAddr:%08x", aSection->iNumberOfRelocs, aLoadAddress));
  2361 
  2362 	SRelocateSectionInfo info={this, (TUint8*)(aSection+1), aSection->iNumberOfRelocs, aLoadAddress};
  2363 
  2364 	// call function in supervisor mode to relocate the section
  2365 	TInt r = ExecuteInSupervisorMode(&svRelocateSection, &info);
  2366 
  2367 	__IF_DEBUG(Printf("Relocate returning %d",r));
  2368 	return r;
  2369 	}
  2370 
  2371 
  2372 /**
  2373 Relocate the export directory for the code's run address
  2374 */
  2375 TInt E32Image::RelocateExports()
  2376 	{
  2377 	// This only has to be done for PE-derived images, ELF marks all
  2378 	// export table entries as 'relocations' so this job has already been done.
  2379 	TUint impfmt = iHeader->ImportFormat();
  2380 	if (impfmt == KImageImpFmt_ELF)
  2381 		return KErrNone;
  2382 
  2383 	__IF_DEBUG(Printf("E32Image::RelocateExports %S",&iFileName));
  2384 
  2385 	if(iHeader->iExportDirOffset)
  2386 		{
  2387 		// call function in supervisor mode to fix up export directory
  2388 		ExecuteInSupervisorMode(&svRelocateExports, this);
  2389 		}
  2390 	return KErrNone;
  2391 	}
  2392 
  2393 
  2394 /**
  2395 Validate import section data structures in iRestOfFileData.
  2396 Set iImportData to point to point to start of this.
  2397 Allocate memory (iCurrentImportList) which is big enough to store imports for a single dependency.
  2398 */
  2399 TInt E32Image::ReadImportData()
  2400 	{
  2401 	__IF_DEBUG(Printf("E32Image::ReadImportData %S",&iFileName));
  2402 
  2403 	if(!iHeader->iImportOffset)
  2404 		return KErrNone;
  2405 
  2406 	TUint biggestImportCount; 
  2407 	TInt r = ((E32ImageHeaderV*)iHeader)->ValidateImports(iRestOfFileData,iRestOfFileSize,biggestImportCount);
  2408 	if(r!=KErrNone)
  2409 		return r;
  2410 
  2411 	iImportData = (TUint32*)(iRestOfFileData+iHeader->iImportOffset-iConversionOffset);
  2412 	iCurrentImportList = (TUint32*)User::Alloc(biggestImportCount * sizeof(TUint32));
  2413 	__IF_DEBUG(Printf("E32Image::ReadImportData - alloc %d current import slots at %08x", biggestImportCount, iCurrentImportList));
  2414 	if(!iCurrentImportList)
  2415 		return KErrNoMemory;
  2416 
  2417 	return KErrNone;
  2418 	}
  2419 
  2420 
  2421 void E32Image::SortCurrentImportList()
  2422 	{
  2423 	if (!iCurrentImportListSorted)
  2424 		{
  2425 		RArray<TUint> array((TUint*)iCurrentImportList, iCurrentImportCount);
  2426 		array.Sort();
  2427 		iCurrentImportListSorted = (TUint8)ETrue;
  2428 		}
  2429 	}
  2430 
  2431 
  2432 TInt CheckRomExports(const TRomImageHeader* aR, const E32Image* aI)
  2433 	{
  2434 	__IF_DEBUG(Printf("CheckRomExports"));
  2435 	if (aR->iExportDirCount == 0)
  2436 		return aI->iCurrentImportCount ? KErrNotSupported : KErrNone;
  2437 	const TUint32* xd = (const TUint32*)aR->iExportDir;
  2438 	const TUint32* p = aI->iCurrentImportList;
  2439 	const TUint32* pE = p + aI->iCurrentImportCount;
  2440 	for (; p<pE; ++p)
  2441 		if (xd[*p] == 0)
  2442 			return KErrNotSupported;
  2443 	return KErrNone;
  2444 	}
  2445 
  2446 
  2447 TInt CheckRamExports(TUint aEDT, const TUint8* aED, TUint aEDC, E32Image* aI)
  2448 	{
  2449 	__IF_DEBUG(Printf("CheckRamExports"));
  2450 	if (aEDC == 0)
  2451 		return aI->iCurrentImportCount ? KErrNotSupported : KErrNone;
  2452 	if (aEDT == KImageHdr_ExpD_NoHoles)
  2453 		return KErrNone;	// nothing missing
  2454 
  2455 	const TUint32* p = aI->iCurrentImportList;
  2456 	const TUint32* pE = p + aI->iCurrentImportCount;
  2457 
  2458 	if (aEDT == KImageHdr_ExpD_FullBitmap)
  2459 		{
  2460 		for (; p<pE; ++p)
  2461 			{
  2462 			TUint32 x = *p - 1;
  2463 			if ( !(aED[x>>3] & (1u<<(x&7))) )
  2464 				return KErrNotSupported;
  2465 			}
  2466 		return KErrNone;
  2467 		}
  2468 
  2469 	if (aEDT != KImageHdr_ExpD_SparseBitmap8)
  2470 		return KErrNotSupported;		// don't know what this is
  2471 	aI->SortCurrentImportList();		// sort imports to increasing order
  2472 	TUint32 memsz = (aEDC + 7) >> 3;	// size of complete bitmap
  2473 	TUint32 mbs = (memsz + 7) >> 3;		// size of meta-bitmap
  2474 	const TUint8* mptr = aED;
  2475 	const TUint8* gptr = mptr + mbs;
  2476 	const TUint8* mptrE = mptr + mbs;
  2477 	TUint xlim = 64;
  2478 	for (; mptr<mptrE && p<pE; ++mptr, xlim+=64)
  2479 		{
  2480 		TUint m = *mptr;
  2481 		if (m==0)
  2482 			{
  2483 			// nothing missing in this block of 64 exports; step to next block
  2484 			for (; p<pE && *p<=xlim; ++p) {}
  2485 			continue;
  2486 			}
  2487 		// expand this block of 64
  2488 		TUint32 g32[2] = {0xffffffffu, 0xffffffffu};
  2489 		TUint8* g = (TUint8*)g32;
  2490 		for (; m; m>>=1, ++g)
  2491 			if (m&1)
  2492 				*g = *gptr++;
  2493 		g = (TUint8*)g32;
  2494 		for (; p<pE && *p<=xlim; ++p)
  2495 			{
  2496 			TUint ix = *p - (xlim - 64) - 1;
  2497 			if ( !(g[ix>>3] & (1u<<(ix&7))) )
  2498 				return KErrNotSupported;
  2499 			}
  2500 		}
  2501 	return KErrNone;
  2502 	}
  2503 
  2504 
  2505 TInt CheckRequiredImports(E32Image* aImporter, E32Image* aExporter, TInt aAction)
  2506 	{
  2507 	__IF_DEBUG(Printf("E32Image::CheckRequiredImports (existing) %d", aAction));
  2508 	TInt last = aImporter->LastCurrentImport();
  2509 	if (last > aExporter->iExportDirCount)
  2510 		return KErrNotSupported;
  2511 	if (aAction == EAction_CheckLastImport)
  2512 		return KErrNone;
  2513 	if (aExporter->iRomImageHeader)
  2514 		return CheckRomExports(aExporter->iRomImageHeader, aImporter);
  2515 	if (aExporter->iHeader)
  2516 		{
  2517 		E32ImageHeaderV* v = (E32ImageHeaderV*)aExporter->iHeader;
  2518 		return CheckRamExports(v->iExportDescType, v->iExportDesc, v->iExportDirCount, aImporter);
  2519 		}
  2520 	TInt r = aExporter->ReadExportDirLoad();
  2521 	if (r != KErrNone)
  2522 		return r;				// could fail with OOM
  2523 	TBool hasNmdExp = (aExporter->iAttr & ECodeSegAttNmdExpData);
  2524 	const TUint32* p = aImporter->iCurrentImportList;
  2525 	const TUint32* pE = p + aImporter->iCurrentImportCount;
  2526 	const TUint32* pX = (const TUint32*)aExporter->iExportDirLoad - 1;
  2527 	TUint32 xep = aExporter->iFileEntryPoint;
  2528 	for (; p<pE; ++p)
  2529 		{
  2530 		TUint32 x = *p;
  2531 		TUint32 xx = pX[x];
  2532 		if ((xx==0 && (x!=0 || (x==0&&hasNmdExp))) || xx==xep)
  2533 			return KErrNotSupported;
  2534 		}
  2535 	return KErrNone;
  2536 	}
  2537 
  2538 
  2539 TInt CheckRequiredImports(E32Image* aImporter, const RImageInfo& aExporter, TInt aAction)
  2540 	{
  2541 	__IF_DEBUG(Printf("E32Image::CheckRequiredImports (new) %d", aAction));
  2542 	TInt last = aImporter->LastCurrentImport();
  2543 	if (last > aExporter.iExportDirCount)
  2544 		return KErrNotSupported;
  2545 	if (aAction == EAction_CheckLastImport)
  2546 		return KErrNone;
  2547 	if (aExporter.iRomImageHeader)
  2548 		return CheckRomExports(aExporter.iRomImageHeader, aImporter);
  2549 	return CheckRamExports(aExporter.iExportDescType, aExporter.iExportDesc, aExporter.iExportDirCount, aImporter);
  2550 	}
  2551 
  2552 
  2553 TInt E32Image::GetCurrentImportList(const E32ImportBlock* a)
  2554 	{
  2555 	__IF_DEBUG(Printf("E32Image::GetCurrentImportList(E32ImportBlock* a:%08X)", a));
  2556 	TInt r;
  2557 	TInt n = a->iNumberOfImports;
  2558 	iCurrentImportCount = n;
  2559 	iCurrentImportListSorted = (TUint8)EFalse;
  2560 	__IF_DEBUG(Printf("iCurrentImportCount:%d, iCurrentImportListSorted:%d)", iCurrentImportCount, iCurrentImportListSorted));
  2561 	__IF_DEBUG(Printf("iHeader->ImportFormat() == KImageImpFmt_ELF:%d", (iHeader->ImportFormat() == KImageImpFmt_ELF) ));
  2562 	
  2563 	if (iHeader->ImportFormat() == KImageImpFmt_ELF)
  2564 		{
  2565 		SGetImportDataInfo info;
  2566 		info.iCount = n;
  2567 		info.iDest = iCurrentImportList;
  2568 		info.iCodeLoadAddress = iCodeLoadAddress;
  2569 		info.iImportOffsetList = (TUint32*)a->Imports();
  2570 		r = ExecuteInSupervisorMode(&svElfDerivedGetImportInfo, &info);
  2571 		}
  2572 	else
  2573 		{
  2574 		TUint32* iat = (TUint32*)(iCodeLoadAddress + iTextSize);
  2575 		WordCopy(iCurrentImportList, iat + iNextImportPos, n * sizeof(TUint32));
  2576 		r = KErrNone;
  2577 		}
  2578 	iNextImportPos += n;
  2579 	__IF_DEBUG(Printf("End of E32Image::GetCurrentImportList:%d)", r));
  2580 	return r;
  2581 	}
  2582 
  2583 
  2584 TInt E32Image::LastCurrentImport()
  2585 	{
  2586 	TUint32 last = 0;
  2587 	if (iCurrentImportListSorted)
  2588 		last = iCurrentImportList[iCurrentImportCount - 1];
  2589 	else
  2590 		{
  2591 		const TUint32* p = iCurrentImportList;
  2592 		const TUint32* pE = p + iCurrentImportCount;
  2593 		for (; p<pE; ++p)
  2594 			if (*p > last) last = *p;
  2595 		}
  2596 	__IF_DEBUG(Printf("E32Image::LastCurrentImport = %d", last));
  2597 	return last;
  2598 	}
  2599 
  2600 
  2601 TInt E32Image::ProcessImports()
  2602 //
  2603 //	This function is only ever called on the exe/dll which is loaded from 
  2604 //	the RProcess/RLibrary load.
  2605 //	It reads this DLL/EXE's imports section and builds up a table of dlls referenced.
  2606 //	It never goes recursive.
  2607 //
  2608 	{
  2609 	__IF_DEBUG(Printf("E32Image::ProcessImports %S",&iFileName));
  2610 	__IF_DEBUG(Printf("DepCount=%d",iDepCount));
  2611 	
  2612 	if (iDepCount==0 || AlwaysLoaded())
  2613 		return KErrNone;	// no imports
  2614 
  2615 	TFileNameInfo fi;
  2616 	fi.Set(iFileName, 0);
  2617 	gLoadeePath.Zero();
  2618 	fi.GetName(gLoadeePath, TFileNameInfo::EIncludeDrivePath);
  2619 	if (PlatSec::ConfigSetting(PlatSec::EPlatSecEnforceSysBin)
  2620 			&& gLoadeePath.Length()==11
  2621 			&& KSysBin().CompareF(TPtrC8(gLoadeePath.Ptr()+1,10))==0)
  2622 		{
  2623 		// Main loadee is in the default path, so unset this in order to
  2624 		// search normally for dependents
  2625 		gLoadeePath.Zero();
  2626 		}
  2627 #ifdef __X86__
  2628 	if (gLoadeePath.Length()>=2 && gLoadeePath[1]==':')
  2629 		{
  2630 		TInt d = gLoadeePath[0];
  2631 		if (d=='a' || d=='A')
  2632 			UseFloppy = EDriveA;
  2633 		else if (d=='b' || d=='B')
  2634 			UseFloppy = EDriveB;
  2635 		}
  2636 #endif
  2637 	RImageArray array;
  2638 	TInt r = array.Add(this);
  2639 	if (r==KErrNone)
  2640 		r = LoadDlls(array);
  2641 	if (r==KErrNone)
  2642 		r = FixupDlls(array);
  2643 	if (r==KErrNone)
  2644 		r = FinaliseDlls(array);
  2645 	CleanupDlls(array);
  2646 	array.Close();
  2647 
  2648 	__IF_DEBUG(Printf("E32Image::ProcessImports returns %d",r));
  2649 	return r;
  2650 	}
  2651 
  2652 void E32Image::CleanupDlls(RImageArray& aArray)
  2653 //
  2654 // Free the space used in fixing up the dlls.
  2655 // Don't free the entry corresponding to the main loadee.
  2656 //
  2657 	{
  2658 
  2659 	__IF_DEBUG(Printf("CleanupDlls"));
  2660 	TInt n = aArray.Count();
  2661 	TInt i;
  2662 	for (i=0; i<n; ++i)
  2663 		{
  2664 		E32Image* e = aArray[i];
  2665 		if (e != this)
  2666 			delete e;
  2667 		}
  2668 	}
  2669 
  2670 TInt E32Image::FinaliseDlls(RImageArray& aArray)
  2671 	{
  2672 	__IF_DEBUG(Printf("E32Image::FinaliseDlls"));
  2673 	TInt i;
  2674 	TInt c = aArray.Count();
  2675 	TInt r = KErrNone;
  2676 	for(i=0; i<c && r==KErrNone; i++)
  2677 		{
  2678 		E32Image* e = aArray[i];
  2679 		if(e!=this && !e->iAlreadyLoaded)
  2680 			{
  2681 			// transfers ownership of clamp handle to codeseg; nulls handle if successful
  2682 			if(!e->AlwaysLoaded())
  2683 				r = E32Loader::CodeSegLoaded(*e);
  2684 			if(r==KErrNone && e->iUseCodePaging)
  2685 				{
  2686 				e->iFileClamp.iCookie[0]=0;// null handle to indicate 
  2687 				e->iFileClamp.iCookie[1]=0;// transfer of ownership of clamp handle to codeseg
  2688 				}
  2689 			}
  2690 		}
  2691 	__IF_DEBUG(Printf("E32Image::FinaliseDlls returns %d",r));
  2692 	return r;
  2693 	}
  2694 
  2695 
  2696 TInt E32Image::LoadDlls(RImageArray& aArray)
  2697 //
  2698 // Build a matrix of all DLLs referenced by the one we're loading, and
  2699 // ensure they're all loaded.
  2700 //
  2701 	{
  2702 	__IF_DEBUG(Printf("E32Image::LoadDlls"));
  2703 	TInt r=KErrNone;
  2704 	E32ImportSection* importSection=(E32ImportSection *)iImportData;
  2705 	E32ImportBlock* block;
  2706 	if(importSection)
  2707 		block=(E32ImportBlock*)(importSection+1);
  2708 	else
  2709 		block=NULL;
  2710 	const TRomImageHeader* const * pR=NULL;
  2711 	if (iRomImageHeader)
  2712 		pR=iRomImageHeader->iDllRefTable->iEntry;
  2713 	iNextImportPos = 0;
  2714 
  2715 	// For each module referenced by this module
  2716 	for (TInt i=0; i<iDepCount; ++i)
  2717 		{
  2718 		RImageFinder finder;
  2719 		E32ImportBlock* thisBlock = block;
  2720 		E32Image* e = NULL;	// will represent referenced module
  2721 		const TRomImageHeader* rih = NULL;
  2722 		RLdrReq req;		// new loader request to load referenced module
  2723 		TBuf8<KMaxKernelName> rootname;
  2724 		req.iFileName = (HBufC8*)&rootname;
  2725 
  2726 		if (pR)
  2727 			{
  2728 			// Processing imports for ROM XIP module
  2729 			rih = *pR++;
  2730 			__IF_DEBUG(Printf("Importing from ROM XIP %08x", rih));
  2731 			e = aArray.Find(rih);
  2732 			}
  2733 		else
  2734 			{
  2735 			// Processing imports for RAM module
  2736 			__IF_DEBUG(Printf("Import block address %08x",block));
  2737 			TPtrC8 dllname = (const TText8*)((TUint32)iImportData + block->iOffsetOfDllName);
  2738 			if (dllname.Length() > KMaxKernelName)
  2739 				{
  2740 				__IF_DEBUG(Printf("Import DLL name too big: %S",&dllname));
  2741 				RETURN_FAILURE(KErrNotSupported);
  2742 				}
  2743 			TFileNameInfo fni;
  2744 			r = fni.Set(dllname, TFileNameInfo::EAllowUid);
  2745 			if (r!=KErrNone)
  2746 				RETURN_FAILURE(KErrCorrupt);
  2747 			fni.GetName(rootname, TFileNameInfo::EIncludeBaseExt);
  2748 			TUint32* uid=(TUint32*)&req.iRequestedUids;
  2749 			uid[2] = fni.Uid();
  2750 			req.iRequestedVersion = fni.Version();
  2751 			if (gLoadeePath.Length() > 0)
  2752 				req.iPath = (HBufC8*)&gLoadeePath;
  2753 			req.iPlatSecCaps = iS.iCaps;
  2754 			req.iFileNameInfo.Set(rootname, 0);
  2755 			req.iImporter = this;
  2756 			r = GetCurrentImportList(block);	// get list of required exports from this exporter
  2757 			if (r!=KErrNone)
  2758 				{
  2759 				return r;
  2760 				}
  2761 			TUint impfmt = iHeader->ImportFormat();
  2762 			block = (E32ImportBlock*)block->NextBlock(impfmt);
  2763 
  2764 			r = finder.Set(req);
  2765 			if (r == KErrNone)
  2766 				r = finder.SearchExisting(aArray);	// see what we've already got
  2767 			if (r == KErrNone)
  2768 				{
  2769 				TBool search = ETrue;
  2770 				if (finder.iExisting)
  2771 					{
  2772 					// Found an existing DLL - check for an exact version match
  2773 					if (DetailedCompareVersions(finder.iCurrentVersion, finder.iReq->iRequestedVersion) <= EVersion_Exact)
  2774 						search = EFalse;		// if exact match, don't need to continue search
  2775 					}
  2776 				if (search)
  2777 					r = finder.Search();		// see what else is available
  2778 				}
  2779 			if (r!=KErrNone)
  2780 				{
  2781 				finder.Close();
  2782 				return r;
  2783 				}
  2784 			if (finder.iExisting)
  2785 				e = finder.iExisting;			// already have the required module
  2786 			}
  2787 
  2788 		// If it's already in the array, go on to the next module
  2789 		if (e)
  2790 		    {
  2791 			__IF_DEBUG(Printf("Already there"));
  2792 			}
  2793 		else
  2794 			{
  2795 			//	Not already in the array
  2796 			__IF_DEBUG(Printf("Not in array, add it"));
  2797 			e = new E32Image;
  2798 			if (!e)
  2799 				{
  2800 				finder.Close();
  2801 				return KErrNoMemory;
  2802 				}
  2803 			e->iMain = iMain;
  2804 			e->iClientProcessHandle = iMain->iClientProcessHandle;
  2805 			if (iMain->iAttr & ECodeSegAttKernel)
  2806 				e->iAttr |= ECodeSegAttKernel;
  2807 			if (rih)
  2808 				{
  2809 				// loading a specified ROM XIP DLL
  2810 				r = e->DoLoadCodeSeg(*rih);
  2811 				}
  2812 			else
  2813 				{
  2814 				// loading a DLL by name
  2815 				r = e->DoLoadCodeSeg(req, finder); // also closes 'finder'
  2816 				__IF_DEBUG(Printf("%S DoLoadCodeSeg returned %d",req.iFileName,r));
  2817 				}
  2818 
  2819 			//	Add the new entry to the array
  2820 			if (r==KErrNone)
  2821 				{
  2822 				__IF_DEBUG(Printf("Add to the array"));
  2823 				r = aArray.Add(e);
  2824 				}
  2825 			if (r!=KErrNone)
  2826 				{
  2827 				delete e;
  2828 				return r;
  2829 				}
  2830 						
  2831 			//	Now go nice and recursive, and call LoadDlls on this latest dll, if it 
  2832 			//	imports anything
  2833 			//	This recursive horror *will* terminate because it is only called
  2834 			//	on "new" dlls
  2835 			if (e->iDepCount && !e->iAlreadyLoaded && e->iIsDll)
  2836 				{
  2837 				__IF_DEBUG(Printf("****Go recursive****"));
  2838 				r = e->LoadDlls(aArray);
  2839 				if (r!=KErrNone)
  2840 					{
  2841 					return r;
  2842 					}
  2843 				}
  2844 
  2845 			}
  2846 
  2847 		// If we added an SMP unsafe dependent, this image is SMP unsafe.
  2848 		// This is done after recursing into LoadDlls, so a single unsafe
  2849 		// dependent anywhere down the tree will poison everything above it.
  2850 		// This isn't sufficient to deal with cycles, though, so the kernel
  2851 		// also has to update the flag in DCodeSeg::FinaliseRecursiveFlags.
  2852 		// It has to be done here first because the kernel doesn't know
  2853 		// about XIP DLLs that don't have a codeseg created.
  2854 		if (!(e->iAttr & ECodeSegAttSMPSafe))
  2855 			{
  2856 			__IF_DEBUG(Printf("%S is not SMP safe because it loads %S", &iFileName, &e->iFileName));
  2857 			iAttr &= ~ECodeSegAttSMPSafe;
  2858 			}
  2859 
  2860 		// If exporter is an EXE it must be the same as the client process or newly created process
  2861 		__IF_DEBUG(Printf("Check EXE->EXE"));
  2862 		if (gExeCodeSeg && !e->iIsDll && e->iHandle!=gExeCodeSeg)
  2863 			return KErrNotSupported;
  2864 
  2865 		// A globally-visible module may only link to other globally visible modules
  2866 		__IF_DEBUG(Printf("Check Global Attribute"));
  2867 		if ( (iAttr&ECodeSegAttGlobal) && !(e->iAttr&ECodeSegAttGlobal) )
  2868 			return KErrNotSupported;
  2869 
  2870 		// A ram-loaded globally-visible module may only link to ROM XIP modules with no static data
  2871 		__IF_DEBUG(Printf("Check RAM Global"));
  2872 		if ( (iAttr&ECodeSegAttGlobal) && !iRomImageHeader && e->iHandle)
  2873 			return KErrNotSupported;
  2874 
  2875 		if (thisBlock)
  2876 			thisBlock->iOffsetOfDllName=(TUint32)e;   // For easy access when fixing up imports
  2877 		if (e->iHandle)
  2878 			{
  2879 			//	Record the dependence of this on e
  2880 			r=E32Loader::CodeSegAddDependency(iHandle, e->iHandle);
  2881 			if (r!=KErrNone)
  2882 				{
  2883 				return r;
  2884 				}
  2885 			}
  2886 		}
  2887 	__IF_DEBUG(Printf("E32Image::LoadDlls OK"));
  2888 	return KErrNone;
  2889 	}
  2890 
  2891 
  2892 TInt E32Image::ReadExportDirLoad()
  2893 	{
  2894 	//	Get the exporter's export directory
  2895 	__IF_DEBUG(Printf("ReadExportDirLoad exp_dir=%08x", iExportDirLoad));
  2896 	if (!iExportDirLoad)
  2897 		{
  2898 		// already loaded nonglobal DLL - must read the export directory
  2899 		if (iExportDirCount==0 && !(iAttr&ECodeSegAttNmdExpData))
  2900 			return KErrGeneral; // DLL has no exports, something must be wrong
  2901 		iCopyOfExportDir = (TUint32*)User::Alloc((iExportDirCount+1) * sizeof(TUint32));
  2902 		if (!iCopyOfExportDir)
  2903 			return KErrNoMemory;
  2904 		__IF_DEBUG(Printf("Reading %d exports", iExportDirCount));
  2905 		E32Loader::ReadExportDir(iHandle, iCopyOfExportDir);
  2906 		iExportDirLoad = (TUint32)(iCopyOfExportDir+1);
  2907 		}
  2908 	return KErrNone;
  2909 	}
  2910 
  2911 
  2912 TInt E32Image::FixupDlls(RImageArray& aArray)
  2913 //
  2914 // Go through the array, fixing up the files
  2915 //
  2916 	{
  2917 	__IF_DEBUG(Printf("E32Image::FixupDlls"));
  2918 
  2919 	// For each E32Image file in the array
  2920 	TInt i;
  2921 	TInt c = aArray.Count();
  2922 
  2923 	for (i=0; i<c; ++i)
  2924 		{
  2925 		TInt r;
  2926 
  2927 		E32Image* imp = aArray[i];
  2928 		__IF_DEBUG(Printf("Dll number %d %S",i,&imp->iFileName));
  2929 
  2930 		const E32ImportSection* importSection = (const E32ImportSection*)imp->iImportData;
  2931 		if (!importSection)
  2932 			{
  2933 			__IF_DEBUG(Printf("Has no imports to fixup"));
  2934 			continue;	//	No imports, skip this dll (true of ALL ROM dlls)
  2935 			}
  2936 
  2937 		const E32ImportBlock* block = (const E32ImportBlock*)(importSection + 1);
  2938 
  2939 		SFixupImportAddressesInfo info;
  2940 		info.iIat = (TUint32*)(imp->iCodeLoadAddress + imp->iTextSize);
  2941 		info.iCodeLoadAddress = imp->iCodeLoadAddress;
  2942 
  2943 		// fix up imports from each dependent DLL, building a table of all the imports for the binary
  2944 		TInt depCount = imp->iDepCount;
  2945 		while (depCount--)
  2946 			{
  2947 			// declare variables at start of loop body to prevent 'crosses initialization' errors
  2948 			TUint impfmt;
  2949 
  2950 			// E32Image::LoadDlls() will have set iOffsetOfDllName of the 
  2951 			// import block to point to the E32Image object of the exporter
  2952 			// it's importing
  2953 			E32Image* exp = (E32Image*)(block->iOffsetOfDllName);   // LoadDlls() set this to exporter
  2954 
  2955 			//	Get the exporter's export directory
  2956 			r = exp->ReadExportDirLoad();
  2957 			if (r != KErrNone)
  2958 				return r;
  2959 			info.iExportDir = (TUint32*)exp->iExportDirLoad;
  2960 			info.iExportDirEntryDelta = exp->iExportDirEntryDelta;
  2961 			info.iNumImports = block->iNumberOfImports;
  2962 			info.iExporter = exp;
  2963 
  2964 			// if demand paging, expand the import fixup buffer for this next exporting DLL
  2965 			if (! imp->iUseCodePaging)
  2966 				info.iFixup64 = 0;
  2967 			else
  2968 				{
  2969 				info.iFixup64 = imp->ExpandFixups(block->iNumberOfImports);
  2970 				if (!info.iFixup64)
  2971 					return KErrNoMemory;
  2972 				}
  2973 
  2974 			// call function in supervisor mode to fix up the import addresses.
  2975 			impfmt = imp->iHeader->ImportFormat();
  2976 			if (impfmt == KImageImpFmt_ELF)
  2977 				{
  2978 				info.iImportOffsetList = (TUint32*)(block+1);
  2979 				r = ExecuteInSupervisorMode(&svElfDerivedFixupImportAddresses, &info);
  2980 				}
  2981 			else
  2982 				r = ExecuteInSupervisorMode(&svFixupImportAddresses, &info);
  2983 
  2984 			if (r != KErrNone)
  2985 				{
  2986 				__IF_DEBUG(Printf("svFixupImportAddresses returns %d", r));
  2987 				return r;
  2988 				}
  2989 
  2990 			// Next import block...
  2991 			block = block->NextBlock(impfmt);
  2992 			}	// while (depCount--)
  2993 
  2994 		if (imp->iUseCodePaging && imp->iFixupCount > 0)
  2995 			{
  2996 			// convert the <addr,val> pairs to an import fixup tab which can be used when
  2997 			// the code is paged.
  2998 			r = imp->BuildImportFixupTable();
  2999 			if (r != KErrNone)
  3000 				return r;
  3001 			}
  3002 		}
  3003 
  3004 	__IF_DEBUG(Printf("E32Image::FixupDlls OK"));
  3005 	return KErrNone;
  3006 	}
  3007 
  3008 
  3009 /**
  3010 This function is defined because RArray does not natively support
  3011 sorting 64-bit integers.
  3012 
  3013 It is used by FixupDlls to order the import fixup locations in the image
  3014 so they can be organized by page.
  3015 
  3016 @param	aLeft			64-bit unsigned integer to compare against aRight.
  3017 @param	aRight			64-bit unsigned integer to compare against aLeft.
  3018 @return					-1 if aLeft < aRight; 0 if aLeft == aRight; and
  3019 						+1 if aLeft > aRight.  This conforms to the behavior
  3020 						which is expected from a function used by TLinearOrder.
  3021 */
  3022 static TInt Uint64LinearOrderFunc(const TUint64& aLeft, const TUint64& aRight)
  3023 	{
  3024 	if (aLeft < aRight)
  3025 		return -1;
  3026 	else if (aLeft > aRight)
  3027 		return 1;
  3028 	else
  3029 		return 0;
  3030 	}
  3031 
  3032 
  3033 TUint64* E32Image::ExpandFixups(TInt aNumFixups)
  3034 	{
  3035 	__IF_DEBUG(Printf("ExpandFixups,%d+%d", iFixupCount,aNumFixups));
  3036 	TInt newCount = iFixupCount+aNumFixups;
  3037 	TUint64* fixups = (TUint64*) User::ReAlloc(iFixups, sizeof(TUint64) * newCount);
  3038 	if(!fixups)
  3039 		return 0;
  3040 	TUint64* newFixups = fixups+iFixupCount;
  3041 	iFixupCount = newCount;
  3042 	iFixups = fixups;
  3043 	return newFixups;
  3044 	}
  3045 
  3046 
  3047 /**
  3048 Helper function for FixupImports.  Takes the set of
  3049 64-bit <addr,val> fixups, and organizes them into pages.
  3050 
  3051 Each page is stored as fXXX YYYY ZZZZ where YYYY ZZZZ is written
  3052 to the word at offset XXX.  (See PREQ1110 Design Sketch v1.0 S3.1.1.2.3.2.)
  3053 
  3054 On success iImportFixupTableSize is set to the table size in bytes,
  3055 and iImportFixupTable is a cell containing the table.
  3056 
  3057 @return					Symbian OS error code.
  3058 */
  3059 TInt E32Image::BuildImportFixupTable()
  3060 	{
  3061 	__IF_DEBUG(Printf(">BuildImportFixupTable,0x%08x,%d", iFixups, iFixupCount));
  3062 
  3063 	// sort the array in address order, to organize by page
  3064 	RArray<TUint64> fixup64ToSort(sizeof(TUint64), iFixups, iFixupCount);
  3065 	// SortUnsigned doesn't work on TUint64
  3066 	fixup64ToSort.Sort(TLinearOrder<TUint64>(Uint64LinearOrderFunc));
  3067 
  3068 	// now have <address | new-value> pairs, organize into pages.
  3069 	// Each page is stored as fXXX YYYY ZZZZ where YYYY ZZZZ is written
  3070 	// to the word at offset XXX.  (See PREQ1110 Design Sketch v1.0 S3.1.1.2.3.2.)
  3071 
  3072 	TUint32 pageCount = SizeToPageCount(iCodeSize);
  3073 	iImportFixupTableSize = (pageCount+1) * sizeof(TUint32) + iFixupCount * 3 * sizeof(TUint16);
  3074 	iImportFixupTable = (TUint32*) User::Alloc(iImportFixupTableSize);
  3075 	__IF_DEBUG(Printf("iImportFixupTable=0x%08x", iImportFixupTable));
  3076 	if (iImportFixupTable == 0)
  3077 		return KErrNoMemory;
  3078 
  3079 	// byte offsets of pages into the table are written as 32-bit words at
  3080 	// the start of the table
  3081 
  3082 	TUint32 lastPage = 0;
  3083 	// byte index of first 48-bit entry in the table, after sentinel index
  3084 	iImportFixupTable[0] = (pageCount + 1) * sizeof(TUint32);;
  3085 
  3086 	// location to which 48-bit imports are written
  3087 	TUint16* importOffset = (TUint16*)(iImportFixupTable + pageCount + 1);
  3088 
  3089 	// location from where 64-bit <addr,val> pairs are read
  3090 	const TUint64* avEnd = iFixups + iFixupCount;
  3091 
  3092 	for (const TUint64* avPtr = iFixups; avPtr < avEnd; ++avPtr)
  3093 		{
  3094 		TUint64 addr_val = *avPtr;
  3095 		TUint32 addr = I64HIGH(addr_val) - iCodeLoadAddress;
  3096 		TUint32 page = addr >> 12;
  3097 		if (page > lastPage)
  3098 			{
  3099 			// calculate new start index for current page
  3100 			TUint32 newStart = TUint32(importOffset) - TUint32(iImportFixupTable);
  3101 
  3102 			__IF_DEBUG(Printf("page=%d, lastPage=%d, newStart=0x%08x", page, lastPage, newStart));
  3103 
  3104 			// mark intermediate pages as zero-length, starting and ending at
  3105 			// current offset
  3106 			while (++lastPage <= page)
  3107 				iImportFixupTable[lastPage] = newStart;
  3108 			--lastPage;
  3109 			}
  3110 
  3111 		TUint16 offsetIntoPage;
  3112 		offsetIntoPage = (addr & KPageOffsetMask);
  3113 		*importOffset++ = offsetIntoPage;
  3114 
  3115 		TUint32 val = I64LOW(addr_val);
  3116 		*importOffset++ = val;				// low halfword stored first (YYYY)
  3117 		*importOffset++ = val >> 16;		// high halfword stored second (ZZZZ)
  3118 		}
  3119 
  3120 	// sentinel value marks end of table
  3121 	while (++lastPage <= pageCount)
  3122 		iImportFixupTable[lastPage] = iImportFixupTableSize;
  3123 
  3124 	__IF_DEBUG(Printf("processed table (size=%d,pageCount=%d)", iImportFixupTableSize, pageCount));
  3125 
  3126 #ifdef _DEBUG
  3127 	// dump the import fixup table if loader tracing enabled
  3128 	const TUint16* table16 = (const TUint16*)iImportFixupTable;
  3129 	const TInt halfWordsInTable = iImportFixupTableSize / 2;
  3130 	for (TInt i = 0; i < halfWordsInTable; i += 4)
  3131 		{
  3132 		__IF_DEBUG(Printf(
  3133 			"%04x: %04x %04x %04x %04x",
  3134 			i * 2, table16[i+0], table16[i+1], table16[i+2], table16[i+3]));
  3135 		}
  3136 #endif
  3137 
  3138 	User::Free(iFixups);
  3139 	iFixups = 0;
  3140 	return KErrNone;
  3141 	}
  3142 
  3143 
  3144 TInt GetModuleInfo(RLdrReq& aReq)
  3145 //
  3146 //	Read capabilities from file found
  3147 //
  3148 	{
  3149 	__IF_DEBUG(Printf("ReadModuleInfo %S",aReq.iFileName));
  3150 	TFileNameInfo& fi = aReq.iFileNameInfo;
  3151 	RImageFinder finder;
  3152 	TInt r = finder.Set(aReq);
  3153 	if (r == KErrNone)
  3154 		{
  3155 		finder.iFindExact = ETrue;
  3156 
  3157 		r = KErrNotSupported;
  3158 
  3159 		// must specify a fully qualified name
  3160 		if (fi.DriveLen() && fi.PathLen())
  3161 			{
  3162 			if (fi.VerLen())
  3163 				aReq.iRequestedVersion = fi.iVersion;
  3164 			else
  3165 				aReq.iRequestedVersion = KModuleVersionWild;
  3166 			r = finder.Search();
  3167 			if (r == KErrNone)
  3168 				{
  3169 				RLibrary::TInfo ret_info;
  3170 				memclr(&ret_info,sizeof(ret_info));
  3171 				ret_info.iModuleVersion = finder.iNew.iModuleVersion;
  3172 				ret_info.iUids = *(const TUidType*)finder.iNew.iUid;
  3173 				*(SSecurityInfo*)&ret_info.iSecurityInfo = finder.iNew.iS;
  3174 				TPckgC<RLibrary::TInfo> ret_pckg(ret_info);
  3175 				r = aReq.iMsg->Write(2, ret_pckg);
  3176 				}
  3177 			}
  3178 		}
  3179 	finder.Close();
  3180 	return r;
  3181 	}
  3182 
  3183 TInt GetInfoFromHeader(const RLoaderMsg& aMsg)
  3184 	{
  3185 	TInt r;
  3186 
  3187 	// Get size of header supplied by client
  3188 	TInt size;
  3189 	size = aMsg.GetDesLength(0);
  3190 	if(size<0)
  3191 		return size;
  3192 	if(size>RLibrary::KRequiredImageHeaderSize)
  3193 		size = RLibrary::KRequiredImageHeaderSize;
  3194 	if((TUint)size<sizeof(E32ImageHeaderV))
  3195 		return KErrUnderflow;
  3196 
  3197 	// Get header data
  3198 	TUint8* data = new TUint8[size];
  3199 	if(!data)
  3200 		return KErrNoMemory;
  3201 	TPtr8 ptr(data,size);
  3202 	r = aMsg.Read(0,ptr);
  3203 	if(r==KErrNone)
  3204 		{
  3205 		// Check header is valid
  3206 		E32ImageHeaderV* header=(E32ImageHeaderV*)data;
  3207 		if(header->TotalSize()>size)
  3208 			r = KErrUnderflow;
  3209 		else
  3210 			{
  3211 			TUint32 uncompressedSize;
  3212 			r = header->ValidateHeader(-1,uncompressedSize);
  3213 			}
  3214 		if(r==KErrNone)
  3215 			{
  3216 			// Get info
  3217 			RLibrary::TInfoV2 ret_info;
  3218 			memclr(&ret_info,sizeof(ret_info));
  3219 			ret_info.iModuleVersion = header->ModuleVersion();
  3220 			ret_info.iUids = (TUidType&)header->iUid1;
  3221 			header->GetSecurityInfo((SSecurityInfo&)ret_info.iSecurityInfo);
  3222 			ret_info.iHardwareFloatingPoint = (header->iFlags & KImageHWFloatMask) >> KImageHWFloatShift;
  3223 
  3224 			ret_info.iDebugAttributes = 0;	// default
  3225 			if (header->iFlags & KImageDebuggable)
  3226 				ret_info.iDebugAttributes |= RLibrary::TInfoV2::EDebugAllowed;
  3227 
  3228 			TPckg<RLibrary::TInfoV2> ret_pckg(ret_info);
  3229 			TInt max = aMsg.GetDesMaxLength(1);
  3230 			if (ret_pckg.Length() > max)
  3231 				ret_pckg.SetLength(max);
  3232 			r = aMsg.Write(1, ret_pckg);
  3233 			}
  3234 		}
  3235 
  3236 	delete[] data;
  3237 	return r;
  3238 	}
  3239 
  3240 #if defined(_DEBUG) || defined(_DEBUG_RELEASE)
  3241 void memory_dump(const TAny* a, TUint l)
  3242 	{
  3243 	TBuf8<80> buf;
  3244 	const TUint8* s = (const TUint8*)a;
  3245 	TInt n=0;
  3246 	while (l)
  3247 		{
  3248 		buf.Append(' ');
  3249 		buf.AppendNumFixedWidth(*s++, EHex, 2);
  3250 		--l;
  3251 		++n;
  3252 		if (l==0 || n==16)
  3253 			{
  3254 			RDebug::Printf((const char*)buf.PtrZ());
  3255 			buf.Zero();
  3256 			n=0;
  3257 			}
  3258 		}
  3259 	}
  3260 
  3261 void RImageFinder::Dump(const char* aTitle, TInt aR)
  3262 	{
  3263 	RDebug::Printf(aTitle);
  3264 	RDebug::Printf("r=%d",aR);
  3265 	if (iExisting)
  3266 		{
  3267 		RDebug::Printf("Existing image found");
  3268 		RDebug::Printf("Filename=%S Attr=%08x", &iExisting->iFileName, iExisting->iAttr);
  3269 		RDebug::Printf("SID %08x Caps %08x %08x", iExisting->iS.iSecureId, iExisting->iS.iCaps[1], iExisting->iS.iCaps[0]);
  3270 		const TUint32* uid = (const TUint32*)&iExisting->iUids;
  3271 		RDebug::Printf("UIDs %08x %08x %08x VER %08x", uid[0], uid[1], uid[2], iExisting->iModuleVersion);
  3272 		RDebug::Printf("Rom %08x", iExisting->iRomImageHeader);
  3273 		}
  3274 	else if (iNewValid)
  3275 		{
  3276 		RDebug::Printf("New image found");
  3277 		RDebug::Printf("Filename=%S Attr=%08x", &iNewFileName, iNew.iAttr);
  3278 		RDebug::Printf("SID %08x Caps %08x %08x", iNew.iS.iSecureId, iNew.iS.iCaps[1], iNew.iS.iCaps[0]);
  3279 		const TUint32* uid = (const TUint32*)iNew.iUid;
  3280 		RDebug::Printf("UIDs %08x %08x %08x VER %08x", uid[0], uid[1], uid[2], iNew.iModuleVersion);
  3281 		RDebug::Printf("Rom %08x", iNew.iRomImageHeader);
  3282 		}
  3283 	else
  3284 		{
  3285 		RDebug::Printf("No suitable image found");
  3286 		RDebug::Printf("#NM=%d #UidFail=%d #CapFail=%d #MajVFail=%d #ImpFail=%d", iNameMatches, iUidFail, iCapFail, iMajorVersionFail, iImportFail);
  3287 		}
  3288 	}
  3289 
  3290 void DumpImageHeader(const E32ImageHeader* a)
  3291 	{
  3292 	RDebug::Printf("E32ImageHeader at %08x :", a);
  3293 	TUint abi = a->ABI();
  3294 	TUint hdrfmt = a->HeaderFormat();
  3295 	TUint impfmt = a->ImportFormat();
  3296 	TUint eptfmt = a->EntryPointFormat();
  3297 	RDebug::Printf("Header format %d", hdrfmt>>KImageHdrFmtShift);
  3298 	RDebug::Printf("Import format %d", impfmt>>KImageImpFmtShift);
  3299 	RDebug::Printf("EntryPoint format %d", eptfmt>>KImageEptShift);
  3300 	RDebug::Printf("ABI %d", abi>>KImageABIShift);
  3301 	RDebug::Printf("UIDs %08x %08x %08x (%08x)", a->iUid1, a->iUid2, a->iUid3, a->iUidChecksum);
  3302 	RDebug::Printf("Header CRC %08x", a->iHeaderCrc);
  3303 	RDebug::Printf("Signature %08x", a->iSignature);
  3304 	RDebug::Printf("CPU %08x", (TUint)a->CpuIdentifier());
  3305 	RDebug::Printf("ModuleVersion %08x", a->ModuleVersion());
  3306 	RDebug::Printf("Compression Type %08x", a->CompressionType());
  3307 	RDebug::Printf("Tools Version %d.%02d(%d)", a->iToolsVersion.iMajor, a->iToolsVersion.iMinor, a->iToolsVersion.iBuild);
  3308 	RDebug::Printf("Flags %08x", a->iFlags);
  3309 	RDebug::Printf("Code Size %08x", a->iCodeSize);
  3310 	RDebug::Printf("Text Size %08x", a->iTextSize);
  3311 	RDebug::Printf("Data Size %08x", a->iDataSize);
  3312 	RDebug::Printf("BSS Size %08x", a->iBssSize);
  3313 	RDebug::Printf("Stack Size %08x", a->iStackSize);
  3314 	RDebug::Printf("HeapSizeMin %08x", a->iHeapSizeMin);
  3315 	RDebug::Printf("HeapSizeMax %08x", a->iHeapSizeMax);
  3316 	RDebug::Printf("iEntryPoint %08x", a->iEntryPoint);
  3317 	RDebug::Printf("iCodeBase %08x", a->iCodeBase);
  3318 	RDebug::Printf("iDataBase %08x", a->iDataBase);
  3319 	RDebug::Printf("DLL Ref Table Count %d", a->iDllRefTableCount);
  3320 	RDebug::Printf("Export Dir Count %d", a->iExportDirCount);
  3321 	RDebug::Printf("Code Offset %08x", a->iCodeOffset);
  3322 	RDebug::Printf("Data Offset %08x", a->iDataOffset);
  3323 	RDebug::Printf("Code Reloc Offset %08x", a->iCodeRelocOffset);
  3324 	RDebug::Printf("Data Reloc Offset %08x", a->iDataRelocOffset);
  3325 	RDebug::Printf("Import Offset %08x", a->iImportOffset);
  3326 	RDebug::Printf("Export Dir Offset %08x", a->iExportDirOffset);
  3327 	RDebug::Printf("Priority %d", (TUint)a->ProcessPriority());
  3328 	// KImageHdrFmt_J
  3329 	RDebug::Printf("iUncompressedSize %08x", ((E32ImageHeaderComp*)a)->iUncompressedSize);
  3330 	// KImageHdrFmt_V
  3331 	E32ImageHeaderV* v = (E32ImageHeaderV*)a;
  3332 	RDebug::Printf("SID %08x VID %08x CAP %08x %08x", v->iS.iSecureId, v->iS.iVendorId, v->iS.iCaps[1], v->iS.iCaps[0]);
  3333 	RDebug::Printf("iExportDescType %02x", v->iExportDescType);
  3334 	RDebug::Printf("iExportDescSize %04x", v->iExportDescSize);
  3335 	if (v->iExportDescSize)
  3336 		memory_dump(v->iExportDesc, v->iExportDescSize);
  3337 	}
  3338 #endif
  3339