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