os/kernelhwsrv/kerneltest/f32test/loader/t_ldrtst.cpp
author sl
Tue, 10 Jun 2014 14:32:02 +0200
changeset 1 260cb5ec6c19
permissions -rw-r--r--
Update contrib.
sl@0
     1
// Copyright (c) 1999-2009 Nokia Corporation and/or its subsidiary(-ies).
sl@0
     2
// All rights reserved.
sl@0
     3
// This component and the accompanying materials are made available
sl@0
     4
// under the terms of the License "Eclipse Public License v1.0"
sl@0
     5
// which accompanies this distribution, and is available
sl@0
     6
// at the URL "http://www.eclipse.org/legal/epl-v10.html".
sl@0
     7
//
sl@0
     8
// Initial Contributors:
sl@0
     9
// Nokia Corporation - initial contribution.
sl@0
    10
//
sl@0
    11
// Contributors:
sl@0
    12
//
sl@0
    13
// Description:
sl@0
    14
// f32test\loader\t_ldrtst.cpp
sl@0
    15
// 
sl@0
    16
//
sl@0
    17
sl@0
    18
#define __E32TEST_EXTENSION__
sl@0
    19
sl@0
    20
#include "t_hash.h"
sl@0
    21
#include "t_ldrtst.h"
sl@0
    22
#include "../../../e32test/mmu/d_memorytest.h"
sl@0
    23
sl@0
    24
#if defined(__WINS__)
sl@0
    25
	#include <e32wins.h>
sl@0
    26
	#include <emulator.h>
sl@0
    27
#elif defined(__EPOC32__)
sl@0
    28
	#include <f32image.h>
sl@0
    29
#endif
sl@0
    30
sl@0
    31
const TInt KNumberOfCorruptFiles = 2;
sl@0
    32
sl@0
    33
RTest test(_L("T_LDRTST"));
sl@0
    34
sl@0
    35
LoaderTest* TheLoaderTest;
sl@0
    36
RFs Fs;
sl@0
    37
#if defined (__X86__) || defined(__WINS__)
sl@0
    38
TBool NoRemovable=ETrue;
sl@0
    39
#else
sl@0
    40
TBool NoRemovable=EFalse;
sl@0
    41
#endif
sl@0
    42
sl@0
    43
/** Error code of simulated RFs error */
sl@0
    44
const TInt KRFsError = -99;
sl@0
    45
sl@0
    46
/**
sl@0
    47
	Number of drives which are identified by a numeric value,
sl@0
    48
	which means, e.g., run from an internal pageable drive.
sl@0
    49
 */
sl@0
    50
const TInt KSpecialDriveCount = 2;
sl@0
    51
sl@0
    52
/** The real drive letters corresponding to each special drive. */
sl@0
    53
static TFixedArray<TText, KSpecialDriveCount> SpecialDrives;
sl@0
    54
sl@0
    55
/** Bitmask of paged and unpaged module flags. */
sl@0
    56
const TUint32 KModulePagedCodeFlags = (KModuleFlagPagedCode | KModuleFlagUnpagedCode);
sl@0
    57
sl@0
    58
_LIT(KSysHash,"?:\\Sys\\Hash\\");
sl@0
    59
sl@0
    60
TInt GetModuleFlags(TInt aModule)
sl@0
    61
	{
sl@0
    62
	TInt f = ModuleFlags[aModule];
sl@0
    63
#ifdef __WINS__
sl@0
    64
	// paged and unpaged flags are not supported on the emulator
sl@0
    65
	f &= ~KModulePagedCodeFlags;
sl@0
    66
	// On emulator, treat all modules as XIP, all EXEs as fixed
sl@0
    67
	f |= KModuleFlagXIP;
sl@0
    68
	if (f & KModuleFlagExe)
sl@0
    69
		f|=KModuleFlagFixed;
sl@0
    70
#endif	// #ifdef __EPOC32__
sl@0
    71
	return f;
sl@0
    72
	}
sl@0
    73
sl@0
    74
TModuleSet::TModuleSet()
sl@0
    75
	{
sl@0
    76
	Mem::FillZ(this,sizeof(TModuleSet));
sl@0
    77
	}
sl@0
    78
sl@0
    79
void TModuleSet::Add(TInt aModule)
sl@0
    80
	{
sl@0
    81
	TUint8 m=(TUint8)(1<<(aModule&7));
sl@0
    82
	TInt i=aModule>>3;
sl@0
    83
	if (!(iBitMap[i]&m))
sl@0
    84
		{
sl@0
    85
		iBitMap[i]|=m;
sl@0
    86
		++iCount;
sl@0
    87
		}
sl@0
    88
	}
sl@0
    89
sl@0
    90
void TModuleSet::Remove(TInt aModule)
sl@0
    91
	{
sl@0
    92
	TUint8 m=(TUint8)(1<<(aModule&7));
sl@0
    93
	TInt i=aModule>>3;
sl@0
    94
	if (iBitMap[i]&m)
sl@0
    95
		{
sl@0
    96
		iBitMap[i]&=~m;
sl@0
    97
		--iCount;
sl@0
    98
		}
sl@0
    99
	}
sl@0
   100
sl@0
   101
TModuleSet::TModuleSet(const TModuleList& aList, TInt aMask, TInt aVal)
sl@0
   102
	{
sl@0
   103
	Mem::FillZ(this,sizeof(TModuleSet));
sl@0
   104
	TInt i;
sl@0
   105
	for (i=0; i<aList.iCount; ++i)
sl@0
   106
		{
sl@0
   107
		TInt m=aList.iInfo[i].iDllNum;
sl@0
   108
		if (((GetModuleFlags(m)&aMask)^aVal)==0)
sl@0
   109
			Add(aList.iInfo[i].iDllNum);
sl@0
   110
		}
sl@0
   111
	}
sl@0
   112
sl@0
   113
void TModuleSet::Remove(const TModuleList& aList)
sl@0
   114
	{
sl@0
   115
	TInt i;
sl@0
   116
	for (i=0; i<aList.iCount; ++i)
sl@0
   117
		Remove(aList.iInfo[i].iDllNum);
sl@0
   118
	}
sl@0
   119
sl@0
   120
void TModuleSet::Display(const TDesC& aTitle) const
sl@0
   121
	{
sl@0
   122
	TBuf<256> s=aTitle;
sl@0
   123
	TInt i;
sl@0
   124
	for (i=0; i<iCount; ++i)
sl@0
   125
		{
sl@0
   126
		if (Present(i))
sl@0
   127
			s.AppendFormat(_L("%3d "),i);
sl@0
   128
		}
sl@0
   129
	test.Printf(_L("%S\n"),&s);
sl@0
   130
	}
sl@0
   131
sl@0
   132
TModuleList::TModuleList()
sl@0
   133
	{
sl@0
   134
	iCount=0;
sl@0
   135
	Mem::Fill(iInfo, KNumModules*sizeof(SDllInfo), 0xff);
sl@0
   136
	}
sl@0
   137
sl@0
   138
void TModuleList::SetCount()
sl@0
   139
	{
sl@0
   140
	TInt i;
sl@0
   141
	for (i=0; i<KNumModules && iInfo[i].iDllNum>=0; ++i) {}
sl@0
   142
	iCount=i;
sl@0
   143
	}
sl@0
   144
sl@0
   145
void TModuleList::Display(const TDesC& aTitle) const
sl@0
   146
	{
sl@0
   147
	TBuf<256> s=aTitle;
sl@0
   148
	TInt i;
sl@0
   149
	for (i=0; i<iCount; ++i)
sl@0
   150
		{
sl@0
   151
		TInt modnum=iInfo[i].iDllNum;
sl@0
   152
		s.AppendFormat(_L("%3d "),modnum);
sl@0
   153
		}
sl@0
   154
	test.Printf(_L("%S\n"),&s);
sl@0
   155
	}
sl@0
   156
sl@0
   157
TBool TModuleList::IsPresent(TInt aModNum) const
sl@0
   158
	{
sl@0
   159
	return Find(aModNum)>=0;
sl@0
   160
	}
sl@0
   161
sl@0
   162
TInt TModuleList::Find(TInt aModNum) const
sl@0
   163
	{
sl@0
   164
	TInt i;
sl@0
   165
	for (i=iCount-1; i>=0 && iInfo[i].iDllNum!=aModNum; --i) {}
sl@0
   166
	return i;
sl@0
   167
	}
sl@0
   168
sl@0
   169
void TModuleList::Add(const SDllInfo& a)
sl@0
   170
	{
sl@0
   171
	iInfo[iCount++]=a;
sl@0
   172
	}
sl@0
   173
sl@0
   174
sl@0
   175
RMemoryTestLdd TestLdd;
sl@0
   176
sl@0
   177
TBool AddressReadable(TLinAddr a)
sl@0
   178
	{
sl@0
   179
	TUint32 value;
sl@0
   180
	return TestLdd.ReadMemory((TAny*)a,value)==KErrNone;
sl@0
   181
	}
sl@0
   182
sl@0
   183
TInt LoaderTest::DetermineDllLoadResult(TInt aDllNum, TInt aExeNum)
sl@0
   184
	{
sl@0
   185
	TBool proc_sym=(iMemModelAtt & (EMemModelAttrSameVA|EMemModelAttrSupportFixed))==EMemModelAttrSameVA;
sl@0
   186
	const TInt* exeinfo=ModuleExeInfo[aDllNum];
sl@0
   187
	TInt attp=exeinfo[0];
sl@0
   188
	TInt linkexe=exeinfo[1];
sl@0
   189
	TInt dllflags=GetModuleFlags(aDllNum);
sl@0
   190
	TInt exeflags=GetModuleFlags(aExeNum);
sl@0
   191
sl@0
   192
#ifdef __EPOC32__
sl@0
   193
	// if NP and DEFAULTPAGED or DEFAULTUNPAGED (not NOPAGING or ALWAYSPAGE) then
sl@0
   194
	// executable identified as corrupt, unless previous conditions in S3.1.3.2 cause
sl@0
   195
	// it to be paged or unpaged without examining the flags.
sl@0
   196
sl@0
   197
	TUint32 policy = E32Loader::PagingPolicy();
sl@0
   198
	test.Printf(_L("DetermineDllLoadResult,dll=%d,exe=%d,dllflags=0x%x,policy=0x%x\n"), aDllNum, aExeNum, dllflags, policy);
sl@0
   199
sl@0
   200
	TBool flagsChecked =
sl@0
   201
			policy != EKernelConfigCodePagingPolicyNoPaging					// 3.1.3.2.1, policy != no paging
sl@0
   202
		&&	(dllflags & KModuleFlagIDrive) != 0							// 3.1.3.2.2-3, pageable drive
sl@0
   203
		&&	(dllflags & (KModuleFlagUncompressed | KModuleFlagBytePair)) != 0	// 3.1.3.2.4 pageable format
sl@0
   204
		&&	policy != EKernelConfigCodePagingPolicyAlwaysPage;				// 3.1.3.2.5, policy != ALWAYS
sl@0
   205
	
sl@0
   206
	if (flagsChecked && (dllflags & KModulePagedCodeFlags) == KModulePagedCodeFlags)
sl@0
   207
		{
sl@0
   208
		TBool codePolDefUnpaged = (policy == EKernelConfigCodePagingPolicyDefaultUnpaged);
sl@0
   209
		TBool codePolDefPaged = (policy == EKernelConfigCodePagingPolicyDefaultPaged);
sl@0
   210
		if (codePolDefPaged || codePolDefUnpaged)
sl@0
   211
			return KErrCorrupt;
sl@0
   212
		}
sl@0
   213
#endif
sl@0
   214
sl@0
   215
	if (linkexe>=0 && linkexe!=aExeNum)
sl@0
   216
		return KErrNotSupported;	// if DLL links to a different EXE, no good
sl@0
   217
	if (!(dllflags&KModuleFlagDataInTree))
sl@0
   218
		return KErrNone;			// if no data in DLL tree, OK
sl@0
   219
	if (proc_sym)
sl@0
   220
		return KErrNone;			// if all user processes equivalent, OK
sl@0
   221
	if (!(dllflags&KModuleFlagXIPDataInTree))
sl@0
   222
		return KErrNone;			// if no XIP modules with data in DLL tree, OK
sl@0
   223
sl@0
   224
#ifdef __EPOC32__
sl@0
   225
	if (attp<0 || !(GetModuleFlags(attp)&KModuleFlagFixed))
sl@0
   226
		{
sl@0
   227
		// moving processes only
sl@0
   228
		if (!(exeflags&KModuleFlagFixed))
sl@0
   229
			return KErrNone;
sl@0
   230
		return KErrNotSupported;
sl@0
   231
		}
sl@0
   232
	// fixed attach process only
sl@0
   233
	if (aExeNum!=attp)
sl@0
   234
		return KErrNotSupported;
sl@0
   235
#else
sl@0
   236
	(void)attp;
sl@0
   237
	(void)exeflags;
sl@0
   238
#endif
sl@0
   239
	return KErrNone;
sl@0
   240
	}
sl@0
   241
sl@0
   242
TInt LoaderTest::DetermineDllLoadResult(TInt aDllNum, TInt aExeNum1, TInt aExeNum2)
sl@0
   243
	{
sl@0
   244
	// Determine result of loading aDllNum into aExeNum2 given that it's already loaded into aExeNum1
sl@0
   245
	// return KErrNone if code segment can be shared, 1 if it must be duplicated
sl@0
   246
	
sl@0
   247
	TBool proc_sym=(iMemModelAtt & (EMemModelAttrSameVA|EMemModelAttrSupportFixed))==EMemModelAttrSameVA;
sl@0
   248
	const TInt* exeinfo=ModuleExeInfo[aDllNum];
sl@0
   249
//	TInt attp=exeinfo[0];
sl@0
   250
	TInt linkexe=exeinfo[1];
sl@0
   251
	TInt dllflags=GetModuleFlags(aDllNum);
sl@0
   252
	TInt exe1flags=GetModuleFlags(aExeNum1);
sl@0
   253
	TInt exe2flags=GetModuleFlags(aExeNum2);
sl@0
   254
	if (linkexe>=0 && linkexe!=aExeNum2)
sl@0
   255
		return KErrNotSupported;	// if DLL links to a different EXE, no good
sl@0
   256
	if (!(dllflags&KModuleFlagDataInTree))
sl@0
   257
		return KErrNone;			// if no data in DLL tree, OK
sl@0
   258
	if (proc_sym)
sl@0
   259
		return KErrNone;			// if all user processes equivalent, OK
sl@0
   260
	if (!((exe1flags|exe2flags)&KModuleFlagFixed))
sl@0
   261
		return KErrNone;			// if neither process fixed, OK
sl@0
   262
	if (!(dllflags&KModuleFlagXIPDataInTree))
sl@0
   263
		return 1;					// if no XIP modules with data in DLL tree, OK but can't share
sl@0
   264
#ifdef __WINS__
sl@0
   265
	return KErrNone;
sl@0
   266
#else
sl@0
   267
	return KErrNotSupported;
sl@0
   268
#endif
sl@0
   269
	}
sl@0
   270
sl@0
   271
TBool LoaderTest::IsRomAddress(TLinAddr a)
sl@0
   272
	{
sl@0
   273
	const TRomHeader& rh=*(const TRomHeader*)UserSvr::RomHeaderAddress();
sl@0
   274
	return (a>=rh.iRomBase && (a-rh.iRomBase)<rh.iRomSize);
sl@0
   275
	}
sl@0
   276
sl@0
   277
TBool LoaderTest::IsRamCodeAddress(TLinAddr a)
sl@0
   278
	{
sl@0
   279
	switch (iMemModelAtt & EMemModelTypeMask)
sl@0
   280
		{
sl@0
   281
		case EMemModelTypeDirect:
sl@0
   282
			return ETrue;
sl@0
   283
		case EMemModelTypeMoving:
sl@0
   284
			return (a>=0xc0000000u);
sl@0
   285
		case EMemModelTypeMultiple:
sl@0
   286
			return (a<0x80000000u);
sl@0
   287
		case EMemModelTypeFlexible:
sl@0
   288
			return (a<0x80000000u);
sl@0
   289
		case EMemModelTypeEmul:
sl@0
   290
			return (a<0x80000000u);
sl@0
   291
		default:
sl@0
   292
			return EFalse;
sl@0
   293
		}
sl@0
   294
	}
sl@0
   295
sl@0
   296
TBool LoaderTest::CheckDataAddress(TLinAddr a, TInt aDllNum, TInt aExeNum)
sl@0
   297
	{
sl@0
   298
	TInt xf=GetModuleFlags(aExeNum);
sl@0
   299
	TInt df=GetModuleFlags(aDllNum);
sl@0
   300
	switch (iMemModelAtt & EMemModelTypeMask)
sl@0
   301
		{
sl@0
   302
		case EMemModelTypeDirect:
sl@0
   303
			return ETrue;
sl@0
   304
		case EMemModelTypeMoving:
sl@0
   305
			{
sl@0
   306
			const TRomHeader& rh=*(const TRomHeader*)UserSvr::RomHeaderAddress();
sl@0
   307
			if (!(xf&KModuleFlagFixed))
sl@0
   308
				return (a<0x40000000u);
sl@0
   309
			if ((xf&KModuleFlagXIP) && (df&KModuleFlagXIP))
sl@0
   310
				return (a>=rh.iKernDataAddress && a<rh.iKernelLimit);
sl@0
   311
			return (a>=rh.iKernelLimit && a<0xc0000000u);
sl@0
   312
			}
sl@0
   313
		case EMemModelTypeMultiple:
sl@0
   314
			return (a<0x80000000u);
sl@0
   315
		case EMemModelTypeFlexible:
sl@0
   316
			return (a<0x80000000u);
sl@0
   317
		case EMemModelTypeEmul:
sl@0
   318
			return (a<0x80000000u);
sl@0
   319
		default:
sl@0
   320
			return EFalse;
sl@0
   321
		}
sl@0
   322
	}
sl@0
   323
sl@0
   324
void LoaderTest::DumpModuleInfo(const SDllInfo& aInfo, TInt aExeNum)
sl@0
   325
	{
sl@0
   326
	TInt flags=GetModuleFlags(aInfo.iDllNum);
sl@0
   327
	TUint32 mmtype=iMemModelAtt & EMemModelTypeMask;
sl@0
   328
	TAny* h=iDev.ModuleCodeSeg(aInfo.iModuleHandle);
sl@0
   329
	if (!h)
sl@0
   330
		{
sl@0
   331
#ifdef __EPOC32__
sl@0
   332
		test(flags & KModuleFlagXIP);
sl@0
   333
		test(IsRomAddress(aInfo.iEntryPointAddress));
sl@0
   334
		test.Printf(_L("Module handle %08x ROM XIP\n"),aInfo.iModuleHandle);
sl@0
   335
#endif
sl@0
   336
		test(!(flags & KModuleFlagData));
sl@0
   337
		return;
sl@0
   338
		}
sl@0
   339
	TCodeSegCreateInfo info;
sl@0
   340
	TInt r=iDev.GetCodeSegInfo(h, info);
sl@0
   341
	test(r==KErrNone);
sl@0
   342
	TFileName fn;
sl@0
   343
	fn.Copy(info.iFileName);
sl@0
   344
	test.Printf(_L("DCodeSeg@%08x Data=%08x+%x,%x File %S,attr=0x%x\n"),h,info.iDataRunAddress,info.iDataSize,info.iBssSize,&fn,info.iAttr);
sl@0
   345
	TInt total_data_size=info.iDataSize+info.iBssSize;
sl@0
   346
#ifndef __WINS__
sl@0
   347
	// Don't do check below for WINS because:
sl@0
   348
	// a. It doesn't work on code warrior since it puts constants into .data
sl@0
   349
	// b. On MSCV with c++ exceptions enabled we also get data
sl@0
   350
	if (flags & KModuleFlagData)
sl@0
   351
		test(total_data_size!=0);
sl@0
   352
	else
sl@0
   353
		test(total_data_size==0);
sl@0
   354
sl@0
   355
	// ensure code paged iff expected.  This implements the logic from
sl@0
   356
	// PREQ1110 Design Sketch SGL.TS0022.008 v1.0 S3.1.3.2
sl@0
   357
sl@0
   358
	TUint policy = E32Loader::PagingPolicy();
sl@0
   359
sl@0
   360
	TBool expected;
sl@0
   361
	TBool isCodePaged = (info.iAttr & ECodeSegAttCodePaged)!=0;
sl@0
   362
sl@0
   363
	// 1. If paging policy is NOPAGING then executable is Unpaged.
sl@0
   364
	TUint32 memModelAttributes=UserSvr::HalFunction(EHalGroupKernel, EKernelHalMemModelInfo, NULL, NULL);
sl@0
   365
	if (policy == EKernelConfigCodePagingPolicyNoPaging || !(memModelAttributes&EMemModelAttrCodePaging))
sl@0
   366
		{
sl@0
   367
		test.Printf(_L("sbcpexp,1\n"));
sl@0
   368
		expected = false;
sl@0
   369
		}
sl@0
   370
	// 2. If ... media ... doesn't have Pageable Media Attribute then it is Unpaged.
sl@0
   371
	// (this has been superseded by BlockMap check on filesystem / media.  During these
sl@0
   372
	// tests, only the internal media supports paging.)
sl@0
   373
	else if ((flags & KModuleFlagIDrive) == 0)
sl@0
   374
		{
sl@0
   375
		test.Printf(_L("sbcpexp,2\n"));
sl@0
   376
		expected = false;
sl@0
   377
		}
sl@0
   378
	// 3. If ... removable media then it is Unpaged.
sl@0
   379
	// Not tested here because removable media (drive 1) covered by above case.
sl@0
   380
//	else if (MODULE_FILENAME(aInfo.iDllNum)[0] == '1')
sl@0
   381
//		{
sl@0
   382
//		test.Printf(_L("sbcpexp,2\n"));
sl@0
   383
//		expected = false;
sl@0
   384
//		}
sl@0
   385
	// 4. [If not bytepair [or uncompressed]] then Unpaged
sl@0
   386
	else if ((flags & (KModuleFlagBytePair | KModuleFlagUncompressed)) == 0)
sl@0
   387
		{
sl@0
   388
		test.Printf(_L("sbcpexp,3\n"));
sl@0
   389
		expected = false;
sl@0
   390
		}
sl@0
   391
	// 5. If the Paging Policy is ALWAYSPAGE then the executable is Paged.
sl@0
   392
	else if (policy == EKernelConfigCodePagingPolicyAlwaysPage)
sl@0
   393
		{
sl@0
   394
		test.Printf(_L("sbcpexp,4\n"));
sl@0
   395
		expected = true;
sl@0
   396
		}
sl@0
   397
	// 6. if KImageCodePaged and KImageCodePaged both set, should not reach here
sl@0
   398
	//	because load will have failed with KErrCorrupt.  If Paged on its own
sl@0
   399
	//	then paged; if unpaged on its own then unpaged
sl@0
   400
	else if ((flags & KModuleFlagPagedCode) != 0)
sl@0
   401
		{
sl@0
   402
		test.Printf(_L("sbcpexp,5\n"));
sl@0
   403
		expected = true;
sl@0
   404
		}
sl@0
   405
	else if ((flags & KModuleFlagUnpagedCode) != 0)
sl@0
   406
		{
sl@0
   407
		test.Printf(_L("sbcpexp,6\n"));
sl@0
   408
		expected = false;
sl@0
   409
		}
sl@0
   410
	// 7. Otherwise the PagingPolicy (DEFAULTPAGED or DEFAULTUNPAGED) determines
sl@0
   411
	//	how the executable is treated
sl@0
   412
	else
sl@0
   413
		{
sl@0
   414
		test.Printf(_L("sbcpexp,7\n"));
sl@0
   415
		expected = (policy == EKernelConfigCodePagingPolicyDefaultPaged);
sl@0
   416
		}
sl@0
   417
sl@0
   418
	test(expected == isCodePaged);
sl@0
   419
#endif
sl@0
   420
	if ((flags & KModuleFlagXIP) && mmtype!=EMemModelTypeEmul)
sl@0
   421
		test(IsRomAddress(aInfo.iEntryPointAddress));
sl@0
   422
	else
sl@0
   423
		{
sl@0
   424
		test(IsRamCodeAddress(aInfo.iEntryPointAddress));
sl@0
   425
		if(mmtype==EMemModelTypeFlexible)
sl@0
   426
			{
sl@0
   427
			// can't make assumtions about current processes address space
sl@0
   428
			}
sl@0
   429
		else if (mmtype==EMemModelTypeMultiple)
sl@0
   430
			{
sl@0
   431
			test(!AddressReadable(aInfo.iEntryPointAddress));
sl@0
   432
			}
sl@0
   433
		else
sl@0
   434
			{
sl@0
   435
			test(AddressReadable(aInfo.iEntryPointAddress));
sl@0
   436
			}
sl@0
   437
		}
sl@0
   438
sl@0
   439
	if (total_data_size!=0)
sl@0
   440
		test(CheckDataAddress(info.iDataRunAddress, aInfo.iDllNum, aExeNum));
sl@0
   441
	}
sl@0
   442
sl@0
   443
void LoaderTest::DumpModuleList(const TModuleList& aList, TInt aExeNum)
sl@0
   444
	{
sl@0
   445
	TInt i;
sl@0
   446
	for (i=0; i<aList.iCount; ++i)
sl@0
   447
		{
sl@0
   448
		TInt modnum=aList.iInfo[i].iDllNum;
sl@0
   449
		TInt entry=aList.iInfo[i].iEntryPointAddress;
sl@0
   450
		test.Printf(_L("MODULE %3d: ENTRY %08x "),modnum,entry);
sl@0
   451
		DumpModuleInfo(aList.iInfo[i],aExeNum);
sl@0
   452
		}
sl@0
   453
	}
sl@0
   454
sl@0
   455
void LoaderTest::CheckModuleList(TInt aRoot, const TModuleList& aList)
sl@0
   456
	{
sl@0
   457
	const TInt* deps=ModuleDependencies[aRoot];
sl@0
   458
	TInt ndeps=*deps++;
sl@0
   459
	TInt f=0;
sl@0
   460
	TInt i;
sl@0
   461
	for (i=0; i<ndeps; ++i)
sl@0
   462
		{
sl@0
   463
		TInt m=deps[i];
sl@0
   464
		f|=GetModuleFlags(m);
sl@0
   465
		}
sl@0
   466
	if (!(f&KModuleFlagDllInCycle))
sl@0
   467
		{
sl@0
   468
		i=0;		// indexes aList
sl@0
   469
		TInt j=0;	// indexes deps
sl@0
   470
		while(i<KNumModules)
sl@0
   471
			{
sl@0
   472
			if (j<ndeps)
sl@0
   473
				{
sl@0
   474
				if (!(GetModuleFlags(deps[j])&KModuleFlagExe))
sl@0
   475
					{
sl@0
   476
					test(aList.iInfo[i].iDllNum==deps[j]);
sl@0
   477
					++i;
sl@0
   478
					}
sl@0
   479
				++j;
sl@0
   480
				}
sl@0
   481
			else if (j==ndeps)
sl@0
   482
				{
sl@0
   483
				test(aList.iInfo[i].iDllNum==aRoot);
sl@0
   484
				++i;
sl@0
   485
				++j;
sl@0
   486
				}
sl@0
   487
			else
sl@0
   488
				{
sl@0
   489
				test(aList.iInfo[i].iDllNum<0);
sl@0
   490
				++i;
sl@0
   491
				}
sl@0
   492
			}
sl@0
   493
		}
sl@0
   494
	TModuleSet ml;
sl@0
   495
	TInt nd=ndeps;
sl@0
   496
	TBool root_included=EFalse;
sl@0
   497
	for (i=0; i<ndeps; ++i)
sl@0
   498
		{
sl@0
   499
		if (deps[i]==aRoot)
sl@0
   500
			root_included=ETrue;
sl@0
   501
		if (!(GetModuleFlags(deps[i])&KModuleFlagExe))
sl@0
   502
			ml.Add(deps[i]);
sl@0
   503
		else
sl@0
   504
			--nd;
sl@0
   505
		}
sl@0
   506
	test(ml.iCount==nd);
sl@0
   507
	for (i=0; i<KNumModules; ++i)
sl@0
   508
		{
sl@0
   509
		if (i<nd)
sl@0
   510
			{
sl@0
   511
			test(aList.iInfo[i].iDllNum>=0);
sl@0
   512
			ml.Remove(aList.iInfo[i].iDllNum);
sl@0
   513
			}
sl@0
   514
		else if (i==nd && !root_included)
sl@0
   515
			test(aList.iInfo[i].iDllNum==aRoot);
sl@0
   516
		else
sl@0
   517
			test(aList.iInfo[i].iDllNum<0);
sl@0
   518
		}
sl@0
   519
	test(ml.iCount==0);
sl@0
   520
	}
sl@0
   521
sl@0
   522
LoaderTest::LoaderTest()
sl@0
   523
	{
sl@0
   524
	Mem::Fill(iCmdLine, sizeof(iCmdLine), 0xff);
sl@0
   525
	iMemModelAtt=(TUint32)UserSvr::HalFunction(EHalGroupKernel, EKernelHalMemModelInfo, NULL, NULL);
sl@0
   526
	test.Printf(_L("MemModelAttributes=%08x\n"),iMemModelAtt);
sl@0
   527
	}
sl@0
   528
sl@0
   529
LoaderTest::~LoaderTest()
sl@0
   530
	{
sl@0
   531
	iFs.Close();
sl@0
   532
	iDev.Close();
sl@0
   533
	}
sl@0
   534
sl@0
   535
void LoaderTest::Init()
sl@0
   536
	{
sl@0
   537
	test.Next(_L("Load device driver"));
sl@0
   538
	TInt r=User::LoadLogicalDevice(_L("D_LDRTST"));
sl@0
   539
	test(r==KErrNone || r==KErrAlreadyExists);
sl@0
   540
	r=iDev.Open();
sl@0
   541
	test(r==KErrNone);
sl@0
   542
	r=iFs.Connect();
sl@0
   543
	test(r==KErrNone);
sl@0
   544
sl@0
   545
	TBuf<256> cmdline;
sl@0
   546
	User::CommandLine(cmdline);
sl@0
   547
	TLex lex(cmdline);
sl@0
   548
	TInt i;
sl@0
   549
	for (i=0; i<8; ++i)
sl@0
   550
		{
sl@0
   551
		lex.SkipSpace();
sl@0
   552
		if (lex.Eos())
sl@0
   553
			break;
sl@0
   554
		lex.Val(iCmdLine[i]);
sl@0
   555
		}
sl@0
   556
	}
sl@0
   557
sl@0
   558
LoaderTest* LoaderTest::New()
sl@0
   559
	{
sl@0
   560
	LoaderTest* p=new LoaderTest;
sl@0
   561
	test(p!=NULL);
sl@0
   562
	p->Init();
sl@0
   563
	return p;
sl@0
   564
	}
sl@0
   565
sl@0
   566
void LoaderTest::Close()
sl@0
   567
	{
sl@0
   568
	delete this;
sl@0
   569
	}
sl@0
   570
sl@0
   571
void LoaderTest::TraceOn()
sl@0
   572
	{
sl@0
   573
	iFs.SetDebugRegister(KFLDR);
sl@0
   574
	User::SetDebugMask(0xefdfffff);
sl@0
   575
	}
sl@0
   576
sl@0
   577
void LoaderTest::TraceOff()
sl@0
   578
	{
sl@0
   579
	iFs.SetDebugRegister(0);
sl@0
   580
	User::SetDebugMask(0x80000000);
sl@0
   581
	}
sl@0
   582
sl@0
   583
void LoaderTest::TestOneByOne()
sl@0
   584
	{
sl@0
   585
	test.Next(_L("Test all single EXE/DLL combinations"));
sl@0
   586
	TInt i=0;
sl@0
   587
	TInt r=0;
sl@0
   588
	TInt x=0;
sl@0
   589
	for (x=0; x<KNumModules; ++x)
sl@0
   590
		{
sl@0
   591
		if (!(GetModuleFlags(x)&KModuleFlagExe))
sl@0
   592
			continue;
sl@0
   593
#ifdef __WINS__
sl@0
   594
		if (GetModuleFlags(x)&KModuleFlagTargetOnly)
sl@0
   595
			continue;
sl@0
   596
#endif
sl@0
   597
		RProcess p;
sl@0
   598
		TUint32 tt;
sl@0
   599
		r=LoadExe(x, 0, p, tt);
sl@0
   600
		test.Printf(_L("LoadExe(%d)->%d\n"),x,r);
sl@0
   601
		test.Printf(_L("BENCHMARK: LoadExe(%d)->%dms\n"),x,tt);
sl@0
   602
		test(r==KErrNone);
sl@0
   603
		RLoaderTest lt;
sl@0
   604
		r=lt.Connect(x);
sl@0
   605
		test.Printf(_L("Connect(%d)->%d\n"),x,r);
sl@0
   606
		test(r==KErrNone);
sl@0
   607
		TModuleList exe_info;
sl@0
   608
		r=lt.GetExeDepList(exe_info.iInfo);
sl@0
   609
		test(r==KErrNone);
sl@0
   610
		exe_info.SetCount();
sl@0
   611
		DumpModuleList(exe_info, x);
sl@0
   612
		CheckModuleList(x, exe_info);
sl@0
   613
sl@0
   614
		TInt m;
sl@0
   615
		for (m=0; m<KNumModules; ++m)
sl@0
   616
			{
sl@0
   617
			if (GetModuleFlags(m)&KModuleFlagExe)
sl@0
   618
				continue;
sl@0
   619
#ifdef __WINS__
sl@0
   620
			if (GetModuleFlags(m)&KModuleFlagTargetOnly)
sl@0
   621
				continue;
sl@0
   622
#endif
sl@0
   623
sl@0
   624
			if ((GetModuleFlags(m) & KModuleFlagVDrive) && NoRemovable)
sl@0
   625
				{
sl@0
   626
				test.Printf(_L("LoadDll: Not testing dll %d from removable media\n"),m);
sl@0
   627
				continue;
sl@0
   628
				}
sl@0
   629
			TInt predicted=DetermineDllLoadResult(m,x);
sl@0
   630
			if (x==iCmdLine[1] && m==iCmdLine[2])
sl@0
   631
				TraceOn();
sl@0
   632
			TModuleList dll_init_info;
sl@0
   633
			TModuleList dll_c_info;
sl@0
   634
			TModuleList dll_d_info;
sl@0
   635
			TInt h=lt.LoadDll(m, dll_init_info.iInfo);
sl@0
   636
			dll_init_info.SetCount();
sl@0
   637
			test.Printf(_L("LoadDll(%d)->%d (%d)\n"),m,h,predicted);
sl@0
   638
sl@0
   639
			test(Min(h,0)==predicted);
sl@0
   640
			if (h>=0)
sl@0
   641
				{
sl@0
   642
				DumpModuleList(dll_init_info, x);
sl@0
   643
				CheckModuleList(m, dll_init_info);
sl@0
   644
				test(lt.GetCDList(dll_c_info.iInfo)==KErrNone);
sl@0
   645
				dll_c_info.SetCount();
sl@0
   646
				dll_c_info.Display(_L("Construct: "));
sl@0
   647
				if (!(GetModuleFlags(m)&KModuleFlagDllInCycle))
sl@0
   648
					{
sl@0
   649
					TInt j=0;
sl@0
   650
					for (i=0; i<dll_init_info.iCount; ++i)
sl@0
   651
						{
sl@0
   652
						TInt modnum=dll_init_info.iInfo[i].iDllNum;
sl@0
   653
						if ((GetModuleFlags(modnum)&KModuleFlagData) && !exe_info.IsPresent(modnum))
sl@0
   654
							{
sl@0
   655
							test(modnum==dll_c_info.iInfo[j].iDllNum);
sl@0
   656
							++j;
sl@0
   657
							}
sl@0
   658
						}
sl@0
   659
					test(j==dll_c_info.iCount);
sl@0
   660
					}
sl@0
   661
				else
sl@0
   662
					{
sl@0
   663
					TModuleSet ms(dll_init_info, KModuleFlagData, KModuleFlagData);
sl@0
   664
					ms.Remove(exe_info);
sl@0
   665
					test(ms.iCount==dll_c_info.iCount);
sl@0
   666
					ms.Remove(dll_c_info);
sl@0
   667
					test(ms.iCount==0);
sl@0
   668
					}
sl@0
   669
				TInt y=(7*m+59);
sl@0
   670
				r=lt.CallRBlkI(h,y);
sl@0
   671
				r-=y;
sl@0
   672
				r/=INC_BLOCK_SZ;
sl@0
   673
				test.Printf(_L("DLL %d RBlkI->%d\n"),m,r);
sl@0
   674
				y=ModuleRBlkIParams[m][1]+ModuleRBlkIParams[m][0]*DLLNUMOFFSET;
sl@0
   675
				test(r==y);
sl@0
   676
				r=lt.CloseDll(h);
sl@0
   677
				test.Printf(_L("CloseDll(%d)->%d\n"),h,r);
sl@0
   678
				test(r==KErrNone);
sl@0
   679
				test(lt.GetCDList(dll_d_info.iInfo)==KErrNone);
sl@0
   680
				dll_d_info.SetCount();
sl@0
   681
				dll_d_info.Display(_L("Destruct:  "));
sl@0
   682
				test(dll_d_info.iCount==dll_c_info.iCount);
sl@0
   683
				for (i=0; i<dll_d_info.iCount; ++i)
sl@0
   684
					test(dll_d_info.iInfo[i].iDllNum==dll_c_info.iInfo[dll_c_info.iCount-i-1].iDllNum);
sl@0
   685
				}
sl@0
   686
			if (x==iCmdLine[1] && m==iCmdLine[2])
sl@0
   687
				TraceOff();
sl@0
   688
			}
sl@0
   689
		lt.Exit();
sl@0
   690
		p.Close();
sl@0
   691
		}
sl@0
   692
	}
sl@0
   693
sl@0
   694
// return KErrNone if shared code, 1 if not shared
sl@0
   695
TInt LoaderTest::DetermineLoadExe2Result(TInt aExeNum)
sl@0
   696
	{
sl@0
   697
	if ( (iMemModelAtt&(EMemModelAttrSameVA|EMemModelAttrSupportFixed))==EMemModelAttrSameVA )
sl@0
   698
		return KErrNone;	// multiple memory model always supports multiple instances
sl@0
   699
	TUint32 f=GetModuleFlags(aExeNum);
sl@0
   700
	if (!(f&KModuleFlagFixed))
sl@0
   701
		return KErrNone;	// not fixed, so share code segment
sl@0
   702
	if (!(f&KModuleFlagDataInTree))
sl@0
   703
		{
sl@0
   704
#ifdef __EPOC32__
sl@0
   705
		return KErrNone;	// fixed but no data, so share code segment
sl@0
   706
#else
sl@0
   707
		return 1;			// on emulator, never share EXE code segments
sl@0
   708
#endif
sl@0
   709
		}
sl@0
   710
#ifdef __EPOC32__
sl@0
   711
	if (!(f&KModuleFlagXIP))
sl@0
   712
		return 1;			// fixed but not XIP, data in tree - create second code segment
sl@0
   713
	// fixed, XIP, data in tree
sl@0
   714
	return KErrAlreadyExists;
sl@0
   715
#else
sl@0
   716
	if (f & KModuleFlagExports)
sl@0
   717
		return KErrAlreadyExists;
sl@0
   718
	if (!(f & KModuleFlagData))
sl@0
   719
		return KErrNone;
sl@0
   720
	return 1;
sl@0
   721
#endif
sl@0
   722
	}
sl@0
   723
sl@0
   724
void LoaderTest::TestMultipleExeInstances()
sl@0
   725
	{
sl@0
   726
	test.Next(_L("Test multiple instantiation of EXEs"));
sl@0
   727
	TInt i=0;
sl@0
   728
	TInt r=0;
sl@0
   729
	TInt x=0;
sl@0
   730
	for (x=0; x<KNumModules; ++x)
sl@0
   731
		{
sl@0
   732
		TUint32 f=GetModuleFlags(x);
sl@0
   733
		if (!(f&KModuleFlagExe))
sl@0
   734
			continue;
sl@0
   735
#ifdef __WINS__
sl@0
   736
		if (f&KModuleFlagTargetOnly)
sl@0
   737
			continue;
sl@0
   738
#endif
sl@0
   739
		RProcess p1, p2;
sl@0
   740
		RLoaderTest lt1, lt2;
sl@0
   741
		TModuleList exe_info1;
sl@0
   742
		TModuleList exe_info2;
sl@0
   743
		TUint32 tt;
sl@0
   744
		r=LoadExe(x, 0, p1, tt);
sl@0
   745
		test.Printf(_L("LoadExe1(%d)->%d\n"),x,r);
sl@0
   746
		test.Printf(_L("BENCHMARK: LoadExe1(%d)->%dms\n"),x,tt);
sl@0
   747
		test(r==KErrNone);
sl@0
   748
		r=lt1.Connect(x, 0);
sl@0
   749
		test.Printf(_L("Connect1(%d)->%d\n"),x,r);
sl@0
   750
		test(r==KErrNone);
sl@0
   751
		TInt s=DetermineLoadExe2Result(x);
sl@0
   752
		r=LoadExe(x, 1, p2, tt);
sl@0
   753
		test.Printf(_L("LoadExe2(%d)->%d (%d)\n"),x,r,s);
sl@0
   754
		if (s==KErrNone)
sl@0
   755
			test.Printf(_L("BENCHMARK: LoadExe2(%d)->%dms\n"),x,tt);
sl@0
   756
		test(r==Min(s,0));
sl@0
   757
sl@0
   758
		if (r==KErrNone)
sl@0
   759
			{
sl@0
   760
			r=lt2.Connect(x, 1);
sl@0
   761
			test.Printf(_L("Connect2(%d)->%d\n"),x,r);
sl@0
   762
			test(r==KErrNone);
sl@0
   763
			r=lt1.GetExeDepList(exe_info1.iInfo);
sl@0
   764
			test(r==KErrNone);
sl@0
   765
			exe_info1.SetCount();
sl@0
   766
			DumpModuleList(exe_info1, x);
sl@0
   767
			r=lt2.GetExeDepList(exe_info2.iInfo);
sl@0
   768
			test(r==KErrNone);
sl@0
   769
			exe_info2.SetCount();
sl@0
   770
			DumpModuleList(exe_info2, x);
sl@0
   771
sl@0
   772
			test(exe_info1.iCount==exe_info2.iCount);
sl@0
   773
			if (s==1)
sl@0
   774
				{
sl@0
   775
				TInt nm=exe_info1.iCount;
sl@0
   776
				test(exe_info1.iInfo[nm-1].iModuleHandle!=exe_info2.iInfo[nm-1].iModuleHandle);
sl@0
   777
				}
sl@0
   778
#ifdef __WINS__
sl@0
   779
			else if((GetModuleFlags(x) & KModuleFlagData))
sl@0
   780
#else
sl@0
   781
			else
sl@0
   782
#endif
sl@0
   783
				{
sl@0
   784
				for (i=0; i<exe_info1.iCount; ++i)
sl@0
   785
					test(exe_info1.iInfo[i].iModuleHandle==exe_info2.iInfo[i].iModuleHandle);
sl@0
   786
				}
sl@0
   787
sl@0
   788
			const TInt* tests=TC_ExeLoad;
sl@0
   789
			TInt ntests=*tests++;
sl@0
   790
			while(ntests--)
sl@0
   791
				{
sl@0
   792
				TInt m=*tests++;
sl@0
   793
				TModuleList dll_init_info1;
sl@0
   794
				TModuleList dll_c_info1;
sl@0
   795
				TModuleList dll_d_info1;
sl@0
   796
				TModuleList dll_init_info2;
sl@0
   797
				TModuleList dll_c_info2;
sl@0
   798
				TModuleList dll_d_info2;
sl@0
   799
				TInt h1=lt1.LoadDll(m, dll_init_info1.iInfo);
sl@0
   800
				dll_init_info1.SetCount();
sl@0
   801
				test.Printf(_L("LoadDll1(%d)->%d\n"),m,h1);
sl@0
   802
				if (h1>=0)
sl@0
   803
					{
sl@0
   804
					DumpModuleList(dll_init_info1, x);
sl@0
   805
					CheckModuleList(m, dll_init_info1);
sl@0
   806
					test(lt1.GetCDList(dll_c_info1.iInfo)==KErrNone);
sl@0
   807
					dll_c_info1.SetCount();
sl@0
   808
					dll_c_info1.Display(_L("Construct1: "));
sl@0
   809
					TInt y=(41*m+487);
sl@0
   810
					r=lt1.CallRBlkI(h1,y);
sl@0
   811
					r-=y;
sl@0
   812
					r/=INC_BLOCK_SZ;
sl@0
   813
					test.Printf(_L("DLL1 %d RBlkI->%d\n"),m,r);
sl@0
   814
					y=ModuleRBlkIParams[m][1]+ModuleRBlkIParams[m][0]*DLLNUMOFFSET;
sl@0
   815
					test(r==y);
sl@0
   816
sl@0
   817
					TInt s=DetermineDllLoadResult(m, x, x);
sl@0
   818
					TInt h2=lt2.LoadDll(m, dll_init_info2.iInfo);
sl@0
   819
					dll_init_info2.SetCount();
sl@0
   820
					test.Printf(_L("LoadDll2(%d)->%d (%d)\n"),m,h2,s);
sl@0
   821
					test(h2==Min(s,0));
sl@0
   822
					if (h2>=0)
sl@0
   823
						{
sl@0
   824
						DumpModuleList(dll_init_info2, x);
sl@0
   825
						CheckModuleList(m, dll_init_info2);
sl@0
   826
						test(lt2.GetCDList(dll_c_info2.iInfo)==KErrNone);
sl@0
   827
						dll_c_info2.SetCount();
sl@0
   828
						dll_c_info2.Display(_L("Construct2: "));
sl@0
   829
						y=(79*m+257);
sl@0
   830
						r=lt2.CallRBlkI(h2,y);
sl@0
   831
						r-=y;
sl@0
   832
						r/=INC_BLOCK_SZ;
sl@0
   833
						test.Printf(_L("DLL2 %d RBlkI->%d\n"),m,r);
sl@0
   834
						y=ModuleRBlkIParams[m][1]+ModuleRBlkIParams[m][0]*DLLNUMOFFSET;
sl@0
   835
						test(r==y);
sl@0
   836
sl@0
   837
						test(dll_init_info1.iCount==dll_init_info2.iCount);
sl@0
   838
#ifdef __WINS__
sl@0
   839
						if (s==1 && !(ModuleFlags[m]&KModuleFlagDataInTree))
sl@0
   840
#else
sl@0
   841
						if (s==1)
sl@0
   842
#endif
sl@0
   843
							{
sl@0
   844
							TInt nm=dll_init_info1.iCount;
sl@0
   845
							test(dll_init_info1.iInfo[nm-1].iModuleHandle!=dll_init_info2.iInfo[nm-1].iModuleHandle);
sl@0
   846
							}
sl@0
   847
						else
sl@0
   848
							{
sl@0
   849
							for (i=0; i<dll_init_info1.iCount; ++i)
sl@0
   850
								test(dll_init_info1.iInfo[i].iModuleHandle==dll_init_info2.iInfo[i].iModuleHandle);
sl@0
   851
							}
sl@0
   852
sl@0
   853
						r=lt2.CloseDll(h2);
sl@0
   854
						test.Printf(_L("CloseDll2(%d)->%d\n"),h2,r);
sl@0
   855
						test(r==KErrNone);
sl@0
   856
						test(lt2.GetCDList(dll_d_info2.iInfo)==KErrNone);
sl@0
   857
						dll_d_info2.SetCount();
sl@0
   858
						dll_d_info2.Display(_L("Destruct2:  "));
sl@0
   859
						test(dll_d_info2.iCount==dll_c_info2.iCount);
sl@0
   860
						for (i=0; i<dll_d_info2.iCount; ++i)
sl@0
   861
							test(dll_d_info2.iInfo[i].iDllNum==dll_c_info2.iInfo[dll_c_info2.iCount-i-1].iDllNum);
sl@0
   862
						}
sl@0
   863
sl@0
   864
					r=lt1.CloseDll(h1);
sl@0
   865
					test.Printf(_L("CloseDll1(%d)->%d\n"),h1,r);
sl@0
   866
					test(r==KErrNone);
sl@0
   867
					test(lt1.GetCDList(dll_d_info1.iInfo)==KErrNone);
sl@0
   868
					dll_d_info1.SetCount();
sl@0
   869
					dll_d_info1.Display(_L("Destruct1:  "));
sl@0
   870
					test(dll_d_info1.iCount==dll_c_info1.iCount);
sl@0
   871
					for (i=0; i<dll_d_info1.iCount; ++i)
sl@0
   872
						test(dll_d_info1.iInfo[i].iDllNum==dll_c_info1.iInfo[dll_c_info1.iCount-i-1].iDllNum);
sl@0
   873
					}
sl@0
   874
				}
sl@0
   875
sl@0
   876
			lt2.Exit();
sl@0
   877
			p2.Close();
sl@0
   878
			}
sl@0
   879
		lt1.Exit();
sl@0
   880
		p1.Close();
sl@0
   881
		}
sl@0
   882
	}
sl@0
   883
sl@0
   884
void SetLoaderFail(TInt aLdr, TInt aKern)
sl@0
   885
	{
sl@0
   886
	test.Printf(_L("ldr=%d, kern=%d\n"),aLdr,aKern);
sl@0
   887
	RLoader l;
sl@0
   888
	test(l.Connect()==KErrNone);
sl@0
   889
	test(l.DebugFunction(ELoaderDebug_SetHeapFail, aLdr, aKern, 0)==KErrNone);
sl@0
   890
	l.Close();
sl@0
   891
	}
sl@0
   892
sl@0
   893
void SetLoaderFailRFs(TInt aError, TInt aCount)
sl@0
   894
	{
sl@0
   895
	test.Printf(_L("SetLoaderFailRFs: error=%d, count=%d\n"),aError,aCount);
sl@0
   896
	RLoader l;
sl@0
   897
	test(l.Connect()==KErrNone);
sl@0
   898
	test(l.DebugFunction(ELoaderDebug_SetRFsFail, aError, aCount, 0)==KErrNone);
sl@0
   899
	l.Close();
sl@0
   900
	}
sl@0
   901
sl@0
   902
class TLoopOOM
sl@0
   903
	{
sl@0
   904
public:
sl@0
   905
	enum OomState{EInit, EKernelHeap, EUserHeap, ERFsError};
sl@0
   906
sl@0
   907
	TLoopOOM();
sl@0
   908
	void Reset();
sl@0
   909
	TBool Iterate(TInt aResult);
sl@0
   910
public:
sl@0
   911
	TInt iLdr;
sl@0
   912
	TInt iKern;
sl@0
   913
	TInt iRFsCount;
sl@0
   914
	OomState iState;
sl@0
   915
	};
sl@0
   916
sl@0
   917
TLoopOOM::TLoopOOM()
sl@0
   918
	{
sl@0
   919
	Reset();
sl@0
   920
	}
sl@0
   921
sl@0
   922
void TLoopOOM::Reset()
sl@0
   923
	{
sl@0
   924
	iLdr = 0;
sl@0
   925
	iKern = 0;
sl@0
   926
	iRFsCount = 0;
sl@0
   927
	iState = EInit;
sl@0
   928
	}
sl@0
   929
sl@0
   930
TBool TLoopOOM::Iterate(TInt aResult)
sl@0
   931
	{
sl@0
   932
	TBool noErrors = (aResult==KErrNone||aResult==KErrNotSupported);
sl@0
   933
sl@0
   934
	test.Printf(_L("%d %d %d %d\n"), iKern,iLdr,iRFsCount,aResult);
sl@0
   935
sl@0
   936
	switch(iState)
sl@0
   937
		{
sl@0
   938
sl@0
   939
	case EInit:
sl@0
   940
		iState = EKernelHeap;
sl@0
   941
		SetLoaderFail(iLdr,++iKern);
sl@0
   942
		return ETrue;
sl@0
   943
sl@0
   944
	case EKernelHeap:
sl@0
   945
		if (noErrors)
sl@0
   946
			{
sl@0
   947
			iKern = 0;
sl@0
   948
			iLdr = 1;
sl@0
   949
			iState = EUserHeap;
sl@0
   950
			}
sl@0
   951
		else
sl@0
   952
			++iKern;
sl@0
   953
sl@0
   954
		SetLoaderFail(iLdr,iKern);
sl@0
   955
		return ETrue;
sl@0
   956
	
sl@0
   957
	case EUserHeap:
sl@0
   958
		if (noErrors)
sl@0
   959
			{
sl@0
   960
			iLdr = 0;
sl@0
   961
			iState = ERFsError;
sl@0
   962
			SetLoaderFail(0,0);
sl@0
   963
			SetLoaderFailRFs(KRFsError, ++iRFsCount);
sl@0
   964
			}
sl@0
   965
		else
sl@0
   966
			SetLoaderFail(++iLdr,iKern);
sl@0
   967
		return ETrue;
sl@0
   968
	
sl@0
   969
	case ERFsError:
sl@0
   970
		if (noErrors)
sl@0
   971
			break;
sl@0
   972
		else
sl@0
   973
			{
sl@0
   974
			SetLoaderFailRFs(KRFsError, ++iRFsCount);
sl@0
   975
			return ETrue;
sl@0
   976
			}
sl@0
   977
		}
sl@0
   978
sl@0
   979
	SetLoaderFailRFs(KErrNone, 0);
sl@0
   980
	return EFalse;
sl@0
   981
	}
sl@0
   982
sl@0
   983
void LoaderTest::TestOOM()
sl@0
   984
	{
sl@0
   985
	test.Next(_L("Test OOM Handling"));
sl@0
   986
#ifdef _DEBUG
sl@0
   987
	TInt r=0;
sl@0
   988
	TInt x=0;
sl@0
   989
	TUint32 tt;
sl@0
   990
	for (x=0; x<KNumModules; ++x)
sl@0
   991
		{
sl@0
   992
		if (!(GetModuleFlags(x)&KModuleFlagExe))
sl@0
   993
			continue;
sl@0
   994
#ifdef __WINS__
sl@0
   995
		if (GetModuleFlags(x)&KModuleFlagTargetOnly)
sl@0
   996
			continue;
sl@0
   997
#endif
sl@0
   998
sl@0
   999
		if ((GetModuleFlags(x) & KModuleFlagVDrive) && NoRemovable)
sl@0
  1000
			{
sl@0
  1001
			test.Printf(_L("LoaderTest::TestOOM Not testing dll %d from removable media\n"),x);
sl@0
  1002
			continue;
sl@0
  1003
			}
sl@0
  1004
		if (x==iCmdLine[1])
sl@0
  1005
			TraceOn();
sl@0
  1006
		TLoopOOM loom;
sl@0
  1007
		RProcess p;
sl@0
  1008
		RLoaderTest lt;
sl@0
  1009
		while(loom.Iterate(r))
sl@0
  1010
			{
sl@0
  1011
			r=LoadExe(x, 0, p, tt);
sl@0
  1012
			test.Printf(_L("LoadExe(%d)->%d\n"),x,r);
sl@0
  1013
			test(r==KErrNone || (loom.iState!=TLoopOOM::ERFsError && r==KErrNoMemory) || 
sl@0
  1014
				(loom.iState==TLoopOOM::ERFsError && r==KRFsError));
sl@0
  1015
			if (r==KErrNone)
sl@0
  1016
				{
sl@0
  1017
				TInt s=lt.Connect(x);
sl@0
  1018
				test.Printf(_L("Connect(%d)->%d\n"),x,s);
sl@0
  1019
				test(s==KErrNone);
sl@0
  1020
				lt.Exit();
sl@0
  1021
				p.Close();
sl@0
  1022
				}
sl@0
  1023
			}
sl@0
  1024
		SetLoaderFail(0,0);
sl@0
  1025
		r=LoadExe(x, 0, p, tt);
sl@0
  1026
		test(r==KErrNone);
sl@0
  1027
		r=lt.Connect(x);
sl@0
  1028
		test(r==KErrNone);
sl@0
  1029
		const TInt* tests=TC_DllOOM;
sl@0
  1030
		TInt ntests=*tests++;
sl@0
  1031
		TModuleList list;
sl@0
  1032
		while(ntests--)
sl@0
  1033
			{
sl@0
  1034
			TInt m=*tests++;
sl@0
  1035
			if ((GetModuleFlags(m) & KModuleFlagVDrive) && NoRemovable)
sl@0
  1036
				{
sl@0
  1037
				test.Printf(_L("LoaderTest::TestOOM Not testing dll %d from removable media\n"),m);
sl@0
  1038
				continue;
sl@0
  1039
				}
sl@0
  1040
			loom.Reset();
sl@0
  1041
			r=KErrNone;
sl@0
  1042
			while(loom.Iterate(r))
sl@0
  1043
				{
sl@0
  1044
				TInt h=lt.LoadDll(m, list.iInfo);
sl@0
  1045
				r=Min(h,0);
sl@0
  1046
				test.Printf(_L("%d:LoadDll(%d)->%d\n"),x,m,h);
sl@0
  1047
				
sl@0
  1048
				test(r==KErrNone || r==KErrNotSupported || KErrNoMemory || 
sl@0
  1049
					(loom.iState==TLoopOOM::ERFsError && r==KRFsError) );
sl@0
  1050
					
sl@0
  1051
				if (r==KErrNone)
sl@0
  1052
					{
sl@0
  1053
					TInt s=lt.CloseDll(h);
sl@0
  1054
					test(s==KErrNone);
sl@0
  1055
					}
sl@0
  1056
				}
sl@0
  1057
			}
sl@0
  1058
		lt.Exit();
sl@0
  1059
		p.Close();
sl@0
  1060
		if (x==iCmdLine[1])
sl@0
  1061
			TraceOff();
sl@0
  1062
		}
sl@0
  1063
#else
sl@0
  1064
	test.Printf(_L("Only on DEBUG builds\n"));
sl@0
  1065
#endif
sl@0
  1066
	}
sl@0
  1067
sl@0
  1068
class RLoaderTestHandle : public RSessionBase
sl@0
  1069
	{
sl@0
  1070
public:
sl@0
  1071
	TInt Connect();
sl@0
  1072
	void TryToGetPaniced();
sl@0
  1073
	};
sl@0
  1074
sl@0
  1075
TInt RLoaderTestHandle::Connect()
sl@0
  1076
	{
sl@0
  1077
	return CreateSession(_L("!Loader"),TVersion(KLoaderMajorVersionNumber,KLoaderMinorVersionNumber,KE32BuildVersionNumber));
sl@0
  1078
	}
sl@0
  1079
sl@0
  1080
void RLoaderTestHandle::TryToGetPaniced()
sl@0
  1081
	{
sl@0
  1082
	_LIT(KFoo,"foo");
sl@0
  1083
	TLdrInfo info;
sl@0
  1084
	TPckg<TLdrInfo> infoBuf(info);
sl@0
  1085
	TIpcArgs args;
sl@0
  1086
	args.Set(0,(TDes8*)&infoBuf);
sl@0
  1087
	args.Set(1,&KFoo);
sl@0
  1088
	args.Set(2,&KFoo);
sl@0
  1089
	SendReceive(ELoadLibrary, args);
sl@0
  1090
	}
sl@0
  1091
sl@0
  1092
TInt PanicTestThread(TAny*)
sl@0
  1093
	{
sl@0
  1094
	RLoaderTestHandle t;
sl@0
  1095
	TInt r = t.Connect();
sl@0
  1096
	if (r==KErrNone) t.TryToGetPaniced();
sl@0
  1097
	return r;
sl@0
  1098
	}
sl@0
  1099
sl@0
  1100
sl@0
  1101
void TestCorruptedFiles()
sl@0
  1102
	{
sl@0
  1103
	test.Next(_L("Test corrupted files"));
sl@0
  1104
sl@0
  1105
	TInt numCorruptFiles=0;
sl@0
  1106
	TInt r=0;
sl@0
  1107
	for (TInt x=0; x<KNumModules; ++x)
sl@0
  1108
		{
sl@0
  1109
		if (!(GetModuleFlags(x)&KModuleFlagExe))
sl@0
  1110
			continue;
sl@0
  1111
sl@0
  1112
		const TPtrC fn = MODULE_FILENAME(x);
sl@0
  1113
		if (fn[1] != ':')
sl@0
  1114
			continue;
sl@0
  1115
sl@0
  1116
		if (++numCorruptFiles > KNumberOfCorruptFiles)
sl@0
  1117
			break;
sl@0
  1118
sl@0
  1119
		RProcess p;
sl@0
  1120
		TUint32 tt;
sl@0
  1121
		r=LoadExe(x, 0, p, tt);
sl@0
  1122
		test.Printf(_L("LoadCorruptExe(%d)->%d\n"),x,r);
sl@0
  1123
		test(r==KErrCorrupt);
sl@0
  1124
		}
sl@0
  1125
	}
sl@0
  1126
sl@0
  1127
// -------- copying files to non-ROM media --------
sl@0
  1128
sl@0
  1129
static void GetSpecialDrives()
sl@0
  1130
/**
sl@0
  1131
	Work out which physical drive corresponds to each
sl@0
  1132
	numeric drive in the list of filenames.  This populates
sl@0
  1133
	SpecialDrives.
sl@0
  1134
	
sl@0
  1135
	@see SpecialDrives
sl@0
  1136
 */
sl@0
  1137
	{
sl@0
  1138
	test.Printf(_L("NoRemovable=%d\n"),NoRemovable);
sl@0
  1139
sl@0
  1140
	// mark each special drive as not present
sl@0
  1141
	for (TInt i = 0; i < KSpecialDriveCount; ++i)
sl@0
  1142
		{
sl@0
  1143
		SpecialDrives[i] = '!';
sl@0
  1144
		}
sl@0
  1145
	
sl@0
  1146
	// cannot load binaries from emulated removable drives
sl@0
  1147
#if defined (__WINS__)
sl@0
  1148
	SpecialDrives[1] = 'c';			// "removable"
sl@0
  1149
#endif
sl@0
  1150
	
sl@0
  1151
	TBuf<12> hashDir;
sl@0
  1152
	hashDir = KSysHash;
sl@0
  1153
	hashDir[0] = (TUint8) RFs::GetSystemDriveChar();
sl@0
  1154
sl@0
  1155
	TInt r = Fs.MkDirAll(hashDir);
sl@0
  1156
	test(r == KErrNone || r == KErrAlreadyExists);
sl@0
  1157
sl@0
  1158
	for (TInt d = 0; d <= (TInt)sizeof(SpecialDriveList); ++d)
sl@0
  1159
		{
sl@0
  1160
		TInt dr = SpecialDriveList[d];
sl@0
  1161
		TDriveInfo di;
sl@0
  1162
		test.Printf(_L("Drive %d\n"), dr);
sl@0
  1163
		test(Fs.Drive(di, dr) == KErrNone);
sl@0
  1164
		if (di.iType == EMediaNotPresent)
sl@0
  1165
			continue;
sl@0
  1166
		
sl@0
  1167
		TChar ch0;
sl@0
  1168
		test(RFs::DriveToChar(dr, ch0) == KErrNone);
sl@0
  1169
		
sl@0
  1170
		TText ch = static_cast<TText>(TUint(ch0));
sl@0
  1171
		
sl@0
  1172
		// drive 0 == internal
sl@0
  1173
		if ((di.iDriveAtt & KDriveAttInternal) && SpecialDrives[0] == '!')
sl@0
  1174
			{
sl@0
  1175
			SpecialDrives[0] = ch;
sl@0
  1176
			if (NoRemovable)
sl@0
  1177
				SpecialDrives[1] = ch;
sl@0
  1178
			}
sl@0
  1179
		// drive 1 == removable
sl@0
  1180
		else if ((di.iDriveAtt & KDriveAttRemovable) && SpecialDrives[1] == '!' && !NoRemovable)
sl@0
  1181
			SpecialDrives[1] = ch;
sl@0
  1182
		else
sl@0
  1183
			{
sl@0
  1184
			// drive not useful so continue and don't create \sys\bin
sl@0
  1185
			continue;
sl@0
  1186
			}
sl@0
  1187
sl@0
  1188
		TFileName fn;
sl@0
  1189
		fn.Append(ch);
sl@0
  1190
		fn.Append(_L(":\\sys\\bin\\"));
sl@0
  1191
		r = Fs.MkDirAll(fn);
sl@0
  1192
		test.Printf(_L("MkDirAll %S returns %d\n"), &fn, r);
sl@0
  1193
		test(r == KErrNone || r == KErrAlreadyExists);
sl@0
  1194
		}
sl@0
  1195
	}
sl@0
  1196
sl@0
  1197
void GetNonZFileName(const TDesC& aOrigName, TDes& aNonZName)
sl@0
  1198
/**
sl@0
  1199
	Resolve a special drive to the target drive using the mappings in
sl@0
  1200
	SpecialDrives.  This is used to load non-XIP binaries from pageable media.
sl@0
  1201
	
sl@0
  1202
	@param	aOrigName		Fully-qualified filename with special drive number.
sl@0
  1203
							E.g., "3:\\sys\\bin\\dllt45.dll".
sl@0
  1204
	@param	aNonZName		Descriptor to populate with aOrigName and the transformed
sl@0
  1205
							drive, e.g. "c:\\sys\\bin\\dllt45.dll".
sl@0
  1206
 */
sl@0
  1207
	{
sl@0
  1208
	test.Printf(_L(">GetNonZFileName,\"%S\"\n"), &aOrigName);
sl@0
  1209
	test(aOrigName[1] == ':');
sl@0
  1210
	aNonZName.Copy(aOrigName);
sl@0
  1211
	TText replaceChar = SpecialDrives[aOrigName[0] - '0'];
sl@0
  1212
	test(TChar(replaceChar).IsAlpha());
sl@0
  1213
	aNonZName[0] = replaceChar;
sl@0
  1214
	test.Printf(_L("<GetNonZFileName,\"%S\"\n"), &aNonZName);
sl@0
  1215
	}
sl@0
  1216
sl@0
  1217
static void GetHashFileName(const TDesC& aOrigName, TDes& aHashName)
sl@0
  1218
/**
sl@0
  1219
	Get name of the hash file used for an EXE or DLL which has been
sl@0
  1220
	copied to writable media.
sl@0
  1221
sl@0
  1222
	@param	aOrigName		Name of EXE or DLL which has been copied to
sl@0
  1223
							writable media.  This does not have to be
sl@0
  1224
							qualified because only the name and extension
sl@0
  1225
							are used.
sl@0
  1226
	@param	aHashName		On return this is set to the absolute filename
sl@0
  1227
							which should contain the file's hash.  This
sl@0
  1228
							function does not create the file, or its containing
sl@0
  1229
							directory.
sl@0
  1230
 */
sl@0
  1231
	{
sl@0
  1232
	aHashName.Copy(KSysHash);
sl@0
  1233
	aHashName[0] = (TUint8) RFs::GetSystemDriveChar();
sl@0
  1234
	const TParsePtrC ppc(aOrigName);
sl@0
  1235
	aHashName.Append(ppc.NameAndExt());
sl@0
  1236
	}
sl@0
  1237
sl@0
  1238
static void CopyExecutablesL(TBool aCorruptMode=EFalse)
sl@0
  1239
/**
sl@0
  1240
	Make a copy of each executable that should be copied
sl@0
  1241
	to a writable drive.
sl@0
  1242
	
sl@0
  1243
	If aCorruptMode make KNumberOfCorruptFiles corrupted copies: truncated file and a file with corrupted header 
sl@0
  1244
sl@0
  1245
 */
sl@0
  1246
	{
sl@0
  1247
	TInt r;
sl@0
  1248
	TInt numCorruptFiles = 0;
sl@0
  1249
sl@0
  1250
	GetSpecialDrives();
sl@0
  1251
	
sl@0
  1252
	CFileMan* fm = CFileMan::NewL(Fs);
sl@0
  1253
	
sl@0
  1254
	for (TInt i = 0; i < KNumModules; ++i)
sl@0
  1255
		{
sl@0
  1256
		if (aCorruptMode && numCorruptFiles==KNumberOfCorruptFiles)
sl@0
  1257
			break;
sl@0
  1258
sl@0
  1259
		if (aCorruptMode && !(GetModuleFlags(i)&KModuleFlagExe))
sl@0
  1260
			continue;
sl@0
  1261
sl@0
  1262
		const TPtrC fn = MODULE_FILENAME(i);
sl@0
  1263
		
sl@0
  1264
		// if this is an absolute filename then copy it to
sl@0
  1265
		// the appropriate drive.
sl@0
  1266
		if (fn[1] != ':')
sl@0
  1267
			continue;
sl@0
  1268
		
sl@0
  1269
		TFileName fnDest;
sl@0
  1270
		GetNonZFileName(fn, fnDest);
sl@0
  1271
sl@0
  1272
		
sl@0
  1273
		TFileName fnSrc(fn);
sl@0
  1274
		fnSrc[0] = 'z';
sl@0
  1275
sl@0
  1276
		test.Printf(_L("CopyExecutables;%S,%S\n"), &fnSrc, &fnDest);
sl@0
  1277
sl@0
  1278
#ifdef __WINS__
sl@0
  1279
		const TParsePtrC sppc(fnSrc);
sl@0
  1280
		TBuf<MAX_PATH> sName;
sl@0
  1281
		r = MapEmulatedFileName(sName, sppc.NameAndExt());
sl@0
  1282
		test(r == KErrNone);
sl@0
  1283
sl@0
  1284
		TBuf<MAX_PATH> dName;
sl@0
  1285
		r = MapEmulatedFileName(dName, fnDest);
sl@0
  1286
		test(r == KErrNone);
sl@0
  1287
sl@0
  1288
		BOOL b = Emulator::CopyFile((LPCTSTR)sName.PtrZ(),(LPCTSTR)dName.PtrZ(),FALSE);
sl@0
  1289
		test(b);
sl@0
  1290
#else
sl@0
  1291
		r = fm->Copy(fnSrc, fnDest);
sl@0
  1292
		test(r == KErrNone);
sl@0
  1293
#endif
sl@0
  1294
sl@0
  1295
		r = Fs.SetAtt(fnDest, 0, KEntryAttReadOnly);
sl@0
  1296
		test.Printf(_L("CopyExecutables:setatt=%d\n"), r);
sl@0
  1297
		User::LeaveIfError(r);
sl@0
  1298
sl@0
  1299
#ifdef __EPOC32__
sl@0
  1300
		TInt moduleFlags = GetModuleFlags(i);
sl@0
  1301
sl@0
  1302
		// modify the new destination file by applying the required paging flags
sl@0
  1303
		RFile fNp;
sl@0
  1304
		r = fNp.Open(Fs, fnDest, EFileWrite | EFileStream);
sl@0
  1305
		User::LeaveIfError(r);
sl@0
  1306
		CleanupClosePushL(fNp);
sl@0
  1307
sl@0
  1308
		// read the header and get the total number of bytes to checksum.
sl@0
  1309
		// (This may be greater than sizeof(E32ImageHeader).
sl@0
  1310
		TPckgBuf<E32ImageHeader> hdrBuf;
sl@0
  1311
		r = fNp.Read(0, hdrBuf);
sl@0
  1312
		User::LeaveIfError(r);
sl@0
  1313
		TInt totalSize = hdrBuf().TotalSize();
sl@0
  1314
		test.Printf(_L("np flags=0x%x,totalSize=%d\n"), hdrBuf().iFlags, totalSize);
sl@0
  1315
		
sl@0
  1316
		// read in the actual bytes to checksum
sl@0
  1317
		TUint8* startBytes0 = (TUint8*) User::AllocLC(totalSize);
sl@0
  1318
		TPtr8 startBytes(startBytes0, 0, totalSize);
sl@0
  1319
		r = fNp.Read(0, startBytes);
sl@0
  1320
		User::LeaveIfError(r);
sl@0
  1321
		test(startBytes.Length() == totalSize);
sl@0
  1322
sl@0
  1323
		// apply the required paging flags to the header
sl@0
  1324
		E32ImageHeader* hdr2 = reinterpret_cast<E32ImageHeader*>(startBytes0);
sl@0
  1325
		TUint& flags = hdr2->iFlags;
sl@0
  1326
		flags &= ~(KImageCodePaged | KImageCodeUnpaged);
sl@0
  1327
		if (moduleFlags & KModuleFlagPagedCode)
sl@0
  1328
			flags |= KImageCodePaged;
sl@0
  1329
		if (moduleFlags & KModuleFlagUnpagedCode)
sl@0
  1330
			flags |= KImageCodeUnpaged;
sl@0
  1331
		test.Printf(_L("setting new image flags 0x%x\n"), flags);
sl@0
  1332
sl@0
  1333
		// corrupt header of the 2nd file
sl@0
  1334
		if (aCorruptMode && numCorruptFiles==1 && (moduleFlags&KModuleFlagExe))
sl@0
  1335
			{
sl@0
  1336
			hdr2->iCodeBase += 3;
sl@0
  1337
			hdr2->iDataBase += 1;
sl@0
  1338
			hdr2->iImportOffset += 1;
sl@0
  1339
			hdr2->iCodeRelocOffset += 3;
sl@0
  1340
			hdr2->iDataRelocOffset += 3;
sl@0
  1341
sl@0
  1342
			++numCorruptFiles;
sl@0
  1343
			}
sl@0
  1344
sl@0
  1345
		// recalculate the checksum
sl@0
  1346
		hdr2->iHeaderCrc = KImageCrcInitialiser;
sl@0
  1347
		TUint32 crc = 0;
sl@0
  1348
		Mem::Crc32(crc, startBytes.Ptr(), totalSize);
sl@0
  1349
		hdr2->iHeaderCrc = crc;
sl@0
  1350
		r = fNp.Write(0, startBytes);
sl@0
  1351
		User::LeaveIfError(r);
sl@0
  1352
sl@0
  1353
		// truncate 1st corrupted file
sl@0
  1354
		if (aCorruptMode && numCorruptFiles==0 && (moduleFlags&KModuleFlagExe))
sl@0
  1355
			{
sl@0
  1356
			TInt size;
sl@0
  1357
			r = fNp.Size(size);
sl@0
  1358
			User::LeaveIfError(r);
sl@0
  1359
			// if trncate by 1 it managed to load. if trancate by 3 it failed to load with KErrCorrupt as expected
sl@0
  1360
			r = fNp.SetSize(size-3); 
sl@0
  1361
			User::LeaveIfError(r);
sl@0
  1362
			++numCorruptFiles;
sl@0
  1363
			}
sl@0
  1364
sl@0
  1365
		CleanupStack::PopAndDestroy(2, &fNp);		// startBytes0, fNp
sl@0
  1366
#endif
sl@0
  1367
sl@0
  1368
		// if copied to removable media, then generate hash
sl@0
  1369
		if (fn[0] == '0')
sl@0
  1370
			continue;
sl@0
  1371
sl@0
  1372
		CSHA1* sha1 = CSHA1::NewL();
sl@0
  1373
		CleanupStack::PushL(sha1);
sl@0
  1374
sl@0
  1375
		RFile fDest;
sl@0
  1376
		r = fDest.Open(Fs, fnDest, EFileRead | EFileStream);
sl@0
  1377
		User::LeaveIfError(r);
sl@0
  1378
		CleanupClosePushL(fDest);
sl@0
  1379
sl@0
  1380
		TBool done;
sl@0
  1381
		TBuf8<512> content;
sl@0
  1382
		do
sl@0
  1383
			{
sl@0
  1384
			r = fDest.Read(content);
sl@0
  1385
			User::LeaveIfError(r);
sl@0
  1386
			done = (content.Length() == 0);
sl@0
  1387
			if (! done)
sl@0
  1388
				sha1->Update(content);
sl@0
  1389
			} while (! done);
sl@0
  1390
		CleanupStack::PopAndDestroy(&fDest);
sl@0
  1391
sl@0
  1392
		// write hash to \sys\hash
sl@0
  1393
		TBuf8<SHA1_HASH> hashVal = sha1->Final();
sl@0
  1394
sl@0
  1395
		// reuse fnSrc to save stack space
sl@0
  1396
		GetHashFileName(fnDest, fnSrc);
sl@0
  1397
		RFile fHash;
sl@0
  1398
		r = fHash.Replace(Fs, fnSrc, EFileWrite | EFileStream);
sl@0
  1399
		test.Printf(_L("hash file,%S,r=%d\n"), &fnSrc, r);
sl@0
  1400
		User::LeaveIfError(r);
sl@0
  1401
		CleanupClosePushL(fHash);
sl@0
  1402
		r = fHash.Write(hashVal);
sl@0
  1403
		User::LeaveIfError(r);
sl@0
  1404
sl@0
  1405
		CleanupStack::PopAndDestroy(2, sha1);
sl@0
  1406
		}
sl@0
  1407
	
sl@0
  1408
	delete fm;
sl@0
  1409
	}
sl@0
  1410
sl@0
  1411
static void DeleteExecutables(TBool aCorruptMode=EFalse)
sl@0
  1412
/**
sl@0
  1413
	Delete any executables which were created by CopyExecutables.
sl@0
  1414
	This function is defined so the test cleans up when it has finished.
sl@0
  1415
 */
sl@0
  1416
	{
sl@0
  1417
	TInt numCorruptFiles = 0;
sl@0
  1418
sl@0
  1419
	for (TInt i = 0; i < KNumModules; ++i)
sl@0
  1420
		{
sl@0
  1421
		if (aCorruptMode && numCorruptFiles==KNumberOfCorruptFiles)
sl@0
  1422
			break;
sl@0
  1423
sl@0
  1424
		if (aCorruptMode && !(GetModuleFlags(i)&KModuleFlagExe))
sl@0
  1425
			continue;
sl@0
  1426
sl@0
  1427
		const TPtrC fn = MODULE_FILENAME(i);
sl@0
  1428
		
sl@0
  1429
		// if this is an absolute filename then copy it to
sl@0
  1430
		// the appropriate drive.
sl@0
  1431
		if (fn[1] != ':')
sl@0
  1432
			continue;
sl@0
  1433
		
sl@0
  1434
		test.Printf(_L("DeleteExecutables:fn=%S\n"), &fn);
sl@0
  1435
		TFileName fnDest;
sl@0
  1436
		GetNonZFileName(fn, fnDest);
sl@0
  1437
		
sl@0
  1438
		TInt r;
sl@0
  1439
sl@0
  1440
		r = Fs.Delete(fnDest);
sl@0
  1441
		test.Printf(_L("DeleteExecutables:fnDest=%S,del=%d\n"), &fnDest, r);
sl@0
  1442
		test(r == KErrNone);
sl@0
  1443
sl@0
  1444
		// only need to delete hash files for binaries copied to removable media,
sl@0
  1445
		// but simpler to delete and test for KErrNotFound
sl@0
  1446
		TFileName fnHash;
sl@0
  1447
		GetHashFileName(fnDest, fnHash);
sl@0
  1448
		r = Fs.Delete(fnHash);
sl@0
  1449
		test.Printf(_L("DeleteExecutables,h=%S,hdel=%d\n"), &fnHash, r);
sl@0
  1450
		test(r == KErrPathNotFound || r == KErrNotFound || r == KErrNone);
sl@0
  1451
sl@0
  1452
		if (aCorruptMode)
sl@0
  1453
			++numCorruptFiles;
sl@0
  1454
		}
sl@0
  1455
	}
sl@0
  1456
sl@0
  1457
GLDEF_C TInt E32Main()
sl@0
  1458
	{
sl@0
  1459
	RThread().SetPriority(EPriorityLess);
sl@0
  1460
sl@0
  1461
	test.Title();
sl@0
  1462
	test.Start(_L("Setup"));
sl@0
  1463
sl@0
  1464
	RLoader l;
sl@0
  1465
	test(l.Connect()==KErrNone);
sl@0
  1466
	test(l.CancelLazyDllUnload()==KErrNone);
sl@0
  1467
	l.Close();
sl@0
  1468
sl@0
  1469
	test(TestLdd.Open()==KErrNone);
sl@0
  1470
	LoaderTest* pL=LoaderTest::New();
sl@0
  1471
	TheLoaderTest=pL;
sl@0
  1472
sl@0
  1473
	TInt tm=pL->iCmdLine[0];
sl@0
  1474
	TInt nr = (tm>>4)&3;
sl@0
  1475
	if (nr==1)
sl@0
  1476
		NoRemovable = ETrue;
sl@0
  1477
	else if (nr==2)
sl@0
  1478
		NoRemovable = EFalse;
sl@0
  1479
sl@0
  1480
	test(Fs.Connect() == KErrNone);
sl@0
  1481
sl@0
  1482
	// allocate a cleanup stack so can call CFileMan::NewL in CopyExecutables
sl@0
  1483
	test.Printf(_L("CopyExecutablesL()\n"));
sl@0
  1484
	CTrapCleanup* cleanup=CTrapCleanup::New();
sl@0
  1485
	TRAPD(r, CopyExecutablesL());
sl@0
  1486
	test(r == KErrNone);
sl@0
  1487
	delete cleanup;
sl@0
  1488
sl@0
  1489
	if (tm&1)
sl@0
  1490
		pL->TestOneByOne();
sl@0
  1491
	if (tm&2)
sl@0
  1492
		pL->TestMultipleExeInstances();
sl@0
  1493
	if (tm&4)
sl@0
  1494
		pL->TestOOM();
sl@0
  1495
	if (tm&8)
sl@0
  1496
		pL->TestMultipleLoads();
sl@0
  1497
sl@0
  1498
	pL->Close();
sl@0
  1499
sl@0
  1500
	// Test loader error handling - will panic the client thread
sl@0
  1501
	test.Next(_L("Test loader error handling - will panic the client thread"));
sl@0
  1502
	RThread t;
sl@0
  1503
	t.Create(_L("Loader panic test"),PanicTestThread,KDefaultStackSize,0x1000,0x1000,NULL);
sl@0
  1504
	TRequestStatus s;
sl@0
  1505
	t.Logon(s);
sl@0
  1506
	TBool justInTime=User::JustInTime(); 
sl@0
  1507
	User::SetJustInTime(EFalse); 
sl@0
  1508
	t.Resume();
sl@0
  1509
	User::WaitForRequest(s);
sl@0
  1510
	test(t.ExitType()==EExitPanic);
sl@0
  1511
	test(t.ExitCategory().Compare(_L("LOADER"))==0);
sl@0
  1512
	test(t.ExitReason()==0);
sl@0
  1513
	t.Close();
sl@0
  1514
	User::SetJustInTime(justInTime);
sl@0
  1515
sl@0
  1516
	DeleteExecutables();
sl@0
  1517
sl@0
  1518
#ifdef __EPOC32__
sl@0
  1519
	// test corrupted files
sl@0
  1520
	cleanup=CTrapCleanup::New();
sl@0
  1521
	test.Next(_L("CopyExecutablesL(ETrue)"));
sl@0
  1522
	TRAPD(rr, CopyExecutablesL(ETrue));
sl@0
  1523
	test(rr == KErrNone);
sl@0
  1524
	delete cleanup;
sl@0
  1525
	test.Next(_L("TestCorruptedFiles()"));
sl@0
  1526
	TestCorruptedFiles();
sl@0
  1527
	test.Next(_L("DeleteExecutables()"));
sl@0
  1528
	DeleteExecutables(ETrue);
sl@0
  1529
#endif
sl@0
  1530
sl@0
  1531
	Fs.Close();
sl@0
  1532
sl@0
  1533
	test.End();
sl@0
  1534
	return KErrNone;
sl@0
  1535
	}
sl@0
  1536