sl@0: // Copyright (c) 1999-2009 Nokia Corporation and/or its subsidiary(-ies). sl@0: // All rights reserved. sl@0: // This component and the accompanying materials are made available sl@0: // under the terms of the License "Eclipse Public License v1.0" sl@0: // which accompanies this distribution, and is available sl@0: // at the URL "http://www.eclipse.org/legal/epl-v10.html". sl@0: // sl@0: // Initial Contributors: sl@0: // Nokia Corporation - initial contribution. sl@0: // sl@0: // Contributors: sl@0: // sl@0: // Description: sl@0: // f32test\loader\exet.cpp sl@0: // sl@0: // sl@0: sl@0: #define __INCLUDE_DEPENDENCY_GRAPH sl@0: sl@0: #include sl@0: #include "dllt.h" sl@0: #include "exetifc.h" sl@0: #include "dlltree.h" sl@0: #include sl@0: sl@0: #ifdef __VC32__ sl@0: #pragma warning(disable:4706) sl@0: #endif sl@0: sl@0: const TInt KMaxHandlesPerDll=4; sl@0: const TInt KMaxHandles=KMaxHandlesPerDll*KNumModules; sl@0: sl@0: extern "C" TInt _E32Startup(); sl@0: sl@0: extern "C" IMPORT_C void RegisterConstructorCall(TInt aDllNum); sl@0: extern "C" IMPORT_C void RegisterInitCall(TInt aDllNum); sl@0: extern "C" IMPORT_C void RegisterDestructorCall(TInt aDllNum); sl@0: sl@0: #define PANIC() ExeTPanic(__LINE__) sl@0: #define EXET_ASSERT(c) ((void)((c)||(PANIC(),0))) sl@0: sl@0: void ExeTPanic(TInt aLine) sl@0: { sl@0: User::Panic(_L("EXET"),aLine); sl@0: } sl@0: sl@0: /****************************************************************************** sl@0: * Class Definitions sl@0: ******************************************************************************/ sl@0: class CDllInfo; sl@0: class TDllList : public MDllList sl@0: { sl@0: public: sl@0: TDllList(); sl@0: virtual TBool IsPresent(const SDllInfo& aInfo); sl@0: virtual TInt Add(const SDllInfo& aInfo); sl@0: virtual void MoveToEnd(TInt aPos); sl@0: public: sl@0: TInt iCount; sl@0: SDllInfo iInfo[KNumModules]; sl@0: }; sl@0: sl@0: class CTestServer : public CServer2 sl@0: { sl@0: public: sl@0: CTestServer(); sl@0: virtual ~CTestServer(); sl@0: virtual CSession2* NewSessionL(const TVersion& aVersion, const RMessage2& aMessage) const; sl@0: virtual TInt RunError(TInt aError); sl@0: public: sl@0: CDllInfo* iInfo; sl@0: }; sl@0: sl@0: class CTestSession : public CSession2 sl@0: { sl@0: public: sl@0: virtual ~CTestSession(); sl@0: virtual void CreateL(); sl@0: virtual void ServiceL(const RMessage2& aMessage); sl@0: public: sl@0: TInt GetExeDepList(const RMessage2& aMessage); sl@0: TInt GetCDList(const RMessage2& aMessage); sl@0: TInt LoadDll(const RMessage2& aMessage); sl@0: TInt CloseDll(TInt aHandle); sl@0: TInt CallBlkI(TInt aHandle, TInt aIn); sl@0: TInt CallRBlkI(TInt aHandle, TInt aIn); sl@0: public: sl@0: CDllInfo* iInfo; sl@0: }; sl@0: sl@0: class CDllInfo : public CBase sl@0: { sl@0: public: sl@0: CDllInfo(); sl@0: virtual ~CDllInfo(); sl@0: TInt Create(); sl@0: TInt StoreHandle(TInt aHandle); sl@0: void RemoveHandle(TInt aIndex); sl@0: void SetupCDList(); sl@0: public: sl@0: void RegisterConstructorCall(TInt aDllNum); sl@0: void RegisterInitCall(TInt aDllNum); sl@0: void RegisterDestructorCall(TInt aDllNum); sl@0: public: sl@0: TInt iNextGen; sl@0: TInt iHandleCount; sl@0: TInt iNextHandle; sl@0: TInt iHandles[KMaxHandles]; sl@0: TInt iModuleNum[KMaxHandles]; sl@0: TDllList iExeDepList; sl@0: TDllList iDllConstructList; sl@0: }; sl@0: sl@0: /****************************************************************************** sl@0: * Static data sl@0: ******************************************************************************/ sl@0: #ifdef __MODULE_HAS_DATA sl@0: class TExeData sl@0: { sl@0: public: sl@0: TExeData(); sl@0: public: sl@0: TTime iStartTime; sl@0: TTime iInitTime; sl@0: TInt iTest1; sl@0: TFileName iFileName; sl@0: }; sl@0: sl@0: TInt Bss[16]; sl@0: TInt ExeNum=EXENUM; sl@0: TInt Generation=0; sl@0: TInt InitFlag=0; sl@0: TFullName StartThread=RThread().FullName(); sl@0: TName StartProcess=RProcess().Name(); sl@0: TExeData TheExeDataObject; sl@0: sl@0: TExeData::TExeData() sl@0: : iFileName(RProcess().FileName()) sl@0: { sl@0: TInt r; sl@0: CHKDEPS(r); // Check our dependencies are initialised sl@0: if (r!=KErrNone) sl@0: User::Panic(_L("CHKDEPS"),r); sl@0: iStartTime.HomeTime(); sl@0: iTest1=299792458; sl@0: RegisterConstructorCall(EXENUM); sl@0: } sl@0: #endif sl@0: sl@0: /****************************************************************************** sl@0: * Class TDllList sl@0: ******************************************************************************/ sl@0: TDllList::TDllList() sl@0: { sl@0: iCount=0; sl@0: Mem::Fill(iInfo, KNumModules*sizeof(SDllInfo), 0xff); sl@0: } sl@0: sl@0: TBool TDllList::IsPresent(const SDllInfo& aInfo) sl@0: { sl@0: TInt i; sl@0: for (i=0; iiExeDepList.iInfo, KNumModules*sizeof(SDllInfo)); sl@0: aMsg.WriteL(0, dep_list_ptr, 0); sl@0: return KErrNone; sl@0: } sl@0: sl@0: TInt CTestSession::GetCDList(const RMessage2& aMsg) sl@0: { sl@0: TPtrC8 list_ptr((const TUint8*)&iInfo->iDllConstructList.iInfo, KNumModules*sizeof(SDllInfo)); sl@0: aMsg.WriteL(0, list_ptr, 0); sl@0: return KErrNone; sl@0: } sl@0: sl@0: TInt CTestSession::LoadDll(const RMessage2& aMsg) sl@0: { sl@0: TInt module=aMsg.Int0(); sl@0: TDllList dll_list; sl@0: TPtrC8 dll_list_ptr((const TUint8*)dll_list.iInfo, KNumModules*sizeof(SDllInfo)); sl@0: TPtrC dllname=MODULE_FILENAME(module); sl@0: iInfo->SetupCDList(); sl@0: RLibrary l; sl@0: TInt r=l.Load(dllname, TUidType()); sl@0: if (r!=KErrNone) sl@0: return r; sl@0: TInitFunction f=(TInitFunction)l.Lookup(INIT_ORDINAL); sl@0: EXET_ASSERT(f); sl@0: r=(*f)(dll_list); sl@0: if (r!=KErrNone) sl@0: return r; sl@0: TBlkIFunction bf=(TBlkIFunction)l.Lookup(BLOCK_INC_ORDINAL); sl@0: EXET_ASSERT(bf); sl@0: TInt result=(*bf)(531441); sl@0: EXET_ASSERT(result==BlkIValue(module, 531441)); sl@0: TInt h=iInfo->StoreHandle(l.Handle()); sl@0: EXET_ASSERT(h>=0); sl@0: iInfo->iModuleNum[h]=module; sl@0: aMsg.WriteL(1, dll_list_ptr, 0); sl@0: return h; sl@0: } sl@0: sl@0: TInt CTestSession::CallBlkI(TInt aHandle, TInt aIn) sl@0: { sl@0: TInt h=iInfo->iHandles[aHandle]; sl@0: EXET_ASSERT(h!=0); sl@0: RLibrary l; sl@0: l.SetHandle(h); sl@0: TBlkIFunction bf=(TBlkIFunction)l.Lookup(BLOCK_INC_ORDINAL); sl@0: EXET_ASSERT(bf); sl@0: return (*bf)(aIn); sl@0: } sl@0: sl@0: TInt CTestSession::CallRBlkI(TInt aHandle, TInt aIn) sl@0: { sl@0: TInt h=iInfo->iHandles[aHandle]; sl@0: EXET_ASSERT(h!=0); sl@0: RLibrary l; sl@0: l.SetHandle(h); sl@0: TRBlkIFunction rbf=(TRBlkIFunction)l.Lookup(REC_BLOCK_INC_ORDINAL); sl@0: EXET_ASSERT(rbf); sl@0: ++iInfo->iNextGen; sl@0: return (*rbf)(aIn,iInfo->iNextGen); sl@0: } sl@0: sl@0: TInt CTestSession::CloseDll(TInt aHandle) sl@0: { sl@0: TInt h=iInfo->iHandles[aHandle]; sl@0: TInt m=iInfo->iModuleNum[aHandle]; sl@0: EXET_ASSERT(h!=0); sl@0: EXET_ASSERT(m>=0); sl@0: iInfo->iHandles[aHandle]=0; sl@0: iInfo->iModuleNum[aHandle]=-1; sl@0: iInfo->SetupCDList(); sl@0: RLibrary l; sl@0: l.SetHandle(h); sl@0: l.Close(); sl@0: return KErrNone; sl@0: } sl@0: sl@0: CTestServer::CTestServer() sl@0: : CServer2(0,ESharableSessions) sl@0: { sl@0: } sl@0: sl@0: CTestServer::~CTestServer() sl@0: { sl@0: } sl@0: sl@0: CSession2* CTestServer::NewSessionL(const TVersion& aVersion, const RMessage2&) const sl@0: { sl@0: (void)aVersion; sl@0: CTestSession* s = new (ELeave) CTestSession; sl@0: s->iInfo=iInfo; sl@0: return s; sl@0: } sl@0: sl@0: _LIT(KExetErr,"EXETERR"); sl@0: TInt CTestServer::RunError(TInt aError) sl@0: { sl@0: User::Panic(KExetErr,aError); sl@0: return 0; sl@0: } sl@0: sl@0: /****************************************************************************** sl@0: * Class CDllInfo sl@0: ******************************************************************************/ sl@0: TInt ChkC() sl@0: { sl@0: #ifdef __MODULE_HAS_DATA sl@0: TInt init_mark=~((EXENUM+DLLNUMOFFSET)*(EXENUM+DLLNUMOFFSET)); sl@0: if (InitFlag==init_mark) sl@0: return KErrNone; sl@0: if (InitFlag!=0) sl@0: return 0x494e4946; sl@0: TInt i; sl@0: TInt x=0; sl@0: for (i=0; i<16; ++i) x|=Bss[i]; sl@0: if (x) sl@0: return 0x425353; sl@0: if (ExeNum!=EXENUM) sl@0: return 0x44415441; sl@0: if (Generation!=0) sl@0: return 0x47454e; sl@0: if (StartProcess!=RProcess().Name()) sl@0: return 0x535450; sl@0: if (TheExeDataObject.iTest1!=299792458) sl@0: return 0x54455354; sl@0: if (TheExeDataObject.iFileName != RProcess().FileName()) sl@0: return 0x464e414d; sl@0: InitFlag=init_mark; sl@0: RDebug::Print(_L("ChkC %S OK"),&TheExeDataObject.iFileName); sl@0: #endif sl@0: return KErrNone; sl@0: } sl@0: sl@0: TInt Init(MDllList& aList) sl@0: { sl@0: TInt r=KErrNone; sl@0: SDllInfo info; sl@0: info.iDllNum=DLLNUM; sl@0: info.iEntryPointAddress=((TInt)&_E32Startup); sl@0: RLdrTest ldd; sl@0: ldd.Open(); sl@0: info.iModuleHandle=ldd.ModuleHandleFromAddr((TInt)&_E32Startup); sl@0: ldd.Close(); sl@0: if (!aList.IsPresent(info)) sl@0: { sl@0: TInt pos=aList.Add(info); sl@0: INITDEPS(r,aList); // Call Init on our dependencies sl@0: aList.MoveToEnd(pos); sl@0: #ifdef __MODULE_HAS_DATA sl@0: if (r==KErrNone) sl@0: r=ChkC(); // Check initial values for .data/.bss and check constructors have been called sl@0: #endif sl@0: RegisterInitCall(DLLNUM); sl@0: } sl@0: return r; sl@0: } sl@0: sl@0: CDllInfo::CDllInfo() sl@0: { sl@0: Mem::Fill(iModuleNum, sizeof(iModuleNum), 0xff); sl@0: } sl@0: sl@0: CDllInfo::~CDllInfo() sl@0: { sl@0: } sl@0: sl@0: TInt CDllInfo::Create() sl@0: { sl@0: TInt r; sl@0: r=UserSvr::DllSetTls(0, this); sl@0: if (r==KErrNone) sl@0: r=UserSvr::DllSetTls(TLS_INDEX, NULL); sl@0: if (r==KErrNone) sl@0: { sl@0: r=Init(iExeDepList); sl@0: } sl@0: return r; sl@0: } sl@0: sl@0: void CDllInfo::RegisterConstructorCall(TInt aDllNum) sl@0: { sl@0: (void)aDllNum; sl@0: } sl@0: sl@0: void CDllInfo::RegisterInitCall(TInt aDllNum) sl@0: { sl@0: (void)aDllNum; sl@0: } sl@0: sl@0: void CDllInfo::RegisterDestructorCall(TInt aDllNum) sl@0: { sl@0: (void)aDllNum; sl@0: } sl@0: sl@0: TInt CDllInfo::StoreHandle(TInt aHandle) sl@0: { sl@0: if (iHandleCount==KMaxHandles) sl@0: return KErrOverflow; sl@0: TInt i=iNextHandle; sl@0: for (; iRegisterConstructorCall(aDllNum); sl@0: } sl@0: sl@0: extern "C" __MODULE_EXPORT void RegisterInitCall(TInt aDllNum) sl@0: { sl@0: CDllInfo* p=(CDllInfo*)UserSvr::DllTls(0); sl@0: if (p) sl@0: p->RegisterInitCall(aDllNum); sl@0: } sl@0: sl@0: extern "C" __MODULE_EXPORT void RegisterDestructorCall(TInt aDllNum) sl@0: { sl@0: CDllInfo* p=(CDllInfo*)UserSvr::DllTls(0); sl@0: if (p) sl@0: p->RegisterDestructorCall(aDllNum); sl@0: } sl@0: sl@0: GLDEF_C TInt E32Main() sl@0: { sl@0: CTrapCleanup* cleanup=CTrapCleanup::New(); sl@0: EXET_ASSERT(cleanup); sl@0: CActiveScheduler* sched=new CActiveScheduler; sl@0: EXET_ASSERT(sched); sl@0: CActiveScheduler::Install(sched); sl@0: CTestServer* svr=new CTestServer; sl@0: EXET_ASSERT(svr); sl@0: TBuf<16> suffix; sl@0: User::CommandLine(suffix); sl@0: TName svr_name=KServerName(); sl@0: if (suffix.Length()) sl@0: { sl@0: svr_name.Append('.'); sl@0: svr_name+=suffix; sl@0: } sl@0: EXET_ASSERT(svr->Start(svr_name)==KErrNone); sl@0: CDllInfo* dllinfo=new CDllInfo; sl@0: EXET_ASSERT(dllinfo); sl@0: EXET_ASSERT(dllinfo->Create()==KErrNone); sl@0: svr->iInfo=dllinfo; sl@0: sl@0: CActiveScheduler::Start(); sl@0: sl@0: UserSvr::DllFreeTls(0); sl@0: UserSvr::DllFreeTls(TLS_INDEX); sl@0: delete dllinfo; sl@0: delete svr; sl@0: delete sched; sl@0: delete cleanup; sl@0: sl@0: return 0; sl@0: }