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