| 0 |      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 | 
 |