--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/kerneltest/f32test/loader/t_ldrtst2.cpp Mon Oct 19 15:55:17 2009 +0100
@@ -0,0 +1,558 @@
+// Copyright (c) 1999-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+// f32test\loader\t_ldrtst2.cpp
+//
+//
+
+#include "t_ldrtst.h"
+
+extern TInt GetModuleFlags(TInt);
+
+inline TBool AlwaysLoaded(TInt aModule)
+ {
+#ifdef __EPOC32__
+ TUint32 f=GetModuleFlags(aModule);
+ return ( (f&(KModuleFlagExe|KModuleFlagDataInTree|KModuleFlagXIP)) == (TUint32)KModuleFlagXIP );
+#else
+ TUint32 f=GetModuleFlags(aModule);
+ return ( (f&(KModuleFlagExe|KModuleFlagDataInTree)) == 0 );
+#endif
+ }
+
+TInt Order(const SModuleInstance& m1, const SModuleInstance& m2)
+ {
+ return TInt(m1.iCodeSeg)-TInt(m2.iCodeSeg);
+ }
+
+CGlobalModuleList::CGlobalModuleList()
+ : iModules(KNumModules)
+ {
+ }
+
+CGlobalModuleList::~CGlobalModuleList()
+ {
+ iModules.Close();
+ User::Free(iModuleAlloc);
+ TInt i;
+ for (i=0; i<KNumModules; ++i)
+ {
+ delete iPPInfo[i];
+ }
+ }
+
+void CGlobalModuleList::Init()
+ {
+ TBool proc_sym=(iMemModelAtt & (EMemModelAttrSameVA|EMemModelAttrSupportFixed))==EMemModelAttrSameVA;
+ TInt i;
+ for (i=0; i<KNumModules; ++i)
+ {
+ TUint32 f=GetModuleFlags(i);
+ if (f&KModuleFlagExe)
+ {
+ ++iNumExes;
+ if (!proc_sym && (f&KModuleFlagFixed))
+ ++iFixedExes;
+ }
+ }
+ iMaxModules=(1+iFixedExes)*(KNumModules-iNumExes)+iNumExes;
+ test.Printf(_L("iNumExes=%d iFixedExes=%d iMaxModules=%d\n"),iNumExes,iFixedExes,iMaxModules);
+ SModuleInstance* mi=(SModuleInstance*)User::Alloc(iMaxModules*sizeof(SModuleInstance));
+ test(mi!=NULL);
+ iFreeModules=mi;
+ iModuleAlloc=mi;
+ SModuleInstance* miE=mi+iMaxModules;
+ for (; mi<miE; ++mi)
+ {
+ SModuleInstance* miN=mi+1;
+ mi->iCodeSeg=(miN<miE)?miN:NULL;
+ }
+ for (i=0; i<KNumModules; ++i)
+ {
+ TUint32 f=GetModuleFlags(i);
+ if (f&KModuleFlagExe)
+ {
+ CPerProcessInfo* p=CPerProcessInfo::New(i,*this);
+ iPPInfo[i]=p;
+ }
+ }
+ }
+
+CGlobalModuleList* CGlobalModuleList::New(const LoaderTest& a)
+ {
+ CGlobalModuleList* p=new CGlobalModuleList;
+ test(p!=NULL);
+ test.Printf(_L("CGlobalModuleList at %08x\n"),p);
+ p->iDev=a.iDev;
+ p->iMemModelAtt=a.iMemModelAtt;
+ p->Init();
+ return p;
+ }
+
+void CGlobalModuleList::Free(SModuleInstance* a)
+ {
+ a->iCodeSeg=iFreeModules;
+ iFreeModules=a;
+ }
+
+SModuleInstance* CGlobalModuleList::GetMI()
+ {
+ SModuleInstance* p=iFreeModules;
+ test(p!=NULL);
+ iFreeModules=(SModuleInstance*)p->iCodeSeg;
+ return p;
+ }
+
+TAny* CGlobalModuleList::CodeSegFromHandle(TModuleHandle aModHandle)
+ {
+ return iDev.ModuleCodeSeg(aModHandle);
+ }
+
+void CGlobalModuleList::Close(SModuleInstance* a)
+ {
+ test.Printf(_L("Module %d@%08x Close(%d)\n"),a->iModNum,a->iCodeSeg,a->iAccessCount);
+ if (!--a->iAccessCount)
+ {
+ TCodeSegCreateInfo codeSeg;
+ TInt r=iDev.GetCodeSegInfo(a->iCodeSeg, codeSeg);
+ test(r==KErrArgument);
+ r=iModules.FindInOrder(a, Order);
+ test(r>=0);
+ iModules.Remove(r);
+ Free(a);
+ }
+ }
+
+
+void CGlobalModuleList::CheckAll()
+ {
+ TInt i;
+ for (i=0; i<KNumModules; ++i)
+ {
+ if (iPPInfo[i])
+ iPPInfo[i]->Check();
+ }
+ }
+
+TInt CGlobalModuleList::Load(TInt aExeNum, TInt aDllNum)
+ {
+ return iPPInfo[aExeNum]->Load(aDllNum);
+ }
+
+TInt CGlobalModuleList::CloseHandle(TInt aExeNum, TInt aDllNum)
+ {
+ CPerProcessInfo* p=iPPInfo[aExeNum];
+ TInt i;
+ for (i=0; i<KMaxHandles && p->iModuleNum[i]!=aDllNum; ++i) {}
+ if (i==KMaxHandles)
+ return KErrNotFound;
+ return p->CloseHandle(i);
+ }
+
+CPerProcessInfo::CPerProcessInfo()
+ {
+ Mem::Fill(iModuleNum, sizeof(iModuleNum), 0xff);
+ }
+
+CPerProcessInfo::~CPerProcessInfo()
+ {
+ if (iSession.Handle())
+ {
+ iSession.Exit();
+ iSession.Close();
+ User::WaitForRequest(iStatus);
+ test(iProcess.ExitType()==EExitKill);
+ test(iProcess.ExitReason()==KErrNone);
+ }
+ iProcess.Close();
+ }
+
+CPerProcessInfo* CPerProcessInfo::New(TInt aExeNum, CGlobalModuleList& aG)
+ {
+ CPerProcessInfo* p=new CPerProcessInfo;
+ test(p!=NULL);
+ test.Printf(_L("CPerProcessInfo for %d at %08x\n"),aExeNum,p);
+ p->iExeNum=aExeNum;
+ p->iDev=aG.iDev;
+ p->iGlobalList=&aG;
+ TInt r = p->Init();
+ if (r==KErrNone)
+ return p;
+ delete p;
+ return NULL;
+ }
+
+TInt CPerProcessInfo::Init()
+ {
+ TUint32 tt;
+ TInt r=LoadExe(iExeNum, 0, iProcess, tt);
+ test.Printf(_L("LoadExe(%d)->%d\n"),iExeNum,r);
+#ifdef __EPOC32__
+ test(r==KErrNone);
+ test.Printf(_L("BENCHMARK: LoadExe(%d)->%dms\n"),iExeNum,tt);
+#else
+ test(r==KErrNone || r==KErrNotSupported);
+ if (r!=KErrNone)
+ return r;
+#endif
+ iProcess.Logon(iStatus);
+ test(iStatus==KRequestPending);
+ r=iSession.Connect(iExeNum);
+ test.Printf(_L("Connect(%d)->%d\n"),iExeNum,r);
+ test(r==KErrNone);
+ TModuleList exe_info;
+ r=iSession.GetExeDepList(exe_info.iInfo);
+ exe_info.SetCount();
+ test.Printf(_L("GetExeDepList(%d)->%d count %d\n"),iExeNum,r,exe_info.iCount);
+ test(r==KErrNone);
+ r=AddModules(iExeNum, NULL, &exe_info);
+ test.Printf(_L("AddModules->%d\n"),r);
+ test(r==KErrNone);
+ return KErrNone;
+ }
+
+void CPerProcessInfo::GetModuleSet(TModuleSet& aSet)
+ {
+ TInt m;
+ for (m=0; m<KNumModules; ++m)
+ {
+ if (iHandleCount[m]==0 && m!=iExeNum)
+ continue;
+ aSet.Add(m);
+ const TInt* deps=ModuleDependencies[m];
+ TInt ndeps=*deps++;
+ TInt i;
+ for (i=0; i<ndeps; ++i)
+ {
+ TInt dm=*deps++;
+#ifndef __EPOC32__
+ // Emulator doesn't register subtrees without data
+ TInt f = GetModuleFlags(dm);
+ if (f & KModuleFlagDataInTree)
+#endif
+ aSet.Add(dm);
+ }
+ }
+ }
+
+void CPerProcessInfo::Check()
+ {
+ test.Printf(_L("%d:Check\n"),iExeNum);
+ TBool code_prot=iGlobalList->iMemModelAtt&EMemModelAttrRamCodeProt;
+ TBool data_prot=iGlobalList->iMemModelAtt&EMemModelAttrProcessProt;
+ TInt mmtype=iGlobalList->iMemModelAtt&EMemModelTypeMask;
+ TModuleSet set;
+ GetModuleSet(set);
+ TInt m;
+ for (m=0; m<KNumModules; ++m)
+ {
+ TUint32 f=GetModuleFlags(m);
+ if (set.Present(m))
+ {
+ test.Printf(_L("%d "),m);
+ SModuleInstance* pM=iModules[m];
+ test(pM!=NULL);
+ test(iSession.CheckReadable(pM->iEntryPointAddress)==KErrNone);
+ if (f&KModuleFlagData)
+ test(iSession.CheckReadable(pM->iData)==KErrNone);
+ }
+ else
+ {
+ SModuleInstance* pM=iModules[m];
+ test(pM==NULL);
+ }
+ }
+ TInt ix;
+ TInt c=iGlobalList->iModules.Count();
+ test.Printf(_L("\n%d:CheckNP\n"),iExeNum);
+ for (ix=0; ix<c; ++ix)
+ {
+ const SModuleInstance* pM=iGlobalList->iModules[ix];
+ if (set.Present(pM->iModNum))
+ continue;
+ test.Printf(_L("%d "),pM->iModNum);
+ TUint32 f=GetModuleFlags(pM->iModNum);
+ if (!(f&KModuleFlagXIP) && code_prot)
+ {
+ if(mmtype==EMemModelTypeFlexible && (f&KModuleFlagExe))
+ {
+ // don't test EXEs on FlexibleMM because they don't live at unique addresses
+ }
+ else
+ {
+ // check code not loaded into this porcess....
+ test(iSession.CheckReadable(pM->iEntryPointAddress)==KErrGeneral);
+ }
+ }
+ TBool check_data=(f&(KModuleFlagData|KModuleFlagExe))==(TUint32)KModuleFlagData;
+ if (check_data && mmtype==EMemModelTypeMoving)
+ {
+ if (f&KModuleFlagXIP)
+ {
+ const TInt* exeinfo=ModuleExeInfo[pM->iModNum];
+ TInt attp=exeinfo[0];
+ if (attp>=0 && (GetModuleFlags(attp)&KModuleFlagFixed))
+ check_data=EFalse;
+ }
+ }
+ if (check_data && data_prot)
+ test(iSession.CheckReadable(pM->iData)==KErrGeneral);
+ }
+ TInt h;
+ for (h=0; h<KMaxHandles; ++h)
+ {
+ m=iModuleNum[h];
+ if (m<0)
+ continue;
+ test(set.Present(m));
+ TInt y=++iGlobalList->iParam;
+ TInt r=iSession.CallRBlkI(h,y);
+ r-=y;
+ r/=INC_BLOCK_SZ;
+ test.Printf(_L("DLL %d RBlkI->%d\n"),m,r);
+ y=ModuleRBlkIParams[m][1]+ModuleRBlkIParams[m][0]*DLLNUMOFFSET;
+ test(r==y);
+ }
+ }
+
+void CPerProcessInfo::Unlink(const SDllInfo& a, TModuleList& aList)
+ {
+ test.Printf(_L("%d:Unlink %d %08x\n"),iExeNum,a.iDllNum,a.iModuleHandle);
+ test(iHandleCount[a.iDllNum]==0);
+ TBool code_prot=iGlobalList->iMemModelAtt&EMemModelAttrRamCodeProt;
+ TBool data_prot=iGlobalList->iMemModelAtt&EMemModelAttrProcessProt;
+ TInt mmtype=iGlobalList->iMemModelAtt&EMemModelTypeMask;
+ TModuleSet set;
+ GetModuleSet(set);
+ set.Display(_L("set: "));
+ TInt m;
+ for (m=0; m<KNumModules; ++m)
+ {
+ if (set.Present(m))
+ continue;
+ SModuleInstance* pM=iModules[m];
+ if (!pM)
+ continue;
+ iModules[m]=NULL;
+ TUint32 f=GetModuleFlags(m);
+ SDllInfo info;
+ info.iDllNum=m;
+ info.iEntryPointAddress=pM->iEntryPointAddress;
+ info.iModuleHandle=pM->iModuleHandle;
+ aList.Add(info);
+ test(pM->iModNum==m);
+ if (!(f&KModuleFlagXIP) && code_prot)
+ test(iSession.CheckReadable(pM->iEntryPointAddress)==KErrGeneral);
+ TBool check_data=f&KModuleFlagData;
+ if (check_data && mmtype==EMemModelTypeMoving)
+ {
+ if (f&KModuleFlagXIP)
+ {
+ const TInt* exeinfo=ModuleExeInfo[pM->iModNum];
+ TInt attp=exeinfo[0];
+ if (attp>=0 && (GetModuleFlags(attp)&KModuleFlagFixed))
+ check_data=EFalse;
+ }
+ }
+ if (check_data && data_prot)
+ test(iSession.CheckReadable(pM->iData)==KErrGeneral);
+ iGlobalList->Close(pM);
+ }
+ }
+
+TInt CPerProcessInfo::CloseHandle(TInt aHandle)
+ {
+ TInt m=iModuleNum[aHandle];
+ test(m>=0);
+ iModuleNum[aHandle]=-1;
+ SModuleInstance* pM=iModules[m];
+ test(pM!=NULL);
+ SDllInfo dll_info;
+ dll_info.iDllNum=m;
+ dll_info.iEntryPointAddress=pM->iEntryPointAddress;
+ dll_info.iModuleHandle=pM->iModuleHandle;
+ TModuleList d_list;
+ TInt r=iSession.CloseDll(aHandle);
+ test(r==KErrNone);
+ r=iSession.GetCDList(d_list.iInfo);
+ test(r==KErrNone);
+ d_list.SetCount();
+ if (--iHandleCount[m])
+ {
+ test(d_list.iCount==0);
+ return KErrNone;
+ }
+ TModuleList xd_list;
+ if (!AlwaysLoaded(m))
+ Unlink(dll_info, xd_list);
+ TInt i;
+ TInt dcount=0;
+ for (i=0; i<xd_list.iCount; ++i)
+ {
+ TInt mn=xd_list.iInfo[i].iDllNum;
+ TUint32 f=GetModuleFlags(mn);
+ if (f&KModuleFlagData)
+ {
+ ++dcount;
+ test(d_list.IsPresent(mn));
+ }
+ }
+ d_list.Display(_L("d_list: "));
+ xd_list.Display(_L("xd_list: "));
+ test(dcount==d_list.iCount);
+ return KErrNone;
+ }
+
+TInt CPerProcessInfo::Load(TInt aDllNum)
+ {
+ TModuleList init_list;
+ TModuleList c_list;
+ TInt h=iSession.LoadDll(aDllNum, init_list.iInfo);
+ init_list.SetCount();
+ test.Printf(_L("%d:Load(%d)->%d Icount %d\n"),iExeNum,aDllNum,h,init_list.iCount);
+ if (h<0)
+ {
+ return h;
+ }
+ test(iSession.GetCDList(c_list.iInfo)==KErrNone);
+ c_list.SetCount();
+ iModuleNum[h]=aDllNum;
+ return AddModules(aDllNum, &c_list, &init_list);
+ }
+
+TInt CPerProcessInfo::AddModules(TInt aDllNum, TModuleList* aCList, TModuleList* aIList)
+ {
+ TInt r=0;
+ if (++iHandleCount[aDllNum]>1)
+ {
+ if (aCList)
+ test(aCList->iCount==0);
+ return KErrNone;
+ }
+ TModuleSet set;
+ if (!iModules[aDllNum] && !AlwaysLoaded(aDllNum))
+ set.Add(aDllNum);
+ const TInt* deps=ModuleDependencies[aDllNum];
+ TInt ndeps=*deps++;
+ TInt i;
+ TInt ccount=0;
+ for (i=0; i<ndeps; ++i)
+ {
+ TInt dm=*deps++;
+ if (!iModules[dm] && !AlwaysLoaded(dm))
+ {
+ set.Add(dm);
+ if (GetModuleFlags(dm)&KModuleFlagData)
+ ++ccount;
+ }
+ }
+ if (aCList)
+ test(ccount==aCList->iCount);
+ for (i=0; i<KNumModules; ++i)
+ {
+ if (!set.Present(i))
+ continue;
+ SModuleInstance mi;
+ mi.iAccessCount=1;
+ mi.iModNum=i;
+ if (GetModuleFlags(i)&KModuleFlagData)
+ {
+ if (aCList)
+ test(aCList->Find(i)>=0);
+ }
+ TInt j=aIList->Find(i);
+ test(j>=0);
+ mi.iEntryPointAddress=aIList->iInfo[j].iEntryPointAddress;
+ mi.iModuleHandle=aIList->iInfo[j].iModuleHandle;
+ mi.iCodeSeg=iGlobalList->CodeSegFromHandle(mi.iModuleHandle);
+ test(mi.iCodeSeg!=NULL);
+ if (GetModuleFlags(i)&KModuleFlagData)
+ {
+ TCodeSegCreateInfo cs_info;
+ r=iDev.GetCodeSegInfo(mi.iCodeSeg, cs_info);
+ test(r==KErrNone);
+ mi.iData=cs_info.iDataRunAddress;
+ }
+ else
+ {
+ mi.iData=0;
+ }
+
+ r=iGlobalList->iModules.FindInOrder(&mi, Order);
+ if (r>=0)
+ {
+ test.Printf(_L("Module %d@%08x already exists\n"),mi.iModNum,mi.iCodeSeg);
+ SModuleInstance& mi0=*iGlobalList->iModules[r];
+ ++mi0.iAccessCount;
+ test(mi.iEntryPointAddress==mi0.iEntryPointAddress);
+ test(mi.iModuleHandle==mi0.iModuleHandle);
+ test(mi.iData==mi0.iData);
+ test(mi.iModNum==mi0.iModNum);
+ iModules[i]=&mi0;
+ }
+ else
+ {
+ test.Printf(_L("Module %d@%08x new\n"),mi.iModNum,mi.iCodeSeg);
+ SModuleInstance* pM=iGlobalList->GetMI();
+ test(pM!=NULL);
+ *pM=mi;
+ iModules[i]=pM;
+ r=iGlobalList->iModules.InsertInOrder(pM, Order);
+ test(r==KErrNone);
+ }
+ }
+ return KErrNone;
+ }
+
+void LoaderTest::TestMultipleLoads()
+ {
+ CGlobalModuleList* p=CGlobalModuleList::New(*this);
+ p->CheckAll();
+
+#ifdef __WINS__
+ const TInt* multiLoad[] = {TC_MultLoad,0};
+#else
+ const TInt* multiLoad[] = {TC_MultLoad,TC_MultLoadTargetOnly,0};
+#endif
+ const TInt** multiLoadLists = multiLoad;
+ const TInt* tests;
+ while((tests=*multiLoadLists++)!=0)
+ {
+ TInt ntests=*tests++;
+ while(ntests>=4)
+ {
+ ntests-=4;
+ TInt exe1=*tests++;
+ TInt dll1=*tests++;
+ TInt exe2=*tests++;
+ TInt dll2=*tests++;
+ TUint32 xf1=GetModuleFlags(exe1);
+ TUint32 xf2=GetModuleFlags(exe2);
+ if (xf1&KModuleFlagExe)
+ {
+ TInt r=p->Load(exe1, dll1);
+ test.Printf(_L("%d:Load %d->%d"),exe1,dll1,r);
+ p->CheckAll();
+ }
+ if (xf2&KModuleFlagExe)
+ {
+ TInt r=p->CloseHandle(exe2, dll2);
+ test.Printf(_L("%d:Close %d->%d"),exe2,dll2,r);
+ p->CheckAll();
+ }
+ }
+ }
+
+ delete p;
+ }
+