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