1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/os/kernelhwsrv/kerneltest/f32test/loader/t_ldrtst.cpp Fri Jun 15 03:10:57 2012 +0200
1.3 @@ -0,0 +1,1536 @@
1.4 +// Copyright (c) 1999-2009 Nokia Corporation and/or its subsidiary(-ies).
1.5 +// All rights reserved.
1.6 +// This component and the accompanying materials are made available
1.7 +// under the terms of the License "Eclipse Public License v1.0"
1.8 +// which accompanies this distribution, and is available
1.9 +// at the URL "http://www.eclipse.org/legal/epl-v10.html".
1.10 +//
1.11 +// Initial Contributors:
1.12 +// Nokia Corporation - initial contribution.
1.13 +//
1.14 +// Contributors:
1.15 +//
1.16 +// Description:
1.17 +// f32test\loader\t_ldrtst.cpp
1.18 +//
1.19 +//
1.20 +
1.21 +#define __E32TEST_EXTENSION__
1.22 +
1.23 +#include "t_hash.h"
1.24 +#include "t_ldrtst.h"
1.25 +#include "../../../e32test/mmu/d_memorytest.h"
1.26 +
1.27 +#if defined(__WINS__)
1.28 + #include <e32wins.h>
1.29 + #include <emulator.h>
1.30 +#elif defined(__EPOC32__)
1.31 + #include <f32image.h>
1.32 +#endif
1.33 +
1.34 +const TInt KNumberOfCorruptFiles = 2;
1.35 +
1.36 +RTest test(_L("T_LDRTST"));
1.37 +
1.38 +LoaderTest* TheLoaderTest;
1.39 +RFs Fs;
1.40 +#if defined (__X86__) || defined(__WINS__)
1.41 +TBool NoRemovable=ETrue;
1.42 +#else
1.43 +TBool NoRemovable=EFalse;
1.44 +#endif
1.45 +
1.46 +/** Error code of simulated RFs error */
1.47 +const TInt KRFsError = -99;
1.48 +
1.49 +/**
1.50 + Number of drives which are identified by a numeric value,
1.51 + which means, e.g., run from an internal pageable drive.
1.52 + */
1.53 +const TInt KSpecialDriveCount = 2;
1.54 +
1.55 +/** The real drive letters corresponding to each special drive. */
1.56 +static TFixedArray<TText, KSpecialDriveCount> SpecialDrives;
1.57 +
1.58 +/** Bitmask of paged and unpaged module flags. */
1.59 +const TUint32 KModulePagedCodeFlags = (KModuleFlagPagedCode | KModuleFlagUnpagedCode);
1.60 +
1.61 +_LIT(KSysHash,"?:\\Sys\\Hash\\");
1.62 +
1.63 +TInt GetModuleFlags(TInt aModule)
1.64 + {
1.65 + TInt f = ModuleFlags[aModule];
1.66 +#ifdef __WINS__
1.67 + // paged and unpaged flags are not supported on the emulator
1.68 + f &= ~KModulePagedCodeFlags;
1.69 + // On emulator, treat all modules as XIP, all EXEs as fixed
1.70 + f |= KModuleFlagXIP;
1.71 + if (f & KModuleFlagExe)
1.72 + f|=KModuleFlagFixed;
1.73 +#endif // #ifdef __EPOC32__
1.74 + return f;
1.75 + }
1.76 +
1.77 +TModuleSet::TModuleSet()
1.78 + {
1.79 + Mem::FillZ(this,sizeof(TModuleSet));
1.80 + }
1.81 +
1.82 +void TModuleSet::Add(TInt aModule)
1.83 + {
1.84 + TUint8 m=(TUint8)(1<<(aModule&7));
1.85 + TInt i=aModule>>3;
1.86 + if (!(iBitMap[i]&m))
1.87 + {
1.88 + iBitMap[i]|=m;
1.89 + ++iCount;
1.90 + }
1.91 + }
1.92 +
1.93 +void TModuleSet::Remove(TInt aModule)
1.94 + {
1.95 + TUint8 m=(TUint8)(1<<(aModule&7));
1.96 + TInt i=aModule>>3;
1.97 + if (iBitMap[i]&m)
1.98 + {
1.99 + iBitMap[i]&=~m;
1.100 + --iCount;
1.101 + }
1.102 + }
1.103 +
1.104 +TModuleSet::TModuleSet(const TModuleList& aList, TInt aMask, TInt aVal)
1.105 + {
1.106 + Mem::FillZ(this,sizeof(TModuleSet));
1.107 + TInt i;
1.108 + for (i=0; i<aList.iCount; ++i)
1.109 + {
1.110 + TInt m=aList.iInfo[i].iDllNum;
1.111 + if (((GetModuleFlags(m)&aMask)^aVal)==0)
1.112 + Add(aList.iInfo[i].iDllNum);
1.113 + }
1.114 + }
1.115 +
1.116 +void TModuleSet::Remove(const TModuleList& aList)
1.117 + {
1.118 + TInt i;
1.119 + for (i=0; i<aList.iCount; ++i)
1.120 + Remove(aList.iInfo[i].iDllNum);
1.121 + }
1.122 +
1.123 +void TModuleSet::Display(const TDesC& aTitle) const
1.124 + {
1.125 + TBuf<256> s=aTitle;
1.126 + TInt i;
1.127 + for (i=0; i<iCount; ++i)
1.128 + {
1.129 + if (Present(i))
1.130 + s.AppendFormat(_L("%3d "),i);
1.131 + }
1.132 + test.Printf(_L("%S\n"),&s);
1.133 + }
1.134 +
1.135 +TModuleList::TModuleList()
1.136 + {
1.137 + iCount=0;
1.138 + Mem::Fill(iInfo, KNumModules*sizeof(SDllInfo), 0xff);
1.139 + }
1.140 +
1.141 +void TModuleList::SetCount()
1.142 + {
1.143 + TInt i;
1.144 + for (i=0; i<KNumModules && iInfo[i].iDllNum>=0; ++i) {}
1.145 + iCount=i;
1.146 + }
1.147 +
1.148 +void TModuleList::Display(const TDesC& aTitle) const
1.149 + {
1.150 + TBuf<256> s=aTitle;
1.151 + TInt i;
1.152 + for (i=0; i<iCount; ++i)
1.153 + {
1.154 + TInt modnum=iInfo[i].iDllNum;
1.155 + s.AppendFormat(_L("%3d "),modnum);
1.156 + }
1.157 + test.Printf(_L("%S\n"),&s);
1.158 + }
1.159 +
1.160 +TBool TModuleList::IsPresent(TInt aModNum) const
1.161 + {
1.162 + return Find(aModNum)>=0;
1.163 + }
1.164 +
1.165 +TInt TModuleList::Find(TInt aModNum) const
1.166 + {
1.167 + TInt i;
1.168 + for (i=iCount-1; i>=0 && iInfo[i].iDllNum!=aModNum; --i) {}
1.169 + return i;
1.170 + }
1.171 +
1.172 +void TModuleList::Add(const SDllInfo& a)
1.173 + {
1.174 + iInfo[iCount++]=a;
1.175 + }
1.176 +
1.177 +
1.178 +RMemoryTestLdd TestLdd;
1.179 +
1.180 +TBool AddressReadable(TLinAddr a)
1.181 + {
1.182 + TUint32 value;
1.183 + return TestLdd.ReadMemory((TAny*)a,value)==KErrNone;
1.184 + }
1.185 +
1.186 +TInt LoaderTest::DetermineDllLoadResult(TInt aDllNum, TInt aExeNum)
1.187 + {
1.188 + TBool proc_sym=(iMemModelAtt & (EMemModelAttrSameVA|EMemModelAttrSupportFixed))==EMemModelAttrSameVA;
1.189 + const TInt* exeinfo=ModuleExeInfo[aDllNum];
1.190 + TInt attp=exeinfo[0];
1.191 + TInt linkexe=exeinfo[1];
1.192 + TInt dllflags=GetModuleFlags(aDllNum);
1.193 + TInt exeflags=GetModuleFlags(aExeNum);
1.194 +
1.195 +#ifdef __EPOC32__
1.196 + // if NP and DEFAULTPAGED or DEFAULTUNPAGED (not NOPAGING or ALWAYSPAGE) then
1.197 + // executable identified as corrupt, unless previous conditions in S3.1.3.2 cause
1.198 + // it to be paged or unpaged without examining the flags.
1.199 +
1.200 + TUint32 policy = E32Loader::PagingPolicy();
1.201 + test.Printf(_L("DetermineDllLoadResult,dll=%d,exe=%d,dllflags=0x%x,policy=0x%x\n"), aDllNum, aExeNum, dllflags, policy);
1.202 +
1.203 + TBool flagsChecked =
1.204 + policy != EKernelConfigCodePagingPolicyNoPaging // 3.1.3.2.1, policy != no paging
1.205 + && (dllflags & KModuleFlagIDrive) != 0 // 3.1.3.2.2-3, pageable drive
1.206 + && (dllflags & (KModuleFlagUncompressed | KModuleFlagBytePair)) != 0 // 3.1.3.2.4 pageable format
1.207 + && policy != EKernelConfigCodePagingPolicyAlwaysPage; // 3.1.3.2.5, policy != ALWAYS
1.208 +
1.209 + if (flagsChecked && (dllflags & KModulePagedCodeFlags) == KModulePagedCodeFlags)
1.210 + {
1.211 + TBool codePolDefUnpaged = (policy == EKernelConfigCodePagingPolicyDefaultUnpaged);
1.212 + TBool codePolDefPaged = (policy == EKernelConfigCodePagingPolicyDefaultPaged);
1.213 + if (codePolDefPaged || codePolDefUnpaged)
1.214 + return KErrCorrupt;
1.215 + }
1.216 +#endif
1.217 +
1.218 + if (linkexe>=0 && linkexe!=aExeNum)
1.219 + return KErrNotSupported; // if DLL links to a different EXE, no good
1.220 + if (!(dllflags&KModuleFlagDataInTree))
1.221 + return KErrNone; // if no data in DLL tree, OK
1.222 + if (proc_sym)
1.223 + return KErrNone; // if all user processes equivalent, OK
1.224 + if (!(dllflags&KModuleFlagXIPDataInTree))
1.225 + return KErrNone; // if no XIP modules with data in DLL tree, OK
1.226 +
1.227 +#ifdef __EPOC32__
1.228 + if (attp<0 || !(GetModuleFlags(attp)&KModuleFlagFixed))
1.229 + {
1.230 + // moving processes only
1.231 + if (!(exeflags&KModuleFlagFixed))
1.232 + return KErrNone;
1.233 + return KErrNotSupported;
1.234 + }
1.235 + // fixed attach process only
1.236 + if (aExeNum!=attp)
1.237 + return KErrNotSupported;
1.238 +#else
1.239 + (void)attp;
1.240 + (void)exeflags;
1.241 +#endif
1.242 + return KErrNone;
1.243 + }
1.244 +
1.245 +TInt LoaderTest::DetermineDllLoadResult(TInt aDllNum, TInt aExeNum1, TInt aExeNum2)
1.246 + {
1.247 + // Determine result of loading aDllNum into aExeNum2 given that it's already loaded into aExeNum1
1.248 + // return KErrNone if code segment can be shared, 1 if it must be duplicated
1.249 +
1.250 + TBool proc_sym=(iMemModelAtt & (EMemModelAttrSameVA|EMemModelAttrSupportFixed))==EMemModelAttrSameVA;
1.251 + const TInt* exeinfo=ModuleExeInfo[aDllNum];
1.252 +// TInt attp=exeinfo[0];
1.253 + TInt linkexe=exeinfo[1];
1.254 + TInt dllflags=GetModuleFlags(aDllNum);
1.255 + TInt exe1flags=GetModuleFlags(aExeNum1);
1.256 + TInt exe2flags=GetModuleFlags(aExeNum2);
1.257 + if (linkexe>=0 && linkexe!=aExeNum2)
1.258 + return KErrNotSupported; // if DLL links to a different EXE, no good
1.259 + if (!(dllflags&KModuleFlagDataInTree))
1.260 + return KErrNone; // if no data in DLL tree, OK
1.261 + if (proc_sym)
1.262 + return KErrNone; // if all user processes equivalent, OK
1.263 + if (!((exe1flags|exe2flags)&KModuleFlagFixed))
1.264 + return KErrNone; // if neither process fixed, OK
1.265 + if (!(dllflags&KModuleFlagXIPDataInTree))
1.266 + return 1; // if no XIP modules with data in DLL tree, OK but can't share
1.267 +#ifdef __WINS__
1.268 + return KErrNone;
1.269 +#else
1.270 + return KErrNotSupported;
1.271 +#endif
1.272 + }
1.273 +
1.274 +TBool LoaderTest::IsRomAddress(TLinAddr a)
1.275 + {
1.276 + const TRomHeader& rh=*(const TRomHeader*)UserSvr::RomHeaderAddress();
1.277 + return (a>=rh.iRomBase && (a-rh.iRomBase)<rh.iRomSize);
1.278 + }
1.279 +
1.280 +TBool LoaderTest::IsRamCodeAddress(TLinAddr a)
1.281 + {
1.282 + switch (iMemModelAtt & EMemModelTypeMask)
1.283 + {
1.284 + case EMemModelTypeDirect:
1.285 + return ETrue;
1.286 + case EMemModelTypeMoving:
1.287 + return (a>=0xc0000000u);
1.288 + case EMemModelTypeMultiple:
1.289 + return (a<0x80000000u);
1.290 + case EMemModelTypeFlexible:
1.291 + return (a<0x80000000u);
1.292 + case EMemModelTypeEmul:
1.293 + return (a<0x80000000u);
1.294 + default:
1.295 + return EFalse;
1.296 + }
1.297 + }
1.298 +
1.299 +TBool LoaderTest::CheckDataAddress(TLinAddr a, TInt aDllNum, TInt aExeNum)
1.300 + {
1.301 + TInt xf=GetModuleFlags(aExeNum);
1.302 + TInt df=GetModuleFlags(aDllNum);
1.303 + switch (iMemModelAtt & EMemModelTypeMask)
1.304 + {
1.305 + case EMemModelTypeDirect:
1.306 + return ETrue;
1.307 + case EMemModelTypeMoving:
1.308 + {
1.309 + const TRomHeader& rh=*(const TRomHeader*)UserSvr::RomHeaderAddress();
1.310 + if (!(xf&KModuleFlagFixed))
1.311 + return (a<0x40000000u);
1.312 + if ((xf&KModuleFlagXIP) && (df&KModuleFlagXIP))
1.313 + return (a>=rh.iKernDataAddress && a<rh.iKernelLimit);
1.314 + return (a>=rh.iKernelLimit && a<0xc0000000u);
1.315 + }
1.316 + case EMemModelTypeMultiple:
1.317 + return (a<0x80000000u);
1.318 + case EMemModelTypeFlexible:
1.319 + return (a<0x80000000u);
1.320 + case EMemModelTypeEmul:
1.321 + return (a<0x80000000u);
1.322 + default:
1.323 + return EFalse;
1.324 + }
1.325 + }
1.326 +
1.327 +void LoaderTest::DumpModuleInfo(const SDllInfo& aInfo, TInt aExeNum)
1.328 + {
1.329 + TInt flags=GetModuleFlags(aInfo.iDllNum);
1.330 + TUint32 mmtype=iMemModelAtt & EMemModelTypeMask;
1.331 + TAny* h=iDev.ModuleCodeSeg(aInfo.iModuleHandle);
1.332 + if (!h)
1.333 + {
1.334 +#ifdef __EPOC32__
1.335 + test(flags & KModuleFlagXIP);
1.336 + test(IsRomAddress(aInfo.iEntryPointAddress));
1.337 + test.Printf(_L("Module handle %08x ROM XIP\n"),aInfo.iModuleHandle);
1.338 +#endif
1.339 + test(!(flags & KModuleFlagData));
1.340 + return;
1.341 + }
1.342 + TCodeSegCreateInfo info;
1.343 + TInt r=iDev.GetCodeSegInfo(h, info);
1.344 + test(r==KErrNone);
1.345 + TFileName fn;
1.346 + fn.Copy(info.iFileName);
1.347 + 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);
1.348 + TInt total_data_size=info.iDataSize+info.iBssSize;
1.349 +#ifndef __WINS__
1.350 + // Don't do check below for WINS because:
1.351 + // a. It doesn't work on code warrior since it puts constants into .data
1.352 + // b. On MSCV with c++ exceptions enabled we also get data
1.353 + if (flags & KModuleFlagData)
1.354 + test(total_data_size!=0);
1.355 + else
1.356 + test(total_data_size==0);
1.357 +
1.358 + // ensure code paged iff expected. This implements the logic from
1.359 + // PREQ1110 Design Sketch SGL.TS0022.008 v1.0 S3.1.3.2
1.360 +
1.361 + TUint policy = E32Loader::PagingPolicy();
1.362 +
1.363 + TBool expected;
1.364 + TBool isCodePaged = (info.iAttr & ECodeSegAttCodePaged)!=0;
1.365 +
1.366 + // 1. If paging policy is NOPAGING then executable is Unpaged.
1.367 + TUint32 memModelAttributes=UserSvr::HalFunction(EHalGroupKernel, EKernelHalMemModelInfo, NULL, NULL);
1.368 + if (policy == EKernelConfigCodePagingPolicyNoPaging || !(memModelAttributes&EMemModelAttrCodePaging))
1.369 + {
1.370 + test.Printf(_L("sbcpexp,1\n"));
1.371 + expected = false;
1.372 + }
1.373 + // 2. If ... media ... doesn't have Pageable Media Attribute then it is Unpaged.
1.374 + // (this has been superseded by BlockMap check on filesystem / media. During these
1.375 + // tests, only the internal media supports paging.)
1.376 + else if ((flags & KModuleFlagIDrive) == 0)
1.377 + {
1.378 + test.Printf(_L("sbcpexp,2\n"));
1.379 + expected = false;
1.380 + }
1.381 + // 3. If ... removable media then it is Unpaged.
1.382 + // Not tested here because removable media (drive 1) covered by above case.
1.383 +// else if (MODULE_FILENAME(aInfo.iDllNum)[0] == '1')
1.384 +// {
1.385 +// test.Printf(_L("sbcpexp,2\n"));
1.386 +// expected = false;
1.387 +// }
1.388 + // 4. [If not bytepair [or uncompressed]] then Unpaged
1.389 + else if ((flags & (KModuleFlagBytePair | KModuleFlagUncompressed)) == 0)
1.390 + {
1.391 + test.Printf(_L("sbcpexp,3\n"));
1.392 + expected = false;
1.393 + }
1.394 + // 5. If the Paging Policy is ALWAYSPAGE then the executable is Paged.
1.395 + else if (policy == EKernelConfigCodePagingPolicyAlwaysPage)
1.396 + {
1.397 + test.Printf(_L("sbcpexp,4\n"));
1.398 + expected = true;
1.399 + }
1.400 + // 6. if KImageCodePaged and KImageCodePaged both set, should not reach here
1.401 + // because load will have failed with KErrCorrupt. If Paged on its own
1.402 + // then paged; if unpaged on its own then unpaged
1.403 + else if ((flags & KModuleFlagPagedCode) != 0)
1.404 + {
1.405 + test.Printf(_L("sbcpexp,5\n"));
1.406 + expected = true;
1.407 + }
1.408 + else if ((flags & KModuleFlagUnpagedCode) != 0)
1.409 + {
1.410 + test.Printf(_L("sbcpexp,6\n"));
1.411 + expected = false;
1.412 + }
1.413 + // 7. Otherwise the PagingPolicy (DEFAULTPAGED or DEFAULTUNPAGED) determines
1.414 + // how the executable is treated
1.415 + else
1.416 + {
1.417 + test.Printf(_L("sbcpexp,7\n"));
1.418 + expected = (policy == EKernelConfigCodePagingPolicyDefaultPaged);
1.419 + }
1.420 +
1.421 + test(expected == isCodePaged);
1.422 +#endif
1.423 + if ((flags & KModuleFlagXIP) && mmtype!=EMemModelTypeEmul)
1.424 + test(IsRomAddress(aInfo.iEntryPointAddress));
1.425 + else
1.426 + {
1.427 + test(IsRamCodeAddress(aInfo.iEntryPointAddress));
1.428 + if(mmtype==EMemModelTypeFlexible)
1.429 + {
1.430 + // can't make assumtions about current processes address space
1.431 + }
1.432 + else if (mmtype==EMemModelTypeMultiple)
1.433 + {
1.434 + test(!AddressReadable(aInfo.iEntryPointAddress));
1.435 + }
1.436 + else
1.437 + {
1.438 + test(AddressReadable(aInfo.iEntryPointAddress));
1.439 + }
1.440 + }
1.441 +
1.442 + if (total_data_size!=0)
1.443 + test(CheckDataAddress(info.iDataRunAddress, aInfo.iDllNum, aExeNum));
1.444 + }
1.445 +
1.446 +void LoaderTest::DumpModuleList(const TModuleList& aList, TInt aExeNum)
1.447 + {
1.448 + TInt i;
1.449 + for (i=0; i<aList.iCount; ++i)
1.450 + {
1.451 + TInt modnum=aList.iInfo[i].iDllNum;
1.452 + TInt entry=aList.iInfo[i].iEntryPointAddress;
1.453 + test.Printf(_L("MODULE %3d: ENTRY %08x "),modnum,entry);
1.454 + DumpModuleInfo(aList.iInfo[i],aExeNum);
1.455 + }
1.456 + }
1.457 +
1.458 +void LoaderTest::CheckModuleList(TInt aRoot, const TModuleList& aList)
1.459 + {
1.460 + const TInt* deps=ModuleDependencies[aRoot];
1.461 + TInt ndeps=*deps++;
1.462 + TInt f=0;
1.463 + TInt i;
1.464 + for (i=0; i<ndeps; ++i)
1.465 + {
1.466 + TInt m=deps[i];
1.467 + f|=GetModuleFlags(m);
1.468 + }
1.469 + if (!(f&KModuleFlagDllInCycle))
1.470 + {
1.471 + i=0; // indexes aList
1.472 + TInt j=0; // indexes deps
1.473 + while(i<KNumModules)
1.474 + {
1.475 + if (j<ndeps)
1.476 + {
1.477 + if (!(GetModuleFlags(deps[j])&KModuleFlagExe))
1.478 + {
1.479 + test(aList.iInfo[i].iDllNum==deps[j]);
1.480 + ++i;
1.481 + }
1.482 + ++j;
1.483 + }
1.484 + else if (j==ndeps)
1.485 + {
1.486 + test(aList.iInfo[i].iDllNum==aRoot);
1.487 + ++i;
1.488 + ++j;
1.489 + }
1.490 + else
1.491 + {
1.492 + test(aList.iInfo[i].iDllNum<0);
1.493 + ++i;
1.494 + }
1.495 + }
1.496 + }
1.497 + TModuleSet ml;
1.498 + TInt nd=ndeps;
1.499 + TBool root_included=EFalse;
1.500 + for (i=0; i<ndeps; ++i)
1.501 + {
1.502 + if (deps[i]==aRoot)
1.503 + root_included=ETrue;
1.504 + if (!(GetModuleFlags(deps[i])&KModuleFlagExe))
1.505 + ml.Add(deps[i]);
1.506 + else
1.507 + --nd;
1.508 + }
1.509 + test(ml.iCount==nd);
1.510 + for (i=0; i<KNumModules; ++i)
1.511 + {
1.512 + if (i<nd)
1.513 + {
1.514 + test(aList.iInfo[i].iDllNum>=0);
1.515 + ml.Remove(aList.iInfo[i].iDllNum);
1.516 + }
1.517 + else if (i==nd && !root_included)
1.518 + test(aList.iInfo[i].iDllNum==aRoot);
1.519 + else
1.520 + test(aList.iInfo[i].iDllNum<0);
1.521 + }
1.522 + test(ml.iCount==0);
1.523 + }
1.524 +
1.525 +LoaderTest::LoaderTest()
1.526 + {
1.527 + Mem::Fill(iCmdLine, sizeof(iCmdLine), 0xff);
1.528 + iMemModelAtt=(TUint32)UserSvr::HalFunction(EHalGroupKernel, EKernelHalMemModelInfo, NULL, NULL);
1.529 + test.Printf(_L("MemModelAttributes=%08x\n"),iMemModelAtt);
1.530 + }
1.531 +
1.532 +LoaderTest::~LoaderTest()
1.533 + {
1.534 + iFs.Close();
1.535 + iDev.Close();
1.536 + }
1.537 +
1.538 +void LoaderTest::Init()
1.539 + {
1.540 + test.Next(_L("Load device driver"));
1.541 + TInt r=User::LoadLogicalDevice(_L("D_LDRTST"));
1.542 + test(r==KErrNone || r==KErrAlreadyExists);
1.543 + r=iDev.Open();
1.544 + test(r==KErrNone);
1.545 + r=iFs.Connect();
1.546 + test(r==KErrNone);
1.547 +
1.548 + TBuf<256> cmdline;
1.549 + User::CommandLine(cmdline);
1.550 + TLex lex(cmdline);
1.551 + TInt i;
1.552 + for (i=0; i<8; ++i)
1.553 + {
1.554 + lex.SkipSpace();
1.555 + if (lex.Eos())
1.556 + break;
1.557 + lex.Val(iCmdLine[i]);
1.558 + }
1.559 + }
1.560 +
1.561 +LoaderTest* LoaderTest::New()
1.562 + {
1.563 + LoaderTest* p=new LoaderTest;
1.564 + test(p!=NULL);
1.565 + p->Init();
1.566 + return p;
1.567 + }
1.568 +
1.569 +void LoaderTest::Close()
1.570 + {
1.571 + delete this;
1.572 + }
1.573 +
1.574 +void LoaderTest::TraceOn()
1.575 + {
1.576 + iFs.SetDebugRegister(KFLDR);
1.577 + User::SetDebugMask(0xefdfffff);
1.578 + }
1.579 +
1.580 +void LoaderTest::TraceOff()
1.581 + {
1.582 + iFs.SetDebugRegister(0);
1.583 + User::SetDebugMask(0x80000000);
1.584 + }
1.585 +
1.586 +void LoaderTest::TestOneByOne()
1.587 + {
1.588 + test.Next(_L("Test all single EXE/DLL combinations"));
1.589 + TInt i=0;
1.590 + TInt r=0;
1.591 + TInt x=0;
1.592 + for (x=0; x<KNumModules; ++x)
1.593 + {
1.594 + if (!(GetModuleFlags(x)&KModuleFlagExe))
1.595 + continue;
1.596 +#ifdef __WINS__
1.597 + if (GetModuleFlags(x)&KModuleFlagTargetOnly)
1.598 + continue;
1.599 +#endif
1.600 + RProcess p;
1.601 + TUint32 tt;
1.602 + r=LoadExe(x, 0, p, tt);
1.603 + test.Printf(_L("LoadExe(%d)->%d\n"),x,r);
1.604 + test.Printf(_L("BENCHMARK: LoadExe(%d)->%dms\n"),x,tt);
1.605 + test(r==KErrNone);
1.606 + RLoaderTest lt;
1.607 + r=lt.Connect(x);
1.608 + test.Printf(_L("Connect(%d)->%d\n"),x,r);
1.609 + test(r==KErrNone);
1.610 + TModuleList exe_info;
1.611 + r=lt.GetExeDepList(exe_info.iInfo);
1.612 + test(r==KErrNone);
1.613 + exe_info.SetCount();
1.614 + DumpModuleList(exe_info, x);
1.615 + CheckModuleList(x, exe_info);
1.616 +
1.617 + TInt m;
1.618 + for (m=0; m<KNumModules; ++m)
1.619 + {
1.620 + if (GetModuleFlags(m)&KModuleFlagExe)
1.621 + continue;
1.622 +#ifdef __WINS__
1.623 + if (GetModuleFlags(m)&KModuleFlagTargetOnly)
1.624 + continue;
1.625 +#endif
1.626 +
1.627 + if ((GetModuleFlags(m) & KModuleFlagVDrive) && NoRemovable)
1.628 + {
1.629 + test.Printf(_L("LoadDll: Not testing dll %d from removable media\n"),m);
1.630 + continue;
1.631 + }
1.632 + TInt predicted=DetermineDllLoadResult(m,x);
1.633 + if (x==iCmdLine[1] && m==iCmdLine[2])
1.634 + TraceOn();
1.635 + TModuleList dll_init_info;
1.636 + TModuleList dll_c_info;
1.637 + TModuleList dll_d_info;
1.638 + TInt h=lt.LoadDll(m, dll_init_info.iInfo);
1.639 + dll_init_info.SetCount();
1.640 + test.Printf(_L("LoadDll(%d)->%d (%d)\n"),m,h,predicted);
1.641 +
1.642 + test(Min(h,0)==predicted);
1.643 + if (h>=0)
1.644 + {
1.645 + DumpModuleList(dll_init_info, x);
1.646 + CheckModuleList(m, dll_init_info);
1.647 + test(lt.GetCDList(dll_c_info.iInfo)==KErrNone);
1.648 + dll_c_info.SetCount();
1.649 + dll_c_info.Display(_L("Construct: "));
1.650 + if (!(GetModuleFlags(m)&KModuleFlagDllInCycle))
1.651 + {
1.652 + TInt j=0;
1.653 + for (i=0; i<dll_init_info.iCount; ++i)
1.654 + {
1.655 + TInt modnum=dll_init_info.iInfo[i].iDllNum;
1.656 + if ((GetModuleFlags(modnum)&KModuleFlagData) && !exe_info.IsPresent(modnum))
1.657 + {
1.658 + test(modnum==dll_c_info.iInfo[j].iDllNum);
1.659 + ++j;
1.660 + }
1.661 + }
1.662 + test(j==dll_c_info.iCount);
1.663 + }
1.664 + else
1.665 + {
1.666 + TModuleSet ms(dll_init_info, KModuleFlagData, KModuleFlagData);
1.667 + ms.Remove(exe_info);
1.668 + test(ms.iCount==dll_c_info.iCount);
1.669 + ms.Remove(dll_c_info);
1.670 + test(ms.iCount==0);
1.671 + }
1.672 + TInt y=(7*m+59);
1.673 + r=lt.CallRBlkI(h,y);
1.674 + r-=y;
1.675 + r/=INC_BLOCK_SZ;
1.676 + test.Printf(_L("DLL %d RBlkI->%d\n"),m,r);
1.677 + y=ModuleRBlkIParams[m][1]+ModuleRBlkIParams[m][0]*DLLNUMOFFSET;
1.678 + test(r==y);
1.679 + r=lt.CloseDll(h);
1.680 + test.Printf(_L("CloseDll(%d)->%d\n"),h,r);
1.681 + test(r==KErrNone);
1.682 + test(lt.GetCDList(dll_d_info.iInfo)==KErrNone);
1.683 + dll_d_info.SetCount();
1.684 + dll_d_info.Display(_L("Destruct: "));
1.685 + test(dll_d_info.iCount==dll_c_info.iCount);
1.686 + for (i=0; i<dll_d_info.iCount; ++i)
1.687 + test(dll_d_info.iInfo[i].iDllNum==dll_c_info.iInfo[dll_c_info.iCount-i-1].iDllNum);
1.688 + }
1.689 + if (x==iCmdLine[1] && m==iCmdLine[2])
1.690 + TraceOff();
1.691 + }
1.692 + lt.Exit();
1.693 + p.Close();
1.694 + }
1.695 + }
1.696 +
1.697 +// return KErrNone if shared code, 1 if not shared
1.698 +TInt LoaderTest::DetermineLoadExe2Result(TInt aExeNum)
1.699 + {
1.700 + if ( (iMemModelAtt&(EMemModelAttrSameVA|EMemModelAttrSupportFixed))==EMemModelAttrSameVA )
1.701 + return KErrNone; // multiple memory model always supports multiple instances
1.702 + TUint32 f=GetModuleFlags(aExeNum);
1.703 + if (!(f&KModuleFlagFixed))
1.704 + return KErrNone; // not fixed, so share code segment
1.705 + if (!(f&KModuleFlagDataInTree))
1.706 + {
1.707 +#ifdef __EPOC32__
1.708 + return KErrNone; // fixed but no data, so share code segment
1.709 +#else
1.710 + return 1; // on emulator, never share EXE code segments
1.711 +#endif
1.712 + }
1.713 +#ifdef __EPOC32__
1.714 + if (!(f&KModuleFlagXIP))
1.715 + return 1; // fixed but not XIP, data in tree - create second code segment
1.716 + // fixed, XIP, data in tree
1.717 + return KErrAlreadyExists;
1.718 +#else
1.719 + if (f & KModuleFlagExports)
1.720 + return KErrAlreadyExists;
1.721 + if (!(f & KModuleFlagData))
1.722 + return KErrNone;
1.723 + return 1;
1.724 +#endif
1.725 + }
1.726 +
1.727 +void LoaderTest::TestMultipleExeInstances()
1.728 + {
1.729 + test.Next(_L("Test multiple instantiation of EXEs"));
1.730 + TInt i=0;
1.731 + TInt r=0;
1.732 + TInt x=0;
1.733 + for (x=0; x<KNumModules; ++x)
1.734 + {
1.735 + TUint32 f=GetModuleFlags(x);
1.736 + if (!(f&KModuleFlagExe))
1.737 + continue;
1.738 +#ifdef __WINS__
1.739 + if (f&KModuleFlagTargetOnly)
1.740 + continue;
1.741 +#endif
1.742 + RProcess p1, p2;
1.743 + RLoaderTest lt1, lt2;
1.744 + TModuleList exe_info1;
1.745 + TModuleList exe_info2;
1.746 + TUint32 tt;
1.747 + r=LoadExe(x, 0, p1, tt);
1.748 + test.Printf(_L("LoadExe1(%d)->%d\n"),x,r);
1.749 + test.Printf(_L("BENCHMARK: LoadExe1(%d)->%dms\n"),x,tt);
1.750 + test(r==KErrNone);
1.751 + r=lt1.Connect(x, 0);
1.752 + test.Printf(_L("Connect1(%d)->%d\n"),x,r);
1.753 + test(r==KErrNone);
1.754 + TInt s=DetermineLoadExe2Result(x);
1.755 + r=LoadExe(x, 1, p2, tt);
1.756 + test.Printf(_L("LoadExe2(%d)->%d (%d)\n"),x,r,s);
1.757 + if (s==KErrNone)
1.758 + test.Printf(_L("BENCHMARK: LoadExe2(%d)->%dms\n"),x,tt);
1.759 + test(r==Min(s,0));
1.760 +
1.761 + if (r==KErrNone)
1.762 + {
1.763 + r=lt2.Connect(x, 1);
1.764 + test.Printf(_L("Connect2(%d)->%d\n"),x,r);
1.765 + test(r==KErrNone);
1.766 + r=lt1.GetExeDepList(exe_info1.iInfo);
1.767 + test(r==KErrNone);
1.768 + exe_info1.SetCount();
1.769 + DumpModuleList(exe_info1, x);
1.770 + r=lt2.GetExeDepList(exe_info2.iInfo);
1.771 + test(r==KErrNone);
1.772 + exe_info2.SetCount();
1.773 + DumpModuleList(exe_info2, x);
1.774 +
1.775 + test(exe_info1.iCount==exe_info2.iCount);
1.776 + if (s==1)
1.777 + {
1.778 + TInt nm=exe_info1.iCount;
1.779 + test(exe_info1.iInfo[nm-1].iModuleHandle!=exe_info2.iInfo[nm-1].iModuleHandle);
1.780 + }
1.781 +#ifdef __WINS__
1.782 + else if((GetModuleFlags(x) & KModuleFlagData))
1.783 +#else
1.784 + else
1.785 +#endif
1.786 + {
1.787 + for (i=0; i<exe_info1.iCount; ++i)
1.788 + test(exe_info1.iInfo[i].iModuleHandle==exe_info2.iInfo[i].iModuleHandle);
1.789 + }
1.790 +
1.791 + const TInt* tests=TC_ExeLoad;
1.792 + TInt ntests=*tests++;
1.793 + while(ntests--)
1.794 + {
1.795 + TInt m=*tests++;
1.796 + TModuleList dll_init_info1;
1.797 + TModuleList dll_c_info1;
1.798 + TModuleList dll_d_info1;
1.799 + TModuleList dll_init_info2;
1.800 + TModuleList dll_c_info2;
1.801 + TModuleList dll_d_info2;
1.802 + TInt h1=lt1.LoadDll(m, dll_init_info1.iInfo);
1.803 + dll_init_info1.SetCount();
1.804 + test.Printf(_L("LoadDll1(%d)->%d\n"),m,h1);
1.805 + if (h1>=0)
1.806 + {
1.807 + DumpModuleList(dll_init_info1, x);
1.808 + CheckModuleList(m, dll_init_info1);
1.809 + test(lt1.GetCDList(dll_c_info1.iInfo)==KErrNone);
1.810 + dll_c_info1.SetCount();
1.811 + dll_c_info1.Display(_L("Construct1: "));
1.812 + TInt y=(41*m+487);
1.813 + r=lt1.CallRBlkI(h1,y);
1.814 + r-=y;
1.815 + r/=INC_BLOCK_SZ;
1.816 + test.Printf(_L("DLL1 %d RBlkI->%d\n"),m,r);
1.817 + y=ModuleRBlkIParams[m][1]+ModuleRBlkIParams[m][0]*DLLNUMOFFSET;
1.818 + test(r==y);
1.819 +
1.820 + TInt s=DetermineDllLoadResult(m, x, x);
1.821 + TInt h2=lt2.LoadDll(m, dll_init_info2.iInfo);
1.822 + dll_init_info2.SetCount();
1.823 + test.Printf(_L("LoadDll2(%d)->%d (%d)\n"),m,h2,s);
1.824 + test(h2==Min(s,0));
1.825 + if (h2>=0)
1.826 + {
1.827 + DumpModuleList(dll_init_info2, x);
1.828 + CheckModuleList(m, dll_init_info2);
1.829 + test(lt2.GetCDList(dll_c_info2.iInfo)==KErrNone);
1.830 + dll_c_info2.SetCount();
1.831 + dll_c_info2.Display(_L("Construct2: "));
1.832 + y=(79*m+257);
1.833 + r=lt2.CallRBlkI(h2,y);
1.834 + r-=y;
1.835 + r/=INC_BLOCK_SZ;
1.836 + test.Printf(_L("DLL2 %d RBlkI->%d\n"),m,r);
1.837 + y=ModuleRBlkIParams[m][1]+ModuleRBlkIParams[m][0]*DLLNUMOFFSET;
1.838 + test(r==y);
1.839 +
1.840 + test(dll_init_info1.iCount==dll_init_info2.iCount);
1.841 +#ifdef __WINS__
1.842 + if (s==1 && !(ModuleFlags[m]&KModuleFlagDataInTree))
1.843 +#else
1.844 + if (s==1)
1.845 +#endif
1.846 + {
1.847 + TInt nm=dll_init_info1.iCount;
1.848 + test(dll_init_info1.iInfo[nm-1].iModuleHandle!=dll_init_info2.iInfo[nm-1].iModuleHandle);
1.849 + }
1.850 + else
1.851 + {
1.852 + for (i=0; i<dll_init_info1.iCount; ++i)
1.853 + test(dll_init_info1.iInfo[i].iModuleHandle==dll_init_info2.iInfo[i].iModuleHandle);
1.854 + }
1.855 +
1.856 + r=lt2.CloseDll(h2);
1.857 + test.Printf(_L("CloseDll2(%d)->%d\n"),h2,r);
1.858 + test(r==KErrNone);
1.859 + test(lt2.GetCDList(dll_d_info2.iInfo)==KErrNone);
1.860 + dll_d_info2.SetCount();
1.861 + dll_d_info2.Display(_L("Destruct2: "));
1.862 + test(dll_d_info2.iCount==dll_c_info2.iCount);
1.863 + for (i=0; i<dll_d_info2.iCount; ++i)
1.864 + test(dll_d_info2.iInfo[i].iDllNum==dll_c_info2.iInfo[dll_c_info2.iCount-i-1].iDllNum);
1.865 + }
1.866 +
1.867 + r=lt1.CloseDll(h1);
1.868 + test.Printf(_L("CloseDll1(%d)->%d\n"),h1,r);
1.869 + test(r==KErrNone);
1.870 + test(lt1.GetCDList(dll_d_info1.iInfo)==KErrNone);
1.871 + dll_d_info1.SetCount();
1.872 + dll_d_info1.Display(_L("Destruct1: "));
1.873 + test(dll_d_info1.iCount==dll_c_info1.iCount);
1.874 + for (i=0; i<dll_d_info1.iCount; ++i)
1.875 + test(dll_d_info1.iInfo[i].iDllNum==dll_c_info1.iInfo[dll_c_info1.iCount-i-1].iDllNum);
1.876 + }
1.877 + }
1.878 +
1.879 + lt2.Exit();
1.880 + p2.Close();
1.881 + }
1.882 + lt1.Exit();
1.883 + p1.Close();
1.884 + }
1.885 + }
1.886 +
1.887 +void SetLoaderFail(TInt aLdr, TInt aKern)
1.888 + {
1.889 + test.Printf(_L("ldr=%d, kern=%d\n"),aLdr,aKern);
1.890 + RLoader l;
1.891 + test(l.Connect()==KErrNone);
1.892 + test(l.DebugFunction(ELoaderDebug_SetHeapFail, aLdr, aKern, 0)==KErrNone);
1.893 + l.Close();
1.894 + }
1.895 +
1.896 +void SetLoaderFailRFs(TInt aError, TInt aCount)
1.897 + {
1.898 + test.Printf(_L("SetLoaderFailRFs: error=%d, count=%d\n"),aError,aCount);
1.899 + RLoader l;
1.900 + test(l.Connect()==KErrNone);
1.901 + test(l.DebugFunction(ELoaderDebug_SetRFsFail, aError, aCount, 0)==KErrNone);
1.902 + l.Close();
1.903 + }
1.904 +
1.905 +class TLoopOOM
1.906 + {
1.907 +public:
1.908 + enum OomState{EInit, EKernelHeap, EUserHeap, ERFsError};
1.909 +
1.910 + TLoopOOM();
1.911 + void Reset();
1.912 + TBool Iterate(TInt aResult);
1.913 +public:
1.914 + TInt iLdr;
1.915 + TInt iKern;
1.916 + TInt iRFsCount;
1.917 + OomState iState;
1.918 + };
1.919 +
1.920 +TLoopOOM::TLoopOOM()
1.921 + {
1.922 + Reset();
1.923 + }
1.924 +
1.925 +void TLoopOOM::Reset()
1.926 + {
1.927 + iLdr = 0;
1.928 + iKern = 0;
1.929 + iRFsCount = 0;
1.930 + iState = EInit;
1.931 + }
1.932 +
1.933 +TBool TLoopOOM::Iterate(TInt aResult)
1.934 + {
1.935 + TBool noErrors = (aResult==KErrNone||aResult==KErrNotSupported);
1.936 +
1.937 + test.Printf(_L("%d %d %d %d\n"), iKern,iLdr,iRFsCount,aResult);
1.938 +
1.939 + switch(iState)
1.940 + {
1.941 +
1.942 + case EInit:
1.943 + iState = EKernelHeap;
1.944 + SetLoaderFail(iLdr,++iKern);
1.945 + return ETrue;
1.946 +
1.947 + case EKernelHeap:
1.948 + if (noErrors)
1.949 + {
1.950 + iKern = 0;
1.951 + iLdr = 1;
1.952 + iState = EUserHeap;
1.953 + }
1.954 + else
1.955 + ++iKern;
1.956 +
1.957 + SetLoaderFail(iLdr,iKern);
1.958 + return ETrue;
1.959 +
1.960 + case EUserHeap:
1.961 + if (noErrors)
1.962 + {
1.963 + iLdr = 0;
1.964 + iState = ERFsError;
1.965 + SetLoaderFail(0,0);
1.966 + SetLoaderFailRFs(KRFsError, ++iRFsCount);
1.967 + }
1.968 + else
1.969 + SetLoaderFail(++iLdr,iKern);
1.970 + return ETrue;
1.971 +
1.972 + case ERFsError:
1.973 + if (noErrors)
1.974 + break;
1.975 + else
1.976 + {
1.977 + SetLoaderFailRFs(KRFsError, ++iRFsCount);
1.978 + return ETrue;
1.979 + }
1.980 + }
1.981 +
1.982 + SetLoaderFailRFs(KErrNone, 0);
1.983 + return EFalse;
1.984 + }
1.985 +
1.986 +void LoaderTest::TestOOM()
1.987 + {
1.988 + test.Next(_L("Test OOM Handling"));
1.989 +#ifdef _DEBUG
1.990 + TInt r=0;
1.991 + TInt x=0;
1.992 + TUint32 tt;
1.993 + for (x=0; x<KNumModules; ++x)
1.994 + {
1.995 + if (!(GetModuleFlags(x)&KModuleFlagExe))
1.996 + continue;
1.997 +#ifdef __WINS__
1.998 + if (GetModuleFlags(x)&KModuleFlagTargetOnly)
1.999 + continue;
1.1000 +#endif
1.1001 +
1.1002 + if ((GetModuleFlags(x) & KModuleFlagVDrive) && NoRemovable)
1.1003 + {
1.1004 + test.Printf(_L("LoaderTest::TestOOM Not testing dll %d from removable media\n"),x);
1.1005 + continue;
1.1006 + }
1.1007 + if (x==iCmdLine[1])
1.1008 + TraceOn();
1.1009 + TLoopOOM loom;
1.1010 + RProcess p;
1.1011 + RLoaderTest lt;
1.1012 + while(loom.Iterate(r))
1.1013 + {
1.1014 + r=LoadExe(x, 0, p, tt);
1.1015 + test.Printf(_L("LoadExe(%d)->%d\n"),x,r);
1.1016 + test(r==KErrNone || (loom.iState!=TLoopOOM::ERFsError && r==KErrNoMemory) ||
1.1017 + (loom.iState==TLoopOOM::ERFsError && r==KRFsError));
1.1018 + if (r==KErrNone)
1.1019 + {
1.1020 + TInt s=lt.Connect(x);
1.1021 + test.Printf(_L("Connect(%d)->%d\n"),x,s);
1.1022 + test(s==KErrNone);
1.1023 + lt.Exit();
1.1024 + p.Close();
1.1025 + }
1.1026 + }
1.1027 + SetLoaderFail(0,0);
1.1028 + r=LoadExe(x, 0, p, tt);
1.1029 + test(r==KErrNone);
1.1030 + r=lt.Connect(x);
1.1031 + test(r==KErrNone);
1.1032 + const TInt* tests=TC_DllOOM;
1.1033 + TInt ntests=*tests++;
1.1034 + TModuleList list;
1.1035 + while(ntests--)
1.1036 + {
1.1037 + TInt m=*tests++;
1.1038 + if ((GetModuleFlags(m) & KModuleFlagVDrive) && NoRemovable)
1.1039 + {
1.1040 + test.Printf(_L("LoaderTest::TestOOM Not testing dll %d from removable media\n"),m);
1.1041 + continue;
1.1042 + }
1.1043 + loom.Reset();
1.1044 + r=KErrNone;
1.1045 + while(loom.Iterate(r))
1.1046 + {
1.1047 + TInt h=lt.LoadDll(m, list.iInfo);
1.1048 + r=Min(h,0);
1.1049 + test.Printf(_L("%d:LoadDll(%d)->%d\n"),x,m,h);
1.1050 +
1.1051 + test(r==KErrNone || r==KErrNotSupported || KErrNoMemory ||
1.1052 + (loom.iState==TLoopOOM::ERFsError && r==KRFsError) );
1.1053 +
1.1054 + if (r==KErrNone)
1.1055 + {
1.1056 + TInt s=lt.CloseDll(h);
1.1057 + test(s==KErrNone);
1.1058 + }
1.1059 + }
1.1060 + }
1.1061 + lt.Exit();
1.1062 + p.Close();
1.1063 + if (x==iCmdLine[1])
1.1064 + TraceOff();
1.1065 + }
1.1066 +#else
1.1067 + test.Printf(_L("Only on DEBUG builds\n"));
1.1068 +#endif
1.1069 + }
1.1070 +
1.1071 +class RLoaderTestHandle : public RSessionBase
1.1072 + {
1.1073 +public:
1.1074 + TInt Connect();
1.1075 + void TryToGetPaniced();
1.1076 + };
1.1077 +
1.1078 +TInt RLoaderTestHandle::Connect()
1.1079 + {
1.1080 + return CreateSession(_L("!Loader"),TVersion(KLoaderMajorVersionNumber,KLoaderMinorVersionNumber,KE32BuildVersionNumber));
1.1081 + }
1.1082 +
1.1083 +void RLoaderTestHandle::TryToGetPaniced()
1.1084 + {
1.1085 + _LIT(KFoo,"foo");
1.1086 + TLdrInfo info;
1.1087 + TPckg<TLdrInfo> infoBuf(info);
1.1088 + TIpcArgs args;
1.1089 + args.Set(0,(TDes8*)&infoBuf);
1.1090 + args.Set(1,&KFoo);
1.1091 + args.Set(2,&KFoo);
1.1092 + SendReceive(ELoadLibrary, args);
1.1093 + }
1.1094 +
1.1095 +TInt PanicTestThread(TAny*)
1.1096 + {
1.1097 + RLoaderTestHandle t;
1.1098 + TInt r = t.Connect();
1.1099 + if (r==KErrNone) t.TryToGetPaniced();
1.1100 + return r;
1.1101 + }
1.1102 +
1.1103 +
1.1104 +void TestCorruptedFiles()
1.1105 + {
1.1106 + test.Next(_L("Test corrupted files"));
1.1107 +
1.1108 + TInt numCorruptFiles=0;
1.1109 + TInt r=0;
1.1110 + for (TInt x=0; x<KNumModules; ++x)
1.1111 + {
1.1112 + if (!(GetModuleFlags(x)&KModuleFlagExe))
1.1113 + continue;
1.1114 +
1.1115 + const TPtrC fn = MODULE_FILENAME(x);
1.1116 + if (fn[1] != ':')
1.1117 + continue;
1.1118 +
1.1119 + if (++numCorruptFiles > KNumberOfCorruptFiles)
1.1120 + break;
1.1121 +
1.1122 + RProcess p;
1.1123 + TUint32 tt;
1.1124 + r=LoadExe(x, 0, p, tt);
1.1125 + test.Printf(_L("LoadCorruptExe(%d)->%d\n"),x,r);
1.1126 + test(r==KErrCorrupt);
1.1127 + }
1.1128 + }
1.1129 +
1.1130 +// -------- copying files to non-ROM media --------
1.1131 +
1.1132 +static void GetSpecialDrives()
1.1133 +/**
1.1134 + Work out which physical drive corresponds to each
1.1135 + numeric drive in the list of filenames. This populates
1.1136 + SpecialDrives.
1.1137 +
1.1138 + @see SpecialDrives
1.1139 + */
1.1140 + {
1.1141 + test.Printf(_L("NoRemovable=%d\n"),NoRemovable);
1.1142 +
1.1143 + // mark each special drive as not present
1.1144 + for (TInt i = 0; i < KSpecialDriveCount; ++i)
1.1145 + {
1.1146 + SpecialDrives[i] = '!';
1.1147 + }
1.1148 +
1.1149 + // cannot load binaries from emulated removable drives
1.1150 +#if defined (__WINS__)
1.1151 + SpecialDrives[1] = 'c'; // "removable"
1.1152 +#endif
1.1153 +
1.1154 + TBuf<12> hashDir;
1.1155 + hashDir = KSysHash;
1.1156 + hashDir[0] = (TUint8) RFs::GetSystemDriveChar();
1.1157 +
1.1158 + TInt r = Fs.MkDirAll(hashDir);
1.1159 + test(r == KErrNone || r == KErrAlreadyExists);
1.1160 +
1.1161 + for (TInt d = 0; d <= (TInt)sizeof(SpecialDriveList); ++d)
1.1162 + {
1.1163 + TInt dr = SpecialDriveList[d];
1.1164 + TDriveInfo di;
1.1165 + test.Printf(_L("Drive %d\n"), dr);
1.1166 + test(Fs.Drive(di, dr) == KErrNone);
1.1167 + if (di.iType == EMediaNotPresent)
1.1168 + continue;
1.1169 +
1.1170 + TChar ch0;
1.1171 + test(RFs::DriveToChar(dr, ch0) == KErrNone);
1.1172 +
1.1173 + TText ch = static_cast<TText>(TUint(ch0));
1.1174 +
1.1175 + // drive 0 == internal
1.1176 + if ((di.iDriveAtt & KDriveAttInternal) && SpecialDrives[0] == '!')
1.1177 + {
1.1178 + SpecialDrives[0] = ch;
1.1179 + if (NoRemovable)
1.1180 + SpecialDrives[1] = ch;
1.1181 + }
1.1182 + // drive 1 == removable
1.1183 + else if ((di.iDriveAtt & KDriveAttRemovable) && SpecialDrives[1] == '!' && !NoRemovable)
1.1184 + SpecialDrives[1] = ch;
1.1185 + else
1.1186 + {
1.1187 + // drive not useful so continue and don't create \sys\bin
1.1188 + continue;
1.1189 + }
1.1190 +
1.1191 + TFileName fn;
1.1192 + fn.Append(ch);
1.1193 + fn.Append(_L(":\\sys\\bin\\"));
1.1194 + r = Fs.MkDirAll(fn);
1.1195 + test.Printf(_L("MkDirAll %S returns %d\n"), &fn, r);
1.1196 + test(r == KErrNone || r == KErrAlreadyExists);
1.1197 + }
1.1198 + }
1.1199 +
1.1200 +void GetNonZFileName(const TDesC& aOrigName, TDes& aNonZName)
1.1201 +/**
1.1202 + Resolve a special drive to the target drive using the mappings in
1.1203 + SpecialDrives. This is used to load non-XIP binaries from pageable media.
1.1204 +
1.1205 + @param aOrigName Fully-qualified filename with special drive number.
1.1206 + E.g., "3:\\sys\\bin\\dllt45.dll".
1.1207 + @param aNonZName Descriptor to populate with aOrigName and the transformed
1.1208 + drive, e.g. "c:\\sys\\bin\\dllt45.dll".
1.1209 + */
1.1210 + {
1.1211 + test.Printf(_L(">GetNonZFileName,\"%S\"\n"), &aOrigName);
1.1212 + test(aOrigName[1] == ':');
1.1213 + aNonZName.Copy(aOrigName);
1.1214 + TText replaceChar = SpecialDrives[aOrigName[0] - '0'];
1.1215 + test(TChar(replaceChar).IsAlpha());
1.1216 + aNonZName[0] = replaceChar;
1.1217 + test.Printf(_L("<GetNonZFileName,\"%S\"\n"), &aNonZName);
1.1218 + }
1.1219 +
1.1220 +static void GetHashFileName(const TDesC& aOrigName, TDes& aHashName)
1.1221 +/**
1.1222 + Get name of the hash file used for an EXE or DLL which has been
1.1223 + copied to writable media.
1.1224 +
1.1225 + @param aOrigName Name of EXE or DLL which has been copied to
1.1226 + writable media. This does not have to be
1.1227 + qualified because only the name and extension
1.1228 + are used.
1.1229 + @param aHashName On return this is set to the absolute filename
1.1230 + which should contain the file's hash. This
1.1231 + function does not create the file, or its containing
1.1232 + directory.
1.1233 + */
1.1234 + {
1.1235 + aHashName.Copy(KSysHash);
1.1236 + aHashName[0] = (TUint8) RFs::GetSystemDriveChar();
1.1237 + const TParsePtrC ppc(aOrigName);
1.1238 + aHashName.Append(ppc.NameAndExt());
1.1239 + }
1.1240 +
1.1241 +static void CopyExecutablesL(TBool aCorruptMode=EFalse)
1.1242 +/**
1.1243 + Make a copy of each executable that should be copied
1.1244 + to a writable drive.
1.1245 +
1.1246 + If aCorruptMode make KNumberOfCorruptFiles corrupted copies: truncated file and a file with corrupted header
1.1247 +
1.1248 + */
1.1249 + {
1.1250 + TInt r;
1.1251 + TInt numCorruptFiles = 0;
1.1252 +
1.1253 + GetSpecialDrives();
1.1254 +
1.1255 + CFileMan* fm = CFileMan::NewL(Fs);
1.1256 +
1.1257 + for (TInt i = 0; i < KNumModules; ++i)
1.1258 + {
1.1259 + if (aCorruptMode && numCorruptFiles==KNumberOfCorruptFiles)
1.1260 + break;
1.1261 +
1.1262 + if (aCorruptMode && !(GetModuleFlags(i)&KModuleFlagExe))
1.1263 + continue;
1.1264 +
1.1265 + const TPtrC fn = MODULE_FILENAME(i);
1.1266 +
1.1267 + // if this is an absolute filename then copy it to
1.1268 + // the appropriate drive.
1.1269 + if (fn[1] != ':')
1.1270 + continue;
1.1271 +
1.1272 + TFileName fnDest;
1.1273 + GetNonZFileName(fn, fnDest);
1.1274 +
1.1275 +
1.1276 + TFileName fnSrc(fn);
1.1277 + fnSrc[0] = 'z';
1.1278 +
1.1279 + test.Printf(_L("CopyExecutables;%S,%S\n"), &fnSrc, &fnDest);
1.1280 +
1.1281 +#ifdef __WINS__
1.1282 + const TParsePtrC sppc(fnSrc);
1.1283 + TBuf<MAX_PATH> sName;
1.1284 + r = MapEmulatedFileName(sName, sppc.NameAndExt());
1.1285 + test(r == KErrNone);
1.1286 +
1.1287 + TBuf<MAX_PATH> dName;
1.1288 + r = MapEmulatedFileName(dName, fnDest);
1.1289 + test(r == KErrNone);
1.1290 +
1.1291 + BOOL b = Emulator::CopyFile((LPCTSTR)sName.PtrZ(),(LPCTSTR)dName.PtrZ(),FALSE);
1.1292 + test(b);
1.1293 +#else
1.1294 + r = fm->Copy(fnSrc, fnDest);
1.1295 + test(r == KErrNone);
1.1296 +#endif
1.1297 +
1.1298 + r = Fs.SetAtt(fnDest, 0, KEntryAttReadOnly);
1.1299 + test.Printf(_L("CopyExecutables:setatt=%d\n"), r);
1.1300 + User::LeaveIfError(r);
1.1301 +
1.1302 +#ifdef __EPOC32__
1.1303 + TInt moduleFlags = GetModuleFlags(i);
1.1304 +
1.1305 + // modify the new destination file by applying the required paging flags
1.1306 + RFile fNp;
1.1307 + r = fNp.Open(Fs, fnDest, EFileWrite | EFileStream);
1.1308 + User::LeaveIfError(r);
1.1309 + CleanupClosePushL(fNp);
1.1310 +
1.1311 + // read the header and get the total number of bytes to checksum.
1.1312 + // (This may be greater than sizeof(E32ImageHeader).
1.1313 + TPckgBuf<E32ImageHeader> hdrBuf;
1.1314 + r = fNp.Read(0, hdrBuf);
1.1315 + User::LeaveIfError(r);
1.1316 + TInt totalSize = hdrBuf().TotalSize();
1.1317 + test.Printf(_L("np flags=0x%x,totalSize=%d\n"), hdrBuf().iFlags, totalSize);
1.1318 +
1.1319 + // read in the actual bytes to checksum
1.1320 + TUint8* startBytes0 = (TUint8*) User::AllocLC(totalSize);
1.1321 + TPtr8 startBytes(startBytes0, 0, totalSize);
1.1322 + r = fNp.Read(0, startBytes);
1.1323 + User::LeaveIfError(r);
1.1324 + test(startBytes.Length() == totalSize);
1.1325 +
1.1326 + // apply the required paging flags to the header
1.1327 + E32ImageHeader* hdr2 = reinterpret_cast<E32ImageHeader*>(startBytes0);
1.1328 + TUint& flags = hdr2->iFlags;
1.1329 + flags &= ~(KImageCodePaged | KImageCodeUnpaged);
1.1330 + if (moduleFlags & KModuleFlagPagedCode)
1.1331 + flags |= KImageCodePaged;
1.1332 + if (moduleFlags & KModuleFlagUnpagedCode)
1.1333 + flags |= KImageCodeUnpaged;
1.1334 + test.Printf(_L("setting new image flags 0x%x\n"), flags);
1.1335 +
1.1336 + // corrupt header of the 2nd file
1.1337 + if (aCorruptMode && numCorruptFiles==1 && (moduleFlags&KModuleFlagExe))
1.1338 + {
1.1339 + hdr2->iCodeBase += 3;
1.1340 + hdr2->iDataBase += 1;
1.1341 + hdr2->iImportOffset += 1;
1.1342 + hdr2->iCodeRelocOffset += 3;
1.1343 + hdr2->iDataRelocOffset += 3;
1.1344 +
1.1345 + ++numCorruptFiles;
1.1346 + }
1.1347 +
1.1348 + // recalculate the checksum
1.1349 + hdr2->iHeaderCrc = KImageCrcInitialiser;
1.1350 + TUint32 crc = 0;
1.1351 + Mem::Crc32(crc, startBytes.Ptr(), totalSize);
1.1352 + hdr2->iHeaderCrc = crc;
1.1353 + r = fNp.Write(0, startBytes);
1.1354 + User::LeaveIfError(r);
1.1355 +
1.1356 + // truncate 1st corrupted file
1.1357 + if (aCorruptMode && numCorruptFiles==0 && (moduleFlags&KModuleFlagExe))
1.1358 + {
1.1359 + TInt size;
1.1360 + r = fNp.Size(size);
1.1361 + User::LeaveIfError(r);
1.1362 + // if trncate by 1 it managed to load. if trancate by 3 it failed to load with KErrCorrupt as expected
1.1363 + r = fNp.SetSize(size-3);
1.1364 + User::LeaveIfError(r);
1.1365 + ++numCorruptFiles;
1.1366 + }
1.1367 +
1.1368 + CleanupStack::PopAndDestroy(2, &fNp); // startBytes0, fNp
1.1369 +#endif
1.1370 +
1.1371 + // if copied to removable media, then generate hash
1.1372 + if (fn[0] == '0')
1.1373 + continue;
1.1374 +
1.1375 + CSHA1* sha1 = CSHA1::NewL();
1.1376 + CleanupStack::PushL(sha1);
1.1377 +
1.1378 + RFile fDest;
1.1379 + r = fDest.Open(Fs, fnDest, EFileRead | EFileStream);
1.1380 + User::LeaveIfError(r);
1.1381 + CleanupClosePushL(fDest);
1.1382 +
1.1383 + TBool done;
1.1384 + TBuf8<512> content;
1.1385 + do
1.1386 + {
1.1387 + r = fDest.Read(content);
1.1388 + User::LeaveIfError(r);
1.1389 + done = (content.Length() == 0);
1.1390 + if (! done)
1.1391 + sha1->Update(content);
1.1392 + } while (! done);
1.1393 + CleanupStack::PopAndDestroy(&fDest);
1.1394 +
1.1395 + // write hash to \sys\hash
1.1396 + TBuf8<SHA1_HASH> hashVal = sha1->Final();
1.1397 +
1.1398 + // reuse fnSrc to save stack space
1.1399 + GetHashFileName(fnDest, fnSrc);
1.1400 + RFile fHash;
1.1401 + r = fHash.Replace(Fs, fnSrc, EFileWrite | EFileStream);
1.1402 + test.Printf(_L("hash file,%S,r=%d\n"), &fnSrc, r);
1.1403 + User::LeaveIfError(r);
1.1404 + CleanupClosePushL(fHash);
1.1405 + r = fHash.Write(hashVal);
1.1406 + User::LeaveIfError(r);
1.1407 +
1.1408 + CleanupStack::PopAndDestroy(2, sha1);
1.1409 + }
1.1410 +
1.1411 + delete fm;
1.1412 + }
1.1413 +
1.1414 +static void DeleteExecutables(TBool aCorruptMode=EFalse)
1.1415 +/**
1.1416 + Delete any executables which were created by CopyExecutables.
1.1417 + This function is defined so the test cleans up when it has finished.
1.1418 + */
1.1419 + {
1.1420 + TInt numCorruptFiles = 0;
1.1421 +
1.1422 + for (TInt i = 0; i < KNumModules; ++i)
1.1423 + {
1.1424 + if (aCorruptMode && numCorruptFiles==KNumberOfCorruptFiles)
1.1425 + break;
1.1426 +
1.1427 + if (aCorruptMode && !(GetModuleFlags(i)&KModuleFlagExe))
1.1428 + continue;
1.1429 +
1.1430 + const TPtrC fn = MODULE_FILENAME(i);
1.1431 +
1.1432 + // if this is an absolute filename then copy it to
1.1433 + // the appropriate drive.
1.1434 + if (fn[1] != ':')
1.1435 + continue;
1.1436 +
1.1437 + test.Printf(_L("DeleteExecutables:fn=%S\n"), &fn);
1.1438 + TFileName fnDest;
1.1439 + GetNonZFileName(fn, fnDest);
1.1440 +
1.1441 + TInt r;
1.1442 +
1.1443 + r = Fs.Delete(fnDest);
1.1444 + test.Printf(_L("DeleteExecutables:fnDest=%S,del=%d\n"), &fnDest, r);
1.1445 + test(r == KErrNone);
1.1446 +
1.1447 + // only need to delete hash files for binaries copied to removable media,
1.1448 + // but simpler to delete and test for KErrNotFound
1.1449 + TFileName fnHash;
1.1450 + GetHashFileName(fnDest, fnHash);
1.1451 + r = Fs.Delete(fnHash);
1.1452 + test.Printf(_L("DeleteExecutables,h=%S,hdel=%d\n"), &fnHash, r);
1.1453 + test(r == KErrPathNotFound || r == KErrNotFound || r == KErrNone);
1.1454 +
1.1455 + if (aCorruptMode)
1.1456 + ++numCorruptFiles;
1.1457 + }
1.1458 + }
1.1459 +
1.1460 +GLDEF_C TInt E32Main()
1.1461 + {
1.1462 + RThread().SetPriority(EPriorityLess);
1.1463 +
1.1464 + test.Title();
1.1465 + test.Start(_L("Setup"));
1.1466 +
1.1467 + RLoader l;
1.1468 + test(l.Connect()==KErrNone);
1.1469 + test(l.CancelLazyDllUnload()==KErrNone);
1.1470 + l.Close();
1.1471 +
1.1472 + test(TestLdd.Open()==KErrNone);
1.1473 + LoaderTest* pL=LoaderTest::New();
1.1474 + TheLoaderTest=pL;
1.1475 +
1.1476 + TInt tm=pL->iCmdLine[0];
1.1477 + TInt nr = (tm>>4)&3;
1.1478 + if (nr==1)
1.1479 + NoRemovable = ETrue;
1.1480 + else if (nr==2)
1.1481 + NoRemovable = EFalse;
1.1482 +
1.1483 + test(Fs.Connect() == KErrNone);
1.1484 +
1.1485 + // allocate a cleanup stack so can call CFileMan::NewL in CopyExecutables
1.1486 + test.Printf(_L("CopyExecutablesL()\n"));
1.1487 + CTrapCleanup* cleanup=CTrapCleanup::New();
1.1488 + TRAPD(r, CopyExecutablesL());
1.1489 + test(r == KErrNone);
1.1490 + delete cleanup;
1.1491 +
1.1492 + if (tm&1)
1.1493 + pL->TestOneByOne();
1.1494 + if (tm&2)
1.1495 + pL->TestMultipleExeInstances();
1.1496 + if (tm&4)
1.1497 + pL->TestOOM();
1.1498 + if (tm&8)
1.1499 + pL->TestMultipleLoads();
1.1500 +
1.1501 + pL->Close();
1.1502 +
1.1503 + // Test loader error handling - will panic the client thread
1.1504 + test.Next(_L("Test loader error handling - will panic the client thread"));
1.1505 + RThread t;
1.1506 + t.Create(_L("Loader panic test"),PanicTestThread,KDefaultStackSize,0x1000,0x1000,NULL);
1.1507 + TRequestStatus s;
1.1508 + t.Logon(s);
1.1509 + TBool justInTime=User::JustInTime();
1.1510 + User::SetJustInTime(EFalse);
1.1511 + t.Resume();
1.1512 + User::WaitForRequest(s);
1.1513 + test(t.ExitType()==EExitPanic);
1.1514 + test(t.ExitCategory().Compare(_L("LOADER"))==0);
1.1515 + test(t.ExitReason()==0);
1.1516 + t.Close();
1.1517 + User::SetJustInTime(justInTime);
1.1518 +
1.1519 + DeleteExecutables();
1.1520 +
1.1521 +#ifdef __EPOC32__
1.1522 + // test corrupted files
1.1523 + cleanup=CTrapCleanup::New();
1.1524 + test.Next(_L("CopyExecutablesL(ETrue)"));
1.1525 + TRAPD(rr, CopyExecutablesL(ETrue));
1.1526 + test(rr == KErrNone);
1.1527 + delete cleanup;
1.1528 + test.Next(_L("TestCorruptedFiles()"));
1.1529 + TestCorruptedFiles();
1.1530 + test.Next(_L("DeleteExecutables()"));
1.1531 + DeleteExecutables(ETrue);
1.1532 +#endif
1.1533 +
1.1534 + Fs.Close();
1.1535 +
1.1536 + test.End();
1.1537 + return KErrNone;
1.1538 + }
1.1539 +