os/kernelhwsrv/kerneltest/e32test/debug/t_codemodifier.cpp
author sl@SLION-WIN7.fritz.box
Fri, 15 Jun 2012 03:10:57 +0200
changeset 0 bde4ae8d615e
permissions -rw-r--r--
First public contribution.
     1 // Copyright (c) 2005-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 // e32test\debug\t_codemodifier.cpp
    15 // Overview:
    16 // Exercises Kernel's Code Modifier. This is common use case for run-mode debuggers.
    17 // API Information:
    18 // DebugSupport::InitialiseCodeModifier
    19 // DebugSupport::CloseCodeModifier
    20 // DebugSupport::ModifyCode
    21 // DebugSupport::RestoreCode
    22 // Kern::ThreadRawRead
    23 // Kern::ThreadRawWrite
    24 // Details:
    25 // -Three applications are running in the test:
    26 // - t_codemodifier.exe client
    27 // - t_codemodifier.exe server (XIP code)
    28 // - t_codemodifier2.exe client (non-XIP code)
    29 // -Test1 -Checks that the TestFunc (that will be altered by breakpoints) is really deadly if un-altered.
    30 // -Test2 -Checks Code Modifier if data segment address is passed to set breakpoint.	
    31 // -Test3 -Checks Code Modifier if invalid address is passed to set breakpoint.Kern::ThreadRawRead\Write is also checked.	
    32 // -Test4 -Replaces BRK instruction in TestFunc with NOP using 1.2 and 4 bytes long breakpoints. Executes the 
    33 // function in the servers.
    34 // -Test5 -Repeats Test4 (for XIP server only) with previously shedowed TestFunc
    35 // -Test6 -Tests scenario when a process terminates while there are still associated breakpoints.
    36 // -Test7 -Tests out-of-breakpoints scenario
    37 // -Test8 -Tests breakpoint-already-exists scenario
    38 // -Test9 -Tests CodeModifier closing when there are still active breakpoints.	Breakpoints in this test occupies more then
    39 // one shadowed page.
    40 // -Test10-A random stress test. Sets/Clears random brekpoints in CodeArea of the both servers. Then replaces
    41 // all BRKs with NOPs in CodeArea and executes them.
    42 // -Test11-Checks that overlaping breakpoints are rejected.
    43 // Platforms/Drives/Compatibility:
    44 // Hardware (Automatic). Not supported on emulator.
    45 // Assumptions/Requirement/Pre-requisites:
    46 // Failures and causes:
    47 // Base Port information:
    48 // 
    49 //
    50 
    51 #define __E32TEST_EXTENSION__
    52 #include <e32test.h>
    53 #include <e32ldr.h>
    54 #include <e32ldr_private.h>
    55 #include <f32dbg.h>
    56 #include "d_codemodifier.h"
    57 #include "../misc/prbs.h"
    58 
    59 LOCAL_D RTest test(_L("T_CODEMODIFIER"));
    60 _LIT(KServerXIP,"ServerXIP");
    61 _LIT(KServerNONXIP,"ServerNONXIP");
    62 _LIT(KAppXIP,"t_codemodifier.exe");
    63 _LIT(KAppNONXIP,"t_codemodifier2.exe");
    64 
    65 extern void TestFunc();
    66 extern void CodeArea();
    67 
    68 //------------client globals---------------------
    69 RCodeModifierDevice Device;
    70 
    71 /**	These addresses/names is all the client needs to test a server.
    72 	There are XIP and non-XIP server in the test*/
    73 struct SServerData
    74 	{
    75 	TInt  		 iThreadId;
    76 	TUint 		 iVarAddr;
    77 	TUint 		 iFuncAddr;
    78 	TUint 		 iInvalidAddr;
    79 	TUint 		 iCodeAreaAddr;
    80 	const TDesC* iAppName;
    81 	const TDesC* iServerName;
    82 	RProcess 	 iProcess;
    83 	} ServerData[2];
    84 
    85 /**Will hold assembler instructions that make TestFunc.*/
    86 struct STestFunc
    87 	{
    88 	TInt iBRK;
    89 	TInt iNOP;
    90 	TInt iRET;
    91 	} TestFuncCode;
    92 
    93 /**ServerData[0] is about XIP server, ServerData[1] is non-XIP server*/
    94 enum TWhichServer
    95 	{
    96 	EXip = 0,
    97 	ENonxip = 1
    98 	};
    99 
   100 /**Server*/
   101 class CCodeModifierServer : public CServer2
   102 	{
   103 public:
   104 	static CCodeModifierServer* New(TInt aPriority);
   105 private:
   106 	CCodeModifierServer(TInt aPriority) : CServer2(aPriority){}
   107 	CSession2* NewSessionL(const TVersion& aVersion,const RMessage2& aMessage) const;
   108 public:
   109 	TInt iTestVar;
   110 	RChunk chunk;
   111 	};
   112 
   113 CCodeModifierServer* CCodeModifierServer::New(TInt aPriority)
   114 	{
   115 	return new CCodeModifierServer(aPriority);
   116 	}
   117 
   118 /**Server side session*/
   119 class CCodeModifierSession : public CSession2
   120 	{
   121 public:
   122 	enum TCommand {EStop, EGetServerInfo, ERunTestFunc, ERunCodeAreaFunc};
   123 private:
   124 	void ServiceL(const RMessage2& aMessage);
   125 	};
   126 
   127 /*Client-side session*/
   128 class RCodeModifierSession : private RSessionBase
   129 	{
   130 public:
   131 	/**Updates ServerData[aServer] with data from the server*/
   132 	static TInt GetServerInfo(TInt aServer)
   133 		{
   134 		TPtr8 ptr((TUint8*)&ServerData[aServer].iThreadId, 5*sizeof(TInt),5*sizeof(TInt));
   135 		TIpcArgs args(&ptr);
   136 		return Control(CCodeModifierSession::EGetServerInfo,aServer,args);
   137 		};
   138 	/**Stops the server*/	
   139 	static TInt Stop(TInt aServer)
   140 		{TIpcArgs args;return Control(CCodeModifierSession::EStop,aServer, args);};
   141 	/**Issues the command to server to run TestFunc*/
   142 	static TInt RunTestFunc(TInt aServer)
   143 		{TIpcArgs args;return Control(CCodeModifierSession::ERunTestFunc,aServer,args);};
   144 	/**Issues the command to server to run CodeArea*/
   145 	static TInt RunCodeAreaFunc(TInt aServer)
   146 		{TIpcArgs args;return Control(CCodeModifierSession::ERunCodeAreaFunc,aServer,args);};
   147 private:
   148 	/*Executes a synchronius client-server request*/
   149 	static TInt Control(CCodeModifierSession::TCommand aRequest, TInt aServer, TIpcArgs& aArgs)
   150 		{
   151 		RCodeModifierSession p;
   152 		TInt r = p.CreateSession(*ServerData[aServer].iServerName, TVersion(), 0);
   153 		if (r == KErrNone)
   154 			p.SendReceive(aRequest, aArgs);
   155 		p.Close();
   156 		return r;
   157 		};
   158 	};
   159 
   160 //------------server globals---------------------
   161 CCodeModifierServer* CodeModifierServer;
   162 
   163 /**Creates a new client for this server.*/
   164 CSession2* CCodeModifierServer::NewSessionL(const TVersion&, const RMessage2&) const
   165 	{
   166 	return new(ELeave) CCodeModifierSession();
   167 	}
   168 
   169 /**Session entry point on the server side.*/
   170 void CCodeModifierSession::ServiceL(const RMessage2& aMessage)
   171 	{
   172 	TInt r=KErrNone;
   173 	switch (aMessage.Function())
   174 		{
   175 	case EGetServerInfo:		//Pass threadId and addresses to the client
   176 		{
   177 		struct SInfo
   178 			{
   179 			TInt  iThreadId;
   180 			TUint iVarAddr;
   181 			TUint iFuncAddr;
   182 			TUint iInvalidAddr;
   183 			TUint iCodeAreaAddr;
   184 			} info;
   185 		RThread thread;
   186 		info.iThreadId =    (TInt) thread.Id();
   187 		info.iVarAddr =     (TUint) &CodeModifierServer->iTestVar;
   188 		info.iInvalidAddr = (TUint)CodeModifierServer->chunk.Base()+0x1000;
   189 		info.iFuncAddr =    (TUint)&TestFunc;
   190 		info.iCodeAreaAddr =(TUint)&CodeArea;
   191 		TPtrC8 ptr((TUint8*)&info, sizeof(SInfo));
   192 		r=aMessage.Write(0,ptr);
   193 		}
   194 		break;
   195 
   196 	case ERunTestFunc:			//Execute TestFunc
   197 		TestFunc();
   198 		break;
   199 
   200 	case ERunCodeAreaFunc:			//Execute CodeArea
   201 		CodeArea();
   202 		break;
   203 
   204 	case EStop:					//This will stop the server thread.
   205 		CActiveScheduler::Stop();
   206 		break;
   207 
   208 	default:
   209 		r=KErrNotSupported;
   210 		}
   211 	aMessage.Complete(r);
   212 	}
   213 
   214 /**Server application entry point*/
   215 LOCAL_C TInt ServerEntryPoint(TInt aServer)
   216 	{
   217 	TInt r=0;
   218 	__UHEAP_MARK;
   219 	
   220 	CActiveScheduler *pR=new CActiveScheduler;
   221 	if (!pR)
   222 		User::Panic(_L("SVR:Could't create Active Scheduler\n"), KErrNoMemory);
   223 	CActiveScheduler::Install(pR);
   224 
   225 	CodeModifierServer = CCodeModifierServer::New(0);
   226 	if(!CodeModifierServer)
   227 		{
   228 		delete pR;
   229 		User::Panic(_L("SVR:Create svr error\n"), KErrNoMemory);
   230 		}
   231 
   232 	//Create a chunk with a hole between addresses 0x1000 & 0x2000
   233 	r=CodeModifierServer->chunk.CreateDisconnectedLocal(0,0,0x200000);
   234 	test_KErrNone(r);
   235 	r=CodeModifierServer->chunk.Commit(0,0x1000);
   236 	test_KErrNone(r);
   237 	r=CodeModifierServer->chunk.Commit(0x2000,0x1000);
   238 	test_KErrNone(r);
   239 
   240 	//We decide here which server to start.
   241 	if (aServer==0)
   242 		r=CodeModifierServer->Start(KServerXIP);
   243 	else
   244 		r=CodeModifierServer->Start(KServerNONXIP);
   245 		
   246 	if (r!=KErrNone)
   247 		{
   248 		delete CodeModifierServer;
   249 		delete pR;
   250 		User::Panic(_L("SVR:Error starting server\n"), r);
   251 		}
   252 	RProcess::Rendezvous(KErrNone);
   253 	CActiveScheduler::Start();
   254 
   255 	//We come here on CActiveScheduler::Stop()
   256 	delete CodeModifierServer;
   257 	delete pR;
   258 	__UHEAP_MARKEND;
   259 	return(KErrNone);
   260 	}
   261 
   262 //Initializes the globals and switch off lazy (un)loader. Called just once at the start.
   263 void UpdateClientsGlobals()
   264 	{
   265 	TInt* ptr = (TInt*)TestFunc;
   266 	TestFuncCode.iBRK = *(ptr++);
   267 	TestFuncCode.iNOP = *(ptr++);
   268 	TestFuncCode.iRET = *(ptr++);
   269 	test.Printf(_L("UpdateClientsGlobals BRK:%x NOP:%x RET:%x\n"),TestFuncCode.iBRK,TestFuncCode.iNOP,TestFuncCode.iRET);
   270 
   271 	ServerData[0].iAppName=&KAppXIP;
   272 	ServerData[1].iAppName=&KAppNONXIP;
   273 	ServerData[0].iServerName=&KServerXIP;
   274 	ServerData[1].iServerName=&KServerNONXIP;
   275 
   276 	//Turn off lazy dll (un)loader.
   277 	//If we don't this, the second run of the test (within 2 minutes of the first one) would fail.
   278 	RLoader l;
   279 	test_KErrNone(l.Connect());
   280 	test_KErrNone(l.CancelLazyDllUnload());
   281 	l.Close();
   282 	}
   283 	
   284 //Starts the server (0-XIP 1-NONXIP server)
   285 //Obtains data from the server
   286 //Updates the driver with the threadID of the server
   287 void StartAndUpdate(TInt aServer)
   288 	{
   289 	TRequestStatus status;
   290 	RProcess& p = ServerData[aServer].iProcess;
   291 	test.Printf(_L("StartAndUpdate %d\n"),aServer);
   292 	//Starts the server
   293 	TInt r = p.Create(*ServerData[aServer].iAppName,*ServerData[aServer].iServerName);
   294 	test_KErrNone(r);
   295 	p.Rendezvous(status);
   296 	p.Resume();
   297 	User::WaitForRequest(status);
   298 	test.Printf(_L("%d returned\n"),status.Int());
   299 	test_KErrNone(status.Int());
   300 	//Get threadId and addresses from the server
   301 	test_KErrNone(RCodeModifierSession::GetServerInfo(aServer));
   302 	SServerData& s = ServerData[aServer];
   303 	test.Printf(_L("ServerData:TId:%x VA:%x FA:%x IA:%x CA:%x \n"),s.iThreadId,s.iVarAddr,s.iFuncAddr,s.iInvalidAddr,s.iCodeAreaAddr);
   304 	//Update threadID of the server in device driver
   305 	test_KErrNone(Device.ThreadId(aServer, s.iThreadId));
   306 	}
   307 
   308 //Kills the server(by forcing to execute TestFunc), then restarts it.
   309 void KillAndRestart(TInt aServer)
   310 	{
   311 	test.Printf(_L("KillAndRestart %d\n"),aServer);
   312 	TInt r=RCodeModifierSession::RunTestFunc(aServer);
   313 	test.Printf(_L("%d returned\n"),r);
   314 
   315 	test.Printf(_L("Check the server died\n"));
   316 	r = RCodeModifierSession::GetServerInfo(aServer);
   317 	test.Printf(_L("%d returned\n"),r);
   318 	test(r!=KErrNone);
   319 	
   320 	StartAndUpdate(aServer);
   321 	}
   322 
   323 //Terminates the server
   324 void TerminateServer(TInt aServer)
   325 	{
   326 	TRequestStatus status;
   327 	RProcess& p = ServerData[aServer].iProcess;
   328 
   329 	test.Printf(_L("TerminateServer %d\n"),aServer);
   330 	test_KErrNone(RCodeModifierSession::Stop(aServer));
   331 	p.Logon(status);
   332 	User::WaitForRequest(status);
   333 	test_Equal(EExitKill, p.ExitType());
   334 	CLOSE_AND_WAIT(p);
   335 	}
   336 
   337 //Starts LDD
   338 void StartDriver()
   339 	{
   340 	test.Printf(_L("StartDriver\n"));
   341 	TInt r = User::LoadLogicalDevice(KCodeModifierName);
   342 	test_Value(r, r==KErrNone || r==KErrAlreadyExists);
   343 	if((r = Device.Open())!=KErrNone)	
   344 		{
   345 		User::FreeLogicalDevice(KCodeModifierName);
   346 		test.Printf(_L("Could not open LDD"));
   347 		test(0);
   348 		}
   349 	}
   350 
   351 //Unloads LDD
   352 void StopDriver()
   353 	{
   354 	test.Printf(_L("StopDriver\n"));
   355 	Device.Close();
   356 	User::FreeLogicalDevice(KCodeModifierName);
   357 	}
   358 
   359 //Checks that TestFunc in servers is really deadly if we do not alter the code
   360 void Test1()
   361 	{
   362 	test.Printf(_L("Test1\n"));
   363 	KillAndRestart(EXip);
   364 	}
   365 
   366 //Passing data segment address to set breakpoint.
   367 //The actual behaviour depends of the memory model
   368 //ARMv5: KErrBadDescriptor (-38) is returned
   369 //ARMv6: Will return 0
   370 //We have to make sure here that nothing panics or take any nasty behaviour.
   371 void Test2(TInt aServer)
   372 	{
   373 	TInt val;
   374 	test.Printf(_L("Test2 %d\n"), aServer);
   375 	test_KErrNone(Device.InitialiseCodeModifier(10));
   376 
   377 	//Write/read data through ThreadRowWrite/Read
   378 	test_KErrNone(Device.WriteWord(aServer, ServerData[aServer].iVarAddr,/*value*/1));
   379 	test_KErrNone(Device.ReadWord(aServer, ServerData[aServer].iVarAddr,&val));
   380 	test_Equal(1, val);
   381 		
   382 	//Set breakpoint
   383 	TInt r=Device.WriteCode(aServer, ServerData[aServer].iVarAddr,/*value*/5, /*size*/4);
   384 	test.Printf(_L("returns %d\n"),r);
   385 
   386 	test_KErrNone(Device.CloseCodeModifier());
   387 	}
   388 
   389 //Passing invalid address to set breakpoint.
   390 void Test3(TInt aServer)
   391 	{
   392 	TInt val;
   393 	test.Printf(_L("Test3 %d\n"), aServer);
   394 	test_KErrNone(Device.InitialiseCodeModifier(10));
   395 
   396 	//Write/read by ThreadRowWrite/Read
   397 	test_Equal(KErrBadDescriptor, Device.WriteWord(aServer, ServerData[aServer].iInvalidAddr,/*value*/1));
   398 	test_Equal(KErrBadDescriptor, Device.ReadWord(aServer, ServerData[aServer].iInvalidAddr,&val));
   399 		
   400 	//Set breakpoints
   401 	test_Equal(KErrBadDescriptor, Device.WriteCode(aServer, ServerData[aServer].iInvalidAddr,/*value*/5, /*size*/1));
   402 	test_Equal(KErrBadDescriptor, Device.WriteCode(aServer, ServerData[aServer].iInvalidAddr,/*value*/5, /*size*/2));
   403 	test_Equal(KErrBadDescriptor, Device.WriteCode(aServer, ServerData[aServer].iInvalidAddr,/*value*/5, /*size*/4));
   404 
   405 	test_KErrNone(Device.CloseCodeModifier());
   406 	}
   407 
   408 //Replace BRK in TestFunc in server using 1,2 and 4 long breakpoints.
   409 //Check the content of test func.
   410 //Execute Test Func
   411 void Test4(TInt aServer)
   412 	{
   413 	TInt var;
   414 	test.Printf(_L("Test4 %d\n"), aServer);
   415 
   416 	//Try to write code segment throught Kern::ThreadRowWrite
   417 	test_Equal(KErrBadDescriptor, Device.WriteWord(aServer, ServerData[aServer].iFuncAddr,/*value*/1));
   418 
   419 	test_KErrNone(Device.InitialiseCodeModifier(10));
   420 
   421 	test.Printf(_L("Replace byte 3 of the 1st instruction\n"));
   422 	test_KErrNone(Device.WriteCode(aServer, ServerData[aServer].iFuncAddr+3,TestFuncCode.iNOP>>24, /*size*/1));
   423 	test_KErrNone(Device.ReadWord(aServer,ServerData[aServer].iFuncAddr, &var));
   424 	test.Printf(_L("%xH returned\n"),var);
   425 	test((TUint)var == ((TestFuncCode.iBRK & 0xffffff) | (TestFuncCode.iNOP & 0xff000000)));
   426 
   427 	test.Printf(_L("Replace byte 2 of the 1st instruction\n"));
   428 	test_KErrNone(Device.WriteCode(aServer, ServerData[aServer].iFuncAddr+2,TestFuncCode.iNOP>>16, /*size*/1));
   429 	test_KErrNone(Device.ReadWord(aServer,ServerData[aServer].iFuncAddr, &var));
   430 	test.Printf(_L("%xH returned\n"),var);
   431 	test((TUint)var == ((TestFuncCode.iBRK & 0xffff) | (TestFuncCode.iNOP & 0xffff0000)));
   432 
   433 	test.Printf(_L("Replace bytes 0 & 1 of the 1st instruction\n"));
   434 	var = TestFuncCode.iNOP | 0xff0000; //byte 3 is messed up - but it won't be writen into code bacause iSize is 2
   435 	test_KErrNone(Device.WriteCode(aServer, ServerData[aServer].iFuncAddr,var, /*size*/2));
   436 	test_KErrNone(Device.ReadWord(aServer,ServerData[aServer].iFuncAddr, &var));
   437 	test.Printf(_L("%xH returned\n"),var);
   438 	test_Equal(TestFuncCode.iNOP, var);
   439 
   440 	//We have replaced BRK with NOP. It should be safe now for the server to execute TestFunc.
   441 	test.Printf(_L("Run TestFunc in server and check the server is still alive\n"));
   442 	test_KErrNone(RCodeModifierSession::RunTestFunc(aServer));
   443 	test_KErrNone(RCodeModifierSession::GetServerInfo(aServer));//Any call will work here
   444 
   445 	test.Printf(_L("Revert bytes 0 & 1\n"));
   446 	test_KErrNone(Device.RestoreCode(aServer, ServerData[aServer].iFuncAddr));
   447 	test_KErrNone(Device.ReadWord(aServer, ServerData[aServer].iFuncAddr, &var));
   448 	test.Printf(_L("%xH returned\n"),var);
   449 	test((TUint)var == ((TestFuncCode.iBRK & 0xffff) | (TestFuncCode.iNOP & 0xffff0000)));
   450 
   451 	test.Printf(_L("Revert byte 2\n"));
   452 	test_KErrNone(Device.RestoreCode(aServer, ServerData[aServer].iFuncAddr+2));
   453 	test_KErrNone(Device.ReadWord(aServer, ServerData[aServer].iFuncAddr, &var));
   454 	test.Printf(_L("%xH returned\n"),var);
   455 	test((TUint)var == ((TestFuncCode.iBRK & 0xffffff) | (TestFuncCode.iNOP & 0xff000000)));
   456 
   457 	test.Printf(_L("Revert byte 3\n"));
   458 	test_KErrNone(Device.RestoreCode(aServer, ServerData[aServer].iFuncAddr+3));
   459 	test_KErrNone(Device.ReadWord(aServer, ServerData[aServer].iFuncAddr, &var));
   460 	test.Printf(_L("%xH returned\n"),var);
   461 	test(var == TestFuncCode.iBRK);
   462 
   463 	test.Printf(_L("Replace the 1st instruction with the 2nd one in TestFunc\n"));
   464 	test_KErrNone(Device.WriteCode(aServer, ServerData[aServer].iFuncAddr,TestFuncCode.iNOP, /*size*/4));
   465 	test_KErrNone(Device.ReadWord(aServer,ServerData[aServer].iFuncAddr, &var));
   466 	test.Printf(_L("%xH returned\n"),var);
   467 	test(var == TestFuncCode.iNOP);
   468 
   469 	//We have replaced BRK with NOP. It should be safe now for the server to execute TestFunc.
   470 	test.Printf(_L("Run TestFunc in server and check the server is still alive\n"));
   471 	test_KErrNone(RCodeModifierSession::RunTestFunc(aServer));
   472 	test_KErrNone(RCodeModifierSession::GetServerInfo(aServer));//Any call will work here
   473 
   474 	test_KErrNone(Device.CloseCodeModifier());
   475 	}
   476 
   477 //Executes Test4 but with previously shadowed page
   478 void Test5(TInt aServer)
   479 	{
   480 	test.Printf(_L("Test5 %d\n"), aServer);
   481 
   482 	test_KErrNone(Device.AllocShadowPage(ServerData[aServer].iFuncAddr));
   483 	Test4(aServer);	
   484 	test_KErrNone(Device.FreeShadowPage(ServerData[aServer].iFuncAddr));
   485 	}
   486 
   487 //Tests scenario when a process terminates while there are still associated breakpoints.
   488 void Test6(TInt aServer)
   489 	{
   490 	TInt var;
   491 	test.Printf(_L("Test6 %d\n"), aServer);
   492 
   493 	test_KErrNone(Device.InitialiseCodeModifier(10));
   494 
   495 	test.Printf(_L("Replace the 1st instruction (BRK) with the 2nd one (NOP) in TestFunc\n"));
   496 	test_KErrNone(Device.WriteCode(aServer, ServerData[aServer].iFuncAddr,TestFuncCode.iNOP, /*size*/4));
   497 	test_KErrNone(Device.ReadWord(aServer,ServerData[aServer].iFuncAddr, &var));
   498 	test.Printf(_L("%xH returned\n"),var);
   499 	test(var == TestFuncCode.iNOP);
   500 
   501 	TerminateServer(aServer);
   502 	//After application has stopped, Kernel should clean the breakpoint associated to the server's process....
   503 	
   504 	StartAndUpdate(aServer);
   505 	KillAndRestart(aServer);//... and TestFunct must be deadly again.
   506 
   507 	test_KErrNone(Device.CloseCodeModifier());
   508 	}
   509 
   510 //Tests out-of-breakpoints scenario
   511 void Test7(TInt aServer)
   512 	{
   513 	test.Printf(_L("Test7 %d\n"), aServer);
   514 	test_KErrNone(Device.InitialiseCodeModifier(1));
   515 
   516 	test_KErrNone(Device.WriteCode(aServer, ServerData[aServer].iCodeAreaAddr,TestFuncCode.iNOP, /*size*/4));
   517 	test_Equal(KErrNoMemory, Device.WriteCode(aServer, ServerData[aServer].iCodeAreaAddr+4,TestFuncCode.iNOP, /*size*/4));
   518 
   519 	test_KErrNone(Device.CloseCodeModifier());
   520 	}
   521 
   522 //Tests breakpoint-already-exists scenario
   523 void Test8(TInt aServer)
   524 	{
   525 	test.Printf(_L("Test8 %d\n"), aServer);
   526 	test_KErrNone(Device.InitialiseCodeModifier(1));
   527 
   528 	test_KErrNone(Device.WriteCode(aServer, ServerData[aServer].iCodeAreaAddr,TestFuncCode.iNOP, /*size*/4));
   529 	test_Equal(KErrAlreadyExists, Device.WriteCode(aServer, ServerData[aServer].iCodeAreaAddr,TestFuncCode.iNOP, /*size*/4));
   530 
   531 	test_KErrNone(Device.CloseCodeModifier());
   532 	}
   533 
   534 //Tests CodeModifier closing when there are still breakpoints.
   535 //Breakpoints in this test occupies more then one shadowed page.
   536 void Test9()
   537 	{
   538 	TInt var;
   539 	test.Printf(_L("Test9\n"));
   540 	test_KErrNone(Device.InitialiseCodeModifier(10));
   541 
   542 	//Put NOPs at the beginning of the code area
   543 	test_KErrNone(Device.WriteCode(EXip, ServerData[EXip].iCodeAreaAddr,TestFuncCode.iNOP, /*size*/4));
   544 	test_KErrNone(Device.WriteCode(ENonxip, ServerData[ENonxip].iCodeAreaAddr,TestFuncCode.iNOP, /*size*/4));
   545 
   546 	//Put NOPs at the end of the code area (there are 1024 BRK instructions in CodeArea
   547 	test_KErrNone(Device.WriteCode(EXip, ServerData[EXip].iCodeAreaAddr+1024*sizeof(TInt),TestFuncCode.iNOP, /*size*/4));
   548 	test_KErrNone(Device.WriteCode(ENonxip, ServerData[ENonxip].iCodeAreaAddr+1024*sizeof(TInt),TestFuncCode.iNOP, /*size*/4));
   549 
   550 	//Check NOPs are there
   551 	test_KErrNone(Device.ReadWord(EXip,ServerData[EXip].iCodeAreaAddr, &var));
   552 	test_Equal(TestFuncCode.iNOP, var);
   553 	test_KErrNone(Device.ReadWord(ENonxip,ServerData[ENonxip].iCodeAreaAddr, &var));
   554 	test_Equal(TestFuncCode.iNOP, var);
   555 	test_KErrNone(Device.ReadWord(EXip,ServerData[EXip].iCodeAreaAddr+1024*sizeof(TInt), &var));
   556 	test_Equal(TestFuncCode.iNOP, var);
   557 	test_KErrNone(Device.ReadWord(ENonxip,ServerData[ENonxip].iCodeAreaAddr+1024*sizeof(TInt), &var));
   558 	test_Equal(TestFuncCode.iNOP, var);
   559 
   560 	//Close Code Modifier. It should revert the changes in the code.
   561 	test_KErrNone(Device.CloseCodeModifier());
   562 
   563 	//Check BRKs are back
   564 	test_KErrNone(Device.ReadWord(EXip,ServerData[EXip].iCodeAreaAddr, &var));
   565 	test_Equal(TestFuncCode.iBRK, var);
   566 	test_KErrNone(Device.ReadWord(ENonxip,ServerData[ENonxip].iCodeAreaAddr, &var));
   567 	test_Equal(TestFuncCode.iBRK, var);
   568 	test_KErrNone(Device.ReadWord(EXip,ServerData[EXip].iCodeAreaAddr+1023*sizeof(TInt), &var));
   569 	test_Equal(TestFuncCode.iBRK, var);
   570 	test_KErrNone(Device.ReadWord(ENonxip,ServerData[ENonxip].iCodeAreaAddr+1023*sizeof(TInt), &var));
   571 	test_Equal(TestFuncCode.iBRK, var);
   572 	}
   573 
   574 
   575 
   576 //Used in test 10 to keep the list of breakpoints
   577 class TBrks:public CBase //derived from CBase as we need data initialized to 0
   578 	{
   579 public:	
   580 	TInt iCounter;				//Counts the number of the active brakpoints
   581 	TInt8 iBreakpoint[1025][2];		//0 - no breakpoint, 1-breakpoint set in CodeArea of XIP Server & NON-XIP server
   582 	};
   583 
   584 //Performs a random stress test on breakpoint pool.
   585 //There are 1025*2 words in CodeArea in xip and non-xip server.
   586 //A word is randomly picked up to set or clear 4 bytes long breakpoint.
   587 void Test10()
   588 	{
   589 	TInt i,index,whichServer,var;
   590 	TBrks* brks = new TBrks;
   591 	test((TInt)brks);//fail if no memory
   592 	TUint iSeed[2];
   593 	iSeed[0]=User::TickCount();
   594 	iSeed[1]=0;
   595 	test.Printf(_L("Test10 iSeed=%x\n"), iSeed[0]);
   596 
   597 	test_KErrNone(Device.InitialiseCodeModifier(2050));//enought to replace all BRK instructions in CodeArea with NOPs in both servers
   598 
   599 	for (i=0; i<1000;i++)
   600 		{
   601 		index=Random(iSeed)%2050;
   602 		whichServer = index>1024 ? 1 : 0;
   603 		if (index >1024)
   604 			index-=1025;
   605 		
   606 		TInt8& brk = brks->iBreakpoint[index][whichServer];
   607 		 if (brk)
   608 		 	{//Remove breakpoint
   609 		 	brk = 0;
   610 			test_KErrNone(Device.RestoreCode(whichServer, ServerData[whichServer].iCodeAreaAddr+index*sizeof(TInt)));
   611 			brks->iCounter--;
   612 		 	}
   613 		 else
   614 		 	{//Set breakpoint
   615 		 	brk = 1;
   616 			test_KErrNone(Device.WriteCode(whichServer, ServerData[whichServer].iCodeAreaAddr+index*sizeof(TInt),TestFuncCode.iNOP, /*size*/4));
   617 			brks->iCounter++;	 	
   618 		 	}
   619 		}
   620 	
   621 	test.Printf(_L("Breakpoints left:%d\n"), brks->iCounter);
   622 
   623 	//Check the content of the CodeArea in both XIP and Non-XIP Server
   624 	for (i=0; i<2050;i++)
   625 		{
   626 		whichServer = i>1024 ? 1 : 0;
   627 		if (i<=1024)index = i;
   628 		else		index = i-1025;
   629 
   630 		test_KErrNone(Device.ReadWord(whichServer,ServerData[whichServer].iCodeAreaAddr+index*sizeof(TInt), &var));
   631 		if(brks->iBreakpoint[index][whichServer])
   632 			test(var == TestFuncCode.iNOP); //Well, breakpoint is actually NOP ...
   633 		else
   634 			test(var == TestFuncCode.iBRK); //... while the original content is BRK instruction
   635 		}
   636 
   637 	//Now, apply breakpoints on all remaining addresses
   638 	for (i=0; i<2050;i++)
   639 		{
   640 		whichServer = i>1024 ? 1 : 0;
   641 		if (i<=1024)index = i;
   642 		else		index = i-1025;
   643 
   644 		if(!brks->iBreakpoint[index][whichServer])
   645 			test_KErrNone(Device.WriteCode(whichServer, ServerData[whichServer].iCodeAreaAddr+index*sizeof(TInt),TestFuncCode.iNOP, /*size*/4));
   646 		}
   647 
   648 	//All BRKs are replaced with NOPs in CodeArea function in both Servers. It should be safe to call the function.
   649 	test_KErrNone(RCodeModifierSession::RunCodeAreaFunc(EXip));
   650 	test_KErrNone(RCodeModifierSession::GetServerInfo(EXip));//This will check the server is still alive
   651 	test_KErrNone(RCodeModifierSession::RunCodeAreaFunc(ENonxip));
   652 	test_KErrNone(RCodeModifierSession::GetServerInfo(ENonxip));//This will check the server is still alive
   653 
   654 	test_KErrNone(Device.CloseCodeModifier()); //This will also remove all breakpoints
   655 	delete brks;
   656 	}
   657 
   658 //Tests out-of-breakpoints scenario
   659 void Test11(TInt aServer)
   660 	{
   661 	test.Printf(_L("Test11 %d\n"), aServer);
   662 	test_KErrNone(Device.InitialiseCodeModifier(10));
   663 
   664 	test_KErrNone(Device.WriteCode(aServer, ServerData[aServer].iCodeAreaAddr+4, /*aValue*/0, /*size*/4));
   665 
   666 	//4 bytes breakpoint
   667 	test_KErrNone(Device.WriteCode(aServer, ServerData[aServer].iCodeAreaAddr, /*aValue*/0, /*size*/4));
   668 	test_Equal(KErrAccessDenied, Device.WriteCode(aServer, ServerData[aServer].iCodeAreaAddr, /*aValue*/0, /*size*/2));
   669 	test_Equal(KErrAccessDenied, Device.WriteCode(aServer, ServerData[aServer].iCodeAreaAddr+2, /*aValue*/0, /*size*/2));
   670 	test_Equal(KErrAccessDenied, Device.WriteCode(aServer, ServerData[aServer].iCodeAreaAddr, /*aValue*/0, /*size*/1));
   671 	test_Equal(KErrAccessDenied, Device.WriteCode(aServer, ServerData[aServer].iCodeAreaAddr+1, /*aValue*/0, /*size*/1));
   672 	test_Equal(KErrAccessDenied, Device.WriteCode(aServer, ServerData[aServer].iCodeAreaAddr+2, /*aValue*/0, /*size*/1));
   673 	test_Equal(KErrAccessDenied, Device.WriteCode(aServer, ServerData[aServer].iCodeAreaAddr+3, /*aValue*/0, /*size*/1));
   674 	test_KErrNone(Device.RestoreCode(aServer, ServerData[aServer].iCodeAreaAddr));
   675 
   676 	//2 bytes breakpoint aligned to word
   677 	test_KErrNone(Device.WriteCode(aServer, ServerData[aServer].iCodeAreaAddr, /*aValue*/0, /*size*/2));
   678 	test_Equal(KErrAccessDenied, Device.WriteCode(aServer, ServerData[aServer].iCodeAreaAddr, /*aValue*/0, /*size*/4));
   679 	test_Equal(KErrAccessDenied, Device.WriteCode(aServer, ServerData[aServer].iCodeAreaAddr, /*aValue*/0, /*size*/1));
   680 	test_Equal(KErrAccessDenied, Device.WriteCode(aServer, ServerData[aServer].iCodeAreaAddr+1, /*aValue*/0, /*size*/1));
   681 	test_KErrNone(Device.WriteCode(aServer, ServerData[aServer].iCodeAreaAddr+2, /*aValue*/0, /*size*/2));
   682 	test_KErrNone(Device.RestoreCode(aServer, ServerData[aServer].iCodeAreaAddr));
   683 	test_KErrNone(Device.RestoreCode(aServer, ServerData[aServer].iCodeAreaAddr+2));
   684 
   685 	//2 bytes breakpoint aligned to word+2
   686 	test_KErrNone(Device.WriteCode(aServer, ServerData[aServer].iCodeAreaAddr+2, /*aValue*/0, /*size*/2));
   687 	test_Equal(KErrAccessDenied, Device.WriteCode(aServer, ServerData[aServer].iCodeAreaAddr, /*aValue*/0, /*size*/4));
   688 	test_Equal(KErrAccessDenied, Device.WriteCode(aServer, ServerData[aServer].iCodeAreaAddr+2, /*aValue*/0, /*size*/1));
   689 	test_Equal(KErrAccessDenied, Device.WriteCode(aServer, ServerData[aServer].iCodeAreaAddr+3, /*aValue*/0, /*size*/1));
   690 	test_KErrNone(Device.WriteCode(aServer, ServerData[aServer].iCodeAreaAddr, /*aValue*/0, /*size*/2));
   691 	test_KErrNone(Device.RestoreCode(aServer, ServerData[aServer].iCodeAreaAddr));
   692 	test_KErrNone(Device.RestoreCode(aServer, ServerData[aServer].iCodeAreaAddr+2));
   693 
   694 	//1 byte breakpoint
   695 	test_KErrNone(Device.WriteCode(aServer, ServerData[aServer].iCodeAreaAddr, /*aValue*/0, /*size*/1));
   696 	test_Equal(KErrAccessDenied, Device.WriteCode(aServer, ServerData[aServer].iCodeAreaAddr, /*aValue*/0, /*size*/4));
   697 	test_Equal(KErrAccessDenied, Device.WriteCode(aServer, ServerData[aServer].iCodeAreaAddr, /*aValue*/0, /*size*/2));
   698 	test_KErrNone(Device.WriteCode(aServer, ServerData[aServer].iCodeAreaAddr+1, /*aValue*/0, /*size*/1));
   699 	test_KErrNone(Device.WriteCode(aServer, ServerData[aServer].iCodeAreaAddr+2, /*aValue*/0, /*size*/1));
   700 	test_KErrNone(Device.WriteCode(aServer, ServerData[aServer].iCodeAreaAddr+3, /*aValue*/0, /*size*/1));
   701 	test_KErrNone(Device.RestoreCode(aServer, ServerData[aServer].iCodeAreaAddr));
   702 	test_KErrNone(Device.RestoreCode(aServer, ServerData[aServer].iCodeAreaAddr+1));
   703 	test_KErrNone(Device.RestoreCode(aServer, ServerData[aServer].iCodeAreaAddr+2));
   704 	test_KErrNone(Device.RestoreCode(aServer, ServerData[aServer].iCodeAreaAddr+3));
   705 
   706 	test_KErrNone(Device.CloseCodeModifier());
   707 	}
   708 
   709 
   710 void ClientAppL()
   711 	{
   712 	test.Start(_L("ClientAppL"));
   713 	UpdateClientsGlobals();
   714 	StartDriver();	
   715 	StartAndUpdate(EXip);
   716 	StartAndUpdate(ENonxip);
   717 	
   718 // All tests run with the following pre-conditions:
   719 // - both XIP and nonXIP server are running.
   720 // - device driver has updated servers' threadIDs (used for setting breakpoints and reading/writing data).
   721 // - all global variables (ServerData, TestFuncCode)are valid.
   722 // - CodeModifier is not installed.
   723 	Test1();
   724 	Test2(EXip);
   725 	Test2(ENonxip);
   726 	Test3(EXip);
   727 	Test3(ENonxip);
   728 	Test4(EXip);
   729 	Test4(ENonxip);
   730 	Test5(EXip);
   731 	Test6(EXip);
   732 	Test7(EXip);
   733 	Test8(EXip);
   734 	Test9();
   735 	Test10();
   736 	Test11(EXip);
   737 	Test11(ENonxip);
   738 	TerminateServer(EXip);
   739 	TerminateServer(ENonxip);
   740 	StopDriver();	
   741 	test.End();
   742 	}
   743 
   744 /**Entry point for both client and server apps*/
   745 TInt E32Main()
   746 	{
   747 	//Chech if we are client, XIP server or nonXIP server
   748 	TBuf<64> c;
   749 	User::CommandLine(c);
   750 	if (c.FindF(KServerXIP) >= 0) 
   751 		return ServerEntryPoint(EXip);
   752 	if (c.FindF(KServerNONXIP) >= 0) 
   753 		return ServerEntryPoint(ENonxip);
   754 	
   755 	// client
   756 	CTrapCleanup* trap = CTrapCleanup::New();
   757 	if (!trap)
   758 		return KErrNoMemory;
   759 	test.Title();
   760 	__UHEAP_MARK;
   761 	TRAPD(r,ClientAppL());
   762 	__UHEAP_MARKEND;
   763 	delete trap;
   764 	return r;
   765 	}