First public contribution.
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".
8 // Initial Contributors:
9 // Nokia Corporation - initial contribution.
14 // f32test\loader\t_ldrtst.cpp
18 #define __E32TEST_EXTENSION__
22 #include "../../../e32test/mmu/d_memorytest.h"
27 #elif defined(__EPOC32__)
31 const TInt KNumberOfCorruptFiles = 2;
33 RTest test(_L("T_LDRTST"));
35 LoaderTest* TheLoaderTest;
37 #if defined (__X86__) || defined(__WINS__)
38 TBool NoRemovable=ETrue;
40 TBool NoRemovable=EFalse;
43 /** Error code of simulated RFs error */
44 const TInt KRFsError = -99;
47 Number of drives which are identified by a numeric value,
48 which means, e.g., run from an internal pageable drive.
50 const TInt KSpecialDriveCount = 2;
52 /** The real drive letters corresponding to each special drive. */
53 static TFixedArray<TText, KSpecialDriveCount> SpecialDrives;
55 /** Bitmask of paged and unpaged module flags. */
56 const TUint32 KModulePagedCodeFlags = (KModuleFlagPagedCode | KModuleFlagUnpagedCode);
58 _LIT(KSysHash,"?:\\Sys\\Hash\\");
60 TInt GetModuleFlags(TInt aModule)
62 TInt f = ModuleFlags[aModule];
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
68 if (f & KModuleFlagExe)
70 #endif // #ifdef __EPOC32__
74 TModuleSet::TModuleSet()
76 Mem::FillZ(this,sizeof(TModuleSet));
79 void TModuleSet::Add(TInt aModule)
81 TUint8 m=(TUint8)(1<<(aModule&7));
90 void TModuleSet::Remove(TInt aModule)
92 TUint8 m=(TUint8)(1<<(aModule&7));
101 TModuleSet::TModuleSet(const TModuleList& aList, TInt aMask, TInt aVal)
103 Mem::FillZ(this,sizeof(TModuleSet));
105 for (i=0; i<aList.iCount; ++i)
107 TInt m=aList.iInfo[i].iDllNum;
108 if (((GetModuleFlags(m)&aMask)^aVal)==0)
109 Add(aList.iInfo[i].iDllNum);
113 void TModuleSet::Remove(const TModuleList& aList)
116 for (i=0; i<aList.iCount; ++i)
117 Remove(aList.iInfo[i].iDllNum);
120 void TModuleSet::Display(const TDesC& aTitle) const
124 for (i=0; i<iCount; ++i)
127 s.AppendFormat(_L("%3d "),i);
129 test.Printf(_L("%S\n"),&s);
132 TModuleList::TModuleList()
135 Mem::Fill(iInfo, KNumModules*sizeof(SDllInfo), 0xff);
138 void TModuleList::SetCount()
141 for (i=0; i<KNumModules && iInfo[i].iDllNum>=0; ++i) {}
145 void TModuleList::Display(const TDesC& aTitle) const
149 for (i=0; i<iCount; ++i)
151 TInt modnum=iInfo[i].iDllNum;
152 s.AppendFormat(_L("%3d "),modnum);
154 test.Printf(_L("%S\n"),&s);
157 TBool TModuleList::IsPresent(TInt aModNum) const
159 return Find(aModNum)>=0;
162 TInt TModuleList::Find(TInt aModNum) const
165 for (i=iCount-1; i>=0 && iInfo[i].iDllNum!=aModNum; --i) {}
169 void TModuleList::Add(const SDllInfo& a)
175 RMemoryTestLdd TestLdd;
177 TBool AddressReadable(TLinAddr a)
180 return TestLdd.ReadMemory((TAny*)a,value)==KErrNone;
183 TInt LoaderTest::DetermineDllLoadResult(TInt aDllNum, TInt aExeNum)
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);
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.
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);
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
206 if (flagsChecked && (dllflags & KModulePagedCodeFlags) == KModulePagedCodeFlags)
208 TBool codePolDefUnpaged = (policy == EKernelConfigCodePagingPolicyDefaultUnpaged);
209 TBool codePolDefPaged = (policy == EKernelConfigCodePagingPolicyDefaultPaged);
210 if (codePolDefPaged || codePolDefUnpaged)
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
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
225 if (attp<0 || !(GetModuleFlags(attp)&KModuleFlagFixed))
227 // moving processes only
228 if (!(exeflags&KModuleFlagFixed))
230 return KErrNotSupported;
232 // fixed attach process only
234 return KErrNotSupported;
242 TInt LoaderTest::DetermineDllLoadResult(TInt aDllNum, TInt aExeNum1, TInt aExeNum2)
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
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
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
267 return KErrNotSupported;
271 TBool LoaderTest::IsRomAddress(TLinAddr a)
273 const TRomHeader& rh=*(const TRomHeader*)UserSvr::RomHeaderAddress();
274 return (a>=rh.iRomBase && (a-rh.iRomBase)<rh.iRomSize);
277 TBool LoaderTest::IsRamCodeAddress(TLinAddr a)
279 switch (iMemModelAtt & EMemModelTypeMask)
281 case EMemModelTypeDirect:
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);
296 TBool LoaderTest::CheckDataAddress(TLinAddr a, TInt aDllNum, TInt aExeNum)
298 TInt xf=GetModuleFlags(aExeNum);
299 TInt df=GetModuleFlags(aDllNum);
300 switch (iMemModelAtt & EMemModelTypeMask)
302 case EMemModelTypeDirect:
304 case EMemModelTypeMoving:
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);
313 case EMemModelTypeMultiple:
314 return (a<0x80000000u);
315 case EMemModelTypeFlexible:
316 return (a<0x80000000u);
317 case EMemModelTypeEmul:
318 return (a<0x80000000u);
324 void LoaderTest::DumpModuleInfo(const SDllInfo& aInfo, TInt aExeNum)
326 TInt flags=GetModuleFlags(aInfo.iDllNum);
327 TUint32 mmtype=iMemModelAtt & EMemModelTypeMask;
328 TAny* h=iDev.ModuleCodeSeg(aInfo.iModuleHandle);
332 test(flags & KModuleFlagXIP);
333 test(IsRomAddress(aInfo.iEntryPointAddress));
334 test.Printf(_L("Module handle %08x ROM XIP\n"),aInfo.iModuleHandle);
336 test(!(flags & KModuleFlagData));
339 TCodeSegCreateInfo info;
340 TInt r=iDev.GetCodeSegInfo(h, info);
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;
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);
353 test(total_data_size==0);
355 // ensure code paged iff expected. This implements the logic from
356 // PREQ1110 Design Sketch SGL.TS0022.008 v1.0 S3.1.3.2
358 TUint policy = E32Loader::PagingPolicy();
361 TBool isCodePaged = (info.iAttr & ECodeSegAttCodePaged)!=0;
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))
367 test.Printf(_L("sbcpexp,1\n"));
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)
375 test.Printf(_L("sbcpexp,2\n"));
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')
382 // test.Printf(_L("sbcpexp,2\n"));
385 // 4. [If not bytepair [or uncompressed]] then Unpaged
386 else if ((flags & (KModuleFlagBytePair | KModuleFlagUncompressed)) == 0)
388 test.Printf(_L("sbcpexp,3\n"));
391 // 5. If the Paging Policy is ALWAYSPAGE then the executable is Paged.
392 else if (policy == EKernelConfigCodePagingPolicyAlwaysPage)
394 test.Printf(_L("sbcpexp,4\n"));
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)
402 test.Printf(_L("sbcpexp,5\n"));
405 else if ((flags & KModuleFlagUnpagedCode) != 0)
407 test.Printf(_L("sbcpexp,6\n"));
410 // 7. Otherwise the PagingPolicy (DEFAULTPAGED or DEFAULTUNPAGED) determines
411 // how the executable is treated
414 test.Printf(_L("sbcpexp,7\n"));
415 expected = (policy == EKernelConfigCodePagingPolicyDefaultPaged);
418 test(expected == isCodePaged);
420 if ((flags & KModuleFlagXIP) && mmtype!=EMemModelTypeEmul)
421 test(IsRomAddress(aInfo.iEntryPointAddress));
424 test(IsRamCodeAddress(aInfo.iEntryPointAddress));
425 if(mmtype==EMemModelTypeFlexible)
427 // can't make assumtions about current processes address space
429 else if (mmtype==EMemModelTypeMultiple)
431 test(!AddressReadable(aInfo.iEntryPointAddress));
435 test(AddressReadable(aInfo.iEntryPointAddress));
439 if (total_data_size!=0)
440 test(CheckDataAddress(info.iDataRunAddress, aInfo.iDllNum, aExeNum));
443 void LoaderTest::DumpModuleList(const TModuleList& aList, TInt aExeNum)
446 for (i=0; i<aList.iCount; ++i)
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);
455 void LoaderTest::CheckModuleList(TInt aRoot, const TModuleList& aList)
457 const TInt* deps=ModuleDependencies[aRoot];
461 for (i=0; i<ndeps; ++i)
464 f|=GetModuleFlags(m);
466 if (!(f&KModuleFlagDllInCycle))
468 i=0; // indexes aList
469 TInt j=0; // indexes deps
474 if (!(GetModuleFlags(deps[j])&KModuleFlagExe))
476 test(aList.iInfo[i].iDllNum==deps[j]);
483 test(aList.iInfo[i].iDllNum==aRoot);
489 test(aList.iInfo[i].iDllNum<0);
496 TBool root_included=EFalse;
497 for (i=0; i<ndeps; ++i)
501 if (!(GetModuleFlags(deps[i])&KModuleFlagExe))
507 for (i=0; i<KNumModules; ++i)
511 test(aList.iInfo[i].iDllNum>=0);
512 ml.Remove(aList.iInfo[i].iDllNum);
514 else if (i==nd && !root_included)
515 test(aList.iInfo[i].iDllNum==aRoot);
517 test(aList.iInfo[i].iDllNum<0);
522 LoaderTest::LoaderTest()
524 Mem::Fill(iCmdLine, sizeof(iCmdLine), 0xff);
525 iMemModelAtt=(TUint32)UserSvr::HalFunction(EHalGroupKernel, EKernelHalMemModelInfo, NULL, NULL);
526 test.Printf(_L("MemModelAttributes=%08x\n"),iMemModelAtt);
529 LoaderTest::~LoaderTest()
535 void LoaderTest::Init()
537 test.Next(_L("Load device driver"));
538 TInt r=User::LoadLogicalDevice(_L("D_LDRTST"));
539 test(r==KErrNone || r==KErrAlreadyExists);
546 User::CommandLine(cmdline);
554 lex.Val(iCmdLine[i]);
558 LoaderTest* LoaderTest::New()
560 LoaderTest* p=new LoaderTest;
566 void LoaderTest::Close()
571 void LoaderTest::TraceOn()
573 iFs.SetDebugRegister(KFLDR);
574 User::SetDebugMask(0xefdfffff);
577 void LoaderTest::TraceOff()
579 iFs.SetDebugRegister(0);
580 User::SetDebugMask(0x80000000);
583 void LoaderTest::TestOneByOne()
585 test.Next(_L("Test all single EXE/DLL combinations"));
589 for (x=0; x<KNumModules; ++x)
591 if (!(GetModuleFlags(x)&KModuleFlagExe))
594 if (GetModuleFlags(x)&KModuleFlagTargetOnly)
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);
605 test.Printf(_L("Connect(%d)->%d\n"),x,r);
607 TModuleList exe_info;
608 r=lt.GetExeDepList(exe_info.iInfo);
611 DumpModuleList(exe_info, x);
612 CheckModuleList(x, exe_info);
615 for (m=0; m<KNumModules; ++m)
617 if (GetModuleFlags(m)&KModuleFlagExe)
620 if (GetModuleFlags(m)&KModuleFlagTargetOnly)
624 if ((GetModuleFlags(m) & KModuleFlagVDrive) && NoRemovable)
626 test.Printf(_L("LoadDll: Not testing dll %d from removable media\n"),m);
629 TInt predicted=DetermineDllLoadResult(m,x);
630 if (x==iCmdLine[1] && m==iCmdLine[2])
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);
639 test(Min(h,0)==predicted);
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))
650 for (i=0; i<dll_init_info.iCount; ++i)
652 TInt modnum=dll_init_info.iInfo[i].iDllNum;
653 if ((GetModuleFlags(modnum)&KModuleFlagData) && !exe_info.IsPresent(modnum))
655 test(modnum==dll_c_info.iInfo[j].iDllNum);
659 test(j==dll_c_info.iCount);
663 TModuleSet ms(dll_init_info, KModuleFlagData, KModuleFlagData);
665 test(ms.iCount==dll_c_info.iCount);
666 ms.Remove(dll_c_info);
673 test.Printf(_L("DLL %d RBlkI->%d\n"),m,r);
674 y=ModuleRBlkIParams[m][1]+ModuleRBlkIParams[m][0]*DLLNUMOFFSET;
677 test.Printf(_L("CloseDll(%d)->%d\n"),h,r);
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);
686 if (x==iCmdLine[1] && m==iCmdLine[2])
694 // return KErrNone if shared code, 1 if not shared
695 TInt LoaderTest::DetermineLoadExe2Result(TInt aExeNum)
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))
705 return KErrNone; // fixed but no data, so share code segment
707 return 1; // on emulator, never share EXE code segments
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;
716 if (f & KModuleFlagExports)
717 return KErrAlreadyExists;
718 if (!(f & KModuleFlagData))
724 void LoaderTest::TestMultipleExeInstances()
726 test.Next(_L("Test multiple instantiation of EXEs"));
730 for (x=0; x<KNumModules; ++x)
732 TUint32 f=GetModuleFlags(x);
733 if (!(f&KModuleFlagExe))
736 if (f&KModuleFlagTargetOnly)
740 RLoaderTest lt1, lt2;
741 TModuleList exe_info1;
742 TModuleList exe_info2;
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);
749 test.Printf(_L("Connect1(%d)->%d\n"),x,r);
751 TInt s=DetermineLoadExe2Result(x);
752 r=LoadExe(x, 1, p2, tt);
753 test.Printf(_L("LoadExe2(%d)->%d (%d)\n"),x,r,s);
755 test.Printf(_L("BENCHMARK: LoadExe2(%d)->%dms\n"),x,tt);
761 test.Printf(_L("Connect2(%d)->%d\n"),x,r);
763 r=lt1.GetExeDepList(exe_info1.iInfo);
765 exe_info1.SetCount();
766 DumpModuleList(exe_info1, x);
767 r=lt2.GetExeDepList(exe_info2.iInfo);
769 exe_info2.SetCount();
770 DumpModuleList(exe_info2, x);
772 test(exe_info1.iCount==exe_info2.iCount);
775 TInt nm=exe_info1.iCount;
776 test(exe_info1.iInfo[nm-1].iModuleHandle!=exe_info2.iInfo[nm-1].iModuleHandle);
779 else if((GetModuleFlags(x) & KModuleFlagData))
784 for (i=0; i<exe_info1.iCount; ++i)
785 test(exe_info1.iInfo[i].iModuleHandle==exe_info2.iInfo[i].iModuleHandle);
788 const TInt* tests=TC_ExeLoad;
789 TInt ntests=*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);
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: "));
810 r=lt1.CallRBlkI(h1,y);
813 test.Printf(_L("DLL1 %d RBlkI->%d\n"),m,r);
814 y=ModuleRBlkIParams[m][1]+ModuleRBlkIParams[m][0]*DLLNUMOFFSET;
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);
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: "));
830 r=lt2.CallRBlkI(h2,y);
833 test.Printf(_L("DLL2 %d RBlkI->%d\n"),m,r);
834 y=ModuleRBlkIParams[m][1]+ModuleRBlkIParams[m][0]*DLLNUMOFFSET;
837 test(dll_init_info1.iCount==dll_init_info2.iCount);
839 if (s==1 && !(ModuleFlags[m]&KModuleFlagDataInTree))
844 TInt nm=dll_init_info1.iCount;
845 test(dll_init_info1.iInfo[nm-1].iModuleHandle!=dll_init_info2.iInfo[nm-1].iModuleHandle);
849 for (i=0; i<dll_init_info1.iCount; ++i)
850 test(dll_init_info1.iInfo[i].iModuleHandle==dll_init_info2.iInfo[i].iModuleHandle);
854 test.Printf(_L("CloseDll2(%d)->%d\n"),h2,r);
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);
865 test.Printf(_L("CloseDll1(%d)->%d\n"),h1,r);
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);
884 void SetLoaderFail(TInt aLdr, TInt aKern)
886 test.Printf(_L("ldr=%d, kern=%d\n"),aLdr,aKern);
888 test(l.Connect()==KErrNone);
889 test(l.DebugFunction(ELoaderDebug_SetHeapFail, aLdr, aKern, 0)==KErrNone);
893 void SetLoaderFailRFs(TInt aError, TInt aCount)
895 test.Printf(_L("SetLoaderFailRFs: error=%d, count=%d\n"),aError,aCount);
897 test(l.Connect()==KErrNone);
898 test(l.DebugFunction(ELoaderDebug_SetRFsFail, aError, aCount, 0)==KErrNone);
905 enum OomState{EInit, EKernelHeap, EUserHeap, ERFsError};
909 TBool Iterate(TInt aResult);
922 void TLoopOOM::Reset()
930 TBool TLoopOOM::Iterate(TInt aResult)
932 TBool noErrors = (aResult==KErrNone||aResult==KErrNotSupported);
934 test.Printf(_L("%d %d %d %d\n"), iKern,iLdr,iRFsCount,aResult);
940 iState = EKernelHeap;
941 SetLoaderFail(iLdr,++iKern);
954 SetLoaderFail(iLdr,iKern);
963 SetLoaderFailRFs(KRFsError, ++iRFsCount);
966 SetLoaderFail(++iLdr,iKern);
974 SetLoaderFailRFs(KRFsError, ++iRFsCount);
979 SetLoaderFailRFs(KErrNone, 0);
983 void LoaderTest::TestOOM()
985 test.Next(_L("Test OOM Handling"));
990 for (x=0; x<KNumModules; ++x)
992 if (!(GetModuleFlags(x)&KModuleFlagExe))
995 if (GetModuleFlags(x)&KModuleFlagTargetOnly)
999 if ((GetModuleFlags(x) & KModuleFlagVDrive) && NoRemovable)
1001 test.Printf(_L("LoaderTest::TestOOM Not testing dll %d from removable media\n"),x);
1009 while(loom.Iterate(r))
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));
1017 TInt s=lt.Connect(x);
1018 test.Printf(_L("Connect(%d)->%d\n"),x,s);
1025 r=LoadExe(x, 0, p, tt);
1029 const TInt* tests=TC_DllOOM;
1030 TInt ntests=*tests++;
1035 if ((GetModuleFlags(m) & KModuleFlagVDrive) && NoRemovable)
1037 test.Printf(_L("LoaderTest::TestOOM Not testing dll %d from removable media\n"),m);
1042 while(loom.Iterate(r))
1044 TInt h=lt.LoadDll(m, list.iInfo);
1046 test.Printf(_L("%d:LoadDll(%d)->%d\n"),x,m,h);
1048 test(r==KErrNone || r==KErrNotSupported || KErrNoMemory ||
1049 (loom.iState==TLoopOOM::ERFsError && r==KRFsError) );
1053 TInt s=lt.CloseDll(h);
1064 test.Printf(_L("Only on DEBUG builds\n"));
1068 class RLoaderTestHandle : public RSessionBase
1072 void TryToGetPaniced();
1075 TInt RLoaderTestHandle::Connect()
1077 return CreateSession(_L("!Loader"),TVersion(KLoaderMajorVersionNumber,KLoaderMinorVersionNumber,KE32BuildVersionNumber));
1080 void RLoaderTestHandle::TryToGetPaniced()
1084 TPckg<TLdrInfo> infoBuf(info);
1086 args.Set(0,(TDes8*)&infoBuf);
1089 SendReceive(ELoadLibrary, args);
1092 TInt PanicTestThread(TAny*)
1094 RLoaderTestHandle t;
1095 TInt r = t.Connect();
1096 if (r==KErrNone) t.TryToGetPaniced();
1101 void TestCorruptedFiles()
1103 test.Next(_L("Test corrupted files"));
1105 TInt numCorruptFiles=0;
1107 for (TInt x=0; x<KNumModules; ++x)
1109 if (!(GetModuleFlags(x)&KModuleFlagExe))
1112 const TPtrC fn = MODULE_FILENAME(x);
1116 if (++numCorruptFiles > KNumberOfCorruptFiles)
1121 r=LoadExe(x, 0, p, tt);
1122 test.Printf(_L("LoadCorruptExe(%d)->%d\n"),x,r);
1123 test(r==KErrCorrupt);
1127 // -------- copying files to non-ROM media --------
1129 static void GetSpecialDrives()
1131 Work out which physical drive corresponds to each
1132 numeric drive in the list of filenames. This populates
1138 test.Printf(_L("NoRemovable=%d\n"),NoRemovable);
1140 // mark each special drive as not present
1141 for (TInt i = 0; i < KSpecialDriveCount; ++i)
1143 SpecialDrives[i] = '!';
1146 // cannot load binaries from emulated removable drives
1147 #if defined (__WINS__)
1148 SpecialDrives[1] = 'c'; // "removable"
1153 hashDir[0] = (TUint8) RFs::GetSystemDriveChar();
1155 TInt r = Fs.MkDirAll(hashDir);
1156 test(r == KErrNone || r == KErrAlreadyExists);
1158 for (TInt d = 0; d <= (TInt)sizeof(SpecialDriveList); ++d)
1160 TInt dr = SpecialDriveList[d];
1162 test.Printf(_L("Drive %d\n"), dr);
1163 test(Fs.Drive(di, dr) == KErrNone);
1164 if (di.iType == EMediaNotPresent)
1168 test(RFs::DriveToChar(dr, ch0) == KErrNone);
1170 TText ch = static_cast<TText>(TUint(ch0));
1172 // drive 0 == internal
1173 if ((di.iDriveAtt & KDriveAttInternal) && SpecialDrives[0] == '!')
1175 SpecialDrives[0] = ch;
1177 SpecialDrives[1] = ch;
1179 // drive 1 == removable
1180 else if ((di.iDriveAtt & KDriveAttRemovable) && SpecialDrives[1] == '!' && !NoRemovable)
1181 SpecialDrives[1] = ch;
1184 // drive not useful so continue and don't create \sys\bin
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);
1197 void GetNonZFileName(const TDesC& aOrigName, TDes& aNonZName)
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.
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".
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);
1217 static void GetHashFileName(const TDesC& aOrigName, TDes& aHashName)
1219 Get name of the hash file used for an EXE or DLL which has been
1220 copied to writable media.
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
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
1232 aHashName.Copy(KSysHash);
1233 aHashName[0] = (TUint8) RFs::GetSystemDriveChar();
1234 const TParsePtrC ppc(aOrigName);
1235 aHashName.Append(ppc.NameAndExt());
1238 static void CopyExecutablesL(TBool aCorruptMode=EFalse)
1240 Make a copy of each executable that should be copied
1241 to a writable drive.
1243 If aCorruptMode make KNumberOfCorruptFiles corrupted copies: truncated file and a file with corrupted header
1248 TInt numCorruptFiles = 0;
1252 CFileMan* fm = CFileMan::NewL(Fs);
1254 for (TInt i = 0; i < KNumModules; ++i)
1256 if (aCorruptMode && numCorruptFiles==KNumberOfCorruptFiles)
1259 if (aCorruptMode && !(GetModuleFlags(i)&KModuleFlagExe))
1262 const TPtrC fn = MODULE_FILENAME(i);
1264 // if this is an absolute filename then copy it to
1265 // the appropriate drive.
1270 GetNonZFileName(fn, fnDest);
1273 TFileName fnSrc(fn);
1276 test.Printf(_L("CopyExecutables;%S,%S\n"), &fnSrc, &fnDest);
1279 const TParsePtrC sppc(fnSrc);
1280 TBuf<MAX_PATH> sName;
1281 r = MapEmulatedFileName(sName, sppc.NameAndExt());
1282 test(r == KErrNone);
1284 TBuf<MAX_PATH> dName;
1285 r = MapEmulatedFileName(dName, fnDest);
1286 test(r == KErrNone);
1288 BOOL b = Emulator::CopyFile((LPCTSTR)sName.PtrZ(),(LPCTSTR)dName.PtrZ(),FALSE);
1291 r = fm->Copy(fnSrc, fnDest);
1292 test(r == KErrNone);
1295 r = Fs.SetAtt(fnDest, 0, KEntryAttReadOnly);
1296 test.Printf(_L("CopyExecutables:setatt=%d\n"), r);
1297 User::LeaveIfError(r);
1300 TInt moduleFlags = GetModuleFlags(i);
1302 // modify the new destination file by applying the required paging flags
1304 r = fNp.Open(Fs, fnDest, EFileWrite | EFileStream);
1305 User::LeaveIfError(r);
1306 CleanupClosePushL(fNp);
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);
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);
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);
1333 // corrupt header of the 2nd file
1334 if (aCorruptMode && numCorruptFiles==1 && (moduleFlags&KModuleFlagExe))
1336 hdr2->iCodeBase += 3;
1337 hdr2->iDataBase += 1;
1338 hdr2->iImportOffset += 1;
1339 hdr2->iCodeRelocOffset += 3;
1340 hdr2->iDataRelocOffset += 3;
1345 // recalculate the checksum
1346 hdr2->iHeaderCrc = KImageCrcInitialiser;
1348 Mem::Crc32(crc, startBytes.Ptr(), totalSize);
1349 hdr2->iHeaderCrc = crc;
1350 r = fNp.Write(0, startBytes);
1351 User::LeaveIfError(r);
1353 // truncate 1st corrupted file
1354 if (aCorruptMode && numCorruptFiles==0 && (moduleFlags&KModuleFlagExe))
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);
1365 CleanupStack::PopAndDestroy(2, &fNp); // startBytes0, fNp
1368 // if copied to removable media, then generate hash
1372 CSHA1* sha1 = CSHA1::NewL();
1373 CleanupStack::PushL(sha1);
1376 r = fDest.Open(Fs, fnDest, EFileRead | EFileStream);
1377 User::LeaveIfError(r);
1378 CleanupClosePushL(fDest);
1384 r = fDest.Read(content);
1385 User::LeaveIfError(r);
1386 done = (content.Length() == 0);
1388 sha1->Update(content);
1390 CleanupStack::PopAndDestroy(&fDest);
1392 // write hash to \sys\hash
1393 TBuf8<SHA1_HASH> hashVal = sha1->Final();
1395 // reuse fnSrc to save stack space
1396 GetHashFileName(fnDest, fnSrc);
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);
1405 CleanupStack::PopAndDestroy(2, sha1);
1411 static void DeleteExecutables(TBool aCorruptMode=EFalse)
1413 Delete any executables which were created by CopyExecutables.
1414 This function is defined so the test cleans up when it has finished.
1417 TInt numCorruptFiles = 0;
1419 for (TInt i = 0; i < KNumModules; ++i)
1421 if (aCorruptMode && numCorruptFiles==KNumberOfCorruptFiles)
1424 if (aCorruptMode && !(GetModuleFlags(i)&KModuleFlagExe))
1427 const TPtrC fn = MODULE_FILENAME(i);
1429 // if this is an absolute filename then copy it to
1430 // the appropriate drive.
1434 test.Printf(_L("DeleteExecutables:fn=%S\n"), &fn);
1436 GetNonZFileName(fn, fnDest);
1440 r = Fs.Delete(fnDest);
1441 test.Printf(_L("DeleteExecutables:fnDest=%S,del=%d\n"), &fnDest, r);
1442 test(r == KErrNone);
1444 // only need to delete hash files for binaries copied to removable media,
1445 // but simpler to delete and test for KErrNotFound
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);
1457 GLDEF_C TInt E32Main()
1459 RThread().SetPriority(EPriorityLess);
1462 test.Start(_L("Setup"));
1465 test(l.Connect()==KErrNone);
1466 test(l.CancelLazyDllUnload()==KErrNone);
1469 test(TestLdd.Open()==KErrNone);
1470 LoaderTest* pL=LoaderTest::New();
1473 TInt tm=pL->iCmdLine[0];
1474 TInt nr = (tm>>4)&3;
1476 NoRemovable = ETrue;
1478 NoRemovable = EFalse;
1480 test(Fs.Connect() == KErrNone);
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);
1492 pL->TestMultipleExeInstances();
1496 pL->TestMultipleLoads();
1500 // Test loader error handling - will panic the client thread
1501 test.Next(_L("Test loader error handling - will panic the client thread"));
1503 t.Create(_L("Loader panic test"),PanicTestThread,KDefaultStackSize,0x1000,0x1000,NULL);
1506 TBool justInTime=User::JustInTime();
1507 User::SetJustInTime(EFalse);
1509 User::WaitForRequest(s);
1510 test(t.ExitType()==EExitPanic);
1511 test(t.ExitCategory().Compare(_L("LOADER"))==0);
1512 test(t.ExitReason()==0);
1514 User::SetJustInTime(justInTime);
1516 DeleteExecutables();
1519 // test corrupted files
1520 cleanup=CTrapCleanup::New();
1521 test.Next(_L("CopyExecutablesL(ETrue)"));
1522 TRAPD(rr, CopyExecutablesL(ETrue));
1523 test(rr == KErrNone);
1525 test.Next(_L("TestCorruptedFiles()"));
1526 TestCorruptedFiles();
1527 test.Next(_L("DeleteExecutables()"));
1528 DeleteExecutables(ETrue);