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