os/kernelhwsrv/kerneltest/f32test/loader/exet.cpp
author sl
Tue, 10 Jun 2014 14:32:02 +0200
changeset 1 260cb5ec6c19
permissions -rw-r--r--
Update contrib.
     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\exet.cpp
    15 // 
    16 //
    17 
    18 #define __INCLUDE_DEPENDENCY_GRAPH
    19 
    20 #include <e32svr.h>
    21 #include <f32file.h>
    22 #include "dllt.h"
    23 #include "exetifc.h"
    24 #include "dlltree.h"
    25 #include <d_ldrtst.h>
    26 #include "../mmu/d_memorytest.h"
    27 
    28 #ifdef __VC32__
    29 #pragma warning(disable:4706)
    30 #endif
    31 
    32 const TInt KMaxHandlesPerDll=4;
    33 const TInt KMaxHandles=KMaxHandlesPerDll*KNumModules;
    34 
    35 extern "C" TInt _E32Startup();
    36 
    37 extern "C" IMPORT_C void RegisterConstructorCall(TInt aDllNum);
    38 extern "C" IMPORT_C void RegisterInitCall(TInt aDllNum);
    39 extern "C" IMPORT_C void RegisterDestructorCall(TInt aDllNum);
    40 
    41 #define PANIC()		ExeTPanic(__LINE__)
    42 #define EXET_ASSERT(c)	((void)((c)||(PANIC(),0)))
    43 
    44 static TText GetSpecialDrive(TInt aSpecialDriveNum);
    45 
    46 void ExeTPanic(TInt aLine)
    47 	{
    48 	User::Panic(_L("EXET"),aLine);
    49 	}
    50 
    51 /******************************************************************************
    52  * Class Definitions
    53  ******************************************************************************/
    54 class CDllInfo;
    55 NONSHARABLE_CLASS(TDllList) : public MDllList
    56 	{
    57 public:
    58 	TDllList();
    59 	virtual TBool IsPresent(const SDllInfo& aInfo);
    60 	virtual TInt Add(const SDllInfo& aInfo);
    61 	virtual void MoveToEnd(TInt aPos);
    62 public:
    63 	TInt iCount;
    64 	SDllInfo iInfo[KNumModules];
    65 	};
    66 
    67 NONSHARABLE_CLASS(CTestServer) : public CServer2
    68 	{
    69 public:
    70 	CTestServer();
    71 	virtual ~CTestServer();
    72 	virtual CSession2* NewSessionL(const TVersion& aVersion, const RMessage2& aMessage) const;
    73 	virtual TInt RunError(TInt aError);
    74 public:
    75 	CDllInfo* iInfo;
    76 	};
    77 
    78 NONSHARABLE_CLASS(CTestSession) : public CSession2
    79 	{
    80 public:
    81 	virtual ~CTestSession();
    82 	virtual void CreateL();
    83 	virtual void ServiceL(const RMessage2& aMessage);
    84 public:
    85 	TInt GetExeDepList(const RMessage2& aMessage);
    86 	TInt GetCDList(const RMessage2& aMessage);
    87 	TInt LoadDll(const RMessage2& aMessage);
    88 	TInt CloseDll(TInt aHandle);
    89 	TInt CallBlkI(TInt aHandle, TInt aIn);
    90 	TInt CallRBlkI(TInt aHandle, TInt aIn);
    91 public:
    92 	CDllInfo* iInfo;
    93 	RMemoryTestLdd iTestLdd;
    94 	};
    95 
    96 NONSHARABLE_CLASS(CDllInfo) : public CBase
    97 	{
    98 public:
    99 	CDllInfo();
   100 	virtual ~CDllInfo();
   101 	TInt Create();
   102 	TInt StoreHandle(TInt aHandle);
   103 	void RemoveHandle(TInt aIndex);
   104 	void SetupCDList();
   105 public:
   106 	void RegisterConstructorCall(TInt aDllNum);
   107 	void RegisterInitCall(TInt aDllNum);
   108 	void RegisterDestructorCall(TInt aDllNum);
   109 public:
   110 	TInt iNextGen;
   111 	TInt iHandleCount;
   112 	TInt iNextHandle;
   113 	TInt iHandles[KMaxHandles];
   114 	TInt iModuleNum[KMaxHandles];
   115 	TDllList iExeDepList;
   116 	TDllList iDllConstructList;
   117 	};
   118 
   119 /******************************************************************************
   120  * Static data
   121  ******************************************************************************/
   122 #ifdef __MODULE_HAS_DATA
   123 class TExeData
   124 	{
   125 public:
   126 	TExeData();
   127 public:
   128 	TTime iStartTime;
   129 	TTime iInitTime;
   130 	TInt iTest1;
   131 	TFileName iFileName;
   132 	};
   133 
   134 TInt Bss[16];
   135 TInt ExeNum=EXENUM;
   136 TInt Generation=0;
   137 TInt InitFlag=0;
   138 TFullName StartThread=RThread().FullName();
   139 TName StartProcess=RProcess().Name();
   140 TExeData TheExeDataObject;
   141 
   142 TExeData::TExeData()
   143 	:	iFileName(RProcess().FileName())
   144 	{
   145 	TInt r;
   146 	CHKDEPS(r);		// Check our dependencies are initialised
   147 	if (r!=KErrNone)
   148 		User::Panic(_L("CHKDEPS"),r);
   149 	iStartTime.HomeTime();
   150 	iTest1=299792458;
   151 	RegisterConstructorCall(EXENUM);
   152 	}
   153 #endif
   154 
   155 /******************************************************************************
   156  * Class TDllList
   157  ******************************************************************************/
   158 TDllList::TDllList()
   159 	{
   160 	iCount=0;
   161 	Mem::Fill(iInfo, KNumModules*sizeof(SDllInfo), 0xff);
   162 	}
   163 
   164 TBool TDllList::IsPresent(const SDllInfo& aInfo)
   165 	{
   166 	TInt i;
   167 	for (i=0; i<iCount; ++i)
   168 		{
   169 		if (iInfo[i].iDllNum==aInfo.iDllNum)
   170 			return ETrue;
   171 		}
   172 	return EFalse;
   173 	}
   174 
   175 TInt TDllList::Add(const SDllInfo& aInfo)
   176 	{
   177 	EXET_ASSERT(iCount<KNumModules);
   178 	TInt pos=iCount;
   179 	iInfo[iCount++]=aInfo;
   180 	return pos;
   181 	}
   182 
   183 void TDllList::MoveToEnd(TInt aPos)
   184 	{
   185 	if (aPos<iCount-1)
   186 		{
   187 		SDllInfo x(iInfo[aPos]);
   188 		Mem::Move(iInfo+aPos, iInfo+aPos+1, (iCount-aPos-1)*sizeof(SDllInfo));
   189 		iInfo[iCount-1]=x;
   190 		}
   191 	}
   192 
   193 /******************************************************************************
   194  * Class CTestSession/CTestServer
   195  ******************************************************************************/
   196 
   197 CTestSession::~CTestSession()
   198 	{
   199 	}
   200 
   201 void CTestSession::CreateL()
   202 	{
   203 	User::LeaveIfError(iTestLdd.Open());
   204 	}
   205 
   206 void CTestSession::ServiceL(const RMessage2& aMessage)
   207 	{
   208 	TInt r=KErrNotSupported;
   209 	TInt mid=aMessage.Function();
   210 	switch(mid)
   211 		{
   212 		case RLoaderTest::EMsgGetExeDepList:
   213 			r=GetExeDepList(aMessage);
   214 			break;
   215 		case RLoaderTest::EMsgLoadDll:
   216 			r=LoadDll(aMessage);
   217 			break;
   218 		case RLoaderTest::EMsgCallBlkI:
   219 			r=CallBlkI(aMessage.Int0(), aMessage.Int1());
   220 			break;
   221 		case RLoaderTest::EMsgCallRBlkI:
   222 			r=CallRBlkI(aMessage.Int0(), aMessage.Int1());
   223 			break;
   224 		case RLoaderTest::EMsgCloseDll:
   225 			r=CloseDll(aMessage.Int0());
   226 			break;
   227 		case RLoaderTest::EMsgGetCDList:
   228 			r=GetCDList(aMessage);
   229 			break;
   230 		case RLoaderTest::EMsgCheckReadable:
   231 			{
   232 			TUint32 value;
   233 			r = iTestLdd.ReadMemory((TAny*)aMessage.Int0(),value);
   234 			if(r)
   235 				r = KErrGeneral;
   236 			}
   237 			break;
   238 		case RLoaderTest::EMsgExit:
   239 			r=KErrNone;
   240 			CActiveScheduler::Stop();
   241 			break;
   242 		default:
   243 			break;
   244 		}
   245 	aMessage.Complete(r);
   246 	}
   247 
   248 TInt CTestSession::GetExeDepList(const RMessage2& aMsg)
   249 	{
   250 	TPtrC8 dep_list_ptr((const TUint8*)&iInfo->iExeDepList.iInfo, KNumModules*sizeof(SDllInfo));
   251 	aMsg.WriteL(0, dep_list_ptr, 0);
   252 	return KErrNone;
   253 	}
   254 
   255 TInt CTestSession::GetCDList(const RMessage2& aMsg)
   256 	{
   257 	TPtrC8 list_ptr((const TUint8*)&iInfo->iDllConstructList.iInfo, KNumModules*sizeof(SDllInfo));
   258 	aMsg.WriteL(0, list_ptr, 0);
   259 	return KErrNone;
   260 	}
   261 
   262 static void GetDllFileName(const TDesC& aListName, TDes& aTargetName)
   263 /**
   264 	Helper function for CTestSession::LoadDll transforms the supplied
   265 	filename to an absolutely qualified name if it has been copied to a drive.
   266 
   267 	@param	aListName		The DLL name.  This will not have a path if it should
   268 							be loaded from the Z drive.  Otherwise it will be fully
   269 							qualified but with a digit for the drive letter.
   270 	@param	aTargetName		Descriptor to populate with target filename.  If the
   271 							DLL should be loaded from Z this is the same as aListName.
   272 							Otherwise, it is the same as aListName but with the correct
   273 							drive letter.
   274  */
   275 	{
   276 	aTargetName.Copy(aListName);
   277 	if (aListName[1] != ':')
   278 		return;
   279 
   280 	TText& targetDrive = aTargetName[0];
   281 	targetDrive = GetSpecialDrive(targetDrive - '0');
   282 	}
   283 
   284 
   285 TInt CTestSession::LoadDll(const RMessage2& aMsg)
   286 	{
   287 	TInt module=aMsg.Int0();
   288 	TDllList dll_list;
   289 	TPtrC8 dll_list_ptr((const TUint8*)dll_list.iInfo, KNumModules*sizeof(SDllInfo));
   290 	TPtrC dllname0=MODULE_FILENAME(module);
   291 	TFileName dllname;
   292 	GetDllFileName(dllname0, dllname);
   293 	iInfo->SetupCDList();
   294 	RLibrary l;
   295 	TInt r=l.Load(dllname, TUidType());
   296 	if (r>0)
   297 		{
   298 		RDebug::Printf("RLibrary::Load returned 0x%x !",r);
   299 		return -999; // return unexpected error type so test fails.
   300 		}
   301 	if (r!=KErrNone)
   302 		return r;
   303 	TInitFunction f=(TInitFunction)l.Lookup(INIT_ORDINAL);
   304 	EXET_ASSERT(f);
   305 	r=(*f)(dll_list);
   306 	if (r!=KErrNone)
   307 		return r;
   308 	TBlkIFunction bf=(TBlkIFunction)l.Lookup(BLOCK_INC_ORDINAL);
   309 	EXET_ASSERT(bf);
   310 	TInt result=(*bf)(531441);
   311 	EXET_ASSERT(result==BlkIValue(module, 531441));
   312 	TInt h=iInfo->StoreHandle(l.Handle());
   313 	EXET_ASSERT(h>=0);
   314 	iInfo->iModuleNum[h]=module;
   315 	aMsg.WriteL(1, dll_list_ptr, 0);
   316 	return h;
   317 	}
   318 
   319 TInt CTestSession::CallBlkI(TInt aHandle, TInt aIn)
   320 	{
   321 	TInt h=iInfo->iHandles[aHandle];
   322 	EXET_ASSERT(h!=0);
   323 	RLibrary l;
   324 	l.SetHandle(h);
   325 	TBlkIFunction bf=(TBlkIFunction)l.Lookup(BLOCK_INC_ORDINAL);
   326 	EXET_ASSERT(bf);
   327 	return (*bf)(aIn);
   328 	}
   329 
   330 TInt CTestSession::CallRBlkI(TInt aHandle, TInt aIn)
   331 	{
   332 	TInt h=iInfo->iHandles[aHandle];
   333 	EXET_ASSERT(h!=0);
   334 	RLibrary l;
   335 	l.SetHandle(h);
   336 	TRBlkIFunction rbf=(TRBlkIFunction)l.Lookup(REC_BLOCK_INC_ORDINAL);
   337 	EXET_ASSERT(rbf);
   338 	++iInfo->iNextGen;
   339 	return (*rbf)(aIn,iInfo->iNextGen);
   340 	}
   341 
   342 TInt CTestSession::CloseDll(TInt aHandle)
   343 	{
   344 	TInt h=iInfo->iHandles[aHandle];
   345 	TInt m=iInfo->iModuleNum[aHandle];
   346 	EXET_ASSERT(h!=0);
   347 	EXET_ASSERT(m>=0);
   348 	iInfo->iHandles[aHandle]=0;
   349 	iInfo->iModuleNum[aHandle]=-1;
   350 	iInfo->SetupCDList();
   351 	RLibrary l;
   352 	l.SetHandle(h);
   353 	l.Close();
   354 	return KErrNone;
   355 	}
   356 
   357 CTestServer::CTestServer()
   358 	: CServer2(0,ESharableSessions)
   359 	{
   360 	}
   361 
   362 CTestServer::~CTestServer()
   363 	{
   364 	}
   365 
   366 CSession2* CTestServer::NewSessionL(const TVersion& aVersion, const RMessage2& /*aMessage*/) const
   367 	{
   368 	(void)aVersion;
   369 	CTestSession* s = new (ELeave) CTestSession;
   370 	s->iInfo=iInfo;
   371 	return s;
   372 	}
   373 
   374 _LIT(KExetErr,"EXETERR");
   375 TInt CTestServer::RunError(TInt aError)
   376 	{
   377 	User::Panic(KExetErr,aError);
   378 	return 0;
   379 	}
   380 
   381 /******************************************************************************
   382  * Class CDllInfo
   383  ******************************************************************************/
   384 TInt ChkC()
   385 	{
   386 #ifdef __MODULE_HAS_DATA
   387 	TInt init_mark=~((EXENUM+DLLNUMOFFSET)*(EXENUM+DLLNUMOFFSET));
   388 	if (InitFlag==init_mark)
   389 		return KErrNone;
   390 	if (InitFlag!=0)
   391 		return 0x494e4946;
   392 	TInt i;
   393 	TInt x=0;
   394 	for (i=0; i<16; ++i) x|=Bss[i];
   395 	if (x)
   396 		return 0x425353;
   397 	if (ExeNum!=EXENUM)
   398 		return 0x44415441;
   399 	if (Generation!=0)
   400 		return 0x47454e;
   401 	if (StartProcess!=RProcess().Name())
   402 		return 0x535450;
   403 	if (TheExeDataObject.iTest1!=299792458)
   404 		return 0x54455354;
   405 	if (TheExeDataObject.iFileName != RProcess().FileName())
   406 		return 0x464e414d;
   407 	InitFlag=init_mark;
   408 	RDebug::Print(_L("ChkC %S OK"),&TheExeDataObject.iFileName);
   409 #endif
   410 	return KErrNone;
   411 	}
   412 
   413 TInt Init(MDllList& aList)
   414 	{
   415 	TInt r=KErrNone;
   416 	SDllInfo info;
   417 	info.iDllNum=DLLNUM;
   418 	info.iEntryPointAddress=((TInt)&_E32Startup);
   419 	RLdrTest ldd;
   420 	ldd.Open();
   421 	info.iModuleHandle=ldd.ModuleHandleFromAddr((TInt)&_E32Startup);
   422 	ldd.Close();
   423 	if (!aList.IsPresent(info))
   424 		{
   425 		TInt pos=aList.Add(info);
   426 		INITDEPS(r,aList);		// Call Init on our dependencies
   427 		aList.MoveToEnd(pos);
   428 #ifdef __MODULE_HAS_DATA
   429 		if (r==KErrNone)
   430 			r=ChkC();		// Check initial values for .data/.bss and check constructors have been called
   431 #endif
   432 		RegisterInitCall(DLLNUM);
   433 		}
   434 	return r;
   435 	}
   436 
   437 CDllInfo::CDllInfo()
   438 	{
   439 	Mem::Fill(iModuleNum, sizeof(iModuleNum), 0xff);
   440 	}
   441 
   442 CDllInfo::~CDllInfo()
   443 	{
   444 	}
   445 
   446 TInt CDllInfo::Create()
   447 	{
   448 	TInt r;
   449 	r=UserSvr::DllSetTls(0, this);
   450 	if (r==KErrNone)
   451 		r=UserSvr::DllSetTls(TLS_INDEX, NULL);
   452 	if (r==KErrNone)
   453 		{
   454 		r=Init(iExeDepList);
   455 		}
   456 	return r;
   457 	}
   458 
   459 void CDllInfo::RegisterConstructorCall(TInt aDllNum)
   460 	{
   461 	(void)aDllNum;
   462 	}
   463 
   464 void CDllInfo::RegisterInitCall(TInt aDllNum)
   465 	{
   466 	(void)aDllNum;
   467 	}
   468 
   469 void CDllInfo::RegisterDestructorCall(TInt aDllNum)
   470 	{
   471 	(void)aDllNum;
   472 	}
   473 
   474 TInt CDllInfo::StoreHandle(TInt aHandle)
   475 	{
   476 	if (iHandleCount==KMaxHandles)
   477 		return KErrOverflow;
   478 	TInt i=iNextHandle;
   479 	for (; i<KMaxHandles && iHandles[i]!=0; ++i) {}
   480 	if (i==KMaxHandles)
   481 		{
   482 		for (i=0; i<iNextHandle && iHandles[i]!=0; ++i) {}
   483 		EXET_ASSERT(i!=iNextHandle);
   484 		}
   485 	iNextHandle=i;
   486 	iHandles[i]=aHandle;
   487 	++iHandleCount;
   488 	return i;
   489 	}
   490 
   491 void CDllInfo::RemoveHandle(TInt aIndex)
   492 	{
   493 	iHandles[aIndex]=0;
   494 	--iHandleCount;
   495 	}
   496 
   497 void CDllInfo::SetupCDList()
   498 	{
   499 	new (&iDllConstructList) TDllList;
   500 	EXET_ASSERT(UserSvr::DllSetTls(TLS_INDEX, &iDllConstructList)==KErrNone);
   501 	}
   502 
   503 /******************************************************************************
   504  * Exports
   505  ******************************************************************************/
   506 extern "C" __MODULE_EXPORT void RegisterConstructorCall(TInt aDllNum)
   507 	{
   508 	CDllInfo* p=(CDllInfo*)UserSvr::DllTls(0);
   509 	if (p)
   510 		p->RegisterConstructorCall(aDllNum);
   511 	}
   512 
   513 extern "C" __MODULE_EXPORT void RegisterInitCall(TInt aDllNum)
   514 	{
   515 	CDllInfo* p=(CDllInfo*)UserSvr::DllTls(0);
   516 	if (p)
   517 		p->RegisterInitCall(aDllNum);
   518 	}
   519 
   520 extern "C" __MODULE_EXPORT void RegisterDestructorCall(TInt aDllNum)
   521 	{
   522 	CDllInfo* p=(CDllInfo*)UserSvr::DllTls(0);
   523 	if (p)
   524 		p->RegisterDestructorCall(aDllNum);
   525 	}
   526 
   527 static TText GetSpecialDrive(TInt aSpecialDriveNum)
   528 /**
   529 	Work out which physical drive corresponds to the supplied
   530 	logical drive.
   531 	
   532 	@param	aSpecialDriveNum	Number which identifies which drive to find.
   533 							Zero means internal drive.
   534 	@return					Drive letter.
   535  */
   536 	{
   537 	RFs fs;
   538 	TInt r = fs.Connect();
   539 	EXET_ASSERT(r == KErrNone);
   540 
   541 	// cannot load binaries from emulated removable drives
   542 #ifdef __WINS__
   543 	if (aSpecialDriveNum == 1)
   544 		return 'c';
   545 #endif
   546 
   547 	TInt dr = 0;
   548 	for (TInt d = 0; d <= (TInt)sizeof(SpecialDriveList); ++d)
   549 		{
   550 		dr = SpecialDriveList[d];
   551 		TDriveInfo di;
   552 		r = fs.Drive(di, dr);
   553 		EXET_ASSERT(r == KErrNone);
   554 		if (di.iType == EMediaNotPresent)
   555 			continue;
   556 		
   557 		// drive 0 == internal
   558 		if (aSpecialDriveNum == 0 && (di.iDriveAtt & KDriveAttInternal) != 0)
   559 			break;
   560 		// drive 1 == removable
   561 		if (aSpecialDriveNum == 1 && (di.iDriveAtt & KDriveAttRemovable) != 0)
   562 			break;
   563 		}	
   564 
   565 	TChar ch0;
   566 	r = RFs::DriveToChar(dr, ch0);
   567 	EXET_ASSERT(r == KErrNone);
   568 	fs.Close();
   569 	return static_cast<TText>(TUint(ch0));
   570 	}
   571 
   572 GLDEF_C TInt E32Main()
   573 	{
   574 	CTrapCleanup* cleanup=CTrapCleanup::New();
   575 	EXET_ASSERT(cleanup);
   576 	CActiveScheduler* sched=new CActiveScheduler;
   577 	EXET_ASSERT(sched);
   578 	CActiveScheduler::Install(sched);
   579 	CTestServer* svr=new CTestServer;
   580 	EXET_ASSERT(svr);
   581 	TBuf<16> suffix;
   582 	User::CommandLine(suffix);
   583 	TName svr_name=KServerName();
   584 	if (suffix.Length())
   585 		{
   586 		svr_name.Append('.');
   587 		svr_name+=suffix;
   588 		}
   589 	EXET_ASSERT(svr->Start(svr_name)==KErrNone);
   590 	CDllInfo* dllinfo=new CDllInfo;
   591 	EXET_ASSERT(dllinfo);
   592 	EXET_ASSERT(dllinfo->Create()==KErrNone);
   593 	svr->iInfo=dllinfo;
   594 
   595 	CActiveScheduler::Start();
   596 
   597 	UserSvr::DllFreeTls(0);
   598 	UserSvr::DllFreeTls(TLS_INDEX);
   599 	delete dllinfo;
   600 	delete svr;
   601 	delete sched;
   602 	delete cleanup;
   603 
   604 	return 0;
   605 	}