author | mikek |
Sun, 27 Jun 2010 21:43:55 +0100 | |
branch | GCC_SURGE |
changeset 181 | bd8f1e65581b |
parent 0 | a41df078684a |
permissions | -rw-r--r-- |
// 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; }