201033
authorhgs
Fri, 27 Aug 2010 11:37:29 +0300
changeset 42 0ff24a8f6ca2
parent 41 838cdffd57ce
child 50 827f48a8fbdf
child 51 98307c651589
201033
debugsrv/runmodedebug/build.config.xml
debugsrv/runmodedebug/group/bld.inf
debugsrv/runmodedebug/rmdebug_test/eabi/t_rmdebug_dllu.def
debugsrv/runmodedebug/rmdebug_test/group/bld.inf
debugsrv/runmodedebug/rmdebug_test/group/e32test.bld
debugsrv/runmodedebug/rmdebug_test/group/mk_rmdbg_test.bat
debugsrv/runmodedebug/rmdebug_test/rm_debug/basic_tests/r_kernel_low_memory_security_svr_session.cpp
debugsrv/runmodedebug/rmdebug_test/rm_debug/basic_tests/r_kernel_low_memory_security_svr_session.h
debugsrv/runmodedebug/rmdebug_test/rm_debug/basic_tests/r_low_memory_security_svr_session.cpp
debugsrv/runmodedebug/rmdebug_test/rm_debug/basic_tests/r_low_memory_security_svr_session.h
debugsrv/runmodedebug/rmdebug_test/rm_debug/basic_tests/r_user_low_memory_security_svr_session.cpp
debugsrv/runmodedebug/rmdebug_test/rm_debug/basic_tests/r_user_low_memory_security_svr_session.h
debugsrv/runmodedebug/rmdebug_test/rm_debug/basic_tests/t_rmdebug2.cpp
debugsrv/runmodedebug/rmdebug_test/rm_debug/basic_tests/t_rmdebug2.h
debugsrv/runmodedebug/rmdebug_test/rm_debug/basic_tests/t_rmdebug2_oemtoken.cpp
debugsrv/runmodedebug/rmdebug_test/rm_debug/common/t_debug_logging.h
debugsrv/runmodedebug/rmdebug_test/rm_debug/common/t_target_launcher.cpp
debugsrv/runmodedebug/rmdebug_test/rm_debug/common/t_target_launcher.h
debugsrv/runmodedebug/rmdebug_test/rm_debug/debug_targets/d_demand_paging.cia
debugsrv/runmodedebug/rmdebug_test/rm_debug/debug_targets/d_demand_paging.h
debugsrv/runmodedebug/rmdebug_test/rm_debug/debug_targets/d_rmdebug_bkpt_test.h
debugsrv/runmodedebug/rmdebug_test/rm_debug/debug_targets/d_rmdebug_bkpt_test.s
debugsrv/runmodedebug/rmdebug_test/rm_debug/debug_targets/d_rmdebug_step_test.h
debugsrv/runmodedebug/rmdebug_test/rm_debug/debug_targets/d_rmdebug_step_test.s
debugsrv/runmodedebug/rmdebug_test/rm_debug/debug_targets/d_rmdebug_step_test_armv4.h
debugsrv/runmodedebug/rmdebug_test/rm_debug/debug_targets/d_rmdebug_step_test_armv4.s
debugsrv/runmodedebug/rmdebug_test/rm_debug/debug_targets/d_rmdebugthread.cpp
debugsrv/runmodedebug/rmdebug_test/rm_debug/debug_targets/d_rmdebugthread.h
debugsrv/runmodedebug/rmdebug_test/rm_debug/debug_targets/d_rmdebugthread2.cpp
debugsrv/runmodedebug/rmdebug_test/rm_debug/debug_targets/d_rmdebugthread2.h
debugsrv/runmodedebug/rmdebug_test/rm_debug/debug_targets/d_rmdebugthreadasm.cia
debugsrv/runmodedebug/rmdebug_test/rm_debug/debug_targets/d_rmdebugthreadasm2.cia
debugsrv/runmodedebug/rmdebug_test/rm_debug/debug_targets/t_rmdebug_app.cpp
debugsrv/runmodedebug/rmdebug_test/rm_debug/debug_targets/t_rmdebug_app.h
debugsrv/runmodedebug/rmdebug_test/rm_debug/debug_targets/t_rmdebug_dll.cpp
debugsrv/runmodedebug/rmdebug_test/rm_debug/debug_targets/t_rmdebug_dll.h
debugsrv/runmodedebug/rmdebug_test/rm_debug/debug_targets/t_rmdebug_security.cpp
debugsrv/runmodedebug/rmdebug_test/rm_debug/debug_targets/t_rmdebug_security.h
debugsrv/runmodedebug/rmdebug_test/rm_debug/group/bld.inf
debugsrv/runmodedebug/rmdebug_test/rm_debug/group/mytraces_rm_debug.txt
debugsrv/runmodedebug/rmdebug_test/rm_debug/group/mytraces_rm_debug_ekern.txt
debugsrv/runmodedebug/rmdebug_test/rm_debug/group/rmdbg_test.pkg
debugsrv/runmodedebug/rmdebug_test/rm_debug/group/rmdebug.iby
debugsrv/runmodedebug/rmdebug_test/rm_debug/group/t_multi_agent_launcher.mmp
debugsrv/runmodedebug/rmdebug_test/rm_debug/group/t_performance_test.mmp
debugsrv/runmodedebug/rmdebug_test/rm_debug/group/t_rmdebug.iby
debugsrv/runmodedebug/rmdebug_test/rm_debug/group/t_rmdebug.mmp
debugsrv/runmodedebug/rmdebug_test/rm_debug/group/t_rmdebug2.mmh
debugsrv/runmodedebug/rmdebug_test/rm_debug/group/t_rmdebug2.mmp
debugsrv/runmodedebug/rmdebug_test/rm_debug/group/t_rmdebug2_allcaps.mmp
debugsrv/runmodedebug/rmdebug_test/rm_debug/group/t_rmdebug2_allcapstoken.mmp
debugsrv/runmodedebug/rmdebug_test/rm_debug/group/t_rmdebug2_oem.mmp
debugsrv/runmodedebug/rmdebug_test/rm_debug/group/t_rmdebug2_oem2.mmp
debugsrv/runmodedebug/rmdebug_test/rm_debug/group/t_rmdebug2_oemtoken.mmp
debugsrv/runmodedebug/rmdebug_test/rm_debug/group/t_rmdebug2_oemtoken2.mmp
debugsrv/runmodedebug/rmdebug_test/rm_debug/group/t_rmdebug_app.mmp
debugsrv/runmodedebug/rmdebug_test/rm_debug/group/t_rmdebug_app1.mmp
debugsrv/runmodedebug/rmdebug_test/rm_debug/group/t_rmdebug_app10.mmp
debugsrv/runmodedebug/rmdebug_test/rm_debug/group/t_rmdebug_app2.mmp
debugsrv/runmodedebug/rmdebug_test/rm_debug/group/t_rmdebug_app3.mmp
debugsrv/runmodedebug/rmdebug_test/rm_debug/group/t_rmdebug_app4.mmp
debugsrv/runmodedebug/rmdebug_test/rm_debug/group/t_rmdebug_app5.mmp
debugsrv/runmodedebug/rmdebug_test/rm_debug/group/t_rmdebug_app6.mmp
debugsrv/runmodedebug/rmdebug_test/rm_debug/group/t_rmdebug_app7.mmp
debugsrv/runmodedebug/rmdebug_test/rm_debug/group/t_rmdebug_app8.mmp
debugsrv/runmodedebug/rmdebug_test/rm_debug/group/t_rmdebug_app9.mmp
debugsrv/runmodedebug/rmdebug_test/rm_debug/group/t_rmdebug_dll.mmp
debugsrv/runmodedebug/rmdebug_test/rm_debug/group/t_rmdebug_multi_agent.mmp
debugsrv/runmodedebug/rmdebug_test/rm_debug/group/t_rmdebug_multi_target.mmp
debugsrv/runmodedebug/rmdebug_test/rm_debug/group/t_rmdebug_performance_allcapstoken.mmp
debugsrv/runmodedebug/rmdebug_test/rm_debug/group/t_rmdebug_security0.mmp
debugsrv/runmodedebug/rmdebug_test/rm_debug/group/t_rmdebug_security1.mmp
debugsrv/runmodedebug/rmdebug_test/rm_debug/group/t_rmdebug_security2.mmp
debugsrv/runmodedebug/rmdebug_test/rm_debug/group/t_rmdebug_security3.mmp
debugsrv/runmodedebug/rmdebug_test/rm_debug/group/t_rmdebug_target_launcher.mmp
debugsrv/runmodedebug/rmdebug_test/rm_debug/group/t_rmdebug_tests.iby
debugsrv/runmodedebug/rmdebug_test/rm_debug/multi_agent_tests/t_agent_eventhandler.cpp
debugsrv/runmodedebug/rmdebug_test/rm_debug/multi_agent_tests/t_agent_eventhandler.h
debugsrv/runmodedebug/rmdebug_test/rm_debug/multi_agent_tests/t_multi_agent.cpp
debugsrv/runmodedebug/rmdebug_test/rm_debug/multi_agent_tests/t_multi_agent.h
debugsrv/runmodedebug/rmdebug_test/rm_debug/multi_agent_tests/t_multi_agent_launcher.cpp
debugsrv/runmodedebug/rmdebug_test/rm_debug/multi_agent_tests/t_multi_agent_launcher.h
debugsrv/runmodedebug/rmdebug_test/rm_debug/multi_target_tests/t_multi_target.cpp
debugsrv/runmodedebug/rmdebug_test/rm_debug/multi_target_tests/t_multi_target.h
debugsrv/runmodedebug/rmdebug_test/rm_debug/performance_test/t_rmdebug_performance_oemtoken.cpp
debugsrv/runmodedebug/rmdebug_test/rm_debug/performance_test/t_rmdebug_performance_test.cpp
debugsrv/runmodedebug/rmdebug_test/rm_debug/performance_test/t_rmdebug_performance_test.h
debugsrv/runmodedebug/rmdebug_test/rm_debug/scripts/tef_execute_rtests.script
debugsrv/runmodedebug/rmdriver/group/bld.inf
debugsrv/runmodedebug/rmdriver/group/rm_debug_kerneldriver.mmh
debugsrv/runmodedebug/rmdriver/group/rm_debug_kerneldriver.mmp
debugsrv/runmodedebug/rmdriver/group/rm_debug_svr.iby
debugsrv/runmodedebug/rmdriver/group/sis/eula.txt
debugsrv/runmodedebug/rmdriver/group/sis/mk_rmdbg.bat
debugsrv/runmodedebug/rmdriver/group/sis/rmdbg.pkg
debugsrv/runmodedebug/rmdriver/inc/d_debug_agent.h
debugsrv/runmodedebug/rmdriver/inc/d_debug_agent.inl
debugsrv/runmodedebug/rmdriver/inc/d_debug_functionality.h
debugsrv/runmodedebug/rmdriver/inc/d_driver_event_info.h
debugsrv/runmodedebug/rmdriver/inc/d_list_manager.h
debugsrv/runmodedebug/rmdriver/inc/d_process_tracker.h
debugsrv/runmodedebug/rmdriver/inc/d_rmd_breakpoints.h
debugsrv/runmodedebug/rmdriver/inc/d_rmd_breakpoints_debug.inl
debugsrv/runmodedebug/rmdriver/inc/d_rmd_stepping.h
debugsrv/runmodedebug/rmdriver/inc/d_rmd_stepping.inl
debugsrv/runmodedebug/rmdriver/inc/d_target_process.h
debugsrv/runmodedebug/rmdriver/inc/debug_logging.h
debugsrv/runmodedebug/rmdriver/inc/debug_utils.h
debugsrv/runmodedebug/rmdriver/inc/rm_debug_driver.h
debugsrv/runmodedebug/rmdriver/inc/rm_debug_eventhandler.h
debugsrv/runmodedebug/rmdriver/inc/rm_debug_kerneldriver.h
debugsrv/runmodedebug/rmdriver/src/d_debug_agent.cpp
debugsrv/runmodedebug/rmdriver/src/d_debug_functionality.cpp
debugsrv/runmodedebug/rmdriver/src/d_driver_event_info.cpp
debugsrv/runmodedebug/rmdriver/src/d_list_manager.cpp
debugsrv/runmodedebug/rmdriver/src/d_process_tracker.cpp
debugsrv/runmodedebug/rmdriver/src/d_rmd_breakpoints.cpp
debugsrv/runmodedebug/rmdriver/src/d_rmd_stepping.cpp
debugsrv/runmodedebug/rmdriver/src/d_target_process.cpp
debugsrv/runmodedebug/rmdriver/src/debug_utils.cpp
debugsrv/runmodedebug/rmdriver/src/rm_debug_eventhandler.cpp
debugsrv/runmodedebug/rmdriver/src/rm_debug_kerneldriver.cpp
debugsrv/runmodedebug/securityserver/group/rm_debug_svr.mmp
debugsrv/runmodedebug/securityserver/inc/c_process_pair.h
debugsrv/runmodedebug/securityserver/inc/c_security_svr_async.h
debugsrv/runmodedebug/securityserver/inc/c_security_svr_server.h
debugsrv/runmodedebug/securityserver/inc/c_security_svr_session.h
debugsrv/runmodedebug/securityserver/inc/c_shutdown_timer.h
debugsrv/runmodedebug/securityserver/inc/low_mem_requests.h
debugsrv/runmodedebug/securityserver/inc/rm_debug_api.h
debugsrv/runmodedebug/securityserver/inc/rm_debug_logging.h
debugsrv/runmodedebug/securityserver/src/c_process_pair.cpp
debugsrv/runmodedebug/securityserver/src/c_security_svr_async.cpp
debugsrv/runmodedebug/securityserver/src/c_security_svr_server.cpp
debugsrv/runmodedebug/securityserver/src/c_security_svr_session.cpp
debugsrv/runmodedebug/securityserver/src/c_shutdown_timer.cpp
debugsrv/runmodedebug/securityserver/src/rm_debug_svr.cpp
layers.sysdef.xml
piprofiler/group/ReleaseNotes_PIProfiler.txt
piprofiler/group/bld.inf
piprofiler/plugins/GeneralsPlugin/src/GppSamplerImpl.cpp
piprofiler/plugins/PWRplugin/data/2001E5B9.rss
piprofiler/plugins/PWRplugin/group/PWRPlugin.mmp
piprofiler/plugins/PWRplugin/group/bld.inf
piprofiler/plugins/PWRplugin/inc/PwrPlugin.h
piprofiler/plugins/PWRplugin/sis/PWRPlugin.pkg
piprofiler/plugins/PWRplugin/src/PwrPlugin.cpp
piprofiler/plugins/PWRplugin/src/PwrPluginImplementationTable.cpp
piprofiler/rom/piprofiler.iby
piprofiler/rom/piprofiler_s2.iby
piprofiler/symbian_version.hrh
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/debugsrv/runmodedebug/build.config.xml	Fri Aug 27 11:37:29 2010 +0300
@@ -0,0 +1,109 @@
+<?xml version="1.0"?>
+<!DOCTYPE SystemDefinition [
+ <!ELEMENT SystemDefinition (systemModel?, build?)>
+ <!ATTLIST SystemDefinition
+  name CDATA #REQUIRED
+  schema CDATA #REQUIRED>
+ <!ELEMENT systemModel (layer+)>
+ <!ELEMENT layer (logicalset* | module*)*>
+ <!ATTLIST layer
+  name CDATA #REQUIRED
+  levels CDATA #IMPLIED
+  span CDATA #IMPLIED>
+ <!ELEMENT logicalset (logicalsubset* | module* | unit* | package* | prebuilt*)*>
+ <!ATTLIST logicalset 
+  name CDATA #REQUIRED
+  levels CDATA #IMPLIED  
+  span CDATA #IMPLIED
+  level CDATA #IMPLIED>
+ <!ELEMENT logicalsubset (module* | unit* | package* | prebuilt*)*>
+ <!ATTLIST logicalsubset name CDATA #REQUIRED>
+ <!ELEMENT module (component* | unit* | package* | prebuilt*)*>
+ <!ATTLIST module
+  name CDATA #REQUIRED
+  level CDATA #IMPLIED>
+ <!ELEMENT component (unit* | package* | prebuilt*)*>
+ <!ATTLIST component name CDATA #REQUIRED>
+ <!ELEMENT unit EMPTY>
+ <!ATTLIST unit
+  unitID ID #REQUIRED
+  name CDATA #REQUIRED
+  mrp CDATA #REQUIRED
+  filter CDATA #IMPLIED
+  bldFile CDATA #REQUIRED
+  priority CDATA #IMPLIED
+  contract CDATA #IMPLIED>
+ <!ELEMENT package EMPTY>
+ <!ATTLIST package
+  name CDATA #REQUIRED
+  mrp CDATA #REQUIRED
+  filter CDATA #IMPLIED
+  contract CDATA #IMPLIED>
+ <!ELEMENT prebuilt EMPTY>
+ <!ATTLIST prebuilt
+  name CDATA #REQUIRED
+  version CDATA #REQUIRED
+  late (Y|N) #IMPLIED
+  filter CDATA #IMPLIED
+  contract CDATA #IMPLIED>
+ <!ELEMENT build (option* | target+ | targetList+ | unitList+ | configuration+)*>
+ <!ELEMENT unitList (unitRef+)>
+ <!ATTLIST unitList
+  name ID #REQUIRED
+  description CDATA #REQUIRED>
+ <!ELEMENT unitRef EMPTY>
+ <!ATTLIST unitRef unit IDREF #REQUIRED>
+ <!ELEMENT targetList EMPTY>
+ <!ATTLIST targetList
+  name ID #REQUIRED
+  description CDATA #REQUIRED
+  target IDREFS #REQUIRED>
+ <!ELEMENT target EMPTY>
+ <!ATTLIST target
+  name ID #REQUIRED
+  abldTarget CDATA #REQUIRED
+  description CDATA #REQUIRED>
+ <!ELEMENT option EMPTY>
+ <!ATTLIST option
+  name ID #REQUIRED
+  abldOption CDATA #REQUIRED
+  description CDATA #REQUIRED
+  enable (Y | N | y | n) #REQUIRED>
+ <!ELEMENT configuration (unitListRef+ | layerRef+ | task+)*>
+ <!ATTLIST configuration
+  name ID #REQUIRED
+  description CDATA #REQUIRED
+  filter CDATA #REQUIRED> 
+ <!ELEMENT task ( unitListRef* , (buildLayer | specialInstructions))>
+ <!ELEMENT unitListRef EMPTY>
+ <!ATTLIST unitListRef unitList IDREF #REQUIRED>
+ <!ELEMENT layerRef EMPTY>
+ <!ATTLIST layerRef layerName CDATA #REQUIRED>
+ <!ELEMENT buildLayer EMPTY>
+ <!ATTLIST buildLayer
+  command CDATA #REQUIRED
+  targetList IDREFS #IMPLIED
+  unitParallel (Y | N | y | n) #REQUIRED
+  targetParallel (Y | N | y | n) #IMPLIED>
+ <!ELEMENT specialInstructions EMPTY>
+ <!ATTLIST specialInstructions
+  name CDATA #REQUIRED
+  cwd CDATA #REQUIRED
+  command CDATA #REQUIRED>
+ <!ENTITY layer_real_source_path "sf/dev/devicedbgsrvs/dbgsrv/coredumpserver/rmdebug" >
+]>
+
+<SystemDefinition name="rmdebug" schema="1.4.0">
+  <systemModel>
+    <layer name="os_layer">
+      <module name="RunMode">
+		  <unit name="RunModeComp" unitID="RunMode.Comp" mrp="" bldFile="&layer_real_source_path;/group"/>
+      </module>
+    </layer>
+	<layer name="api_test_layer">
+      <module name="RunMode_test">
+         <unit name="RunModeComp_Test" unitID="RunMode.Comp_test" mrp="" bldFile="&layer_real_source_path;/group"/>
+      </module>
+    </layer>
+  </systemModel>
+</SystemDefinition>
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/debugsrv/runmodedebug/group/bld.inf	Fri Aug 27 11:37:29 2010 +0300
@@ -0,0 +1,25 @@
+// Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+// Run mode component and test top level bld.inf
+// 
+//
+
+/**
+ @file
+*/
+
+#include "../rmdriver/group/bld.inf"
+
+
+#include "../rmdebug_test/group/bld.inf"
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/debugsrv/runmodedebug/rmdebug_test/eabi/t_rmdebug_dllu.def	Fri Aug 27 11:37:29 2010 +0300
@@ -0,0 +1,3 @@
+EXPORTS
+	_Z9GetDSSUidv @ 1 NONAME
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/debugsrv/runmodedebug/rmdebug_test/group/bld.inf	Fri Aug 27 11:37:29 2010 +0300
@@ -0,0 +1,22 @@
+// Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+// Kernel and User library test code
+// 
+//
+
+/**
+ @file
+*/
+
+#include "../rm_debug/group/bld.inf"
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/debugsrv/runmodedebug/rmdebug_test/group/e32test.bld	Fri Aug 27 11:37:29 2010 +0300
@@ -0,0 +1,5 @@
+
+!EXPLICIT
+!INCREMENTAL
+
+e32test		e32test\group
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/debugsrv/runmodedebug/rmdebug_test/group/mk_rmdbg_test.bat	Fri Aug 27 11:37:29 2010 +0300
@@ -0,0 +1,18 @@
+@rem
+@rem Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+@rem All rights reserved.
+@rem This component and the accompanying materials are made available
+@rem under the terms of "Eclipse Public License v1.0"
+@rem which accompanies this distribution, and is available
+@rem at the URL "http://www.eclipse.org/legal/epl-v10.html".
+@rem
+@rem Initial Contributors:
+@rem Nokia Corporation - initial contribution.
+@rem
+@rem Contributors:
+@rem
+@rem Description: 
+@rem
+
+makesis rmdbg_test.pkg
+signsis rmdbg_test.sis rmdbg_test.sisx  RDTest_02.der RDTest_02.key
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/debugsrv/runmodedebug/rmdebug_test/rm_debug/basic_tests/r_kernel_low_memory_security_svr_session.cpp	Fri Aug 27 11:37:29 2010 +0300
@@ -0,0 +1,39 @@
+// Copyright (c) 2007-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+// Implementation of RKernelLowMemorySecuritySvrSession
+// 
+//
+
+#include "r_kernel_low_memory_security_svr_session.h"
+
+void RKernelLowMemorySecuritySvrSession::FailAlloc(const TInt aCount)
+	{
+	__KHEAP_FAILNEXT(aCount);
+	}
+
+void RKernelLowMemorySecuritySvrSession::HeapReset()
+	{
+	__KHEAP_RESET;
+	}
+
+void RKernelLowMemorySecuritySvrSession::MarkHeap()
+	{
+	__KHEAP_MARK;
+	}
+
+void RKernelLowMemorySecuritySvrSession::MarkHeapEnd()
+	{
+	__KHEAP_MARKEND;
+	}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/debugsrv/runmodedebug/rmdebug_test/rm_debug/basic_tests/r_kernel_low_memory_security_svr_session.h	Fri Aug 27 11:37:29 2010 +0300
@@ -0,0 +1,39 @@
+// Copyright (c) 2007-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+// Version of security server session to enable testing of low memory conditions on kernel side
+// 
+//
+
+/**
+ @file
+ @internalTechnology
+ @released
+*/
+
+#ifndef R_KERNEL_LOW_MEMORY_SECURITY_SVR_SESSION_H
+#define R_KERNEL_LOW_MEMORY_SECURITY_SVR_SESSION_H
+
+#include "r_low_memory_security_svr_session.h"
+
+class RKernelLowMemorySecuritySvrSession : public RLowMemorySecuritySvrSession
+	{
+protected:
+	void FailAlloc(const TInt aCount);
+	void HeapReset();
+	void MarkHeap();
+	void MarkHeapEnd();
+	};
+
+#endif //R_KERNEL_LOW_MEMORY_SECURITY_SVR_SESSION_H
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/debugsrv/runmodedebug/rmdebug_test/rm_debug/basic_tests/r_low_memory_security_svr_session.cpp	Fri Aug 27 11:37:29 2010 +0300
@@ -0,0 +1,86 @@
+// Copyright (c) 2007-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+// Implementation of RLowMemorySecuritySvrSession
+// 
+//
+
+#include "r_low_memory_security_svr_session.h"
+#include <e32debug.h>
+
+// test the effects of heap failure on global RSecuritySvrSession::GetList() in debug mode,
+// in release mode normal call is made (heap checking not applicable)
+TInt RLowMemorySecuritySvrSession::GetList(const Debug::TListId aListId, TDes8& aListData, TUint32& aDataSize)
+	{
+	TInt failAt = 0;
+	TInt err = KErrNoMemory;
+	while(err == KErrNoMemory)
+		{
+		failAt++;
+		FailAlloc(failAt);
+		MarkHeap();
+		err = this->RSecuritySvrSession::GetList(aListId, aListData, aDataSize);
+		if(KErrNoMemory == err)
+			{
+			MarkHeapEnd();
+			}
+		HeapReset();
+		//RDebug::Printf("Debug::RLowMemorySecuritySvrSession::GetList(): failAt: %d, err: %d", failAt, err);
+		}
+	return err;
+	}
+
+// test the effects of heap failure on thread-specific RSecuritySvrSession::GetList() in debug mode,
+// in release mode normal call is made (heap checking not applicable)
+TInt RLowMemorySecuritySvrSession::GetList(const TThreadId aThreadId, const Debug::TListId aListId, TDes8& aListData, TUint32& aDataSize)
+	{
+	TInt failAt = 0;
+	TInt err = KErrNoMemory;
+	while(err == KErrNoMemory)
+		{
+		failAt++;
+		FailAlloc(failAt);
+		MarkHeap();
+		err = this->RSecuritySvrSession::GetList(aThreadId, aListId, aListData, aDataSize);
+		if(KErrNoMemory == err)
+			{
+			MarkHeapEnd();
+			}
+		HeapReset();
+		//RDebug::Printf("Debug::RLowMemorySecuritySvrSession::GetList(TThreadId): failAt: %d, err: %d", failAt, err);
+		}
+	return err;
+	}
+
+// test the effects of heap failure on process-specific RSecuritySvrSession::GetList() in debug mode,
+// in release mode normal call is made (heap checking not applicable)
+TInt RLowMemorySecuritySvrSession::GetList(const TProcessId aProcessId, const Debug::TListId aListId, TDes8& aListData, TUint32& aDataSize)
+	{
+	TInt failAt = 0;
+	TInt err = KErrNoMemory;
+	while(err == KErrNoMemory)
+		{
+		failAt++;
+		FailAlloc(failAt);
+		MarkHeap();
+		err = this->RSecuritySvrSession::GetList(aProcessId, aListId, aListData, aDataSize);
+		if(KErrNoMemory == err)
+			{
+			MarkHeapEnd();
+			}
+		HeapReset();
+		//RDebug::Printf("Debug::RLowMemorySecuritySvrSession::GetList(TProcessId): failAt: %d, err: %d", failAt, err);
+		}
+	return err;
+	}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/debugsrv/runmodedebug/rmdebug_test/rm_debug/basic_tests/r_low_memory_security_svr_session.h	Fri Aug 27 11:37:29 2010 +0300
@@ -0,0 +1,43 @@
+// Copyright (c) 2007-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+// Version of security server session to enable testing of low memory conditions
+// 
+//
+
+/**
+ @file
+ @internalTechnology
+ @released
+*/
+
+#ifndef R_LOW_MEMORY_SECURITY_SVR_SESSION_H
+#define R_LOW_MEMORY_SECURITY_SVR_SESSION_H
+
+#include <rm_debug_api.h>
+
+class RLowMemorySecuritySvrSession : public Debug::RSecuritySvrSession
+	{
+public:
+	TInt GetList(const Debug::TListId aListId, TDes8& aListData, TUint32& aDataSize);
+	TInt GetList(const TThreadId aThreadId, const Debug::TListId aListId, TDes8& aListData, TUint32& aDataSize);
+	TInt GetList(const TProcessId aProcessId, const Debug::TListId aListId, TDes8& aListData, TUint32& aDataSize);
+protected:
+	virtual void FailAlloc(const TInt aCount) = 0;
+	virtual void HeapReset() = 0;
+	virtual void MarkHeap() = 0;
+	virtual void MarkHeapEnd() = 0;
+	};
+
+#endif //R_LOW_MEMORY_SECURITY_SVR_SESSION_H
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/debugsrv/runmodedebug/rmdebug_test/rm_debug/basic_tests/r_user_low_memory_security_svr_session.cpp	Fri Aug 27 11:37:29 2010 +0300
@@ -0,0 +1,54 @@
+// Copyright (c) 2007-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+// r_kernel_low_memory_security_svr_session.cpp
+// Implementation of RUserLowMemorySecuritySvrSession
+// 
+//
+
+#include "r_user_low_memory_security_svr_session.h"
+#include <rm_debug_api.h>
+#ifdef _DEBUG
+#include "low_mem_requests.h"
+#endif
+
+void RUserLowMemorySecuritySvrSession::FailAlloc(const TInt aCount)
+	{
+#ifdef _DEBUG
+	TIpcArgs args(aCount);
+	SendReceive(EDebugServFailAlloc, args);
+#endif
+	}
+
+void RUserLowMemorySecuritySvrSession::HeapReset()
+	{
+#ifdef _DEBUG
+	TIpcArgs args(0);
+	SendReceive(EDebugServFailAlloc, args);
+#endif
+	}
+
+void RUserLowMemorySecuritySvrSession::MarkHeap()
+	{
+#ifdef _DEBUG
+	SendReceive(EDebugServMarkHeap);
+#endif
+	}
+
+void RUserLowMemorySecuritySvrSession::MarkHeapEnd()
+	{
+#ifdef _DEBUG
+	SendReceive(EDebugServMarkEnd);
+#endif
+	}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/debugsrv/runmodedebug/rmdebug_test/rm_debug/basic_tests/r_user_low_memory_security_svr_session.h	Fri Aug 27 11:37:29 2010 +0300
@@ -0,0 +1,39 @@
+// Copyright (c) 2007-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+// Version of security server session to enable testing of low memory conditions on user side
+// 
+//
+
+/**
+ @file
+ @internalTechnology
+ @released
+*/
+
+#ifndef R_USER_LOW_MEMORY_SECURITY_SVR_SESSION_H
+#define R_USER_LOW_MEMORY_SECURITY_SVR_SESSION_H
+
+#include "r_low_memory_security_svr_session.h"
+
+class RUserLowMemorySecuritySvrSession : public RLowMemorySecuritySvrSession
+	{
+protected:
+	void FailAlloc(const TInt aCount);
+	void HeapReset();
+	void MarkHeap();
+	void MarkHeapEnd();
+	};
+
+#endif //R_USER_LOW_MEMORY_SECURITY_SVR_SESSION_H
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/debugsrv/runmodedebug/rmdebug_test/rm_debug/basic_tests/t_rmdebug2.cpp	Fri Aug 27 11:37:29 2010 +0300
@@ -0,0 +1,4985 @@
+// Copyright (c) 2006-2010 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+// Tests the functionality of the run mode debug device driver.
+//
+//
+
+#include <e32base.h>
+#include <e32base_private.h>
+#include <e32cons.h>
+#include <e32test.h>
+#include <e32ldr.h>
+#include <e32cmn.h>
+#include <e32cmn_private.h>
+#include <f32dbg.h>
+#include <f32file.h>
+#include <hal.h>
+#include <u32hal.h>
+#include <e32property.h>
+
+#include "t_rmdebug_dll.h"
+
+#include <rm_debug_api.h>
+#include "d_rmdebugthread2.h"
+#include "t_rmdebug2.h"
+#include "t_rmdebug_app.h"
+
+#ifdef __MARM_ARMV4__
+#include "d_rmdebug_step_test_armv4.h"
+#endif
+
+#ifdef __MARM_ARMV5__
+#include "d_rmdebug_step_test.h"
+#include "d_rmdebug_bkpt_test.h"
+#endif
+
+#include "d_demand_paging.h"
+
+#ifdef KERNEL_OOM_TESTING
+	#ifdef USER_OOM_TESTING
+		#error "Cannot define both KERNEL_OOM_TESTING and USER_OOM_TESTING"
+	#endif
+#endif
+
+#if  defined (NO_DEBUGTOKEN)  || defined (SOMECAPS_DEBUGTOKEN) || defined (FEWCAPS_DEBUGTOKEN)
+_LIT8(KCrashDummyData, "This is a sample write");
+#endif
+
+using namespace Debug;
+
+const TVersion securityServerVersion(0,1,1);
+
+const TVersion testVersion(2,1,0);
+
+IMPORT_C TInt StartDebugThread(RThread& aServerThread, const TDesC& aDebugThreadName);
+ 
+extern TInt TestData;
+extern TTestFunction FunctionChooser;
+extern TBuf8<SYMBIAN_RMDBG_MEMORYSIZE> gMemoryAccessBytes;
+
+IMPORT_C TInt TestFunction();
+IMPORT_C void TestPagedCode();
+IMPORT_C extern TInt RMDebugDemandPagingTest();
+
+// Device driver name
+_LIT(KDebugDriverFileName,"rm_debug.ldd");
+_LIT(KRMDebugAppName, "t_rmdebug_app");
+
+
+#if defined(NO_DEBUGTOKEN)
+    _LIT(KTestName, "T_RMDEBUG2");
+#elif defined(SOMECAPS_DEBUGTOKEN)
+    _LIT(KTestName, "T_RMDEBUG2_OEM");
+#elif defined(FEWCAPS_DEBUGTOKEN)
+    _LIT(KTestName, "T_RMDEBUG2_OEM2");
+#elif defined(ALLCAPS_DEBUGTOKEN)
+    _LIT(KTestName, "T_RMDEBUG2_ALLCAPS");
+#endif
+
+#define TIMED_WAIT(request, timeoutInMs) CRunModeAgent::TimedWait(request, timeoutInMs, __LINE__)
+
+LOCAL_D RTest test(KTestName);
+
+TBool gUseDelay;
+
+CRunModeAgent::CRunModeAgent()
+//
+// CRunModeAgent constructor
+//
+	{
+	FillArray();
+	RProcess thisProcess;
+	iFileName = thisProcess.FileName();
+	thisProcess.Close();
+	}
+
+CRunModeAgent* CRunModeAgent::NewL()
+//
+// CRunModeAgent::NewL
+//
+	{
+	CRunModeAgent* self = new(ELeave) CRunModeAgent();
+
+  	self->ConstructL();
+
+	return self;
+	}
+
+CRunModeAgent::~CRunModeAgent()
+//
+// CRunModeAgent destructor
+//
+	{
+    iTimer.Close();
+    iRunCountSubscribe.Close();
+    
+	User::FreeLogicalDevice(KDebugDriverFileName);
+	iServSession.Close();
+	iDebugThread.Close();
+	}
+
+void CRunModeAgent::ConstructL()
+//
+// CRunModeAgent::ConstructL
+//
+	{
+	// nothing to do here
+	}
+
+void CRunModeAgent::SetupAndAttachToDSS()
+//
+// CRunModeAgent::SetupAndAttachToDSS
+//
+	{
+	TInt err = StartDebugThread(iDebugThread, KDebugThreadName);
+
+	// get the thread id for use in the tests
+	iThreadID = iDebugThread.Id();
+
+	if (err != KErrNone)
+		{
+		User::Panic(_L("Can't start debug thread"), err);
+		}
+
+    err = iRunCountSubscribe.Attach( RProcess().SecureId(), CDebugServThread::ERMDBGRunCountProperty);
+    if (err != KErrNone)
+        {
+        User::Panic(_L("Can't attach to RProperty iRunCountSubscribe"), err);
+        }
+
+    err = iTimer.CreateLocal(); 
+    if (err != KErrNone)
+        {
+        User::Panic(_L("Can't create RTimer::CreateLocal()"), err);
+        }
+    
+	err = iServSession.Connect(securityServerVersion);
+	if (err != KErrNone)
+		{
+		User::Panic(_L("Can't open server session"), err);
+		}
+	}
+
+CRunModeAgent *RunModeAgent;
+
+// helper function to check whether the listing of type aListId is supported for a scope of aListScope
+TBool CRunModeAgent::ListingSupported(const TListId aListId, const TListScope aListScope)
+	{
+	TTag tag = GetTag(ETagHeaderList, aListId);
+
+	return (tag.iValue) & aListScope;
+	}
+
+//---------------------------------------------
+//! @SYMTestCaseID KBase-T-RMDEBUG2-0426
+//! @SYMTestType
+//! @SYMPREQ PREQ1426
+//! @SYMTestCaseDesc Test getting the list of XIP libraries
+//! @SYMTestActions The XIP library list should be successfully obtained
+//! @SYMTestExpectedResults The specified ldd file should be present in the obtained listing
+//! @SYMTestPriority High
+//! @SYMTestStatus Implemented
+//---------------------------------------------
+void CRunModeAgent::TestGetXipLibrariesList()
+	{
+	test.Next(_L("TestGetXipLibrariesList\n"));
+
+	test(ListingSupported(EXipLibraries, EScopeGlobal));
+	test(!ListingSupported(EXipLibraries, EScopeProcessSpecific));
+	test(!ListingSupported(EXipLibraries, EScopeThreadSpecific));
+
+	//allocate a very small buffer so the GetList call initially fails
+	RBuf8 buffer;
+	test(KErrNone == buffer.Create(1));
+	TUint32 size = 0;
+
+	//get the list data
+	DoGetList(EXipLibraries, EScopeGlobal, buffer, size);
+
+	//search the buffer for entry corresponding to the debug kernel driver
+	//which should be in the rom
+	_LIT(KRmDebugLddName, "z:\\sys\\bin\\rm_debug.ldd");
+
+	//iterate through the buffer and set found to ETrue if we find the driver
+	TBool found = EFalse;
+	TUint8* ptr = (TUint8*)buffer.Ptr();
+	const TUint8* ptrEnd = ptr + size;
+	while(ptr < ptrEnd)
+		{
+		TXipLibraryListEntry& xipLibrary = *(TXipLibraryListEntry*)ptr;
+
+		//get the name of the library
+		TPtr name(&xipLibrary.iName[0], xipLibrary.iNameLength, xipLibrary.iNameLength);
+		if(name.CompareF(KRmDebugLddName()) == 0)
+			{
+			//found the library but continue reading the rest of the buffer to
+			//check nothing bad happens towards the end
+			found = ETrue;
+			}
+		//move pointer on to next library
+		ptr += Align4(xipLibrary.GetSize());
+		}
+	test(found);
+
+	//do cleanup
+	buffer.Close();
+	}
+
+//---------------------------------------------
+//! @SYMTestCaseID KBase-T-RMDEBUG2-0427
+//! @SYMTestType
+//! @SYMPREQ PREQ1426
+//! @SYMTestCaseDesc Test getting the list of executables
+//! @SYMTestActions The list of debuggable executable files should be obtained
+//! @SYMTestExpectedResults The client exe should appear in the list
+//! @SYMTestPriority High
+//! @SYMTestStatus Implemented
+//---------------------------------------------
+void CRunModeAgent::TestGetExecutablesList()
+	{
+	test.Next(_L("TestGetExecutablesList\n"));
+
+	test(ListingSupported(EExecutables, EScopeGlobal));
+	test(!ListingSupported(EExecutables, EScopeProcessSpecific));
+	test(!ListingSupported(EExecutables, EScopeThreadSpecific));
+
+	//allocate a very small buffer so the GetList call initially fails
+	RBuf8 buffer;
+	test(KErrNone == buffer.Create(1));
+	TUint32 size = 0;
+
+	test(KErrNone == iServSession.AttachExecutable(iFileName, EFalse));
+
+	//get the list data
+	DoGetList(EExecutables, EScopeGlobal, buffer, size);
+
+	//get this process' name
+	RProcess thisProcess;
+	TFileName thisProcessName = thisProcess.FileName();
+
+	//look through the buffer and check if the target debug thread is there
+	TBool found = EFalse;
+	TUint8* ptr = (TUint8*)buffer.Ptr();
+	const TUint8* ptrEnd = ptr + size;
+	while(ptr < ptrEnd)
+		{
+		TExecutablesListEntry& entry = *(TExecutablesListEntry*)ptr;
+		//get name
+		TPtr name(&entry.iName[0], entry.iNameLength, entry.iNameLength);
+		if( (entry.iIsActivelyDebugged != 0) && (0 == thisProcessName.CompareF(name)) )
+			{
+			//found this process and asserted it is being actively debugged
+			found = ETrue;
+			}
+		//move pointer on to next entry
+		ptr += Align4(entry.GetSize());
+		}
+	test(found);
+
+	//clean up
+	buffer.Close();
+
+	test(KErrNone == iServSession.DetachExecutable(iFileName));
+	}
+
+//---------------------------------------------
+//! @SYMTestCaseID KBase-T-RMDEBUG2-0428
+//! @SYMTestType
+//! @SYMPREQ PREQ1426
+//! @SYMTestCaseDesc Test error conditions for the GetList calls
+//! @SYMTestActions Multiple calls to test calling GetList with bad arguments
+//! @SYMTestExpectedResults All tests should fail with the appropriate error codes
+//! @SYMTestPriority High
+//! @SYMTestStatus Implemented
+//---------------------------------------------
+void CRunModeAgent::TestGetListInvalidData()
+	{
+	test.Next(_L("TestGetListInvalidData\n"));
+
+	//allocate a buffer, the size should not matter as expecting all calls to fail
+	RBuf8 buffer;
+	test(KErrNone == buffer.Create(1));
+	TUint32 size = 0;
+
+	//test what happens if we ask for an unsupported list type globally
+	test(KErrNotSupported == iServSession.GetList((TListId)1234, buffer, size));
+
+	//test what happens if we ask for an unsupported list type
+	test(KErrNotSupported == iServSession.GetList(RThread().Id(), (TListId)1234, buffer, size));
+
+	//test what happens if we try to get a non-global libraries list
+	test(KErrArgument == iServSession.GetList(RThread().Id(), EXipLibraries, buffer, size));
+
+	//test what happens if we try to get a non-global executables list
+	test(KErrArgument == iServSession.GetList(RThread().Id(), EExecutables, buffer, size));
+
+	//test what happens if we try to get a non-global process list
+	test(KErrArgument == iServSession.GetList(RThread().Id(), EProcesses, buffer, size));
+
+	//check that using a process id fails
+	test(KErrArgument == iServSession.GetList(RProcess().Id(), EProcesses, buffer, size));
+
+	//check that specifying a non-existant thread id fails
+	test(KErrArgument == iServSession.GetList((TThreadId)0x12345678, EThreads, buffer, size));
+
+	//check that specifying a non-existant process id fails
+	test(KErrArgument == iServSession.GetList((TProcessId)0x12345678, EThreads, buffer, size));
+
+	//check that specifying a non-existant thread id fails
+	test(KErrArgument == iServSession.GetList((TThreadId)0x12345678, ECodeSegs, buffer, size));
+
+	//check that specifying a non-existant process id fails
+	test(KErrArgument == iServSession.GetList((TProcessId)0x12345678, ECodeSegs, buffer, size));
+
+	//cleanup
+	buffer.Close();
+	}
+
+//---------------------------------------------
+//! @SYMTestCaseID KBase-T-RMDEBUG2-0429
+//! @SYMTestType
+//! @SYMPREQ PREQ1426
+//! @SYMTestCaseDesc Test getting the process list
+//! @SYMTestActions Get the process listing
+//! @SYMTestExpectedResults The process listing should be successfully obtained and the current process should be present in the list
+//! @SYMTestPriority High
+//! @SYMTestStatus Implemented
+//---------------------------------------------
+void CRunModeAgent::TestGetProcessList()
+	{
+	test.Next(_L("TestGetProcessList\n"));
+
+	test(ListingSupported(EProcesses, EScopeGlobal));
+	test(!ListingSupported(EProcesses, EScopeProcessSpecific));
+	test(!ListingSupported(EProcesses, EScopeThreadSpecific));
+
+	//allocate a very small buffer so the GetList call fails
+	RBuf8 buffer;
+	test(KErrNone == buffer.Create(1));
+	TUint32 size = 0;
+
+	//get the list data
+	DoGetList(EProcesses, EScopeGlobal, buffer, size);
+
+	//initialise data about the target debug thread to compare the kernel's data against
+	RProcess thisProcess;
+	TFileName thisProcessName = thisProcess.FileName();
+	TUint32 processId = thisProcess.Id().Id();
+
+	//look through the buffer and check if the target debug thread is there
+	TBool found = EFalse;
+	TUint8* ptr = (TUint8*)buffer.Ptr();
+	const TUint8* ptrEnd = ptr + size;
+	while(ptr < ptrEnd)
+		{
+		TProcessListEntry& entry = *(TProcessListEntry*)ptr;
+		if( (RProcess().Id().Id() == entry.iProcessId) &&
+			(0 == thisProcessName.CompareF(TPtr(&(entry.iNames[0]), entry.iFileNameLength, entry.iFileNameLength))) &&
+		 	(0 == thisProcess.FullName().CompareF(TPtr(&(entry.iNames[0]) + entry.iFileNameLength, entry.iDynamicNameLength, entry.iDynamicNameLength))) &&
+			0x4321bbbb /* Magic */ == entry.iUid3)
+			{
+			//if all match then we've found it
+			found = ETrue;
+			}
+		ptr += Align4(entry.GetSize());
+		}
+
+	//check whether the expected result happened
+	test(found);
+
+	//clean up
+	buffer.Close();
+	}
+
+//---------------------------------------------
+//! @SYMTestCaseID KBase-T-RMDEBUG2-0430
+//! @SYMTestType
+//! @SYMPREQ PREQ1426
+//! @SYMTestCaseDesc Test getting the thread list
+//! @SYMTestActions Get the thread listing globally and for a specified thread or process
+//! @SYMTestExpectedResults The thread listings should all be successfully obtained and the current thread should be present in all listings
+//! @SYMTestPriority High
+//! @SYMTestStatus Implemented
+//---------------------------------------------
+void CRunModeAgent::TestGetThreadList()
+	{
+	test.Next(_L("TestGetThreadList\n"));
+
+	test(ListingSupported(EThreads, EScopeGlobal));
+	test(ListingSupported(EThreads, EScopeProcessSpecific));
+	test(ListingSupported(EThreads, EScopeThreadSpecific));
+
+	test(KErrNone == iServSession.AttachExecutable(iFileName, EFalse));
+	test(KErrNone == iServSession.SuspendThread(iThreadID));
+
+	TBool found = EFalse;
+	
+	/* We need these loops because on some system the kernel run mode debugger does not 
+	 immediately present the thread in the thread list. 
+	 */
+	
+	for(TInt retryCount = 0; retryCount < 10 && !found; retryCount++ )
+		{
+		//test getting this process's thread list, ETrue as should find the target debug thread
+		User::After(50000);
+		found = DoTestGetThreadList(ETrue, EScopeProcessSpecific, RProcess().Id().Id());
+		}
+	test( found );
+	found = EFalse;
+
+	for(TInt retryCount = 0; retryCount < 10 && !found; retryCount++ )
+		{
+		//test getting the global list, ETrue as should find the target debug thread
+		User::After(50000);
+		found = DoTestGetThreadList(ETrue, EScopeGlobal);
+		}
+	test( found );
+
+	found = EFalse;
+	for(TInt retryCount = 0; retryCount < 10 && !found; retryCount++ )
+		{
+		//test getting this thread's thread list, ETrue as should find the target debug thread
+		User::After(50000);
+		found = DoTestGetThreadList(ETrue, EScopeThreadSpecific, RThread().Id().Id());
+		}
+	test( found );
+
+	test(KErrNone == iServSession.ResumeThread(iThreadID));
+	test(KErrNone == iServSession.DetachExecutable(iFileName));
+	}
+			
+TBool CRunModeAgent::DoTestGetThreadList(const TBool aShouldPass, const TListScope aListScope, const TUint64 aTargetId)
+	{
+	//create data to pass
+	RBuf8 buffer;
+	TUint32 size = 0;
+
+	//perform the call to get the thread list
+	DoGetList(EThreads, aListScope, buffer, size, aTargetId);
+
+	//initialise data about the target debug thread to compare the kernel's data against
+	TFileName name = iDebugThread.FullName();
+	RProcess thisProcess;
+	TUint64 processId = thisProcess.Id();
+	TUint64 threadId = iDebugThread.Id();
+
+	//look through the buffer and check if the target debug thread is there
+	TBool found = EFalse;
+	TUint8* ptr = (TUint8*)buffer.Ptr();
+	const TUint8* ptrEnd = ptr + size;
+	while(ptr < ptrEnd)
+		{
+		TThreadListEntry* entry = (TThreadListEntry*)ptr;
+		TPtr entryName(&(entry->iName[0]), entry->iNameLength, entry->iNameLength);
+
+		if( (threadId == entry->iThreadId) && (processId == entry->iProcessId) && (0 == name.CompareF(entryName)) )
+			{
+			test(entry->iSupervisorStackBaseValid);
+			test(entry->iSupervisorStackSizeValid);
+			//if all match then we've found it
+			found = ETrue;
+			break;
+			}
+
+		ptr += Align4(entry->GetSize());
+		}
+
+	//clean up
+	buffer.Close();
+	return found;
+
+	}
+
+//---------------------------------------------
+//! @SYMTestCaseID KBase-T-RMDEBUG2-0431
+//! @SYMTestType
+//! @SYMPREQ PREQ1426
+//! @SYMTestCaseDesc Test getting the code segment list
+//! @SYMTestActions Get the code segment list global and for a specified thread
+//! @SYMTestExpectedResults The listings should be returned successfully
+//! @SYMTestPriority High
+//! @SYMTestStatus Implemented
+//---------------------------------------------
+void CRunModeAgent::TestGetCodeSegsList()
+	{
+	test.Next(_L("TestGetCodeSegsList\n"));
+
+	test(ListingSupported(ECodeSegs, EScopeGlobal));
+	test(ListingSupported(ECodeSegs, EScopeProcessSpecific));
+	test(ListingSupported(ECodeSegs, EScopeThreadSpecific));
+
+	// Cannot perform this test with OEM2 debug token, as the t_rmdebug2 app
+	// needs AllFiles, and the OEM2 debug token does not authorise this.
+	// It seems reasonable to suppose that it would work anyway
+
+#ifndef FEWCAPS_DEBUGTOKEN
+	test(KErrNone == iServSession.AttachExecutable(iFileName, EFalse));
+
+ 	//test getting the global list, ETrue as should find this process' main codeSeg
+	DoTestGetCodeSegsList(ETrue, EScopeGlobal);
+
+	//test getting this process' codeSegs, ETrue as should find this process' main codeSeg
+	DoTestGetCodeSegsList(ETrue, EScopeProcessSpecific, RProcess().Id().Id());
+
+	//test getting this thread's codeSegs, ETrue as should find this process' main codeSeg
+	DoTestGetCodeSegsList(ETrue, EScopeThreadSpecific, RThread().Id().Id());
+
+	test(KErrNone == iServSession.DetachExecutable(iFileName));
+#endif // FEWCAPS_DEBUGTOKEN
+
+	}
+
+void CRunModeAgent::DoTestGetCodeSegsList(const TBool aShouldPass, const TListScope aListScope, const TUint64 aTargetId)
+	{
+	//create data to pass
+	RBuf8 buffer;
+	TUint32 size = 0;
+
+	//perform the call to get the Code segs
+	DoGetList(ECodeSegs, aListScope, buffer, size, aTargetId);
+
+	//create memoryInfo to contain info about this process
+	RProcess thisProcess;
+	TModuleMemoryInfo memoryInfo;
+	test(KErrNone == thisProcess.GetMemoryInfo(memoryInfo));
+
+	// check whether this process came from a file in ROM so we know whether to
+	// expect the code seg to be XIP or not.
+	RFs fs;
+	test(KErrNone == fs.Connect());
+	TBool thisFileIsInRom = EFalse;
+	if(fs.IsFileInRom(iFileName))
+		{
+		thisFileIsInRom = ETrue;
+		}
+
+	//look through the buffer to find this process' main code seg
+	TBool found = EFalse;
+	TUint8* ptr = (TUint8*)buffer.Ptr();
+	const TUint8* ptrEnd = ptr + size;
+	while(ptr < ptrEnd)
+		{
+		TCodeSegListEntry* codeSeg = (TCodeSegListEntry*)ptr;
+
+		if( (codeSeg->iIsXip == thisFileIsInRom) && (0 == iFileName.CompareF(TPtr(&(codeSeg->iName[0]), codeSeg->iNameLength, codeSeg->iNameLength))) )
+			{
+			if( (memoryInfo.iCodeBase == codeSeg->iCodeBase) &&
+					(memoryInfo.iCodeSize == codeSeg->iCodeSize) &&
+					(memoryInfo.iConstDataSize == codeSeg->iConstDataSize) &&
+					(memoryInfo.iInitialisedDataBase == codeSeg->iInitialisedDataBase) &&
+					(memoryInfo.iInitialisedDataSize == codeSeg->iInitialisedDataSize) &&
+					(memoryInfo.iUninitialisedDataSize == codeSeg->iUninitialisedDataSize))
+				{
+				//all matched so means we've found the codeSeg we're looking for
+				found = ETrue;
+				}
+			}
+		ptr += Align4(codeSeg->GetSize());
+		}
+
+	//check whether the result was as expected
+	test(found == aShouldPass);
+
+	// only care about rm_debug.ldd if we have global scope (belongs to the system not this process)
+	if (aListScope == EScopeGlobal)
+	{
+		// Search for rm_debug.ldd library and check its UID3 is correct
+		found = EFalse;
+
+_LIT(KRMDebugDriverFileName,"Z:\\sys\bin\\rm_debug.ldd");
+
+		TFileName rmdebugFilename(KRMDebugDriverFileName);
+
+		// reset the Ptr
+		ptr = (TUint8*)buffer.Ptr();
+		ptrEnd = ptr+size;
+		while(ptr < ptrEnd)
+		{
+			TCodeSegListEntry* codeSeg = (TCodeSegListEntry*)ptr;
+
+			if( rmdebugFilename.CompareF(TPtr(&(codeSeg->iName[0]), codeSeg->iNameLength, codeSeg->iNameLength)))
+				{
+				if(codeSeg->iUid3 == 0x101f7157 /* Magic */)
+					{
+					//all matched so means we've found the codeSeg we're looking for
+					found = ETrue;
+					}
+				}
+			ptr += Align4(codeSeg->GetSize());
+		}
+		test((TUint32)found == (TUint32)ETrue);
+	}
+
+	//clean up
+	buffer.Close();
+
+	}
+
+
+/**
+ * Get a list from the run mode debug system. Most list calls will initially return KErrTooBig, 
+ * since the initial size of the buffer is 0. However it is sometimes valid for a list to be empty
+ * given its filtering and scope. These calls should return KErrNone.
+ */
+void CRunModeAgent::DoGetList(const TListId aListId, const TListScope aListScope, RBuf8& aBuffer, TUint32& aSize, const TUint64 aTargetId)
+	{
+	//close the buffer in case there's stuff allocated in it
+	aBuffer.Close();
+	//initialise it to be one byte big, which will guarantee data won't fit in it
+	test(KErrNone == aBuffer.Create(1));
+	aSize = 0;
+	
+	TInt ret = KErrNone;
+	//should pass this test (assuming we've passed in sensible arguments above...)
+	if(EScopeGlobal == aListScope)
+		{
+		ret = iServSession.GetList(aListId, aBuffer, aSize);
+		}
+	else if(EScopeThreadSpecific == aListScope)
+		{
+		ret = iServSession.GetList((TThreadId)aTargetId, aListId, aBuffer, aSize);
+		}
+	else if(EScopeProcessSpecific == aListScope)
+		{
+		ret = iServSession.GetList((TProcessId)aTargetId, aListId, aBuffer, aSize);
+		}
+	else
+		{
+		// unknown list scope
+		test(0);
+		}
+
+	if( KErrNone == ret )
+		{
+		/* In the case that there is no data, just return and let the caller check
+		the buffer. It is valid for a caller to not expect any data to be returned.
+		*/
+		return;
+		}
+	
+	// The only other allowed return is KErrTooBig
+	test( ret == KErrTooBig );
+
+	//keep allocating larger buffers, beginning with the aSize returned by the above call,
+	//and hopefully we'll eventually make a large enough one
+	test(KErrNone == aBuffer.ReAlloc(aSize));
+
+	for(;;)
+		{
+		TInt err = KErrNone;
+		if(EScopeGlobal == aListScope)
+			{
+			err = iServSession.GetList(aListId, aBuffer, aSize);
+			}
+		else if(EScopeThreadSpecific == aListScope)
+			{
+			err = iServSession.GetList((TThreadId)aTargetId, aListId, aBuffer, aSize);
+			}
+		else if(EScopeProcessSpecific == aListScope)
+			{
+			err = iServSession.GetList((TProcessId)aTargetId, aListId, aBuffer, aSize);
+			}
+		else
+			{
+			// unknown list scope
+			test(0);
+			}
+		if(err == KErrTooBig)
+			{
+			//wasn't big enough so double it
+			aSize = aSize << 1;
+			err = aBuffer.ReAlloc(aSize);
+			if(err != KErrNone)
+				{
+				//print out a message if couldn't allocate memory and quit
+				test.Printf(_L("Out ot memory when attempting to allocate %d bytes."), aSize);
+				test(KErrNone == err);
+				}
+
+			RDebug::Printf(" List size =%d", aSize );
+			}
+		else
+			{
+			test(KErrNone == err);
+			test(aBuffer.Length() == aSize);
+			//break out of the loop if the list has been successfully read in
+			break;
+			}
+		}
+	}
+
+//---------------------------------------------
+//! @SYMTestCaseID KBase-T-RMDEBUG2-0432
+//! @SYMTestType
+//! @SYMPREQ PREQ1426
+//! @SYMTestCaseDesc Test reading and writing memory
+//! @SYMTestActions Multiple calls to read and write memory, with various sizes and at various locations.
+//!	Also test that bad input values cause appropriate errors to be returned.
+//! @SYMTestExpectedResults All tests should pass and the target process should be left unaffected
+//! @SYMTestPriority High
+//! @SYMTestStatus Implemented
+//---------------------------------------------
+void CRunModeAgent::TestMemoryAccess()
+{
+	TInt err;
+
+	test.Next(_L("TestMemoryAccess - Read Memory\n"));
+
+	//initialise buffer
+	gMemoryAccessBytes.SetLength(0);
+	for (TInt i=0; i<SYMBIAN_RMDBG_MEMORYSIZE; i++)
+		{
+		gMemoryAccessBytes.Append(i);
+		}
+
+	TUint32 address = (TUint32)(&gMemoryAccessBytes[0]);
+	TUint32 dataSize = SYMBIAN_RMDBG_MEMORYSIZE;
+
+	//create size for buffer that is rounded up to nearest 4 bytes if not
+	//already 4 byte aligned
+	TUint32 size = dataSize;
+	if(size % 4 != 0)
+		{
+		size += (4 - (size % 4));
+		}
+
+	RBuf8 dataBlock;
+	err = dataBlock.Create(size);
+	test(err==KErrNone);
+	test(KErrNone == iServSession.AttachExecutable(iFileName, EFalse));
+
+	//suspend the thread prior to memory operations
+	test(KErrNone == iServSession.SuspendThread(iThreadID));
+
+	err = iServSession.ReadMemory(iThreadID, address, size, dataBlock, EAccess32, EEndLE8);
+	test(err==KErrNone);
+
+	for (TInt i=0; i<dataSize; i++)
+		{
+		test(dataBlock.Ptr()[i] == gMemoryAccessBytes[i]);
+		}
+
+	test.Next(_L("TestMemoryAccess - Write Memory\n"));
+
+	// Now reset the buffer
+	for (TInt i=0; i<dataSize; i++)
+		{
+		gMemoryAccessBytes[i] = 0;
+		}
+
+	// Write our data into the buffer
+	err = iServSession.WriteMemory(iThreadID, address, size, dataBlock, EAccess32, EEndLE8);
+	test(err==KErrNone);
+
+	for (TInt i=0; i<dataSize; i++)
+		{
+		test(dataBlock.Ptr()[i] == gMemoryAccessBytes[i]);
+		}
+
+	//final test that everything's not been going wrong
+	test(gMemoryAccessBytes[5] != 0);
+
+	test.Next(_L("TestMemoryAccess - Invalid arguments\n"));
+	test.Printf(_L("This test may emit crash-like information. This is intended.\n"));
+
+	//test address that is not 32 bit aligned
+	err = iServSession.ReadMemory(iThreadID, address + 1, size, dataBlock, EAccess32, EEndLE8);
+	test(err == KErrArgument);
+
+	//test size that is not multiple of 4 bytes
+	err = iServSession.WriteMemory(iThreadID, address, size + 2, dataBlock, EAccess32, EEndLE8);
+	test(err == KErrArgument);
+
+	//test size > max block size
+	err = iServSession.ReadMemory(iThreadID, address, (1<<15), dataBlock, EAccess32, EEndLE8);
+	test(err == KErrArgument);
+
+	//test access size == 2 bytes
+	err = iServSession.ReadMemory(iThreadID, address, size, dataBlock, EAccess16, EEndLE8);
+	test(err == KErrNotSupported);
+
+	//test access size == 1 byte
+	err = iServSession.WriteMemory(iThreadID, address, size, dataBlock, EAccess8, EEndLE8);
+	test(err == KErrNotSupported);
+
+	//test endianess == EEndBE8
+	err = iServSession.ReadMemory(iThreadID, address, size, dataBlock, EAccess32, EEndBE8);
+	test(err == KErrNotSupported);
+
+	//test endianess == EEndBE32
+	err = iServSession.WriteMemory(iThreadID, address, size, dataBlock, EAccess32, EEndBE32);
+	test(err == KErrNotSupported);
+
+	//test reading off end of memory
+	err = iServSession.ReadMemory(iThreadID, 0xffffff00, 0x00000101, dataBlock, EAccess32, EEndLE8);
+	test(err == KErrArgument);
+
+	//The following three tests check that edge conditions in the range check are handled correctly.
+	err = iServSession.ReadMemory(iThreadID, 0xffffff00, 0x000000FF, dataBlock, EAccess32, EEndLE8);
+	test(err == KErrArgument);
+
+	err = iServSession.ReadMemory(iThreadID, 0xffffff00, 0x000000F0, dataBlock, EAccess32, EEndLE8);
+	test(err == KErrBadDescriptor);
+
+	//Third range check test. Check that range check is handled correctly even when base + size wraps to 0.
+	err = iServSession.ReadMemory(iThreadID, 0xffffff00, 0x00000100, dataBlock, EAccess32, EEndLE8);
+	test(err == KErrBadDescriptor);
+	//end of range check tests
+
+	//test size == 0
+	err = iServSession.WriteMemory(iThreadID, address, 0, dataBlock, EAccess32, EEndLE8);
+	test(err == KErrArgument);
+
+	//attempt to write to address outside of process data segments,
+	//this address corresponds to the vectors so shouldn't be able to write
+	err = iServSession.WriteMemory(iThreadID, 0xffff0000, size, dataBlock, EAccess32, EEndLE8);
+	test(err == KErrBadDescriptor);
+
+	//attempt to read and write to address in process code segment
+
+	//open a handle to the thread
+	RThread debugThread;
+	test(debugThread.Open(iThreadID) == KErrNone);
+
+	//get a reference to the debug process
+	RProcess debugProcess;
+	test(debugThread.Process(debugProcess) == KErrNone);
+
+	//get the memory info for the process
+	TProcessMemoryInfo info;
+	test(debugProcess.GetMemoryInfo(info) == KErrNone);
+
+	address = info.iCodeBase;
+	if(size <= info.iCodeSize)
+		{
+		test(KErrNone == iServSession.ReadMemory(iThreadID, address, size, dataBlock, EAccess32, EEndLE8));
+		test(KErrBadDescriptor == iServSession.WriteMemory(iThreadID, address, size, dataBlock, EAccess32, EEndLE8));
+		}
+
+	// Some performance tests now
+	TUint32 bytesRead = 0;
+
+	// Allocate a data buffer
+	TUint32* p = (TUint32*)User::Alloc(size);
+	test(p != 0);
+
+	TInt nanokernel_tick_period;
+	HAL::Get(HAL::ENanoTickPeriod, nanokernel_tick_period);
+	test (nanokernel_tick_period != 0);
+
+	static const TInt KOneMillion = 1000000;
+
+	TInt nkTicksPerSecond = KOneMillion/nanokernel_tick_period;
+
+	TUint32 stopTickCount = User::NTickCount() + nkTicksPerSecond;
+
+	while (User::NTickCount() < stopTickCount)
+		{
+		err = iServSession.ReadMemory(iThreadID, (TUint32)p, size, dataBlock, EAccess32, EEndLE8);
+		test(err==KErrNone);
+
+		// Increase the count of bytes read
+		bytesRead += size;
+		}
+
+	test(bytesRead != 0);
+	iMemoryReadKbytesPerSecond = bytesRead/1024;
+
+	// write memory test
+	TUint32 bytesWritten = 0;
+
+	stopTickCount = User::NTickCount() + nkTicksPerSecond;
+
+	while (User::NTickCount() < stopTickCount)
+		{
+		err = iServSession.WriteMemory(iThreadID, (TUint32)p, size, dataBlock, EAccess32, EEndLE8);
+		test(err==KErrNone);
+
+		// Increase the count of bytes read
+		bytesWritten += size;
+		}
+
+	test (bytesWritten != 0);
+	iMemoryWriteKbytesPerSecond = bytesWritten/1024;
+
+	User::Free(p);
+
+	//resume the thread
+	test(KErrNone == iServSession.ResumeThread(iThreadID));
+
+	debugThread.Close();
+	dataBlock.Close();
+
+	test(KErrNone == iServSession.DetachExecutable(iFileName));
+	}
+
+//---------------------------------------------
+//! @SYMTestCaseID KBase-T-RMDEBUG2-0433
+//! @SYMTestType
+//! @SYMPREQ PREQ1426
+//! @SYMTestCaseDesc Test suspending and resuming threads
+//! @SYMTestActions Multiple calls to suspend and resume threads with and without attaching to the thread
+//! @SYMTestExpectedResults All tests should pass and the target process should be left unaffected
+//! @SYMTestPriority High
+//! @SYMTestStatus Implemented
+//---------------------------------------------
+void CRunModeAgent::TestSuspendResume()
+	{
+	TInt err;
+
+	test.Next(_L("TestSuspendResume - Suspend\n"));
+
+	test(KErrNone == iServSession.AttachExecutable(iFileName, EFalse));
+
+	err = iServSession.SuspendThread(iThreadID);
+	test(err==KErrNone);
+	err = TestRunCountSame( iRunCountSubscribe, iTimer );
+	test( KErrNone == err );
+	
+	// Resume the thread
+	test.Next(_L("TestSuspendResume - Resume\n"));
+	err = iServSession.ResumeThread(iThreadID);
+	test(err==KErrNone);
+
+	test(KErrNone == iServSession.DetachExecutable(iFileName));
+
+	err = WaitForRunCountChange( iRunCountSubscribe, iTimer );
+	test(KErrNone == err );
+	
+	// check that agent can resume thread which it previously detached from
+	test(KErrNone == iServSession.AttachExecutable(iFileName, EFalse));
+	test(KErrNone == iServSession.SuspendThread(iThreadID));
+	test(KErrNone == iServSession.DetachExecutable(iFileName));
+
+	test(KErrNone == iServSession.AttachExecutable(iFileName, EFalse));
+	err = TestRunCountSame( iRunCountSubscribe, iTimer );
+	test( KErrNone == err );
+	test(KErrNone == iServSession.ResumeThread(iThreadID));
+	test(KErrNone == iServSession.DetachExecutable(iFileName));
+
+	err = WaitForRunCountChange( iRunCountSubscribe, iTimer );
+	test( KErrNone == err );
+	
+	test(KErrNone == iServSession.AttachExecutable(iFileName, EFalse));
+	test(KErrNone == iServSession.SuspendThread(iThreadID));
+	err = TestRunCountSame( iRunCountSubscribe, iTimer );
+	test( KErrNone == err );
+	test(KErrNone == iServSession.DetachExecutable(iFileName));
+	err = TestRunCountSame( iRunCountSubscribe, iTimer );
+	test( KErrNone == err );
+	    
+	test(KErrNone == iServSession.AttachExecutable(iFileName, EFalse));
+	err = TestRunCountSame( iRunCountSubscribe, iTimer );
+	test( KErrNone == err );
+	test(KErrNone == iServSession.ResumeThread(iThreadID));
+	test(KErrNone == iServSession.DetachExecutable(iFileName));
+	
+	err = WaitForRunCountChange( iRunCountSubscribe, iTimer );
+    test( KErrNone == err );
+	}
+
+//---------------------------------------------
+//! @SYMTestCaseID KBase-T-RMDEBUG2-0434
+//! @SYMTestType
+//! @SYMPREQ PREQ1426
+//! @SYMTestCaseDesc Test getting the debug functionality from the driver
+//! @SYMTestActions Get the size and contents of the debug functionality block
+//! @SYMTestExpectedResults All tests should pass and the expected data should appear in the functionality block
+//! @SYMTestPriority High
+//! @SYMTestStatus Implemented
+//---------------------------------------------
+void CRunModeAgent::TestDebugFunctionality()
+	{
+
+	TInt err;
+
+	test.Next(_L("TestDebugFunctionality - GetDebugFunctionalityBufSize\n"));
+
+	TUint32 bufsize = 0;	// Safe default size
+
+	// Get functionality block size
+	err = iServSession.GetDebugFunctionalityBufSize(&bufsize);
+	test(err==KErrNone);
+	test.Next(_L("TestDebugFunctionality - GetDebugFunctionality\n"));
+
+	// Ensure we have a finite buffer size
+	test(bufsize!=0);
+
+	// Allocate space for the functionality data
+	HBufC8* dftext = HBufC8::NewLC(bufsize);
+
+	// create an empty TPtr8 refering to dftext
+	TPtr8 dftextPtr(dftext->Des());
+
+	// Get the functionality block
+	err = iServSession.GetDebugFunctionality(dftextPtr);
+	test(err==KErrNone);
+
+	// Check that the first entry is correct
+	TTagHeader RefHdr =
+	{
+		ETagHeaderIdCore,ECoreLast,
+	};
+
+	// First header passed from rm_debug.ldd
+	TTagHeader* TestHdr = (TTagHeader*)dftextPtr.Ptr();
+
+	// Check
+	test(RefHdr.iTagHdrId==TestHdr->iTagHdrId);
+	// this test might fail if the agent is used with a Debug Security Server different from
+	// the one it was compiled against. So removing it for now.
+	//test(RefHdr.iNumTags==TestHdr->iNumTags);
+
+	// read a value from the data to check it has come through as expected
+	TTagHeader* header = GetTagHdr(dftext->Des(), ETagHeaderIdApiConstants);
+	test(header != NULL);
+	TTag* tag = GetTag(header, EApiConstantsTEventInfoSize);
+	test(tag != NULL);
+	// this test might fail if the agent is used with a Debug Security Server different from
+	// the one it was compiled against. So removing it for now.
+	//test(sizeof(TEventInfo) == tag->iValue);
+
+	// Remove our temporary buffer
+	CleanupStack::PopAndDestroy(dftext);
+	}
+
+//---------------------------------------------
+//! @SYMTestCaseID KBase-T-RMDEBUG2-0435
+//! @SYMTestType
+//! @SYMPREQ PREQ1426
+//! @SYMTestCaseDesc Test setting and clearing consecutive breakpoints
+//! @SYMTestActions Set and clear consecutive breakpoints of all combinations of breakpoint types
+//! @SYMTestExpectedResults All breakpoints should be set and cleared without error
+//! @SYMTestPriority High
+//! @SYMTestStatus Implemented
+//---------------------------------------------
+void CRunModeAgent::TestConsecutiveBreakPoints()
+	{
+	test.Next(_L("TestConsecutiveBreakPoints\n"));
+
+	test(KErrNone == iServSession.SuspendThread(iThreadID));
+
+	// just a temporary structure for storing info about a breakpoint
+	struct TBreakPoint
+		{
+	public:
+		TBreakPoint()
+			:iId(0),
+			iMode((TArchitectureMode)0),
+			iAddress(0)
+			{}
+		TBreakId iId;
+		TArchitectureMode iMode;
+		TUint32 iAddress;
+		inline TInt Size() { return (EArmMode == iMode) ? 4 : 2; }
+		};
+
+	//an address in the target debug thread
+	TUint32 address = (TUint32)(&TestFunction);
+
+	// there are six orders in which three breakpoints can be set, these are looped
+	// through below to check setting and clearing consecutive breakpoints works
+	TUint8 order[6][3] =
+		{
+			{0,1,2},
+			{0,2,1},
+			{1,0,2},
+			{1,2,0},
+			{2,0,1},
+			{2,1,0}
+		};
+
+	// The following code checks that setting and clearing consecutive breakpoints works correctly:
+	// It checks that setting all combinations of three arm and thumb breakpoints succeeds, and check that the
+	// breakpoints can be set in any order, and then cleared in any order
+
+	// the 3 least significant bits of i control whether each of the three breakpoints should be arm or thumb
+	for(TInt i=0; i<8; i++)
+		{
+		// controls the order in which the breakpoints should be set
+		for(TInt j=0; j<6; j++)
+			{
+			// create the three breakpoints and set their modes
+			TBreakPoint bp[3];
+			bp[0].iMode = (i&1) ? EArmMode : EThumbMode;
+			bp[1].iMode = (i&2) ? EArmMode : EThumbMode;
+			bp[2].iMode = (i&4) ? EArmMode : EThumbMode;
+
+			// set the address of each of the breakpoints
+			bp[0].iAddress = address;
+			if(EArmMode == bp[0].iMode)
+				{ // if an arm breakpoint then must be on a four byte boundary
+				bp[0].iAddress = Align4(bp[0].iAddress);
+				}
+			bp[1].iAddress = bp[0].iAddress + bp[0].Size();
+			if(EArmMode == bp[1].iMode)
+				{ // if an arm breakpoint then must be on a four byte boundary
+				bp[1].iAddress = Align4(bp[1].iAddress);
+				}
+			bp[2].iAddress = bp[1].iAddress + bp[1].Size();
+			if(EArmMode == bp[2].iMode)
+				{ // if an arm breakpoint then must be on a four byte boundary
+				bp[2].iAddress = Align4(bp[2].iAddress);
+				}
+			for(TInt k=0; k<6; k++)
+				{
+				// set the three breakpoints in the order defined by j and then clear them in the order defined by k
+				test(KErrNone==iServSession.SetBreak(bp[order[j][0]].iId, iThreadID, bp[order[j][0]].iAddress, bp[order[j][0]].iMode));
+				test(KErrNone==iServSession.SetBreak(bp[order[j][1]].iId, iThreadID, bp[order[j][1]].iAddress, bp[order[j][1]].iMode));
+				test(KErrNone==iServSession.SetBreak(bp[order[j][2]].iId, iThreadID, bp[order[j][2]].iAddress, bp[order[j][2]].iMode));
+				test(KErrNone==iServSession.ClearBreak(bp[order[k][0]].iId));
+				test(KErrNone==iServSession.ClearBreak(bp[order[k][1]].iId));
+				test(KErrNone==iServSession.ClearBreak(bp[order[k][2]].iId));
+				}
+			}
+		}
+
+	// resume the thread
+	test(KErrNone == iServSession.ResumeThread(iThreadID));
+	}
+
+//---------------------------------------------
+//! @SYMTestCaseID KBase-T-RMDEBUG2-0436
+//! @SYMTestType
+//! @SYMPREQ PREQ1426
+//! @SYMTestCaseDesc Test breakpoint functionality
+//! @SYMTestActions Multiple calls to set and clear breakpoints. Checking bad input produces appropriate errors.
+//! @SYMTestExpectedResults All tests should pass and the target debug thread should be left unaffected
+//! @SYMTestPriority High
+//! @SYMTestStatus Implemented
+//---------------------------------------------
+void CRunModeAgent::TestBreakPoints()
+	{
+	TInt err;
+
+	test.Next(_L("TestBreakPoints - Set\n"));
+
+	test(KErrNone == iServSession.AttachExecutable(iFileName, EFalse));
+
+	TestConsecutiveBreakPoints();
+
+	//an address in the target debug thread
+	TUint32 address = (TUint32)(&TestFunction);
+
+	/*
+	 * Ensure that breakpoint operations don't
+	 * affect memory read/write by checking that reads/writes
+	 * in locations containing breakpoints don't change behaviour
+	 * because of the breakpoints.
+	 */
+
+	TUint32 size = SYMBIAN_RMDBG_MEMORYSIZE;
+
+	RBuf8 originalDataBlock;
+	err = originalDataBlock.Create(size);
+	test(err==KErrNone);
+
+	//suspend the thread
+	test(KErrNone == iServSession.SuspendThread(iThreadID));
+
+	err = iServSession.ReadMemory(iThreadID, address, size, originalDataBlock, EAccess32, EEndLE8);
+	test(err==KErrNone);
+
+	// Test data block for comparison
+	RBuf8 testDataBlock;
+	err = testDataBlock.Create(size);
+	test(err==KErrNone);
+
+	/*
+	 * set an arm breakpoint
+	 */
+	test.Next(_L("TestBreakPoints - set an arm breakpoint1"));
+
+	TBreakId armBreakId = 0;
+	err = iServSession.SetBreak(armBreakId, iThreadID, address, EArmMode);
+	test(err == KErrNone);
+
+	// Ensure that memory read is not corrupted
+	test.Next(_L("TestBreakPoints - read mem 2"));
+	err = iServSession.ReadMemory(iThreadID, address, size, testDataBlock, EAccess32, EEndLE8);
+	test(err==KErrNone);
+
+	test (testDataBlock == originalDataBlock);
+
+	/*
+	 * set a thumb breakpoint
+	 */
+	test.Next(_L("TestBreak- set a thumb breakpoint1"));
+	TBreakId thumbBreakId = 0;
+	err = iServSession.SetBreak(thumbBreakId, iThreadID, address+4, EThumbMode);
+	test(err == KErrNone);
+
+	/*
+	 * set a thumb2EE breakpoint
+	 */
+	test.Next(_L("TestBreak- set a thumb2EE breakpoint"));
+
+	TBreakId thumb2EEBreakId = 0;
+	err = iServSession.SetBreak(thumb2EEBreakId, iThreadID, address+8, EThumb2EEMode);
+	test(err == KErrNotSupported);
+
+	/*
+	 * overlapping breakpoint (same address/threadId/mode)
+	 */
+	test.Next(_L("TestBreak- set overlapping breakpoint 1"));
+	TBreakId overlapBreakId = 0;
+	err = iServSession.SetBreak(overlapBreakId, iThreadID, address, EArmMode);
+	test(err == KErrAlreadyExists);
+
+	/*
+	 * overlapping breakpoint (different address/same threadId/different mode)
+	 *
+	 * address - EArmBreakpoint
+	 * address+2 - EThumbBreakpoint
+	 */
+	test.Next(_L("TestBreak- set overlapping breakpoint 2"));
+	TBreakId overlap2BreakId = 0;
+	err = iServSession.SetBreak(overlap2BreakId, iThreadID, address+2, EThumbMode);
+	test(err == KErrAlreadyExists);
+
+	/*
+	 * Un-aligned address (arm)
+	 */
+	test.Next(_L("TestBreak- set Un-aligned address (arm)"));
+	TBreakId armUnalignedBreakId = 0;
+	err = iServSession.SetBreak(armUnalignedBreakId, iThreadID, address+6, EArmMode);
+	test(err == KErrArgument);
+
+	/*
+	 * Un-aligned address (thumb)
+	 */
+	test.Next(_L("TestBreak- set Un-aligned address (thumb)"));
+	TBreakId thumbUnalignedBreakId = 0;
+	err = iServSession.SetBreak(thumbUnalignedBreakId, iThreadID, address+7, EThumbMode);
+	test(err == KErrArgument);
+
+	/*
+	 * Invalid address (arm)
+	 */
+	test.Next(_L("TestBreak- set Invalid address (arm)"));
+	TBreakId armBadAddressBreakId = 0;
+	err = iServSession.SetBreak(armBadAddressBreakId, iThreadID, 0 /* address */, EThumbMode);
+	test(err == KErrBadDescriptor);
+
+	/*
+	 * Different thread, same address. Should fail for the same process, but succeed
+	 * for a different process.
+	 */
+
+	/*
+	 * Invalid thread
+	 */
+	TBreakId invalidThreadBreakId = 0;
+	err = iServSession.SetBreak(invalidThreadBreakId, 0xbabababa, address, EThumbMode);
+	test(err == KErrPermissionDenied);
+
+	// Clear the ARM breakpoint
+	err = iServSession.ClearBreak(armBreakId);
+	test(err == KErrNone);
+
+	// Clear the Thumb breakpoint
+	err = iServSession.ClearBreak(thumbBreakId);
+	test(err == KErrNone);
+
+	// to do : two threads at the same address
+	// to do : two processes at the same address
+
+	// Ensure that memory read is not corrupted after clearing the breakpoints
+	err = iServSession.ReadMemory(iThreadID, address, size, testDataBlock, EAccess32, EEndLE8);
+	test(err==KErrNone);
+
+	test (testDataBlock == originalDataBlock);
+
+	/*
+	 * How fast can we set breakpoints?
+	 *
+	 * Measure the time by setting/clearing breakpoints for 1 second.
+     */
+	TInt nanokernel_tick_period;
+	HAL::Get(HAL::ENanoTickPeriod, nanokernel_tick_period);
+	test (nanokernel_tick_period != 0);
+
+	TInt nkTicksPerSecond = HelpTicksPerSecond();
+
+	TInt breaksPerSecond = 0;
+
+	TUint32 stopTickCount = User::NTickCount() + nkTicksPerSecond;
+
+	while (User::NTickCount() < stopTickCount)
+		{
+		// set the breakpoint
+		TBreakId armBreakId = 0;
+		err = iServSession.SetBreak(armBreakId, iThreadID, address, EArmMode);
+		test(err == KErrNone);
+
+		// Clear the breakpoint
+		err = iServSession.ClearBreak(armBreakId);
+		test(err == KErrNone);
+
+		// Update the count of breakpoints
+		breaksPerSecond++;
+
+		// Gone wrong if we wrap to negative breakpoints (cannot set 2billion/second!)
+		test(breaksPerSecond >0);
+		}
+
+	// Store the results for later
+	iBreakpointsPerSecond = breaksPerSecond;
+
+	/*
+	 * How many breakpoints can we set?
+	 */
+
+	TBool done = EFalse;
+
+	// We assume all the breakpoints id's are issued in ascending order
+	TInt maxBreakPoints = 0;
+
+	// Temporary buffer
+	RArray<TBreakId> breakIdList;
+
+	TUint32 testAddress = address;
+
+	while(!done)
+		{
+		TBreakId breakId = 0;
+
+		// set the breakpoint
+		testAddress += 4;	// ensure the addresses don't overlap
+
+		err = iServSession.SetBreak(breakId, iThreadID, testAddress, EArmMode);
+		test (err == KErrNone || err == KErrOverflow);
+		if (err != KErrNone)
+			{
+			// we've reached the limit of the number of breaks we can set
+			done = ETrue;
+			break;
+			}
+
+		// store the id of this breakpoint
+		breakIdList.Append(breakId);
+
+		// Increase the count of breakpoints
+		maxBreakPoints++;
+		test(maxBreakPoints > 0);
+		}
+
+	// How many breakpoints can we set?
+	iMaxBreakpoints = maxBreakPoints;
+
+	// now clear all those breakpoints again
+	while(breakIdList.Count() != 0)
+		{
+		// Place it into a TBreakId
+		TBreakId id = breakIdList[0];
+
+		err = iServSession.ClearBreak(id);
+		test(err == KErrNone);
+
+		// next id
+		breakIdList.Remove(0);
+		}
+
+	breakIdList.Close();
+
+	// close our temporary buffers
+	originalDataBlock.Close();
+	testDataBlock.Close();
+
+	err = iServSession.ResumeThread(iThreadID);
+	test (err == KErrNone);
+
+	test(KErrNone == iServSession.DetachExecutable(iFileName));
+	}
+
+//---------------------------------------------
+//! @SYMTestCaseID KBase-T-RMDEBUG2-0437
+//! @SYMTestType
+//! @SYMPREQ PREQ1426
+//! @SYMTestCaseDesc Test modifying breakpoints
+//! @SYMTestActions Several calls to modify breakpoints
+//! @SYMTestExpectedResults Valid requests should result in the breakpoints being changed, invalid requests should return errors
+//! @SYMTestPriority High
+//! @SYMTestStatus Implemented
+//---------------------------------------------
+void CRunModeAgent::TestModifyBreak()
+	{
+	test.Next(_L("TestModifyBreak\n"));
+
+	DoTestModifyBreak(ETrue);
+	DoTestModifyBreak(EFalse);
+	}
+
+void CRunModeAgent::DoTestModifyBreak(TBool aThreadSpecific)
+	{
+	test.Printf(_L("DoTestModifyBreak: aThreadSpecific: %d\n"), aThreadSpecific?1:0);
+
+	TInt err;
+
+	RProcess process;
+	TProcessId processId = process.Id();
+	process.Close();
+
+	test(KErrNone == iServSession.AttachExecutable(iFileName, EFalse));
+
+	//suspend the thread
+	test(KErrNone == iServSession.SuspendThread(iThreadID));
+
+	//an address in the target debug thread
+	TUint32 address = (TUint32)(&TestFunction);
+
+	//set an arm mode break point
+	TBreakId armBreakId = 0;
+	err = aThreadSpecific
+		? iServSession.SetBreak(armBreakId, iThreadID, address, EArmMode)
+		: iServSession.SetProcessBreak(armBreakId, processId, address, EArmMode);
+	test(err == KErrNone);
+
+	/*
+	 * Invalid thread
+	 */
+	err = aThreadSpecific
+		? iServSession.ModifyBreak(armBreakId, 0xbabababa, address, EArmMode)
+		: iServSession.ModifyProcessBreak(armBreakId, 0xbabababa, address, EArmMode);
+	test(err == KErrPermissionDenied);
+
+	/*
+	 * Valid address
+	 */
+	err = aThreadSpecific
+		? iServSession.ModifyBreak(armBreakId, iThreadID, address+4, EArmMode)
+		: iServSession.ModifyProcessBreak(armBreakId, processId, address+4, EArmMode);
+	test(err == KErrNone);
+
+	/*
+	 * Invalid address
+	 */
+	err = aThreadSpecific
+		? iServSession.ModifyBreak(armBreakId, iThreadID, 0, EArmMode)
+		: iServSession.ModifyProcessBreak(armBreakId, processId, 0, EArmMode);
+	test(err == KErrBadDescriptor);
+
+	/*
+	 * Thumb mode
+	 */
+	err = aThreadSpecific
+		? iServSession.ModifyBreak(armBreakId, iThreadID, address, EThumbMode)
+		: iServSession.ModifyProcessBreak(armBreakId, processId, address, EThumbMode);
+	test(err == KErrNone);
+
+	/*
+	 * Thumb2EE mode
+	 */
+	err = aThreadSpecific
+		? iServSession.ModifyBreak(armBreakId, iThreadID, address, EThumb2EEMode)
+		: iServSession.ModifyProcessBreak(armBreakId, processId, address, EThumb2EEMode);
+	test(err == KErrNotSupported);
+
+	/*
+	 * Arm mode
+	 */
+	err = aThreadSpecific
+		? iServSession.ModifyBreak(armBreakId, iThreadID, address, EArmMode)
+		: iServSession.ModifyProcessBreak(armBreakId, processId, address, EArmMode);
+	test(err == KErrNone);
+
+	// Finally, clear the breakpoint
+	err = iServSession.ClearBreak(armBreakId);
+	test(err == KErrNone);
+
+	//resume the thread
+	test(KErrNone == iServSession.ResumeThread(iThreadID));
+	test(KErrNone == iServSession.DetachExecutable(iFileName));
+	}
+
+//---------------------------------------------
+//! @SYMTestCaseID KBase-T-RMDEBUG2-0438
+//! @SYMTestType
+//! @SYMPREQ PREQ1426
+//! @SYMTestCaseDesc Test extracting information about breakpoints
+//! @SYMTestActions Several calls to get information about breakpoints
+//! @SYMTestExpectedResults All tests should pass and the target process should be left unaffected
+//! @SYMTestPriority High
+//! @SYMTestStatus Implemented
+//---------------------------------------------
+void CRunModeAgent::TestBreakInfo()
+	{
+	test.Next(_L("TestBreakInfo\n"));
+
+	DoTestBreakInfo(ETrue);
+	DoTestBreakInfo(EFalse);
+	}
+
+void CRunModeAgent::DoTestBreakInfo(TBool aThreadSpecific)
+	{
+	test.Printf(_L("DoTestModifyBreak: aThreadSpecific: %d\n"), aThreadSpecific?1:0);
+
+	TInt err;
+
+	RProcess process;
+	TProcessId processId = process.Id();
+	process.Close();
+
+	//an address in the target debug thread
+	TUint32 address = (TUint32)(&TestFunction);
+
+	test(KErrNone == iServSession.AttachExecutable(iFileName, EFalse));
+
+	//suspend thread
+	test(KErrNone == iServSession.SuspendThread(iThreadID));
+
+	//set an arm mode break point
+	TBreakId armBreakId = 0;
+	err = aThreadSpecific
+		? iServSession.SetBreak(armBreakId, iThreadID, address, EArmMode)
+		: iServSession.SetProcessBreak(armBreakId, processId, address, EArmMode);
+	test(err == KErrNone);
+
+	// Read back the information and check it is correct
+	TThreadId testThreadId = TThreadId(0);
+	TProcessId testProcessId = TProcessId(0);
+	TUint32 testAddress = 0;
+	TArchitectureMode testMode = EArmMode;
+
+	err = aThreadSpecific
+		? iServSession.BreakInfo(armBreakId,testThreadId,testAddress, testMode)
+		: iServSession.ProcessBreakInfo(armBreakId, testProcessId, testAddress, testMode);
+	test (err == KErrNone);
+	test (aThreadSpecific ? (testThreadId == iThreadID) : (testProcessId == processId));
+	test (testAddress == address);
+	test (testMode == EArmMode);
+
+	//change the address
+	TUint32 changeAddress = address + 64;
+	err = aThreadSpecific
+		? iServSession.ModifyBreak(armBreakId, iThreadID, changeAddress,EArmMode)
+		: iServSession.ModifyProcessBreak(armBreakId, processId, changeAddress, EArmMode);
+	test(err == KErrNone);
+
+	// Check the address has changed
+	err = aThreadSpecific
+		? iServSession.BreakInfo(armBreakId,testThreadId,testAddress, testMode)
+		: iServSession.ProcessBreakInfo(armBreakId, testProcessId, testAddress, testMode);
+	test (err == KErrNone);
+	test (testAddress == changeAddress);
+
+	// change the architecture type
+	TArchitectureMode checkMode = EThumbMode;
+	err = aThreadSpecific
+		? iServSession.ModifyBreak(armBreakId, iThreadID, address,checkMode)
+		: iServSession.ModifyProcessBreak(armBreakId, processId, address, checkMode);
+	test (err == KErrNone);
+
+	// Check the mode has changed
+	err = aThreadSpecific
+		? iServSession.BreakInfo(armBreakId,testThreadId,testAddress,testMode)
+		: iServSession.ProcessBreakInfo(armBreakId, testProcessId, testAddress, testMode);
+	test (err == KErrNone);
+	test (testMode == checkMode);
+
+	// clear the breakpoint again
+	err = iServSession.ClearBreak(armBreakId);
+	test (err == KErrNone);
+
+	//resume thread
+	test(KErrNone == iServSession.ResumeThread(iThreadID));
+	test(KErrNone == iServSession.DetachExecutable(iFileName));
+	}
+
+// Needed for the RunToBreak test
+IMPORT_C extern void RMDebug_BranchTst1();
+IMPORT_C extern void RMDebug_BranchTst2();
+
+//---------------------------------------------
+//! @SYMTestCaseID KBase-T-RMDEBUG2-0439
+//! @SYMTestType
+//! @SYMPREQ PREQ1426
+//! @SYMTestCaseDesc Test hitting various types of breakpoints
+//! @SYMTestActions Several calls to register to observe breakpoints and to hit breakpoints of different types
+//! @SYMTestExpectedResults All tests should pass and the target process should be left unaffected
+//! @SYMTestPriority High
+//! @SYMTestStatus Implemented
+//---------------------------------------------
+void CRunModeAgent::TestRunToBreak()
+	{
+	test.Next(_L("TestRunToBreak\n"));
+
+	DoTestRunToBreak(ETrue);
+	DoTestRunToBreak(EFalse);
+	}
+
+void CRunModeAgent::DoTestRunToBreak(TBool aThreadSpecific)
+	{
+	test.Printf(_L("DoTestRunToBreak: aThreadSpecific: %d\n"), aThreadSpecific?1:0);
+
+	TInt err = KErrNone;
+
+	RProcess process;
+	TProcessId processId = process.Id();
+	process.Close();
+
+	test(KErrNone == iServSession.AttachExecutable(iFileName, EFalse));
+	// we should suspend the thread first, then set the breakpoint
+	err = iServSession.SuspendThread(iThreadID);
+	test (err == KErrNone);
+
+	// Try to set the breakpoint
+	TBreakId armBreakId;
+	TUint32 address = (TUint32)(&RMDebug_BranchTst1);
+
+	err = aThreadSpecific
+		? iServSession.SetBreak(armBreakId,iThreadID,address,EArmMode)
+		: iServSession.SetProcessBreak(armBreakId, processId, address, EArmMode);
+	test(err == KErrNone);
+
+	err = aThreadSpecific
+		? iServSession.SetEventAction(iFileName,EEventsBreakPoint, EActionContinue)
+		: iServSession.SetEventAction(iFileName,EEventsProcessBreakPoint, EActionContinue);
+	test (err == KErrNone);
+
+	// Continue the thread
+	err = iServSession.ResumeThread(iThreadID);
+	test (err == KErrNone);
+
+	// wait for the breakpoint to be hit
+	TEventInfo info;
+	static TRequestStatus status;
+
+	TPtr8 infoPtr((TUint8*)&info,0,sizeof(TEventInfo));
+
+	iServSession.GetEvent(iFileName,status,infoPtr);
+
+	// Wait for notification of the breakpoint hit event
+	User::WaitForRequest(status);
+	test(status==KErrNone);
+
+	// info should now be filled with the details
+	test(info.iEventType == (aThreadSpecific ? EEventsBreakPoint : EEventsProcessBreakPoint));
+	test(info.iThreadBreakPointInfo.iRmdArmExcInfo.iR15 == address);
+	test(info.iProcessIdValid);
+	test(info.iThreadIdValid);
+
+	// Not interested in breakpoint events any more
+	err = aThreadSpecific
+		? iServSession.SetEventAction(iFileName,EEventsBreakPoint, EActionIgnore)
+		: iServSession.SetEventAction(iFileName, EEventsProcessBreakPoint, EActionIgnore);
+	test (err == KErrNone);
+
+	// Clear the breakpoint again
+	err = iServSession.ClearBreak(armBreakId);
+	test(err == KErrNone);
+
+	// continue the thread again
+	err = iServSession.ResumeThread(iThreadID);
+	test (err == KErrNone);
+	test(KErrNone == iServSession.DetachExecutable(iFileName));
+	}
+
+//---------------------------------------------
+//! @SYMTestCaseID KBASE-rmdebug2-2704
+//! @SYMTestType
+//! @SYMPREQ PREQ1426
+//! @SYMTestCaseDesc Test breakpoints in a loop
+//! @SYMTestActions Several calls to register to verify breakpoints are stopping at correct address
+//! @SYMTestExpectedResults All tests should pass and the target thread should be left unaffected
+//! @SYMTestPriority High
+//! @SYMTestStatus Implemented
+//---------------------------------------------
+void CRunModeAgent::TestBreakPointsInLoop()
+	{
+	test.Next(_L("TestBreakPointsInLoop\n"));
+
+	DoTestBreakPointsInLoop(ETrue);
+	DoTestBreakPointsInLoop(EFalse);
+	}
+
+void CRunModeAgent::DoTestBreakPointsInLoop(TBool aThreadSpecific)
+	{
+	test.Printf(_L("DoTestBreakPointsInLoop: aThreadSpecific: %d\n"), aThreadSpecific?1:0);
+
+	TInt err = KErrNone;
+	TProcessId processId = RProcess().Id(); 
+
+	test(KErrNone == iServSession.AttachExecutable(iFileName, EFalse));
+	
+	// We should suspend the thread first, then set the breakpoint
+	err = iServSession.SuspendThread(iThreadID);
+	test (err == KErrNone);
+
+	// 2 breakpoints are sufficient to find issues with hitting breakpoints in a loop
+	const TInt numOfBreakPointsInLoop = 2;
+
+	TBreakId armBreakId[numOfBreakPointsInLoop];
+	TUint32 address[numOfBreakPointsInLoop];
+   	
+	TUint32 entryAddress = (TUint32)(&RMDebug_Bkpt_Test_Entry);
+	TBreakId entryArmBreakId;
+
+	// Copy breakpoint address's in array
+	address[0] = (TUint32)(&RMDebug_Bkpt_Test_Loop_Break_1);
+	address[1] = (TUint32)(&RMDebug_Bkpt_Test_Loop_Break_2);
+
+	err = aThreadSpecific
+		? iServSession.SetBreak(entryArmBreakId,iThreadID,entryAddress,EArmMode)
+		: iServSession.SetProcessBreak(entryArmBreakId, processId, entryAddress, EArmMode);
+	test(err == KErrNone);
+
+	// Try to set the breakpoints inside loop
+	for (TInt i = 0; i < numOfBreakPointsInLoop; i++)
+		{
+		err = aThreadSpecific
+			? iServSession.SetBreak(armBreakId[i],iThreadID,address[i],EArmMode)
+			: iServSession.SetProcessBreak(armBreakId[i], processId, address[i], EArmMode);
+		test(err == KErrNone);
+		}
+
+	err = aThreadSpecific
+		? iServSession.SetEventAction(iFileName,EEventsBreakPoint, EActionSuspend)
+		: iServSession.SetEventAction(iFileName,EEventsProcessBreakPoint, EActionSuspend);
+	test (err == KErrNone);
+
+	// Continue the thread
+	err = iServSession.ResumeThread(iThreadID);
+	test (err == KErrNone);
+
+	// Wait for the breakpoint to be hit
+	TEventInfo info;
+	TRequestStatus status;
+
+	TPtr8 infoPtr((TUint8*)&info,0,sizeof(TEventInfo));
+	iServSession.GetEvent(iFileName,status,infoPtr);
+
+	// Wait for notification of breakpoint event
+	User::WaitForRequest(status);
+	test(status==KErrNone);
+
+	// Info should now be filled with the details
+	test(info.iEventType == (aThreadSpecific ? EEventsBreakPoint : EEventsProcessBreakPoint));
+
+	// Have we stopped at the correct breakpoint?
+	test(info.iThreadBreakPointInfo.iRmdArmExcInfo.iR15 == entryAddress);
+	test(info.iProcessIdValid);
+	test(info.iThreadIdValid);
+
+	// Don't require the entry breakpoint anymore
+	err = iServSession.ClearBreak(entryArmBreakId);
+	test(err == KErrNone);
+	
+	// Stress the system by setting loop count to 100
+	const TUint32 loopCount = 100;
+
+	for (TInt i = 0; i < loopCount; i++)
+		{
+		// Continue the thread
+		err = iServSession.ResumeThread(iThreadID);
+		test (err == KErrNone);
+
+		// Wait for the breakpoint to be hit
+		iServSession.GetEvent(iFileName,status,infoPtr);
+		
+		// Wait for notification of the breakpoint hit event
+		User::WaitForRequest(status);
+		test(status==KErrNone);
+		
+		// Info should now be filled with the details
+		test(info.iEventType == (aThreadSpecific ? EEventsBreakPoint : EEventsProcessBreakPoint));
+		
+		// Have we stopped at the correct breakpoint?
+		test(info.iThreadBreakPointInfo.iRmdArmExcInfo.iR15 == address[i%numOfBreakPointsInLoop]);
+		
+		// Check process and thread id too
+		test(info.iProcessIdValid);
+		test(info.iThreadIdValid);
+		}
+
+	// Not interested in breakpoint events any more
+	err = aThreadSpecific
+		? iServSession.SetEventAction(iFileName,EEventsBreakPoint, EActionIgnore)
+		: iServSession.SetEventAction(iFileName, EEventsProcessBreakPoint, EActionIgnore);
+	test (err == KErrNone);
+
+	// Clear breakpoints
+	for (TInt i = 0; i < numOfBreakPointsInLoop; i++)
+		{
+		err = iServSession.ClearBreak(armBreakId[i]);
+		test(err == KErrNone);
+		}
+	
+	// Continue the thread again
+	err = iServSession.ResumeThread(iThreadID);
+	test (err == KErrNone);
+	test(KErrNone == iServSession.DetachExecutable(iFileName));
+	}
+
+//----------------------------------------------------------------------------------------------
+//! @SYMTestCaseID      KBase-T-RMDEBUG2-0440
+//! @SYMTestType
+//! @SYMPREQ            PREQ1426
+//! @SYMTestCaseDesc    Test access to target user-side registers.
+//! @SYMTestActions     Suspends a target thread, and reads/writes target thread register contents
+//!
+//! @SYMTestExpectedResults KErrNone. Should access target registers without problems.
+//! @SYMTestPriority        High
+//! @SYMTestStatus          Implemented
+//----------------------------------------------------------------------------------------------
+
+void CRunModeAgent::TestRegisterAccess()
+	{
+	TInt err;
+
+	test.Next(_L("TestRegisterAccess - Read\n"));
+
+	test(KErrNone == iServSession.AttachExecutable(iFileName, EFalse));
+
+	//suspend the thread to read registers
+	err = iServSession.SuspendThread(iThreadID);
+	test(err==KErrNone);
+
+	//we'll try to read/write registers ERegisterR0 - ERegisterCPSR and ERegisterR13_IRQ
+	//this way should get valid register values back, invalid ones and not supported ones, and it
+	//means that the register IDs are not completely contiguous
+
+	TInt firstRegister = 0;
+	TInt lastRegister = 17;
+	TInt numberOfRegisters = (lastRegister - firstRegister) + 1;
+
+	RBuf8 ids;
+	err = ids.Create(numberOfRegisters * sizeof(TRegisterInfo));
+	test(err == KErrNone);
+
+	for(TInt i=0; i<numberOfRegisters - 1; i++)
+		{
+		TRegisterInfo reg = (TRegisterInfo)((i + firstRegister)<<8);
+		ids.Append(reinterpret_cast<const TUint8*>(&reg), sizeof(TRegisterInfo));
+		}
+
+	TRegisterInfo reg = ERegisterR13Irq;
+	ids.Append(reinterpret_cast<const TUint8*>(&reg), sizeof(TRegisterInfo));
+
+	//create a buffer to store the register values in
+	RBuf8 originalValues;
+	err = originalValues.Create(numberOfRegisters*sizeof(TUint32));
+	test(err == KErrNone);
+
+	//create a buffer to store the register flags in
+	RBuf8 originalFlags;
+	err = originalFlags.Create(numberOfRegisters*sizeof(TUint8));
+	test(err == KErrNone);
+
+	//read register values
+	err = iServSession.ReadRegisters(iThreadID, ids, originalValues, originalFlags);
+	test(err == KErrNone);
+
+	//create a buffer containing data to write into the registers
+	RBuf8 tempValues;
+	err = tempValues.Create(numberOfRegisters*sizeof(TUint32));
+	test(err == KErrNone);
+
+	TUint cpsrId = 16;
+	for(TUint8 i=0; i<numberOfRegisters*sizeof(TUint32); i++)
+		{
+		if(i/sizeof(TUint32) == cpsrId)
+			{
+			//For the CPSR we wish to write data that makes sense - for USR mode we are
+			//allowed change all except the mode, ie. we must stay in usr mode. We try that here
+			//(allowedCPSRValue[4:0] = 10000) thus not changing the mode.
+			TUint32 allowedCPSRValue = 0x50000010;
+			tempValues.Append((TUint8*)&allowedCPSRValue, 4);
+			i += 3;
+			}
+		else
+			{
+			tempValues.Append(&i, 1);
+			}
+		}
+
+	test.Next(_L("TestRegisterAccess - Write\n"));
+
+	//create a buffer to store the register flags in
+	RBuf8 tempWriteFlags;
+	err = tempWriteFlags.Create(numberOfRegisters*sizeof(TUint8));
+	test(err == KErrNone);
+
+	//write the temp data into the registers
+	err = iServSession.WriteRegisters(iThreadID, ids, tempValues, tempWriteFlags);
+	test(err == KErrNone);
+
+	//create another buffer to store the register flags in
+	RBuf8 tempReadFlags;
+	err = tempReadFlags.Create(numberOfRegisters*sizeof(TUint8));
+	test(err == KErrNone);
+
+	RBuf8 tempReadValues;
+	err = tempReadValues.Create(numberOfRegisters*sizeof(TUint32));
+	test(err == KErrNone);
+
+	//read the temp data out again
+	err = iServSession.ReadRegisters(iThreadID, ids, tempReadValues, tempReadFlags);
+	test(err == KErrNone);
+
+	//check values are correct
+	for(TInt i=0; i<numberOfRegisters; i++)
+		{
+		TRegisterFlag writeFlag;
+		err = GetFlag(tempWriteFlags, i, writeFlag);
+		test(err == KErrNone);
+
+		TRegisterFlag readFlag;
+		err = GetFlag(tempReadFlags, i, readFlag);
+		test(err == KErrNone);
+
+		if((writeFlag == EValid) && (readFlag == EValid))
+			{
+			TUint8 offset = i * sizeof(TUint32);
+			for(TUint j = offset; j< offset + sizeof(TUint32); j++)
+				{
+				test(tempValues.Ptr()[j] == tempReadValues.Ptr()[j]);
+				}
+			}
+		}
+
+	//write the original data into the registers
+	err = iServSession.WriteRegisters(iThreadID, ids, originalValues, originalFlags);
+	test(err == KErrNone);
+
+	//read the data out again
+	err = iServSession.ReadRegisters(iThreadID, ids, tempValues, tempReadFlags);
+	test(err == KErrNone);
+
+	//check values are correct
+	for(TInt i=0; i<numberOfRegisters; i++)
+		{
+		TRegisterFlag writeFlag;
+		err = GetFlag(originalFlags, i, writeFlag);
+		test(err == KErrNone);
+
+		TRegisterFlag readFlag;
+		err = GetFlag(tempReadFlags, i, readFlag);
+		test(err == KErrNone);
+
+		if((writeFlag == EValid) && (readFlag == EValid))
+			{
+			TUint8 offset = i * sizeof(TUint32);
+			for(TUint j = offset; j< offset + sizeof(TUint32); j++)
+				{
+				test(tempValues.Ptr()[j] == originalValues.Ptr()[j]);
+				}
+			}
+		}
+
+	test.Next(_L("TestRegisterAccess - Invalid data\n"));
+
+	//create a buffer of max size 1
+	RBuf8 emptyBuffer;
+	emptyBuffer.Create(1);
+
+	//test register IDs buffer not being a multiple of sizeof(TRegisterInfo)
+	err = iServSession.ReadRegisters(iThreadID, emptyBuffer, tempValues, tempReadFlags);
+	test(err == KErrArgument);
+
+	//test register values buffer not being a multiple of sizeof(TUint32)
+	err = iServSession.ReadRegisters(iThreadID, ids, emptyBuffer, tempReadFlags);
+	test(err == KErrArgument);
+
+	//test flags buffer being representing different number of registers from other two
+	err = iServSession.ReadRegisters(iThreadID, ids, tempValues, emptyBuffer);
+	test(err == KErrArgument);
+
+	//set max length to 0
+	emptyBuffer.ReAlloc(0);
+
+	//test ids buffer being of 0 max length
+	err = iServSession.ReadRegisters(iThreadID, emptyBuffer, tempValues, tempReadFlags);
+	test(err == KErrArgument);
+
+	//do cleanup
+	emptyBuffer.Close();
+	tempValues.Close();
+	tempWriteFlags.Close();
+	tempReadFlags.Close();
+	tempReadValues.Close();
+
+	test.Next(_L("TestRegisterAccess - Setting PC value\n"));
+
+	//create buffer containing PC register ID
+	RBuf8 pcId;
+	err = pcId.Create(sizeof(TRegisterInfo));
+	test(err == KErrNone);
+	TRegisterInfo reg1 = (TRegisterInfo)0x00000f00;
+	pcId.Append(reinterpret_cast<const TUint8*>(&reg1), sizeof(TRegisterInfo));
+
+	//create buffer containing desired PC value
+	RBuf8 pcValue;
+	err = pcValue.Create(sizeof(TUint32));
+	test(err == KErrNone);
+	TUint32 address = (TUint32)(&TestFunction);
+	pcValue.Append(reinterpret_cast<const TUint8*>(&address), sizeof(TUint32));
+
+	//craete buffer for PC flag value
+	RBuf8 pcFlag;
+	err = pcFlag.Create(sizeof(TUint8));
+
+	//write the new PC value
+	err = iServSession.WriteRegisters(iThreadID, pcId, pcValue, pcFlag);
+	test(err==KErrNone);
+
+	//get the flag and check the PC value was written ok
+	TRegisterFlag flag = ENotSupported;
+	err = GetFlag(pcFlag, 0, flag);
+	test(err==KErrNone);
+	test( flag == EValid);
+	if(flag == EValid)
+		{
+		/* The PC value was changed to execute the function TestFunction.
+		* TestFunction changes the value of TestData to a given value and 
+		* then calls RMDebug_BranchTst1.
+		* We place a breakpoint on RMDebug_BranchTst1 so that to we are able 
+		* to test the value of TestData.
+		*/
+
+		test(KErrNone == iServSession.SetEventAction(iFileName,EEventsBreakPoint, EActionSuspend));
+		TBreakId armBreakId;
+		TUint32 address = (TUint32)(&RMDebug_BranchTst1);
+		test(KErrNone == iServSession.SetBreak(armBreakId,iThreadID,address,EArmMode));
+
+		// Continue the thread
+		test(KErrNone == iServSession.ResumeThread(iThreadID));
+
+		// wait for the breakpoint to be hit
+		TEventInfo info;
+		static TRequestStatus status;
+
+		TPtr8 infoPtr((TUint8*)&info,0,sizeof(TEventInfo));
+		iServSession.GetEvent(iFileName,status,infoPtr);
+
+		// Wait for notification of the breakpoint hit event
+		User::WaitForRequest(status);
+		test(status==KErrNone);
+
+		// info should now be filled with the details
+		test(info.iEventType == EEventsBreakPoint);
+		test(info.iThreadBreakPointInfo.iRmdArmExcInfo.iR15 == address);
+		test(info.iProcessIdValid);
+		test(info.iThreadIdValid);
+
+		test(KErrNone == iServSession.ClearBreak(armBreakId));
+
+		// Finally test the value
+		test(TestData == 0xffeeddcc);
+		}
+
+	//Make sure we cannot change the CPSR
+	test.Next(_L("Verifying we cannot change the CPSR mode from USR Mode"));
+
+	TUint32 disallowedCpsr = 0x50000013;
+
+	RBuf8 cpsrRegId;
+	err = cpsrRegId.Create(sizeof(TUint32));
+	test(err == KErrNone);
+
+	TRegisterInfo cpsr = (TRegisterInfo)((cpsrId + firstRegister)<<8);
+	cpsrRegId.Append(reinterpret_cast<const TUint8*>(&cpsr), sizeof(TRegisterInfo));
+
+	RBuf8 cpsrRegFlags;
+	err = cpsrRegFlags.Create(sizeof(TUint8));
+	test(err == KErrNone);
+
+	RBuf8 cpsrVal;
+	err = cpsrVal.Create(sizeof(TUint32));
+	test(err == KErrNone);
+
+	cpsrVal.Append((TUint8*)&disallowedCpsr, 4);
+
+	//attempt to write disallowed CPSR in
+	err = iServSession.WriteRegisters(iThreadID, cpsrRegId, cpsrVal, cpsrRegFlags);
+	test(err == KErrNone);
+
+	RBuf8 cpsrReadVal;
+	err = cpsrReadVal.Create(sizeof(TUint32));
+	test(err == KErrNone);
+
+	//Read back the CPSR
+	err = iServSession.ReadRegisters(iThreadID, cpsrRegId, cpsrReadVal, cpsrRegFlags);
+	test(err == KErrNone);
+
+	//Make sure we havent switched modes ie. its not what we wrote
+	TUint32* readVal = (TUint32*)cpsrReadVal.Ptr();
+	test(*readVal != disallowedCpsr);
+
+	cpsrRegId.Close();
+	cpsrRegFlags.Close();
+	cpsrVal.Close();
+	cpsrReadVal.Close();
+
+	//write the original values back into here
+	err = iServSession.WriteRegisters(iThreadID, ids, originalValues, originalFlags);
+	test(err == KErrNone);
+	
+	test(KErrNone == SwitchTestFunction(EDefaultFunction));
+
+	// Resume the thread
+	err = iServSession.ResumeThread(iThreadID);
+	test(err==KErrNone);
+
+	test(KErrNone == iServSession.DetachExecutable(iFileName));
+
+	//do cleanup
+	pcId.Close();
+	pcValue.Close();
+	pcFlag.Close();
+	ids.Close();
+	originalValues.Close();
+	originalFlags.Close();
+	}
+
+//----------------------------------------------------------------------------------------------
+//! @SYMTestCaseID      KBase-T-RMDEBUG2-0441
+//! @SYMTestType
+//! @SYMPREQ            PREQ1426
+//! @SYMTestCaseDesc    Test registration/de-registration of debug interest in target exe with the Debug Security Server
+//! @SYMTestActions     As per description
+//!
+//! @SYMTestExpectedResults KErrNone.
+//! @SYMTestPriority        High
+//! @SYMTestStatus          Implemented
+//----------------------------------------------------------------------------------------------
+
+void CRunModeAgent::TestAttachExecutable()
+	{
+
+	test.Next(_L("TestAttachExecutable - Attach\n"));
+
+	//attach to process passively
+	test(KErrNone == iServSession.AttachExecutable(iFileName, ETrue));
+
+	//make a thread id for a non-existent thread
+	TThreadId threadId(0x12345678);
+
+	//get a handle to the target thread
+	RThread targetThread;
+	TInt err = targetThread.Open(threadId);
+	test(err != KErrNone);
+
+	//not registered for this thread's process (as it doesn't exist)
+	//so should fail security check
+	err = iServSession.ResumeThread(threadId);
+	test(err==KErrPermissionDenied || err==KErrNotFound); // newer DSS returns the more-descriptive KErrNotFound here
+
+	//try to attach to the same process (and fail)
+	test(KErrAlreadyExists == iServSession.AttachExecutable(iFileName, EFalse));
+
+	test.Next(_L("TestAttachExecutable - Detach\n"));
+
+	//detach from process
+	test(KErrNone == iServSession.DetachExecutable(iFileName));
+
+	//attach non-passively
+	test(KErrNone == iServSession.AttachExecutable(iFileName, EFalse));
+
+	//not registered for this thread's process (as it doesn't exist)
+	//so should fail security check
+	err = iServSession.ResumeThread(0x12345678);
+	test(err==KErrPermissionDenied || err==KErrNotFound); // newer DSS returns the more-descriptive KErrNotFound here
+	test(KErrNone == iServSession.DetachExecutable(iFileName));
+	}
+
+//----------------------------------------------------------------------------------------------
+//! @SYMTestCaseID      KBase-T-RMDEBUG2-0442
+//! @SYMTestType
+//! @SYMPREQ            PREQ1426
+//! @SYMTestCaseDesc    Tests single-stepping target threads.
+//! @SYMTestActions     Steps target thread assembly level instructions, mainly branch/change PC
+//!
+//! @SYMTestExpectedResults KErrNone.
+//! @SYMTestPriority        High
+//! @SYMTestStatus          Implemented
+//----------------------------------------------------------------------------------------------
+
+void CRunModeAgent::TestStep()
+	{
+	test.Next(_L("TestStep\n"));
+
+	DoTestStep(EFalse);
+	DoTestStep(ETrue);
+	}
+
+void CRunModeAgent::DoTestStep(TBool aThreadSpecific)
+	{
+	test.Printf(_L("DoTestStep: aThreadSpecific: %d\n"), aThreadSpecific?1:0);
+
+	TInt err = KErrNone;
+
+	RProcess process;
+	TProcessId processId = process.Id();
+	process.Close();
+
+	test(KErrNone == iServSession.AttachExecutable(iFileName, EFalse));
+	//set the target thread to execute the stepping functions
+	test(KErrNone == SwitchTestFunction(EStepFunction, EFalse));
+
+	
+	err = iServSession.SetEventAction(iFileName,EEventsBreakPoint, EActionContinue);
+	test (err == KErrNone);
+
+	if(!aThreadSpecific)
+		{
+		err = iServSession.SetEventAction(iFileName, EEventsProcessBreakPoint, EActionContinue);
+		test (err == KErrNone);
+		}
+
+	TUint32	startAddress;
+	TUint32	endAddress;
+
+	/*
+	 * RMDebug_StepTest_Non_PC_Modifying
+	 */
+	test.Next(_L("TestStep - Non-PC modifying\n"));
+
+	startAddress = (TUint32)(&RMDebug_StepTest_Non_PC_Modifying);
+
+	endAddress = (TUint32)(&RMDebug_StepTest_Non_PC_Modifying_OK);
+
+	err = aThreadSpecific
+		? HelpTestStep(iThreadID,startAddress,endAddress,EArmMode,1)
+		: HelpTestStep(iThreadID,startAddress,endAddress,EArmMode,1, EFalse, processId);
+	test(err==KErrNone);
+
+	/*
+	 * RMDebug_StepTest_Branch
+	 */
+	test.Next(_L("TestStep - Branch\n"));
+
+	startAddress = (TUint32)(&RMDebug_StepTest_Branch);
+
+	endAddress = (TUint32)(&RMDebug_StepTest_Branch_1);
+
+	err = aThreadSpecific
+		? HelpTestStep(iThreadID,startAddress,endAddress,EArmMode,1)
+		: HelpTestStep(iThreadID,startAddress,endAddress,EArmMode,1, EFalse, processId);
+	test(err==KErrNone);
+
+	/*
+	 * RMDebug_StepTest_Branch_And_Link
+	 */
+	test.Next(_L("TestStep - Branch_And_Link\n"));
+
+	startAddress = (TUint32)(&RMDebug_StepTest_Branch_And_Link_1);
+
+	endAddress = (TUint32)(&RMDebug_StepTest_Branch_And_Link_2);
+
+	err = aThreadSpecific
+		? HelpTestStep(iThreadID,startAddress,endAddress,EArmMode,1)
+		: HelpTestStep(iThreadID,startAddress,endAddress,EArmMode,1, EFalse, processId);
+	test(err==KErrNone);
+
+	/*
+	 * RMDebug_StepTest_MOV_PC
+	 */
+	test.Next(_L("TestStep - MOV PC,X\n"));
+
+	startAddress = (TUint32)(&RMDebug_StepTest_MOV_PC_1);
+
+	endAddress = (TUint32)(&RMDebug_StepTest_MOV_PC_2);
+
+	err = aThreadSpecific
+		? HelpTestStep(iThreadID,startAddress,endAddress,EArmMode,1)
+		: HelpTestStep(iThreadID,startAddress,endAddress,EArmMode,1, EFalse, processId);
+	test(err==KErrNone);
+
+	/*
+	 * RMDebug_StepTest_LDR_PC
+	 */
+	test.Next(_L("TestStep - LDR PC\n"));
+
+	startAddress = (TUint32)(&RMDebug_StepTest_LDR_PC);
+
+	endAddress = (TUint32)(&RMDebug_StepTest_LDR_PC_1);
+
+	err = aThreadSpecific
+		? HelpTestStep(iThreadID,startAddress,endAddress,EArmMode,1)
+		: HelpTestStep(iThreadID,startAddress,endAddress,EArmMode,1, EFalse, processId);
+	test(err==KErrNone);
+
+// thumb and interworking tests are not supported on armv4
+#ifdef __MARM_ARMV5__
+
+	/*
+	 * RMDebug_StepTest_Thumb_Non_PC_Modifying
+	 */
+	test.Next(_L("TestStep - Thumb Non PC-Modifying\n"));
+
+	startAddress = (TUint32)(&RMDebug_StepTest_Thumb_Non_PC_Modifying_1);
+
+	endAddress = (TUint32)(&RMDebug_StepTest_Thumb_Non_PC_Modifying_2);
+
+	err = aThreadSpecific
+		? HelpTestStep(iThreadID,startAddress,endAddress,EThumbMode,1)
+		: HelpTestStep(iThreadID,startAddress,endAddress,EThumbMode,1, EFalse, processId);
+	test(err==KErrNone);
+
+	/*
+	 * RMDebug_StepTest_Thumb_Branch
+	 */
+	test.Next(_L("TestStep - Thumb Branch\n"));
+
+	startAddress = (TUint32)(&RMDebug_StepTest_Thumb_Branch_1);
+
+	endAddress = (TUint32)(&RMDebug_StepTest_Thumb_Branch_2);
+
+	err = aThreadSpecific
+		? HelpTestStep(iThreadID,startAddress,endAddress,EThumbMode,1)
+		: HelpTestStep(iThreadID,startAddress,endAddress,EThumbMode,1, EFalse, processId);
+	test(err==KErrNone);
+
+	/*
+	 * RMDebug_StepTest_Thumb_Branch_And_Link
+	 */
+	test.Next(_L("TestStep - Thumb Branch_And_Link\n"));
+
+	startAddress = (TUint32)(&RMDebug_StepTest_Thumb_Branch_And_Link_2);
+
+	endAddress = (TUint32)(&RMDebug_StepTest_Thumb_Branch_And_Link_3);
+
+	TInt muid=0;
+    test(HAL::Get(HAL::EMachineUid, muid)==KErrNone);
+
+	// check if running on ARMv7 core
+	if(muid==HAL::EMachineUid_OmapH6 || muid==HAL::EMachineUid_OmapZoom || muid==HAL::EMachineUid_EmuBoard)
+        {
+        // Note: ARMv7 treats BL instructions as single 32-bit instructions
+        err = aThreadSpecific
+		? HelpTestStep(iThreadID,startAddress,endAddress,EThumbMode,1)
+		: HelpTestStep(iThreadID,startAddress,endAddress,EThumbMode,1, EFalse, processId);
+        }
+    else
+	    {
+        // Note: Due to the fact that the stepper treats BL instructions
+		// as two instructions (as the hardware does), then we must step
+		// the first half instruction first)
+
+		err = aThreadSpecific
+		? HelpTestStep(iThreadID,startAddress,startAddress+2,EThumbMode,1)
+		: HelpTestStep(iThreadID,startAddress,startAddress+2,EThumbMode,1, EFalse, processId);
+		test(err==KErrNone);
+
+	// Now we actually do the BL
+	err = aThreadSpecific
+		? HelpTestStep(iThreadID,startAddress+2,endAddress,EThumbMode,1)
+		: HelpTestStep(iThreadID,startAddress+2,endAddress,EThumbMode,1, EFalse, processId);
+        }
+	test(err==KErrNone);
+
+	/*
+	 * RMDebug_StepTest_Thumb_Back_Branch_And_Link
+	 */
+	test.Next(_L("TestStep - Thumb Back_Branch_And_Link\n"));
+
+	startAddress = (TUint32)(&RMDebug_StepTest_Thumb_Back_Branch_And_Link_2);
+
+	endAddress = (TUint32)(&RMDebug_StepTest_Thumb_Back_Branch_And_Link_3);
+
+	// check if running on ARMv7 core
+	if(muid==HAL::EMachineUid_OmapH6 || muid==HAL::EMachineUid_OmapZoom || muid==HAL::EMachineUid_EmuBoard)
+		{
+		// Note: ARMv7 treats BL instructions as single 32-bit instructions
+		err = aThreadSpecific
+			? HelpTestStep(iThreadID,startAddress,endAddress,EThumbMode,1)
+			: HelpTestStep(iThreadID,startAddress,endAddress,EThumbMode,1, EFalse, processId);
+		}
+	else
+		{
+		// Note: Due to the fact that the stepper treats BL instructions
+		// as two instructions (as the hardware does), then we must step
+		// the first half instruction first)
+
+		err = aThreadSpecific
+	   		? HelpTestStep(iThreadID,startAddress,startAddress+2,EThumbMode,1)
+			: HelpTestStep(iThreadID,startAddress,startAddress+2,EThumbMode,1, EFalse, processId);
+		test(err==KErrNone);
+
+	   	// Now we actually do the BL
+		err = aThreadSpecific
+   			? HelpTestStep(iThreadID,startAddress+2,endAddress,EThumbMode,1)
+			: HelpTestStep(iThreadID,startAddress+2,endAddress,EThumbMode,1, EFalse, processId);
+		}
+	test(err==KErrNone);
+
+	/*
+	 * RMDebug_StepTest_Thumb_AddPC
+	 */
+	test.Next(_L("TestStep - Thumb ADD PC, PC, R0\n"));
+
+	startAddress = (TUint32)(&RMDebug_StepTest_Thumb_AddPC_2);
+
+	endAddress = (TUint32)(&RMDebug_StepTest_Thumb_AddPC_3);
+
+	err = aThreadSpecific
+		? HelpTestStep(iThreadID,startAddress,endAddress,EThumbMode,1)
+		: HelpTestStep(iThreadID,startAddress,endAddress,EThumbMode,1, EFalse, processId);
+	test(err==KErrNone);
+
+	/*
+	 * RMDebug_StepTest_Interwork ARM to Thumb
+	 */
+	test.Next(_L("TestStep - Interworking ARM to Thumb - BLX \n"));
+
+	startAddress = (TUint32)(&RMDebug_StepTest_Interwork_1);
+
+	endAddress = (TUint32)(&RMDebug_StepTest_Interwork_2);
+
+	err = aThreadSpecific // nb initial breakpoint in ARM code
+		? HelpTestStep(iThreadID,startAddress,endAddress,EArmMode,1)
+		: HelpTestStep(iThreadID,startAddress,endAddress,EArmMode,1, EFalse, processId);
+
+	test(err==KErrNone);
+
+	/*
+	 * RMDebug_StepTest_Interwork Thumb to ARM
+	 */
+	test.Next(_L("TestStep - Interworking Thumb to ARM - BLX\n"));
+
+	startAddress = (TUint32)(&RMDebug_StepTest_Interwork_2);
+
+	endAddress = (TUint32)(&RMDebug_StepTest_Interwork_3);
+
+	// check if running on ARMv7 core
+	if(muid==HAL::EMachineUid_OmapH6 || muid==HAL::EMachineUid_OmapZoom || muid==HAL::EMachineUid_EmuBoard)
+        {
+        // ARMv7 treats BLX instructions as single 32-bit instructions
+        err = aThreadSpecific
+		? HelpTestStep(iThreadID,startAddress,endAddress,EThumbMode,1)
+		: HelpTestStep(iThreadID,startAddress,endAddress,EThumbMode,1, EFalse, processId);
+        }
+    else
+        {
+    	// Stepper treats this as a two-stage instruction (just like the hardware)
+	err = aThreadSpecific
+		? HelpTestStep(iThreadID,startAddress,startAddress+2,EThumbMode,1)
+		: HelpTestStep(iThreadID,startAddress,startAddress+2,EThumbMode,1, EFalse, processId);
+	test(err == KErrNone);
+
+	err = aThreadSpecific
+		? HelpTestStep(iThreadID,startAddress+2,endAddress,EThumbMode,1)
+		: HelpTestStep(iThreadID,startAddress+2,endAddress,EThumbMode,1, EFalse, processId);
+        }
+	test(err == KErrNone);
+
+#endif // __MARM_ARMV5__
+
+	/*
+	 * Test multiple-step of ARM code
+	 */
+	test.Next(_L("TestStep - ARM Multiple instruction step\n"));
+
+	startAddress = (TUint32)(&RMDebug_StepTest_ARM_Step_Multiple);
+
+	endAddress = (TUint32)(&RMDebug_StepTest_ARM_Step_Multiple_1);
+
+	err = aThreadSpecific
+		? HelpTestStep(iThreadID,startAddress,endAddress,EArmMode,5)
+		: HelpTestStep(iThreadID,startAddress,endAddress,EArmMode,5, EFalse, processId);
+	test(err == KErrNone);
+	// stepping performance
+	test.Next(_L("TestStep - Steps per second\n"));
+
+	// run until we reach RMDebug_StepTest_Count_1
+	TBreakId stepBreakId;
+	startAddress = (TUint32)(&RMDebug_StepTest_Count_1);
+	endAddress = (TUint32)(&RMDebug_StepTest_Count_2);
+
+	err = aThreadSpecific
+		? HelpTestStepSetBreak(stepBreakId,iThreadID,startAddress,EArmMode)
+		: HelpTestStepSetBreak(stepBreakId,iThreadID,startAddress,EArmMode,EFalse,processId);
+	test (err == KErrNone);
+
+	// wait until we hit the breakpoint
+	TEventInfo info;
+	err = HelpTestStepWaitForBreak(iFileName,info);
+	test (err == KErrNone);
+
+	// Now clear the breakpoint
+	err = iServSession.ClearBreak(stepBreakId);
+	test(err == KErrNone);
+
+	if(aThreadSpecific)
+		{
+		// now step the code
+		TInt stepsPerSecond = 0;
+
+		TUint32 stopTickCount = User::NTickCount() + HelpTicksPerSecond();
+
+		while (User::NTickCount() < stopTickCount)
+			{
+			err = iServSession.Step(iThreadID,1);
+			test (err == KErrNone);
+
+			// we need to wait now until the step completes before asking for the next step
+				{
+				TEventInfo info;
+				static TRequestStatus status;
+
+				TPtr8 infoPtr((TUint8*)&info,0,sizeof(TEventInfo));
+
+				iServSession.GetEvent(iFileName,status,infoPtr);
+
+				// Wait for notification of the breakpoint hit event
+				User::WaitForRequest(status);
+				test(status==KErrNone);
+				}
+
+			// Update the count of steps
+			stepsPerSecond += 1;
+
+			// Gone wrong if we do too many
+			test(stepsPerSecond < 10000);
+			}
+
+		iStepsPerSecond = stepsPerSecond;
+		test(iStepsPerSecond != 0);
+		}
+
+	// finally resume the thread
+	err = iServSession.ResumeThread(iThreadID);
+	test (err == KErrNone);
+
+	err = iServSession.SetEventAction(iFileName,EEventsBreakPoint, EActionIgnore);
+	test (err == KErrNone);
+
+	if(!aThreadSpecific)
+		{
+		err = iServSession.SetEventAction(iFileName, EEventsProcessBreakPoint, EActionIgnore);
+		test (err == KErrNone);
+		}
+
+	test(KErrNone == iServSession.DetachExecutable(iFileName));
+	}
+
+//----------------------------------------------------------------------------------------------
+//! @SYMTestCaseID      KBase-T-RMDEBUG2-0443
+//! @SYMTestType
+//! @SYMPREQ            PREQ1426
+//! @SYMTestCaseDesc    Tests registration and occurrence of target thread event (in this case panic)
+//! @SYMTestActions     Registers for a panic in the target thread, causes it, and catches the panic notification.
+//!
+//! @SYMTestExpectedResults KErrNone.
+//! @SYMTestPriority        High
+//! @SYMTestStatus          Implemented
+//----------------------------------------------------------------------------------------------
+
+void CRunModeAgent::TestEvents()
+	{
+	TInt err = KErrNone;
+
+	test.Next(_L("TestEvents\n"));
+
+	TInt panicReason = 12345;
+
+	test.Printf(_L("Thread t_rmdebug.exe::DebugThread should panic with reason %d.\n"), panicReason);
+
+	//attach non-passively
+	test(KErrNone == iServSession.AttachExecutable(iFileName, EFalse));
+
+	RThread threadToPanic;
+	test(KErrNone == StartDebugThread(threadToPanic, _L("EventsThread")));
+	TThreadId threadToPanicId = threadToPanic.Id();
+	TEventInfo info;
+
+	// Set things up to wait for a thread kill event
+	err = iServSession.SetEventAction(iFileName, EEventsKillThread, EActionContinue);
+	test(err==KErrNone);
+
+	// Wait for an event to occur in this process - nothing should have happened yet.
+	static TRequestStatus status;
+
+	TPtr8 infoPtr((TUint8*)&info,0,sizeof(TEventInfo));
+
+	iServSession.GetEvent(iFileName,status,infoPtr);
+
+	// Test Request cancellation
+	err = iServSession.CancelGetEvent(iFileName);
+	test (err==KErrNone);
+
+	// Again wait for an event to occur in our process - we will provoke the
+	// thread kill event by panic'ing the test thread.
+	iServSession.GetEvent(iFileName,status,infoPtr);
+
+	// Panic the debug thread to cause a thread kill event
+	threadToPanic.Panic(_L("t_rmdebug panic thread test"), panicReason);
+
+	// Wait for notification of the Thread Kill event
+	User::WaitForRequest(status);
+	test(status==KErrNone);
+
+	// Check we are really recieving information about the panic
+	test(info.iProcessIdValid);
+	test(info.iThreadIdValid);
+	test(info.iProcessId==RProcess().Id());
+	test(info.iThreadId==threadToPanicId);
+	test(info.iEventType==EEventsKillThread);
+	test(info.iThreadKillInfo.iExitType==EExitPanic);
+
+	// Ignore other panic events
+	err = iServSession.SetEventAction(iFileName, EEventsKillThread, EActionIgnore);
+	test(err==KErrNone);
+
+	test(KErrNone == iServSession.DetachExecutable(iFileName));
+	}
+
+//----------------------------------------------------------------------------------------------
+//! @SYMTestCaseID      KBase-T-RMDEBUG2-0444
+//! @SYMTestType
+//! @SYMPREQ            PREQ1426
+//! @SYMTestCaseDesc    Tests registration and occurence of target thread events in separate process.
+//! @SYMTestActions     Registers for a hardware exception and kill thread events, and receives them.
+//!
+//! @SYMTestExpectedResults KErrNone.
+//! @SYMTestPriority        High
+//! @SYMTestStatus          Implemented
+//----------------------------------------------------------------------------------------------
+void CRunModeAgent::TestEventsForExternalProcess()
+	{
+	test.Next(_L("TestEventsForExternalProcess\n"));
+
+	for(TInt main=0; main<3; main++)
+		{
+		for(TInt extra=0; extra<3; extra++)
+			{
+			TestEventsWithExtraThreads((TKernelEventAction)main, (TKernelEventAction)extra, 0);
+			TestEventsWithExtraThreads((TKernelEventAction)main, (TKernelEventAction)extra, 2);
+			}
+		}
+	}
+
+void CRunModeAgent::TestEventsWithExtraThreads(TKernelEventAction aActionMain, TKernelEventAction aActionExtra, TUint32 aExtraThreads)
+	{
+	const TInt KNumberOfTypes = 8;
+	struct TEventStruct
+		{
+		public:
+		TDebugFunctionType iDebugFunctionType;
+		TEventType iEventType;
+		};
+
+	TEventStruct type[KNumberOfTypes] =
+		{
+			{EStackOverflowFunction, EEventsHwExc},
+			{EUserPanicFunction, EEventsKillThread},
+			{EPrefetchAbortFunction, EEventsHwExc},
+			{EDataAbortFunction, EEventsHwExc},
+			{EUndefInstructionFunction, EEventsHwExc},
+			{EDataReadErrorFunction, EEventsHwExc},
+			{EDataWriteErrorFunction, EEventsHwExc},
+			{EUserExceptionFunction, EEventsSwExc},
+		};
+
+	for(TInt j=0; j<KNumberOfTypes; j++)
+		{
+		if( gUseDelay ) User::After(500000);
+
+		RDebug::Printf("CRunModeAgent::TestEventsWithExtraThreads type: %d, main action: %d, extra action: %d, extraThreads: %d", 
+			j, (TUint32)aActionMain, (TUint32)aActionExtra, aExtraThreads);
+
+		// do this check as it seems to hard to do these cases with the current set up
+		if(EEventsKillThread == type[j].iEventType)
+			{
+			if(EActionSuspend != aActionMain)
+				{
+				if(aActionMain != aActionExtra)
+					{
+					return;
+					}
+				}
+			}
+		// attach to KRMDebugTestApplication
+		test(KErrNone == iServSession.AttachExecutable(KRMDebugTestApplication, EFalse));
+
+		// Set things up to wait for the expected exception in KRMDebugTestApplication
+		test(KErrNone == iServSession.SetEventAction(KRMDebugTestApplication, type[j].iEventType, aActionMain));
+
+		if(EActionSuspend != aActionMain)
+			{
+			test(KErrNone == iServSession.SetEventAction(KRMDebugTestApplication, EEventsKillThread, aActionExtra));
+			}
+
+		// declare a TRequestStatus object for asynchronous calls
+		TRequestStatus status;
+
+		TEventInfo info;
+		TPtr8 infoBuffer = TPtr8((TUint8*)&info,0,sizeof(TEventInfo));
+		if(EActionIgnore != aActionMain)
+			{
+			iServSession.GetEvent(KRMDebugTestApplication(), status, infoBuffer);
+			}
+
+		// launch the target process to trigger the expected exception
+		RProcess targetProcess;
+		test(KErrNone == LaunchProcess(targetProcess, KRMDebugTestApplication(), type[j].iDebugFunctionType, 0, aExtraThreads));
+		TProcessId processId(targetProcess.Id());
+		targetProcess.Close();
+
+		if(EActionIgnore != aActionMain)
+			{
+			// wait for notification of the exception
+			User::WaitForRequest(status);
+			test(KErrNone == status.Int());
+
+			// check that this is the event we were expecting
+			test(info.iProcessIdValid);
+			test(info.iThreadIdValid);
+			test(info.iProcessId==processId);
+			test(info.iEventType==type[j].iEventType);
+			}
+
+		if(EActionSuspend == aActionMain)
+			{
+			//RDebug::Printf("CRunModeAgent::TestEventsWithExtraThreads EActionSuspend == aActionMain, j=%d", j);
+			// read the thread list, partly to check the call works, and partly to check the thread still exists
+			test(ThreadExistsForProcess(info.iThreadId, info.iProcessId));
+
+			// register to catch all the thread kills which will occur
+			test(KErrNone == iServSession.SetEventAction(KRMDebugTestApplication, EEventsKillThread, aActionExtra));
+			// we specified EActionSuspend earlier so need to call resume on this thread
+			test(KErrNone == iServSession.ResumeThread(info.iThreadId));
+			}
+
+		// find out how many threads there are in the process and catch all the thread kill events,
+		// the number of kill thread events should correspond to the number of extra threads launched,
+		// plus one if the main thread panicked with a Sw/Hw exception
+		if(EActionIgnore != aActionExtra)
+			{
+			TInt dyingThreads = aExtraThreads + ( (type[j].iEventType != EEventsKillThread) ? 1 : 0);
+			for(TInt k=0; k<dyingThreads; k++)
+				{
+				//RDebug::Printf("CRunModeAgent::TestEventsWithExtraThreads dyingThreads, k=%d, j=%d", k,j);
+				iServSession.GetEvent(KRMDebugTestApplication(), status, infoBuffer);
+
+				// wait for notification of the kill thread
+				User::WaitForRequest(status);
+				test(KErrNone == status.Int());
+
+				// check that this is the event we were expecting
+				test(info.iProcessIdValid);
+				test(info.iThreadIdValid);
+				test(info.iProcessId==processId);
+				test(info.iEventType==EEventsKillThread);
+				if(EActionSuspend == aActionExtra)
+					{
+					// do some calls to check listings work ok at this stage
+					test(ProcessExists(info.iProcessId));
+					test(ThreadExistsForProcess(info.iThreadId, info.iProcessId));
+					// we specified EActionSuspend earlier so need to call resume on this thread
+					test(KErrNone == iServSession.ResumeThread(info.iThreadId));
+					}
+				}
+			}
+
+		if( gUseDelay ) User::After(500000);
+
+		// reset the thread kill event
+		test(KErrNone == iServSession.SetEventAction(KRMDebugTestApplication(), EEventsKillThread, EActionIgnore));
+
+		// reset events for KRMDebugTestApplication
+		test(KErrNone == iServSession.SetEventAction(KRMDebugTestApplication(), type[j].iEventType, EActionIgnore));
+
+		// finished debugging KRMDebugTestApplication so detach
+		test(KErrNone == iServSession.DetachExecutable(KRMDebugTestApplication()));
+	
+		// want to validate that the process has really exited, i.e. we're not accidentally keeping a handle to it...
+		TInt waitCount = 10;
+		while((waitCount-- > 0) && ProcessExists(processId))
+			{
+			/* Wait a little while and try again, just in case the process is still being removed.
+			This can happen on a very busy system or when a popup for the events is still active
+			*/
+			RDebug::Printf("CRunModeAgent::TestEventsWithExtraThreads. ProcessExists(id=%d), waiting count exit=%d", 
+				I64LOW(processId), waitCount);
+			User::After(50000);
+			}
+		test(!ProcessExists(processId));
+		}
+	}
+
+// helper function to check whether a thread with id aThreadId exists in the process with id aProcessId
+TBool CRunModeAgent::ThreadExistsForProcess(const TThreadId aThreadId, const TProcessId aProcessId)
+	{
+	RThread lThread;
+	TInt ret = lThread.Open( aThreadId.Id() );
+
+	if( ret != KErrNone )
+		{
+		RDebug::Printf("ThreadExistsForProcess: thread id=%d opening returned %d",
+			I64LOW( aThreadId.Id() ), ret );
+		lThread.Close();
+		return EFalse;
+		}
+
+	RProcess lProcess;
+	ret = lThread.Process( lProcess );
+
+	lThread.Close();
+
+	if( ret != KErrNone )
+		{
+		RDebug::Printf("ThreadExistsForProcess: proc opening returned %d", ret );
+		ret = KErrNotFound;
+		}
+	else if( lProcess.Id() != aProcessId )
+		{
+		RDebug::Printf("ThreadExistsForProcess: lProcess.Id()(%d)!= aProcessId(%d)",
+				I64LOW(lProcess.Id().Id()), I64LOW(aProcessId.Id()));
+		ret = KErrNotFound;
+		}
+
+	lProcess.Close();
+	
+	return ( ret == KErrNone );
+	}
+
+// helper function to check whether a process with id aProcessId exists
+TBool CRunModeAgent::ProcessExists(const TProcessId aProcessId)
+	{
+	TUint32 size;
+	RBuf8 buffer;
+	test(KErrNone == buffer.Create(1024));
+	TInt err = iServSession.GetList(EProcesses, buffer, size);
+	while(KErrTooBig == err)
+		{
+		size*=2;
+		test(size<=47*1024); // 256 TProcessListEntrys is about 46KB. (256 is max num processes)
+		test(KErrNone == buffer.ReAlloc(size));
+		err = iServSession.GetList(EProcesses, buffer, size);
+		}
+	test(KErrNone == err);
+
+	//look through the buffer and check if the target debug thread is there
+	TUint8* ptr = (TUint8*)buffer.Ptr();
+	const TUint8* ptrEnd = ptr + size;
+	while(ptr < ptrEnd)
+		{
+		TProcessListEntry& entry = *(TProcessListEntry*)ptr;
+		if(aProcessId.Id() == entry.iProcessId)
+			{
+			buffer.Close();
+			return ETrue;
+			}
+		ptr += Align4(entry.GetSize());
+		}
+	buffer.Close();
+	return EFalse;
+	}
+
+//----------------------------------------------------------------------------------------------
+//! @SYMTestCaseID      KBase-T-RMDEBUG2-0445
+//! @SYMTestType
+//! @SYMPREQ            PREQ1426
+//! @SYMTestCaseDesc    Tests basic debug functions work on demand-paged target threads
+//! @SYMTestActions     Checks it can r/w memory, set breakpoints etc in a demand paged target.
+//!
+//! @SYMTestExpectedResults KErrNone.
+//! @SYMTestPriority        High
+//! @SYMTestStatus          Implemented
+//----------------------------------------------------------------------------------------------
+
+void CRunModeAgent::TestDemandPaging(void)
+	{
+	test.Next(_L("TestDemandPaging\n"));
+
+	test(KErrNone == iServSession.AttachExecutable(iFileName, EFalse));
+	test(KErrNone == iServSession.SuspendThread(iThreadID));
+
+	// get the address of a function in code that will be paged in
+	TUint32 address = (TUint32)(&RMDebugDemandPagingTest);
+	const TUint32 armInstSize = 4;
+
+	// read the memory at &RMDebugDemandPagingTest to check that reading memory in demand paged code works
+	TUint32 demandPagedInst = 0;
+	TPtr8 demandPagedInstBuf((TUint8*)&demandPagedInst, armInstSize);
+	test(KErrNone == iServSession.ReadMemory(iThreadID, address, armInstSize, demandPagedInstBuf, EAccess32, EEndLE8));
+
+	// this is the MOVS instruction that we expect to find in RMDebugDemandPagingTest
+	TUint32 expectedDemandPagedInst = 0xe1b02000;
+
+	// check that the instruction we read is as expected
+	test(demandPagedInst == expectedDemandPagedInst);
+
+	// set event action for break points
+	test(KErrNone == iServSession.SetEventAction(RProcess().FileName(), EEventsBreakPoint, EActionContinue));
+
+	// set an arm breakpoint on RMDebugDemandPagingTest
+	TBreakId armBreakId = 0;
+	test(KErrNone == iServSession.SetBreak(armBreakId, iThreadID, address, EArmMode));
+
+	// Ensure that after setting the breakpoint the memory read returns the correct value
+	TUint32 demandPagedInstWithBreakPoint = 0;
+	TPtr8 spinForeverInstWithBreakPointBuf((TUint8*)&demandPagedInstWithBreakPoint, armInstSize);
+	test(KErrNone == iServSession.ReadMemory(iThreadID, address, armInstSize, spinForeverInstWithBreakPointBuf, EAccess32, EEndLE8));
+	test(demandPagedInst == demandPagedInstWithBreakPoint);
+
+	// switch the target thread to run the demand paging function
+	test(KErrNone == SwitchTestFunction(EDemandPagingFunction));
+
+	// set up event watcher to catch breakpoint being hit in demand paged code
+	TEventInfo info;
+	static TRequestStatus status;
+	TPtr8 infoPtr((TUint8*)&info,sizeof(TEventInfo));
+	iServSession.GetEvent(RProcess().FileName(), status, infoPtr);
+
+	// resume the thread
+	test(KErrNone == iServSession.ResumeThread(iThreadID));
+	// wait for notification of the breakpoint hit event
+	User::WaitForRequest(status);
+	test(status==KErrNone);
+
+	// info should now be filled with the details
+	test(info.iProcessIdValid);
+	test(info.iThreadIdValid);
+	test(info.iEventType == EEventsBreakPoint);
+	test(info.iThreadBreakPointInfo.iRmdArmExcInfo.iR15 == address);
+
+	// remove the break point and resume the thread
+	test(KErrNone == iServSession.ClearBreak(armBreakId));
+
+	// switch the target thread to run the default function
+	test(KErrNone == SwitchTestFunction(EDefaultFunction));
+
+	test(KErrNone == iServSession.ResumeThread(iThreadID));
+	test(KErrNone == iServSession.DetachExecutable(iFileName));
+	}
+
+// Names of some test programs used for testing security
+_LIT(KRMDebugSecurity0FileName,"z:\\sys\\bin\\t_rmdebug_security0.exe"); // Debuggable
+_LIT(KRMDebugSecurity1FileName,"z:\\sys\\bin\\t_rmdebug_security1.exe"); // Not debuggable
+
+#if defined (NO_DEBUGTOKEN) || defined (SOMECAPS_DEBUGTOKEN) || defined(FEWCAPS_DEBUGTOKEN)
+_LIT(KRMDebugSecurity2FileName,"z:\\sys\\bin\\t_rmdebug_security2.exe"); // AllFiles
+#endif
+
+_LIT(KRMDebugSecurity3FileName,"z:\\sys\\bin\\t_rmdebug_security3.exe"); // TCB AllFiles
+
+// include the test header file here
+#include "rm_debug_kerneldriver.h"
+
+//----------------------------------------------------------------------------------------------
+//! @SYMTestCaseID      KBase-T-RMDEBUG2-0446
+//! @SYMTestType
+//! @SYMPREQ            PREQ1426
+//! @SYMTestCaseDesc    Tests Debug Device Driver is locked to the SID of the Debug Security Svr.
+//! @SYMTestActions     Loads rm-debug.ldd and tries to open a handle to it. This should fail.
+//!
+//! @SYMTestExpectedResults KErrPermissionDenied.
+//! @SYMTestPriority        High
+//! @SYMTestStatus          Implemented
+//----------------------------------------------------------------------------------------------
+
+void CRunModeAgent::TestDriverSecurity(void)
+	{
+	test.Next(_L("TestDriverSecurity\n"));
+
+	RRM_DebugDriver kernelDriver;
+
+	// Load the debug device driver
+	TInt err = User::LoadLogicalDevice( KDebugDriverFileName );
+	test((KErrNone == err) || (KErrAlreadyExists == err));
+
+	// we were allowed to load the driver, or its already loaded.
+
+	// Try to open a handle to the driver - this should return KErrPermissionDenied as we don't have the DSS SID
+	TRM_DebugDriverInfo driverInfo;
+	driverInfo.iUserLibraryEnd = 0;
+	err = kernelDriver.Open(driverInfo);
+	test((err == KErrInUse) || (err == KErrPermissionDenied));
+
+	}
+
+//----------------------------------------------------------------------------------------------
+//! @SYMTestCaseID      KBase-T-RMDEBUG2-0447
+//! @SYMTestType
+//! @SYMPREQ            PREQ1426
+//! @SYMTestCaseDesc    Tests Debug driver can only be access via the DSS. Also tests DSS cannot
+//!						be subverted. Tests functionality of two representative OEM Debug Tokens.
+//! @SYMTestActions     Tries to open rm_debug.ldd (should fail). Tries to debug various processes
+//!						(only debuggable one should succeed). Checks that DSS behaves correctly
+//!						when different versions are passed in to Connect().
+//!
+//! @SYMTestExpectedResults KErrPermissionDenied.
+//! @SYMTestPriority        High
+//! @SYMTestStatus          Implemented
+//----------------------------------------------------------------------------------------------
+
+void CRunModeAgent::TestSecurity(void)
+	{
+	// Things to test
+	//
+	// try to use debug driver directly ( should have the wrong UID/SID value!)
+	test.Next(_L("TestSecurity - Bypass Debug Security Server to Debug Device Driver - DSS running\n"));
+
+	// Things to test
+	//
+	// Load the debug device driver
+	RRM_DebugDriver kernelDriver;
+	TInt err = User::LoadLogicalDevice( KDebugDriverFileName );
+	test((KErrNone == err) || (KErrAlreadyExists == err));
+
+	// we were allowed to load the driver, or its already loaded.
+
+	// Try to open handle a to the driver - this should return KErrPermission/KErrInUse as we don't have the DSS SID
+	// and we expect the DSS to already be using it.
+	TRM_DebugDriverInfo driverInfo;
+	driverInfo.iUserLibraryEnd = 0;
+	err = kernelDriver.Open(driverInfo);
+	test(err == KErrInUse);
+
+	// Try requesting an unsupported version of DSS
+	test.Next(_L("TestSecurity - requesting unsupported versions of DSS\n"));
+	RSecuritySvrSession dss;
+	err = dss.Connect(TVersion(999999, 0, 0));
+	test(err == KErrNotSupported); // Prior to DEF142018 this would crash, causing a KErrServerTerminated
+	err = dss.Connect(TVersion(KDebugServMajorVersionNumber, 999999, 0));
+	test(err == KErrNotSupported); // Explicitly asking for a minor version should give KErrNotSupported too if it's newer than what's running.
+	err = dss.Connect(TVersion(KDebugServMajorVersionNumber, 0, 0));
+	test(err == KErrNone); // But the correct major version and no explicit minor version should always succeed
+	dss.Close();
+	
+	//
+	// Attach to the Debug Security Server (passive)
+	//
+	test.Next(_L("TestSecurity - Attach to the Debug Security Server (passive)\n"));
+
+	_LIT(KSecurityServerProcessName, "z:\\sys\\bin\\rm_debug_svr.exe");
+
+	test(KErrPermissionDenied == iServSession.AttachExecutable(KSecurityServerProcessName, ETrue));
+
+	//
+	// Attach to the Debug Security Server (active)
+	//
+	test.Next(_L("TestSecurity - Attach to the Debug Security Server (active)\n"));
+
+	test(KErrPermissionDenied == iServSession.AttachExecutable(KSecurityServerProcessName, EFalse));
+
+	//
+	// Attach to Process 0
+	//
+	// Target: Debuggable
+	//
+	test.Next(_L("TestSecurity - Attach to test process 0\n"));
+
+	// Agent can debug the target app as it is marked debuggable - ie capabilities are ignored)
+	HelpTestSecurityAttachDetachExecutable(KRMDebugSecurity0FileName,ETrue);
+
+	//
+	// Attach to Process - 1
+	//
+	// Target: Non-debuggable for ordinary debug agent, debuggable for OEM/OEM2 token authorised agent
+	//
+	// Note: This target app has no PlatSec capabilities
+	//
+	// Agent cannot debug the app unless it has an OEM/OEM2 Debug Token
+
+
+#ifdef NO_DEBUGTOKEN
+	test.Next(_L("TestSecurity NO_DEBUGTOKEN - Attach to test process 1\n"));
+	HelpTestSecurityAttachDetachExecutable(KRMDebugSecurity1FileName,EFalse);
+#endif
+
+#ifdef SOMECAPS_DEBUGTOKEN
+	test.Next(_L("TestSecurity SOMECAPS_DEBUGTOKEN - Attach to test process 1\n"));
+	HelpTestSecurityAttachDetachExecutable(KRMDebugSecurity1FileName,ETrue);
+#endif
+
+#ifdef FEWCAPS_DEBUGTOKEN
+	test.Next(_L("TestSecurity FEWCAPS_DEBUGTOKEN - Attach to test process 1\n"));
+	HelpTestSecurityAttachDetachExecutable(KRMDebugSecurity1FileName,ETrue);
+#endif
+
+	//
+	// Attach to Process - 2
+	//
+	// Target: Non-debuggable for ordinary debug agent, non-debuggable for OEM2 authorised agent (insufficient caps)
+	//
+	// Note: This target app has AllFiles capability
+	//
+	// Agent cannot debug the app unless it has an OEM Debug Token
+
+
+#ifdef NO_DEBUGTOKEN
+	test.Next(_L("TestSecurity NO_DEBUGTOKEN - Attach to test process 2\n"));
+	HelpTestSecurityAttachDetachExecutable(KRMDebugSecurity2FileName,EFalse);
+#endif
+
+#ifdef SOMECAPS_DEBUGTOKEN
+	test.Next(_L("TestSecurity SOMECAPS_DEBUGTOKEN - Attach to test process 2\n"));
+	HelpTestSecurityAttachDetachExecutable(KRMDebugSecurity2FileName,ETrue);
+#endif
+
+#ifdef FEWCAPS_DEBUGTOKEN
+	test.Next(_L("TestSecurity FEWCAPS_DEBUGTOKEN - Attach to test process 2\n"));
+	HelpTestSecurityAttachDetachExecutable(KRMDebugSecurity2FileName,EFalse);
+#endif
+
+	//
+	// Attach to Process - 3
+	//
+	// Target: Non-debuggable for ordinary debug agent, non-debuggable for OEM authorised agent (insufficient caps)
+	//
+	// Note: This target app has AllFiles and TCB and NetworkControl capabilities
+	//
+
+#if  defined (NO_DEBUGTOKEN)  || defined (SOMECAPS_DEBUGTOKEN) || defined (FEWCAPS_DEBUGTOKEN)
+	test.Next(_L("TestSecurity - Attach to test process 3 : Should not be able to debug it\n"));
+	HelpTestSecurityAttachDetachExecutable(KRMDebugSecurity3FileName,EFalse);
+#else
+	test.Next(_L("TestSecurity - Attach to test process 3 : Should be able to debug it\n"));
+	HelpTestSecurityAttachDetachExecutable(KRMDebugSecurity3FileName,ETrue);
+#endif
+	}
+
+//----------------------------------------------------------------------------------------------
+//! @SYMTestCaseID      KBase-T-RMDEBUG2-0543
+//! @SYMTestType
+//! @SYMPREQ            PREQ1426
+//! @SYMTestCaseDesc    Validates that a dll can be built which #include's the rm_debug_api.h header, i.e. rm_debug_api.h contains no static data.
+//! @SYMTestActions     Calls a dummy function in t_rmdebug_dll.dll which implies the dll has been built correctly.
+//!
+//! @SYMTestExpectedResults KErrNone.
+//! @SYMTestPriority        High
+//! @SYMTestStatus          Implemented
+//----------------------------------------------------------------------------------------------
+void CRunModeAgent::TestDllUsage(void)
+	{
+	test.Next(_L("TestDllUsage\n"));
+	test(KUidDebugSecurityServer == GetDSSUid());
+	}
+
+//----------------------------------------------------------------------------------------------
+//! @SYMTestCaseID      KBase-T-RMDEBUG2-0812
+//! @SYMTestType
+//! @SYMPREQ            PREQ1700
+//! @SYMTestCaseDesc    Writes a known data to the crash flash and validates the data written
+//!						using the read operation and finally erase the data. In the absence
+//!						of an OEM debug token, access to the crash partition should not be allowed
+//! @SYMTestActions     Invoke the flash write method in DSS and call the read method in DSS
+//!						to validate the data is written correctly and then erase the written area
+//!
+//! @SYMTestExpectedResults KErrNone.
+//! @SYMTestPriority        High
+//! @SYMTestStatus          Implemented
+//----------------------------------------------------------------------------------------------
+void CRunModeAgent::TestCrashFlash(void)
+	{
+#if  defined (NO_DEBUGTOKEN)  || defined (FEWCAPS_DEBUGTOKEN)
+
+	test.Next(_L("@SYMTestCaseID:DT-debug-securityserver-006 Testing We cannot Erase the Crash Flash with insufficient privileges"));
+
+	TUint32 size = 0;
+	TInt err = iServSession.EraseCrashLog(0, 1);
+	test(KErrPermissionDenied == err);
+
+	test.Next(_L("@SYMTestCaseID:DT-debug-securityserver-005 Testing We can't Write to the Crash Flash with insufficient privileges"));
+
+	err = iServSession.WriteCrashConfig(0, KCrashDummyData, size);
+	test(KErrPermissionDenied == err);
+	test(size == 0);
+
+	test.Next(_L("@SYMTestCaseID:DT-debug-securityserver-008 Testing We can't Read from the Crash Flash with insufficient privileges"));
+
+	TUint32 readSize = 0x10;
+	RBuf8 buf;
+	buf.CleanupClosePushL();
+	err = buf.Create(readSize);
+
+	test(err == KErrNone);
+
+	err = iServSession.ReadCrashLog(0, buf, readSize);
+	test(KErrPermissionDenied == err);
+
+	test.Next(_L("@SYMTestCaseID:DT-debug-securityserver-004 Testing Writing To an invalid location"));
+
+	TUint32 writeSize = 0;
+	err = iServSession.WriteCrashConfig(0xFFFFFFFF, KCrashDummyData, writeSize);
+
+	test(err == KErrPermissionDenied);
+
+	test.Next(_L("@SYMTestCaseID:DT-debug-securityserver-003 Testing Reading from an invalid location"));
+
+	buf.FillZ();
+	err = iServSession.ReadCrashLog(0, buf, writeSize);
+
+	test(err == KErrPermissionDenied);
+
+	CleanupStack::PopAndDestroy(&buf);
+
+#endif
+
+#ifdef SOMECAPS_DEBUGTOKEN
+
+	TInt err = KErrNone;
+
+	test.Next(_L("@SYMTestCaseID:DT-debug-securityserver-007 Testing We can Erase the Crash Flash with sufficient privileges"));
+
+	err = iServSession.EraseCrashLog(0, 1);
+
+	// For platforms where NAND flash is not currently supported we get a KErrNotSupported - this is still a pass
+	if (KErrNotSupported == err)
+		{
+		test.Printf(_L("Nand flash not supported - continue"));
+		return;
+		}
+
+ 	//For platforms without a flash partition we get KErrNotFound - this is still a pass
+ 	if(KErrNotFound == err)
+ 		{
+ 		test.Printf(_L("Platform has no flash partition - continue"));
+ 		return;
+ 		}
+
+	test(KErrNone == err);
+
+	//Read back the start of the block to make sure its 0xFFFFFFFF
+	const TUint numBytesToCheck = 0x80;  //We dont know the block size
+	TBuf8<numBytesToCheck> eraseCheck;
+	eraseCheck.SetLength(numBytesToCheck);
+
+	err = iServSession.ReadCrashLog(0, eraseCheck, numBytesToCheck);
+	test(err == KErrNone);
+
+	TBool dataIsOk = ETrue;
+	for(TUint cnt = 0; cnt < numBytesToCheck; cnt++)
+		{
+		if(eraseCheck[cnt] != 0xFF)
+			{
+			dataIsOk = EFalse;
+			}
+		}
+
+	test(dataIsOk);
+
+	test.Next(_L("@SYMTestCaseID:DT-debug-securityserver-002 Testing We can Write to the Crash Flash with sufficient privileges"));
+
+	TUint32 writeSize = 0;
+	err = iServSession.WriteCrashConfig(0, KCrashDummyData, writeSize);
+
+	test(writeSize == KCrashDummyData().Length());
+
+	test.Next(_L("@SYMTestCaseID:DT-debug-securityserver-001 Testing We can Read from the Crash Flash with sufficient privileges"));
+
+	RBuf8 buf;
+	buf.CleanupClosePushL();
+	err = buf.Create(writeSize);
+
+	test(err == KErrNone);
+
+	buf.FillZ();
+
+	err = iServSession.ReadCrashLog(0, buf, writeSize);
+
+	test(0 == buf.Compare(KCrashDummyData));
+
+	test.Next(_L("@SYMTestCaseID:DT-debug-securityserver-004 Testing Writing To an invalid location"));
+
+	writeSize = 0;
+	err = iServSession.WriteCrashConfig(0xFFFFFFFF, KCrashDummyData, writeSize);
+
+	test(err == KErrArgument);
+
+	test.Next(_L("@SYMTestCaseID:DT-debug-securityserver-003 Testing Reading from an invalid location"));
+
+	buf.FillZ();
+	err = iServSession.ReadCrashLog(0xFFFFFFFF, buf, writeSize);
+
+	test(err == KErrArgument);
+
+	CleanupStack::PopAndDestroy(&buf);
+
+#endif
+	}
+//----------------------------------------------------------------------------------------------
+//! @SYMTestCaseID      KBase-T-RMDEBUG2-0735
+//! @SYMTestType
+//! @SYMPREQ            PREQ1426
+//! @SYMTestCaseDesc    Tests the Kill Process functionality. Only can kill a debuggable process.
+//! @SYMTestActions     Launches a debuggable and non-debuggable process and tries to kill both.
+//!
+//! @SYMTestExpectedResults KErrNone.
+//! @SYMTestPriority        High
+//! @SYMTestStatus          Implemented
+//----------------------------------------------------------------------------------------------
+void CRunModeAgent::TestKillProcess(void)
+	{
+	test.Next(_L("TestKillProcess\n"));
+
+	// Kill a debuggable process
+
+	// check that killing a process is supported
+	TTag tag = GetTag(ETagHeaderIdKillObjects, EFunctionalityKillProcess);
+	test(tag.iValue);
+	// check that killing a thread is not supported
+	tag = GetTag(ETagHeaderIdKillObjects, EFunctionalityKillThread);
+	test(!tag.iValue);
+
+	// attach first!
+	TInt err = iServSession.AttachExecutable(KRMDebugTestApplication, EFalse /* Active */);
+	test(err == KErrNone);
+
+	// first launch a debuggable process
+	RProcess process;
+	err = LaunchProcess(process, KRMDebugTestApplication(),ESpinForever, 0, 0);
+	test (err == KErrNone);
+
+	// try to find the process in the list
+_LIT(KRMDebugAppName, "t_rmdebug_app");
+
+	TBool found = ProcessExists(KRMDebugAppName);
+	test (found);
+
+	TInt processId = process.Id();
+	process.Close();
+
+	// program now running, so try to kill it
+	err = iServSession.KillProcess(processId, 0 /* kill reason */);
+	test(err == KErrNone);
+
+	User::After(2000000);	// should die within two seconds.
+
+	// can we still find it? Should be gone
+	found = ProcessExists(KRMDebugAppName);
+	test (!found);
+
+	// release the program again.
+	err = iServSession.DetachExecutable(KRMDebugTestApplication);
+	test(err == KErrNone);
+
+	// Try to kill a non-debuggable process and fail.
+
+	// first launch a non-debuggable process
+	RProcess process2;
+	err = LaunchProcess(process2, KRMDebugSecurity1FileName(),ESpinForever, 0, 0);
+	test (err == KErrNone);
+
+	// try to find the process in the list
+_LIT(KRMDebugAppName2, "t_rmdebug_security1");
+
+	TBool found2 = ProcessExists(KRMDebugAppName2);
+	test (found2);
+
+	TInt process2Id = process2.Id();
+	process2.Close();
+
+	// program now running, so try to kill it
+	err = iServSession.KillProcess(process2Id, 0 /* kill reason */);
+	test(err == KErrPermissionDenied);
+
+	User::After(2000000);	// should die within two seconds if it is going to die.
+
+	// can we still find it? Should be still around!
+	found2 = ProcessExists(KRMDebugAppName2);
+	test (found2);
+
+	}
+
+//----------------------------------------------------------------------------------------------
+//! @SYMTestCaseID      KBase-T-RMDEBUG2-1388
+//! @SYMTestType
+//! @SYMPREQ            PREQ1426
+//! @SYMTestCaseDesc    Tests the correct operation of the AddProcess and Remove Process
+//! @SYMTestActions     1. Registers for AddProcess and Remove Process events
+//!                     2. Starts a test process z:\sys\bin\t_rmdebug_security0.exe
+//!                     3. Wait for the AddProcess event to be reported
+//!                     4. Kill the newly started test process
+//!                     5. Wait for the RemoveProcess event to be reported
+//!                     6. Tell the DSS it is no longer interested in AddProcess and RemoveProcess events
+//!
+//! @SYMTestExpectedResults KErrNone.
+//! @SYMTestPriority        High
+//! @SYMTestStatus          Implemented
+//----------------------------------------------------------------------------------------------
+
+void CRunModeAgent::TestAddRemoveProcessEvents()
+	{
+	test.Next(_L("TestAddRemoveProcessEvents\n"));
+
+	// attach to a process (e.g. one of the simple security test programs)
+	// launch the security program
+	// wait for the add event
+	// continue the program.
+	// wait for the remove event
+	// detach process
+
+	test(KErrNone == iServSession.AttachExecutable(KRMDebugSecurity0FileName, EFalse));
+
+	test(KErrNone == iServSession.SetEventAction(KRMDebugSecurity0FileName,EEventsAddProcess, EActionContinue));
+
+	test(KErrNone == iServSession.SetEventAction(KRMDebugSecurity0FileName,EEventsRemoveProcess, EActionContinue));
+
+	// Creator thread ID of the current thread (to be creator of test application)
+	TInt creatorThreadId = RThread().Id();
+
+	RProcess process;
+	TInt err = process.Create(KRMDebugSecurity0FileName, KNullDesC, EOwnerProcess);
+	test (err == KErrNone);
+
+	// Rendezvous with process
+	TRequestStatus status;
+	process.Rendezvous(status);
+
+	// Start the test program
+	process.Resume();
+	User::WaitForRequest(status);
+	test(status==KErrNone);
+
+	// Wait for the addprocess event
+	TEventInfo info;
+	TPtr8 infoPtr((TUint8*)&info,0,sizeof(TEventInfo));
+
+	iServSession.GetEvent(KRMDebugSecurity0FileName,status,infoPtr);
+
+	// Wait for notification of the addprocess hit event
+	User::WaitForRequest(status);
+	test(status==KErrNone);
+
+	// Check this was the right kind of event
+	test(info.iEventType == EEventsAddProcess);
+
+	const TInt uid3offset = 2;
+
+	// Get UID3 for current process
+	TUint32 Uid3 = process.Type()[uid3offset].iUid;
+
+	// Check correct UID3 is returned from the driver
+    test(info.iAddProcessInfo.iUid3 == Uid3);
+
+    // Check correct creator ID for test application is returned from the driver
+    test(info.iAddProcessInfo.iCreatorThreadId == creatorThreadId);
+
+	// Kill the process, as we don't need it anymore
+	process.Kill(KErrNone);
+
+	// Wait for the remove process event
+	iServSession.GetEvent(KRMDebugSecurity0FileName,status,infoPtr);
+
+	// Wait for notification of the remove process hit event
+	User::WaitForRequest(status);
+	test(status==KErrNone);
+
+	// Check this was the right kind of event
+	test(info.iEventType == EEventsRemoveProcess);
+
+	test(KErrNone == iServSession.SetEventAction(KRMDebugSecurity0FileName,EEventsRemoveProcess, EActionIgnore));
+
+	test(KErrNone == iServSession.SetEventAction(KRMDebugSecurity0FileName,EEventsAddProcess, EActionIgnore));
+
+	test(KErrNone == iServSession.DetachExecutable(KRMDebugSecurity0FileName));
+
+	}
+
+//----------------------------------------------------------------------------------------------
+//! @SYMTestCaseID      KBase-T-RMDEBUG2-0736
+//! @SYMTestType
+//! @SYMPREQ            PREQ1426
+//! @SYMTestCaseDesc    Checks that process break points can be set, and that they can co-exist alongside thread breakpoints
+//! @SYMTestActions     Checks that process break points can be set, and that they can co-exist alongside thread breakpoints
+//!
+//! @SYMTestExpectedResults KErrNone.
+//! @SYMTestPriority        High
+//! @SYMTestStatus          Implemented
+//----------------------------------------------------------------------------------------------
+void CRunModeAgent::TestProcessBreakPoints(void)
+	{
+	test.Next(_L("TestProcessBreakPoints\n"));
+
+	// check that process breakpoints are supported
+	TTag tag = GetTag(ETagHeaderIdBreakpoints, EBreakpointProcess);
+	test(tag.iValue);
+
+	test(KErrNone == iServSession.AttachExecutable(iFileName, EFalse));
+	test(KErrNone == iServSession.SuspendThread(iThreadID));
+
+	// Try to set the breakpoint
+	TBreakId breakId;
+	TUint32 address = (TUint32)(&RMDebug_BranchTst1);
+	RProcess process;
+	TProcessId processId = process.Id();
+	process.Close();
+
+	test(KErrNone == iServSession.SetProcessBreak(breakId, processId, address, EArmMode));
+	test(KErrAlreadyExists == iServSession.SetBreak(breakId, iThreadID, address, EArmMode));
+	test(KErrAlreadyExists == iServSession.SetBreak(breakId, iThreadID, address, EThumbMode));
+	test(KErrAlreadyExists == iServSession.SetProcessBreak(breakId, processId, address, EArmMode));
+	test(KErrAlreadyExists == iServSession.SetProcessBreak(breakId, processId, address, EThumbMode));
+	test(KErrNone == iServSession.ClearBreak(breakId));
+
+	test(KErrNone == iServSession.SetBreak(breakId, iThreadID, address, EArmMode));
+	test(KErrAlreadyExists == iServSession.SetProcessBreak(breakId, processId, address, EArmMode));
+	test(KErrAlreadyExists == iServSession.SetProcessBreak(breakId, processId, address, EThumbMode));
+	test(KErrNone == iServSession.ClearBreak(breakId));
+
+	test(KErrNone == iServSession.ResumeThread(iThreadID));
+
+	test(KErrNone == iServSession.DetachExecutable(iFileName));
+	}
+
+//----------------------------------------------------------------------------------------------
+//! @SYMTestCaseID      KBase-T-RMDEBUG2-1309
+//! @SYMTestType
+//! @SYMPREQ            PREQ1426
+//! @SYMTestCaseDesc    Checks that in the case of multiple low priority events (user traces in this case) we can still receive higher
+//!				priority events should the buffer reach a critical level
+//! @SYMTestActions     Run to first breakpoint in our test code. Then multiple trace events are issued. We should still be able to hit
+//!				the second breakpoint
+//!
+//! @SYMTestExpectedResults KErrNone.
+//! @SYMTestPriority        High
+//! @SYMTestStatus          Implemented
+//----------------------------------------------------------------------------------------------
+
+void CRunModeAgent::TestMultipleTraceEvents(void)
+	{
+	test.Next(_L("TestMultipleTraceEvents\n"));
+
+	//attach to target debug process
+	test(KErrNone == iServSession.AttachExecutable(iFileName, EFalse));
+
+	//set the target thread to execute the trace test function
+	test(KErrNone == SwitchTestFunction(EMultipleTraceCalls, EFalse));
+	
+	
+
+	//register interest in BP's & trace events and trace ignored events
+	test(KErrNone == iServSession.SetEventAction(iFileName,EEventsBreakPoint, EActionSuspend));
+	test(KErrNone == iServSession.SetEventAction(iFileName,EEventsUserTrace, EActionContinue));
+	test(KErrNone == iServSession.SetEventAction(iFileName,EEventsUserTracesLost, EActionContinue));
+
+	// Try to set the breakpoints
+	TBreakId armBreakId;
+	TBreakId armBreakId2;
+	TUint32 address = (TUint32)(&RMDebug_BranchTst1);
+	TUint32 address2 = (TUint32)(&RMDebug_StepTest_Non_PC_Modifying);
+
+	test(KErrNone == iServSession.SetBreak(armBreakId,iThreadID,address,EArmMode));
+	test(KErrNone == iServSession.SetBreak(armBreakId2,iThreadID,address2,EArmMode));
+
+	// Continue the thread
+	test(KErrNone == iServSession.ResumeThread(iThreadID));
+
+	// wait for the breakpoint to be hit
+	TEventInfo info;
+	static TRequestStatus status;
+
+	TPtr8 infoPtr((TUint8*)&info,0,sizeof(TEventInfo));
+	iServSession.GetEvent(iFileName,status,infoPtr);
+
+	// Wait for notification of the 1st breakpoint hit event
+	User::WaitForRequest(status);
+	test(status==KErrNone);
+
+	// info should now be filled with the details
+	test(info.iEventType == EEventsBreakPoint);
+	test(info.iThreadBreakPointInfo.iRmdArmExcInfo.iR15 == address);
+	test(info.iProcessIdValid);
+	test(info.iThreadIdValid);
+
+	// Continue the thread
+	test(KErrNone == iServSession.ResumeThread(iThreadID));
+
+	//Now we try to hit the second breakpoint. This will occur after a number of trace calls. If we hit this breakpoint it
+	//means many trace calls are not preventing us hitting breakpoints.
+	iServSession.GetEvent(iFileName,status,infoPtr);
+
+	// Wait for notification of the 2nd breakpoint hit event
+	User::WaitForRequest(status);
+	test(status==KErrNone);
+
+	TBool receivedTracesLost = EFalse;
+
+	while(info.iEventType == EEventsUserTrace || info.iEventType == EEventsUserTracesLost)
+		{
+		//ensure we get told traces are being thrown away - we generate enough to flood the buffer
+		if(info.iEventType == EEventsUserTracesLost)
+			{
+			receivedTracesLost = ETrue;
+
+			// Now stop the target thread from generating trace events
+			test(KErrNone == SwitchTestFunction(EDoNothing, EFalse));
+			break;
+			}
+		else
+			{
+			// Its EEventsUserTrace, so delay us in getting the next event so that it will be more 
+			// likely to get a EEventsUserTracesLost next time. 
+			// This is important on SMP since the platform can process lots of events, and thus
+			// withouth the delay it is difficult for this test to reproduce the abnormal situation of 
+			// lost trace packets
+			User::After(200000);
+			}
+
+		iServSession.GetEvent(iFileName,status,infoPtr);
+
+		// Wait for notification of the 2nd breakpoint hit event
+		User::WaitForRequest(status);
+		test(status==KErrNone);
+		}
+
+	//make sure we got told traces were lost
+	test(receivedTracesLost != EFalse);
+
+	//dont care for breakpoints or trace events no more
+	test(KErrNone == iServSession.SetEventAction(iFileName,EEventsBreakPoint, EActionIgnore));
+	test(KErrNone == iServSession.SetEventAction(iFileName,EEventsUserTrace, EActionIgnore));
+	test(KErrNone == iServSession.SetEventAction(iFileName,EEventsUserTracesLost, EActionIgnore));
+
+	//clear the breaks we set
+	test(KErrNone == iServSession.ClearBreak(armBreakId));
+	test(KErrNone == iServSession.ClearBreak(armBreakId2));
+
+	// Continue the thread
+	test(KErrNone == iServSession.ResumeThread(iThreadID));
+
+	//attach to target debug process
+	test(KErrNone == iServSession.DetachExecutable(iFileName));
+
+	}
+
+//----------------------------------------------------------------------------------------------
+//! @SYMTestCaseID KBase-T-RMDEBUG2-2441
+//! @SYMTestType
+//! @SYMPREQ PREQ1426
+//! @SYMTestCaseDesc Test clearing of a process breakpoint once the process has been killed.
+//! @SYMTestActions Creates a new process then tries to set a process breakpoint and then kills the process which should clear the previously set breakpoint. Then repeat the step once again.
+//! @SYMTestExpectedResults KErrNone
+//! @SYMTestPriority High
+//! @SYMTestStatus Implemented
+//----------------------------------------------------------------------------------------------
+
+void CRunModeAgent::TestProcessKillBreakpoint(void)
+	{
+	test.Next(_L("TestProcessKillBreakpoint\n"));
+
+	DoTestProcessKillBreakpoint();
+	// called once again
+	// to check if we can set the breakpoint once again after the process gets killed
+	DoTestProcessKillBreakpoint();
+
+	// And do it a couple more times, there was a leaked process handle that didn't show up
+	// until the third or fourth time this code was run
+	DoTestProcessKillBreakpoint();
+	DoTestProcessKillBreakpoint();
+	}
+
+void CRunModeAgent::DoTestProcessKillBreakpoint()
+	{
+	test.Printf(_L("\nDoTestProcessKillBreakpoint\n"));
+
+	// check that killing a process is supported
+	TTag tag = GetTag(ETagHeaderIdKillObjects, EFunctionalityKillProcess);
+	test(tag.iValue);
+	// check that killing a thread is not supported
+	tag = GetTag(ETagHeaderIdKillObjects, EFunctionalityKillThread);
+	test(!tag.iValue);
+
+	// attach first!
+	test ( KErrNone == iServSession.AttachExecutable(KRMDebugTestApplication, EFalse/*  Active */));
+
+	RProcess processDebug;
+	TThreadId dontCare;
+	LaunchDebugProcessAndSetBreakpoint(processDebug, dontCare);
+
+	// Not interested in breakpoint events any more
+	test(KErrNone == iServSession.SetEventAction(KRMDebugTestApplication, EEventsProcessBreakPoint, EActionIgnore));
+
+	// program now running, so try to kill it which should clear all the breakpoints
+	test(KErrNone == iServSession.KillProcess(processDebug.Id(), 0  /* kill reason */ ));
+
+	TRequestStatus stat;
+	processDebug.NotifyDestruction(stat);
+	processDebug.Close();
+	TIMED_WAIT(stat, 1000);
+
+	// release the program again
+	test(KErrNone == iServSession.DetachExecutable(KRMDebugTestApplication));
+	}
+
+void CRunModeAgent::LaunchDebugProcessAndSetBreakpoint(RProcess& aResultProcess, TThreadId& aResultThread)
+	{
+	// define a property to pass on the address from the other process we would try to debug
+	static _LIT_SECURITY_POLICY_PASS(KAllowAllPolicy);
+	TInt err = RProperty::Define(RProcess().SecureId(), EMyPropertyInteger, RProperty::EInt, KAllowAllPolicy, KAllowAllPolicy);
+	test (err == KErrNone || err == KErrAlreadyExists);
+
+	RSemaphore addressGlobSem;
+	//define a global semaphore to synchronise with debuggable process publishing the property
+	err = addressGlobSem.CreateGlobal(_L("RMDebugGlobSem"), 0);
+	test (err == KErrNone);
+
+	// first launch a debuggable process
+	RProcess& processDebug(aResultProcess);
+	test ( KErrNone == LaunchProcess(processDebug, KRMDebugTestApplication(),ESpinForeverWithBreakPoint, 0, 0));
+
+	// try to find the process in the list
+	TBool found = ProcessExists(KRMDebugAppName);
+	test (found);
+
+	//search for the main thread created
+   _LIT(KThreadWildCard, "t_rmdebug_app*");
+	TProcessId processDebugId = processDebug.Id();
+	TThreadId& threadDebugId(aResultThread);
+
+   	TFindThread find(KThreadWildCard);
+	TFullName name;
+	found = EFalse;
+	while(find.Next(name)==KErrNone && !found)
+		{
+		RThread thread;
+		err = thread.Open(find);
+       	if (err == KErrNone)
+			{
+			RProcess process;
+			thread.Process(process);
+			if (((TUint32)process.Id() == processDebugId))
+				{
+				TFullName fullname = thread.FullName();
+				test.Printf(_L("Match Found Name: %S Process id: %ld Thread id: %ld\n"), &fullname, process.Id().Id(), thread.Id().Id());
+				found = ETrue;
+				threadDebugId = thread.Id();
+				}
+			process.Close();
+			}
+		thread.Close();
+   		}
+
+	test (found); //check if we actually found the thread we want to debug
+
+	//waiting on semaphore to be sure that the property is set
+	addressGlobSem.Wait();
+
+	//get the value(property) for the breakpoint address for the process to debug
+	TInt address;
+	test(KErrNone == RProperty::Get(RProcess().SecureId(), EMyPropertyInteger, address));
+
+	test.Printf(_L("Address retrieved to set breakpoint 0x%08x\n"), address);
+
+	//suspend the thread before we set a breakpoint
+	test (KErrNone == iServSession.SuspendThread(threadDebugId));
+
+	//set a process breakpoint
+	TBreakId breakId;
+	test(KErrNone == iServSession.SetProcessBreak(breakId, processDebugId, address, EArmMode));
+
+	test(KErrNone == iServSession.SetEventAction(KRMDebugTestApplication, EEventsProcessBreakPoint, EActionContinue));
+
+	//resume the thread now
+	test(KErrNone == iServSession.ResumeThread(threadDebugId));
+
+	// wait for the breakpoint to be hit
+	TRequestStatus status;
+	TEventInfo info;
+	TPtr8 infoPtr((TUint8*)&info,0,sizeof(TEventInfo));
+	iServSession.GetEvent(KRMDebugTestApplication,status,infoPtr);
+	// Wait for notification of the breakpoint hit event
+	TIMED_WAIT(status, 2000);
+	test(status==KErrNone);
+
+	// info should now be filled with the details
+	test(info.iEventType ==  EEventsProcessBreakPoint);
+	test(info.iThreadBreakPointInfo.iRmdArmExcInfo.iR15 == address);
+	test(info.iProcessIdValid);
+	test(info.iThreadIdValid);
+
+	addressGlobSem.Close();
+	}
+
+void CRunModeAgent::HelpTestSecurityAttachDetachExecutable(const TDesC& aProcessName, TBool aExpectSuccess)
+	{
+	RProcess process;
+	TInt err = process.Create(aProcessName, KNullDesC, EOwnerProcess);
+	test (err == KErrNone);
+
+	// rendezvous with process
+	TRequestStatus status;
+	process.Rendezvous(status);
+
+	// start the test program
+	process.Resume();
+	User::WaitForRequest(status);
+	test(status==KErrNone);
+
+	// attach to the program (passively)
+	err = iServSession.AttachExecutable(aProcessName, EFalse);
+
+	if( gUseDelay ) User::After(500000);
+
+	// Do we expect to successfully attach
+	if (aExpectSuccess)
+	{
+		// Yes
+		test(KErrNone == err);
+
+		// Now detach again
+		test(KErrNone == iServSession.DetachExecutable(aProcessName));
+		if( gUseDelay ) User::After(500000);
+	}
+	else
+	{
+		// No
+		test(KErrPermissionDenied == err);
+
+		// Just to be sure, try active attachment
+		test(KErrPermissionDenied == iServSession.AttachExecutable(aProcessName, ETrue));
+		if( gUseDelay ) User::After(500000);
+	}
+
+	// Kill the process, as we don't need it anymore
+	process.Kill(KErrNone);
+	if( gUseDelay ) User::After(500000);
+	}
+
+void CRunModeAgent::ReportPerformance(void)
+//
+// Reports performance metrics from all the tests
+//
+	{
+	test.Printf(_L("\nPerformance\n"));
+	test.Printf(_L("========================\n"));
+
+	// Memory
+	test.Printf(_L("Memory read: %d KBytes/sec\n"),iMemoryReadKbytesPerSecond);
+	test.Printf(_L("Memory write: %d KBytes/sec\n"),iMemoryWriteKbytesPerSecond);
+
+	// Registers
+	// to do
+
+	// events
+	// to do
+
+	// Breakpoints
+	test.Printf(_L("Breakpoint set/clear: %d/sec\n"),iBreakpointsPerSecond);
+	test.Printf(_L("Maximum number of breakpoints: %d\n"),iMaxBreakpoints);
+
+	// Stepping
+	test.Printf(_L("Stepping speed: %d/sec\n"),iStepsPerSecond);
+
+	// Runtime
+	TInt ticks = HelpGetTestTicks();
+	test (ticks != 0);
+
+	TInt nkTicksPerSecond = HelpTicksPerSecond();
+	test (nkTicksPerSecond != 0);
+
+	test.Printf(_L("Total test runtime: %d seconds\n"),ticks/nkTicksPerSecond);
+
+	// Final sizes of executables/rom/ram etc
+	// to do
+
+	test.Printf(_L("\n"));
+	}
+
+/**
+ * Helper code for the stepping tests. Sets a breakpoint in a running thread.
+ * It suspends the thread, sets the breakpoint, and resumes the thread.
+ *
+ * @param aBreakId - Reference to a TBreakId which will be set when the breakpoint is set
+ * @param aThreadId - The thread id for which we should set the breakpoint.
+ * @param aBreakAddress - The address to set the breakpoint
+ * @param aMode - The architecture of the breakpoint to be set (ARM/Thumb/Thumb2EE)
+ * @return KErrNone if successful. One of the other system wide error codes otherwise.
+ */
+TInt CRunModeAgent::HelpTestStepSetBreak(TBreakId& aBreakId, TThreadId aThreadId, const TUint32 aBreakAddress, TArchitectureMode aMode, TBool aThreadSpecific, TProcessId aProcessId)
+	{
+	TInt err = KErrNone;
+
+
+	// Set the breakpoint
+	err = aThreadSpecific
+		? iServSession.SetBreak(aBreakId,aThreadId,aBreakAddress,aMode)
+		: iServSession.SetProcessBreak(aBreakId, aProcessId, aBreakAddress, aMode);
+	if (err != KErrNone)
+		{
+		test.Printf(_L("HelpTestStepSetBreak - Failed to set breakpoint\n"));
+		return err;
+		}
+
+	// Continue the thread
+	err = iServSession.ResumeThread(aThreadId);
+	if (err != KErrNone)
+		{
+		test.Printf(_L("HelpTestStepSetBreak - Failed to resume thread\n"));
+		return err;
+		}
+
+	return KErrNone;
+	}
+
+/**
+ * Helper code for the stepping tests. Clears a breakpoint in a running thread.
+ * It suspends the thread, clears the breakpoint, and resumes the thread.
+ *
+ * @param aBreakId - Reference to a TBreakId which will be set when the breakpoint is set
+ * @return KErrNone if successful. One of the other system wide error codes otherwise.
+ */
+TInt CRunModeAgent::HelpTestStepClearBreak(TBreakId aBreakId, const TThreadId aThreadId, TBool aThreadSpecific)
+	{
+	TInt err = KErrNone;
+
+	// Find out what thread id we need to suspend
+	TThreadId threadId;
+	TProcessId processId;
+	TUint32 address;
+	TArchitectureMode mode;
+
+	err = aThreadSpecific
+		? iServSession.BreakInfo(aBreakId, threadId, address, mode)
+		: iServSession.ProcessBreakInfo(aBreakId, processId, address, mode);
+	if (err != KErrNone )
+		{
+		test.Printf(_L("HelpTestStepClearBreak - failed to obtain information for breakpoint\n"));
+		return err;
+		}
+	if(aThreadSpecific && aThreadId != threadId)
+		{
+		test.Printf(_L("HelpTestStepClearBreak - mismatched thread Ids\n"));
+		return KErrGeneral;
+		}
+
+	// Clear the breakpoint
+	err = iServSession.ClearBreak(aBreakId);
+	if (err != KErrNone)
+		{
+		test.Printf(_L("HelpTestStepClearBreak - failed to clear breakpoint\n"));
+		return err;
+		}
+
+	return KErrNone;
+	}
+
+/**
+ * Helper code for the stepping tests. Waits for a previously set breakpoint to be hit.
+ *
+ * @param aProcessName - The name of the process in which the breakpoint is set. E.g. z:\sys\bin\app.exe
+ * @param aEventInfo - The event information block which is filled in when the breakpoint is hit.
+ * @return KErrNone if successful. One of the other system wide error codes otherwise.
+ */
+TInt CRunModeAgent::HelpTestStepWaitForBreak(const TDesC& aProcessName, TEventInfo& aEventInfo)
+	{
+	static TRequestStatus status;
+
+	TPtr8 infoPtr((TUint8*)&aEventInfo,0,sizeof(TEventInfo));
+
+	iServSession.GetEvent(aProcessName,status,infoPtr);
+
+	// Wait for notification of the breakpoint hit event
+	User::WaitForRequest(status);
+	if (status == KErrNone)
+		{
+		return KErrNone;
+		}
+	else
+		{
+		return KErrGeneral;
+		}
+	}
+
+/**
+ * Helper code for the stepping tests. Reads the current target PC for a given thread.
+ *
+ * @param aThreadId - Thread id for which to read the current target PC.
+ * @param aPc - Reference to a TUint32 which will be set to the current target PC.
+ * @return KErrNone if successful. One of the other system wide error codes otherwise.
+ */
+TInt CRunModeAgent::HelpTestStepReadPC(TThreadId aThreadId, TUint32& aPC)
+	{
+	TInt err = KErrNone;
+
+	//create buffer containing PC register ID
+	RBuf8 pcId;
+	err = pcId.Create(sizeof(TRegisterInfo));
+	if (err != KErrNone)
+		{
+		return err;
+		}
+
+	TRegisterInfo reg1 = (TRegisterInfo)0x00000f00;
+	pcId.Append(reinterpret_cast<const TUint8*>(&reg1), sizeof(TRegisterInfo));
+
+	//create buffer containing desired PC value
+	TPtr8 pcValue((TUint8*)&aPC,4,4);
+
+	//create buffer for PC flag value
+	RBuf8 pcFlag;
+	err = pcFlag.Create(sizeof(TUint8));
+
+	//read the new PC value
+	err = iServSession.ReadRegisters(aThreadId, pcId, pcValue, pcFlag);
+	if (err != KErrNone)
+		{
+		//delete temporary buffers
+		pcId.Close();
+		pcFlag.Close();
+		return err;
+		}
+
+	//get the flag and check the PC value was read ok
+	TRegisterFlag flag = ENotSupported;
+	err = GetFlag(pcFlag, 0, flag);
+	if (err != KErrNone)
+		{
+		//delete temporary buffers
+		pcId.Close();
+		pcFlag.Close();
+		return err;
+		}
+
+	if (flag == EValid)
+		{
+		//delete temporary buffers
+		pcId.Close();
+		pcFlag.Close();
+		return KErrNone;
+		}
+	else
+		{
+		//delete temporary buffers
+		pcId.Close();
+		pcFlag.Close();
+		return err;
+		}
+	}
+
+/**
+ * Helper code for the stepping tests. Single steps a given thread from aStartAddress to aEndAddress. Note
+ * that it reaches aStartAddress by setting a breakpoint at that address and waiting until it is hit.
+ *
+ * @param aThreadId - Thread id for which to read the current target PC.
+ * @param aStartAddress - The target address at which stepping will start.
+ * @param aEndAddress - The target address at which stepping will end.
+ * @param aMode - The architecture of the breakpoint which must be set at the start address (ARM/Thumb/Thumb2EE).
+ * @return KErrNone if successful. One of the other system wide error codes otherwise.
+ */
+TInt CRunModeAgent::HelpTestStep(TThreadId aThreadId, TUint32 aStartAddress, TUint32 aEndAddress, TArchitectureMode aMode, TUint aNumSteps, TBool aThreadSpecific, TProcessId aProcessId)
+	{
+	TInt err = KErrNone;
+
+	// Ensure that the supplied addresses are word/half-word aligned as appropriate.
+	if (aMode == EArmMode)
+		{
+		// ARM breakpoints must be word-aligned (2 lsb must be zero)
+		aStartAddress &= 0xFFFFFFFC;
+		aEndAddress &= 0xFFFFFFFC;
+		}
+	else if (aMode == EThumbMode)
+		{
+		// Thumb breakpoints must be half-word aligned (lsb must be zero)
+		aStartAddress &= 0xFFFFFFFE;
+		aEndAddress	 &= 0xFFFFFFFE;
+		}
+	else if (aMode == EThumb2EEMode)
+	{
+		// Thumb2EE breakpoints are not currently supported
+		return KErrNotSupported;
+	}
+
+	// Set breakpoint at the start address
+	TBreakId tempBreakId;
+	TEventInfo info;
+
+	err = HelpTestStepSetBreak(tempBreakId,aThreadId,aStartAddress,aMode,aThreadSpecific,aProcessId);
+	if (err != KErrNone)
+		{
+		test.Printf(_L("HelpTestStep - Failed to set breakpoint at aStartAddress 0x%08x\n"),aStartAddress);
+		return err;
+		}
+
+	// wait for the breakpoint to be hit
+	err = HelpTestStepWaitForBreak(iFileName,info);
+	if (err != KErrNone)
+		{
+		test.Printf(_L("HelpTestStep - Failed to hit the breakpoint at aStartAddress 0x%08x\n"),aStartAddress);
+		return err;
+		}
+
+	// Check the PC == aStartAddress
+	TUint32 pc = 0;
+	err = HelpTestStepReadPC(aThreadId,pc);
+	if (err != KErrNone)
+		{
+		test.Printf(_L("HelpTestStep - Failed to read the PC after hitting breakpoint at aStartAddress 0x%08x\n"),aStartAddress);
+		return err;
+		}
+
+	if (pc != aStartAddress)
+		{
+		test.Printf(_L("HelpTestStep - Incorrect PC value after hitting breakpoint (expected 0x%08x actual 0x%08x)\n"),aStartAddress,pc);
+		return KErrGeneral;
+		}
+
+	err = iServSession.Step(aThreadId,aNumSteps);
+	if (err != KErrNone)
+		{
+		test.Printf(_L("HelpTestStep - Failed to do step from 0x%08x to 0x%08x\n"),aStartAddress,aEndAddress,aNumSteps);
+		return err;
+		}
+
+	// only one 'completed step' event in the buffer.
+	err = HelpTestStepWaitForBreak(iFileName,info);
+	if (err != KErrNone)
+		{
+		test.Printf(_L("HelpTestStep - Could not read breakpoint event info after stepping"));
+		return err;
+		}
+	// end
+
+	// Check PC == aEndAddress
+	err = HelpTestStepReadPC(aThreadId,pc);
+	if (err != KErrNone)
+		{
+		test.Printf(_L("HelpTestStep - failed read the PC after stepping\n"));
+		return err;
+		}
+	if (pc != aEndAddress)
+		{
+		test.Printf(_L("HelpTestStep - Incorrect PC value after stepping (expected 0x%08x actual 0x%08x)\n"),aEndAddress,pc);
+		return KErrGeneral;
+		}
+
+	// Clear the breakpoint
+	err = HelpTestStepClearBreak(tempBreakId, aThreadId, aThreadSpecific);
+	if (err != KErrNone)
+		{
+		test.Printf(_L("HelpTestStep - failed to clear temporary breakpoint\n"));
+		return err;
+		}
+
+	return KErrNone;
+	}
+
+/**
+ * Helper code for the stepping tests. Returns the number of nanokernel ticks in one second.
+ *
+ * @return Number of nanokernel ticks. 0 if unsuccesful.
+ */
+TInt CRunModeAgent::HelpTicksPerSecond(void)
+	{
+	TInt nanokernel_tick_period;
+	HAL::Get(HAL::ENanoTickPeriod, nanokernel_tick_period);
+
+	ASSERT(nanokernel_tick_period != 0);
+
+	static const TInt KOneMillion = 1000000;
+
+	return KOneMillion/nanokernel_tick_period;
+	}
+
+/**
+  Given aTestNumber runs the appropriate test inside heap markers
+
+  @param aTestNumber test to run, corresponds to an entry in iTestArray
+
+  @panic Panic if aTestNumber is not in valid range
+  */
+void CRunModeAgent::RunTest(TInt aTestNumber)
+	{
+	if( (aTestNumber<0) || (aTestNumber>=KMaxTests) )
+		{
+		User::Panic(_L("Test number out of range"), aTestNumber);
+		}
+	__UHEAP_MARK;
+	(this->*(iTestArray[aTestNumber].iFunctionPtr))();
+	__UHEAP_MARKEND;
+	}
+
+void CRunModeAgent::PrintVersion()
+	{
+	test.Printf(_L("\nt_rmdebug2.exe\nVersion: %S\n"), &(testVersion.Name()));
+	test.Printf(_L("Press any key...\n"));
+	test.Getch();
+	}
+
+void CRunModeAgent::PrintUsage()
+	{
+	test.Printf(_L("Invoke with arguments:\n"));
+	test.Printf(_L("-r: run specified tests in reverse order\n"));
+	test.Printf(_L("-h: display usage information\n"));
+	test.Printf(_L("-v: display version\n"));
+	test.Printf(_L("-d: use delays\n"));
+	test.Printf(_L("<number>: test number to run, can specify more than one from the following list:\n"));
+	test.Printf(_L("Press any key for list...\n"));
+	test.Getch();
+	// if there are too many of these they won't fit on the screen! Stick another Getch() in if there get too many
+	for(TInt i=0; i<KMaxTests; i++)
+		{
+		test.Printf(_L("%2d: %S\n"), i, &(iTestArray[i].iFunctionName));
+		}
+	test.Printf(_L("Press any key...\n"));
+	test.Getch();
+	}
+
+/**
+  Parse the command line, see CRunModeAgent::PrintUsage for syntax
+  */
+void CRunModeAgent::ParseCommandLineL(TUint32& aMode, RArray<TInt>& aTests)
+	{
+	// get the length of the command line arguments
+	TInt argc = User::CommandLineLength();
+
+	// allocate a buffer for the command line arguments and extract the data to it
+	HBufC* commandLine = HBufC::NewLC(argc);
+	TPtr commandLineBuffer = commandLine->Des();
+	User::CommandLine(commandLineBuffer);
+
+	// reset mode
+	aMode = (TTestMode)0;
+
+	// create a lexer and read through the command line
+	TLex lex(*commandLine);
+	while (!lex.Eos())
+		{
+		// expecting the first character to be a '-'
+		if (lex.Get() == '-')
+			{
+			TChar arg = lex.Get();
+			switch (arg)
+				{
+				case 'v':
+					//print out the help
+					aMode |= EModeVersion;
+					break;
+				case 'h':
+					//print out the help
+					aMode |= EModeHelp;
+					break;
+				case 'r':
+					//store the fact that we want to run in reverse
+					aMode |= EModeReverse;
+					break;
+				case 'd':
+					//store the fact that we want to run in reverse
+					gUseDelay = EFalse;
+					RDebug::Printf("Not using delays");
+					break;
+				default:
+					// unknown argument so leave
+					User::Leave(KErrArgument);
+				}
+			}
+		else
+			{
+			lex.UnGet();
+			TInt testNumber;
+			User::LeaveIfError(lex.Val(testNumber));
+			if( (testNumber<0) || (testNumber>=KMaxTests) )
+				{
+				User::Leave(KErrArgument);
+				}
+			aTests.AppendL(testNumber);
+			}
+		lex.SkipSpace();
+		}
+	// if no tests specified then run them all
+	if(aTests.Count() == 0)
+		{
+		aMode |= EModeAll;
+		}
+
+	// do clean up
+	CleanupStack::PopAndDestroy(commandLine);
+	}
+
+void CRunModeAgent::ClientAppL()
+//
+// Performs each test in turn
+//
+	{
+	test.Start(_L("ClientAppL"));
+
+	RArray<TInt> testsToRun;
+	TUint32 testMode = 0;
+	ParseCommandLineL(testMode, testsToRun);
+
+	//if help or version mode specified then just print out the relevant stuff and quit
+	if((testMode & EModeHelp) || (testMode & EModeVersion))
+		{
+		if(testMode & EModeHelp)
+			{
+			PrintUsage();
+			}
+		if(testMode & EModeVersion)
+			{
+			PrintVersion();
+			}
+		test.End();
+		return;
+		}
+
+	if(testMode & EModeAll)
+		{
+		for(TInt i=0; i<KMaxTests; i++)
+			{
+			testsToRun.AppendL(i);
+			}
+		}
+
+	// if EModeReverse specified then reverse the array elements
+	TInt numberOfTests = testsToRun.Count();
+	if(testMode & EModeReverse)
+		{
+		for(TInt i=0; i<(numberOfTests>>1); i++)
+			{
+			TInt temp = testsToRun[i];
+			testsToRun[i] = testsToRun[numberOfTests - (i+1)];
+			testsToRun[numberOfTests - (i+1)] = temp;
+			}
+		}
+
+	__UHEAP_MARK;
+	SetupAndAttachToDSS();
+	__UHEAP_MARKEND;
+
+	HelpStartTestTimer();
+	for(TInt i=0; i<numberOfTests; i++)
+		{
+		RunTest(testsToRun[i]);
+		if( gUseDelay ) User::After(500000);
+		}
+	testsToRun.Close();
+
+	HelpStopTestTimer();
+
+	ReportPerformance();
+
+	test.End();
+	}
+
+/**
+  Fill the test array with pointers to each test.
+  */
+void CRunModeAgent::FillArray()
+	{
+	iTestArray[0].iFunctionPtr = &CRunModeAgent::TestDriverSecurity;
+	iTestArray[0].iFunctionName = _L("TestDriverSecurity");
+	iTestArray[1].iFunctionPtr = &CRunModeAgent::TestDllUsage;
+	iTestArray[1].iFunctionName = _L("TestDllUsage");
+	iTestArray[2].iFunctionPtr = &CRunModeAgent::TestSecurity;
+	iTestArray[2].iFunctionName = _L("TestSecurity");
+	iTestArray[3].iFunctionPtr = &CRunModeAgent::TestAttachExecutable;
+	iTestArray[3].iFunctionName = _L("TestAttachExecutable");
+	iTestArray[4].iFunctionPtr = &CRunModeAgent::TestGetExecutablesList;
+	iTestArray[4].iFunctionName = _L("TestGetExecutablesList");
+	iTestArray[5].iFunctionPtr = &CRunModeAgent::TestGetProcessList;
+	iTestArray[5].iFunctionName = _L("TestGetProcessList");
+	iTestArray[6].iFunctionPtr = &CRunModeAgent::TestGetXipLibrariesList;
+	iTestArray[6].iFunctionName = _L("TestGetXipLibrariesList");
+	iTestArray[7].iFunctionPtr = &CRunModeAgent::TestGetThreadList;
+	iTestArray[7].iFunctionName = _L("TestGetThreadList");
+	iTestArray[8].iFunctionPtr = &CRunModeAgent::TestGetCodeSegsList;
+	iTestArray[8].iFunctionName = _L("TestGetCodeSegsList");
+	iTestArray[9].iFunctionPtr = &CRunModeAgent::TestGetListInvalidData;
+	iTestArray[9].iFunctionName = _L("TestGetListInvalidData");
+	iTestArray[10].iFunctionPtr = &CRunModeAgent::TestMemoryAccess;
+	iTestArray[10].iFunctionName = _L("TestMemoryAccess");
+	iTestArray[11].iFunctionPtr = &CRunModeAgent::TestDebugFunctionality;
+	iTestArray[11].iFunctionName = _L("TestDebugFunctionality");
+	iTestArray[12].iFunctionPtr = &CRunModeAgent::TestSuspendResume;
+	iTestArray[12].iFunctionName = _L("TestSuspendResume");
+	iTestArray[13].iFunctionPtr = &CRunModeAgent::TestBreakPoints;
+	iTestArray[13].iFunctionName = _L("TestBreakPoints");
+	iTestArray[14].iFunctionPtr = &CRunModeAgent::TestModifyBreak;
+	iTestArray[14].iFunctionName = _L("TestModifyBreak");
+	iTestArray[15].iFunctionPtr = &CRunModeAgent::TestBreakInfo;
+	iTestArray[15].iFunctionName = _L("TestBreakInfo");
+	iTestArray[16].iFunctionPtr = &CRunModeAgent::TestRunToBreak;
+	iTestArray[16].iFunctionName = _L("TestRunToBreak");
+	iTestArray[17].iFunctionPtr = &CRunModeAgent::TestBreakPointsInLoop;
+	iTestArray[17].iFunctionName = _L("TestBreakPointsInLoop");
+	iTestArray[18].iFunctionPtr = &CRunModeAgent::TestRegisterAccess;
+	iTestArray[18].iFunctionName = _L("TestRegisterAccess");
+	iTestArray[19].iFunctionPtr = &CRunModeAgent::TestStep;
+	iTestArray[19].iFunctionName = _L("TestStep");
+	iTestArray[20].iFunctionPtr = &CRunModeAgent::TestDemandPaging;
+	iTestArray[20].iFunctionName = _L("TestDemandPaging");
+	iTestArray[21].iFunctionPtr = &CRunModeAgent::TestEventsForExternalProcess;
+	iTestArray[21].iFunctionName = _L("TestEventsForExternalProcess");
+	iTestArray[22].iFunctionPtr = &CRunModeAgent::TestEvents;
+	iTestArray[22].iFunctionName = _L("TestEvents");
+	iTestArray[23].iFunctionPtr = &CRunModeAgent::TestKillProcess;
+	iTestArray[23].iFunctionName = _L("TestKillProcess");
+	iTestArray[24].iFunctionPtr = &CRunModeAgent::TestProcessBreakPoints;
+	iTestArray[24].iFunctionName = _L("TestProcessBreakPoints");
+	iTestArray[25].iFunctionPtr = &CRunModeAgent::TestMultipleTraceEvents;
+	iTestArray[25].iFunctionName = _L("TestMultipleTraceEvents");
+	iTestArray[26].iFunctionPtr = &CRunModeAgent::TestAddRemoveProcessEvents;
+	iTestArray[26].iFunctionName = _L("TestAddRemoveProcessEvents");
+	iTestArray[27].iFunctionPtr = &CRunModeAgent::TestCrashFlash;
+	iTestArray[27].iFunctionName = _L("TestCrashFlash");
+	iTestArray[28].iFunctionPtr = &CRunModeAgent::TestProcessKillBreakpoint;
+	iTestArray[28].iFunctionName = _L("TestProcessKillBreakpoint");
+	iTestArray[29].iFunctionPtr = &CRunModeAgent::TestAttachToAll;
+	iTestArray[29].iFunctionName = _L("TestAttachToAll");
+	iTestArray[30].iFunctionPtr = &CRunModeAgent::TestResumeBreakpointsRepeatedly;
+	iTestArray[30].iFunctionName = _L("TestResumeBreakpointsRepeatedly");
+
+	};
+
+GLDEF_C TInt E32Main()
+//
+// Entry point for run mode debug driver test
+//
+	{
+   TInt ret = KErrNone;
+
+	// client
+	CTrapCleanup* trap = CTrapCleanup::New();
+	if (!trap)
+		return KErrNoMemory;
+   	test.Title();
+   RunModeAgent = CRunModeAgent::NewL();
+   if (RunModeAgent != NULL)
+       {
+        __UHEAP_MARK;
+	    TRAP(ret,RunModeAgent->ClientAppL());
+	    __UHEAP_MARKEND;
+
+	    delete RunModeAgent;
+       }
+
+	delete trap;
+
+	return ret;
+	}
+
+/**
+Helper function to get the aOffset'th value from aFlags
+
+@param aFlags descriptor containing TRegisterFlag type flags
+@param aOffset index of flag value to extract from aFlags
+@param aFlagValue the flag value if function returned successfully
+
+@return KErrNone if value was read successfully, KErrTooBig if aOffset is
+        greater than aFlags.Length()
+*/
+TInt CRunModeAgent::GetFlag(const TDes8& aFlags, const TUint aOffset, TRegisterFlag &aFlagValue) const
+	{
+	//get pointer to data
+	const TUint8 *ptr = aFlags.Ptr();
+
+	//check aOffset is valid
+	TUint length = aFlags.Length();
+	if(aOffset >= length)
+		return KErrTooBig;
+
+	//get flag value
+	aFlagValue = (TRegisterFlag)ptr[aOffset];
+	return KErrNone;
+	}
+
+/**
+  Helper function to set the value of FunctionChooser in the target debug thread.
+
+  @param aTestFunction TTestFunction enum to set FunctionChooser to
+
+  @return KErrNone if the value was set correctly, or one of the other system wide error codes
+  */
+TInt CRunModeAgent::SwitchTestFunction(TTestFunction aTestFunction, const TBool aResume)
+	{
+	//suspend the target thread
+	TInt suspendError = iServSession.SuspendThread(iThreadID);
+	if(! ( (suspendError == KErrNone) || (suspendError == KErrAlreadyExists) ) )
+		{
+		//the thread is not suspended so exit
+		return suspendError;
+		}
+
+	//get the address of FunctionChooser
+	TUint32 functionChooserAddress = (TUint32)&FunctionChooser;
+	//put the new value for FunctionChooser into a descriptor
+	TPtr8 functionBuf((TUint8*)&aTestFunction, sizeof(TTestFunction), sizeof(TTestFunction));
+	//write the new value into the target thread
+	TInt writeError = iServSession.WriteMemory(iThreadID, functionChooserAddress, sizeof(TTestFunction), functionBuf, EAccess32, EEndLE8);
+
+	if( (KErrNone == suspendError) && aResume )
+		{
+		//if this function suspended the target thread then we need to resume it
+		TInt resumeError = iServSession.ResumeThread(iThreadID);
+		if(KErrNone != resumeError)
+			{
+			//resuming failed so return the error
+			return resumeError;
+			}
+		}
+
+	//suspending and resuming was successful so return the error code from the WriteMemory call
+	return writeError;
+	}
+
+/**
+  Launch a separate process to debug.
+
+  @param aProcess the RProcess object to use to create the process
+  @param aFileName file name of the executable to create the process from
+  @param aFunctionType function that the target process should call on execution
+  @param aDelay delay before the new process should call the function represented by aFunctionType
+  @param aExtraThreads number of extra threads to create in the child process
+
+  @return KErrNone on success, or one of the other system wide error codes
+  */
+TInt CRunModeAgent::LaunchProcess(RProcess& aProcess, const TDesC& aFileName, TDebugFunctionType aFunctionType, TUint32 aDelay, TUint32 aExtraThreads)
+	{
+	// at the moment we support two arguments, this number might have to be increased to support arguments
+	const TUint KMaxCommandLineLength = 32;
+
+	// create a command line buffer
+	RBuf commandLine;
+	commandLine.Create(KMaxCommandLineLength);
+
+	// append the command line arguments to the buffer
+	_LIT(KFArg, "-f");
+	commandLine.Append(KFArg());
+	commandLine.AppendNum(aFunctionType);
+
+	_LIT(KSpace, " ");
+	commandLine.Append(KSpace());
+
+	_LIT(KDArg, "-d");
+	commandLine.Append(KDArg());
+	commandLine.AppendNum(aDelay);
+
+	commandLine.Append(KSpace());
+
+	_LIT(KEArg, "-e");
+	commandLine.Append(KEArg());
+	commandLine.AppendNum(aExtraThreads);
+
+	// create the new process, matching on file name only, not specifying uid values
+	TInt err = aProcess.Create(aFileName, commandLine);	// owned by the process
+
+	// check that there was no error raised
+	if(err != KErrNone)
+		{
+		commandLine.Close();
+		return err;
+		}
+
+	TRequestStatus status = KRequestPending;
+	aProcess.Rendezvous(status);
+
+	commandLine.Close();	// after target thread starts
+
+	if(KRequestPending != status.Int())
+		{
+		// startup failed so kill the process
+		aProcess.Kill(KErrNone);
+		return status.Int();
+		}
+	else
+		{
+		// start up succeeded so resume the process
+		aProcess.Resume();
+		User::WaitForRequest(status);
+		if(KErrNone != status.Int())
+			{
+			aProcess.Kill(KErrNone);
+			}
+		return status.Int();
+		}
+	}
+
+/**
+  Helper function to read a tag header from a debug functionality block
+
+  @param aDebugFunctionalityBlock block to read header from
+  @param aTagHdrId header type to find
+
+  @return pointer to the header, or NULL if not available
+  */
+TTagHeader* CRunModeAgent::GetTagHdr(const TDesC8& aDebugFunctionalityBlock, const TTagHeaderId aTagHdrId) const
+	{
+	TUint8* ptr = (TUint8*) aDebugFunctionalityBlock.Ptr();
+	TUint8* blockEnd = ptr + aDebugFunctionalityBlock.Size();
+
+	while(ptr < blockEnd)
+		{
+		TTagHeader* header = (TTagHeader*)ptr;
+		if(header->iTagHdrId == aTagHdrId)
+			{
+			return header;
+			}
+		ptr += sizeof(TTagHeader) + (header->iNumTags * sizeof(TTag));
+		}
+	return NULL;
+	}
+
+/**
+  Helper function to read a tag from a debug functionality block
+
+  @param aTagHdr pointer to a tag header in a debug functionality block
+  @param aElement element to return from the header's data
+
+  @return pointer to the tag, or NULL if not available
+  */
+TTag* CRunModeAgent::GetTag(const TTagHeader* aTagHdr, const TInt aElement) const
+	{
+	TUint8* ptr = (TUint8*)aTagHdr + sizeof(TTagHeader);
+	TUint8* blockEnd = ptr + (aTagHdr->iNumTags * sizeof(TTag));
+
+	while(ptr < blockEnd)
+		{
+		TTag* tag = (TTag*)ptr;
+		if(tag->iTagId == aElement)
+			{
+			return tag;
+			}
+		ptr += sizeof(TTag);
+		}
+	return NULL;
+	}
+
+TTag CRunModeAgent::GetTag(const TTagHeaderId aTagHdrId, const TInt aElement)
+	{
+	TUint32 bufsize = 0;	// Safe default size
+
+	// Get functionality block size
+	test(KErrNone == iServSession.GetDebugFunctionalityBufSize(&bufsize));
+
+	// Ensure we have a finite buffer size
+	test(bufsize!=0);
+
+	// Allocate space for the functionality data
+	HBufC8* dftext = HBufC8::NewLC(bufsize);
+
+	// create an empty TPtr8 refering to dftext
+	TPtr8 dftextPtr(dftext->Des());
+
+	// Get the functionality block
+	test(KErrNone == iServSession.GetDebugFunctionality(dftextPtr));
+
+	// read a value from the data to check it has come through as expected
+	TTagHeader* header = GetTagHdr(dftext->Des(), aTagHdrId);
+	test(header != NULL);
+	TTag* tag = GetTag(header, aElement);
+	test(tag != NULL);
+
+	TTag tagToReturn = *tag;
+
+	// Remove our temporary buffer
+	CleanupStack::PopAndDestroy(dftext);
+
+	return tagToReturn;
+	}
+
+/**
+  Helper function which returns a Boolean indicating with a process with the
+  specified name is currently running.
+
+  @param aProcessName - Name of the process to find
+  @return ETrue if found, EFalse otherwise
+  */
+TBool CRunModeAgent::ProcessExists(const TDesC& aProcessName)
+	{
+	TInt    err=KErrNone;
+	TBool	found = FALSE;
+
+_LIT(KWildCard,"*");
+
+	TFindProcess find(KWildCard);
+	TFullName name;
+	while(find.Next(name)==KErrNone)
+		{
+		RProcess process;
+		err = process.Open(find);
+		if (err == KErrNone)
+			{
+			if (name.Find(aProcessName) != KErrNotFound)
+				{
+					found = TRUE;
+				}
+			process.Close();
+			}
+	   }
+
+	return found;
+	}
+
+TInt PanicFn(TAny*)
+	{
+	User::Panic(_L("trmdebug_dummy"), 123);
+	return 0;
+	}
+
+void CRunModeAgent::TestAttachToAll()
+	{
+	test.Next(_L("TestAttachToAll - Attach\n"));
+
+#ifdef ALLCAPS_DEBUGTOKEN
+	test.Next(_L("---- First AttachAll \n"));
+	test(iServSession.AttachAll() == KErrNone);
+	test.Next(_L("---- Second AttachAll \n"));	
+	test(iServSession.AttachAll() == KErrAlreadyExists); // Don't think an agent should be allowed to AttachToAll more than once
+	
+	test.Next(_L("---- DetachAll\n"));
+	test(iServSession.DetachAll() == KErrNone);
+	test.Next(_L("---- AttachAll again\n"));
+	test(iServSession.AttachAll() == KErrNone);
+	
+	test.Next(_L("---- Suspend thread\n"));
+	test( iServSession.SuspendThread(iThreadID) == KErrNone);
+
+	// Check that AttachAll picks up thread crashes without needing to be explicitly attached
+	test.Next(_L("---- Attach all SetEventAction\n"));
+	TInt err = iServSession.SetEventAction(EEventsKillThread, EActionSuspend);
+	test(err == KErrNone);
+
+	test.Next(_L("---- Create DebugThread2\n"));
+	// Set up the thread
+	RThread threadToPanic;
+	err = threadToPanic.Create(_L("DebugThread2"), &PanicFn, 8192, NULL, NULL);
+	test(err == KErrNone);
+	TRequestStatus undertakerStat;
+	threadToPanic.Logon(undertakerStat);
+	test(undertakerStat.Int() == KRequestPending);
+
+	// Start listening for events
+	TRequestStatus stat;
+	TEventInfo info;
+	TPckg<TEventInfo> infoPkg(info);
+	test.Next(_L("Attach all get event and then resume thread DebugThread2\n"));
+	
+	iServSession.GetEvent(stat, infoPkg);
+	
+	threadToPanic.Resume();
+	
+	test.Printf(_L("Waiting for DebugThread2 panic event to be picked up by AttachToAll\n"));
+	User::WaitForRequest(stat);
+	test(stat.Int() == KErrNone);
+	test(info.iThreadId == threadToPanic.Id());
+	test(info.iEventType == EEventsKillThread);
+	test(info.iThreadKillInfo.iExitType == EExitPanic);
+
+	test(undertakerStat.Int() == KRequestPending); // This shouldn't get completed until after we call iServSession.ResumeThread below
+
+	// Now resume the thread and wait for the Logon to complete
+	test.Next(_L("---- Attach all resume panic thread and then wait for event after DSS has handled it\n"));
+	err = iServSession.ResumeThread(threadToPanic.Id());
+	test(err == KErrNone);
+	User::WaitForRequest(undertakerStat);
+	test(undertakerStat.Int() == 123); // The panic reason set in PanicFn is 123
+
+	// And clean up, 
+	ResetAttachToAll(threadToPanic);
+	//still attached to all
+	
+	// Test that an explicit attach eclipses an AttachAll, and the AttachAll session 
+	// doesn't see the events for specifically attached executables
+	test.Next(_L(" ---- ExplicitAttachBeatsAttachAll\n"));
+
+	// We shouldn't see this event because of sess2
+	err = iServSession.SetEventAction(EEventsStartThread, EActionContinue); 
+	test(err == KErrNone);
+	iServSession.GetEvent(stat, infoPkg);
+	test(stat.Int() == KRequestPending);
+
+	test.Next(_L("---- New sec session\n"));
+	RSecuritySvrSession sess2;
+	test(sess2.Connect(securityServerVersion) == KErrNone);
+	test.Next(_L("---- New sec session Attach executable \n"));
+	test(sess2.AttachExecutable(iFileName, EFalse) == KErrNone);
+	err = sess2.SetEventAction(iFileName, EEventsKillThread, EActionSuspend);
+	test(err == KErrNone);
+	// The EActionSuspend above should trump this EActionContinue
+	err = iServSession.SetEventAction(EEventsKillThread, EActionContinue); 
+	test(err == KErrNone);
+
+	test.Next(_L("---- New sec session create DebugThread3\n"));
+	err = threadToPanic.Create(_L("DebugThread3"), &PanicFn, 8192, NULL, NULL);
+	test(err == KErrNone);
+	
+	// The attach executable above leads the DSS to launch the token, which results 
+	// in a start thread event, and since we have done an attach all and a get event, 
+	// the TReqStat will be completed accordingly for this token start event. 
+	
+	threadToPanic.Logon(undertakerStat);
+	test(undertakerStat.Int() == KRequestPending); 
+
+	TRequestStatus sess2stat;
+	TEventInfo sess2event;
+	TPckg<TEventInfo> sess2eventPkg(sess2event);
+	test.Next(_L("---- New sec session get event, TReqStat\n") );
+	RDebug::Printf(" undertakerStat=0x%x, sess2stat = 0x%x, Pkg=0x%x", 
+			&undertakerStat, &sess2stat, &sess2eventPkg);
+	
+	sess2.GetEvent(iFileName, sess2stat, sess2eventPkg);
+	// sess2 didn't ask for EEventsStartThread so we should still be pending at this point	
+	test(sess2stat == KRequestPending); 
+
+	test.Next(_L("---- New sec session resume thread and wait for kill event\n"));
+	threadToPanic.Resume();
+	User::WaitForRequest(sess2stat);
+
+	test(sess2stat.Int() == KErrNone);
+	test(sess2event.iThreadId == threadToPanic.Id());
+	test(sess2event.iEventType == EEventsKillThread);
+	test(sess2event.iThreadKillInfo.iExitType == EExitPanic);
+
+	// the EActionSuspend that sess2 specified should ensure this doesn't get completed
+	test(undertakerStat == KRequestPending);
+
+	// Now resume the thread and wait for the Logon to complete
+	test.Next(_L("---- ExplicitAttachBeatsAttachAll resume thread 3 after kill\n"));
+	err = sess2.ResumeThread(threadToPanic.Id());
+	test(err == KErrNone);
+	User::WaitForRequest(undertakerStat);
+	test(undertakerStat.Int() == 123); // The panic reason set in PanicFn is 123
+
+	// And clean up
+	ResetAttachToAll(threadToPanic, &stat, &sess2);
+	test.Next(_L("---- Finishing ExplicitAttachBeatsAttachAll > sess2.Close\n"));
+	
+	sess2.Close();
+#if 0
+	//TODO allow this by changing from agent pid to session ids in DSS.
+	// This will allow a client to have more than one session and call attachall
+	
+	// Test that a second AttachAll eclipses the first
+	// Commented out since not sure we require this
+
+	test.Next(_L("SecondAttachAllBeatsAttachAll"));
+	
+	//TODO fix detachall in ResetAttachToAll
+	test(iServSession.AttachAll() == KErrNone);
+	test(sess2.AttachAll() == KErrNone);
+	err = iServSession.SetEventAction(EEventsKillThread, EActionSuspend);
+	test(err == KErrNone);
+	err = sess2.SetEventAction(EEventsKillThread, EActionSuspend);
+	test(err == KErrNone);
+	err = threadToPanic.Create(_L("DebugThread4"), &PanicFn, 8192, NULL, NULL);
+	test(err == KErrNone);
+	iServSession.GetEvent(stat, infoPkg);
+	test(stat.Int() == KRequestPending);
+	sess2.GetEvent(sess2stat, sess2eventPkg);
+	test(sess2stat.Int() == KRequestPending);
+
+	threadToPanic.Resume();
+	User::WaitForRequest(sess2stat);
+	test(sess2event.iThreadId == threadToPanic.Id());
+	test(sess2event.iEventType == EEventsKillThread);
+	test(sess2event.iThreadKillInfo.iExitType == EExitPanic);
+	test(stat.Int() == KRequestPending); // Shouldn't see the killthread event because of sess2
+
+	// And cleanup
+	ResetAttachToAll(threadToPanic, &stat, &sess2);
+	//TODO fixme test(sess2.DetachAll() == KErrNone);
+#endif
+
+#else
+	test(iServSession.AttachAll() == KErrPermissionDenied);
+#endif
+	}
+
+void CRunModeAgent::ResetAttachToAll(RThread& aTestThread, TRequestStatus* aFirstSessionStat, RSecuritySvrSession* aSecondSession)
+	{
+	
+	aTestThread.Close();
+
+	RDebug::Printf("---- ResetAttachToAll : > iServSession.SetEventAction Ignore for Kill and StartThread");
+	TInt err = iServSession.SetEventAction(EEventsKillThread, EActionIgnore);
+	test(err == KErrNone);
+	err = iServSession.SetEventAction(EEventsStartThread, EActionIgnore);
+	test(err == KErrNone);
+
+
+	if (aFirstSessionStat)
+		{
+		RDebug::Printf("---- ResetAttachToAll : > iServSession.CancelGetEvent");
+		iServSession.CancelGetEvent();
+		
+		RDebug::Printf("---- ResetAttachToAll : > User::WaitForRequest(*aFirstSessionStat);");
+		User::WaitForRequest(*aFirstSessionStat);
+		
+		User::After(1000000);
+		RDebug::Printf("---- ResetAttachToAll : > iServSession.DetachAll");
+		test(iServSession.DetachAll() == KErrNone);
+		}
+
+	if (aSecondSession != NULL)
+		{
+		User::After(1000000);
+		RDebug::Printf("---- ResetAttachToAll : > aSecondSession.SetEventAction kill ignore");
+		err = aSecondSession->SetEventAction(iFileName, EEventsKillThread, EActionIgnore);
+		User::After(1000000);
+		test(err == KErrNone);
+		RDebug::Printf("---- ResetAttachToAll : > aSecondSession.SetEventAction start thrd ignore");
+		err = aSecondSession->SetEventAction(iFileName, EEventsStartThread, EActionIgnore);
+		User::After(1000000);
+		test(err == KErrNone);
+		RDebug::Printf("---- ResetAttachToAll : > aSecondSession.DetachExecutable");
+		err = aSecondSession->DetachExecutable(iFileName);
+		User::After(1000000);
+		test( err == KErrNone);
+		}
+	}
+
+void CRunModeAgent::TestResumeBreakpointsRepeatedly()
+	{
+	test.Next(_L("TestResumeBreakpointsRepeatedly\n"));
+	test(iServSession.AttachExecutable(KRMDebugTestApplication, EFalse/*  Active */) == KErrNone);
+
+	RProcess debugProcess;
+	TThreadId debugThreadId;
+	LaunchDebugProcessAndSetBreakpoint(debugProcess, debugThreadId);
+	test(iServSession.ResumeThread(debugThreadId) == KErrNone);
+	
+	// Let the thread die naturally (at least from DSS's point of view)
+	debugProcess.Kill(0);
+	debugProcess.Close();
+
+	test.Printf(_L("Closing iServSession\n"));
+	iServSession.Close();
+	//User::After(1000000); // I hate myself...
+	test(iServSession.Connect(securityServerVersion) == KErrNone);
+	test(iServSession.AttachExecutable(KRMDebugTestApplication, EFalse/*  Active */) == KErrNone);
+
+	test.Printf(_L("Launching process for second time\n"));
+
+	LaunchDebugProcessAndSetBreakpoint(debugProcess, debugThreadId);
+	test(iServSession.ResumeThread(debugThreadId) == KErrNone);
+	debugProcess.Kill(0);
+	debugProcess.Close();
+
+	/*test.Printf(_L("Launching process for third time\n"));
+	debugProcess.Kill(0);
+	debugProcess.Close();
+	iServSession.Close();
+	User::After(1000000); // I hate myself...
+	test(iServSession.Connect(securityServerVersion) == KErrNone);
+	test(iServSession.AttachExecutable(KRMDebugTestApplication, EFalse/ *  Active * /) == KErrNone);
+	*/
+
+	test(KErrNone == iServSession.DetachExecutable(KRMDebugTestApplication));
+	}
+
+void CRunModeAgent::TimedWait(TRequestStatus& aStatus, TInt aTimeoutInMs, TInt aLineNumber)
+	{
+	RTimer timer;
+	TInt err = timer.CreateLocal();
+	test(err == KErrNone);
+
+	TRequestStatus timerstat;
+	timer.After(timerstat, aTimeoutInMs*1000);
+	User::WaitForRequest(aStatus, timerstat);
+	if (timerstat != KRequestPending)
+		{
+		test.Panic(_L("Timed out at line %d\n"), aLineNumber);
+		}
+	else
+		{
+		timer.Cancel();
+		User::WaitForRequest(timerstat);
+		}
+	timer.Close();
+	}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/debugsrv/runmodedebug/rmdebug_test/rm_debug/basic_tests/t_rmdebug2.h	Fri Aug 27 11:37:29 2010 +0300
@@ -0,0 +1,202 @@
+// Copyright (c) 2006-2010 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+// Definitions for the run mode debug tests
+// 
+//
+
+/**
+ @file
+ @internalTechnology
+ @released
+*/
+
+#ifndef RMDEBUG_H
+#define RMDEBUG_H
+
+#include "t_rmdebug_app.h"
+#include "r_user_low_memory_security_svr_session.h"
+#include "r_kernel_low_memory_security_svr_session.h"
+
+
+class CRunModeAgent;
+
+// Create a pointer to function type
+typedef void (CRunModeAgent::*testFunction)();
+
+class TFunctionData
+	{
+public:
+	testFunction iFunctionPtr;
+	TBuf<40> iFunctionName;
+	};
+
+//number of test functions that we have
+const TInt KMaxTests = 31; 
+
+//
+// class CRunModeAgent
+//
+// The basic run mode agent.
+//
+class CRunModeAgent : public CBase
+	{
+public:
+	static CRunModeAgent* NewL();
+	~CRunModeAgent();
+	void ClientAppL();
+
+private:
+	CRunModeAgent();
+	void ConstructL();
+	void SetupAndAttachToDSS();
+
+	TInt TestStartup();
+	TInt TestShutdown();
+
+	void TestGetExecutablesList();
+	void TestGetProcessList();
+	void TestGetThreadList();
+	void TestGetCodeSegsList();
+	void TestGetXipLibrariesList();
+	void TestGetListInvalidData();
+
+	TBool DoTestGetThreadList(const TBool aShouldPass, const Debug::TListScope aListScope, const TUint64 aTargetId=0);
+	void DoTestGetCodeSegsList(const TBool aShouldPass, const Debug::TListScope aListScope, const TUint64 aTargetId=0);
+
+	void DoGetList(const Debug::TListId aListId, const Debug::TListScope aListScope, RBuf8& aBuffer, TUint32& aSize, const TUint64 aTargetId=0);
+
+	void TestMemoryAccess();
+	void TestSuspendResume();
+	void TestBreakPoints();
+	void TestConsecutiveBreakPoints();
+	void TestModifyBreak();
+	void DoTestModifyBreak(TBool aThreadSpecific);
+	void TestBreakInfo();
+	void DoTestBreakInfo(TBool aThreadSpecific);
+	void TestRunToBreak();
+	void DoTestRunToBreak(TBool aThreadSpecific);
+	void TestBreakPointsInLoop();
+	void DoTestBreakPointsInLoop(TBool aThreadSpecific);
+	void TestRegisterAccess();
+	void TestAttachExecutable();
+	void TestDebugFunctionality();
+	void TestStep();
+	void DoTestStep(TBool aThreadSpecific);
+	void TestDriverSecurity();
+	void TestSecurity();
+	void TestEvents();
+	void TestEventsForExternalProcess();
+	void TestDemandPaging();
+	void TestTraceSecurity();
+	void TestDllUsage();
+	void TestKillProcess();
+	void TestProcessBreakPoints();
+	void TestMultipleTraceEvents();
+	void TestAddRemoveProcessEvents();
+	void TestProcessKillBreakpoint();
+	void DoTestProcessKillBreakpoint();
+	void TestAttachToAll();
+	void ResetAttachToAll(RThread& aTestThread, TRequestStatus* aFirstSessionStat=NULL, Debug::RSecuritySvrSession* aSecondSession=NULL);
+	void LaunchDebugProcessAndSetBreakpoint(RProcess& aResultProcess, TThreadId& aResultThread);
+	void TestResumeBreakpointsRepeatedly();
+
+	//crash flash test functions
+	void TestCrashFlash();
+		
+	TInt GetFlag(const TDes8 &aFlags, const TUint aOffset, Debug::TRegisterFlag &aFlagValue) const;
+
+	void ReportPerformance(void);
+
+	// helper functions
+	void HelpTestSecurityAttachDetachExecutable(const TDesC& aProcessName, TBool aExpectSuccess);
+
+	TInt HelpTestStepSetBreak(Debug::TBreakId& aBreakId, TThreadId aThreadId, const TUint32 aBreakAddress, Debug::TArchitectureMode aMode, TBool aThreadSpecific=ETrue, TProcessId aProcessId=0);
+	TInt HelpTestStepClearBreak(const Debug::TBreakId aBreakId, const TThreadId aThreadId, TBool aThreadSpecific);
+	TInt HelpTestStepWaitForBreak(const TDesC& aProcessName, Debug::TEventInfo& aEventInfo);
+	TInt HelpTestStepReadPC(TThreadId aThreadId, TUint32& aPC);
+	TInt HelpTestStep(TThreadId aThreadId, TUint32 aStartAddress, TUint32 aEndAddress, Debug::TArchitectureMode aMode, TUint aNumSteps, TBool aThreadSpecific=ETrue, TProcessId=0);
+
+	TInt HelpTicksPerSecond(void);
+
+	// helper functions
+	void HelpStartTestTimer(void) { iStartTick = User::NTickCount(); iStopTick = 0; };
+	void HelpStopTestTimer(void) { iStopTick = User::NTickCount(); };
+	TInt HelpGetTestTicks(void) { return (iStopTick - iStartTick); };
+	TInt SwitchTestFunction(TTestFunction aTestFunction, const TBool aResume = ETrue);
+	TInt LaunchProcess(RProcess& aProcess, const TDesC& aFileName, TDebugFunctionType aFunctionType, TUint32 aDelay=0, TUint32 aExtraThreads=0);
+	Debug::TTagHeader* GetTagHdr(const TDesC8& aDebugFunctionalityBlock, const Debug::TTagHeaderId aTagHdrId) const;
+	Debug::TTag* GetTag(const Debug::TTagHeader* aTagHdr, const TInt aElement) const;
+	Debug::TTag GetTag(const Debug::TTagHeaderId aTagHdrId, const TInt aElement);
+	TBool ProcessExists(const TProcessId aProcessId);
+	TBool ThreadExistsForProcess(const TThreadId aThreadId, const TProcessId aProcessId);
+	TBool ListingSupported(const Debug::TListId aListId, const Debug::TListScope aListScope);
+	void TestEventsWithExtraThreads(Debug::TKernelEventAction aActionMain, Debug::TKernelEventAction aActionExtra, TUint32 aExtraThreads);
+	void FillArray();
+	void PrintUsage();
+	void PrintVersion();
+
+	enum TTestMode 
+		{
+		//run all the tests
+		EModeAll = 1<<0,
+		//run the specified tests in reverse order
+		EModeReverse = 1<<1,
+		//print out help
+		EModeHelp = 1<<2,
+		//print out help
+		EModeVersion = 1<<3
+		};
+
+	void RunTest(TInt aTestNumber);
+	void ParseCommandLineL(TUint32& aMode, RArray<TInt>& aTests);
+
+	TBool ProcessExists(const TDesC& aProcessName);
+	static void TimedWait(TRequestStatus& aStatus, TInt aTimeoutInMs, TInt aLineNumber);
+
+
+private:
+
+	TFunctionData iTestArray[KMaxTests];
+#if defined(KERNEL_OOM_TESTING)
+	RKernelLowMemorySecuritySvrSession iServSession;
+#elif defined (USER_OOM_TESTING)
+	RUserLowMemorySecuritySvrSession iServSession;
+#else
+	Debug::RSecuritySvrSession iServSession;
+#endif
+	RThread	iDebugThread;
+	
+	//Set by test thread, used to check its run state
+	RProperty iRunCountSubscribe;
+	
+	// Used for timeouts when checking the run state
+	RTimer iTimer;
+	
+	RProcess iDSSProcess;
+	TThreadId iThreadID;
+	TFileName iFileName;
+
+	// Performance data
+	TInt iMemoryReadKbytesPerSecond;	
+	TInt iMemoryWriteKbytesPerSecond;	
+	TInt iBreakpointsPerSecond;
+	TInt iMaxBreakpoints;
+	TInt iStepsPerSecond;
+
+	// Timing information
+	TInt iStartTick;
+	TInt iStopTick;
+	};
+
+#endif // RMDEBUG_H
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/debugsrv/runmodedebug/rmdebug_test/rm_debug/basic_tests/t_rmdebug2_oemtoken.cpp	Fri Aug 27 11:37:29 2010 +0300
@@ -0,0 +1,32 @@
+// Copyright (c) 2007-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+//
+
+/**
+ @file
+ @internalTechnology
+ @released
+*/
+
+#include <e32base.h>
+#include <e32base_private.h>
+
+GLDEF_C TInt E32Main()
+	{
+	// No need to do anything, the only requirement is that
+	// this executable can be loaded and runs to completion
+	return 0;
+	}
+
+// End of file - t_rmdebug2_oemtoken.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/debugsrv/runmodedebug/rmdebug_test/rm_debug/common/t_debug_logging.h	Fri Aug 27 11:37:29 2010 +0300
@@ -0,0 +1,68 @@
+// Copyright (c) 2006-2010 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+// Logging macros for use in debug subsystem
+// 
+//
+
+#ifndef RMDEBUG_LOGGING_H
+#define RMDEBUG_LOGGING_H
+
+/* Debug messages
+ * 
+ * Debug messages are only generated for debug builds.
+ * 
+ * As user mode use RDebug::Printf(). 
+ * 
+ */
+
+// Uncomment if logging of required
+//#define RMDEBUG_LOGGING 
+
+#ifdef RMDEBUG_LOGGING
+
+   #include <e32debug.h>
+
+    #define LOG_MSG(args...)            RDebug::Printf(args)
+    #define LOG_DES(args...)            RDebug::Print(args) // For wide descriptors
+    #define LOG_ENTRY()                 RDebug::Printf("+%s", __PRETTY_FUNCTION__)
+    #define LOG_EXIT()                  RDebug::Printf("-%s", __PRETTY_FUNCTION__)
+    #define LOG_ARGS(fmt, args...)      RDebug::Printf("+%s " fmt, __PRETTY_FUNCTION__, args)
+    #define LOG_RETURN(x)               RDebug::Printf("Returning %d from [%s]", x, __PRETTY_FUNCTION__)
+
+    // Kept for compatibility
+    #define LOG_MSG2( a, b )            RDebug::Printf( a, b )
+    #define LOG_MSG3( a, b, c )         RDebug::Printf( a, b, c )
+    #define LOG_MSG4( a, b, c, d )      RDebug::Printf( a, b, c, d )
+    #define LOG_MSG5( a, b, c, d, e )   RDebug::Printf( a, b, c, d, e )
+
+#else
+
+   #include <e32debug.h>
+
+    #define LOG_MSG(args...)            
+    #define LOG_DES(args...)           
+    #define LOG_ENTRY()                 
+    #define LOG_EXIT()                 
+    #define LOG_ARGS(fmt, args...)      
+    #define LOG_RETURN(x)               
+
+    // Kept for compatibility
+    #define LOG_MSG2( a, b )            
+    #define LOG_MSG3( a, b, c )         
+    #define LOG_MSG4( a, b, c, d )     
+    #define LOG_MSG5( a, b, c, d, e )  
+
+#endif 
+
+#endif //RMDEBUG_LOGGING
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/debugsrv/runmodedebug/rmdebug_test/rm_debug/common/t_target_launcher.cpp	Fri Aug 27 11:37:29 2010 +0300
@@ -0,0 +1,224 @@
+// Copyright (c) 2007-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+// Helper app to launch debug targets. Uses command-line parameters as follows using a + sign:
+//  +n<number of applications to launch>
+//  +m<number of times to launch each application>
+//  +o<order of launch, 1 means launch in reverse order>
+//
+
+#include <e32base.h>
+#include <e32base_private.h>
+#include <e32cons.h>
+#include <e32test.h>
+#include <e32ldr.h>
+#include <e32cmn.h>
+#include <e32cmn_private.h>
+#include <f32dbg.h>
+#include <f32file.h>
+#include <hal.h>
+#include <u32hal.h>
+#include <e32property.h>
+
+#include "t_target_launcher.h"
+
+
+/**
+  Launch a process
+
+  @param aProcess The RProcess object to use to create the process
+  @param aExeName File name of the executable to create the process from
+  @param aCommandLine The command line to pass to the new process
+  @return KErrNone on success, or one of the other system wide error codes
+  */
+TInt LaunchProcess(RProcess& aProcess, TDesC & aExeName, TPtr & aCommandLine )
+    {
+
+    TPtrC commandLine( aCommandLine );
+
+    TInt err = aProcess.Create( aExeName, commandLine );
+
+    // check that there was no error raised
+    if(err != KErrNone)
+        {
+        return err;
+        }
+
+    TRequestStatus status = KRequestPending;
+    aProcess.Rendezvous(status);
+
+    if(KRequestPending != status.Int())
+        {
+        // startup failed so kill the process
+        RDebug::Printf( "> RProcess Rendezvous() failed with %d. Killing process", status.Int() );
+        aProcess.Kill(KErrNone);
+        return status.Int();
+        }
+    else
+        {
+        // start up succeeded so resume the process
+        aProcess.Resume();
+        User::WaitForRequest(status);
+        if(KErrNone != status.Int())
+            {
+            RDebug::Printf( "> RProcess Resume() failed with %d. Killing process", status.Int() );
+            aProcess.Kill(KErrNone);
+            }
+        return status.Int();
+        }
+    }
+
+/**
+ * Read command line parameters and control the launching of targets. 
+ * Create global launch semaphore KLaunchSemaphoreName
+ */
+void MainL()
+    {
+
+    TInt numApps = KNumApps;
+    TInt numLaunches = KNumLaunches;
+    TInt launchControl = 0;
+
+    TInt argc = User::CommandLineLength();
+    HBufC* commandLine = NULL;
+    RDebug::Printf( ">Launcher Process() argc=%d", argc );
+
+    if( argc )
+        {
+        commandLine = HBufC::NewLC(argc);
+        TPtr commandLineBuffer = commandLine->Des();
+        User::CommandLine(commandLineBuffer);
+
+        RBuf printCommandLine;
+        CleanupClosePushL( printCommandLine );
+        printCommandLine.CreateL( commandLine->Des().Length() );
+        printCommandLine.Copy( commandLine->Des() );
+        printCommandLine.Collapse();
+        RDebug::Printf( ">command line = %S", &printCommandLine );
+        CleanupStack::PopAndDestroy( &printCommandLine );
+
+        // create a lexer and read through the command line
+        TLex lex(*commandLine);
+        while (!lex.Eos())
+            {
+            // only look for options with first character '+', other switches are for the targets
+            if (lex.Get() == '+')
+                {
+                TChar arg = lex.Get();
+                switch (arg)
+                    {
+                    case 'n':
+                        lex.Val( numApps );
+                        RDebug::Printf("parsed numApps as %d", numApps);
+                        break;
+                    case 'm':
+                        lex.Val( numLaunches );
+                        RDebug::Printf("parsed numLaunches as %d", numLaunches );
+                        break;
+                    case 'o':
+                        lex.Val( launchControl );
+                        RDebug::Printf("parsed launchControl as %d", launchControl);
+                        break;
+                    default:
+                        // unknown argument ignore it
+                        break;             
+                    }//switch
+                }// if +
+            }//while
+        }//if argc
+
+   RSemaphore launchSemaphore;
+   TInt ret = KErrNone;
+   CleanupClosePushL( launchSemaphore );
+   ret = launchSemaphore.CreateGlobal( KLaunchSemaphoreName, 0 );
+   RDebug::Printf( ">Target Launcher : RSemaphore.CreateGlobal ret %d", ret);
+   User::LeaveIfError( ret );
+
+   ret = launchSemaphore.OpenGlobal( KLaunchSemaphoreName );
+   RDebug::Printf( ">Target Launcher : RSemaphore.OpenGlobal ret %d", ret);
+   User::LeaveIfError( ret );
+   
+   //Only now indicate to the launcher that we have fully started, so they can find and open the semaphore
+   RProcess::Rendezvous(KErrNone);
+
+   //Now launch the requested number of apps for the requested number of launches
+   for( ; numLaunches > 0; numLaunches-- )
+       { 
+       for( TInt launchIndex = numApps; launchIndex > 0; launchIndex-- )  
+           {
+           RDebug::Printf( ">Target Launcher:  Semaphore wait app %d, launch %d", launchIndex, numLaunches );
+           launchSemaphore.Wait();
+
+           RBuf targetName;
+           CleanupClosePushL( targetName );
+           RDebug::Printf( ">Target Launcher:  targetName.Create %d, launch %d", launchIndex, numLaunches );
+           targetName.Create( KTargetExe().Length() + 2 );
+
+           if( launchControl == 1 )
+               {
+               // Reverse the order of the apps launched by reversing the index in the name
+               RDebug::Printf( ">Target Launcher:  targetName.Format %d, launch %d", numApps - launchIndex + 1, numLaunches );
+               targetName.Format( KTargetExe(), numApps - launchIndex + 1 );
+               }
+           else
+               {
+               RDebug::Printf( ">Target Launcher:  targetName.Format %d, launch %d", launchIndex, numLaunches );
+               targetName.Format( KTargetExe(), launchIndex );
+               }
+
+           RProcess aProc;
+           CleanupClosePushL( aProc ); 
+    
+           RDebug::Printf( ">Target Launcher: LaunchProcess %d, launch %d", launchIndex, numLaunches );
+           RDebug::Printf( ">LaunchProcess %lS", &targetName );
+           TPtr cmdLinePtr( commandLine->Des() );
+           ret = LaunchProcess( aProc, targetName, cmdLinePtr );
+           CleanupStack::PopAndDestroy( &aProc );
+
+           RDebug::Printf( "<Target Launcher: LaunchProcess returned %d", ret );
+           CleanupStack::PopAndDestroy( &targetName );
+
+           User::LeaveIfError( ret );
+
+           //By now the add proc event should have been delivered to the
+           //test app agent.
+           }
+       }
+
+    launchSemaphore.Wait( 500000 );
+
+    CleanupStack::PopAndDestroy( &launchSemaphore );
+
+    if( commandLine )
+       CleanupStack::PopAndDestroy( commandLine );
+ 
+    }
+
+
+GLDEF_C TInt E32Main()
+	{
+	RProcess thisProcess;
+	thisProcess.Rendezvous(KErrNone);
+	RDebug::Printf( ">Launcher Process()" );
+
+	CTrapCleanup* trap = CTrapCleanup::New();
+	if (!trap)
+		return KErrNoMemory;
+
+	TRAPD(err, MainL());
+	RDebug::Printf( "< Target launching returned %d", err);
+	
+	delete trap;
+	
+	return err;
+	}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/debugsrv/runmodedebug/rmdebug_test/rm_debug/common/t_target_launcher.h	Fri Aug 27 11:37:29 2010 +0300
@@ -0,0 +1,48 @@
+// Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+// Definitions for target launcher
+// 
+//
+
+/**
+ @file
+ @internalTechnology
+ @released
+*/
+
+#ifndef RMDEBUG_TARGET_LAUNCHER_H
+#define RMDEBUG_TARGET_LAUNCHER_H
+
+// Controls how many times the target applications are launched
+const TInt KNumLaunches = 3;
+
+// Controls how many applications are attached and launched
+// If changing this, need to make sure there are enough apps
+// being built. see KTargetExe and t_rmdebug_app*
+const TInt KNumApps = 4;  
+
+_LIT(KLaunchSemaphoreName, "t_rmdebug_launch_semaphore");
+_LIT(KLaunchSemaphoreNameSearchString, "t_rmdebug_launch_semaphore*");
+_LIT(KTargetExe,"z:\\sys\\bin\\t_rmdebug_app%d.exe");
+_LIT8(KTargetExeName,"t_rmdebug_app%d.exe");
+_LIT(KProcessFinder,"*t_rmdebug_app%d*");
+_LIT(KTargetOptions,"-f%d");
+
+_LIT(KZSysBin,"z:\\sys\\bin\\");
+
+_LIT(KLauncherExe,"t_rmdebug_target_launcher.exe");
+
+_LIT_SECURITY_POLICY_PASS(KAllowAllPolicy);
+
+#endif // RMDEBUG_TARGET_LAUNCHER_H
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/debugsrv/runmodedebug/rmdebug_test/rm_debug/debug_targets/d_demand_paging.cia	Fri Aug 27 11:37:29 2010 +0300
@@ -0,0 +1,57 @@
+// Copyright (c) 2007-2010 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+// 
+//
+
+
+#include <u32std.h>
+
+// unused function that contains enough padding that the test function
+// RMDebugDemandPagingTest starts in a new page.
+__NAKED__ TInt RMDebugDemandPagingPaddingBefore()
+	{
+	asm("movs       r2,r0");
+	asm("adds       r0,r2,r1");
+	asm("bx         lr");
+	// add padding to make this function 4kb in size.
+	// The 4084 corresponds to 2^12 (=4096) - 12,
+	// the 12 being the total size of the movs, adds and bx instructions.
+	asm(".space     4084");
+	}
+
+// test function which is in a page by itself
+__NAKED__ TInt RMDebugDemandPagingTest()
+	{
+	asm("movs       r2,r0");
+	asm("adds       r0,r2,r1");
+	asm("bx         lr");
+	// add padding to make this function 4kb in size.
+	// The 4084 corresponds to 2^12 (=4096) - 12,
+	// the 12 being the total size of the movs, adds and bx instructions.
+	asm(".space     4084");
+	}
+
+// unused function that contains enough padding to ensure that no used code
+// is in the same page as RMDebugDemandPagingTest
+__NAKED__ TInt RMDebugDemandPagingPaddingAfter()
+	{
+	asm("movs       r2,r0");
+	asm("adds       r0,r2,r1");
+	asm("bx         lr");
+	// add padding to make this function 4kb in size.
+	// The 4084 corresponds to 2^12 (=4096) - 12,
+	// the 12 being the total size of the movs, adds and bx instructions.
+	asm(".space     4084");
+	}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/debugsrv/runmodedebug/rmdebug_test/rm_debug/debug_targets/d_demand_paging.h	Fri Aug 27 11:37:29 2010 +0300
@@ -0,0 +1,22 @@
+// Copyright (c) 2007-2010 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+// definitions of functions in d_demand_paging.cia
+//
+
+#ifndef D_DEMAND_PAGING_H
+#define D_DEMAND_PAGING_H
+
+TInt RMDebugDemandPagingTest();
+
+#endif // D_DEMAND_PAGING_H
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/debugsrv/runmodedebug/rmdebug_test/rm_debug/debug_targets/d_rmdebug_bkpt_test.h	Fri Aug 27 11:37:29 2010 +0300
@@ -0,0 +1,28 @@
+// Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+//
+
+// definitions of functions in d_rmdebug_bkpt_test.s
+
+#ifndef D_RMDEBUG_BKPT_TESTS_H
+#define D_RMDEBUG_BKPT_TESTS_H
+
+extern "C"
+{
+	// Breakpoints in loop test
+	unsigned int RMDebug_Bkpt_Test_Entry(void);
+	unsigned int RMDebug_Bkpt_Test_Loop_Break_1(void);
+	unsigned int RMDebug_Bkpt_Test_Loop_Break_2(void);
+}
+#endif // D_RMDEBUG_BKPT_TESTS_H
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/debugsrv/runmodedebug/rmdebug_test/rm_debug/debug_targets/d_rmdebug_bkpt_test.s	Fri Aug 27 11:37:29 2010 +0300
@@ -0,0 +1,52 @@
+; Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+; All rights reserved.
+; This component and the accompanying materials are made available
+; under the terms of the License "Eclipse Public License v1.0"
+; which accompanies this distribution, and is available
+; at the URL "http://www.eclipse.org/legal/epl-v10.html".
+;
+; Initial Contributors:
+; Nokia Corporation - initial contribution.
+;
+; Contributors:
+;
+; Description:
+;
+
+        AREA |d-rmdebug-bkpt$$Code|, CODE, READONLY, ALIGN=6
+
+	CODE32
+
+;
+; Breakpoints in loop test
+; 
+; This function initialises some variables and then performs some basic operations 
+; within the for loop. This allows us to set multiple breakpoints within the loop 
+; to test and see whether they are being hit. 
+;
+
+	EXPORT RMDebug_Bkpt_Test_Entry
+	EXPORT RMDebug_Bkpt_Test_Loop_Break_1
+	EXPORT RMDebug_Bkpt_Test_Loop_Break_2
+	
+RMDebug_Bkpt_Test_Entry
+    mov r2,#10
+    mov r0,#20    
+    mov r3,#0
+    mov r1,#1
+    b COMPARE
+LOOP      
+    add r3,r2,r0   
+RMDebug_Bkpt_Test_Loop_Break_1    
+    mov r2,r0
+RMDebug_Bkpt_Test_Loop_Break_2  
+    mov r0,r3 
+    add r1,r1,#1
+COMPARE
+    cmp r1,#30
+    ble LOOP 
+    bx lr
+ 
+	END
+
+; End of file - d_rmdebug_bkpt_test.s
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/debugsrv/runmodedebug/rmdebug_test/rm_debug/debug_targets/d_rmdebug_step_test.h	Fri Aug 27 11:37:29 2010 +0300
@@ -0,0 +1,81 @@
+// Copyright (c) 2007-2010 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+// 
+// definitions of functions in d_rmdebug_step_tests.s
+//
+
+#ifndef D_RMDEBUG_STEP_TESTS_H
+#define D_RMDEBUG_STEP_TESTS_H
+
+extern "C"
+{
+	// ARM tests
+	unsigned int RMDebug_StepTest_Non_PC_Modifying(void);
+	unsigned int RMDebug_StepTest_Non_PC_Modifying_OK(void);
+	
+	unsigned int RMDebug_StepTest_Branch(void);
+	unsigned int RMDebug_StepTest_Branch_1(void);
+
+	unsigned int RMDebug_StepTest_Branch_And_Link(void);
+	unsigned int RMDebug_StepTest_Branch_And_Link_1(void);
+	unsigned int RMDebug_StepTest_Branch_And_Link_2(void);
+	
+	unsigned int RMDebug_StepTest_MOV_PC(void);
+	unsigned int RMDebug_StepTest_MOV_PC_1(void);
+	unsigned int RMDebug_StepTest_MOV_PC_2(void);
+	
+	unsigned int RMDebug_StepTest_LDR_PC(void);
+	unsigned int RMDebug_StepTest_LDR_PC_1(void);
+
+	// Thumb tests
+	unsigned int RMDebug_StepTest_Thumb_Non_PC_Modifying(void);
+	unsigned int RMDebug_StepTest_Thumb_Non_PC_Modifying_1(void);
+	unsigned int RMDebug_StepTest_Thumb_Non_PC_Modifying_2(void);
+
+	unsigned int RMDebug_StepTest_Thumb_Branch(void);
+	unsigned int RMDebug_StepTest_Thumb_Branch_1(void);
+	unsigned int RMDebug_StepTest_Thumb_Branch_2(void);
+	
+	unsigned int RMDebug_StepTest_Thumb_Branch_And_Link(void);
+	unsigned int RMDebug_StepTest_Thumb_Branch_And_Link_1(void);
+	unsigned int RMDebug_StepTest_Thumb_Branch_And_Link_2(void);
+	unsigned int RMDebug_StepTest_Thumb_Branch_And_Link_3(void);
+
+	unsigned int RMDebug_StepTest_Thumb_Back_Branch_And_Link(void);
+	unsigned int RMDebug_StepTest_Thumb_Back_Branch_And_Link_1(void);
+	unsigned int RMDebug_StepTest_Thumb_Back_Branch_And_Link_2(void);
+	unsigned int RMDebug_StepTest_Thumb_Back_Branch_And_Link_3(void);
+
+	unsigned int RMDebug_StepTest_Thumb_AddPC(void);
+	unsigned int RMDebug_StepTest_Thumb_AddPC_1(void);
+	unsigned int RMDebug_StepTest_Thumb_AddPC_2(void);
+	unsigned int RMDebug_StepTest_Thumb_AddPC_3(void);
+
+	// ARM<->Thumb interworking tests
+	unsigned int RMDebug_StepTest_Interwork(void);
+	unsigned int RMDebug_StepTest_Interwork_1(void);
+	unsigned int RMDebug_StepTest_Interwork_2(void);
+	unsigned int RMDebug_StepTest_Interwork_3(void);
+
+	// Stepping performance test
+	unsigned int RMDebug_StepTest_Count(void);
+	unsigned int RMDebug_StepTest_Count_1(void);
+	unsigned int RMDebug_StepTest_Count_2(void);
+
+	// Multiple step test
+	unsigned int RMDebug_StepTest_ARM_Step_Multiple(void);
+	unsigned int RMDebug_StepTest_ARM_Step_Multiple_1(void);
+
+}
+#endif // D_RMDEBUG_STEP_TESTS_H
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/debugsrv/runmodedebug/rmdebug_test/rm_debug/debug_targets/d_rmdebug_step_test.s	Fri Aug 27 11:37:29 2010 +0300
@@ -0,0 +1,268 @@
+; Copyright (c) 2007-2010 Nokia Corporation and/or its subsidiary(-ies).
+; All rights reserved.
+; This component and the accompanying materials are made available
+; under the terms of the License "Eclipse Public License v1.0"
+; which accompanies this distribution, and is available
+; at the URL "http://www.eclipse.org/legal/epl-v10.html".
+;
+; Initial Contributors:
+; Nokia Corporation - initial contribution.
+;
+; Contributors:
+;
+; Description:
+; 
+;
+
+        
+		AREA |d-rmdebug-step$$Code|, CODE, READONLY, ALIGN=6
+
+	CODE32
+
+	; ARM tests
+	
+; 
+; Non-PC modifying
+;
+	EXPORT RMDebug_StepTest_Non_PC_Modifying
+	EXPORT RMDebug_StepTest_Non_PC_Modifying_OK
+ 
+RMDebug_StepTest_Non_PC_Modifying
+	mov		r0,r0		; nop
+RMDebug_StepTest_Non_PC_Modifying_OK
+	bx		lr			; should return to normal execution of the test thread
+
+;
+; Branch
+;
+	EXPORT RMDebug_StepTest_Branch
+	EXPORT RMDebug_StepTest_Branch_1
+
+RMDebug_StepTest_Branch
+	b		RMDebug_StepTest_Branch_1		
+	mov		r0, #2		; if the pc ends up here, we know its gone wrong
+RMDebug_StepTest_Branch_1
+	bx		lr			; return
+
+;
+; Branch and Link
+;
+	EXPORT RMDebug_StepTest_Branch_And_Link
+	EXPORT RMDebug_StepTest_Branch_And_Link_1
+	EXPORT RMDebug_StepTest_Branch_And_Link_2
+
+RMDebug_StepTest_Branch_And_Link		
+	mov		r0, lr		; preserve lr for the moment
+RMDebug_StepTest_Branch_And_Link_1
+	bl		RMDebug_StepTest_Branch_And_Link_2
+	mov		r1, #1		; insert a gap in the instruction stream so we know we branched.
+RMDebug_StepTest_Branch_And_Link_2
+	mov		lr, r0		; restore lr			
+	bx		lr			; should return to normal execution of the test thread
+
+;
+; MOV PC
+;
+	EXPORT RMDebug_StepTest_MOV_PC
+	EXPORT RMDebug_StepTest_MOV_PC_1
+	EXPORT RMDebug_StepTest_MOV_PC_2
+
+RMDebug_StepTest_MOV_PC
+	mov		r0, #4
+RMDebug_StepTest_MOV_PC_1
+	add		pc, pc, r0	; should be a jump (bear in mind reading pc = current inst + 8bytes for arm)
+	mov		r0, #1		; Simple instructions which allow us to test where the PC really is
+	mov		r0, #2		; just by reading r0.
+RMDebug_StepTest_MOV_PC_2
+	mov		r0, #3		; 
+	mov		r0, #4		; 
+	bx		lr			; should return to normal execution of the test thread
+
+; 
+; LDR PC
+;
+	EXPORT RMDebug_StepTest_LDR_PC
+	EXPORT RMDebug_StepTest_LDR_PC_1
+
+RMDebug_StepTest_LDR_PC
+	ldr		pc, =RMDebug_StepTest_LDR_PC_1
+	mov		r0, #1		;  separate the branch target so we can prove it works
+RMDebug_StepTest_LDR_PC_1
+	bx		lr			; should return to normal execution of the test thread
+	
+;
+; ARM -> Thumb -> ARM interworking test
+;
+; Note: We always start and finish this test
+; in ARM mode.
+	EXPORT RMDebug_StepTest_Interwork
+	EXPORT RMDebug_StepTest_Interwork_1
+	EXPORT RMDebug_StepTest_Interwork_2
+	EXPORT RMDebug_StepTest_Interwork_3	
+RMDebug_StepTest_Interwork
+	mov		r0, lr	; preserve lr
+RMDebug_StepTest_Interwork_1
+	blx		RMDebug_StepTest_Interwork_2
+
+	CODE16
+RMDebug_StepTest_Interwork_2
+	blx		RMDebug_StepTest_Interwork_3
+
+	CODE32
+
+RMDebug_StepTest_Interwork_3
+	bx		r0
+
+;
+; Stepping performance tests
+;
+; This counts down from 100000 to 0
+; This means that for all practical purposes
+; we can single-step as much as we like
+; in less than one second and have some likelyhood
+; that we will not step too far from our loop
+
+	EXPORT RMDebug_StepTest_Count
+	EXPORT RMDebug_StepTest_Count_1
+	EXPORT RMDebug_StepTest_Count_2
+
+RMDebug_StepTest_Count
+	ldr		r2, =100000
+RMDebug_StepTest_Count_1
+	subs	r2, r2, #1
+RMDebug_StepTest_Count_2
+	bne		RMDebug_StepTest_Count_1
+	bx		lr
+
+; Thumb tests
+
+; Thumb non-pc modifying
+;
+;
+RMDebug_StepTest_Thumb_Non_PC_Modifying
+	mov		r0, lr	; preserve lr
+	blx		RMDebug_StepTest_Thumb_Non_PC_Modifying_1
+	bx		r0
+
+;
+; Thumb Branch
+;
+RMDebug_StepTest_Thumb_Branch
+	mov		r0, lr	; preserve lr
+	blx		RMDebug_StepTest_Thumb_Branch_1
+	bx		r0		
+
+;
+; Thumb Branch and link
+;
+RMDebug_StepTest_Thumb_Branch_And_Link
+	mov		r0, lr	; preserve lr
+	blx		RMDebug_StepTest_Thumb_Branch_And_Link_1
+	bx		r0 
+
+;
+; Thumb Back Branch and link
+;
+RMDebug_StepTest_Thumb_Back_Branch_And_Link
+	mov		r0, lr	; preserve lr
+	blx		RMDebug_StepTest_Thumb_Back_Branch_And_Link_1
+	bx		r0 
+
+;
+; Thumb ADD PC,PC, #0
+;
+RMDebug_StepTest_Thumb_AddPC
+	mov		r0, lr	; preserve lr
+	blx		RMDebug_StepTest_Thumb_AddPC_1
+	bx		r0 
+
+	CODE16
+
+	; Thumb tests
+	EXPORT RMDebug_StepTest_Thumb_Non_PC_Modifying
+	EXPORT RMDebug_StepTest_Thumb_Non_PC_Modifying_1
+	EXPORT RMDebug_StepTest_Thumb_Non_PC_Modifying_2
+
+	EXPORT RMDebug_StepTest_Thumb_Branch
+	EXPORT RMDebug_StepTest_Thumb_Branch_1
+	EXPORT RMDebug_StepTest_Thumb_Branch_2
+
+	EXPORT RMDebug_StepTest_Thumb_Branch_And_Link
+	EXPORT RMDebug_StepTest_Thumb_Branch_And_Link_1
+	EXPORT RMDebug_StepTest_Thumb_Branch_And_Link_2
+	EXPORT RMDebug_StepTest_Thumb_Branch_And_Link_3
+
+	EXPORT RMDebug_StepTest_Thumb_Back_Branch_And_Link
+	EXPORT RMDebug_StepTest_Thumb_Back_Branch_And_Link_1
+	EXPORT RMDebug_StepTest_Thumb_Back_Branch_And_Link_2
+	EXPORT RMDebug_StepTest_Thumb_Back_Branch_And_Link_3
+
+RMDebug_StepTest_Thumb_Non_PC_Modifying_1
+	mov		r0, r0	; nop
+RMDebug_StepTest_Thumb_Non_PC_Modifying_2
+	bx		lr	
+
+RMDebug_StepTest_Thumb_Branch_1
+	b		RMDebug_StepTest_Thumb_Branch_2
+	mov		r0, r0
+RMDebug_StepTest_Thumb_Branch_2
+	bx		lr
+
+RMDebug_StepTest_Thumb_Branch_And_Link_1
+	mov		r1, lr
+RMDebug_StepTest_Thumb_Branch_And_Link_2
+	bl		RMDebug_StepTest_Thumb_Branch_And_Link_3
+	mov		r0, r0
+RMDebug_StepTest_Thumb_Branch_And_Link_3
+	bx		r1
+
+RMDebug_StepTest_Thumb_Back_Branch_And_Link_3
+	bx		r1
+
+RMDebug_StepTest_Thumb_Back_Branch_And_Link_1
+	mov		r1, lr
+RMDebug_StepTest_Thumb_Back_Branch_And_Link_2
+	bl		RMDebug_StepTest_Thumb_Back_Branch_And_Link_3
+	bx		r1
+
+;
+; ADD PC
+;
+	EXPORT RMDebug_StepTest_Thumb_AddPC
+	EXPORT RMDebug_StepTest_Thumb_AddPC_1
+	EXPORT RMDebug_StepTest_Thumb_AddPC_2
+	EXPORT RMDebug_StepTest_Thumb_AddPC_3
+
+RMDebug_StepTest_Thumb_AddPC_1
+	mov		r1, lr
+	mov		r2, #4
+RMDebug_StepTest_Thumb_AddPC_2
+	add		pc, pc, r2	; should arrive at RMDebug_StepTest_Thumb_AddPC_3
+	mov		r0, r0
+	mov		r0, r0
+	mov		r0, r0
+RMDebug_StepTest_Thumb_AddPC_3
+	bx		r1
+
+	ALIGN 4
+
+	CODE32
+
+;
+; ARM multiple-step ( 5 steps )
+;
+	EXPORT RMDebug_StepTest_ARM_Step_Multiple
+	EXPORT RMDebug_StepTest_ARM_Step_Multiple_1
+
+RMDebug_StepTest_ARM_Step_Multiple
+	mov		r0,r0		; nop
+	mov		r0,r0		; nop
+	mov		r0,r0		; nop
+	mov		r0,r0		; nop
+	mov		r0,r0		; nop
+RMDebug_StepTest_ARM_Step_Multiple_1
+	bx		lr
+
+	END
+
+; End of file - d_rmdebug_step_test.s
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/debugsrv/runmodedebug/rmdebug_test/rm_debug/debug_targets/d_rmdebug_step_test_armv4.h	Fri Aug 27 11:37:29 2010 +0300
@@ -0,0 +1,50 @@
+// Copyright (c) 2007-2010 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+// definitions of functions in d_rmdebug_step_tests_armv4.s
+//
+
+#ifndef D_RMDEBUG_STEP_TESTS_H
+#define D_RMDEBUG_STEP_TESTS_H
+
+extern "C"
+{
+	// ARM tests
+	unsigned int RMDebug_StepTest_Non_PC_Modifying(void);
+	unsigned int RMDebug_StepTest_Non_PC_Modifying_OK(void);
+	
+	unsigned int RMDebug_StepTest_Branch(void);
+	unsigned int RMDebug_StepTest_Branch_1(void);
+
+	unsigned int RMDebug_StepTest_Branch_And_Link(void);
+	unsigned int RMDebug_StepTest_Branch_And_Link_1(void);
+	unsigned int RMDebug_StepTest_Branch_And_Link_2(void);
+	
+	unsigned int RMDebug_StepTest_MOV_PC(void);
+	unsigned int RMDebug_StepTest_MOV_PC_1(void);
+	unsigned int RMDebug_StepTest_MOV_PC_2(void);
+	
+	unsigned int RMDebug_StepTest_LDR_PC(void);
+	unsigned int RMDebug_StepTest_LDR_PC_1(void);
+
+	// Stepping performance test
+	unsigned int RMDebug_StepTest_Count(void);
+	unsigned int RMDebug_StepTest_Count_1(void);
+	unsigned int RMDebug_StepTest_Count_2(void);
+
+	// Multiple step test
+	unsigned int RMDebug_StepTest_ARM_Step_Multiple(void);
+	unsigned int RMDebug_StepTest_ARM_Step_Multiple_1(void);
+
+}
+#endif // D_RMDEBUG_STEP_TESTS_H
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/debugsrv/runmodedebug/rmdebug_test/rm_debug/debug_targets/d_rmdebug_step_test_armv4.s	Fri Aug 27 11:37:29 2010 +0300
@@ -0,0 +1,130 @@
+; Copyright (c) 2007-2010 Nokia Corporation and/or its subsidiary(-ies).
+; All rights reserved.
+; This component and the accompanying materials are made available
+; under the terms of the License "Eclipse Public License v1.0"
+; which accompanies this distribution, and is available
+; at the URL "http://www.eclipse.org/legal/epl-v10.html".
+;
+; Initial Contributors:
+; Nokia Corporation - initial contribution.
+;
+; Contributors:
+;
+; Description:
+; 
+;
+
+        AREA |d-rmdebug-bkpt$$Code|, CODE, READONLY, ALIGN=6
+
+	CODE32
+
+	; ARM tests
+	
+; 
+; Non-PC modifying
+;
+	EXPORT RMDebug_StepTest_Non_PC_Modifying
+	EXPORT RMDebug_StepTest_Non_PC_Modifying_OK
+ 
+RMDebug_StepTest_Non_PC_Modifying
+	mov		r0,r0		; nop
+RMDebug_StepTest_Non_PC_Modifying_OK
+	bx		lr			; should return to normal execution of the test thread
+
+;
+; Branch
+;
+	EXPORT RMDebug_StepTest_Branch
+	EXPORT RMDebug_StepTest_Branch_1
+
+RMDebug_StepTest_Branch
+	b		RMDebug_StepTest_Branch_1		
+	mov		r0, #2		; if the pc ends up here, we know its gone wrong
+RMDebug_StepTest_Branch_1
+	bx		lr			; return
+
+;
+; Branch and Link
+;
+	EXPORT RMDebug_StepTest_Branch_And_Link
+	EXPORT RMDebug_StepTest_Branch_And_Link_1
+	EXPORT RMDebug_StepTest_Branch_And_Link_2
+
+RMDebug_StepTest_Branch_And_Link		
+	mov		r0, lr		; preserve lr for the moment
+RMDebug_StepTest_Branch_And_Link_1
+	bl		RMDebug_StepTest_Branch_And_Link_2
+	mov		r1, #1		; insert a gap in the instruction stream so we know we branched.
+RMDebug_StepTest_Branch_And_Link_2
+	mov		lr, r0		; restore lr			
+	bx		lr			; should return to normal execution of the test thread
+
+;
+; MOV PC
+;
+	EXPORT RMDebug_StepTest_MOV_PC
+	EXPORT RMDebug_StepTest_MOV_PC_1
+	EXPORT RMDebug_StepTest_MOV_PC_2
+
+RMDebug_StepTest_MOV_PC
+	mov		r0, #4
+RMDebug_StepTest_MOV_PC_1
+	add		pc, pc, r0	; should be a jump (bear in mind reading pc = current inst + 8bytes for arm)
+	mov		r0, #1		; Simple instructions which allow us to test where the PC really is
+	mov		r0, #2		; just by reading r0.
+RMDebug_StepTest_MOV_PC_2
+	mov		r0, #3		; 
+	mov		r0, #4		; 
+	bx		lr			; should return to normal execution of the test thread
+
+; 
+; LDR PC
+;
+	EXPORT RMDebug_StepTest_LDR_PC
+	EXPORT RMDebug_StepTest_LDR_PC_1
+
+RMDebug_StepTest_LDR_PC
+	ldr		pc, =RMDebug_StepTest_LDR_PC_1
+	mov		r0, #1		;  separate the branch target so we can prove it works
+RMDebug_StepTest_LDR_PC_1
+	bx		lr			; should return to normal execution of the test thread
+	
+;
+; Stepping performance tests
+;
+; This counts down from 100000 to 0
+; This means that for all practical purposes
+; we can single-step as much as we like
+; in less than one second and have some likelyhood
+; that we will not step too far from our loop
+
+	EXPORT RMDebug_StepTest_Count
+	EXPORT RMDebug_StepTest_Count_1
+	EXPORT RMDebug_StepTest_Count_2
+
+RMDebug_StepTest_Count
+	ldr		r2, =100000
+RMDebug_StepTest_Count_1
+	subs	r2, r2, #1
+RMDebug_StepTest_Count_2
+	bne		RMDebug_StepTest_Count_1
+	bx		lr
+
+;
+; ARM multiple-step ( 5 steps )
+;
+	EXPORT RMDebug_StepTest_ARM_Step_Multiple
+	EXPORT RMDebug_StepTest_ARM_Step_Multiple_1
+
+RMDebug_StepTest_ARM_Step_Multiple
+	mov		r0,r0		; nop
+	mov		r0,r0		; nop
+	mov		r0,r0		; nop
+	mov		r0,r0		; nop
+	mov		r0,r0		; nop
+RMDebug_StepTest_ARM_Step_Multiple_1
+	bx		lr
+
+	END
+
+; End of file - d_rmdebug_step_test_armv4.s
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/debugsrv/runmodedebug/rmdebug_test/rm_debug/debug_targets/d_rmdebugthread.cpp	Fri Aug 27 11:37:29 2010 +0300
@@ -0,0 +1,106 @@
+// Copyright (c) 2006-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+// Implements a debug thread for testing.
+// 
+//
+
+#include <e32base.h>
+#include <e32base_private.h>
+#include <e32cons.h>
+#include "d_rmdebugthread.h"
+
+EXPORT_C TBuf8<SYMBIAN_RMDBG_MEMORYSIZE> gMemoryAccessBytes;
+extern void RMDebug_BranchTst1();
+
+EXPORT_C TInt TestData;
+
+CDebugServThread::CDebugServThread()
+//
+// Empty constructor
+//
+	{
+	}
+
+GLDEF_C TInt CDebugServThread::ThreadFunction(TAny*)
+//
+// Generic thread function for testing
+//
+	{
+	CTrapCleanup* cleanup=CTrapCleanup::New();
+	if (cleanup == NULL)
+		{
+		User::Leave(KErrNoMemory);
+		}
+
+	RThread::Rendezvous(KErrNone);
+
+	TestData = 1;
+
+	while(1)
+		{
+		RMDebug_BranchTst1();
+
+		TestData++;                   
+
+		// Wait half a second (suspends this thread)
+		User::After(500000);
+
+		if (TestData == 0xFFFFFFFF)
+			{
+			break;
+			}
+		}
+
+	delete cleanup;
+
+	return (KErrNone);
+	}
+
+EXPORT_C TInt StartDebugThread(RThread& aDebugThread)
+//
+// Starts the test thread
+//
+{
+	TInt res=KErrNone;
+
+	// Create the thread
+	res = aDebugThread.Create(	KDebugThreadName,
+								CDebugServThread::ThreadFunction,
+								KDefaultStackSize,
+								KDebugThreadDefaultHeapSize,
+								KDebugThreadDefaultHeapSize,
+								NULL
+								);
+
+	// Check that the creation worked
+	if (res == KErrNone)
+		{
+		TRequestStatus rendezvousStatus;
+
+		aDebugThread.SetPriority(EPriorityNormal);
+		// Make a request for a rendezvous
+		aDebugThread.Rendezvous(rendezvousStatus);
+		// Set the thread as ready for execution
+		aDebugThread.Resume();
+		// Wait for the resumption
+		User::WaitForRequest(rendezvousStatus);
+		}                                 
+	else
+		{
+		// Close the handle.
+		aDebugThread.Close();
+		}
+
+	return res;
+	}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/debugsrv/runmodedebug/rmdebug_test/rm_debug/debug_targets/d_rmdebugthread.h	Fri Aug 27 11:37:29 2010 +0300
@@ -0,0 +1,38 @@
+// Copyright (c) 2006-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+// t_rmdebugthread.h
+// Definitions for the run mode debug test thread.
+// 
+//
+
+#ifndef RMDEBUGSVRTHRD_H
+#define RMDEBUGSVRTHRD_H
+
+#define SYMBIAN_RMDBG_MEMORYSIZE    1024*4
+
+// Thread name
+_LIT(KDebugThreadName,"DebugThread");
+
+const TUint KDebugThreadDefaultHeapSize=0x10000;
+
+class CDebugServThread : public CBase
+	{
+	public:
+		CDebugServThread();
+		static TInt ThreadFunction(TAny* aStarted);    
+
+	public:
+	};
+
+#endif // RMDEBUGSVRTHRD_H
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/debugsrv/runmodedebug/rmdebug_test/rm_debug/debug_targets/d_rmdebugthread2.cpp	Fri Aug 27 11:37:29 2010 +0300
@@ -0,0 +1,318 @@
+// Copyright (c) 2006-2010 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+// Implements a debug thread for testing.
+// 
+//
+
+#include <e32base.h>
+#include <e32base_private.h>
+#include <e32cons.h>
+#include <e32debug.h>
+#include "d_rmdebugthread2.h"
+
+#include "d_rmdebug_step_test.h"
+#include "d_rmdebug_bkpt_test.h"
+#include "d_demand_paging.h"
+
+TBuf8<SYMBIAN_RMDBG_MEMORYSIZE> gMemoryAccessBytes;
+IMPORT_C extern void RMDebug_BranchTst1();
+IMPORT_C extern TInt RMDebugDemandPagingTest();
+
+TInt TestData;
+TTestFunction FunctionChooser;
+
+const TInt 	KNumberOfTraceCalls = 50;
+
+EXPORT_C TInt TestFunction()
+	{
+	// Set TestData to an arbitrary value that can be checked by a tester
+	TestData = 0xffeeddcc;
+	RMDebug_BranchTst1();
+	
+	// Code here may not be executed because tests can change the PC value
+	// at any time, typically once the test passes
+	return 0;
+	}
+
+/**
+  Wrapper around RMDebugDemandPagingTest, need to pause for a short time to
+  allow time in t_rmdebug.cpp to issue a User::WaitForRequest to catch the break point
+  */
+EXPORT_C void TestPagedCode()
+	{
+	User::After(100000);
+
+	// call the function in paged code
+	RMDebugDemandPagingTest();
+	}
+
+EXPORT_C void TestMultipleTraceCalls()
+	{
+	//arbitrary function to set a BP on
+	RMDebug_BranchTst1();
+
+	// The tester will change FunctionChooser once it gets what it needs out of the test
+	for(TInt cnt = KNumberOfTraceCalls; cnt>0 && (FunctionChooser==EMultipleTraceCalls); cnt--)
+		{
+		RDebug::Printf("T");
+		RDebug::Printf("R");
+		RDebug::Printf("A");
+		RDebug::Printf("C");
+		RDebug::Printf("E");
+		}
+	
+	//another arbitrary function to set a BP on
+	RMDebug_StepTest_Non_PC_Modifying();
+	}
+
+CDebugServThread::~CDebugServThread()
+    {
+    }
+
+CDebugServThread::CDebugServThread()
+//
+// Empty constructor
+//
+	{
+	}
+
+
+/**
+ * Check that the RProperty argument does not change within the given amount of time.
+ * If the property does change, the error KErrInUse is returned.
+ * 
+ */
+EXPORT_C TInt TestRunCountSame( RProperty & aProperty, RTimer & aTimer, TTimeIntervalMicroSeconds32 aTimeOut )
+    {
+    TRequestStatus propertyStatus;
+    TRequestStatus timerStatus;
+    TInt propertyValueBefore = 0;
+    TInt propertyValueAfter = 0;
+
+    aProperty.Subscribe( propertyStatus );
+    aProperty.Get( propertyValueBefore );
+    aTimer.After( timerStatus, aTimeOut );
+
+    User::WaitForRequest( propertyStatus, timerStatus );
+    if (propertyStatus != KRequestPending)
+        {
+        RDebug::Printf(" CDebugServThread::TestRunCountSame: Property has been set. Returning KErrInUse");
+        aTimer.Cancel();
+        // Wait for the KErrCancel
+        User::WaitForRequest( timerStatus );
+        return KErrInUse;
+        }
+
+    aProperty.Cancel();
+    //This will wait for the KErrCancel to be issued by the property.
+    User::WaitForRequest( propertyStatus );
+    
+    aProperty.Get( propertyValueAfter );
+    if( propertyValueAfter != propertyValueBefore )
+        {
+        RDebug::Printf(" CDebugServThread::TestRunCountSame: Change in property value. Returning KErrInUse");
+        return KErrInUse;
+        }
+        
+    return KErrNone;
+    }
+
+
+/**
+ * Check that the RProperty argument changes within the given amount of time.
+ * If the property does not change, the error KErrTimedOut is returned.
+ * If the values before and after are the same, the error KErrNotReady is returned
+ */
+EXPORT_C TInt WaitForRunCountChange( RProperty & aProperty, RTimer & aTimer, TTimeIntervalMicroSeconds32 aTimeOut )
+    {
+    TRequestStatus propertyStatus;
+    TRequestStatus timerStatus;
+    TInt propertyValueBefore = 0;
+    TInt propertyValueAfter = 0;
+    
+    aProperty.Get( propertyValueBefore );
+    aProperty.Subscribe( propertyStatus );
+
+    aTimer.After( timerStatus, aTimeOut );
+
+    User::WaitForRequest( propertyStatus, timerStatus );
+    if (timerStatus != KRequestPending)
+        {
+        RDebug::Printf(" CDebugServThread::WaitForRunCountChange: timeout. Returning KErrTimedOut");
+        aProperty.Cancel();
+        // Wait for the KErrCancel
+        User::WaitForRequest( propertyStatus );
+        return KErrTimedOut;
+        }
+    
+    aTimer.Cancel();
+    //This will wait for the KErrCancel to be issued by the timer.
+    User::WaitForRequest( timerStatus );
+    
+    aProperty.Get( propertyValueAfter );
+    if( propertyValueAfter == propertyValueBefore )
+        {
+        RDebug::Printf(" CDebugServThread::WaitForRunCountChange: No change in property value. Returning KErrNotReady");
+        return KErrNotReady;
+        }
+        
+    return KErrNone;
+    }
+
+GLDEF_C TInt CDebugServThread::ThreadFunction(TAny*)
+//
+// Generic thread function for testing
+//
+	{
+	// set FunctionChooser to run the default function
+	FunctionChooser = EDefaultFunction;
+
+	CTrapCleanup* cleanup=CTrapCleanup::New();
+	if (cleanup == NULL)
+		{
+		User::Leave(KErrNoMemory);
+		}
+    
+	TInt err = RProperty::Define( RProcess().SecureId(), ERMDBGRunCountProperty, RProperty::EInt );
+    if( (err != KErrAlreadyExists) && (err != KErrNone) )
+        {
+        RDebug::Printf("CDebugServThread::ThreadFunction - unable to create 'ERunCount' property. err:%d", err);
+        }
+    
+	RThread::Rendezvous(KErrNone);
+
+	TestData = 1;
+
+	/* Beware of adding printf or other debug-generating events in this loop because
+	* they interfere with the tests
+	*/
+	while(TestData != 0xFFFFFFFF)
+		{
+        //iRunCountPublish.Set( TestData );
+        RProperty::Set( RProcess().SecureId(), ERMDBGRunCountProperty, TestData );
+        
+		switch(FunctionChooser)
+			{
+			case EDemandPagingFunction:
+				TestPagedCode();
+				break;
+			case EDefaultFunction:
+				// the default function is the stepping test functions
+			case EStepFunction:
+				{
+				RMDebug_BranchTst1();
+
+				// Single stepping test support code
+
+				// ARM tests
+				RMDebug_StepTest_Non_PC_Modifying();
+
+				RMDebug_StepTest_Branch();
+
+				RMDebug_StepTest_Branch_And_Link();
+
+				RMDebug_StepTest_MOV_PC();
+
+				RMDebug_StepTest_LDR_PC();
+ 
+// thumb/interworking tests not supported on armv4
+#ifdef __MARM_ARMV5__
+
+				// Thumb tests
+				RMDebug_StepTest_Thumb_Non_PC_Modifying();
+
+				RMDebug_StepTest_Thumb_Branch();
+
+				RMDebug_StepTest_Thumb_Branch_And_Link();
+
+				RMDebug_StepTest_Thumb_Back_Branch_And_Link();
+
+				// ARM <-> Thumb interworking tests
+				RMDebug_StepTest_Interwork();
+
+				RMDebug_StepTest_Thumb_AddPC();
+
+#endif	// __MARM_ARMV5__
+				
+				// Single-stepping performance
+				RMDebug_StepTest_Count();
+
+				// multiple step test
+				RMDebug_StepTest_ARM_Step_Multiple();
+
+				// Breakpoints in loop test
+				RMDebug_Bkpt_Test_Entry();
+
+				TestData++;
+				
+				RDebug::Printf("** TestData=%d", TestData) ;
+
+				// Wait 50mSecs. // (suspends this thread)
+				User::After(50000);
+
+				break;
+				}
+			case EMultipleTraceCalls:
+				TestMultipleTraceCalls();
+				break;
+			default:
+				//do nothing
+				break;
+			}
+		}
+
+	RProperty::Delete( RProcess().SecureId(), ERMDBGRunCountProperty );
+	        
+	delete cleanup;
+
+	return (KErrNone);
+	}
+
+EXPORT_C TInt StartDebugThread(RThread& aDebugThread, const TDesC& aDebugThreadName)
+//
+// Starts a test thread
+//
+{
+	TInt res=KErrNone;
+
+	// Create the thread
+	res = aDebugThread.Create(	aDebugThreadName,
+								CDebugServThread::ThreadFunction,
+								KDefaultStackSize,
+								KDebugThreadDefaultHeapSize,
+								KDebugThreadDefaultHeapSize,
+								NULL
+								);
+
+	// Check that the creation worked
+	if (res == KErrNone)
+		{
+		TRequestStatus rendezvousStatus;
+
+		aDebugThread.SetPriority(EPriorityNormal);
+		// Make a request for a rendezvous
+		aDebugThread.Rendezvous(rendezvousStatus);
+		// Set the thread as ready for execution
+		aDebugThread.Resume();
+		// Wait for the resumption
+		User::WaitForRequest(rendezvousStatus);
+		}                                 
+	else
+		{
+		// Close the handle.
+		aDebugThread.Close();
+		}
+	        
+	return res;
+	}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/debugsrv/runmodedebug/rmdebug_test/rm_debug/debug_targets/d_rmdebugthread2.h	Fri Aug 27 11:37:29 2010 +0300
@@ -0,0 +1,71 @@
+// Copyright (c) 2006-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+// Definitions for the run mode debug test thread.
+// 
+//
+
+#ifndef RMDEBUGSVRTHRD_H
+#define RMDEBUGSVRTHRD_H
+
+#include <e32property.h>
+
+#define SYMBIAN_RMDBG_MEMORYSIZE    1024*4
+
+// Thread name
+_LIT(KDebugThreadName,"DebugThread");
+
+
+IMPORT_C TInt TestRunCountSame( 
+            RProperty & aProperty, 
+            RTimer & aTimer, 
+            TTimeIntervalMicroSeconds32 aTimeOut = 500000 );
+
+
+IMPORT_C TInt WaitForRunCountChange( 
+            RProperty & aProperty, 
+            RTimer & aTimer, 
+            TTimeIntervalMicroSeconds32 aTimeOut = 500000 );
+
+const TUint KDebugThreadDefaultHeapSize=0x10000;
+
+// enumeration of functions which the target debug thread can call, the
+// debugger can choose to switch the thread to a different function by
+// writing the appropriate enumeration value into FunctionChooser, the
+// target thread will finish executing the function it is currently running
+// then execute the chosen function.
+enum TTestFunction
+	{
+	EDefaultFunction = 0,
+	EStepFunction = 1,
+	EDemandPagingFunction = 2,
+	EMultipleTraceCalls = 3,
+	EDoNothing = 4
+	};
+
+class CDebugServThread : public CBase
+	{
+	public:
+		CDebugServThread();
+		~CDebugServThread();
+		static TInt ThreadFunction(TAny* aStarted);    
+		
+
+	//Enums for all the properties used by this class
+	enum TRMDebugProperties 
+            { 
+            ERMDBGRunCountProperty = 3
+            };
+	};
+
+#endif // RMDEBUGSVRTHRD_H
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/debugsrv/runmodedebug/rmdebug_test/rm_debug/debug_targets/d_rmdebugthreadasm.cia	Fri Aug 27 11:37:29 2010 +0300
@@ -0,0 +1,32 @@
+// Copyright (c) 2006-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+// d_rmdebugthreadasm.h
+// Assembler file for debug thread testing.
+// 
+//
+
+//#include <e32cia.h>
+//#include <e32base.h>
+//#include <e32cons.h>
+//#include "d_rmdebugthread.h"
+
+EXPORT_C __NAKED__ void RMDebug_BranchTst1( void )
+//
+// 
+//
+{
+	asm("mov r0, #0 ");			// aResult==KErrNone
+	asm("bx  lr ");             // Return
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/debugsrv/runmodedebug/rmdebug_test/rm_debug/debug_targets/d_rmdebugthreadasm2.cia	Fri Aug 27 11:37:29 2010 +0300
@@ -0,0 +1,35 @@
+// Copyright (c) 2006-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+// d_rmdebugthreadasm2.h
+// Assembler file for debug thread testing.
+// 
+//
+
+EXPORT_C __NAKED__ void RMDebug_BranchTst1( void )
+//
+// 
+//
+{
+	asm("mov r0, #0 ");			// aResult==KErrNone
+	asm("bx  lr ");             // Return
+}
+
+EXPORT_C __NAKED__ void RMDebug_BranchTst2( void )
+//
+// 
+//
+{
+	asm("mov r0, #0 ");			// aResult==KErrNone
+	asm("bx  lr ");             // Return
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/debugsrv/runmodedebug/rmdebug_test/rm_debug/debug_targets/t_rmdebug_app.cpp	Fri Aug 27 11:37:29 2010 +0300
@@ -0,0 +1,415 @@
+// Copyright (c) 2007-2010 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+//
+
+#include <e32base.h>
+#include <e32base_private.h>
+#include <e32cmn.h>
+#include <e32cmn_private.h>
+#include <e32debug.h>
+#include <e32property.h> 
+#include <u32hal.h>
+#include <hal.h>
+#include <f32file.h>
+#include <e32svr.h>
+#include <e32const.h>
+
+
+#include "t_rmdebug_app.h"
+
+IMPORT_C extern void RMDebug_BranchTst2();
+
+LOCAL_C void ParseCommandLineL(TInt32& aFunctionType, TUint& aDelay, TUint& aExtraThreads, TInt32& aCpuNumber, TInt32& aThreadPriority)
+	{
+
+	// get the length of the command line arguments
+	TInt argc = User::CommandLineLength();
+	RDebug::Printf(" t_rmdebug_app: ParseCommandLineL argc=%d", argc);
+
+	// allocate a buffer for the command line arguments and extract the data to it
+	HBufC* commandLine = HBufC::NewLC(argc);
+	TPtr commandLineBuffer = commandLine->Des();
+	User::CommandLine(commandLineBuffer);
+
+	// create a lexer and read through the command line
+	TLex lex(*commandLine);
+	while (!lex.Eos())
+		{
+		// expecting the first character to be a '-'
+		if (lex.Get() == '-')
+			{
+			TChar arg = lex.Get();
+			switch (arg)
+				{
+				case 'f':
+					// the digits following '-f' give the function type
+					User::LeaveIfError(lex.Val(aFunctionType));
+					RDebug::Printf(" t_rmdebug_app: setting aFunctionType=%d", aFunctionType);
+					break;
+				case 'd':
+					// the digits following '-d' give the delay
+					User::LeaveIfError(lex.Val(aDelay));
+					RDebug::Printf(" t_rmdebug_app: setting aDelay=%d", aDelay);
+					break;
+				case 'e':
+					// the digits following '-e' give the number of extra threads to launch
+					User::LeaveIfError(lex.Val(aExtraThreads));
+					RDebug::Printf(" t_rmdebug_app: setting aExtraThreads=%d", aExtraThreads);
+					break;
+
+				case 'p':
+					// the digits following '-p' gives the value to set for the main thread priority
+					User::LeaveIfError(lex.Val(aThreadPriority));
+					RDebug::Printf(" t_rmdebug_app: aThreadPriority =%d", aThreadPriority);
+					break;
+
+				case 'a':
+					// the digits following '-a' gives the cpu on which this thread will execute on
+					User::LeaveIfError(lex.Val(aCpuNumber));
+					RDebug::Printf(" t_rmdebug_app: CPU Number =%d", aCpuNumber );
+					break;
+
+				default:
+					// unknown argument so leave
+					User::Leave(KErrArgument);
+				}
+			lex.SkipSpace();
+			}
+		else
+			{
+			// unknown argument so leave
+			User::Leave(KErrArgument);
+			}
+		}
+
+	// do clean up
+	CleanupStack::PopAndDestroy(commandLine);
+	}
+
+typedef void (*TPfun)();
+
+// test function to call corresponding to EPrefetchAbortFunction
+void PrefetchAbort()
+	{
+	TPfun f = NULL;
+	f();
+	}
+
+// test function to call corresponding to EUserPanicFunction
+void UserPanic()
+	{
+	User::Panic(KUserPanic, KUserPanicCode);
+	}
+
+// calls self repeatedly until stack is used up. Slightly convoluted to prevent UREL optimising this out...
+TUint32 StackOverFlowFunction(TUint32 aInt=0)
+	{
+	TUint32 unusedArray[150];
+	for(TInt i=0; i<150; i++)
+		{
+		unusedArray[i] = StackOverFlowFunction(i);
+		}
+	return unusedArray[0];
+	}
+
+void DataAbort()
+	{
+	TInt* r = (TInt*) 0x1000;
+	*r = 0x42;              
+	}
+
+void UndefInstruction()
+	{
+	TUint32 undef = 0xE6000010;
+	TPfun f = (TPfun) &undef;
+	f();
+	}
+
+TInt DataRead()
+	{
+	TInt* r = (TInt*) 0x1000;
+	TInt rr = (TInt)*r;
+	//include the following line to ensure that rr doesn't get optimised out
+	RDebug::Printf("Shouldn't see this being printed out: %d", rr);
+
+	// Stop compilation warning. Should not get here anyway.
+	rr++;
+	return rr;
+	}
+
+void DataWrite()
+	{
+	TInt* r = (TInt*) 0x1000;
+	*r = 0x42;                
+	}
+
+void UserException()
+	{
+	User::RaiseException(EExcGeneral);
+	}
+
+void SpinForeverWithBreakPoint()
+	{
+
+    // finding the process t_rmdebug2/t_rmdebug2_oem/t_rmdebug2_oem2
+    // we find the process.SID to attach to the property
+	_LIT(KThreadWildCard, "t_rmdebug2*");
+
+	TInt err = KErrNone;
+	TUid propertySid = KNullUid;
+	TFindThread find(KThreadWildCard);
+	TFullName name;
+	TBool found = EFalse;
+	while(find.Next(name)==KErrNone && !found)
+		{
+		RThread thread;
+		err = thread.Open(find);
+		if (err == KErrNone)
+			{
+			RProcess process;
+			thread.Process(process);
+			TFullName fullname = thread.FullName();
+		    //RDebug::Printf("SID Search Match Found Name %lS Process ID%ld Thread Id %ld", &fullname, process.Id().Id(), thread.Id().Id());
+			found = ETrue;
+			//SID saved so that the property can be attached to
+			propertySid = process.SecureId();
+			process.Close();
+			}
+		thread.Close();
+	}
+
+    // publish the address of the RMDebug_BranchTst2 with the correct SID value
+	TInt address = (TInt)&RMDebug_BranchTst2;
+	err = RProperty::Set(propertySid, EMyPropertyInteger, address);
+	if(KErrNone != err)
+		RDebug::Printf("Error Set of the property %d", err);
+	
+	//open semaphore to signal the fact we have reached the point where we have to set the property
+	RSemaphore globsem;
+	globsem.OpenGlobal(_L("RMDebugGlobSem"));
+	globsem.Signal();
+	globsem.Close();
+
+	RProcess thisProcess;
+	TFileName thisProcessName = thisProcess.FileName();
+	RDebug::Print(_L("App Process Name %S process id %ld thread id %ld"), &thisProcessName, thisProcess.Id().Id(), RThread().Id().Id());
+
+	TInt i=0;
+	RThread::Rendezvous(KErrNone);
+	while(i<0xffffffff)
+		{
+		RMDebug_BranchTst2();
+		User::After(10000);
+		}
+	}
+
+void SpinForever()
+	{
+	TInt i=0;
+	RThread::Rendezvous(KErrNone);
+	while(i<0xffffffff)
+		{
+		User::After(10000);
+		}
+	}
+
+void NormalExit()
+    {
+    RDebug::Printf("Target app: NormalExit() function. Returning to MainL" );
+    }
+
+void LaunchThreads(TUint aNumber)
+	{
+	_LIT(KDebugThreadName, "DebugThread");
+	const TUint KDebugThreadDefaultHeapSize=0x10000;
+	for(TInt i=0; i<aNumber; i++)
+		{
+		RThread thread;
+		RBuf threadName;
+		threadName.Create(KDebugThreadName().Length()+10); // the 10 is for appending i to the end of the name
+		threadName.Append(KDebugThreadName());
+		threadName.AppendNum(i);
+		TInt err = thread.Create(threadName, (TThreadFunction)SpinForever, KDefaultStackSize, KDebugThreadDefaultHeapSize, KDebugThreadDefaultHeapSize, NULL);
+		if(err != KErrNone)
+			{
+			RDebug::Printf("Couldn't create thread %d", err);
+			threadName.Close();
+			thread.Close();
+			break;
+			}
+		thread.SetPriority(EPriorityNormal);
+		TRequestStatus status;
+		thread.Rendezvous(status);
+		thread.Resume();
+		User::WaitForRequest(status);
+		thread.Close();
+		threadName.Close();
+		}
+	}
+
+void WaitFiveSecondsThenExit(void)
+	{
+	// wait for 5 seconds
+	User::After(5000000);
+	}
+
+TInt NumberOfCpus()
+	{
+	TInt r = UserSvr::HalFunction(EHalGroupKernel, EKernelHalNumLogicalCpus, 0, 0);
+	return r;
+	}
+
+TInt SetCpuAffinity(TInt aCpuNumber)
+	{
+    TInt TestCpuCount = NumberOfCpus();
+	RDebug::Printf("SetCpuAffinity --> TestCpuCount = %d\n", TestCpuCount);		
+	TUint32 cpu = 0;
+
+	if ((aCpuNumber % TestCpuCount) != 0)
+	cpu = (TUint32)(aCpuNumber % TestCpuCount);
+
+	RDebug::Printf("SetCpuAffinity --> Setting cpu %3d\n", cpu);
+	TInt r = UserSvr::HalFunction(EHalGroupKernel, EKernelHalLockThreadToCpu, (TAny *)cpu, 0);
+	return r;
+	}
+
+void SetCurrentThreadPriority(TInt aThreadPriority)
+    {
+     RDebug::Printf("SetCurrentThreadPriority  aThreadPriority =%d\n", aThreadPriority);
+     RThread().SetPriority((TThreadPriority) aThreadPriority);
+     RDebug::Printf("SetCurrentThreadPriority Crashapp RThread Priority() = %d", (TInt) RThread().Priority()) ;
+    }
+
+TInt GetTimeInMs()
+{
+    TInt period = 0;
+    User::LeaveIfError(HAL::Get(HALData::ENanoTickPeriod, period));
+    TInt periodInMs = period / 1000;
+    return User::NTickCount() * periodInMs;
+}
+
+void SetNanoTickTime()
+    {
+    TUid t_performance_test_Sid;
+    t_performance_test_Sid.iUid = 0x102831E5;
+    RProperty::Set(t_performance_test_Sid, EPropertyTimeOfCrash, GetTimeInMs());    
+    }
+
+// call the function corresponding to aFunctionType
+LOCAL_C void CallFunction(TDebugFunctionType aFunctionType, TUint aDelay, TUint aExtraThreads, TInt32 aCpuNumber, TUint aThreadPriority )
+	{
+
+	// pause for aDelay microseconds
+	User::After(aDelay);
+
+	// set cpu on which this thread should execute on
+	if ( aCpuNumber )
+		SetCpuAffinity(aCpuNumber);
+	
+	if ( aThreadPriority )
+	    SetCurrentThreadPriority(aThreadPriority);
+
+	// launch the extra threads
+	LaunchThreads(aExtraThreads);
+	
+	// Publish Nano tick count time for RMDBG performance testing
+	SetNanoTickTime();
+	    
+	// call appropriate function
+	switch( aFunctionType )
+		{
+		case EPrefetchAbortFunction:
+			PrefetchAbort();
+			break;
+		case EUserPanicFunction:
+			UserPanic();
+			break;
+		case EStackOverflowFunction:
+			StackOverFlowFunction();
+			break;
+		case EDataAbortFunction:
+			DataAbort();
+			break;
+		case EUndefInstructionFunction:
+			UndefInstruction();
+			break;
+		case EDataReadErrorFunction:
+			DataRead();
+			break;
+		case EDataWriteErrorFunction:
+			DataWrite();
+			break;
+		case EUserExceptionFunction:
+			UserException();
+			break;
+		case EWaitFiveSecondsThenExit:
+			WaitFiveSecondsThenExit();
+			break;
+		case ESpinForever:
+			SpinForever();
+			break;
+		case ESpinForeverWithBreakPoint:
+			SpinForeverWithBreakPoint();
+			break;
+        case ENormalExit:
+            NormalExit();
+            break;			
+		case EDefaultDebugFunction:
+		default:
+			break;
+		}
+	}
+
+void PrintHelp()
+	{
+	RDebug::Printf("Invoke with arguments:\n");
+	RDebug::Printf("\t-d<delay>\n\t: delay in microseconds before calling target function\n");
+	RDebug::Printf("\t-f<function-number>\n\t: enumerator from TDebugFunctionType representing function to call\n");
+	RDebug::Printf("\t-e<number>\n\t: number of extra threads to launch, these threads run endlessly\n");
+	}
+
+TInt E32Main()
+	{
+    
+    RDebug::Printf("<<<<< E32Main() RThread Priority() = %d, RProcess Priority() = %d", (TInt) RThread().Priority(), (TInt) RProcess().Priority()) ;   
+	RDebug::Printf("t_rmdebug_app tid=%d,pid=%d", I64LOW(RThread().Id().Id()), I64LOW(RProcess().Id().Id()) ) ;
+	// setup heap checking and clean up trap
+	__UHEAP_MARK;
+	CTrapCleanup* cleanup=CTrapCleanup::New();
+	RThread().SetPriority(EPriorityNormal);
+	RProcess::Rendezvous(KErrNone);
+	
+	// read arguments from command line
+	TUint delay = 0;
+	TInt32 functionTypeAsTInt32 = (TInt32)EDefaultDebugFunction;
+	TUint extraThreads = 0;
+	TInt32 aCpuNumber = 0;
+	TInt32 aThreadPriority = 0;
+
+	TRAPD(err, ParseCommandLineL(functionTypeAsTInt32, delay, extraThreads, aCpuNumber, aThreadPriority));
+
+	RDebug::Printf("E32Main :: aThreadPriority=%d", aThreadPriority ) ;
+	
+	if(KErrNone == err)
+		{
+		// if the command line arguments were successfully read then call the appropriate function
+		CallFunction((TDebugFunctionType)functionTypeAsTInt32, delay, extraThreads, aCpuNumber, aThreadPriority);
+		}
+
+	// perform clean up and return any error which was recorded
+	delete cleanup;
+	__UHEAP_MARKEND;
+	return err;
+	}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/debugsrv/runmodedebug/rmdebug_test/rm_debug/debug_targets/t_rmdebug_app.h	Fri Aug 27 11:37:29 2010 +0300
@@ -0,0 +1,46 @@
+// Copyright (c) 2007-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+//
+
+#ifndef T_RMDEBUG_APP_H
+#define T_RMDEBUG_APP_H
+
+_LIT(KRMDebugTestApplication, "z:\\sys\\bin\\t_rmdebug_app.exe");
+_LIT(KUserPanic, "UserPanic");
+const TInt KUserPanicCode = 0x1234ABCD;
+
+enum TMyPropertyKeys {EMyPropertyInteger};
+enum TPropertyTimeKeys {EPropertyTimeOfCrash};
+
+
+// enumeration of functions to call in test debug application
+enum TDebugFunctionType
+	{
+	EDefaultDebugFunction,
+	EPrefetchAbortFunction,
+	EUserPanicFunction,
+	EStackOverflowFunction,
+	EDataAbortFunction,
+	EUndefInstructionFunction,
+	EDataReadErrorFunction,
+	EDataWriteErrorFunction,
+	EUserExceptionFunction,
+	EWaitFiveSecondsThenExit,
+	ESpinForever,
+	ESpinForeverWithBreakPoint,
+	ENormalExit
+	};
+
+#endif //T_RMDEBUG_APP_H
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/debugsrv/runmodedebug/rmdebug_test/rm_debug/debug_targets/t_rmdebug_dll.cpp	Fri Aug 27 11:37:29 2010 +0300
@@ -0,0 +1,25 @@
+// Copyright (c) 2007-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+//
+
+#include <e32std.h>
+#include <e32std_private.h>
+#include <rm_debug_api.h>
+#include "t_rmdebug_dll.h"
+
+EXPORT_C TUid GetDSSUid()
+	{
+	return Debug::KUidDebugSecurityServer;
+	}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/debugsrv/runmodedebug/rmdebug_test/rm_debug/debug_targets/t_rmdebug_dll.h	Fri Aug 27 11:37:29 2010 +0300
@@ -0,0 +1,23 @@
+// Copyright (c) 2007-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+//
+
+#include <e32std.h>
+
+/**
+  This is a simple function that uses an element from rm_debug_api.h.
+  If the e32tests can be built and run then this is 'proof' that the
+  rm_debug_api.h header file can be #include'd into a dll
+  */
+IMPORT_C TUid GetDSSUid();
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/debugsrv/runmodedebug/rmdebug_test/rm_debug/debug_targets/t_rmdebug_security.cpp	Fri Aug 27 11:37:29 2010 +0300
@@ -0,0 +1,100 @@
+// Copyright (c) 2006-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+// Target application to be debugged by t_rmdebug.exe when testing
+// security restrictions. This application is built with various
+// capabilities by the t_rmdebug_securityX.mmp files. This allows
+// the t_rmdebug2 program to ensure that security restrictions are
+// properly enforced by the DSS/DDD subsystem.
+// 
+//
+
+#include <e32base.h>
+#include <e32base_private.h>
+#include <e32cons.h>
+#include <e32test.h>
+#include <e32ldr.h>
+#include <e32cmn.h>
+#include <e32cmn_private.h>
+#include "t_rmdebug_security.h"
+
+CRunModeApp* CRunModeApp::NewL()
+//
+// CRunModeApp::NewL
+//
+	{
+	CRunModeApp* self = new(ELeave) CRunModeApp();
+
+  	self->ConstructL();
+   
+	return self;
+	}
+
+CRunModeApp::CRunModeApp()
+//
+// CRunModeApp constructor
+//
+	{
+	}
+
+CRunModeApp::~CRunModeApp()
+//
+// CRunModeApp destructor
+//
+	{
+	}
+
+void CRunModeApp::ConstructL()
+//
+// CRunModeApp::ConstructL
+//
+	{
+	}
+
+void CRunModeApp::TestWaitDebug()
+//
+// CRunModeApp::TestWaitDebug
+//
+	{
+	RProcess::Rendezvous(KErrNone);
+
+	// Wait a 3secs then quit (long enough to test, but not hang around forever)
+	User::After(3000000);
+	}
+
+GLDEF_C TInt E32Main()
+//
+// Entry point for run mode debug app test program
+//
+	{
+   TInt ret = KErrNone;
+   
+	// client
+	CTrapCleanup* trap = CTrapCleanup::New();
+	if (!trap)
+		return KErrNoMemory;
+
+   CRunModeApp* myApp = CRunModeApp::NewL();
+   if (myApp != NULL)
+       {
+        __UHEAP_MARK;
+	    TRAP(ret,myApp->TestWaitDebug());
+	    __UHEAP_MARKEND;
+
+	    delete myApp;
+       }
+       
+	delete trap;
+
+	return ret;
+	}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/debugsrv/runmodedebug/rmdebug_test/rm_debug/debug_targets/t_rmdebug_security.h	Fri Aug 27 11:37:29 2010 +0300
@@ -0,0 +1,44 @@
+// Copyright (c) 2006-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+// Target application to be debugged by t_rmdebug2.exe when testing
+// security restrictions. This application is built with various
+// capabilities by the t_rmdebug_securityX.mmp files. This allows
+// the t_rmdebug2 program to ensure that security restrictions are
+// properly enforced by the DSS/DDD subsystem.
+// 
+//
+
+/**
+ @file
+ @internalTechnology
+ @released
+*/
+
+#ifndef T_RMDEBUG_SECURITY_H
+#define T_RMDEBUG_SECURITY_H
+
+class CRunModeApp : public CBase
+{
+public:
+	static CRunModeApp* NewL();
+	~CRunModeApp();
+
+	void TestWaitDebug();
+
+private:
+	CRunModeApp();
+	void ConstructL();
+};
+
+#endif // T_RMDEBUG_SECURITY_H
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/debugsrv/runmodedebug/rmdebug_test/rm_debug/group/bld.inf	Fri Aug 27 11:37:29 2010 +0300
@@ -0,0 +1,94 @@
+// Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+// e32test/group/bld.inf
+// Kernel and User library test code
+// 
+//
+
+/**
+ @file
+*/
+
+
+PRJ_PLATFORMS
+
+BASEDEFAULT
+
+PRJ_TESTEXPORTS
+
+./t_rmdebug_tests.iby					/epoc32/rom/include/t_rmdebug_tests.iby
+./mytraces_rm_debug_ekern.txt			/epoc32/rombuild/mytraces_rm_debug_ekern.txt
+./mytraces_rm_debug.txt					/epoc32/rombuild/mytraces_rm_debug.txt
+
+./rmdebug.iby							/epoc32/rom/include/rmdebug.iby
+../scripts/tef_execute_rtests.script	z:/scripts/tef_execute_rtests.script
+
+
+PRJ_TESTMMPFILES
+
+/******************************************************************************
+ Put all device drivers here. These build both SMP and non-SMP variants.
+ User side code builds a single variant for both.
+ *NOTE: Base BTB will build properly any kernel-side test code embedded within 
+ positive check ( #ifdef SMP ), however these binaries will not be included in BTB 
+ autotest images for SMP platforms. Refer to DTW-KHS BTB00055 for more details.
+ ******************************************************************************/
+
+/******************************************************************************
+ User side code here - builds a single variant for both SMP and non-SMP.
+ ******************************************************************************/
+
+#if defined(MARM_ARMV5)
+./t_rmdebug_app support
+./t_rmdebug_app1 support
+./t_rmdebug_app2 support
+./t_rmdebug_app3 support
+./t_rmdebug_app4 support
+./t_rmdebug_app5 support
+./t_rmdebug_app6 support
+./t_rmdebug_app7 support
+./t_rmdebug_app8 support
+./t_rmdebug_app9 support
+./t_rmdebug_app10 support
+
+./t_rmdebug_dll support
+
+./t_rmdebug_security0 support
+./t_rmdebug_security1 support
+./t_rmdebug_security2 support
+./t_rmdebug_security3 support
+
+./t_rmdebug2.mmp
+
+./t_rmdebug2_oem.mmp
+./t_rmdebug2_oemtoken support
+
+./t_rmdebug2_oem2.mmp
+./t_rmdebug2_oemtoken2 support
+
+./t_rmdebug2_allcaps.mmp
+./t_rmdebug2_allcapstoken support
+
+./t_rmdebug_target_launcher support
+./t_rmdebug_multi_target.mmp
+
+./t_rmdebug_multi_agent support
+./t_multi_agent_launcher.mmp
+
+./t_rmdebug_performance_allcapstoken
+./t_performance_test.mmp
+
+#endif
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/debugsrv/runmodedebug/rmdebug_test/rm_debug/group/mytraces_rm_debug.txt	Fri Aug 27 11:37:29 2010 +0300
@@ -0,0 +1,37 @@
+_fh4hrp_scmonitornor.dll
+_h4hrp_scmonitornor.dll
+OEMDebug_10282FE5.exe
+OEMDebug_102831E5.exe
+OEMDebug_F1234567.exe
+OEMDebug_F123ABCD.exe
+OEMDebug_F123ABCE.exe
+rm_debug.ldd
+rm_debug_svr.exe
+scmonitor_serial.dll
+t_crashmonitor_lib.exe
+t_performance_test.exe
+t_rmdebug_app.exe
+t_rmdebug_app1.exe
+t_rmdebug_app10.exe
+t_rmdebug_app2.exe
+t_rmdebug_app3.exe
+t_rmdebug_app4.exe
+t_rmdebug_app5.exe
+t_rmdebug_app6.exe
+t_rmdebug_app7.exe
+t_rmdebug_app8.exe
+t_rmdebug_app9.exe
+t_rmdebug_attachall.exe
+t_rmdebug_dll.dll
+t_rmdebug_multi_agent.exe
+t_rmdebug_multi_target.exe
+t_rmdebug_security0.exe
+t_rmdebug_security1.exe
+t_rmdebug_security2.exe
+t_rmdebug_security3.exe
+t_rmdebug_target_launcher.exe
+t_rmdebug2.exe
+t_rmdebug2_allcaps.exe
+t_rmdebug2_oem.exe
+t_rmdebug2_oem2.exe
+t_trkdummyapp.exe
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/debugsrv/runmodedebug/rmdebug_test/rm_debug/group/mytraces_rm_debug_ekern.txt	Fri Aug 27 11:37:29 2010 +0300
@@ -0,0 +1,49 @@
+_34xx_sdp_ekern.exe
+_8500_ekern.exe
+_f34xx_sdp_ekern.exe
+_fh4hrp_ekern.exe
+_fne1_tb_ekern.exe
+_h4hrp_ekern.exe
+_lab_ekern.exe
+_ne1_tb_ekern.exe
+_rapu_ekern.exe
+_rapu_fmm_ekern.exe
+_template_ekern.exe
+
+_fh4hrp_scmonitornor.dll
+_h4hrp_scmonitornor.dll
+OEMDebug_10282FE5.exe
+OEMDebug_102831E5.exe
+OEMDebug_F1234567.exe
+OEMDebug_F123ABCD.exe
+OEMDebug_F123ABCE.exe
+rm_debug.ldd
+rm_debug_svr.exe
+scmonitor_serial.dll
+t_crashmonitor_lib.exe
+t_performance_test.exe
+t_rmdebug_app.exe
+t_rmdebug_app1.exe
+t_rmdebug_app10.exe
+t_rmdebug_app2.exe
+t_rmdebug_app3.exe
+t_rmdebug_app4.exe
+t_rmdebug_app5.exe
+t_rmdebug_app6.exe
+t_rmdebug_app7.exe
+t_rmdebug_app8.exe
+t_rmdebug_app9.exe
+t_rmdebug_attachall.exe
+t_rmdebug_dll.dll
+t_rmdebug_multi_agent.exe
+t_rmdebug_multi_target.exe
+t_rmdebug_security0.exe
+t_rmdebug_security1.exe
+t_rmdebug_security2.exe
+t_rmdebug_security3.exe
+t_rmdebug_target_launcher.exe
+t_rmdebug2.exe
+t_rmdebug2_allcaps.exe
+t_rmdebug2_oem.exe
+t_rmdebug2_oem2.exe
+t_trkdummyapp.exe
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/debugsrv/runmodedebug/rmdebug_test/rm_debug/group/rmdbg_test.pkg	Fri Aug 27 11:37:29 2010 +0300
@@ -0,0 +1,64 @@
+// Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description: 
+//
+
+// BINARIES NEEDED BY TESTS BELOW
+"\epoc32\release\armv5\udeb\t_rmdebug_app.exe"-"c:\sys\bin\t_rmdebug_app.exe"
+"\epoc32\release\armv5\udeb\t_rmdebug_app1.exe"-"c:\sys\bin\t_rmdebug_app1.exe"
+"\epoc32\release\armv5\udeb\t_rmdebug_app2.exe"-"c:\sys\bin\t_rmdebug_app2.exe"
+"\epoc32\release\armv5\udeb\t_rmdebug_app3.exe"-"c:\sys\bin\t_rmdebug_app3.exe"
+"\epoc32\release\armv5\udeb\t_rmdebug_app4.exe"-"c:\sys\bin\t_rmdebug_app4.exe"
+"\epoc32\release\armv5\udeb\t_rmdebug_app5.exe"-"c:\sys\bin\t_rmdebug_app5.exe"
+"\epoc32\release\armv5\udeb\t_rmdebug_app6.exe"-"c:\sys\bin\t_rmdebug_app6.exe"
+"\epoc32\release\armv5\udeb\t_rmdebug_app7.exe"-"c:\sys\bin\t_rmdebug_app7.exe"
+"\epoc32\release\armv5\udeb\t_rmdebug_app8.exe"-"c:\sys\bin\t_rmdebug_app8.exe"
+"\epoc32\release\armv5\udeb\t_rmdebug_app9.exe"-"c:\sys\bin\t_rmdebug_app9.exe"
+"\epoc32\release\armv5\udeb\t_rmdebug_app10.exe"-"c:\sys\bin\t_rmdebug_app10.exe"
+
+"\epoc32\release\armv5\udeb\t_rmdebug_dll.dll"-"c:\sys\bin\t_rmdebug_dll.dll"
+
+"\epoc32\release\armv5\udeb\t_rmdebug_security0.exe"-"c:\sys\bin\t_rmdebug_security0.exe"
+"\epoc32\release\armv5\udeb\t_rmdebug_security1.exe"-"c:\sys\bin\t_rmdebug_security1.exe"
+"\epoc32\release\armv5\udeb\t_rmdebug_security2.exe"-"c:\sys\bin\t_rmdebug_security2.exe"
+"\epoc32\release\armv5\udeb\t_rmdebug_security3.exe"-"c:\sys\bin\t_rmdebug_security3.exe"
+
+
+//RUN_RTESTS_AS_TEF
+"\epoc32\data\z\scripts\tef_execute_rtests.script"-"c:\scripts\tef_execute_rtests.script"
+
+
+//No token required
+"\epoc32\release\armv5\udeb\t_rmdebug2.exe"-"c:\sys\bin\t_rmdebug2.exe"
+
+//SOMECAPS_DEBUGTOKEN
+"\epoc32\release\armv5\udeb\t_rmdebug2_oem.exe"-"c:\sys\bin\t_rmdebug2_oem.exe"
+"\epoc32\release\armv5\udeb\OEMDebug_F123ABCD.exe"-"c:\sys\bin\OEMDebug_F123ABCD.exe"
+
+//FEWCAPS_DEBUGTOKEN
+"\epoc32\release\armv5\udeb\t_rmdebug2_oem2.exe"-"c:\sys\bin\t_rmdebug2_oem2.exe"
+"\epoc32\release\armv5\udeb\OEMDebug_F1234567.exe"-"c:\sys\bin\OEMDebug_F1234567.exe"
+
+//ALLCAPS_DEBUGTOKEN
+"\epoc32\release\armv5\udeb\t_rmdebug2_allcaps.exe"-"c:\sys\bin\t_rmdebug2_allcaps.exe"
+"\epoc32\release\armv5\udeb\OEMDebug_F123ABCE.exe"-"c:\sys\bin\OEMDebug_F123ABCE.exe"
+
+"\epoc32\release\armv5\udeb\t_rmdebug_target_launcher.exe"-"c:\sys\bin\t_rmdebug_target_launcher.exe"
+"\epoc32\release\armv5\udeb\t_rmdebug_multi_target.exe"-"c:\sys\bin\t_rmdebug_multi_target.exe"
+
+"\epoc32\release\armv5\udeb\t_rmdebug_multi_agent.exe"-"c:\sys\bin\t_rmdebug_multi_agent.exe"
+"\epoc32\release\armv5\udeb\t_multi_agent_launcher.exe"-"c:\sys\bin\t_multi_agent_launcher.exe"
+
+//PERFORMANCE TEST DEBUGTOKEN
+"\epoc32\release\armv5\udeb\t_performance_test.exe"-"c:\sys\bin\t_performance_test.exe"
+"\epoc32\release\armv5\udeb\OEMDebug_102831E5.exe"-"c:\sys\bin\OEMDebug_102831E5.exe"
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/debugsrv/runmodedebug/rmdebug_test/rm_debug/group/rmdebug.iby	Fri Aug 27 11:37:29 2010 +0300
@@ -0,0 +1,18 @@
+// Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+// Build configuration file for Sirocco
+//
+
+extension[VARID]=KERNEL_DIR\DEBUG_DIR\rm_debug.ldd		\sys\bin\rm_debug.ldd
+file=KERNEL_DIR\DEBUG_DIR\rm_debug_svr.exe		\sys\bin\rm_debug_svr.exe
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/debugsrv/runmodedebug/rmdebug_test/rm_debug/group/t_multi_agent_launcher.mmp	Fri Aug 27 11:37:29 2010 +0300
@@ -0,0 +1,44 @@
+// Copyright (c) 2006-2010 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+// Application that launches multiple agents which in-turn test the ability of 
+// the run mode debug component to debug several targets
+// 
+//
+
+// This is an RTest configured to run on Sirocco, hence the testexecuteutils linked in lib below.
+
+targettype     exe
+target         t_multi_agent_launcher.exe
+
+library		euser.lib hal.lib
+library		testexecuteutils.lib // for Sirocco
+
+OS_LAYER_SYSTEMINCLUDE_SYMBIAN
+
+userinclude    ../debug_targets
+userinclude    ../common
+userinclude    ../multi_agent_tests
+
+sourcepath	   ../multi_agent_tests
+source         t_multi_agent_launcher.cpp 
+
+UID            0x0 0x4321bbbc
+SECUREID       0x1234aaab
+VENDORID       0x70000001
+
+DEBUGGABLE
+
+macro NO_DEBUGTOKEN
+
+SMPSAFE
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/debugsrv/runmodedebug/rmdebug_test/rm_debug/group/t_performance_test.mmp	Fri Aug 27 11:37:29 2010 +0300
@@ -0,0 +1,40 @@
+// Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+// 
+//
+
+// This is an RTest configured to run on Sirocco, hence the testexecuteutils linked in lib below.
+
+TARGET        t_performance_test.exe
+TARGETTYPE    exe
+UID			  0x1000008D 0x102831E5
+VENDORID	  0x70000001
+
+ 
+USERINCLUDE   ../common
+USERINCLUDE   ../performance_test
+USERINCLUDE   ../debug_targets
+SOURCEPATH    ../performance_test
+
+OS_LAYER_SYSTEMINCLUDE_SYMBIAN
+
+library       euser.lib
+library       hal.lib
+library       testexecuteutils.lib // for Sirocco
+
+DEBUGGABLE
+
+MACRO SYMBIAN_TRACE_ENABLE
+
+SOURCE t_rmdebug_performance_test.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/debugsrv/runmodedebug/rmdebug_test/rm_debug/group/t_rmdebug.iby	Fri Aug 27 11:37:29 2010 +0300
@@ -0,0 +1,28 @@
+// Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+// Tests the functionality of the run mode debug device driver.
+//
+//
+
+
+#ifndef T_RMDEBUG_IBY
+#define T_RMDEBUG_IBY
+
+file=ABI_DIR\DEBUG_DIR\t_rmdebug2.exe			\sys\bin\t_rmdebug2.exe
+file=ABI_DIR\DEBUG_DIR\t_rmdebug2_oem.exe			\sys\bin\t_rmdebug2_oem.exe
+file=ABI_DIR\DEBUG_DIR\OEMDebug_F123ABCD.exe	\sys\bin\OEMDebug_F123ABCD.exe
+
+file=ABI_DIR\DEBUG_DIR\t_rmdebug_dll.dll		\sys\bin\t_rmdebug_dll.dll
+
+#endif
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/debugsrv/runmodedebug/rmdebug_test/rm_debug/group/t_rmdebug.mmp	Fri Aug 27 11:37:29 2010 +0300
@@ -0,0 +1,40 @@
+// Copyright (c) 2006-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+// 
+//
+
+ALWAYS_BUILD_AS_ARM
+
+target         t_rmdebug.exe
+targettype     exe
+
+sourcepath	   	../metro_trk
+source        	d_rmdebugserver.cpp 
+source        	d_rmdebugthread.cpp 
+source        	t_rmdebug.cpp 
+sourcepath	   	../common
+source			d_rmdebugthreadasm.cia
+
+library		euser.lib
+               
+SYMBIAN_BASE_SYSTEMINCLUDE(nkern)
+OS_LAYER_SYSTEMINCLUDE_SYMBIAN
+
+UID            0x100039CE 0x101F7159
+SECUREID       0x101F7159
+VENDORID       0x70000001
+
+CAPABILITY 	ALL -TCB
+
+SMPSAFE
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/debugsrv/runmodedebug/rmdebug_test/rm_debug/group/t_rmdebug2.mmh	Fri Aug 27 11:37:29 2010 +0300
@@ -0,0 +1,66 @@
+// Copyright (c) 2006-2010 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+// 
+//
+
+ALWAYS_BUILD_AS_ARM
+
+targettype     exe
+
+sourcepath	   	..\debug_targets
+
+source        	d_rmdebugthread2.cpp 
+source			d_rmdebugthreadasm2.cia
+
+#if defined(MARM_ARMV5)
+source			d_rmdebug_step_test.s
+source			d_rmdebug_bkpt_test.s
+#endif
+
+#if defined(MARM_ARMV4)
+source			d_rmdebug_step_test_armv4.s
+#endif
+
+source			d_demand_paging.cia
+
+library		euser.lib
+library         hal.lib
+library         efsrv.lib
+library         t_rmdebug_dll.lib
+
+userinclude    ..\..\..\rmdriver\inc
+userinclude    ..\..\..\securityserver\inc
+userinclude    ..\debug_targets
+
+
+#ifdef SYMBIAN_OLD_EXPORT_LOCATION
+SYMBIAN_BASE_SYSTEMINCLUDE(drivers)
+SYMBIAN_BASE_SYSTEMINCLUDE(kernel)
+#endif
+SYMBIAN_BASE_SYSTEMINCLUDE(nkern)
+OS_LAYER_SYSTEMINCLUDE_SYMBIAN
+
+PAGED
+
+// To test heap allocation failure uncomment one or other of the following macros.
+// NOTE: Do not uncomment both, the tests will panic if both are defined!
+
+// To test heap allocation failure in the Debug Device Driver uncomment this macro
+//macro KERNEL_OOM_TESTING
+
+// To test heap allocation failure in the Debug Security Server uncomment this macro
+//macro USER_OOM_TESTING
+
+
+SMPSAFE
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/debugsrv/runmodedebug/rmdebug_test/rm_debug/group/t_rmdebug2.mmp	Fri Aug 27 11:37:29 2010 +0300
@@ -0,0 +1,39 @@
+// Copyright (c) 2006-2010 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+// 
+//
+
+// This is an RTest configured to run on Sirocco, hence the testexecuteutils linked in lib below.
+
+#include "t_rmdebug2.mmh"
+
+target         t_rmdebug2.exe
+
+sourcepath	   	../basic_tests
+source        	t_rmdebug2.cpp 
+source		r_low_memory_security_svr_session.cpp
+source		r_kernel_low_memory_security_svr_session.cpp
+source		r_user_low_memory_security_svr_session.cpp
+
+library		testexecuteutils.lib // for Sirocco
+
+UID            0x0 0x4321bbbb
+SECUREID       0x1234aaaa
+VENDORID       0x70000001
+
+CAPABILITY 	READUSERDATA POWERMGMT ALLFILES
+
+DEBUGGABLE
+
+macro NO_DEBUGTOKEN
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/debugsrv/runmodedebug/rmdebug_test/rm_debug/group/t_rmdebug2_allcaps.mmp	Fri Aug 27 11:37:29 2010 +0300
@@ -0,0 +1,42 @@
+// Copyright (c) 2006-2010 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+// Same tests as t_rmdebug2.mmp but with OEM rights conferred
+// by the OEMDebug_F123ABCD.exe token file.
+// 
+//
+
+// This is an RTest configured to run on Sirocco, hence the testexecuteutils linked in lib below.
+
+#include "t_rmdebug2.mmh"
+
+target         t_rmdebug2_allcaps.exe
+
+sourcepath	   	../basic_tests
+source        	t_rmdebug2.cpp 
+source		r_low_memory_security_svr_session.cpp
+source		r_kernel_low_memory_security_svr_session.cpp
+source		r_user_low_memory_security_svr_session.cpp
+
+library		testexecuteutils.lib // for Sirocco
+
+UID            0x0 0x4321bbbb
+SECUREID       0xF123abce
+VENDORID       0x70000001
+
+CAPABILITY 	READUSERDATA POWERMGMT ALLFILES
+
+// Used when compiling tests to work in the presence of an
+// OEM Debug Token
+macro ALLCAPS_DEBUGTOKEN
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/debugsrv/runmodedebug/rmdebug_test/rm_debug/group/t_rmdebug2_allcapstoken.mmp	Fri Aug 27 11:37:29 2010 +0300
@@ -0,0 +1,36 @@
+// Copyright (c) 2007-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+// 
+//
+
+ALWAYS_BUILD_AS_ARM
+
+target         OEMDebug_F123ABCE.exe
+targettype     exe
+
+sourcepath	   	../basic_tests
+
+source        	t_rmdebug2_oemtoken.cpp 
+
+library		euser.lib
+
+OS_LAYER_SYSTEMINCLUDE_SYMBIAN
+
+capability All
+
+UID            0x0 0x0
+SECUREID       0x0
+VENDORID       0x70000001
+
+SMPSAFE
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/debugsrv/runmodedebug/rmdebug_test/rm_debug/group/t_rmdebug2_oem.mmp	Fri Aug 27 11:37:29 2010 +0300
@@ -0,0 +1,42 @@
+// Copyright (c) 2006-2010 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+// Same tests as t_rmdebug2.mmp but with OEM rights conferred
+// by the OEMDebug_F123ABCD.exe token file.
+// 
+//
+
+// This is an RTest configured to run on Sirocco, hence the testexecuteutils linked in lib below.
+
+#include "t_rmdebug2.mmh"
+
+target         t_rmdebug2_oem.exe
+
+sourcepath	   	../basic_tests
+source        	t_rmdebug2.cpp 
+source		r_low_memory_security_svr_session.cpp
+source		r_kernel_low_memory_security_svr_session.cpp
+source		r_user_low_memory_security_svr_session.cpp
+
+library		testexecuteutils.lib // for Sirocco
+
+UID            0x0 0x4321bbbb
+SECUREID       0xF123abcd
+VENDORID       0x70000001
+
+CAPABILITY 	READUSERDATA POWERMGMT ALLFILES
+
+// Used when compiling tests to work in the presence of an
+// OEM Debug Token
+macro SOMECAPS_DEBUGTOKEN
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/debugsrv/runmodedebug/rmdebug_test/rm_debug/group/t_rmdebug2_oem2.mmp	Fri Aug 27 11:37:29 2010 +0300
@@ -0,0 +1,42 @@
+// Copyright (c) 2006-2010 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+// Same tests as t_rmdebug2.mmp but with some OEM rights conferred
+// by the OEMDebug_F1234567.exe token file.
+// 
+//
+
+//RTEST
+
+#include "t_rmdebug2.mmh"
+
+target         t_rmdebug2_oem2.exe
+
+sourcepath	   	../basic_tests
+source        	t_rmdebug2.cpp 
+source		r_low_memory_security_svr_session.cpp
+source		r_kernel_low_memory_security_svr_session.cpp
+source		r_user_low_memory_security_svr_session.cpp
+
+library		testexecuteutils.lib // for Sirocco
+
+UID            0x0 0x4321bbbb
+SECUREID       0xF1234567
+VENDORID       0x70000001
+
+CAPABILITY 	READUSERDATA POWERMGMT
+
+// Used when compiling tests to work in the presence of an
+// OEM Debug Token with AllFiles only capability
+macro FEWCAPS_DEBUGTOKEN
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/debugsrv/runmodedebug/rmdebug_test/rm_debug/group/t_rmdebug2_oemtoken.mmp	Fri Aug 27 11:37:29 2010 +0300
@@ -0,0 +1,36 @@
+// Copyright (c) 2007-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+// 
+//
+
+ALWAYS_BUILD_AS_ARM
+
+target         OEMDebug_F123ABCD.exe
+targettype     exe
+
+sourcepath	   	../basic_tests
+
+source        	t_rmdebug2_oemtoken.cpp 
+
+library		euser.lib
+
+OS_LAYER_SYSTEMINCLUDE_SYMBIAN
+
+capability PowerMgmt AllFiles Tcb ReadUserData WriteUserData
+
+UID            0x0 0x0
+SECUREID       0x0
+VENDORID       0x70000001
+
+SMPSAFE
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/debugsrv/runmodedebug/rmdebug_test/rm_debug/group/t_rmdebug2_oemtoken2.mmp	Fri Aug 27 11:37:29 2010 +0300
@@ -0,0 +1,37 @@
+// Copyright (c) 2007-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+// 
+//
+
+ALWAYS_BUILD_AS_ARM
+
+target         OEMDebug_F1234567.exe
+targettype     exe
+
+sourcepath	   	../basic_tests
+
+source        	t_rmdebug2_oemtoken.cpp 
+
+library		euser.lib
+
+OS_LAYER_SYSTEMINCLUDE_SYMBIAN
+
+// Token requires AllFiles
+capability AllFiles ReadUserData PowerMgmt
+
+UID            0x0 0x0
+SECUREID       0x0
+VENDORID       0x70000001
+
+SMPSAFE
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/debugsrv/runmodedebug/rmdebug_test/rm_debug/group/t_rmdebug_app.mmp	Fri Aug 27 11:37:29 2010 +0300
@@ -0,0 +1,35 @@
+// Copyright (c) 2007-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+// 
+//
+
+target             t_rmdebug_app.exe
+targettype         exe
+
+sourcepath         ../debug_targets
+source             t_rmdebug_app.cpp 
+source			   d_rmdebugthreadasm2.cia
+
+OS_LAYER_SYSTEMINCLUDE_SYMBIAN
+library            euser.lib hal.lib
+
+uid                0x0 0x0
+capability         none
+
+always_build_as_arm
+pagedcode
+
+DEBUGGABLE
+
+SMPSAFE
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/debugsrv/runmodedebug/rmdebug_test/rm_debug/group/t_rmdebug_app1.mmp	Fri Aug 27 11:37:29 2010 +0300
@@ -0,0 +1,36 @@
+// Copyright (c) 2007-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+// Target application to be debugged
+// 
+//
+
+target             t_rmdebug_app1.exe
+targettype         exe
+
+sourcepath         ../debug_targets
+source             t_rmdebug_app.cpp 
+source             d_rmdebugthreadasm2.cia
+
+OS_LAYER_SYSTEMINCLUDE_SYMBIAN
+library            euser.lib hal.lib
+
+uid                0x0 0x0
+capability         none
+
+always_build_as_arm
+pagedcode
+
+DEBUGGABLE
+
+SMPSAFE
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/debugsrv/runmodedebug/rmdebug_test/rm_debug/group/t_rmdebug_app10.mmp	Fri Aug 27 11:37:29 2010 +0300
@@ -0,0 +1,36 @@
+// Copyright (c) 2007-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+// Target application to be debugged
+// 
+//
+
+target             t_rmdebug_app10.exe
+targettype         exe
+
+sourcepath         ../debug_targets
+source             t_rmdebug_app.cpp 
+source             d_rmdebugthreadasm2.cia
+
+OS_LAYER_SYSTEMINCLUDE_SYMBIAN
+library            euser.lib hal.lib
+
+uid                0x0 0x0
+capability         none
+
+always_build_as_arm
+pagedcode
+
+DEBUGGABLE
+
+SMPSAFE
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/debugsrv/runmodedebug/rmdebug_test/rm_debug/group/t_rmdebug_app2.mmp	Fri Aug 27 11:37:29 2010 +0300
@@ -0,0 +1,36 @@
+// Copyright (c) 2007-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+// Target application to be debugged
+// 
+//
+
+target             t_rmdebug_app2.exe
+targettype         exe
+
+sourcepath         ../debug_targets
+source             t_rmdebug_app.cpp 
+source             d_rmdebugthreadasm2.cia
+
+OS_LAYER_SYSTEMINCLUDE_SYMBIAN
+library            euser.lib hal.lib
+
+uid                0x0 0x0
+capability         none
+
+always_build_as_arm
+pagedcode
+
+DEBUGGABLE
+
+SMPSAFE
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/debugsrv/runmodedebug/rmdebug_test/rm_debug/group/t_rmdebug_app3.mmp	Fri Aug 27 11:37:29 2010 +0300
@@ -0,0 +1,36 @@
+// Copyright (c) 2007-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+// Target application to be debugged
+// 
+//
+
+target             t_rmdebug_app3.exe
+targettype         exe
+
+sourcepath         ../debug_targets
+source             t_rmdebug_app.cpp 
+source             d_rmdebugthreadasm2.cia
+
+OS_LAYER_SYSTEMINCLUDE_SYMBIAN
+library            euser.lib hal.lib
+
+uid                0x0 0x0
+capability         none
+
+always_build_as_arm
+pagedcode
+
+DEBUGGABLE
+
+SMPSAFE
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/debugsrv/runmodedebug/rmdebug_test/rm_debug/group/t_rmdebug_app4.mmp	Fri Aug 27 11:37:29 2010 +0300
@@ -0,0 +1,36 @@
+// Copyright (c) 2007-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+// Target application to be debugged
+// 
+//
+
+target             t_rmdebug_app4.exe
+targettype         exe
+
+sourcepath         ../debug_targets
+source             t_rmdebug_app.cpp 
+source             d_rmdebugthreadasm2.cia
+
+OS_LAYER_SYSTEMINCLUDE_SYMBIAN
+library            euser.lib hal.lib
+
+uid                0x0 0x0
+capability         none
+
+always_build_as_arm
+pagedcode
+
+DEBUGGABLE
+
+SMPSAFE
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/debugsrv/runmodedebug/rmdebug_test/rm_debug/group/t_rmdebug_app5.mmp	Fri Aug 27 11:37:29 2010 +0300
@@ -0,0 +1,36 @@
+// Copyright (c) 2007-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+// Target application to be debugged
+// 
+//
+
+target             t_rmdebug_app5.exe
+targettype         exe
+
+sourcepath         ../debug_targets
+source             t_rmdebug_app.cpp 
+source             d_rmdebugthreadasm2.cia
+
+OS_LAYER_SYSTEMINCLUDE_SYMBIAN
+library            euser.lib hal.lib
+
+uid                0x0 0x0
+capability         none
+
+always_build_as_arm
+pagedcode
+
+DEBUGGABLE
+
+SMPSAFE
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/debugsrv/runmodedebug/rmdebug_test/rm_debug/group/t_rmdebug_app6.mmp	Fri Aug 27 11:37:29 2010 +0300
@@ -0,0 +1,36 @@
+// Copyright (c) 2007-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+// Target application to be debugged
+// 
+//
+
+target             t_rmdebug_app6.exe
+targettype         exe
+
+sourcepath         ../debug_targets
+source             t_rmdebug_app.cpp 
+source             d_rmdebugthreadasm2.cia
+
+OS_LAYER_SYSTEMINCLUDE_SYMBIAN
+library            euser.lib hal.lib
+
+uid                0x0 0x0
+capability         none
+
+always_build_as_arm
+pagedcode
+
+DEBUGGABLE
+
+SMPSAFE
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/debugsrv/runmodedebug/rmdebug_test/rm_debug/group/t_rmdebug_app7.mmp	Fri Aug 27 11:37:29 2010 +0300
@@ -0,0 +1,36 @@
+// Copyright (c) 2007-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+// Target application to be debugged
+// 
+//
+
+target             t_rmdebug_app7.exe
+targettype         exe
+
+sourcepath         ../debug_targets
+source             t_rmdebug_app.cpp 
+source             d_rmdebugthreadasm2.cia
+
+OS_LAYER_SYSTEMINCLUDE_SYMBIAN
+library            euser.lib hal.lib
+
+uid                0x0 0x0
+capability         none
+
+always_build_as_arm
+pagedcode
+
+DEBUGGABLE
+
+SMPSAFE
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/debugsrv/runmodedebug/rmdebug_test/rm_debug/group/t_rmdebug_app8.mmp	Fri Aug 27 11:37:29 2010 +0300
@@ -0,0 +1,36 @@
+// Copyright (c) 2007-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+// Target application to be debugged
+// 
+//
+
+target             t_rmdebug_app8.exe
+targettype         exe
+
+sourcepath         ../debug_targets
+source             t_rmdebug_app.cpp 
+source             d_rmdebugthreadasm2.cia
+
+OS_LAYER_SYSTEMINCLUDE_SYMBIAN
+library            euser.lib hal.lib
+
+uid                0x0 0x0
+capability         none
+
+always_build_as_arm
+pagedcode
+
+DEBUGGABLE
+
+SMPSAFE
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/debugsrv/runmodedebug/rmdebug_test/rm_debug/group/t_rmdebug_app9.mmp	Fri Aug 27 11:37:29 2010 +0300
@@ -0,0 +1,36 @@
+// Copyright (c) 2007-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+// Target application to be debugged
+// 
+//
+
+target             t_rmdebug_app9.exe
+targettype         exe
+
+sourcepath         ../debug_targets
+source             t_rmdebug_app.cpp 
+source             d_rmdebugthreadasm2.cia
+
+OS_LAYER_SYSTEMINCLUDE_SYMBIAN
+library            euser.lib hal.lib
+
+uid                0x0 0x0
+capability         none
+
+always_build_as_arm
+pagedcode
+
+DEBUGGABLE
+
+SMPSAFE
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/debugsrv/runmodedebug/rmdebug_test/rm_debug/group/t_rmdebug_dll.mmp	Fri Aug 27 11:37:29 2010 +0300
@@ -0,0 +1,38 @@
+// Copyright (c) 2007-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+// 
+//
+
+ALWAYS_BUILD_AS_ARM
+
+target         t_rmdebug_dll.dll
+targettype     dll
+
+DEFFILE        ../../~/t_rmdebug_dll.def
+
+sourcepath	   	../debug_targets
+
+source        	t_rmdebug_dll.cpp 
+
+library		euser.lib
+
+OS_LAYER_SYSTEMINCLUDE_SYMBIAN
+
+capability PowerMgmt AllFiles ReadUserData
+
+UID            0x0 0x0
+SECUREID       0x0
+VENDORID       0x70000001
+
+SMPSAFE
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/debugsrv/runmodedebug/rmdebug_test/rm_debug/group/t_rmdebug_multi_agent.mmp	Fri Aug 27 11:37:29 2010 +0300
@@ -0,0 +1,41 @@
+// Copyright (c) 2006-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+// Application that tests the ability of the run mode debug component 
+// to debug multiple targets 
+// 
+//
+
+targettype     exe
+target         t_rmdebug_multi_agent.exe
+
+library		euser.lib hal.lib
+
+OS_LAYER_SYSTEMINCLUDE_SYMBIAN
+
+userinclude    ../debug_targets
+userinclude    ../common
+userinclude    ../multi_agent_tests
+
+sourcepath	   ../multi_agent_tests
+source         t_multi_agent.cpp t_agent_eventhandler.cpp 
+
+UID            0x0 0x4321bbbc
+SECUREID       0x1234aaab
+VENDORID       0x70000001
+
+DEBUGGABLE
+
+macro NO_DEBUGTOKEN
+
+SMPSAFE
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/debugsrv/runmodedebug/rmdebug_test/rm_debug/group/t_rmdebug_multi_target.mmp	Fri Aug 27 11:37:29 2010 +0300
@@ -0,0 +1,46 @@
+// Copyright (c) 2006-2010 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+// Application that tests the ability of the run mode debug component 
+// to debug several targets
+// 
+//
+
+// This is an RTest configured to run on Sirocco, hence the testexecuteutils linked in lib below.
+
+ALWAYS_BUILD_AS_ARM
+
+targettype     exe
+target         t_rmdebug_multi_target.exe
+
+library		euser.lib hal.lib
+library		testexecuteutils.lib // for Sirocco
+
+OS_LAYER_SYSTEMINCLUDE_SYMBIAN
+
+userinclude    ../debug_targets
+userinclude    ../common
+userinclude    ../multi_target_tests
+
+sourcepath	   ../multi_target_tests
+source         t_multi_target.cpp 
+
+UID            0x0 0x4321bbbc
+SECUREID       0x1234aaab
+VENDORID       0x70000001
+
+DEBUGGABLE
+
+macro NO_DEBUGTOKEN
+
+SMPSAFE
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/debugsrv/runmodedebug/rmdebug_test/rm_debug/group/t_rmdebug_performance_allcapstoken.mmp	Fri Aug 27 11:37:29 2010 +0300
@@ -0,0 +1,36 @@
+// Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+// 
+//
+
+ALWAYS_BUILD_AS_ARM
+
+target         OEMDebug_102831E5.exe
+targettype     exe
+
+sourcepath	   	../performance_test
+
+source        	t_rmdebug_performance_oemtoken.cpp 
+
+library		euser.lib
+
+OS_LAYER_SYSTEMINCLUDE_SYMBIAN
+
+capability All
+
+UID            0x0 0x0
+SECUREID       0x0
+VENDORID       0x70000001
+
+SMPSAFE
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/debugsrv/runmodedebug/rmdebug_test/rm_debug/group/t_rmdebug_security0.mmp	Fri Aug 27 11:37:29 2010 +0300
@@ -0,0 +1,36 @@
+// Copyright (c) 2006-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+// 
+//
+
+ALWAYS_BUILD_AS_ARM
+
+target         t_rmdebug_security0.exe
+targettype     exe
+
+sourcepath	   	../debug_targets
+source        	t_rmdebug_security.cpp 
+
+library		euser.lib hal.lib
+               
+SYMBIAN_BASE_SYSTEMINCLUDE(nkern)
+OS_LAYER_SYSTEMINCLUDE_SYMBIAN
+
+UID            0x100039CE 0xbaaaf00d
+SECUREID       0x101F7159
+VENDORID       0x70000001
+
+DEBUGGABLE
+
+SMPSAFE
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/debugsrv/runmodedebug/rmdebug_test/rm_debug/group/t_rmdebug_security1.mmp	Fri Aug 27 11:37:29 2010 +0300
@@ -0,0 +1,35 @@
+// Copyright (c) 2006-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+// 
+//
+
+ALWAYS_BUILD_AS_ARM
+
+target         t_rmdebug_security1.exe
+targettype     exe
+
+sourcepath	   	../debug_targets
+source        	t_rmdebug_security.cpp 
+
+library		euser.lib hal.lib
+               
+SYMBIAN_BASE_SYSTEMINCLUDE(nkern)
+OS_LAYER_SYSTEMINCLUDE_SYMBIAN
+
+UID            0x100039CE 0xdeadbaaa
+SECUREID       0x101F7159
+VENDORID       0x70000001
+
+
+SMPSAFE
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/debugsrv/runmodedebug/rmdebug_test/rm_debug/group/t_rmdebug_security2.mmp	Fri Aug 27 11:37:29 2010 +0300
@@ -0,0 +1,37 @@
+// Copyright (c) 2006-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+// 
+//
+
+ALWAYS_BUILD_AS_ARM
+
+target         t_rmdebug_security2.exe
+targettype     exe
+
+sourcepath	   	../debug_targets
+source        	t_rmdebug_security.cpp 
+
+library		euser.lib hal.lib
+               
+SYMBIAN_BASE_SYSTEMINCLUDE(nkern)
+OS_LAYER_SYSTEMINCLUDE_SYMBIAN
+
+capability AllFiles
+
+UID            0x100039CE 0xdeadbaaa
+SECUREID       0x101F7159
+VENDORID       0x70000001
+
+
+SMPSAFE
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/debugsrv/runmodedebug/rmdebug_test/rm_debug/group/t_rmdebug_security3.mmp	Fri Aug 27 11:37:29 2010 +0300
@@ -0,0 +1,37 @@
+// Copyright (c) 2006-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+// 
+//
+
+ALWAYS_BUILD_AS_ARM
+
+target         t_rmdebug_security3.exe
+targettype     exe
+
+sourcepath	   	../debug_targets
+source        	t_rmdebug_security.cpp 
+
+library		euser.lib hal.lib
+               
+SYMBIAN_BASE_SYSTEMINCLUDE(nkern)
+OS_LAYER_SYSTEMINCLUDE_SYMBIAN
+
+capability TCB AllFiles NetworkControl
+
+UID            0x100039CE 0xdeadbaaa
+SECUREID       0x101F7159
+VENDORID       0x70000001
+
+
+SMPSAFE
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/debugsrv/runmodedebug/rmdebug_test/rm_debug/group/t_rmdebug_target_launcher.mmp	Fri Aug 27 11:37:29 2010 +0300
@@ -0,0 +1,38 @@
+// Copyright (c) 2006-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+// Application that test the ability of the run mode debug component 
+// to handle several target applications
+// 
+//
+
+target         t_rmdebug_target_launcher.exe
+targettype     exe
+
+library		     euser.lib
+
+OS_LAYER_SYSTEMINCLUDE_SYMBIAN
+
+userinclude    ../common
+sourcepath	   ../common
+source         t_target_launcher.cpp 
+
+UID            0x0 0x4321bbbd
+SECUREID       0x1234aaac
+VENDORID       0x70000001
+
+DEBUGGABLE
+
+macro NO_DEBUGTOKEN
+
+SMPSAFE
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/debugsrv/runmodedebug/rmdebug_test/rm_debug/group/t_rmdebug_tests.iby	Fri Aug 27 11:37:29 2010 +0300
@@ -0,0 +1,63 @@
+// Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+// Run Mode Debug Tests ROM include file
+
+
+file=ABI_DIR\BUILD_DIR\t_rmdebug_app.exe	Sys\Bin\t_rmdebug_app.exe
+file=ABI_DIR\BUILD_DIR\t_rmdebug_app1.exe	Sys\Bin\t_rmdebug_app1.exe
+file=ABI_DIR\BUILD_DIR\t_rmdebug_app2.exe	Sys\Bin\t_rmdebug_app2.exe
+file=ABI_DIR\BUILD_DIR\t_rmdebug_app3.exe	Sys\Bin\t_rmdebug_app3.exe
+file=ABI_DIR\BUILD_DIR\t_rmdebug_app4.exe	Sys\Bin\t_rmdebug_app4.exe
+file=ABI_DIR\BUILD_DIR\t_rmdebug_app5.exe	Sys\Bin\t_rmdebug_app5.exe
+file=ABI_DIR\BUILD_DIR\t_rmdebug_app6.exe	Sys\Bin\t_rmdebug_app6.exe
+file=ABI_DIR\BUILD_DIR\t_rmdebug_app7.exe	Sys\Bin\t_rmdebug_app7.exe
+file=ABI_DIR\BUILD_DIR\t_rmdebug_app8.exe	Sys\Bin\t_rmdebug_app8.exe
+file=ABI_DIR\BUILD_DIR\t_rmdebug_app9.exe	Sys\Bin\t_rmdebug_app9.exe
+file=ABI_DIR\BUILD_DIR\t_rmdebug_app10.exe	Sys\Bin\t_rmdebug_app10.exe
+
+file=ABI_DIR\BUILD_DIR\t_rmdebug_dll.dll	Sys\Bin\t_rmdebug_dll.dll
+
+file=ABI_DIR\BUILD_DIR\t_rmdebug_security0.exe Sys\Bin\t_rmdebug_security0.exe
+file=ABI_DIR\BUILD_DIR\t_rmdebug_security1.exe Sys\Bin\t_rmdebug_security1.exe
+file=ABI_DIR\BUILD_DIR\t_rmdebug_security2.exe Sys\Bin\t_rmdebug_security2.exe
+file=ABI_DIR\BUILD_DIR\t_rmdebug_security3.exe Sys\Bin\t_rmdebug_security3.exe
+
+// This script wraps RTests as TEF3 tests.
+data=DATAZ_\scripts\tef_execute_rtests.script		scripts\tef_execute_rtests.script
+
+
+//No token required
+file=ABI_DIR\BUILD_DIR\t_rmdebug2.exe	Sys\Bin\t_rmdebug2.exe
+
+//SOMECAPS_DEBUGTOKEN
+file=ABI_DIR\BUILD_DIR\t_rmdebug2_oem.exe 		Sys\Bin\t_rmdebug2_oem.exe
+file=ABI_DIR\BUILD_DIR\OEMDebug_F123ABCD.exe Sys\Bin\OEMDebug_F123ABCD.exe
+
+//FEWCAPS_DEBUGTOKEN
+file=ABI_DIR\BUILD_DIR\t_rmdebug2_oem2.exe 		Sys\Bin\t_rmdebug2_oem2.exe
+file=ABI_DIR\BUILD_DIR\OEMDebug_F1234567.exe	Sys\Bin\OEMDebug_F1234567.exe
+
+//ALLCAPS_DEBUGTOKEN
+file=ABI_DIR\BUILD_DIR\t_rmdebug2_allcaps.exe 		Sys\Bin\t_rmdebug2_allcaps.exe
+file=ABI_DIR\BUILD_DIR\OEMDebug_F123ABCE.exe Sys\Bin\OEMDebug_F123ABCE.exe
+
+file=ABI_DIR\BUILD_DIR\t_rmdebug_target_launcher.exe	Sys\Bin\t_rmdebug_target_launcher.exe
+file=ABI_DIR\BUILD_DIR\t_rmdebug_multi_target.exe Sys\Bin\t_rmdebug_multi_target.exe
+
+file=ABI_DIR\BUILD_DIR\t_rmdebug_multi_agent.exe Sys\Bin\t_rmdebug_multi_agent.exe
+file=ABI_DIR\BUILD_DIR\t_multi_agent_launcher.exe Sys\Bin\t_multi_agent_launcher.exe
+
+//PERFORMANCE TEST DEBUGTOKEN
+file=ABI_DIR\BUILD_DIR\OEMDebug_102831E5.exe Sys\Bin\OEMDebug_102831E5.exe
+file=ABI_DIR\BUILD_DIR\t_performance_test.exe Sys\Bin\t_performance_test.exe
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/debugsrv/runmodedebug/rmdebug_test/rm_debug/multi_agent_tests/t_agent_eventhandler.cpp	Fri Aug 27 11:37:29 2010 +0300
@@ -0,0 +1,124 @@
+// Copyright (c) 2007-2010 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+// Implements the handling of run mode events for a particular target executable
+// 
+
+#include <e32base.h>
+#include <e32property.h>
+#include <e32test.h>
+
+#include "t_rmdebug_app.h"
+#include "t_agent_eventhandler.h"
+#include "t_multi_agent.h"
+#include "t_debug_logging.h" 
+
+using namespace Debug;
+
+CAgentAsyncEvent::CAgentAsyncEvent(CMultiAgent& aDriver, const TDesC& aExeName, const TDesC& aExeConfig):
+	CActive(EPriorityStandard), iDriver(aDriver)
+	{
+	}
+
+CAgentAsyncEvent* CAgentAsyncEvent::NewLC(CMultiAgent& aDriver, const TDesC& aExeName, const TDesC& aExeConfig)
+	{
+	CAgentAsyncEvent* self = new(ELeave) CAgentAsyncEvent(aDriver, aExeName, aExeConfig);
+	CleanupStack::PushL(self);
+	self->ConstructL(aExeName, aExeConfig);
+	return self;
+	}
+
+CAgentAsyncEvent* CAgentAsyncEvent::NewL(CMultiAgent& aDriver, const TDesC& aExeName, const TDesC& aExeConfig)
+	{
+	CAgentAsyncEvent* self = CAgentAsyncEvent::NewLC(aDriver, aExeName, aExeConfig);
+	CleanupStack::Pop(); // self
+	return self;
+	}
+
+void CAgentAsyncEvent::ConstructL(const TDesC& aExeName, const TDesC& aExeConfig)
+	{
+	iExeName.CreateL(aExeName);
+	iExeConfig.CreateL(aExeConfig);
+	CActiveScheduler::Add(this);
+	}
+
+CAgentAsyncEvent::~CAgentAsyncEvent()
+	{
+	LOG_MSG2("~CAgentAsyncEvent(), this = 0x%08x", this);
+
+	iSEventInfo.iEventInfoBuf.Delete(0, sizeof(TEventInfo));
+	iExeName.Close();
+	iExeConfig.Close();
+	iProc.Close();
+	Cancel(); // Cancel any request, if outstanding
+	}
+
+/*
+ * Issue request to DSS and notify the active scheduler
+ */
+void CAgentAsyncEvent::Watch()
+	{
+	LOG_MSG2("ENTER: CAgentAsyncEvent::Watch, this = 0x%08x", this);
+	iDriver.DebugDriver().GetEvent(GetExecutable(), iStatus, iSEventInfo.iEventInfoBuf);
+
+	if (!IsActive())
+		{
+		LOG_MSG("CAgentAsyncEvent::Watch(): SetActive()");
+		SetActive();
+		}
+
+	LOG_MSG("EXIT: CAgentAsyncEvent::Watch");
+	}
+
+void CAgentAsyncEvent::RunL()
+	{
+	LOG_MSG4("ENTER: CAgentAsyncEvent::RunL iDebugType=%d, iStatus.Int() %d, this 0x%x08", 
+			 iSEventInfo.iEventInfo.iEventType, iStatus.Int(), this);
+	
+    LOG_MSG2("%S", &TPtr8((TUint8*)GetExecutable().Ptr(), 2*GetExecutable().Length(), 2*GetExecutable().Length()));	
+	iDriver.HandleEvent(iSEventInfo.iEventInfo);
+
+	LOG_MSG2("iDriver.GetNumApps() %d: ", iDriver.GetNumApps());
+	LOG_MSG2("iDriver.iLaunchCompleted  %d: ", iDriver.GetLaunchCompleted());
+
+	if (iDriver.GetLaunchCompleted() < iDriver.GetNumApps())
+		{
+		// Do not call Watch() if target has run to completion but test is still on going
+		if (iSEventInfo.iEventInfo.iEventType != EEventsRemoveProcess)
+			{
+			LOG_MSG("CAgentAsyncEvent::RunL Setting Watch()");
+			Watch();
+			}
+		}
+	else
+		{
+		// Stop event handling for all targets
+		LOG_MSG("CAgentAsyncEvent::RunL CActiveScheduler::Stop() & Cancel");
+		CActiveScheduler::Stop();
+		}
+
+	LOG_MSG2("EXIT: CAgentAsyncEvent::RunL", KNullDesC);
+	}
+
+void CAgentAsyncEvent::DoCancel()
+	{
+	LOG_MSG("CAgentAsyncEvent::DoCancel");
+	}
+
+TInt CAgentAsyncEvent::RunError(TInt aError)
+	{
+	LOG_MSG3(" RunL() has left with error %d, this 0x%08X", aError, this);
+	return aError; 
+	// Can we handle this error? Not at the moment!
+	}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/debugsrv/runmodedebug/rmdebug_test/rm_debug/multi_agent_tests/t_agent_eventhandler.h	Fri Aug 27 11:37:29 2010 +0300
@@ -0,0 +1,90 @@
+// Copyright (c) 2007-2010 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+// Definitions for event handling via the DSS and target specific information
+//
+//
+
+#ifndef RMDEBUG_AGENT_EVENTHANDLER_H
+#define RMDEBUG_AGENT_EVENTHANDLER_H
+
+#include "t_multi_agent.h"
+
+using namespace Debug;
+
+class CMultiAgent;
+
+/**
+ Class for gathering event data from the run-mode driver
+ */
+class TAgentEventInfo
+{
+public:
+	TAgentEventInfo() : 
+	iEventInfoBuf((TUint8*)&iEventInfo, sizeof(TEventInfo), sizeof(TEventInfo))
+	{ 	
+	}
+
+public:
+	// This is the underlying class for event interaction with the Run Mode debug API 
+	TEventInfo			iEventInfo;
+	
+	// A convenience handle for iEventInfo used across the Debug::GetEvent() method 
+	TPtr8				iEventInfoBuf;
+};
+
+/**
+  Active object class used to trap asynchronous events
+  Also, contains target specific parameters
+  */
+class CAgentAsyncEvent : public CActive
+	{
+public:
+	// Close buffers and Cancel and destroy
+	~CAgentAsyncEvent();	
+
+	// Two-phased constructor
+	static CAgentAsyncEvent* NewLC(CMultiAgent& aDriver, const TDesC& aExeName, const TDesC& aExeConfig);
+
+	// Two-phased constructor
+	static CAgentAsyncEvent* NewL(CMultiAgent& aDriver, const TDesC& aExeName, const TDesC& aExeConfig);
+
+	// set up ASP and issue another request	
+	void Watch();
+
+	TDesC& GetExecutable() { return iExeName; }
+ 	TDesC& GetExeConfig() { return iExeConfig; }
+	RProcess& GetProcHandle() { return iProc; }
+
+protected:
+	// from CActive
+	virtual void RunL();
+	virtual void DoCancel();
+	virtual TInt RunError(TInt aError);
+
+private:
+	CAgentAsyncEvent(CMultiAgent& aDriver, const TDesC& aExeName, const TDesC& aExeConfig);
+	void ConstructL(const TDesC& aExeName, const TDesC& aExeConfig);
+
+private:
+	RBuf iExeName;
+	RBuf iExeConfig;
+	RProcess iProc;
+
+	CMultiAgent& iDriver;
+	TAgentEventInfo iSEventInfo;
+	};
+
+#endif // RMDEBUG_AGENT_EVENTHANDLER_H
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/debugsrv/runmodedebug/rmdebug_test/rm_debug/multi_agent_tests/t_multi_agent.cpp	Fri Aug 27 11:37:29 2010 +0300
@@ -0,0 +1,434 @@
+// Copyright (c) 2007-2010 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+// Tests the run mode debug device component by launching multiple targets 
+// on different CPUs. On a single core the targets run on the same CPU.  
+//
+
+#include <e32base.h>
+#include <e32property.h>
+#include <hal.h>
+#include <e32test.h>
+#include <e32def.h>
+#include <e32svr.h>
+
+
+#include "t_rmdebug_app.h"
+#include "t_multi_agent.h"
+#include "t_agent_eventhandler.h"
+#include "t_debug_logging.h"
+
+const TVersion securityServerVersion(0,1,1);
+
+/**
+ * First phase constructor
+ */
+CMultiAgent* CMultiAgent::NewL()
+	{
+	CMultiAgent* self = new(ELeave) CMultiAgent();
+	self->ConstructL();
+	return self;
+	}
+
+/**
+  * Destructor
+  */
+CMultiAgent::~CMultiAgent()
+	{
+	LOG_MSG("~CMultiTargetAgent\n");
+	iServSession.Close();
+	}
+
+/**
+ * Constructor
+ */
+CMultiAgent::CMultiAgent() 
+	{
+	}
+
+/**
+ * Second phase constructor
+ */
+void CMultiAgent::ConstructL()
+	{
+	}
+
+/**
+  Parse the command line, set agent cpu affinity and call main test function
+  */
+void CMultiAgent::ClientAppL()
+	{
+	LOG_MSG("ENTER: CMultiTargetAgent::ClientAppL"); 
+
+	iNumApps = KNumApps;
+	iAgentCpuNo = KAgentCpu;
+	iTargetNameOffset = KTargetOffset;
+
+	TInt argc = User::CommandLineLength();
+	HBufC* commandLine = NULL;
+	LOG_MSG2(">Launcher Process() argc=%d", argc);
+	
+	if(argc)
+		{
+		commandLine = HBufC::NewLC(argc);
+		TPtr commandLineBuffer = commandLine->Des();
+		User::CommandLine(commandLineBuffer);
+
+		RBuf printCommandLine;
+		CleanupClosePushL(printCommandLine);
+		printCommandLine.CreateL(commandLine->Des().Length());
+		printCommandLine.Copy(commandLine->Des());
+		printCommandLine.Collapse();
+		LOG_MSG2(">command line = %S", &printCommandLine );
+		CleanupStack::PopAndDestroy( &printCommandLine );
+
+		// create a lexer and read through the command line
+		TLex lex(*commandLine);
+	
+		while (!lex.Eos())
+		{
+			// only look for options with first character '-'
+			if (lex.Get() == '-')
+			{
+			TChar arg = lex.Get();
+			
+				switch ( arg )
+				{
+				case 'n':
+					lex.Val( iNumApps );
+					LOG_MSG2("parsed numApps as %d", iNumApps); 
+					break;
+		
+				case 'a':
+					lex.Val( iAgentCpuNo );
+					LOG_MSG2("parsed agentCpuNo as %d", iAgentCpuNo);                        
+					break;
+
+				case 'o':
+					lex.Val( iTargetNameOffset );
+					LOG_MSG2("parsed iTargetNameOffset as %d", iTargetNameOffset);        
+					break;
+
+				default:
+					LOG_MSG("Bad argument from user"); 
+					break;                 
+				}
+			}
+		}
+	}
+	// Create active scheduler (to run active objects)
+	CActiveScheduler* scheduler = new (ELeave) CActiveScheduler();
+	CleanupStack::PushL(scheduler);
+	CActiveScheduler::Install(scheduler);
+	
+	if (iAgentCpuNo)
+		{
+		LOG_MSG2("CMultiAgent::ClientAppL() - setting agent to cpu %d", iAgentCpuNo);
+		UserSvr::HalFunction(EHalGroupKernel, EKernelHalLockThreadToCpu, (TAny *)iAgentCpuNo, 0);
+		}
+
+	TInt err = iServSession.Connect(securityServerVersion);
+	
+	if (err != KErrNone)
+		{
+		User::Panic(_L("Can't open server session"), err);
+		}
+
+	StartTest();
+
+	// Note: below is a workaround to overcome an issue with RTest server crashing 
+	// when writing to the windows console from different agents (on different CPUs 
+	// at the same time). To overcome this we signal the launcher using a global 
+	// semaphore to indicate a RTest complete instead
+	RSemaphore launchSemaphore;
+	CleanupClosePushL(launchSemaphore);
+            
+	TFindSemaphore launchSemFinder(KLaunchSemaphoreSearchString);
+	TFullName semaphoreResult;
+	TInt ret = launchSemFinder.Next(semaphoreResult);
+	LOG_MSG3( "> Find Launch Semaphote.Next ret=%d, %lS", ret, &semaphoreResult);
+         
+	ret = launchSemaphore.OpenGlobal(semaphoreResult);
+	LOG_MSG2( ">OpenGlobal semaphore ret=%d", ret );         
+    
+	LOG_MSG( ">Signalling semaphore" );
+	launchSemaphore.Signal();
+	CleanupStack::PopAndDestroy(&launchSemaphore); // launchSemaphore
+
+	// Delete active scheduler
+	CleanupStack::PopAndDestroy(scheduler);
+
+	if (commandLine)
+	CleanupStack::PopAndDestroy(commandLine);
+	
+	LOG_MSG( "EXIT: CMultiTargetAgent::ClientAppL"); 
+	}
+
+/**
+  Launch a process
+  @param aProcess the RProcess object used to create the process
+  @param aFileName file name of the executable used to create the process
+  @return KErrNone on success, or one of the other system wide error codes
+  */
+TInt CMultiAgent::LaunchProcess(RProcess& aProcess, const TDesC& aExeName, const TDesC& aCommandLine)    
+	{
+	LOG_MSG( "ENTER: CMultiAgent::LaunchProcess");
+    LOG_MSG2("%S", &TPtr8((TUint8*)aExeName.Ptr(), 2*aExeName.Length(), 2*aExeName.Length()));	
+	
+	// wait for 0.5 seconds due to issue with creating several processes in smp quickly
+	User::After(500000);
+	
+	TInt err = aProcess.Create( aExeName, aCommandLine );
+	LOG_MSG2( "CMultiAgent::LaunchProcess, aProcess.Create err = %d", err); 
+
+	// check that there was no error raised
+	if (err != KErrNone)
+		return err;
+	
+	// rendezvous with process
+	TRequestStatus status = KRequestPending;
+	aProcess.Rendezvous(status);
+
+	if (KRequestPending != status.Int())
+		{
+		// startup failed so kill the process
+		LOG_MSG2( "> RProcess Rendezvous() failed with %d. Killing process", status.Int() );
+		aProcess.Kill(KErrNone);
+		LOG_MSG( "EXIT: CMultiAgent::LaunchProcess");
+		return status.Int();
+		}
+	else
+		{
+		// start the test target
+		aProcess.Resume();
+		User::WaitForRequest(status);
+	
+		LOG_MSG2( "> CMultiAgent::LaunchProcess: RProcess Resume() Rendezvous successful %d: ", status.Int() );
+
+		if(KErrNone != status.Int())
+			{
+			LOG_MSG2( "> RProcess Resume() failed with %d. Killing process", status.Int() );
+			aProcess.Kill(KErrNone);
+			}
+
+		LOG_MSG( "EXIT: CMultiAgent::LaunchProcess");
+		return status.Int();
+		}
+	}
+
+/**
+  Handle Event
+  @param aEventInfo object containing event information from the DSS 
+  */
+void CMultiAgent::HandleEvent(TEventInfo& aEventInfo)
+	{
+	LOG_MSG( "ENTER: CMultiAgent::HandleEvent" ); 
+	TInt ret = KErrNone;
+	const TInt idValid = 1;
+	
+	switch ( aEventInfo.iEventType )
+		{
+		case EEventsAddProcess:
+			{
+			LOG_MSG(">> EEventsAddProcess");                        
+			TPtrC8 exeNamePtr8(aEventInfo.iAddProcessInfo.iFileName, aEventInfo.iAddProcessInfo.iFileNameLength);
+	
+			RBuf8 exeName8;
+			CleanupClosePushL(exeName8);
+			exeName8.CreateL(exeNamePtr8);
+			LOG_MSG2("From event: exeName8=%S", &exeName8);
+			CleanupStack::PopAndDestroy(&exeName8);
+			LOG_MSG("Testing if event process id is valid");
+
+			LOG_MSG2("Got aEventInfo.iProcessId=%d", I64LOW( aEventInfo.iProcessId));
+			__ASSERT_ALWAYS((aEventInfo.iProcessIdValid==idValid), User::Panic(_L("ProcessId Invalid"), aEventInfo.iProcessIdValid));
+	
+			RProcess targetProc;
+			ret = targetProc.Open(TProcessId(aEventInfo.iProcessId));
+			LOG_MSG2("RProcess open ret=%d", ret);
+			targetProc.Close();
+
+			__ASSERT_ALWAYS((ret == KErrNone), User::Panic(_L("ProcessId Invalid"), aEventInfo.iProcessIdValid));
+			break;
+			}
+	
+		case EEventsStartThread:
+			{
+			LOG_MSG(">> EEventsStartThread");                
+			TPtrC8 exeNamePtr8(aEventInfo.iStartThreadInfo.iFileName, aEventInfo.iStartThreadInfo.iFileNameLength);
+			RBuf8 exe8Name;
+			CleanupClosePushL(exe8Name);
+			exe8Name.CreateL(exeNamePtr8);
+			LOG_MSG2("From event: exeName8=%S", &exe8Name);
+			CleanupStack::PopAndDestroy(&exe8Name);
+	
+			LOG_MSG("Testing if event process id is valid" );
+
+			__ASSERT_ALWAYS((aEventInfo.iProcessIdValid==idValid), User::Panic(_L("ProcessId Invalid"), aEventInfo.iProcessIdValid));
+
+			LOG_MSG2("Got aEventInfo.iProcessId=%d", I64LOW(aEventInfo.iProcessId));
+
+			LOG_MSG("Testing if event thread id is valid");
+
+			__ASSERT_ALWAYS((aEventInfo.iThreadIdValid==idValid), User::Panic(_L("ThreadId Invalid"), aEventInfo.iThreadIdValid));
+
+			LOG_MSG2("Got aEventInfo.iThreadId=%d", I64LOW(aEventInfo.iThreadId));
+			break;                    
+			}                       
+
+		case EEventsUserTrace:
+			{
+			LOG_MSG(">> EEventsUserTrace");  
+			break;
+			}
+
+		case EEventsRemoveProcess:
+			{
+			LOG_MSG( ">> EEventsRemoveProcess");                        
+			iLaunchCompleted++; 
+			break;
+			}
+	
+		default:   
+			{
+			LOG_MSG( ">> Unknown event - probably due to DSS busy?");
+			break;
+			}	
+		}
+ 	 
+	LOG_MSG("EXIT: CMultiAgent::HandleEvent"); 
+	}
+
+/**
+ * Main test function which launches several targets and stresses the DSS 
+ */
+TInt CMultiAgent::StartTest()
+	{
+	LOG_MSG("ENTER: CMultiTargetAgent::StartTest");
+
+	for( TInt i = 0; i < iNumApps; i++ )
+		{
+		RBuf targetName;
+		RBuf launcherOptions;
+
+		CleanupClosePushL(targetName); 
+		CleanupClosePushL(launcherOptions); 
+
+		targetName.CreateL( KTargetExe().Length() + 2 );
+		targetName.Format( KTargetExe(), i + iTargetNameOffset + 1 );
+
+		LOG_MSG2("App %d: ", i+1);
+		LOG_MSG2("%S", &TPtr8((TUint8*)targetName.Ptr(), 2*targetName.Length(), 2*targetName.Length()));	
+
+		launcherOptions.CreateL( KTargetOptions().Length() + 2 );
+		launcherOptions.Format( KTargetOptions(), (TUint)ENormalExit, (i+1) );
+
+		LOG_MSG( "AppOptions : ");
+		LOG_MSG2("%S", &TPtr8((TUint8*)launcherOptions.Ptr(), 2*launcherOptions.Length(), 2*launcherOptions.Length()));	
+		
+		// Add each test target to array
+		iTargetList.AppendL(CAgentAsyncEvent::NewL(*this, targetName, launcherOptions));
+		CleanupStack::PopAndDestroy(2, &targetName );
+		}
+	
+	iLaunchCompleted = 0;
+	TInt err = KErrNone;
+		
+	for (TInt i = 0; i < iNumApps; i++)
+		{
+		// Attach to process non-passively
+		LOG_MSG2( ">AttachExecutable app %d ", i + iTargetNameOffset + 1 );
+		LOG_MSG2("%S", &TPtr8((TUint8*)iTargetList[i]->GetExecutable().Ptr(), 2*iTargetList[i]->GetExecutable().Length(), 
+					2*iTargetList[i]->GetExecutable().Length()));
+
+		err = iServSession.AttachExecutable( iTargetList[i]->GetExecutable(), EFalse);
+		__ASSERT_ALWAYS((err == KErrNone), User::Panic(_L("DSS Attach failed"), err));
+
+		// Continue on interested event actions
+		LOG_MSG2( ">SetEventAction app %d,  EEventsStartThread EAcionContinue", i + iTargetNameOffset + 1);
+
+		err = iServSession.SetEventAction( iTargetList[i]->GetExecutable(), EEventsStartThread, EActionContinue);
+		__ASSERT_ALWAYS((err==KErrNone), User::Panic(_L("SetEventAction Error"), err));
+	
+		LOG_MSG2(">SetEventAction app %d,  EEventsAddProcess EActionContinue", i + iTargetNameOffset + 1);
+		err = iServSession.SetEventAction( iTargetList[i]->GetExecutable(), EEventsAddProcess, EActionContinue);
+		__ASSERT_ALWAYS((err==KErrNone), User::Panic(_L("SetEventAction Error"), err));
+
+		LOG_MSG2(">SetEventAction app %d,  EEventsUserTrace EActionContinue", i + iTargetNameOffset + 1);
+		err = iServSession.SetEventAction( iTargetList[i]->GetExecutable(), EEventsUserTrace, EActionContinue);
+		__ASSERT_ALWAYS((err==KErrNone), User::Panic(_L("SetEventAction Error"), err));
+	
+		LOG_MSG2(">SetEventAction app %d,  EEventsRemoveProcess EActionContinue", i + iTargetNameOffset + 1);
+		err = iServSession.SetEventAction( iTargetList[i]->GetExecutable(), EEventsRemoveProcess, EActionContinue);
+		__ASSERT_ALWAYS((err==KErrNone), User::Panic(_L("SetEventAction Error"), err));
+
+		// Add target object to active schedular
+		iTargetList[i]->Watch();
+		}
+
+	for (TInt i= 0; i< iNumApps; i++)
+		{
+		LOG_MSG( ">Calling LaunchProcess function");
+		err = LaunchProcess(iTargetList[i]->GetProcHandle(), iTargetList[i]->GetExecutable(), iTargetList[i]->GetExeConfig());
+		__ASSERT_ALWAYS((err==KErrNone), User::Panic(_L("LaunchProcess failed"), err));
+		}
+
+	LOG_MSG( ">CActiveScheduler::Start()");
+	CActiveScheduler::Start();
+
+	for (TInt i= 0; i < iNumApps; i++)
+		{
+		// Now detach again
+		LOG_MSG( "Before iServSession.DetachExecutable" );
+		err = iServSession.DetachExecutable(iTargetList[i]->GetExecutable());
+		__ASSERT_ALWAYS((err==KErrNone), User::Panic(_L("DetachExecutable failed"), err));
+		}
+	
+	// Free all the memory
+	iTargetList.ResetAndDestroy();
+	LOG_MSG( "EXIT: CMultiTargetAgent::StartTest" );
+
+	return KErrNone;
+	}
+
+/**
+  * Entry point for run mode debug driver test
+  */
+GLDEF_C TInt E32Main()
+	{
+	LOG_MSG( "ENTER: Multi_agent E32Main ");
+	__UHEAP_MARK;
+
+	TInt ret = KErrNone;
+	RProcess::Rendezvous(KErrNone);
+	
+	CTrapCleanup* trap = CTrapCleanup::New();
+		
+	if (!trap)
+		return KErrNoMemory;
+	
+	CMultiAgent *runModeAgent = CMultiAgent::NewL();
+
+	if (runModeAgent != NULL)
+		{
+		TRAP(ret,runModeAgent->ClientAppL());
+		LOG_MSG2( "ClientAppL returned %d", ret );
+		delete runModeAgent;
+		}
+
+	delete trap;
+	__UHEAP_MARKEND;
+	LOG_MSG( "EXIT: Multi_agent E32Main ");
+	return ret;
+	}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/debugsrv/runmodedebug/rmdebug_test/rm_debug/multi_agent_tests/t_multi_agent.h	Fri Aug 27 11:37:29 2010 +0300
@@ -0,0 +1,110 @@
+// Copyright (c) 2006-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+// Definitions for the run mode debug tests
+// 
+//
+
+/**
+ @file
+ @internalTechnology
+ @released
+*/
+
+#ifndef RMDEBUG_MULTI_AGENT_H
+#define RMDEBUG_MULTI_AGENT_H
+
+#include <u32hal.h>
+#include <f32file.h>
+#include <rm_debug_api.h>
+
+using namespace Debug;
+
+_LIT(KLaunchSemaphoreName, "t_rmdebug_launch_semaphore");
+_LIT(KLaunchSemaphoreSearchString, "t_rmdebug_launch_semaphore*");
+
+// Currently the targets are instances of t_rmdebug_app.exe
+_LIT(KTargetExe,"z:\\sys\\bin\\t_rmdebug_app%d.exe");
+
+_LIT(KTargetOptions,"-f%d -a%d");
+
+// If changing this, make sure there are enough apps built/in the rom 
+const TInt KNumApps = 5;
+
+// Default CPU execution for Agent
+const TInt KAgentCpu = 0;
+
+// Workaround to ensure we have the same agent binary when running multiple agents
+const TInt KTargetOffset = 0;
+
+class CAgentAsyncEvent;
+
+/**
+  @Class CRunModeAgent
+  
+  The basic run mode agent
+  */
+class CMultiAgent : public CBase
+	{
+	public:
+	static CMultiAgent* NewL();
+	~CMultiAgent();
+	void ClientAppL();  
+	RSecuritySvrSession&  DebugDriver() { return iServSession; };	
+	void HandleEvent(TEventInfo& aSEventInfo);
+
+	public:
+	TInt GetLaunchCompleted() const { return iLaunchCompleted; }
+	TInt GetNumApps() const { return iNumApps; }
+	TInt GetTargetOffset() const { return iTargetNameOffset; }
+
+	private:
+	CMultiAgent();
+	void ConstructL();
+	TInt StartTest();
+	TInt LaunchProcess(RProcess& aProcess, const TDesC& aExeName, const TDesC& aCommandLine);
+	
+	private:
+
+	/**
+	 * CPU agent executes on; by default this is 0 
+	 */
+	TInt iAgentCpuNo;
+
+	/*
+	 * Offset for running multiple targets using the same agent
+	 */
+	TInt iTargetNameOffset;
+
+	/** 
+	 * Number of applications/targets per agent
+	 */
+	TInt iNumApps;
+
+	/**
+	 * Flag used for terminating the event handling for a target 
+	 */	
+	TInt iLaunchCompleted;
+
+	/*
+	 * Handle to DSS
+	 */
+	RSecuritySvrSession iServSession;
+	
+	/**
+	 * Array to target parameters required by the agent
+	 */	
+	RPointerArray<CAgentAsyncEvent> iTargetList;
+	};
+
+#endif // RMDEBUG_MULTI_AGENT_H
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/debugsrv/runmodedebug/rmdebug_test/rm_debug/multi_agent_tests/t_multi_agent_launcher.cpp	Fri Aug 27 11:37:29 2010 +0300
@@ -0,0 +1,229 @@
+// Copyright (c) 2007-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+// Helper app to launch debug targets
+//
+//
+
+#include "t_multi_agent_launcher.h"
+
+#include "t_debug_logging.h"
+
+/**
+ * Launch a process
+ * @param aProcess the RProcess object used for creating the process
+ * @param aExeName the name of the executable to run 
+ * @param aCommandLine command line parameters to pass when creating the process 
+ * @return KErrNone on success, or one of the other system wide error codes
+ */
+TInt LaunchProcess(RProcess& aProcess, TDesC& aExeName, TDesC& aCommandLine )    
+	{
+	LOG_MSG("ENTER: t_multi_agent_launcher: launchProcess"); 
+
+	LOG_MSG2("aExeName %S ", &TPtr8((TUint8*)aExeName.Ptr(), 2*aExeName.Length(), 2*aExeName.Length()));
+	LOG_MSG2("aCommandLine %S", &TPtr8((TUint8*)aCommandLine.Ptr(), 2*aCommandLine.Length(), 2*aCommandLine.Length()));
+
+	TInt err = aProcess.Create( aExeName, aCommandLine );
+	LOG_MSG2("t_multi_agent_launcher launchProcess, aProcess.Create err = %d", err); 
+
+	// check that there was no error raised
+	if(err != KErrNone)
+		{
+		return err;
+		}
+
+	// rendezvous with process
+	TRequestStatus status = KRequestPending;
+	aProcess.Rendezvous(status);
+
+	if(KRequestPending != status.Int())
+		{
+		// startup failed so kill the process
+		LOG_MSG2("t_multi_agent_launcher: launchProcess: RProcess Rendezvous() failed with %d. Killing process", status.Int());
+		aProcess.Kill(KErrNone);
+		return status.Int();
+		}
+	else
+		{
+		aProcess.Resume();
+		User::WaitForRequest(status);
+
+		LOG_MSG2("t_multi_agent_launcher: launchProcess: RProcess Resume() Rendezvous successful %d: ", status.Int());
+
+		if(KErrNone != status.Int())
+			{
+			LOG_MSG2("t_multi_agent_launcher: RProcess Resume() failed with %d. Killing process", status.Int());
+			aProcess.Kill(KErrNone);
+			}
+
+		LOG_MSG("EXIT: t_multi_agent_launcher launchProcess");
+		return status.Int();
+		}
+	}
+
+/**
+ * Read command line parameters and control the launching of the agents. 
+ */
+void MainL()
+	{	
+	LOG_MSG( "ENTER: t_multi_agent_launcher MainL()");
+
+	TInt ret = KErrNone;
+	TInt numAgents = KNumAgents;
+	TInt numTargets = KNumTargets;
+	TInt numTestRuns = KNumTestRuns;
+
+	TInt argc = User::CommandLineLength();
+	HBufC* commandLine = NULL;
+	LOG_MSG2("t_multi_agent_launcher: MainL(): argc=%d", argc);
+    
+	if(argc)
+		{
+		commandLine = HBufC::NewLC(argc);
+		TPtr commandLineBuffer = commandLine->Des();
+		User::CommandLine(commandLineBuffer);
+
+		RBuf printCommandLine;
+		CleanupClosePushL( printCommandLine );
+		printCommandLine.CreateL( commandLine->Des().Length() );
+		printCommandLine.Copy( commandLine->Des() );
+		printCommandLine.Collapse();
+		LOG_MSG2("t_multi_agent_launcher: command line = %S", &printCommandLine);
+		CleanupStack::PopAndDestroy( &printCommandLine );
+ 
+		// create a lexer and read through the command line
+		TLex lex(*commandLine);
+		while (!lex.Eos())
+			{
+			// only look for options with first character '-'
+			if (lex.Get() == '-')
+				{
+					TChar arg = lex.Get();
+					switch ( arg )
+						{
+						case 'n':
+							lex.Val( numAgents );
+							LOG_MSG2("t_multi_agent_launcher: parsed numAgents as %d", numAgents);
+							break;
+						case 'm':
+							lex.Val( numTargets );
+							LOG_MSG2("t_multi_agent_launcher: parsed numTargets as %d", numTargets);                        
+							break;  
+						case 't':
+							lex.Val( numTestRuns );
+							LOG_MSG2("t_multi_agent_launcher: parsed numTestRuns as %d", numTestRuns);                        
+							break;                    
+						default:
+							LOG_MSG("t_multi_agent_launcher: unknown argument ignoring it");
+							break;                 
+						}
+				}
+			}
+		}
+
+	// Note: below is a workaround to overcome an issue with RTest server crashing 
+	// when writing to the windows console from different agents (on different CPUs 
+	// at the same time). To overcome this we get signaled by the agents when they have 
+	// completed their tests so that we can do a RTest complete
+	RSemaphore launchSemaphore;
+	CleanupClosePushL(launchSemaphore);
+	ret = launchSemaphore.CreateGlobal(KLaunchSemaphoreName, 0);
+	LOG_MSG2( ">Target Launcher : RSemaphore.CreateGlobal ret %d", ret);
+	User::LeaveIfError( ret );
+
+	ret = launchSemaphore.OpenGlobal(KLaunchSemaphoreName);
+	LOG_MSG2( ">Target Launcher : RSemaphore.OpenGlobal ret %d", ret);
+	User::LeaveIfError( ret );
+
+	//Now launch the requested number of apps for the requested number of test runs
+	for( TInt j = 0; j < numTestRuns; j++ )
+		{ 
+			for( TInt i = 0; i < numAgents; i++ )  
+				{
+					RBuf targetName;
+					targetName.CleanupClosePushL();
+					targetName.CreateL(KAgentExe());
+
+					RProcess aProc;
+					CleanupClosePushL(aProc); 
+					RBuf launcherOptions;
+					CleanupClosePushL(launcherOptions);
+				    const TInt additionalWords = 2;	
+					launcherOptions.CreateL( KAgentOptions().Length() + additionalWords );
+		
+					// Apply offset: launcherOptions.Format( .., .., i * numTargets, ..)
+					// workaround to ensure we have the same binary for multiple agents. 
+					// e.g. So if offset = 0, agent attaches to app1, app2, app3, app4, app5
+					// if offset = 5, agent attached to app6, app7, app8, app9, app10 etc.
+					// Note: apps need to be in rom otherwise the agent will fail on an assert 
+					// (with KErrNotFound)
+					launcherOptions.Format( KAgentOptions(), (TUint)numTargets, i * numTargets, 0);
+			
+					ret = LaunchProcess( aProc, targetName, launcherOptions );	
+					CleanupStack::PopAndDestroy(3,&targetName);
+					User::LeaveIfError(ret);
+				}
+		}
+
+	// Wait for all agents to do their testing before checking the semaphore
+	User::After(12000000);
+
+	LOG_MSG( ">Target Launcher:  Semaphore wait");
+
+	for (TInt i = 0; i < numAgents; i ++)
+		{
+		//We need this delay just in case an agent crashes and never signals the sem
+		ret = launchSemaphore.Wait(100000);
+		if( ret != KErrNone )
+			{
+			LOG_MSG3("launchSemaphore.Wait ret %d for agent %d", ret, i);
+			break;
+			}
+		}
+
+	LOG_MSG2( "testing for Semaphore ret %d", ret);
+
+	// We only want to have one RTest instance at any one time since otherwise RTest can panic
+	RTest test(_L("T_MULTI_AGENT_LAUNCHER"));
+	test.Start(_L("t_multi_agent_launcher Check for agents finishing correctly"));
+	test(ret == KErrNone);
+	test.End();
+	test.Close();
+
+	CleanupStack::PopAndDestroy(&launchSemaphore); // launchSemaphore
+
+	if( commandLine )
+	CleanupStack::PopAndDestroy(commandLine);
+	
+	LOG_MSG("EXIT: t_multi_agent_launcher MainL()");
+	}
+ 
+GLDEF_C TInt E32Main()
+	{
+	LOG_MSG("ENTER: Multi_agent_launcher E32Main()");
+	__UHEAP_MARK;
+
+	CTrapCleanup* trap = CTrapCleanup::New();
+	if (!trap)
+		return KErrNoMemory;
+
+	TRAPD(err, MainL());
+	LOG_MSG2("Multi_agent_launcher: returning from MainL(), err = %d", err);
+	
+	delete trap;
+	LOG_MSG("EXIT: Multi_agent_launcher E32Main()");
+	__UHEAP_MARKEND;
+
+	return err;
+	}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/debugsrv/runmodedebug/rmdebug_test/rm_debug/multi_agent_tests/t_multi_agent_launcher.h	Fri Aug 27 11:37:29 2010 +0300
@@ -0,0 +1,45 @@
+// Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+// Definitions for agent launcher
+// 
+//
+
+/**
+ @file
+ @internalTechnology
+ @released
+*/
+
+#ifndef RMDEBUG_MULTI_AGENT_LAUNCHER_H
+#define RMDEBUG_MULTI_AGENT_LAUNCHER_H
+
+#include <e32test.h>
+
+// Default test runs
+const TInt KNumTestRuns = 1; 
+
+// Default number of targets per agent
+const TInt KNumTargets = 5;
+
+// Default number of agents, if changing this make sure there are enough apps being built 
+const TInt KNumAgents = 2; 
+
+_LIT(KAgentExe,"z:\\sys\\bin\\t_rmdebug_multi_agent.exe");
+_LIT(KAgentOptions,"-n%d -o%d -a%d");
+
+_LIT(KLaunchSemaphoreName, "t_rmdebug_launch_semaphore");
+_LIT(KLaunchSemaphoreSearchString, "t_rmdebug_launch_semaphore*");
+
+#endif // RMDEBUG_MULTI_AGENT_LAUNCHER_H
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/debugsrv/runmodedebug/rmdebug_test/rm_debug/multi_target_tests/t_multi_target.cpp	Fri Aug 27 11:37:29 2010 +0300
@@ -0,0 +1,405 @@
+// Copyright (c) 2006-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+// Test the ability of the debug system to handle events from several debug targets
+//
+//
+
+#include <e32base.h>
+#include <e32property.h>
+
+#include <hal.h>
+#include <e32test.h>
+
+#include "t_multi_target.h"
+#include "t_target_launcher.h"
+#include "t_rmdebug_app.h"
+
+#ifdef KERNEL_OOM_TESTING
+  #ifdef USER_OOM_TESTING
+    #error "Cannot define both KERNEL_OOM_TESTING and USER_OOM_TESTING"
+  #endif
+#endif
+
+
+using namespace Debug;
+
+const TVersion securityServerVersion(0,1,1);
+
+const TVersion testVersion(2,1,0);
+
+#ifdef NO_DEBUGTOKEN
+LOCAL_D RTest test(_L("T_RMDEBUG_MULTI_TARGET"));
+#endif
+
+#ifdef SOMECAPS_DEBUGTOKEN
+LOCAL_D RTest test(_L("T_RMDEBUG_MULTI_TARGET_OEM"));
+#endif
+
+#ifdef FEWCAPS_DEBUGTOKEN
+LOCAL_D RTest test(_L("T_RMDEBUG_MULTI_TARGET_OEM2"));
+#endif
+
+
+
+CMultiTargetAgent* CMultiTargetAgent::NewL()
+//
+// CMultiTargetAgent::NewL
+//
+  {
+  CMultiTargetAgent* self = new(ELeave) CMultiTargetAgent();
+
+  self->ConstructL();
+
+  return self;
+  }
+
+
+CMultiTargetAgent::~CMultiTargetAgent()
+//
+// CMultiTargetAgent destructor
+//
+    {
+    RDebug::Printf("~CMultiTargetAgent\n");
+    iServSession.Close();
+    }
+
+
+CMultiTargetAgent::CMultiTargetAgent() : 
+    iEventPtr( (TUint8*)&iEventInfo, sizeof(TEventInfo) )
+    {
+    }
+
+
+void CMultiTargetAgent::ConstructL()
+//
+// CMultiTargetAgent::ConstructL
+//
+  {
+  }
+
+/**
+ * Helper code for the stepping tests. Returns the number of nanokernel ticks in one second.
+ *
+ * @return Number of nanokernel ticks. 0 if unsuccesful.
+ */
+TInt CMultiTargetAgent::HelpTicksPerSecond(void)
+  {
+  TInt nanokernel_tick_period;
+  HAL::Get(HAL::ENanoTickPeriod, nanokernel_tick_period);
+
+  ASSERT(nanokernel_tick_period != 0);
+
+  static const TInt KOneMillion = 1000000;
+
+  return KOneMillion/nanokernel_tick_period;
+  }
+
+void CMultiTargetAgent::ClientAppL()
+//
+// Performs each test in turn
+//
+  {
+  test.Start(_L("ClientAppL"));
+  TInt err = iServSession.Connect(securityServerVersion);
+  if (err != KErrNone)
+      {
+      User::Panic(_L("Can't open server session"), err);
+      }
+  SetupDebugServerL();
+  LaunchTargetsInOrderL();
+  RDebug::Printf( "returning from CMultiTargetAgent::ClientAppL" );
+  test.End();
+  }
+
+/**
+  Launch a process
+
+  @param aProcess The RProcess object to use to create the process
+  @param aExeName File name of the executable to create the process from
+  @param aCommandLine The command line to pass to the new process
+  @return KErrNone on success, or one of the other system wide error codes
+  */
+TInt CMultiTargetAgent::LaunchProcess(RProcess& aProcess, TDesC & aExeName, TDesC & aCommandLine )
+    {    
+    TInt err = aProcess.Create( aExeName, aCommandLine );    
+    if(err != KErrNone)
+        {
+        RDebug::Printf( "aProcess.Create ret %d", err);
+        return err;
+        }
+
+    TRequestStatus status = KRequestPending;
+    aProcess.Rendezvous(status);
+    if(KRequestPending != status.Int())
+        {
+        // startup failed so kill the process
+        aProcess.Kill(KErrNone);
+        return status.Int();
+        }
+    else
+        {
+        // start up succeeded so resume the process
+        aProcess.Resume();
+        // Give the process a chance to run
+        User::After( 500000 );
+        return KErrNone;
+        }
+    }
+
+void CMultiTargetAgent::SetupDebugServerL()
+    {
+    RDebug::Printf( "CMultiTargetAgent::SetupDebugServerL" );
+    test.Next(_L("SetupDebugServerL\n"));
+    iTargets.ReserveL( KNumApps );
+
+    RBuf targetName;
+    CleanupClosePushL( targetName );
+
+    for( TInt numApps = 0; numApps < KNumApps; numApps++ )
+        {
+        iTargets.AppendL( targetName );
+        RDebug::Printf( "Attach to DSS for app %d ", numApps );
+
+        iTargets[numApps].CreateL( KTargetExe().Length() + 2 );
+        iTargets[numApps].Format( KTargetExe(), numApps+1 );
+
+        TInt ret = iServSession.AttachExecutable( iTargets[numApps], EFalse );
+        test( ret == KErrNone );
+
+        RDebug::Printf( ">SetEventAction app %d,  EEventsStartThread EActionSuspend", numApps );
+        ret = iServSession.SetEventAction( iTargets[numApps], EEventsStartThread, EActionSuspend );
+        test( ret == KErrNone );
+
+        RDebug::Printf( ">SetEventAction app %d,  EEventsAddProcess EActionContinue", numApps );
+        ret = iServSession.SetEventAction( iTargets[numApps], EEventsAddProcess, EActionContinue );
+        test( ret == KErrNone );
+
+        RDebug::Printf( ">SetEventAction app %d,  EEventsRemoveProcess EActionContinue", numApps );
+        ret = iServSession.SetEventAction( iTargets[numApps], EEventsRemoveProcess, EActionContinue );
+        test( ret == KErrNone );
+        }
+
+    CleanupStack::PopAndDestroy( &targetName ); // targetName
+
+    }
+
+
+
+TInt CMultiTargetAgent::LaunchTargetsInOrderL()
+    {
+    RDebug::Printf( "CMultiTargetAgent::LaunchTargetsInOrderL" );
+    
+    RBuf launcher;
+    CleanupClosePushL( launcher );
+    launcher.CreateL( KLauncherExe() );
+    
+    RBuf launcherOptions;
+    CleanupClosePushL( launcherOptions ); 
+    launcherOptions.CreateL( KTargetOptions().Length() + 2 );
+    launcherOptions.Format( KTargetOptions(), (TUint)ENormalExit );
+
+    RDebug::Printf( ">LaunchProcess()" );
+    RProcess launcherProc; 
+    CleanupClosePushL( launcherProc );
+    
+    TInt ret = LaunchProcess( launcherProc, launcher, launcherOptions );
+    RDebug::Printf( "<LaunchProcess() ret %d", ret );
+    
+    CleanupStack::PopAndDestroy( &launcherProc ); // launcherProc
+    CleanupStack::PopAndDestroy( &launcherOptions ); // launcherOptions
+    CleanupStack::PopAndDestroy( &launcher ); //launcher 
+
+    test( ret == KErrNone );
+    
+    RSemaphore launchSemaphore;   
+    CleanupClosePushL( launchSemaphore );
+            
+    TFindSemaphore launchSemFinder( KLaunchSemaphoreNameSearchString );
+    TFullName semaphoreResult;
+    ret = launchSemFinder.Next(semaphoreResult);
+    RDebug::Printf( ">  Find Launch Semaphote.Next ret=%d, %lS", ret, &semaphoreResult );
+    test( ret == KErrNone );   
+     
+    ret = launchSemaphore.OpenGlobal( semaphoreResult );
+    RDebug::Printf( "> OpenGlobal semaphore ret=%d", ret );         
+    test( ret == KErrNone );    
+    
+    TBool thisLaunchCompleted; 
+
+    test.Next(_L("LaunchTargetsInOrderL\n"));
+    for( TInt numLaunches = KNumLaunches; numLaunches > 0; numLaunches-- )
+        {
+        for( TInt numApps = KNumApps; numApps > 0; numApps-- )
+            {
+            thisLaunchCompleted = EFalse;
+            // This will trigger the launcher app to launch the next target
+            RDebug::Printf( " >Semaphore.Signal app=%d, launch=%d", numApps, numLaunches);
+            launchSemaphore.Signal();
+            
+            RBuf8 tgt8Name; 
+            CleanupClosePushL( tgt8Name );
+           
+            RBuf tgtCollapseName;
+            CleanupClosePushL( tgtCollapseName );
+                    
+            tgtCollapseName.CreateL( iTargets[numApps-1] );
+            tgt8Name.CreateL( tgtCollapseName.Collapse() );
+            
+
+            while( ! thisLaunchCompleted )
+                {
+                RDebug::Printf( ">GetEvent app %d for %S", numApps, &tgt8Name );
+                iServSession.GetEvent( iTargets[numApps-1], iStatus, iEventPtr );
+          
+                // Wait for the target to get started.
+                RDebug::Printf( " >Wait for event from target app=%d, launch=%d\n", numApps, numLaunches);
+                User::WaitForRequest( iStatus );
+                RDebug::Printf( " <Wait for request returned with status %d", iStatus.Int() );
+                test( iStatus==KErrNone );
+    
+                RDebug::Printf( " > Got iEventType =%d, app=%d", iEventInfo.iEventType, numApps );
+                switch( iEventInfo.iEventType )
+                    {
+                    case EEventsAddProcess:
+                        {
+                        RDebug::Printf( "Got EEventsAddProcess" );                        
+                        TPtrC8 exeNamePtr8( iEventInfo.iAddProcessInfo.iFileName, iEventInfo.iAddProcessInfo.iFileNameLength );
+                        
+                        RBuf8 exeName8;
+                        CleanupClosePushL( exeName8 );
+                        exeName8.CreateL( exeNamePtr8 );
+                        RDebug::Printf( " from event: exeName8=%S", &exeName8 );
+                        CleanupStack::PopAndDestroy( &exeName8 );
+                        
+                        RBuf8 compareName8;
+                        CleanupClosePushL( compareName8 );
+                        compareName8.CreateL( KTargetExeName().Length() + 10 );
+                        compareName8.Format( KTargetExeName(), numApps );
+                        RDebug::Printf( " comparing to: compareName8=%S", &compareName8 );
+                        
+                        test( compareName8.CompareC( exeNamePtr8 ) == 0 );
+                        CleanupStack::PopAndDestroy( &compareName8 );
+
+                        RDebug::Printf( "Testing if event process id is valid" );
+                        test( iEventInfo.iProcessIdValid );
+                        RDebug::Printf( "Got iEventInfo.iProcessId=%d", I64LOW( iEventInfo.iProcessId ) );
+                        
+                        RProcess targetProc;
+                        ret = targetProc.Open( TProcessId( iEventInfo.iProcessId ) );
+                        RDebug::Printf( "RProcess open ret=%d",ret );
+                        targetProc.Close();
+                        test( ret == KErrNone );
+                        
+                        break;
+                        }//EEventsAddProcess
+                        
+                    case EEventsStartThread:
+                        {
+                        RDebug::Printf( "Got EEventsStartThread" );
+                         
+                        TPtrC8 exeNamePtr8( iEventInfo.iStartThreadInfo.iFileName, iEventInfo.iStartThreadInfo.iFileNameLength );
+                        RBuf8 exe8Name;
+                        CleanupClosePushL( exe8Name );
+                        exe8Name.CreateL( exeNamePtr8 );
+                        RDebug::Printf( " from event: exeName8=%S", &exe8Name );
+                        CleanupStack::PopAndDestroy( &exe8Name );
+                        
+                        test( tgt8Name.CompareC( exeNamePtr8 ) == 0 );
+                        
+                        RDebug::Printf( "Testing if event process id is valid" );
+                        test( iEventInfo.iProcessIdValid );
+                        RDebug::Printf( "Got iEventInfo.iProcessId=%d", I64LOW( iEventInfo.iProcessId ) );
+                         
+                        RDebug::Printf( "Testing if event thread id is valid" );
+                        test( iEventInfo.iThreadIdValid );
+                        RDebug::Printf( "Got iEventInfo.iThreadId=%d", I64LOW( iEventInfo.iThreadId ) );
+                        
+                        RThread targetThread;
+                        CleanupClosePushL( targetThread );
+                        
+                        ret = targetThread.Open( TThreadId( iEventInfo.iThreadId ) );
+                        RDebug::Printf( "RThread open ret=%d", ret );
+                        test( ret == KErrNone ); 
+                         
+                        test( iEventInfo.iThreadId == targetThread.Id() );  
+
+                        RDebug::Printf( "Resuming thread for app=%d, id=%d", numApps, I64LOW( targetThread.Id() ));
+                        ret = iServSession.ResumeThread( iEventInfo.iThreadId );
+                        CleanupStack::PopAndDestroy( &targetThread );
+                        
+                        test( ret == KErrNone );
+                        
+                        ret = iServSession.ResumeThread( iEventInfo.iThreadId );
+                        break;                    
+                        }//case EEventsStartThread                        
+
+                    case ( EEventsRemoveProcess ):
+                        {
+                        RDebug::Printf( "*** Got EEventsRemoveProcess. app%d has exited. Moving on to next app", numApps );                        
+                        thisLaunchCompleted = ETrue;
+                        break;
+                        }
+                        
+                    default :   
+                        RDebug::Printf( "Got unknown event" );
+                        test( EFalse );
+                        break;
+                    }
+                }//while
+
+            CleanupStack::PopAndDestroy( &tgtCollapseName ); // tgtCollapseName
+            CleanupStack::PopAndDestroy( &tgt8Name ); // tgt8Name 
+            }
+        }    
+
+    launchSemaphore.Signal();
+    
+	CleanupStack::PopAndDestroy( &launchSemaphore ); // launchSemaphore
+  
+	for( TInt i = iTargets.Count()-1; i>=0; i-- )
+		{
+		RDebug::Printf( "Closing target %d", i );
+		iTargets[ i ].Close();
+		}
+
+	iTargets.Close();
+	
+	return KErrNone;
+    }
+
+
+GLDEF_C TInt E32Main()
+    {
+    TInt ret = KErrNone;
+   
+  
+    CTrapCleanup* trap = CTrapCleanup::New();
+    if (!trap)
+      return KErrNoMemory;
+    test.Title();
+   
+    CMultiTargetAgent *runModeAgent = CMultiTargetAgent::NewL();
+    if (runModeAgent != NULL)
+        {
+        __UHEAP_MARK;
+        TRAP(ret,runModeAgent->ClientAppL());
+        __UHEAP_MARKEND;
+        
+        RDebug::Printf( "ClientAppL returned %d", ret );
+        delete runModeAgent;
+        }
+
+    delete trap;
+    return ret;
+    }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/debugsrv/runmodedebug/rmdebug_test/rm_debug/multi_target_tests/t_multi_target.h	Fri Aug 27 11:37:29 2010 +0300
@@ -0,0 +1,93 @@
+// Copyright (c) 2006-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+// Definitions for the run mode debug tests
+// 
+//
+
+/**
+ @file
+ @internalTechnology
+ @released
+*/
+
+#ifndef RMDEBUG_MULTI_TARGET_H
+#define RMDEBUG_MULTI_TARGET_H
+
+#include "t_rmdebug_app.h"
+
+#include <rm_debug_api.h>
+
+class CMultiTargetAgent;
+
+//
+// class CRunModeAgent
+//
+// The basic run mode agent.
+//
+class CMultiTargetAgent : public CBase
+	{
+public:
+	static CMultiTargetAgent* NewL();
+	~CMultiTargetAgent();
+	void ClientAppL();
+	
+    TInt LaunchProcess(RProcess& aProcess, TDesC & aExeName, TDesC & aCommandLine );
+    
+private:
+	CMultiTargetAgent();
+	void ConstructL();
+
+	void ReportPerformance(void);
+
+	TInt HelpTicksPerSecond(void);
+
+	enum TTestMode 
+		{
+		//run all the tests
+		EModeAll = 1<<0,
+		//run the specified tests in reverse order
+		EModeReverse = 1<<1,
+		//print out help
+		EModeHelp = 1<<2,
+		//print out help
+		EModeVersion = 1<<3
+		};
+	
+	TInt LaunchTargetsInOrderL();
+	void SetupDebugServerL();
+
+private:
+
+#if defined(KERNEL_OOM_TESTING)
+	RKernelLowMemorySecuritySvrSession iServSession;
+#elif defined (USER_OOM_TESTING)
+	RUserLowMemorySecuritySvrSession iServSession;
+#else
+	Debug::RSecuritySvrSession iServSession;
+#endif
+	RSemaphore iAddressGlobSem;
+
+	TUid iMySid;
+
+	// Timing information
+	TInt iStartTick;
+	TInt iStopTick;
+
+	RArray<RBuf> iTargets;
+  TRequestStatus iStatus;
+  Debug::TEventInfo iEventInfo;
+  TPtr8 iEventPtr;
+	};
+
+#endif // RMDEBUG_MULTI_TARGET_H
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/debugsrv/runmodedebug/rmdebug_test/rm_debug/performance_test/t_rmdebug_performance_oemtoken.cpp	Fri Aug 27 11:37:29 2010 +0300
@@ -0,0 +1,31 @@
+// Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+//
+
+/**
+ @file
+ @internalTechnology
+ @released
+*/
+
+#include <e32base.h>
+
+GLDEF_C TInt E32Main()
+	{
+	// No need to do anything, the only requirement is that
+	// this executable can be loaded and runs to completion
+	return 0;
+	}
+
+// End of file - t_rmdebug_performance_oemtoken.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/debugsrv/runmodedebug/rmdebug_test/rm_debug/performance_test/t_rmdebug_performance_test.cpp	Fri Aug 27 11:37:29 2010 +0300
@@ -0,0 +1,599 @@
+// Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+// Tests performance of run mode debug device component   
+//
+
+#include <e32base.h>
+#include <e32property.h>
+#include <e32test.h>
+#include <e32def.h>
+#include <e32const.h>
+#include <hal.h>
+
+#include "t_rmdebug_performance_test.h"
+#include "t_debug_logging.h"
+#include "t_rmdebug_app.h"
+
+const TVersion securityServerVersion(0,1,1);
+
+_LIT(KTestName, "T_RMDEBUG_PERFORMANCE_TEST");
+
+LOCAL_D RTest test(KTestName);
+
+using namespace Debug;
+
+CRunModeAgent* CRunModeAgent::NewL()
+    {
+    LOG_ENTRY();
+    CRunModeAgent* self = new(ELeave) CRunModeAgent();
+    self->ConstructL();
+    LOG_EXIT();
+    return self;
+    }
+
+void CRunModeAgent::ConstructL()
+    {
+    // ConstructL list does not match destruction list as R-Class member variables are implicitly open.
+    // DebugDriver().Connect() is conditionally set depending on the test case hence not part of this function.
+    LOG_ENTRY();
+    User::LeaveIfError(iIntegerProperty.Attach(RProcess().SecureId(), EPropertyTimeOfCrash, EOwnerThread));
+    LOG_EXIT(); 
+    }
+
+CRunModeAgent::~CRunModeAgent()
+    {
+    LOG_ENTRY();   
+    DebugDriver().Close();
+    iTimeDifs.Close();
+    iIntegerProperty.Close();
+    RProperty::Delete(EPropertyTimeOfCrash);
+    LOG_EXIT(); 
+    }
+
+
+void CRunModeAgent::ClientAppL()
+    {
+    LOG_ENTRY();   
+   
+    if ( ParseCommandLine() == EDisplayHelp )
+        {
+        DisplayUsage();
+        }
+    else
+        {
+        static _LIT_SECURITY_POLICY_PASS(KAllowAllPolicy);
+        RProperty::Define(RProcess().SecureId(), EPropertyTimeOfCrash, RProperty::EInt, KAllowAllPolicy, KAllowAllPolicy);        
+        StartTest();
+        }
+        
+    LOG_EXIT(); 
+    }
+
+TInt CRunModeAgent::GetTimeInMs()
+{
+    return User::NTickCount() * iTickPeriodMs;
+}
+
+void CRunModeAgent::GetStartTime()
+    {    
+    LOG_ENTRY();
+
+    test ( KErrNone == iIntegerProperty.Get(iParams.iCountStart) );    
+    LOG_MSG2("iParams.iCountStart %d", iParams.iCountStart);
+    
+    LOG_EXIT();
+    }
+
+void CRunModeAgent::GetNanoTickPeriod()
+    {
+    LOG_ENTRY();
+    
+    TInt period = 0;
+    User::LeaveIfError(HAL::Get(HALData::ENanoTickPeriod, period));
+    iTickPeriodMs = period / 1000;
+    LOG_MSG("iTickPeriodMs = %d\n", iTickPeriodMs);
+    
+    LOG_EXIT();
+    }
+
+void CRunModeAgent::StartTest()
+    {
+    LOG_ENTRY();
+    
+    GetNanoTickPeriod();
+    
+    if (iParams.iTestType == PerformanceTestParams::EBenchMarkTest)
+        {
+        RunBenchMarkTest();
+        }
+    else 
+        {
+        TestDriverPerformance();
+        }
+    
+    CalculatePerformance();
+    
+    LOG_EXIT();
+    }
+
+// This function allows us to provide a benchmark when comparing the performance with the 
+// old and new APIs using the TestDriverPerformance function below. The two possible 
+// configurations are as follows: 
+// 1. Run t_rmdebug_app with a prefetch abort configuration and measure the time from the 
+// point of crash to the logon request completion.
+// 2. Load the debug-system and then run the above configuration.  
+void CRunModeAgent::RunBenchMarkTest()
+    {
+    LOG_ENTRY();
+    
+    test.Start(_L("RunBenchMarkTest"));
+    
+    RProcess process;
+    TRequestStatus status; 
+    
+    if (iParams.iDriver)
+         {
+         RDebug::Printf("RunBenchMarkTest() - DebugDriver().Connect()");
+         test(KErrNone == DebugDriver().Connect(securityServerVersion));
+         }
+ 
+    LOG_MSG("iParams.iNumOfTestRuns = %d", iParams.iNumOfTestRuns);
+    
+    for ( TUint i = 0; i < iParams.iNumOfTestRuns; i++ )
+        {
+        // Start test application
+        test( KErrNone == LaunchProcessL(process, KRMDebugTestApplication(), KTargetOptions()) );
+               
+        process.Logon(status);
+        User::WaitForRequest(status);
+
+        // Stop timer on logon request completion
+        iParams.iCountEnd = GetTimeInMs();
+        LOG_MSG("iParams.iCountEnd = %d", iParams.iCountEnd);
+        
+        LOG_MSG( "status.Int() = %d " , status.Int() );
+        
+        // prefetch abort should raise a KERN-EXEC 3
+        test(3 == status.Int());
+        
+        process.Close();
+        GetStartTime(); 
+       
+        // NTickCount shouldn't overflow, so no reason why this assertion should fail
+        test(iParams.iCountEnd > iParams.iCountStart);
+        iTimeDifs.Append( iParams.iCountEnd - iParams.iCountStart );
+       }
+    
+    LOG_EXIT();
+    }
+
+// This function can be used to compare the performance with the old (e.g. attachExe) and new 
+// (e.g. attachAll) APIs depending depending on the parameters passed in when running this test.  
+void CRunModeAgent::TestDriverPerformance()
+    {
+    LOG_ENTRY();    
+    test.Start(_L("TestDriverPerformance"));
+   
+    RProcess process;
+    
+    test(KErrNone == DebugDriver().Connect(securityServerVersion));
+    
+    LOG_MSG("iParams.iNumOfTestRuns = %d", iParams.iNumOfTestRuns);
+    for ( TUint i = 0; i < iParams.iNumOfTestRuns; i++ )
+        {
+        ilaunchCompleted = EFalse;
+     
+        Attach();
+        SetEventAction();
+        test(KErrNone == LaunchProcessL(process, KRMDebugTestApplication(), KTargetOptions));
+        
+        LOG_MSG("CRunModeAgent::TestDriverPerformance - process.Logon");
+        
+        while ( !ilaunchCompleted )
+            {
+            LOG_MSG("CRunModeAgent::TestDriverPerformance - DebugDriver().GetEvent");
+       
+            GetEvent();
+       
+            LOG_MSG("CRunModeAgent::TestDriverPerformance - User::WaitForRequest");
+
+            User::WaitForRequest(iStatus);
+            LOG_MSG( "iStatus.Int() = %d " , iStatus.Int() );
+            
+            LOG_MSG("CRunModeAgent::TestDriverPerformance - HandleEvent");
+            HandleEvent(iSEventInfo.iEventInfo);
+            }
+        
+        process.Logon(iStatus);
+        LOG_MSG("CRunModeAgent::TestDriverPerformance - process.Logon, User::WaitForRequest");
+        User::WaitForRequest(iStatus);
+        LOG_MSG( "iStatus.Int() = %d " , iStatus.Int() );
+        
+        // Stop timer on logon request completion as in benchmark performance test
+        iParams.iCountEnd = GetTimeInMs();
+                
+        // prefetch abort should raise a KERN-EXEC 3
+        test(3 == iStatus.Int());
+                    
+        Detach();
+        process.Close();       
+        GetStartTime();
+ 
+        // NTickCount shouldn't overflow, so no reason why this assertion should fail
+        test(iParams.iCountEnd > iParams.iCountStart);
+        iTimeDifs.Append( iParams.iCountEnd - iParams.iCountStart );
+       }
+        
+       LOG_EXIT();
+    }
+
+void CRunModeAgent::CalculatePerformance()
+    {
+    LOG_ENTRY();
+
+    TUint median;
+    TUint arrayCount = iTimeDifs.Count();
+
+    for (TInt i = 0; i < arrayCount; i++)
+         {
+         RDebug::Printf("iTimeDifs[%d] = %d ",i,iTimeDifs[i]);
+         }
+    
+    // Sort in ascending order
+    iTimeDifs.Sort();
+            
+    //If the number of elements is odd, the middle element in the sorted array is the median. 
+    //If the number of elements is even, the median is the average of the two midmost elements.
+    if ( arrayCount%2  != 0 )
+        {
+        median = iTimeDifs[arrayCount/2];
+        }
+    else
+        {
+        median = (iTimeDifs[arrayCount/2] + iTimeDifs[arrayCount/2 -1])/2;
+        }
+    
+    RDebug::Printf("Median time %d ms", median );
+    
+    LOG_EXIT();
+    }
+
+/**
+  Launch a process
+  @param aExeName the executable used to create the process
+  @param aCommandLine the commandline parameters passed to the new process file name of the executable used to create the process
+  @return KErrNone on success, or one of the other system wide error codes
+  */
+TInt CRunModeAgent::LaunchProcessL( RProcess& aProcess, const TDesC& aExeName, const TDesC& aCommandLine )
+    {
+    LOG_ENTRY(); 
+    
+    RBuf launcherOptions;
+    launcherOptions.CleanupClosePushL();
+    const TInt additionalWords = 1; 
+    launcherOptions.CreateL( aCommandLine.Length() + additionalWords );
+    launcherOptions.Format( aCommandLine, iParams.iTestTargetPriority);
+   
+    LOG_DES(_L("launcherOptions %S"), &launcherOptions);
+    
+    TInt err = aProcess.Create( aExeName, launcherOptions );   
+    CleanupStack::PopAndDestroy();
+    
+    // check that there was no error raised
+    if (err != KErrNone)
+        return err;
+    
+    // rendezvous with process
+    TRequestStatus status = KRequestPending;
+    aProcess.Rendezvous(status);
+
+    // start the test target
+    aProcess.Resume();
+    User::WaitForRequest(status);
+  
+    if(KErrNone != status.Int())
+        {
+        aProcess.Kill(KErrNone);
+        }
+     LOG_EXIT(); 
+     return status.Int();
+
+    }
+
+void CRunModeAgent::SetEventAction()
+    {
+    LOG_ENTRY();
+    
+    if (iParams.iTestType == PerformanceTestParams::EAttachExe)
+        {
+        test(KErrNone == DebugDriver().SetEventAction( KRMDebugTestApplication(), EEventsKillThread, EActionContinue));
+             
+        if ( iParams.iEvents )
+            {
+            test(KErrNone == DebugDriver().SetEventAction( KRMDebugTestApplication(), EEventsAddLibrary, EActionContinue));
+            test(KErrNone == DebugDriver().SetEventAction( KRMDebugTestApplication(), EEventsUserTrace, EActionContinue));
+            test(KErrNone == DebugDriver().SetEventAction( KRMDebugTestApplication(), EEventsStartThread, EActionContinue));
+            test(KErrNone == DebugDriver().SetEventAction( KRMDebugTestApplication(), EEventsAddProcess, EActionContinue));
+            test(KErrNone == DebugDriver().SetEventAction( KRMDebugTestApplication(), EEventsRemoveProcess, EActionContinue));
+            }
+        }
+    else
+        {
+        test(KErrNone == DebugDriver().SetEventAction( EEventsKillThread, EActionContinue));
+             
+        if ( iParams.iEvents )
+            {
+            test(KErrNone == DebugDriver().SetEventAction( EEventsAddLibrary, EActionContinue));
+            test(KErrNone == DebugDriver().SetEventAction( EEventsUserTrace, EActionContinue));
+            test(KErrNone == DebugDriver().SetEventAction( EEventsStartThread, EActionContinue));
+            test(KErrNone == DebugDriver().SetEventAction( EEventsAddProcess, EActionContinue));
+            test(KErrNone == DebugDriver().SetEventAction( EEventsRemoveProcess, EActionContinue));
+            }
+        }
+    
+    LOG_EXIT();
+    }
+
+void CRunModeAgent::Attach()
+    {
+    LOG_ENTRY();
+    
+    if( iParams.iTestType == PerformanceTestParams::EAttachExe ) 
+        {
+        // Attach to process non-passively
+        test(KErrNone == DebugDriver().AttachExecutable( KRMDebugTestApplication(), EFalse));
+        LOG_MSG("DebugDriver().AttachExecutable");
+        }
+    else 
+        {
+        // Attach to all the processes on the system
+        test(KErrNone == DebugDriver().AttachAll());
+        LOG_MSG("DebugDriver().AttachAll()");
+        }
+    
+    LOG_EXIT();
+    }
+
+void CRunModeAgent::GetEvent()
+    {
+    LOG_ENTRY();
+
+    if( iParams.iTestType == PerformanceTestParams::EAttachExe ) 
+        {
+        DebugDriver().GetEvent( KRMDebugTestApplication(), iStatus, iSEventInfo.iEventInfoBuf );
+        }
+    else
+        {
+        DebugDriver().GetEvent( iStatus, iSEventInfo.iEventInfoBuf );
+        }
+    
+    LOG_EXIT();
+    }
+
+void CRunModeAgent::Detach()
+    {
+    LOG_ENTRY();
+    
+    if( iParams.iTestType == PerformanceTestParams::EAttachExe )
+        {
+        test (KErrNone == DebugDriver().DetachExecutable(KRMDebugTestApplication()));
+        }
+    else
+        {
+        test(KErrNone == DebugDriver().DetachAll());
+        }
+    
+    LOG_EXIT();
+    }
+
+void CRunModeAgent::HandleEvent(TEventInfo& aEventInfo)
+    {
+    LOG_ENTRY(); 
+
+    switch ( aEventInfo.iEventType )
+        {
+        case EEventsAddProcess:
+            {
+            LOG_MSG(">>> EEventsAddProcess");                        
+            break;
+            }
+    
+        case EEventsStartThread:
+            {
+            LOG_MSG(">>> EEventsStartThread");                
+            break;                    
+            }                       
+
+        case EEventsUserTrace:
+            {
+            LOG_MSG(">>> EEventsUserTrace");  
+            break;
+            }
+
+        case EEventsRemoveProcess:
+            {
+            LOG_MSG(">>> EEventsRemoveProcess");                        
+            break;
+            }
+    
+        case EEventsKillThread:
+            {
+            LOG_MSG(">>> EEventsKillThread");   
+            ilaunchCompleted = ETrue;          
+            break;
+            }
+            
+        default:   
+            {
+            LOG_MSG( ">>> Unknown event ");
+            break;
+            }   
+        }
+     
+    LOG_EXIT(); 
+    }
+
+void CRunModeAgent::SetDefaultParamValues()
+    {
+    LOG_ENTRY();
+    
+    iParams.iNumOfTestRuns = KNumOfTestRuns;
+    iParams.iTestType = PerformanceTestParams::EBenchMarkTest;
+    iParams.iTestTargetPriority = 0;
+    iParams.iEvents = 0;
+    iParams.iDriver = 0;
+    
+    LOG_EXIT();
+    }
+
+TInt CRunModeAgent::ParseCommandLine()
+    {
+    LOG_ENTRY();
+    
+    TBool ifDisplayHelp = EDontDisplayHelp;
+    SetDefaultParamValues();
+    
+    TInt argc = User::CommandLineLength();
+    LOG_MSG( "Launcher Process() argc=%d", argc );
+
+    if( argc )
+        {
+        HBufC* commandLine = NULL;
+        commandLine = HBufC::NewLC(argc);
+        TPtr commandLineBuffer = commandLine->Des();
+        User::CommandLine(commandLineBuffer);
+       
+        LOG_DES(_L("CommandLine = %S"), &commandLineBuffer);
+        
+        // create a lexer and read through the command line
+        TLex lex(*commandLine);
+        while (!lex.Eos())
+             {
+             // only look for options with first character '-', other switches are for the targets
+             if (lex.Get() == '-')
+                 {
+                 TChar arg = lex.Get();
+                 switch (arg)
+                     {
+                     case 'n':
+                         lex.Val( iParams.iNumOfTestRuns );
+                         LOG_MSG("Number of test runs %d", iParams.iNumOfTestRuns);
+                         break;
+                      case 't':
+                          lex.Val( iParams.iTestType );
+                          LOG_MSG("parsed testType as %d", iParams.iTestType );
+                          break;
+                      case 'p':
+                          lex.Val( iParams.iTestTargetPriority );
+                          LOG_MSG("parsed test target priority as %d", iParams.iTestTargetPriority );
+                          break;
+                      case 'e':
+                          lex.Val( iParams.iEvents );
+                          LOG_MSG("parsed events as %d", iParams.iEvents );
+                          break;
+                      case 'd':
+                          lex.Val( iParams.iDriver );
+                          LOG_MSG("parsed iDriver as %d", iParams.iDriver );
+                          break;
+                       case 'h':
+                          LOG_MSG( "Display help" );
+                          ifDisplayHelp = EDisplayHelp;
+                       default:
+                           LOG_MSG( "Default usage" );
+                           break;             
+                       }
+                  }
+              }
+            CleanupStack::PopAndDestroy(commandLine);
+        }
+    
+    LOG_EXIT();
+    return ifDisplayHelp;   
+    }
+
+void CRunModeAgent::DisplayUsage()
+    {
+    LOG_ENTRY();
+    test.Printf(_L("\nUsage: t_rmdebug_performance_test [options] \nOptions:\n"));
+    
+    test.Printf(_L("\t-t  \t\ttest type\n"));
+    test.Printf(_L("\t\t\t  0 - AttachAll\n"));
+    test.Printf(_L("\t\t\t  1 - AttachExe\n"));
+    test.Printf(_L("\t\t\t  2 - None\n"));
+           
+    test.Printf(_L("\t-n \t\tnumber of iterations\n"));
+    test.Printf(_L("\t-e \t\ttest with events\n"));
+    test.Printf(_L("\t\t\t  0 - No\n"));
+    test.Printf(_L("\t\t\t  1 - Yes\n"));
+    test.Printf(_L("\t-p \t\tpriority of test target thread\n"));
+    
+    test.Printf(_L("\t\t\t  %d - EPriorityAbsoluteVeryLow \n"), EPriorityAbsoluteVeryLow);
+    test.Printf(_L("\t\t\t  %d - EPriorityAbsoluteLowNormal \n"), EPriorityAbsoluteLowNormal);
+    test.Printf(_L("\t\t\t  %d - EPriorityAbsoluteLow \n"), EPriorityAbsoluteLow);
+    test.Printf(_L("\t\t\t  %d - EPriorityAbsoluteBackgroundNormal \n"), EPriorityAbsoluteBackgroundNormal);
+    test.Printf(_L("\t\t\t  %d - EPriorityAbsoluteBackground \n"), EPriorityAbsoluteBackground);
+    test.Printf(_L("\t\t\t  %d - EPriorityAbsoluteForegroundNormal \n"), EPriorityAbsoluteForegroundNormal);
+    test.Printf(_L("\t\t\t  %d - EPriorityAbsoluteForeground \n"), EPriorityAbsoluteForeground);
+    test.Printf(_L("\t\t\t  %d - EPriorityAbsoluteHighNormal \n"), EPriorityAbsoluteHighNormal);
+    test.Printf(_L("\t\t\t  %d - EPriorityAbsoluteHigh \n"), EPriorityAbsoluteHigh);
+    test.Printf(_L("\t\t\t  %d - EPriorityAbsoluteRealTime1 \n"), EPriorityAbsoluteRealTime1);
+    test.Printf(_L("\t\t\t  %d - EPriorityAbsoluteRealTime2 \n"), EPriorityAbsoluteRealTime2);
+    test.Printf(_L("\t\t\t  %d - EPriorityAbsoluteRealTime3 \n"), EPriorityAbsoluteRealTime3);
+    test.Printf(_L("\t\t\t  %d - EPriorityAbsoluteRealTime4 \n"), EPriorityAbsoluteRealTime4);
+    test.Printf(_L("\t\t\t  %d - EPriorityAbsoluteRealTime5 \n"), EPriorityAbsoluteRealTime5);
+    test.Printf(_L("\t\t\t  %d - EPriorityAbsoluteRealTime6 \n"), EPriorityAbsoluteRealTime6);
+    test.Printf(_L("\t\t\t  %d - EPriorityAbsoluteRealTime7 \n"), EPriorityAbsoluteRealTime7);
+    test.Printf(_L("\t\t\t  %d - EPriorityAbsoluteRealTime8 \n"), EPriorityAbsoluteRealTime8);
+    
+    test.Printf(_L("\t-d  \t\tload driver\n"));
+    test.Printf(_L("\t\t\t  0 - No\n"));
+    test.Printf(_L("\t\t\t  1 - Yes\n"));
+        
+    test.Printf(_L("\t-h \t\tdisplay usage information\n\n"));
+    
+    test.Printf(_L("Press any key...\n"));
+    test.Getch();
+    
+    LOG_EXIT();
+    }
+
+GLDEF_C TInt E32Main()
+    {
+    __UHEAP_MARK;
+
+    TInt ret = KErrNone;        
+    CTrapCleanup* trap = CTrapCleanup::New();
+        
+    if (!trap)
+        return KErrNoMemory;
+    
+    test.Start(KTestName);
+       
+    CRunModeAgent *runModeAgent = CRunModeAgent::NewL();
+
+    if (runModeAgent != NULL)
+        {
+        TRAP(ret,runModeAgent->ClientAppL());
+        LOG_MSG( "ClientAppL() returned %d", ret );
+        delete runModeAgent;
+        }
+    
+    test.End();
+    test.Close();
+
+    delete trap;
+    __UHEAP_MARKEND;
+    return ret;
+    }
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/debugsrv/runmodedebug/rmdebug_test/rm_debug/performance_test/t_rmdebug_performance_test.h	Fri Aug 27 11:37:29 2010 +0300
@@ -0,0 +1,142 @@
+// Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+// Tests performance of run mode debug device component   
+// 
+//
+
+#ifndef RMDEBUG_PERFORMANCE_H
+#define RMDEBUG_PERFORMANCE_H
+
+#include <u32hal.h>
+#include <f32file.h>
+#include <rm_debug_api.h>
+
+/* Config for t_rmdebug_app.exe: 
+ * -f1: prefetch abort,
+ * -d0: zero delay before crash
+ * -p: priority of test target main thread
+ */    
+_LIT(KTargetOptions,"-f1 -d0 -p%d");
+
+// Default number of test runs
+const TInt KNumOfTestRuns = 7;
+
+/**
+ @Class TAgentEventInfo
+ 
+ Class for gathering event data from the run-mode driver
+ */
+class TAgentEventInfo
+{
+public:
+    TAgentEventInfo() : iEventInfoBuf(iEventInfo) {}
+   
+public:
+    // This is the underlying class for event interaction with the Run Mode debug API 
+    Debug::TEventInfo          iEventInfo;
+    
+    TPckg<Debug::TEventInfo>  iEventInfoBuf; 
+};
+
+/**
+  @Class CRunModeAgent
+  
+  The basic run mode agent
+  */
+class CRunModeAgent : public CBase
+	{
+public:
+    
+    enum displayHelp {EDontDisplayHelp =0, EDisplayHelp };
+    
+	static CRunModeAgent* NewL();
+	~CRunModeAgent();
+	void ClientAppL();  
+	Debug::RSecuritySvrSession&  DebugDriver() { return iServSession; };	
+
+private:
+	void ConstructL();
+	void StartTest();
+	void TestDriverPerformance();
+	void RunBenchMarkTest();
+	TInt ParseCommandLine();
+	
+	void Attach();
+	void Detach();
+	    
+	void HandleEvent(Debug::TEventInfo& aEventInfo);
+	TInt LaunchProcessL(RProcess& aProcess, const TDesC& aExeName, const TDesC& aCommandLine);
+	void DisplayUsage();
+	void GetNanoTickPeriod();
+	void SetEventAction();
+	void SetDefaultParamValues();
+	
+	void CalculatePerformance();
+	void GetEvent();
+	void GetStartTime();
+	TInt GetTimeInMs();
+	
+private:
+	
+	/** 
+	  Used for test cases interacting with the RMDBG only
+	 */
+	TRequestStatus iStatus;   
+	
+	/**
+	  The nanokernel tick period in MS
+	*/
+	TInt iTickPeriodMs;
+
+	/*
+	 * Handle to DSS
+	 */
+	Debug::RSecuritySvrSession iServSession;
+	
+	/**
+	 Array to store tick counts between an iteration of a test run
+	*/
+	RArray<TUint> iTimeDifs;
+	
+	/**
+	 Object to gather event data from RMDBG
+	*/
+	TAgentEventInfo iSEventInfo;
+		
+	/**
+	  Flag to indicate test target has crashed
+	*/
+	TBool ilaunchCompleted;
+	
+	/*
+	 * RProperty to get counter value from test app
+	 */
+	RProperty iIntegerProperty;
+		
+	struct PerformanceTestParams
+	    {
+	    enum TestOptions {EAttachAll=0,EAttachExe, EBenchMarkTest };
+	    TUint iTestType;
+	    TUint iNumOfTestRuns;
+	    TUint iTestTargetPriority;
+	    TUint iEvents;
+	    TInt iCountEnd;
+	    TInt iCountStart;
+	    TUint iDriver;
+	    } iParams;
+	    
+	};
+
+#endif // RMDEBUG_PERFORMANCE_H
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/debugsrv/runmodedebug/rmdebug_test/rm_debug/scripts/tef_execute_rtests.script	Fri Aug 27 11:37:29 2010 +0300
@@ -0,0 +1,59 @@
+// Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "Symbian Foundation License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.symbianfoundation.org/legal/sfl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description: Script file for running Run-Mode Debug Tests (RTests) as TEF3 tests.
+// 		Please note, for a description of the tests please goto the RTests themselves.
+//		This file is a temporary measure, until the RTest component itself is updated.
+//		The problem is RTest does not produce logs when run on Sirocco, 
+//		so this wrapper allows us to do that.
+//
+//! @File
+//! @SYMTestSuiteName           tef_execute_rtests.script
+//! @SYMScriptTestEnvironment   RTEST as TEF3
+
+PRINT *** Running RTests as TEF3 tests ***
+
+START_TESTCASE                  KBASE-t_rmdebug2
+RUN_PROGRAM 120 t_rmdebug2
+END_TESTCASE                    KBASE-t_rmdebug2
+
+
+START_TESTCASE                  KBASE-t_rmdebug2_oem
+RUN_PROGRAM 120 t_rmdebug2_oem
+END_TESTCASE                    KBASE-t_rmdebug2_oem
+
+
+START_TESTCASE                  KBASE-t_rmdebug2_oem2
+RUN_PROGRAM 120 t_rmdebug2_oem2
+END_TESTCASE                    KBASE-t_rmdebug2_oem2
+
+
+START_TESTCASE                  KBASE-t_rmdebug2_allcaps
+RUN_PROGRAM 120 t_rmdebug2_allcaps
+END_TESTCASE                    KBASE-t_rmdebug2_allcaps
+
+
+START_TESTCASE                  KBASE-t_performance_test
+RUN_PROGRAM 120 t_performance_test
+END_TESTCASE                    KBASE-t_performance_test
+
+
+START_TESTCASE                  KBASE-t_rmdebug_multi_target
+RUN_PROGRAM 120 t_rmdebug_multi_target
+END_TESTCASE                    KBASE-t_rmdebug_multi_target
+
+
+START_TESTCASE                  KBASE-t_multi_agent_launcher
+RUN_PROGRAM 120 t_multi_agent_launcher
+END_TESTCASE                    KBASE-t_multi_agent_launcher
+
+PRINT *** Completed RTests as TEF3 tests ***
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/debugsrv/runmodedebug/rmdriver/group/bld.inf	Fri Aug 27 11:37:29 2010 +0300
@@ -0,0 +1,52 @@
+// Copyright (c) 2007-2010 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+// e32/drivers/debug/bld.inf
+// Run mode debugger
+// 
+//
+
+/**
+ @file
+*/
+
+
+PRJ_PLATFORMS
+
+BASEDEFAULT
+
+PRJ_EXPORTS
+
+../../securityServer/inc/rm_debug_api.h SYMBIAN_OS_LAYER_PLATFORM_EXPORT_PATH(rm_debug_api.h)
+rm_debug_svr.iby						/epoc32/rom/include/	// Run mode debug driver
+
+PRJ_MMPFILES
+
+#ifndef GCCXML
+
+#if defined(GENERIC_MARM) || defined(WINS) || defined(GENERIC_X86)
+#if !defined(MARM_THUMB) && !defined(MARM_ARMI)
+
+#if defined(MARM_ARMV5) || defined(MARM_ARMV4)
+
+
+rm_debug_kerneldriver
+../../securityServer/group/rm_debug_svr
+
+#endif
+
+#endif
+#endif
+
+
+#endif //#ifndef GCCXML
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/debugsrv/runmodedebug/rmdriver/group/rm_debug_kerneldriver.mmh	Fri Aug 27 11:37:29 2010 +0300
@@ -0,0 +1,50 @@
+// Copyright (c) 2009-2010 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+//
+
+OS_LAYER_SYSTEMINCLUDE
+
+#include <kernel/kern_ext.mmh>
+
+
+UID             0x100000AF 0x101F7157
+
+SOURCEPATH      ../src
+SOURCE          d_list_manager.cpp
+SOURCE          rm_debug_kerneldriver.cpp
+SOURCE          rm_debug_eventhandler.cpp
+SOURCE          d_process_tracker.cpp
+SOURCE          d_target_process.cpp
+SOURCE          d_debug_agent.cpp
+SOURCE          d_rmd_breakpoints.cpp
+SOURCE          d_rmd_stepping.cpp
+SOURCE          d_driver_event_info.cpp
+SOURCE          d_debug_functionality.cpp
+SOURCE          debug_utils.cpp
+
+#ifdef SYMBIAN_OLD_EXPORT_LOCATION
+SYMBIAN_BASE_SYSTEMINCLUDE(memmodel/epoc/mmubase)
+SYMBIAN_BASE_SYSTEMINCLUDE(drivers)
+#endif
+
+userinclude		../inc
+
+VENDORID 0x70000001
+
+//Specified to allow global data
+EPOCALLOWDLLDATA
+
+capability			all
+
+SMPSAFE
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/debugsrv/runmodedebug/rmdriver/group/rm_debug_kerneldriver.mmp	Fri Aug 27 11:37:29 2010 +0300
@@ -0,0 +1,20 @@
+// Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+//
+
+#include "rm_debug_kerneldriver.mmh"
+
+TARGET			rm_debug.ldd
+
+TARGETTYPE LDD
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/debugsrv/runmodedebug/rmdriver/group/rm_debug_svr.iby	Fri Aug 27 11:37:29 2010 +0300
@@ -0,0 +1,48 @@
+/*
+* Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+* All rights reserved.
+* This component and the accompanying materials are made available
+* under the terms of the License "Eclipse Public License v1.0"
+* which accompanies this distribution, and is available
+* at the URL "http://www.eclipse.org/legal/epl-v10.html".
+*
+* Initial Contributors:
+* Nokia Corporation - initial contribution.
+*
+* Contributors:
+*
+* Description:
+*
+*/
+#ifndef __RM_DEBUG_SVR_IBY__
+#define __RM_DEBUG_SVR_IBY__
+
+#ifndef INST_ARM4
+#ifdef KMAIN
+
+// Debug Device Driver
+extension[VARID]=  \Epoc32\Release\##KMAIN##\##BUILD##\rm_debug.ldd		\sys\bin\rm_debug.ldd
+
+// Debug Security Server
+file=			\Epoc32\Release\##MAIN##\##BUILD##\rm_debug_svr.exe		\sys\bin\rm_debug_svr.exe
+
+#endif
+
+#ifndef KMAIN
+
+// Debug Device Driver
+#ifdef STOP_MODE_DEBUGGING_V2
+extension[VARID]=KERNEL_DIR\DEBUG_DIR\rm_debug_ext.ldd		\sys\bin\rm_debug.ldd
+#else
+extension[VARID]=KERNEL_DIR\DEBUG_DIR\rm_debug.ldd		\sys\bin\rm_debug.ldd
+#endif
+
+// Debug Security Server
+file=KERNEL_DIR\DEBUG_DIR\rm_debug_svr.exe		\sys\bin\rm_debug_svr.exe
+
+#endif
+
+
+#endif	// INST_ARM4
+
+#endif	// __RM_DEBUG_SVR_IBY__
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/debugsrv/runmodedebug/rmdriver/group/sis/eula.txt	Fri Aug 27 11:37:29 2010 +0300
@@ -0,0 +1,1 @@
+RMDebug Test Sw. For Nokia use only.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/debugsrv/runmodedebug/rmdriver/group/sis/mk_rmdbg.bat	Fri Aug 27 11:37:29 2010 +0300
@@ -0,0 +1,18 @@
+@rem
+@rem Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+@rem All rights reserved.
+@rem This component and the accompanying materials are made available
+@rem under the terms of "Eclipse Public License v1.0"
+@rem which accompanies this distribution, and is available
+@rem at the URL "http://www.eclipse.org/legal/epl-v10.html".
+@rem
+@rem Initial Contributors:
+@rem Nokia Corporation - initial contribution.
+@rem
+@rem Contributors:
+@rem
+@rem Description: 
+@rem
+
+makesis rmdbg.pkg
+signsis rmdbg.sis rmdbg.sisx  RDTest_02.der RDTest_02.key
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/debugsrv/runmodedebug/rmdriver/group/sis/rmdbg.pkg	Fri Aug 27 11:37:29 2010 +0300
@@ -0,0 +1,48 @@
+;
+; Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+; All rights reserved.
+; This component and the accompanying materials are made available
+; under the terms of "Eclipse Public License v1.0"
+; which accompanies this distribution, and is available
+; at the URL "http://www.eclipse.org/legal/epl-v10.html".
+;
+; Initial Contributors:
+; Nokia Corporation - initial contribution.
+;
+; Contributors:
+;
+; Description: 
+;
+
+
+
+;Languages
+&EN
+
+;Header
+#{"RMDBG"},(0x101F7157),1,4,1, TYPE=SA,RU
+
+
+;Localised Vendor name
+%{"Nokia"}
+
+;Unique Vendor name
+:"Nokia"
+
+;Supports Series 60 v 5.0
+[0x1028315], 0, 0, 0, {"Series60ProductID"}
+
+"eula.txt"-"", FILETEXT, TEXTEXIT
+
+; Files to install
+; Note D Drive is RAM in HW79 products
+
+"\epoc32\release\armv5\udeb\rm_debug_svr.exe"		-"d:\sys\bin\rm_debug_svr.exe"
+"\epoc32\release\armv5\udeb\rm_debug.ldd"				-"d:\sys\bin\rm_debug.ldd"
+
+
+; Required files
+; None
+
+; Component .sis files
+; None
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/debugsrv/runmodedebug/rmdriver/inc/d_debug_agent.h	Fri Aug 27 11:37:29 2010 +0300
@@ -0,0 +1,151 @@
+// Copyright (c) 2006-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+// Purpose: Kernel-side tracking of debug agent information associated
+// with each process being debugged.
+// 
+//
+
+#ifndef D_DEBUG_AGENT_H
+#define D_DEBUG_AGENT_H
+
+#include <rm_debug_api.h>
+#include "d_driver_event_info.h"
+
+/**
+* Handles events from the kernel, filters them according to the debug agent's requests, 
+* and signals these events to the user side in FIFO-style. 
+* @see TKernelEventAction
+* @see TEventInfo
+*/
+class DDebugAgent : public DBase
+	{
+public:
+	static DDebugAgent* New(TUint64 aId);
+	~DDebugAgent();
+
+	TInt SetEventAction(Debug::TEventType aEvent, Debug::TKernelEventAction aEventAction);
+	void GetEvent(TClientDataRequest<Debug::TEventInfo>* aAsyncGetValueRequest, DThread* aClientThread);
+	TInt EventAction(Debug::TEventType aEvent);
+
+	TInt CancelGetEvent(void);
+	void NotifyEvent(const TDriverEventInfo& aEventInfo);
+	TUint64 Id();
+
+protected:
+	DDebugAgent(TUint64 aId);
+	TInt Construct();
+
+private:
+	void QueueEvent(const TDriverEventInfo& aEventInfo);
+	TBool BufferEmpty() const;
+	TBool BufferFull() const;
+	TBool BufferCanStoreEvent() const;
+	TBool BufferAtCriticalLevel() const;
+	void IncrementHeadPosition(void);
+	void IncrementTailPosition(void);
+	TInt NumberOfEmptySlots() const;
+	void LockEventQueue(void);
+	void UnlockEventQueue(void);
+
+private:
+
+	TUint64	iId;
+	Debug::TKernelEventAction iEventActions[Debug::EEventsLast];
+
+	/**
+	* Object used to write events back to DSS thread
+	* @see TEventInfo
+	*/
+	TClientDataRequest<Debug::TEventInfo>* iRequestGetEventStatus;
+
+	DThread* iClientThread;
+
+	/** 
+	* Ring buffer of pending events. Access to it is controlled by 
+	* @see iEventQueueLock
+	*/
+	RArray<TDriverEventInfo> iEventQueue;
+
+	/**
+	* Ring buffer head. Points to the next empty slot in iEventQueue
+	* @see iEventQueue
+	*/
+	TInt iHead;	
+
+	/**
+	* Ring buffer tail. Points to the oldest full slot in iEventQueue
+	* @see iEventQueue 
+	*/
+	TInt iTail;
+
+	/** 
+	* Control access to event queue.
+	* @see iEventQueue
+	*/
+	DSemaphore* iEventQueueLock;
+
+	/**
+	* Keeps track of how many free slots are available in the event queue.
+	* @see iEventQueue
+	*/
+	TInt iFreeSlots;
+
+	/**
+	* Boolean to indicate if we have told the agent that we are ignoring trace events
+	* @see QueueEvent
+	*/
+	TBool iIgnoringTrace;
+	
+	/**
+	* Used to control the delivery of events to the client so that only 
+	* when more requests than deliveries have taken place can we deliver the 
+	* next event
+	* 
+	* Incremented when a request for event takes place
+	* @see GetEvent
+	* 
+	* Decremented when an event is delivered. 
+	* @see NotifyEvent
+	* 
+	* Cleared when event requests are cancelled
+	* @see CancelGetEvent
+	* 
+	*/
+	TInt   iEventBalance;
+
+	/**
+	* Length of kernel-event queue.
+	* This is a power of two for efficiency when using the 
+	* remainder operator
+	* @see DDebugAgent::iEventQueue
+	*/
+	static const TUint KNumberOfEventsToQueue = 128;
+
+	/**
+	* This determines the number of events at which we stop accepting 
+	* low priority events into the event queue.
+	* @see DDebugAgent::BufferAtCriticalLevel
+	* @see DDebugAgent::iEventQueue
+	*/
+	static const TUint KCriticalBufferSize = 64;
+
+	/**
+	* If we encounter an event that will take down the agent (eg a process critical thread crashing)
+	* we use this flag to stop trying to deliver thread death notifications to it.
+	*/
+	TBool iAgentDying;
+	};
+
+#endif // D_DEBUG_AGENT_H
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/debugsrv/runmodedebug/rmdriver/inc/d_debug_agent.inl	Fri Aug 27 11:37:29 2010 +0300
@@ -0,0 +1,109 @@
+// Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+// Inline methods for debug agent class
+//
+
+
+/**
+ @file
+ @internalComponent
+ @released
+*/
+
+#ifndef D_DEBUG_AGENT_INL
+#define D_DEBUG_AGENT_INL
+
+
+/**
+ Checks whether the event queue is empty
+*/
+inline TBool DDebugAgent::BufferEmpty() const
+	{
+	return (NumberOfEmptySlots() == KNumberOfEventsToQueue);
+	}
+
+/**
+ Checks whether the event queue is full
+*/
+inline TBool DDebugAgent::BufferFull() const
+	{
+	return (NumberOfEmptySlots() == 0);
+	}
+
+/**
+ Checks whether there is room in the event queue to store an event
+*/
+inline TBool DDebugAgent::BufferCanStoreEvent() const
+	{
+	return (NumberOfEmptySlots() > 0);
+	}
+
+/**
+ This looks to see if the buffer is close to being full and should only
+ accept higher priority debug events (user trace is the only low priority event) 
+*/
+inline TBool DDebugAgent::BufferAtCriticalLevel() const
+	{
+	return (NumberOfEmptySlots() < KNumberOfEventsToQueue - KCriticalBufferSize);
+	}
+
+/**
+ Increments Head position, wrapping at KNumberOfEventsToQueue if necessary
+*/
+inline void DDebugAgent::IncrementHeadPosition(void)
+	{
+	iHead = (iHead + 1) % KNumberOfEventsToQueue;
+
+	iFreeSlots--;
+	}
+
+/**
+ Increments Tail position, wrapping at KNumberOfEventsToQueue if necessary
+*/
+inline void DDebugAgent::IncrementTailPosition(void)
+	{
+	iTail = (iTail + 1) % KNumberOfEventsToQueue;
+
+	iFreeSlots++;
+}
+
+/**
+ Returns the number of free slots in the event queue
+*/
+inline TInt DDebugAgent::NumberOfEmptySlots() const
+	{
+	return iFreeSlots;
+	}
+
+/**
+ Lock access to this agent's event queue
+*/
+inline void DDebugAgent::LockEventQueue(void)
+	{
+	NKern::ThreadEnterCS(); // Waiting on a semaphore is broken but this makes things marginally better.
+	// Anyone changing this, bear in mind the CS is also needed for some of the DebugUtils::OpenThreadHandle calls
+	Kern::SemaphoreWait(*iEventQueueLock);
+	}
+
+/**
+ Release the lock on this agent's event queue
+*/
+inline void DDebugAgent::UnlockEventQueue(void)
+	{
+	Kern::SemaphoreSignal(*iEventQueueLock);
+	NKern::ThreadLeaveCS();
+	}
+
+
+#endif	// D_DEBUG_AGENT_INL
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/debugsrv/runmodedebug/rmdriver/inc/d_debug_functionality.h	Fri Aug 27 11:37:29 2010 +0300
@@ -0,0 +1,40 @@
+// Copyright (c) 2006-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+// Internal class used to assemble debug functionality data block
+// 
+
+#ifndef T_DEBUG_FUNCTIONALITY_H
+#define T_DEBUG_FUNCTIONALITY_H
+
+/**
+ * This class is used to represent and assemble the debug functionality
+ * block
+ */
+class TDebugFunctionality
+	{
+
+	public:
+		TUint32 GetDebugFunctionalityBufSize(void);
+		TBool GetDebugFunctionality(TDes8& aDFBlock);
+		static TInt GetRegister(const Debug::TRegisterInfo aRegisterInfo, Debug::TTag& aTag);
+		static TUint32 GetMemoryOperationMaxBlockSize();
+
+	private:
+
+		// Helper functions when assembling the buffer
+		void AppendBlock(const Debug::TSubBlock& aDFSubBlock, TDes8& aDFBlock);
+		TUint32 ComputeBlockSize(const Debug::TSubBlock& aDFSubBlock);
+};
+
+#endif	// T_DEBUG_FUNCTIONALITY_H
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/debugsrv/runmodedebug/rmdriver/inc/d_driver_event_info.h	Fri Aug 27 11:37:29 2010 +0300
@@ -0,0 +1,90 @@
+// Copyright (c) 2007-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+// Purpose: Kernel-side tracking of event information
+//
+//
+
+#ifndef T_DRIVER_EVENT_INFO_H
+#define T_DRIVER_EVENT_INFO_H
+
+#include <rm_debug_api.h>
+#include <kernel/kernel.h> 
+
+/**
+@file
+@internalComponent
+*/
+
+class TDriverEventInfo
+	{
+public:
+	TDriverEventInfo();
+	void Reset();
+	TInt WriteEventToClientThread(TClientDataRequest<Debug::TEventInfo>* aAsyncGetValueRequest, DThread* aClientThread) const;
+	TBool FreezeOnSuspend() const;
+
+private:
+	TInt PopulateCommonEventInfo(Debug::TEventInfo& aEventInfo) const;
+	TInt PopulateEventSpecificInfo(Debug::TEventInfo& aEventInfo) const;
+	TInt PopulateThreadBreakPointInfo(Debug::TEventInfo& aEventInfo) const;
+	TInt PopulateThreadHwExceptionInfo(Debug::TEventInfo& aEventInfo) const;
+	TInt PopulateThreadSwExceptionInfo(Debug::TEventInfo& aEventInfo) const;
+	TInt PopulateThreadKillInfo(Debug::TEventInfo& aEventInfo) const;
+	TInt PopulateLibraryLoadedInfo(Debug::TEventInfo& aEventInfo) const;
+	TInt PopulateLibraryUnloadedInfo(Debug::TEventInfo& aEventInfo) const;
+	TInt PopulateRmdArmExcInfo(Debug::TEventInfo& aEventInfo) const;
+	TInt PopulateUserTraceInfo(Debug::TEventInfo& aEventInfo) const;
+	TInt PopulateStartThreadInfo(Debug::TEventInfo& aEventInfo) const;
+	TInt PopulateAddProcessInfo(Debug::TEventInfo& aEventInfo) const;
+	TInt PopulateRemoveProcessInfo(Debug::TEventInfo& aEventInfo) const;
+	TBool TookException() const;
+
+public:
+	Debug::TEventType iEventType;
+	TUint64 iProcessId;
+	TUint64 iThreadId;
+	TUint64 iCreatorThreadId;
+	TUint32 iCurrentPC;
+	TInt iExceptionNumber;
+	TBuf8<KMaxName> iFileName;
+	TBuf8<Debug::KPanicCategoryMaxName> iPanicCategory;
+	TUint32 iCodeAddress;
+	TUint32 iDataAddress;
+	TUint8 iExitType;
+	TUint8 iThreadIdValid;
+	TUint8 iProcessIdValid;
+	TUidType iUids;
+	TUint8 iUidsValid;
+	Debug::TKernelEventAction iActionTaken;
+	TUint32 iThreadFlags;
+
+	//The objects that these pointers point to are not
+	//owned by the Debug::TEventInfo class so no cleanup is required
+	TAny* iArg1;	// a1
+	TAny* iArg2;	// a2
+
+	union
+	{
+		Debug::TRmdArmExcInfo iRmdArmExcInfo;
+		//To store Trace info
+		TUint8 iUserTraceText[Debug::TUserTraceSize];
+	};
+
+	//status of trace message
+	Debug::TUserTraceMessageContext iMessageStatus;
+
+	};
+
+
+#endif //T_DRIVER_EVENT_INFO_H
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/debugsrv/runmodedebug/rmdriver/inc/d_list_manager.h	Fri Aug 27 11:37:29 2010 +0300
@@ -0,0 +1,57 @@
+// Copyright (c) 2007-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+// Definitions for the list manager
+// 
+//
+
+#ifndef T_LIST_MANAGER_H
+#define T_LIST_MANAGER_H
+
+#include <e32cmn.h>
+#include <kernel/kern_priv.h>
+#include <rm_debug_api.h>
+
+/**
+@file
+@internalComponent
+@released
+*/
+
+class TListManager
+{
+public:
+	TInt GetThreadListForThread(TDes8& aBuffer, TUint32& aDataSize, const TUint64 aTargetThreadId) const;
+	TInt GetThreadListForProcess(TDes8& aBuffer, TUint32& aDataSize, const TUint64 aTargetProcessId) const;
+	TInt GetGlobalThreadList(TDes8& aBuffer, TUint32& aDataSize) const;
+	TInt GetProcessList(TDes8& aBuffer, TUint32& aDataSize) const;
+	TInt GetCodeSegListForThread(TDes8& aBuffer, TUint32& aDataSize, const TUint64 aTargetThreadId) const;
+	TInt GetCodeSegListForProcess(TDes8& aBuffer, TUint32& aDataSize, const TUint64 aTargetProcessId) const;
+	TInt GetGlobalCodeSegList(TDes8& aBuffer, TUint32& aDataSize) const;
+	TInt GetXipLibrariesList(TDes8& aBuffer, TUint32& aDataSize) const;
+private:
+	TInt GetThreadList(TDes8& aBuffer, TUint32& aDataSize, TBool aGlobal, const TUint64 aTargetProcessId) const;
+	TInt GetDirectoryContents(RPointerArray<TRomEntry>& aRomEntryArray, const TLinAddr aAddress) const;
+	TInt GetDirectoryEntries(RPointerArray<TRomEntry>& aRomEntryArray, const TDesC& aDirectoryName) const;
+	TInt FindDirectory(const TDesC& aDirectory, TLinAddr& aAddress) const;
+	TInt GetDirectoryEntries(RPointerArray<TRomEntry>& aRomEntryArray, RArray<TPtr8>& aArray, TLinAddr& aAddress) const;
+
+	TInt AppendCodeSegData(TDes8& aBuffer, TUint32& aDataSize, const TModuleMemoryInfo& aMemoryInfo, const TBool aIsXip, const Debug::TCodeSegType aCodeSegType, const TDesC8& aFileName, const TUint32 aUid3) const;
+	void AppendThreadData(TDes8& aBuffer, TUint32& aDataSize, DThread* aThread) const;
+	TInt CopyAndExpandDes(const TDesC& aSrc, TDes& aDest) const;
+	TInt GetCodeSegType(const DCodeSeg* aCodeSeg, Debug::TCodeSegType& aType) const;
+	TInt SplitDirectoryName(const TDesC& aDirectoryName, RArray<TPtr8>& aSubDirectories) const;
+};
+
+#endif //T_LIST_MANAGER_H
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/debugsrv/runmodedebug/rmdriver/inc/d_process_tracker.h	Fri Aug 27 11:37:29 2010 +0300
@@ -0,0 +1,73 @@
+// Copyright (c) 2006-2010 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+// Purpose: Kernel-side tracking of process state
+// 
+//
+ 
+#ifndef D_PROCESS_TRACKER_H
+#define D_PROCESS_TRACKER_H
+
+#include "d_target_process.h"
+
+// The global class which tracks all debugged processes.
+// 
+// Note that multiple debug agents may attach to a process,
+// as the security server will ensure only one is an 'active'
+// agent, preventing conflicts. Other agents will be 'passive',
+// typically interested only in recording events.
+//
+// The above requirement generates the requirement for the class
+// to track the agent IDs, as multiple debug agents may be interested
+// in a process.
+
+class DProcessTracker : public DBase
+{
+public:
+	DProcessTracker();
+	~DProcessTracker();
+
+	TInt AttachProcess(const TDesC8& aProcessName, TUint64 aAgentId);
+
+	TInt DetachProcess(const TDesC8& aProcessName, TUint64 aAgentId);
+
+	TInt DetachAgent(TUint64 aAgentId);
+
+	DTargetProcess* FindProcess(const TDesC8& aProcessName) const;
+	DTargetProcess* FuzzyFindProcess(const TDesC8& aProcessName);
+
+	DDebugAgent* GetCurrentAgentAttachedToAll() const;
+	DDebugAgent* FindAgentForProcessAndId(const TDesC8& aProcessName, TUint64 aAgentId) const;
+	TBool NotifyAgentsForProcessEvent(const TDesC8& aProcessName, const TDriverEventInfo& aEvent, TBool aAllowFuzzy=EFalse);
+
+	TInt SuspendThread(DThread* aTargetThread, TBool aFreezeThread=EFalse);
+	TInt ResumeThread(DThread* aTargetThread);
+	void FSWait();
+	TInt ResumeFrozenThread(DThread* aThread);
+	TInt FreezeThread();
+
+private:
+	TInt RemoveSuspendedThread(DThread* aThread);
+	TInt AddSuspendedThread(DThread* aThread);
+	const TDesC8* GetFileName(DThread* aThread) const;
+
+private:
+	RPointerArray<DTargetProcess> iProcesses;
+	RPointerArray<DDebugAgent> iAgentsAttachedToAll;
+	RPointerArray<NFastSemaphore> iFrozenThreadSemaphores;
+	};
+
+// static global object
+extern DProcessTracker TheDProcessTracker;
+
+#endif // D_PROCESS_TRACKER_H
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/debugsrv/runmodedebug/rmdriver/inc/d_rmd_breakpoints.h	Fri Aug 27 11:37:29 2010 +0300
@@ -0,0 +1,213 @@
+// Copyright (c) 2004-2010 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+// Refactored class containing breakpoint related code from rm_debug_kerneldriver.cpp
+//
+
+
+
+/**
+ @file
+ @internalComponent
+ @released
+*/
+
+#ifndef D_RMD_BREAKPOINTS_H
+#define D_RMD_BREAKPOINTS_H
+
+#include <rm_debug_api.h>
+#include <kernel/kern_priv.h>
+#include "rm_debug_kerneldriver.h"
+
+// fwd declaration of friend classes needed due to re-factoring
+class DRM_DebugChannel;
+
+class DRMDStepper;
+
+//
+// Macros
+//
+const TUint32 KArmBreakPoint = 0xE7F123F4;
+const TUint16 KThumbBreakPoint = 0xDE56;
+const TUint16 KT2EEBreakPoint = 0xC100;	// From ARM ARM DDI0406A, section A9.2.1 Undefined instruction encoding for Thumb2-EE.
+
+#define NUMBER_OF_TEMP_BREAKPOINTS 10
+
+#define NUMBER_OF_MAX_BREAKPOINTS 100
+
+//
+// class TBreakEntry
+//
+class TBreakEntry
+{
+public:
+
+	inline TBreakEntry() { Reset(); };
+
+	inline TBreakEntry(Debug::TBreakId aBreakId, TUint64 aId, TBool aThreadSpecific, TUint32 aAddress, Debug::TArchitectureMode aMode)
+			: iBreakId(aBreakId),
+			  iId(aId),
+			  iAddress(aAddress),
+			  iMode(aMode),
+			  iThreadSpecific(aThreadSpecific)
+	{
+		 iInstruction.FillZ(4);
+		 iPageAddress = 0;
+		 iDisabledForStep = EFalse;
+		 iObsoleteLibraryBreakpoint = EFalse;
+		 iResumeOnceOutOfRange = EFalse;
+		 iSteppingInto = EFalse;
+		 iRangeStart = 0;
+		 iRangeEnd = 0;
+		 iStepTarget = EFalse;
+		 iNumSteps = 0;
+	};
+	
+	inline void Reset()
+	{
+		 iId = 0;
+		 iAddress = 0;
+		 iMode = Debug::EArmMode;
+		 iInstruction.FillZ(4);
+		 iPageAddress = 0;
+		 iDisabledForStep = EFalse;
+		 iObsoleteLibraryBreakpoint = EFalse;
+		 iResumeOnceOutOfRange = EFalse;
+		 iSteppingInto = EFalse;
+		 iRangeStart = 0;
+		 iRangeEnd = 0;
+		 iStepTarget = EFalse;
+		 iNumSteps = 0;
+	};
+
+public:
+	// Unique Id for this breakpoint. Assigned by D_RMD_Breakpoints::DoSetBreak(). @see D_RMD_Breakpoints::DoSetBreak
+	TInt32		iBreakId;
+	// Consider making the iId into a union of TProcessId, TThreadId, global etc. to make things more obvious
+	// Object Id in which this breakpoint should operate.
+	TUint64		iId;
+	// Address at which this breakpoint should operate
+	TUint32		iAddress;
+	// CPU ISA which this breakpoint uses, e.g. EArmMode/EThumbMode.
+	Debug::TArchitectureMode iMode;
+	// The original instruction which was stored at iAddress.
+	TBuf8<4>	iInstruction;
+	TUint32		iPageAddress;   //not used: BC if we remove it
+
+	// Indicates whether this breakpoint has been temporarily replaced with original instruction to enable step-off this breakpoint
+	TBool		iDisabledForStep;
+	/* This is used when libraries and processes are removed, so that
+	 * the driver can say 'ok' when requested to remove breakpoints
+	 * that existed in these cases, rather than 'Not Found'.
+	 *
+	 * Its not logical, but its a BC break if we change it :-(
+	 */
+	TBool		iObsoleteLibraryBreakpoint;
+	// Indicates whether this thread should be resumed after stepping off this breakpoint
+	TBool		iResumeOnceOutOfRange;
+	TBool		iSteppingInto;
+	TUint32		iRangeStart;
+	TUint32		iRangeEnd;
+	TBool		iThreadSpecific;
+	TBool		iStepTarget;
+
+	// Indicates how many more instruction steps should occur after hitting this breakpoint
+	TInt		iNumSteps;
+};
+/**
+@internalTechnology
+
+This class encapsulates all the data concerning run-mode and stop mode breakpoints
+as understood by the run-mode and stop-mode debug system.
+
+Note:                                                                        
+	The internal list of breakpoints is currently divided into two sections. The range from
+	0...NUMBER_OF_TEMP_BREAKPOINTS is used internally by the debug driver for implementing
+	stepping. The range from NUMBER_OF_TEMP_BREAKPOINTS to NUMBER_OF_MAX_BREAKPOINTS is used
+	to store information about breakpoints set by the client debug agents.
+                                                                                                                                                            
+	In future, this should change, so that each breakpoint knows what kind of breakpoint it
+	is (user/temp etc).
+
+
+*/
+class D_RMD_Breakpoints : public DBase
+{
+public:
+	D_RMD_Breakpoints(DRM_DebugChannel* aChannel);
+	~D_RMD_Breakpoints();
+
+	TInt Init();
+
+	// from rm_debug_driver.h
+	TInt DoSetBreak(TInt32 &aBreakId, const TUint64 aId, const TBool aThreadSpecific, const TUint32 aAddress, const Debug::TArchitectureMode aMode );
+	TInt DoEnableBreak(TBreakEntry &aEntry, TBool aSaveOldInstruction);
+	TInt DoClearBreak(const TInt32 aBreakId, TBool aIgnoreTerminatedThreads=EFalse);
+	TInt DoModifyBreak(TModifyBreakInfo* aBreakInfo);
+	TInt DoModifyProcessBreak(TModifyProcessBreakInfo* aBreakInfo);
+	TInt DoBreakInfo(TGetBreakInfo* aBreakInfo);
+	void ClearAllBreakPoints();
+	TInt DisableBreakAtAddress(TUint32 aAddress);
+	TInt DoEnableDisabledBreak(TUint64 aThreadId);
+
+	void DoRemoveThreadBreaks(TUint64 aThreadId);
+	void RemoveBreaksForProcess(TUint64 aProcessId, TUint32 aCodeAddress, TUint32 aCodeSize);
+	void InvalidateLibraryBreakPoints(TUint32 aCodeAddress, TUint32 aCodeSize);
+	TInt BreakPointCount() const;
+	TBreakEntry* GetNextBreak(const TBreakEntry* aBreakEntry) const;
+	TBool IsTemporaryBreak(const TBreakEntry& aBreakEntry) const;
+
+	TInt DoGetBreakList(TUint32* aBuffer, const TUint32 aBufSize, const TUint32 aElement, TUint32& aLastElement);
+
+	// Useful helper functions for debugging breakpoint issues
+	inline void print_BreakpointsDisabledForStep();
+	inline void print_BreakpointsList();
+
+private:
+	// Locked versions of public functions
+	TInt priv_DoSetBreak(TInt32 &aBreakId, const TUint64 aId,  const TBool aThreadSpecific, const TUint32 aAddress, const Debug::TArchitectureMode aMode );
+	TInt priv_DoEnableBreak(TBreakEntry &aEntry, TBool aSaveOldInstruction);
+	TInt priv_DoClearBreak(const TInt32 aBreakId, TBool aIgnoreTerminatedThreads);
+	TInt priv_DoModifyBreak(TModifyBreakInfo* aBreakInfo);
+	TInt priv_DoModifyProcessBreak(TModifyProcessBreakInfo* aBreakInfo);
+	TInt priv_DoBreakInfo(TGetBreakInfo* aBreakInfo);	
+	TInt priv_DisableBreakAtAddress(TUint32 aAddress);
+	TInt priv_DoEnableDisabledBreak(TUint64 aThreadId);
+	void priv_DoRemoveThreadBreaks(TUint64 aThreadId);
+	void priv_ClearAllBreakPoints();
+	TBool priv_IsTemporaryBreak(const TBreakEntry& aBreakEntry) const;
+
+	// helper functions
+	TBool Aligned(TUint32 aAddress, Debug::TArchitectureMode aMode);
+	TInt BreakSize(Debug::TArchitectureMode aMode);
+	TBool BreakpointsOverlap(TBreakEntry& aFirst, TBreakEntry& aSecond);
+	TUint32 BreakInst(Debug::TArchitectureMode aMode);
+
+private:
+	RArray<TBreakEntry> iBreakPointList;
+	TInt iNextBreakId;
+
+	DRM_DebugChannel* iChannel;	// temporary reference back to DRM_DebugChannel to help with refactoring
+
+	/* Protect access to the breakpoint list with a DSemaphore
+	 *
+	 * This means that stop-mode debuggers know when the list is being updated by the run-mode debug subsystem.
+	 */
+	DSemaphore* iLock;
+
+	TBool iInitialised;
+};
+
+#include "d_rmd_breakpoints_debug.inl" 
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/debugsrv/runmodedebug/rmdriver/inc/d_rmd_breakpoints_debug.inl	Fri Aug 27 11:37:29 2010 +0300
@@ -0,0 +1,39 @@
+// Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+//
+
+#include "debug_logging.h"
+
+// Print breakpoints disabled for stepping
+inline void D_RMD_Breakpoints::print_BreakpointsDisabledForStep()
+	{
+	for (TInt i = 0; i < iBreakPointList.Count(); i++)
+		{
+		if(iBreakPointList[i].iDisabledForStep)
+			{
+				LOG_MSG2("Breakpoint disabled for stepping: iBreakPointList[%d]", i);
+				LOG_MSG4("iBreakId = %x, iId = %d, iAddress = %x", iBreakPointList[i].iBreakId, iBreakPointList[i].iId, iBreakPointList[i].iAddress );
+			}
+		}
+	}
+
+// Print breakpoint list
+inline void D_RMD_Breakpoints::print_BreakpointsList()
+	{
+	for (TInt i = NUMBER_OF_TEMP_BREAKPOINTS; i < iBreakPointList.Count(); i++)
+		{
+			LOG_MSG2("Breakpoint list: iBreakPointList[%d]", i);
+			LOG_MSG4("iBreakId = %x, iId = %d, iAddress = %x", iBreakPointList[i].iBreakId, iBreakPointList[i].iId, iBreakPointList[i].iAddress );
+		}
+	}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/debugsrv/runmodedebug/rmdriver/inc/d_rmd_stepping.h	Fri Aug 27 11:37:29 2010 +0300
@@ -0,0 +1,126 @@
+// Copyright (c) 2004-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+//
+
+#ifndef D_RMD_STEPPING_H
+#define D_RMD_STEPPING_H
+
+// fwd declaration of DRM_DebugChannel
+class DRM_DebugChannel;
+
+// extracted from rm_debug_kerneldriver.h
+// Register definitions
+#define SP_REGISTER			13
+#define LINK_REGISTER		14
+#define PC_REGISTER			15
+#define STATUS_REGISTER		16
+
+class DRMDStepping : public DBase
+{
+public:
+	// ctor
+	DRMDStepping(DRM_DebugChannel* aChannel);
+
+	// dtor
+	~DRMDStepping();
+
+	// extracted from rm_debug_kerneldriver.cpp
+	TBool IsExecuted(TUint8 aCondition, TUint32 aStatusRegister);
+	TBool IsPreviousInstructionMovePCToLR(DThread *aThread);
+	void DecodeDataProcessingInstruction(TUint8 aOpcode, TUint32 aOp1, TUint32 aOp2, TUint32 aStatusRegister, TUint32 &aBreakAddress);
+	TUint32 PCAfterInstructionExecutes(DThread *aThread, TUint32 aCurrentPC, TUint32 aStatusRegister, TInt aInstSize, TUint32 &aNewRangeEnd, TBool &aChangingModes);
+	TUint32 ShiftedRegValue(DThread *aThread, TUint32 aInstruction, TUint32 aCurrentPC, TUint32 aStatusRegister);
+	TInt ModifyBreaksForStep(DThread *aThread, TUint32 aRangeStart, TUint32 aRangeEnd,TBool aResumeOnceOutOfRange, TBool aCheckForStubs, const TUint32 aNumSteps);
+
+private:
+
+	// Needed to access private data until re-structuring work is complete.
+	friend class DRM_DebugChannel;
+
+	DRM_DebugChannel* iChannel;	// temporary reference back to DRM_DebugChannel to help with refactoring
+
+	// Set of inline functions for decoding instructions. Formerly these were all macros
+
+	// ARM instruction bitmasks
+	inline TUint32 arm_opcode(const TUint32 aInst);
+
+	// Generic instruction defines
+	inline TUint32 arm_rm(const TUint32 aInst);
+	inline TUint32 arm_rs(const TUint32 aInst);
+	inline TUint32 arm_rd(const TUint32 aInst);
+	inline TUint32 arm_rn(const TUint32 aInst);
+	inline TUint32 arm_load(const TUint32 aInst);
+
+	// Data processing instruction defines
+	inline TUint32 arm_data_shift(const TUint32 aInst);
+	inline TUint32 arm_data_c(const TUint32 aInst);
+	inline TUint32 arm_data_imm(const TUint32 aInst);
+	inline TUint32 arm_data_rot(const TUint32 aInst);
+
+	// Single date transfer instruction defines
+	inline TUint32 arm_single_imm(const TUint32 aInst);
+	inline TUint32 arm_single_byte(const TUint32 aInst);
+	inline TUint32 arm_single_u(const TUint32 aInst);
+	inline TUint32 arm_single_pre(const TUint32 aInst);
+
+	// Block data transfer instruction defines
+	inline TUint32 arm_block_reglist(const TUint32 aInst);
+	inline TUint32 arm_block_u(const TUint32 aInst);
+	inline TUint32 arm_block_pre(const TUint32 aInst);
+
+	// Branch instruction defines
+	inline TUint32 arm_b_addr(const TUint32 aInst);
+	inline TUint32 arm_instr_b_dest(const TUint32 aInst, TUint32& aAddr);
+	inline TUint32 thumb_b_addr(const TUint32 aInst);
+	inline TUint32 thumb_instr_b_dest(const TUint32 aInst, TUint32& aAddr);
+	inline TUint32 arm_carry_bit(void);
+	
+
+	// Thumb instruction bitmasks
+	inline TUint16 thumb_opcode(const TUint16 aInst);
+	inline TUint16 thumb_inst_7_15(const TUint16 aInst);
+	inline TUint16 thumb_inst_8_15(const TUint16 aInst);
+
+	// Thumb2 decode support functions
+	inline TUint16 t2opcode16(const TUint16 aInst);
+
+	inline TUint16 t2opcode16special(const TUint16 aInst);
+
+	// Helper functions
+	TInt CurrentPC(DThread* aThread, TUint32& aPC);
+
+	TInt CurrentCPSR(DThread* aThread, TUint32& aCPSR);	
+
+	TInt CurrentInstruction(DThread* aThread, TUint32& aInstruction);
+
+	TInt CurrentArchMode(const TUint32 cpsr, Debug::TArchitectureMode& mode);
+
+	TInt RegisterValue(DThread *aThread, const TUint32 aKernelRegisterId, TUint32 &aValue);
+
+	TInt ReadMem32(DThread* aThread, const TUint32 aAddress, TUint32& aValue);
+
+	TInt ReadMem16(DThread* aThread, const TUint32 aAddress, TUint16& aValue);
+
+	TInt ReadMem8(DThread* aThread, const TUint32 aAddress, TUint8& aValue);
+
+	inline TUint32 BitCount(const TUint32 aVal);
+
+	inline TUint32 IsBitSet(const TUint32 aBitset, const TUint8 aBitNum);
+};
+
+#include "d_rmd_stepping.inl"
+
+#endif	// D_RMD_STEPPPING_H
+
+// End of file - d-rmd-stepping.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/debugsrv/runmodedebug/rmdriver/inc/d_rmd_stepping.inl	Fri Aug 27 11:37:29 2010 +0300
@@ -0,0 +1,313 @@
+// Copyright (c) 2004-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+//
+
+
+
+/**
+ @file
+ @internalComponent
+ @released
+*/
+
+#ifndef D_RMD_STEPPING_INL
+#define D_RMD_STEPPING_INL
+
+//
+// IsBitSet
+//
+// Returns 1 if the bit 'aNum' is set within aBitset, 0 otherwise
+inline TUint32 DRMDStepping::IsBitSet(const TUint32 aBitset, const TUint8 aNum)
+	{
+	return (aBitset & (1 << aNum) );
+	}
+
+// 
+// BitCount
+//
+// Count number of bits in aVal
+inline TUint32 DRMDStepping::BitCount(const TUint32 aVal)
+	{
+	TUint32 num = 0;
+
+	for(TInt i = 0; i < 32; i++)
+		{
+		if ((1 << i) & aVal)
+			{
+			num++;
+			}
+		}
+	return num;
+	}
+
+//
+// Thumb2 opcode decoding
+//
+// Special data instructions and branch and exchange.
+//
+// Returns Opcode as defined in ARM ARM DDI0406A, section A6.2.3
+inline TUint16 DRMDStepping::t2opcode16special(const TUint16 aInst)
+	{
+	TUint8 aVal = (aInst & 0x03C0) >> 5;
+
+	return aVal;
+	}
+
+
+// Thumb2 opcode decoding instructions
+// 
+// Returns Opcode as defined in ARM ARM DDI0406A, section A6.2
+// 16-bit Thumb instruction encoding
+inline TUint16 DRMDStepping::t2opcode16(const TUint16 aInst)
+{
+	TUint16 aVal = (aInst & 0xFC00) >> 9;
+
+	return aVal;
+}
+
+// ARM opcode decoding functions
+inline TUint32 DRMDStepping::arm_opcode(const TUint32 aInst)
+{
+// #define ARM_OPCODE(x)		(((TUint32)(x) & 0x0E000000) >> 25)
+
+	TUint32 aVal = ((aInst) & 0x0E000000) >> 25;
+
+	return aVal;
+}
+
+inline TUint32 DRMDStepping:: arm_rm(const TUint32 aInst)
+{
+//#define ARM_RM(x)				((TUint32)(x) & 0x0000000F)			// bit 0- 4
+
+	TUint32 aVal = (aInst) & 0x0000000F;
+
+	return aVal;
+}
+
+inline TUint32 DRMDStepping:: arm_rs(const TUint32 aInst)
+{
+//#define ARM_RS(x)				(((TUint32)(x) & 0x00000F00) >> 8)	// bit 8-11
+
+	TUint32 aVal = ((aInst) & 0x00000F00) >> 8;
+
+	return aVal;
+}
+
+inline TUint32 DRMDStepping:: arm_rd(const TUint32 aInst)
+{
+//#define ARM_RD(x)				(((TUint32)(x) & 0x0000F000) >> 12)	// bit 12-15
+
+	TUint32 aVal = ((aInst) & 0x0000F000) >> 12;
+
+	return aVal;
+}
+
+inline TUint32 DRMDStepping:: arm_rn(const TUint32 aInst)
+{
+//#define ARM_RN(x)				(((TUint32)(x) & 0x000F0000) >> 16)	// bit 16-19
+
+	TUint32 aVal = ((aInst) & 0x000F0000) >> 16;
+
+	return aVal;
+}
+
+inline TUint32 DRMDStepping::arm_load(const TUint32 aInst)
+{
+//#define ARM_LOAD(x)				(((TUint32)(x) & 0x00100000) >> 20)	// bit 20
+
+	TUint32 aVal = ((aInst) & 0x00100000) >> 20;
+
+	return aVal;
+}
+
+// Data processing instruction defines
+inline TUint32 DRMDStepping::arm_data_shift(const TUint32 aInst)
+{
+//#define ARM_DATA_SHIFT(x)		(((TUint32)(x) & 0x00000060) >> 5) 	// bit 5- 6
+	
+	TUint32 aVal = ((aInst) & 0x00000060) >> 5;
+
+	return aVal;
+}
+
+inline TUint32 DRMDStepping::arm_data_c(const TUint32 aInst)
+{
+//#define ARM_DATA_C(x)			(((TUint32)(x) & 0x00000F80) >> 7) 	// bit 7-11
+
+	TUint32 aVal = ((aInst) & 0x00000F80) >> 7;
+
+	return aVal;
+}
+
+inline TUint32 DRMDStepping::arm_data_imm(const TUint32 aInst)
+{
+//#define ARM_DATA_IMM(x)			((TUint32)(x) & 0x000000FF)			// bit 0-7
+
+	TUint32 aVal = (aInst) & 0x000000FF;
+
+	return aVal;
+}
+
+inline TUint32 DRMDStepping::arm_data_rot(const TUint32 aInst)
+{
+//#define ARM_DATA_ROT(x)			(((TUint32)(x) & 0x00000F00) >> 8) 	// bit 8-11
+
+	TUint32 aVal = ((aInst) & 0x00000F00) >> 8;
+
+	return aVal;
+}
+
+// Single date transfer instruction defines
+inline TUint32 DRMDStepping::arm_single_imm(const TUint32 aInst)
+{
+//#define ARM_SINGLE_IMM(x)		((TUint32)(x) & 0x00000FFF)			// bit 0-11
+
+	TUint32 aVal = (aInst) & 0x00000FFF;
+
+	return aVal;
+}
+
+inline TUint32 DRMDStepping::arm_single_byte(const TUint32 aInst)
+{
+//#define ARM_SINGLE_BYTE(x)		(((TUint32)(x) & 0x00400000) >> 22)	// bit 22
+
+	TUint32 aVal = ((aInst) & 0x00400000) >> 22;
+
+	return aVal;
+}
+
+inline TUint32 DRMDStepping::arm_single_u(const TUint32 aInst)
+{
+//#define ARM_SINGLE_U(x)			(((TUint32)(x) & 0x00800000) >> 23)	// bit 23
+
+	TUint32 aVal = ((aInst) & 0x00800000) >> 23;
+
+	return aVal;
+}
+
+inline TUint32 DRMDStepping::arm_single_pre(const TUint32 aInst)
+{
+//#define ARM_SINGLE_PRE(x)		(((TUint32)(x) & 0x01000000) >> 24)	// bit 24
+
+	TUint32 aVal = ((aInst) & 0x01000000) >> 24;
+
+	return aVal;
+}
+
+// Block data transfer instruction defines
+inline TUint32 DRMDStepping::arm_block_reglist(const TUint32 aInst)
+{
+//#define ARM_BLOCK_REGLIST(x)	((TUint32)(x) & 0x0000FFFF)		// bit 0-15
+
+	TUint32 aVal = (aInst) & 0x0000FFFF;
+
+	return aVal;
+}
+
+inline TUint32 DRMDStepping::arm_block_u(const TUint32 aInst)
+{
+//#define ARM_BLOCK_U(x)			(((TUint32)(x) & 0x00800000) >> 23)	// bit 23
+
+	TUint32 aVal = ((aInst) & 0x00800000) >> 23;
+
+	return aVal;
+}
+
+inline TUint32 DRMDStepping::arm_block_pre(const TUint32 aInst)
+{
+//#define ARM_BLOCK_PRE(x)		(((TUint32)(x) & 0x01000000) >> 24)	// bit 24
+
+	TUint32 aVal = ((aInst) & 0x01000000) >> 24;
+
+	return aVal;
+}
+
+// Branch instruction defines
+inline TUint32 DRMDStepping::arm_b_addr(const TUint32 aInst)
+{
+//#define ARM_B_ADDR(x)			((x & 0x00800000) ? ((TUint32)(x) & 0x00FFFFFF | 0xFF000000) : (TUint32)(x) & 0x00FFFFFF)
+
+	TUint32 aVal = ((aInst & 0x00800000) ? ((TUint32)(aInst) & 0x00FFFFFF | 0xFF000000) : (TUint32)(aInst) & 0x00FFFFFF);
+
+	return aVal;
+}
+
+inline TUint32 DRMDStepping::arm_instr_b_dest(const TUint32 aInst, TUint32& aAddress)
+{
+//#define ARM_INSTR_B_DEST(x,a)	(ARM_B_ADDR(x) << 2) + ((TUint32)(a) + 8)
+
+	TUint32 aVal = (arm_b_addr(aInst) << 2) + ((TUint32)(aAddress) + 8);
+
+	return aVal;
+}
+
+inline TUint32 DRMDStepping::thumb_b_addr(const TUint32 aInst)
+{
+//#define THUMB_B_ADDR(x) ((x & 0x0400) ? ((((TUint32)(x) & 0x07FF)<<11) | (((TUint32)(x) & 0x07FF0000)>>16) | 0xFFC00000) :\
+                                            ((TUint32)(x) & 0x07FF)<<11) | (((TUint32)(x) & 0x07FF0000)>>16)
+
+	TUint32 aVal = ((((TUint32)(aInst) & 0x07FF)<<11) | ((TUint32)(aInst) & 0x07FF0000)>>16);
+
+	return ((aInst & 0x0400) ? (aVal | 0xFFC00000) : aVal);
+}
+
+inline TUint32 DRMDStepping::thumb_instr_b_dest(const TUint32 aInst, TUint32& aAddress)
+{
+//#define THUMB_INSTR_B_DEST(x,a)	(THUMB_B_ADDR(x) << 1) + ((TUint32)(a) + 4)
+
+	TUint32 aVal = (thumb_b_addr(aInst) << 1) + ((TUint32)(aAddress) + 4);
+
+	return aVal;
+}
+
+inline TUint32 DRMDStepping::arm_carry_bit(void)
+{
+//#define ARM_CARRY_BIT			0x20000000	// bit 30
+
+	TUint32 aVal = 0x20000000;
+
+	return aVal;
+}
+
+// Thumb instruction bitmasks
+inline TUint16 DRMDStepping::thumb_opcode(const TUint16 aInst)
+{
+//	#define THUMB_OPCODE(x)		(((TUint16)(x) & 0xF800) >> 11)
+
+	TUint16 aVal = ((aInst) & 0xF800) >> 11;
+
+	return aVal;
+}
+
+inline TUint16 DRMDStepping::thumb_inst_7_15(const TUint16 aInst)
+{
+//	#define THUMB_INST_7_15(x)	(((TUint16)(x) & 0xFF80) >> 7)
+
+	TUint16 aVal = ((aInst) & 0xFF80) >> 7;
+
+	return aVal;
+}
+
+inline TUint16 DRMDStepping::thumb_inst_8_15(const TUint16 aInst)
+{
+//	#define THUMB_INST_8_15(x)	(((TUint16)(x) & 0xFF00) >> 8)
+
+	TUint16 aVal = ((aInst) & 0xFF00) >> 8;
+
+	return aVal;
+}
+
+#endif	// D_RMD_STEPPPING_INL
+
+// End of file - d-rmd-stepping.inl
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/debugsrv/runmodedebug/rmdriver/inc/d_target_process.h	Fri Aug 27 11:37:29 2010 +0300
@@ -0,0 +1,57 @@
+// Copyright (c) 2006-2010 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+// Purpose: Kernel-side tracking of process state
+// 
+//
+ 
+#ifndef D_TARGET_PROCESS_H
+#define D_TARGET_PROCESS_H
+
+#include "d_debug_agent.h"
+
+// Debug Process Tracker class
+class DTargetProcess : public DBase
+{
+public:
+	DTargetProcess();
+	~DTargetProcess();
+
+	static TInt Compare(const DTargetProcess& aFirst, const DTargetProcess& aSecond);
+
+	TInt SetProcessName(const TDesC8& aProcessName);
+	const TDesC8& ProcessName() const;
+
+	TInt AddAgent(const TUint64 aAgentId);
+
+	TInt RemoveAgent(TUint64 aAgentId);
+
+	DDebugAgent* operator[](TInt aIndex);
+
+	DDebugAgent* Agent(TUint64 aAgentId);
+
+	TInt AgentCount() const;
+	void NotifyEvent(const TDriverEventInfo& aEventInfo);
+
+private:
+	HBuf8* iProcessName;
+	RPointerArray<DDebugAgent> iAgentList;
+
+	RArray<TUint64> iSuspendedThreads;
+
+	RPointerArray<NFastSemaphore> iFrozenThreadSemaphores;
+
+};
+
+#endif // D_TARGET_PROCESS_H
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/debugsrv/runmodedebug/rmdriver/inc/debug_logging.h	Fri Aug 27 11:37:29 2010 +0300
@@ -0,0 +1,108 @@
+// Copyright (c) 2006-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+// Logging macros for use in debug subsystem
+// 
+//
+
+#ifndef DEBUG_LOGGING_H
+#define DEBUG_LOGGING_H
+
+/**
+ * Debug messages
+ * 
+ * Debug messages are only generated for debug builds.
+ * 
+ * For kernel mode, use __KTRACE_OPT(KDEBUGGER, Kern::Printf(), 
+ * for user mode use RDebug::Printf(). 
+ * 
+ */
+
+#ifdef _DEBUG
+
+  #ifdef __KERNEL_MODE__
+
+	#include <kernel/kernel.h>
+	#include <nk_trace.h>
+
+	#define LOG_MSG( a )				__KTRACE_OPT(KDEBUGGER, Kern::Printf( a ))
+	#define LOG_MSG2( a, b )			__KTRACE_OPT(KDEBUGGER, Kern::Printf( a, b ))
+	#define LOG_MSG3( a, b, c )			__KTRACE_OPT(KDEBUGGER, Kern::Printf( a, b, c ))
+	#define LOG_MSG4( a, b, c, d )		__KTRACE_OPT(KDEBUGGER, Kern::Printf( a, b, c, d ))
+	#define LOG_MSG5( a, b, c, d, e )	__KTRACE_OPT(KDEBUGGER, Kern::Printf( a, b, c, d, e ))
+
+	#ifdef __LOG_EVENTS__
+
+	#define LOG_EVENT_MSG( a )				__KTRACE_OPT(KDEBUGGER, Kern::Printf( a ))
+	#define LOG_EVENT_MSG2( a, b )			__KTRACE_OPT(KDEBUGGER, Kern::Printf( a, b ))
+	#define LOG_EVENT_MSG3( a, b, c )		__KTRACE_OPT(KDEBUGGER, Kern::Printf( a, b, c ))
+	#define LOG_EVENT_MSG4( a, b, c, d )	__KTRACE_OPT(KDEBUGGER, Kern::Printf( a, b, c, d ))
+	#define LOG_EVENT_MSG5( a, b, c, d, e )	__KTRACE_OPT(KDEBUGGER, Kern::Printf( a, b, c, d, e ))
+	
+	#else
+
+	#define LOG_EVENT_MSG( a )
+	#define LOG_EVENT_MSG2( a, b )
+	#define LOG_EVENT_MSG3( a, b, c )
+	#define LOG_EVENT_MSG4( a, b, c, d )
+	#define LOG_EVENT_MSG5( a, b, c, d, e )
+
+	#endif
+
+  #else
+
+    #include <e32debug.h>
+
+	#define LOG_MSG( a )				RDebug::Printf( a )
+	#define LOG_MSG2( a, b )			RDebug::Printf( a, b )
+	#define LOG_MSG3( a, b, c )			RDebug::Printf( a, b, c )
+	#define LOG_MSG4( a, b, c, d )		RDebug::Printf( a, b, c, d )
+	#define LOG_MSG5( a, b, c, d, e )	RDebug::Printf( a, b, c, d, e )
+
+	#ifdef __LOG_EVENTS__
+
+	#define LOG_EVENT_MSG( a )					RDebug::Printf( a )
+	#define LOG_EVENT_MSG2( a, b )				RDebug::Printf( a, b )
+	#define LOG_EVENT_MSG3( a, b, c )			RDebug::Printf( a, b, c )
+	#define LOG_EVENT_MSG4( a, b, c, d )		RDebug::Printf( a, b, c, d )
+	#define LOG_EVENT_MSG5( a, b, c, d, e )		RDebug::Printf( a, b, c, d, e )
+
+	#else
+
+	#define LOG_EVENT_MSG( a )
+	#define LOG_EVENT_MSG2( a, b )
+	#define LOG_EVENT_MSG3( a, b, c )
+	#define LOG_EVENT_MSG4( a, b, c, d )
+	#define LOG_EVENT_MSG5( a, b, c, d, e )
+
+    #endif
+
+    #endif
+#else
+
+	#define LOG_MSG( a )
+	#define LOG_MSG2( a, b )
+	#define LOG_MSG3( a, b, c )
+	#define LOG_MSG4( a, b, c, d )
+	#define LOG_MSG5( a, b, c, d, e )
+
+	#define LOG_EVENT_MSG( a )
+	#define LOG_EVENT_MSG2( a, b )
+	#define LOG_EVENT_MSG3( a, b, c )
+	#define LOG_EVENT_MSG4( a, b, c, d )
+	#define LOG_EVENT_MSG5( a, b, c, d, e )
+
+#endif
+
+#endif //DEBUG_LOGGING_H
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/debugsrv/runmodedebug/rmdriver/inc/debug_utils.h	Fri Aug 27 11:37:29 2010 +0300
@@ -0,0 +1,38 @@
+// Copyright (c) 2004-2010 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+// Purpose: Static functions for use by debug driver classes
+//
+
+/**
+ * @file
+ * @internalComponent
+ * @released
+ */
+
+#ifndef DEBUG_UTILS_H
+#define DEBUG_UTILS_H
+
+#include <kernel/kern_priv.h>
+#include <rm_debug_api.h>
+
+class DebugUtils
+	{
+public:
+	static DThread* OpenThreadHandle(TUint64 aThreadId);
+	static DProcess* OpenProcessHandle(TUint64 aProcessId);
+	static DThread* OpenFirstThreadForProcess(DProcess* aProcess);
+	};
+
+#endif //DEBUG_UTILS_H
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/debugsrv/runmodedebug/rmdriver/inc/rm_debug_driver.h	Fri Aug 27 11:37:29 2010 +0300
@@ -0,0 +1,199 @@
+// Copyright (c) 2004-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+//
+
+
+
+/**
+ @file
+ @internalTechnology
+ @released
+*/
+
+#ifndef __RM_DEBUG_DRIVER_H__
+#define __RM_DEBUG_DRIVER_H__
+
+#include "d_rmd_stepping.h"
+#include "d_rmd_breakpoints.h"
+#include "d_driver_event_info.h"
+
+// From mmboot.h header
+const TLinAddr	KDataSectionEnd			=0x40000000u;
+const TLinAddr	KRomLinearBase			=0xF8000000u;
+
+
+#define ROM_LINEAR_BASE KRomLinearBase
+
+// Result checking
+#define ReturnIfError(x) { TInt y = x; if (KErrNone != y) return y; }
+
+//
+// class DRM_DebugDriverFactory
+//
+class DRM_DebugDriverFactory : public DLogicalDevice
+{
+public:
+
+	DRM_DebugDriverFactory();
+	virtual TInt Install();
+	virtual void GetCaps(TDes8& aDes) const;
+	virtual TInt Create(DLogicalChannelBase*& aChannel);
+};
+
+class DRM_DebugEventHandler;
+//
+// DRM_DebugChannel
+//
+class DRM_DebugChannel : public DLogicalChannel
+{
+public:
+
+	DRM_DebugChannel(DLogicalDevice* aLogicalDevice);
+	~DRM_DebugChannel();
+
+	virtual TInt DoCreate(TInt aUnit, const TDesC* anInfo, const TVersion& aVer);	
+	virtual void HandleMsg(TMessageBase* aMsg);
+	virtual TInt SendMsg(TMessageBase* aMsg);
+	TInt SendRequest(TMessageBase* aMsg);
+	
+	//called from the event handler
+	TBool RemoveProcess(TAny* a1, TAny* a2);
+	TBool StartThread(TAny* a1, TAny* a2);
+	TBool AddLibrary(TAny* a1, TAny* a2);
+	TBool RemoveLibrary(TAny* a1, TAny* a2);
+	TBool HandleEventKillThread(TAny* a1, TAny* a2);
+	TBool HandleSwException(TAny* a1, TAny* a2);
+	TBool HandleHwException(TAny* a1, TAny* a2);
+	TBool HandleUserTrace(TAny* a1, TAny* a2);
+	TBool HandleUnsupportedEvent(TAny* a1, TAny* a2) { return EFalse; }
+	TBool HandleAddProcessEvent(TAny* a1, TAny* a2);
+	TBool HandleRemoveProcessEvent(TAny* a1, TAny* a2);
+	
+	// Used to be able to signal events to the DSS
+	DThread* ClientThread(void) {return iClientThread; };
+	
+protected:
+	virtual void DoCancel(TInt aReqNo);
+	virtual void DoRequest(TInt aReqNo, TRequestStatus* aStatus, TAny* a1, TAny* a2);
+	virtual TInt DoControl(TInt aFunction, TAny *a1, TAny *a2);
+	
+private:
+	TInt PreAsyncGetValue(Debug::TEventInfo* aValue, TRequestStatus* aStatus);
+	TInt CreateDfcQ();
+	void DestroyDfcQ();
+	TBool HandleInvalidOpCodeException(TDriverEventInfo& aEventInfo, DThread* aCurrentThread);
+
+	TInt SetBreak(TSetBreakInfo* aBreakInfo);
+	TInt StepRange(DThread* aThread, TRM_DebugStepInfo* aStepInfo);
+	TInt ReadMemory(DThread* aThread, TRM_DebugMemoryInfo* aMemoryInfo);
+	TInt WriteMemory(DThread* aThread, TRM_DebugMemoryInfo* aMemoryInfo);
+	TInt ReadRegistersLegacy(DThread* aThread, TRM_DebugRegisterInfo* aRegisterInfo);
+	TInt WriteRegistersLegacy(DThread* aThread, const TRM_DebugRegisterInfo* aRegisterInfo);
+	TInt ReadRegisters(DThread* aThread, TRM_DebugRegisterInformation* aRegisterInfo) const;
+	TInt WriteRegisters(DThread* aThread, TRM_DebugRegisterInformation* aRegisterInfo) const;
+	TInt GetProcessInfo(TInt aIndex, TRM_DebugTaskInfo* aTaskInfo);
+	TInt GetThreadInfo(TInt aIndex, TRM_DebugTaskInfo* aTaskInfo);
+	TInt GetList(TListInformation* aListInformation) const;
+	
+	TInt Step(const TUint32 aThreadId, const TUint32 aNumSteps);
+	TInt KillProcess(const TUint32 aProcessId, const TInt aReason);
+
+	//Crash Flash	
+	TInt ReadCrashLog(TFlashInfo* aBuffer);
+	TInt WriteCrashLog(TFlashInfo* aBuffer) const;
+	TInt EraseCrashLog();
+
+	// Stop/go
+	TInt DoSuspendThread(DThread *aThread);
+	TInt DoResumeThread(DThread *aThread);
+	TInt DoStepRange(DThread *aThread, const TUint32 aStartAddress, const TUint32 aStopAddress, TBool aStepInto, TBool aResumeOnceOutOfRange, const TUint32 aNumSteps, TBool aUserRequest = EFalse);
+	TInt DoReadMemory(const DThread *aThread, const TUint32 aAddress, const TUint32 aLength, TDes8 &aData) const;
+	TInt DoWriteMemory(DThread *aThread, const TUint32 aAddress, const TUint32 aLength, TDes8 &aData);
+	TInt DoReadRegisters(DThread *aThread, const TInt16 aFirstRegister, const TInt16 aLastRegister, TDes8 &aValues);
+	TInt DoReadRegisters(DThread *aThread, const TDesC8 &aRegisterIds, TDes8 &aRegisterValues, TDes8 &aRegisterFlags) const;
+	TInt DoWriteRegisters(DThread *aThread, const TInt16 aFirstRegister, const TInt16 aLastRegister, TDesC8 &aValues);
+	TInt DoWriteRegisters(DThread *aThread, const TDesC8 &aRegisterIds, TDesC8 &aRegisterValues, TDes8 &aRegisterFlags) const;
+	TInt DoGetProcessInfo(const TInt aIndex, TRM_DebugTaskInfo *aInfo);
+	TInt DoGetThreadInfo(const TInt aIndex, TRM_DebugTaskInfo *aInfo);
+	TBool DoSecurityCheck();
+
+	TInt TryToReadMemory(const DThread *aThread, const TAny *aSrc, TAny *aDest, const TUint32 aLength) const;
+	TInt TryToWriteMemory(const DThread *aThread, TAny *aDest, const TAny *aSrc, const TUint32 aLength);
+	TInt32 ReadRegister(DThread *aThread, TInt aNum);
+	TInt32 ReadDebugRegisterValue(DThread *aThread, const Debug::TRegisterInfo aDebugRegisterId, T4ByteRegisterValue &aValue) const;
+	TInt32 ReadKernelRegisterValue(DThread *aThread, const TArmReg aKernelRegisterId, T4ByteRegisterValue &aValue) const;
+	
+	void NotifyEvent(const TDriverEventInfo& aEventInfo);
+
+	TInt GetTRegisterInfo(const TDesC8 &aRegisterIds, const TUint aIndex, Debug::TRegisterInfo &aValue) const;
+	TInt GetDebugRegisterId(const TArmReg aKernelRegister, Debug::TRegisterInfo& aDebugRegister) const;
+	TInt GetKernelRegisterId(const Debug::TRegisterInfo aDebugRegister, TArmReg& aKernelRegister) const;
+	TBool GetFlagAtOffset(const TUint32 aFlags, const TArmReg aIndex) const;
+
+	TInt AllocAndReadDes(DThread *aThread, const TDesC8& aSrcDes, TPtr8& aDestDes, const TBool aReadFromClient=ETrue, const TUint aOffset=0) const;
+
+	TInt AttachProcess(TAny* a1, TAny* a2);
+	TInt DetachProcess(TAny* a1, TAny* a2);
+	TInt DetachAgent(TAny* a1, TAny* a2);
+	TInt SetEventAction(TAny* a1, TAny* a2);
+	TBool CheckSuspended(const DThread *aThread) const;
+
+	// Needed so moved functions can access iBreakpoint list and related functions
+	friend class D_RMD_Breakpoints;
+	// Needed so moved functions can access stepping functionality
+	friend class DRMDStepping;
+
+	// helper function was previously in rm_debug_kerneldriver.cpp
+	inline TInt Bitcount(TUint32 val)
+		{
+			TInt nbits;
+
+			for (nbits = 0; val != 0; nbits++)
+			{
+				val &= val - 1;		// delete rightmost 1-bit in val
+			}
+			
+			return nbits;
+		}
+
+	// Security critical - this returns whether the specified process is debuggable or not
+	TInt IsDebuggable(const TUint32 aProcessId);
+	
+	TInt NotifyAgentsFromEventPid(const TDriverEventInfo& aEventInfo);
+
+private:
+	DThread* iClientThread;
+	DRM_DebugEventHandler* iEventHandler;
+	
+	TUint32 iExcludedROMAddressStart;
+	TUint32 iExcludedROMAddressEnd;
+	
+	TUint32 iPageSize;
+	
+	RArray<Debug::TProcessInfo> iDebugProcessList; //processes that we are debugging
+
+	D_RMD_Breakpoints* iBreakManager;	// new D_RMD_Breakpoints
+
+	DRMDStepping* iStepper;				// new DRMDStepping
+
+	DSemaphore* iStepLock;				// Synchronisation for stepping code.
+
+	TDynamicDfcQue* iDfcQ;
+
+	TBool	iInitialisedCodeModifier;	// Ensures we control its lifetime
+
+	TClientDataRequest<Debug::TEventInfo>* iAsyncGetValueRequest;
+};
+
+#endif //__RM_DEBUG_DRIVER_H__
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/debugsrv/runmodedebug/rmdriver/inc/rm_debug_eventhandler.h	Fri Aug 27 11:37:29 2010 +0300
@@ -0,0 +1,60 @@
+// Copyright (c) 2004-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+//
+
+/** Event handler and container for all objects being tracked.  */
+#ifndef __RM_DEBUG_EVENTHANDLER_H__
+#define __RM_DEBUG_EVENTHANDLER_H__
+
+
+class DRM_DebugEventHandler : public DKernelEventHandler
+{
+	public:
+		DRM_DebugEventHandler();
+		TInt Create(DLogicalDevice* aDevice, DLogicalChannel* aChannel, DThread* aClient);
+		~DRM_DebugEventHandler();
+		TInt Start();
+		TInt Stop();
+		
+		inline void DRM_DebugEventHandler::LockDataAccess()
+		    {
+		    Kern::SemaphoreWait(*iProtectionLock);
+		    }
+
+		inline void DRM_DebugEventHandler::ReleaseDataAccess()
+		    {
+		    Kern::SemaphoreSignal(*iProtectionLock);
+		    }
+		
+	private:
+		static TUint EventHandler(TKernelEvent aEvent, TAny* a1, TAny* a2, TAny* aThis);
+		TUint HandleEvent(TKernelEvent aType, TAny* a1, TAny* a2);
+		TBool HandleSpecificEvent(TKernelEvent aType, TAny* a1, TAny* a2);
+		
+	private:
+		/** Used to serialise access data structures */
+		DSemaphore* iProtectionLock;
+
+		TBool iTracking;
+
+		DLogicalDevice* iDevice;	// open reference to LDD for avoiding lifetime issues
+		DThread* iClientThread;
+		DRM_DebugChannel* iChannel;
+
+		// typdef for functions which handle our specific events
+		typedef TBool (DRM_DebugChannel::*eventHandler)(TAny* a1, TAny* a2);
+		eventHandler iEventHandlers[EEventLimit];
+};
+
+#endif //__RM_DEBUG_EVENTHANDLER_H__
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/debugsrv/runmodedebug/rmdriver/inc/rm_debug_kerneldriver.h	Fri Aug 27 11:37:29 2010 +0300
@@ -0,0 +1,777 @@
+// Copyright (c) 2004-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+//
+
+
+
+/**
+ @file
+ @internalTechnology
+ @released
+*/
+
+#ifndef __RM_DEBUG_KERNELDRIVER_H__
+#define __RM_DEBUG_KERNELDRIVER_H__
+
+#include <rm_debug_api.h>
+
+/**
+Used to store a value read from or written to an ARM register
+*/
+typedef TUint32 T4ByteRegisterValue;
+
+
+/** 
+Provides static methods for accessing the information stored in a TRegisterInfo
+object.
+*/
+class Register
+	{
+public:
+	static TBool IsCoreReg(const Debug::TRegisterInfo aRegister);
+	static TBool IsCoproReg(const Debug::TRegisterInfo aRegister);
+	static TUint32 GetCoreRegId(const Debug::TRegisterInfo aRegister);
+	static TUint32 GetCRm(const Debug::TRegisterInfo aRegister);
+	static TUint32 GetCRn(const Debug::TRegisterInfo aRegister);
+	static TUint32 GetOpcode1(const Debug::TRegisterInfo aRegister);
+	static TUint32 GetOpcode2(const Debug::TRegisterInfo aRegister);
+	static TUint32 GetCoproNum(const Debug::TRegisterInfo aRegister);
+	};
+
+/**
+Identify whether aRegister is a core register
+@param aRegister register ID to analyse
+@return ETrue if core register, EFalse otherwise
+*/
+inline TBool Register::IsCoreReg(const Debug::TRegisterInfo aRegister)
+	{
+	return ((aRegister & 0xff) == 0x0);
+	}
+
+/**
+Identify whether aRegister is a coprocessor register
+@param aRegister register ID to analyse
+@return ETrue if coprocessor register, EFalse otherwise
+*/
+inline TBool Register::IsCoproReg(const Debug::TRegisterInfo aRegister)
+	{
+	return ((aRegister & 0xff) == 0x1);
+	}
+
+/**
+Get the ID of the core register
+@param aRegister register ID to analyse
+@return ID of the core register
+*/
+inline TUint32 Register::GetCoreRegId(const Debug::TRegisterInfo aRegister)
+	{
+	return ((aRegister >> 8) & 0xff);
+	}
+
+/**
+Get the CRm value of a coprocessor register
+@param aRegister register ID to analyse
+@return the CRm value of a coprocessor register
+*/
+inline TUint32 Register::GetCRm(const Debug::TRegisterInfo aRegister)
+	{
+	return ((aRegister >> 16) & 0xf);
+	}
+
+/**
+Get the CRm value of a coprocessor register
+@param aRegister register ID to analyse
+@return the CRm value of a coprocessor register
+*/
+inline TUint32 Register::GetCRn(const Debug::TRegisterInfo aRegister)
+	{
+	return ((aRegister >> 20) & 0xf);
+	}
+
+/**
+Get the Opcode1 value of a coprocessor register
+@param aRegister register ID to analyse
+@return the Opcode1 value of a coprocessor register
+*/
+inline TUint32 Register::GetOpcode1(const Debug::TRegisterInfo aRegister)
+	{
+	return ((aRegister >> 24) & 0x8);
+	}
+	
+/**
+Get the Opcode2 value of a coprocessor register
+@param aRegister register ID to analyse
+@return the Opcode2 value of a coprocessor register
+*/
+inline TUint32 Register::GetOpcode2(const Debug::TRegisterInfo aRegister)
+	{
+	return ((aRegister >> 27) & 0x8);
+	}
+
+/**
+Get the coprocessor number of a coprocessor register
+@param aRegister register ID to analyse
+@return the coprocessor number of a coprocessor register
+*/
+inline TUint32 Register::GetCoproNum(const Debug::TRegisterInfo aRegister)
+	{
+	return ((aRegister >> 8) & 0xff);
+	}
+
+//
+// class TCapsRM_DebugDriver
+//
+class TCapsRM_DebugDriver
+{
+public:
+	TVersion	iVersion;
+};
+
+/**
+Stores listings information for passing between the DSS and the kernel driver
+*/
+class TListInformation
+{
+public:
+	inline TListInformation(const Debug::TListId aType=(Debug::TListId)NULL, const Debug::TListScope aListScope=(Debug::TListScope)NULL, TDes8* aBuffer=NULL, TUint32* aDataSize=NULL, TUint64 aTargetId=0)
+		: iType(aType),
+		  iListScope(aListScope),
+		  iBuffer(aBuffer),
+		  iDataSize(aDataSize),
+		  iTargetId(aTargetId) {};
+public:
+	Debug::TListId iType;
+	Debug::TListScope iListScope;
+	TDes8* iBuffer;
+	TUint32* iDataSize;
+	TUint64 iTargetId;
+};
+
+/**
+Data structure to hold information to the crash flash
+(Possibly: Could be expanded to hold on configuration data too)
+*/
+class TFlashInfo
+{
+public:
+	inline TFlashInfo(TUint32 aPos, TUint32* aSize, TDes8* aData)
+		:iPos(aPos),
+		iSize(aSize),
+		iData(aData){};
+public:
+	TUint32 iPos;
+	TUint32* iSize;	
+	 TDes8* iData;	
+};
+//
+// class TRM_DebugMemoryInfo
+//
+class TRM_DebugMemoryInfo
+{
+public:
+
+	inline TRM_DebugMemoryInfo(const TUint32 aAddress, const TUint32 aLength, TDesC8 *aData)
+				: iAddress(aAddress),
+				  iLength(aLength),
+				  iData(aData) {};
+	
+public:
+
+	TUint32 iAddress;
+	TUint32	iLength;
+	TDesC8*	iData;
+};
+
+
+/**
+@deprecated
+This class is only used by TRK phase 1 functions.
+
+@see TRM_DebugRegisterInformation which offers similar storage suitable for use
+with the TRK pahse 2 API.
+*/
+class TRM_DebugRegisterInfo
+{
+public:
+
+	inline TRM_DebugRegisterInfo(const TInt16 aFirstRegister, const TInt16 aLastRegister, TDesC8 *aValues)
+				: iFirstRegister(aFirstRegister),
+				  iLastRegister(aLastRegister),
+				  iValues(aValues) {};
+	
+public:
+
+	TInt16	iFirstRegister;
+	TInt16	iLastRegister;
+	TDesC8*	iValues;
+};
+
+/**
+Structure used to store information about registers
+*/
+class TRM_DebugRegisterInformation
+{
+public:
+
+	inline TRM_DebugRegisterInformation(const TDes8 *aRegisterIds=NULL, TDes8 *aRegisterValues=NULL, TDes8 *aRegisterFlags=NULL)
+		: iRegisterIds(aRegisterIds),
+		  iRegisterValues(aRegisterValues),
+		  iRegisterFlags(aRegisterFlags) {};
+	
+public:
+
+	const TDes8* iRegisterIds;
+	TDes8* iRegisterValues;
+	TDes8* iRegisterFlags;
+};
+
+//
+// class TRM_DebugTaskInfo
+//
+class TRM_DebugTaskInfo
+{
+public:
+
+	inline TRM_DebugTaskInfo(TUint32 aOtherId)
+				: iId(0),
+				  iOtherId(aOtherId),
+				  iPriority(0) { iName.FillZ(); };
+
+public:
+
+	TUint32 iId;
+	TUint32 iOtherId;
+	TUint32 iPriority;	
+	TBuf8<KMaxName> iName;
+};
+
+//
+// class TRM_DebugStepInfo
+//
+class TRM_DebugStepInfo
+{
+public:
+
+	inline TRM_DebugStepInfo(const TUint32 aStartAddress, const TUint32 aStopAddress, const TBool aStepInto)
+				: iStartAddress(aStartAddress),
+				  iStopAddress(aStopAddress),
+				  iStepInto(aStepInto) {};
+
+public:
+
+	TUint32 iStartAddress;
+	TUint32 iStopAddress;
+	TBool iStepInto;
+};
+
+
+//
+// class TRM_DebugDriverInfo
+//
+class TRM_DebugDriverInfo
+{
+public:
+
+	TUint32 iPanic1Address;
+	TUint32 iPanic2Address;
+	TUint32 iException1Address;
+	TUint32 iException2Address;
+	TUint32 iLibraryLoadedAddress;
+	TUint32 iUserLibraryEnd;
+};
+
+
+//
+// class TRM_DebugProcessInfo
+//
+class TRM_DebugProcessInfo
+{
+public:
+
+	inline TRM_DebugProcessInfo(TUint32 *aCodeAddress, TUint32 *aDataAddress)
+				: iCodeAddress(aCodeAddress),
+				  iDataAddress(aDataAddress) {};
+
+public:
+
+	TUint32* iCodeAddress;
+	TUint32* iDataAddress;
+};
+
+//
+// class TRM_DebugEventActionInfo
+//
+class TRM_DebugEventActionInfo
+{
+public:
+	inline TRM_DebugEventActionInfo(TUint32 aEvent, TUint32 aAction, TUint64 aAgentId)
+		: iEvent(aEvent),
+		iAction(aAction),
+		iAgentId(aAgentId) {};
+public:
+	TUint32 iEvent;
+	TUint32 iAction;
+	TUint64 iAgentId;
+};
+
+//
+// class TRM_DebugEventInfo
+//
+class TRM_DebugEventInfo
+{
+public:
+	inline TRM_DebugEventInfo(TDesC8& aProcessName, TUint32& aBufSize)
+		: iProcessName(aProcessName),
+		iBufSize(aBufSize) {};
+
+public:
+	TDesC8& iProcessName;
+	TUint32& iBufSize;
+};
+
+//
+// class TRMD_DebugAgentId
+//
+class TRM_DebugAgentId
+{
+public:
+	inline TRM_DebugAgentId(TUint64 aAgentId)
+		: iAgentId(aAgentId) {};
+
+public:
+	TUint64 iAgentId;
+};
+
+//
+// Class TRMD_DebugCancelInfo
+//
+class TRMD_DebugCancelInfo
+{
+public:
+	inline TRMD_DebugCancelInfo(TUint32 aCancelRequest,TDesC8& aProcessName, TUint64 aAgentId)
+		: iCancelRequest(aCancelRequest),
+		iProcessName(aProcessName),
+		iAgentId(aAgentId) {};
+
+	inline TRMD_DebugCancelInfo(void)
+		: iCancelRequest(0),
+	iAgentId(0)
+	{
+	};
+
+public:
+	TUint32 iCancelRequest;
+	TBuf8<KMaxName> iProcessName;
+	TUint64 iAgentId;
+};
+
+class TEventMetaData
+	{
+public:
+	TBuf8<KMaxName> iTargetProcessName;
+	TUint64 iDebugAgentProcessId;
+	};
+
+/**
+@internalComponent
+*/
+class TSetBreakInfo
+{
+public:
+
+	inline TSetBreakInfo(Debug::TBreakId* aBreakId,
+		TUint64 aId,\
+		TUint32 aAddress,\
+		Debug::TArchitectureMode aMode,
+		TBool aThreadSpecific)
+				: iBreakId(aBreakId),
+				  iId(aId),
+				  iAddress(aAddress),
+				  iMode(aMode),
+       				  iThreadSpecific(aThreadSpecific) {};
+
+inline TSetBreakInfo(void)
+			: iBreakId((Debug::TBreakId*)0),
+			  iId(0),
+			  iAddress(0),
+			  iMode(Debug::EArmMode),
+       			  iThreadSpecific(ETrue) {};
+
+
+public:
+	Debug::TBreakId* iBreakId;
+	TUint64 iId;
+	TUint32 iAddress;
+	Debug::TArchitectureMode iMode;
+	TBool iThreadSpecific;
+};
+
+/**
+@internalComponent
+*/
+class TModifyBreakInfo
+{
+public:
+
+	inline TModifyBreakInfo(Debug::TBreakId aBreakId,\
+		const TUint64 aThreadId,\
+		const TUint32 aAddress,\
+		const Debug::TArchitectureMode aMode)
+				: iBreakId(aBreakId),
+				  iThreadId(aThreadId),
+				  iAddress(aAddress),
+				  iMode(aMode) {};
+
+public:
+	const Debug::TBreakId iBreakId;
+	const TUint64 iThreadId;
+	const TUint32 iAddress;
+	const Debug::TArchitectureMode iMode;
+};
+
+/**
+@internalComponent
+*/
+class TModifyProcessBreakInfo
+{
+public:
+
+	inline TModifyProcessBreakInfo(Debug::TBreakId aBreakId,\
+		const TUint64 aProcessId,\
+		const TUint32 aAddress,\
+		const Debug::TArchitectureMode aMode)
+				: iBreakId(aBreakId),
+				  iProcessId(aProcessId),
+				  iAddress(aAddress),
+				  iMode(aMode) {};
+
+public:
+	const Debug::TBreakId iBreakId;
+	const TUint64 iProcessId;
+	const TUint32 iAddress;
+	const Debug::TArchitectureMode iMode;
+};
+
+/**
+@internalComponent
+*/
+class TGetBreakInfo
+{
+public:
+
+	inline TGetBreakInfo(Debug::TBreakId aBreakId,\
+		TUint64& aId,\
+		TUint32& aAddress,\
+		Debug::TArchitectureMode& aMode,
+		TBool& aThreadSpecific)
+				: iBreakId(aBreakId),
+				  iId(&aId),
+				  iAddress(&aAddress),
+				  iMode(&aMode),
+       				  iThreadSpecific(&aThreadSpecific) {};
+
+	inline TGetBreakInfo()
+				: iBreakId((Debug::TBreakId)0),
+				  iId((TUint64*)0),
+				  iAddress((TUint32*)0),
+				  iMode((Debug::TArchitectureMode*)0),
+       				  iThreadSpecific((TBool*)0)	{};
+
+public:
+	const Debug::TBreakId iBreakId;
+	TUint64* iId;
+	TUint32* iAddress;
+	Debug::TArchitectureMode* iMode;
+	TBool* iThreadSpecific;
+};
+
+//
+// class RRM_DebugDriver
+//
+class RRM_DebugDriver : public RBusLogicalChannel
+{
+public:
+
+	enum TControl
+	{
+		EControlSetBreak = 0,
+		EControlClearBreak,
+		EControlModifyBreak,
+		EControlBreakInfo,
+		EControlSuspendThread,
+		EControlResumeThread,
+		EControlStepRange,
+		EControlReadMemory,
+		EControlWriteMemory,
+		EControlReadRegisters,
+		EControlWriteRegisters,
+		EControlGetStaticLibraryInfo,
+		EControlGetDebugFunctionalityBufSize,
+		EControlGetDebugFunctionality,
+		EControlReadRegistersLegacy,
+		EControlWriteRegistersLegacy,		
+		EControlGetMemoryOperationMaxBlockSize,		
+		EControlAttachProcess,
+		EControlDetachProcess,
+		EControlDetachAgent,
+		EControlSetEventAction,
+		EControlGetList,
+		EControlStep,
+		EControlIsDebuggable,
+		EControlKillProcess,		
+		EControlModifyProcessBreak,
+	};
+	
+	enum TRequest
+	{
+		ERequestGetEvent=0x0, ERequestGetEventCancel=0x1
+	};	
+		
+public:
+
+	inline TInt Open(const TRM_DebugDriverInfo aDriverInfo);
+
+	inline TInt	SetBreak(Debug::TBreakId &aBreakId,const TUint32 aThreadId, const TUint32 aAddress, const Debug::TArchitectureMode aThumbMode );
+	inline TInt	SetProcessBreak(Debug::TBreakId &aBreakId,const TUint32 aProcessId, const TUint32 aAddress, const Debug::TArchitectureMode aThumbMode );
+	
+	inline TInt	ClearBreak(const TInt32 aBreakId);
+	
+	inline TInt	ModifyBreak(const Debug::TBreakId aBreakId, const TUint32 aThreadId, const TUint32 aAddress, const Debug::TArchitectureMode aArchitectureMode );
+	inline TInt	ModifyProcessBreak(const Debug::TBreakId aBreakId, const TUint32 aProcessId, const TUint32 aAddress, const Debug::TArchitectureMode aArchitectureMode );
+	
+	inline TInt BreakInfo(const Debug::TBreakId aBreakId, TUint64& aId, TUint32& aAddress, Debug::TArchitectureMode& aMode, TBool& aThreadSpecific);
+	
+	inline TInt	SuspendThread(const TUint32 aThreadId);
+	inline TInt	ResumeThread(const TUint32 aThreadId);
+	inline TInt	StepRange(const TUint32 aThreadId, const TUint32 aStartAddress, const TUint32 aStopAddress, TBool aStepInto);
+	inline TInt ReadMemory(const TUint32 aThreadId, const TUint32 aAddress, const TUint32 aLength, TDes8 &aData);
+	inline TInt WriteMemory(const TUint32 aThreadId, const TUint32 aAddress, const TUint32 aLength, const TDesC8 &aData);
+	inline TInt ReadRegisters(const TUint32 aThreadId, const TDes8 &aRegisterIds, TDes8 &aRegisterValues, TDes8 &aRegisterFlags);
+	inline TInt WriteRegisters(const TUint32 aThreadId, const TDes8 &aRegisterIds, const TDes8 &aRegisterValues, TDes8 &aRegisterFlags);
+	inline TInt ReadRegisters(const TUint32 aThreadId, const TInt32 aFirstRegister, const TInt32 aLastRegister, TDes8 &aValues);
+	inline TInt WriteRegisters(const TUint32 aThreadId, const TInt32 aFirstRegister, const TInt32 aLastRegister, TDesC8 &aValues);
+	inline void GetEvent(TDesC8& aProcessName, TUint64 aAgentId, TRequestStatus &aStatus, Debug::TEventInfo &aEventInfo);
+	inline void CancelGetEvent(TDesC8& aProcessName, TUint64 aAgentId);
+//	inline TInt GetProcessInfo(const TInt aIndex, TRM_DebugTaskInfo &aInfo);
+//	inline TInt GetThreadInfo(const TInt aIndex, TRM_DebugTaskInfo &aInfo);
+	inline TInt GetStaticLibraryInfo(const TInt aIndex, Debug::TEventInfo &aInfo);
+	inline TInt GetDebugFunctionalityBufSize(TUint32 &aBufSize);
+	inline TInt GetDebugFunctionality(TDes8& aDebugFunctionality);
+	inline TInt GetMemoryOperationMaxBlockSize(TUint32 &aMaxSize);
+	inline TInt AttachProcess(TDesC8& aProcessName, TUint64 aAgentId);
+	inline TInt DetachProcess(TDesC8& aProcessName, TUint64 aAgentId);
+	inline TInt DetachAgent(TUint64 aAgentId);
+	inline TInt SetEventAction(TDesC8& aProcessName, Debug::TEventType aEvent, Debug::TKernelEventAction aEventAction, TUint64 aAgentId);
+	inline TInt GetList(const Debug::TListId aType, const Debug::TListScope aListScope, const TUint64 aTargetId, const TUint64 aDebugProcessId, TDes8& aBuffer, TUint32& aDataSize);
+	inline TInt Step(const TUint32 aThreadId, const TUint32 aNumSteps);
+	inline TInt IsDebuggable(const TUint32 aProcessId);
+	inline TInt KillProcess(const TUint32 aProcessId, const TInt32 aReason);
+};
+
+_LIT(KRM_DebugDriverName,"RM Debug Driver");
+
+//priority set equal to that of KDfcThread0Priority defined in e32/kernel/sinit.cpp
+const TInt KRmDebugDriverThreadPriority = 27;
+
+// Version information
+const TInt KMajorVersionNumber=2;
+const TInt KMinorVersionNumber=1;
+const TInt KBuildVersionNumber=0;
+
+
+inline TInt RRM_DebugDriver::Open(const TRM_DebugDriverInfo aDriverInfo)
+{
+	TBuf8<32> buf;
+	buf.Append((TUint8*)&aDriverInfo.iPanic1Address, 4);
+	buf.Append((TUint8*)&aDriverInfo.iPanic2Address, 4);
+	buf.Append((TUint8*)&aDriverInfo.iException1Address, 4);
+	buf.Append((TUint8*)&aDriverInfo.iException2Address, 4);
+	buf.Append((TUint8*)&aDriverInfo.iLibraryLoadedAddress, 4);
+	buf.Append((TUint8*)&aDriverInfo.iUserLibraryEnd, 4);
+	
+	#ifdef EKA2
+	return DoCreate(KRM_DebugDriverName, TVersion(KMajorVersionNumber, KMinorVersionNumber, KBuildVersionNumber), KNullUnit, NULL, &buf);
+	#else
+	return DoCreate(KRM_DebugDriverName, TVersion(KMajorVersionNumber, KMinorVersionNumber, KBuildVersionNumber), NULL, KNullUnit, NULL, &buf);
+	#endif
+}
+
+inline TInt RRM_DebugDriver::SetBreak(Debug::TBreakId &aBreakId, const TUint32 aThreadId, const TUint32 aAddress, const Debug::TArchitectureMode aMode )
+{
+	TSetBreakInfo info(&aBreakId, aThreadId, aAddress, aMode, ETrue);
+	return DoSvControl(EControlSetBreak, reinterpret_cast<TAny*>(&info),0);
+}
+inline TInt RRM_DebugDriver::SetProcessBreak(Debug::TBreakId &aBreakId, const TUint32 aProcessId, const TUint32 aAddress, const Debug::TArchitectureMode aMode )
+{
+	TSetBreakInfo info(&aBreakId, aProcessId, aAddress, aMode, EFalse);
+	return DoSvControl(EControlSetBreak, reinterpret_cast<TAny*>(&info),0);
+}
+
+inline TInt RRM_DebugDriver::ClearBreak(const Debug::TBreakId aBreakId)
+{
+	return DoSvControl(EControlClearBreak, reinterpret_cast<TAny*>(aBreakId), 0);
+}
+
+inline TInt RRM_DebugDriver::ModifyBreak(const Debug::TBreakId aBreakId, const TUint32 aThreadId, const TUint32 aAddress, const Debug::TArchitectureMode aMode)
+{
+	TModifyBreakInfo info(aBreakId, aThreadId, aAddress, aMode);
+	return DoControl(EControlModifyBreak, reinterpret_cast<TAny*>(&info), 0);
+}
+
+inline TInt RRM_DebugDriver::ModifyProcessBreak(const Debug::TBreakId aBreakId, const TUint32 aProcessId, const TUint32 aAddress, const Debug::TArchitectureMode aMode)
+{
+	TModifyProcessBreakInfo info(aBreakId, aProcessId, aAddress, aMode);
+	return DoControl(EControlModifyProcessBreak, reinterpret_cast<TAny*>(&info), 0);
+}
+
+inline TInt RRM_DebugDriver::BreakInfo(const Debug::TBreakId aBreakId, TUint64& aId, TUint32& aAddress, Debug::TArchitectureMode& aMode, TBool& aThreadSpecific)
+{
+	TGetBreakInfo info(aBreakId, aId, aAddress, aMode, aThreadSpecific);
+	return DoControl(EControlBreakInfo, reinterpret_cast<TAny*>(&info), 0);
+}
+
+inline TInt RRM_DebugDriver::SuspendThread(const TUint32 aThreadId)
+{
+	return DoControl(EControlSuspendThread, reinterpret_cast<TAny*>(aThreadId));
+}
+
+inline TInt RRM_DebugDriver::ResumeThread(const TUint32 aThreadId)
+{
+	return DoSvControl(EControlResumeThread, reinterpret_cast<TAny*>(aThreadId));
+}
+
+inline TInt RRM_DebugDriver::StepRange(const TUint32 aThreadId, const TUint32 aStartAddress, const TUint32 aStopAddress, TBool aStepInto)
+{
+	TRM_DebugStepInfo info(aStartAddress, aStopAddress, aStepInto);
+	return DoSvControl(EControlStepRange, reinterpret_cast<TAny*>(aThreadId), (TAny*)&info);
+}
+
+inline TInt RRM_DebugDriver::ReadMemory(const TUint32 aThreadId, const TUint32 aAddress, const TUint32 aLength, TDes8 &aData)
+{
+	TRM_DebugMemoryInfo info(aAddress, aLength, &aData);
+	return DoControl(EControlReadMemory, reinterpret_cast<TAny*>(aThreadId), (TAny*)&info);
+}
+
+inline TInt RRM_DebugDriver::WriteMemory(const TUint32 aThreadId, const TUint32 aAddress, const TUint32 aLength, const TDesC8 &aData)
+{
+	TRM_DebugMemoryInfo info(aAddress, aLength, (TDesC8*)&aData);
+	return DoControl(EControlWriteMemory, reinterpret_cast<TAny*>(aThreadId), (TAny*)&info);
+}
+
+inline TInt RRM_DebugDriver::ReadRegisters(const TUint32 aThreadId, const TDes8 &aRegisterIds, TDes8 &aRegisterValues, TDes8 &aRegisterFlags)
+	{
+	TRM_DebugRegisterInformation info(&aRegisterIds, &aRegisterValues, &aRegisterFlags);
+	return DoControl(EControlReadRegisters, reinterpret_cast<TAny*>(aThreadId), (TAny*)&info);	
+	}
+
+inline TInt RRM_DebugDriver::WriteRegisters(const TUint32 aThreadId, const TDes8 &aRegisterIds, const TDes8 &aRegisterValues, TDes8 &aRegisterFlags)
+	{
+	TRM_DebugRegisterInformation info(&aRegisterIds, (TDes8*)&aRegisterValues, &aRegisterFlags);
+	return DoControl(EControlWriteRegisters, reinterpret_cast<TAny*>(aThreadId), (TAny*)&info);
+	}
+
+inline TInt RRM_DebugDriver::ReadRegisters(const TUint32 aThreadId, const TInt32 aFirstRegister, const TInt32 aLastRegister, TDes8 &aValues)
+{
+	TRM_DebugRegisterInfo info(aFirstRegister, aLastRegister, &aValues);
+	return DoControl(EControlReadRegistersLegacy, reinterpret_cast<TAny*>(aThreadId), (TAny*)&info);
+}
+
+inline TInt RRM_DebugDriver::WriteRegisters(const TUint32 aThreadId, const TInt32 aFirstRegister, const TInt32 aLastRegister, TDesC8 &aValues)
+{
+	TRM_DebugRegisterInfo info(aFirstRegister, aLastRegister, &aValues);
+	return DoControl(EControlWriteRegistersLegacy, reinterpret_cast<TAny*>(aThreadId), (TAny*)&info);
+}
+
+inline void RRM_DebugDriver::GetEvent(TDesC8& aProcessName, TUint64 aAgentId, TRequestStatus &aStatus, Debug::TEventInfo &aEventInfo)
+{
+	// temporary object not needed beyond the DoRequest call
+	TEventMetaData eventMetaData;
+	eventMetaData.iTargetProcessName.Copy(aProcessName);
+	eventMetaData.iDebugAgentProcessId = aAgentId;
+	DoRequest(ERequestGetEvent, aStatus, (TAny*)&aEventInfo, (TAny*)&eventMetaData);
+}
+
+inline void RRM_DebugDriver::CancelGetEvent(TDesC8& aProcessName, TUint64 aAgentId)
+{
+	TRMD_DebugCancelInfo info(ERequestGetEventCancel,aProcessName,aAgentId);
+	DoCancel(reinterpret_cast<TInt>(&info));
+}
+
+inline TInt RRM_DebugDriver::GetStaticLibraryInfo(const TInt aIndex, Debug::TEventInfo &aInfo)
+{
+	return DoControl(EControlGetStaticLibraryInfo, reinterpret_cast<TAny*>(aIndex), (TAny*)&aInfo);
+}
+
+inline TInt RRM_DebugDriver::GetDebugFunctionalityBufSize(TUint32 &aBufSize)
+{
+	return DoControl(EControlGetDebugFunctionalityBufSize, reinterpret_cast<TAny*>(&aBufSize));
+}
+
+inline TInt RRM_DebugDriver::GetDebugFunctionality(TDes8& aDebugFunctionality)
+{
+	return DoControl(EControlGetDebugFunctionality,reinterpret_cast<TAny*>(&aDebugFunctionality));
+}
+
+inline TInt RRM_DebugDriver::GetMemoryOperationMaxBlockSize(TUint32 &aMaxSize)
+{
+	return DoControl(EControlGetMemoryOperationMaxBlockSize, reinterpret_cast<TAny*>(&aMaxSize));
+}
+
+inline TInt RRM_DebugDriver::AttachProcess(TDesC8& aProcessName, TUint64 aAgentId)
+{
+	TRM_DebugAgentId info(aAgentId);
+	return DoControl(EControlAttachProcess,reinterpret_cast<TAny*>(&aProcessName),reinterpret_cast<TAny*>(&info));
+}
+
+inline TInt RRM_DebugDriver::DetachProcess(TDesC8& aProcessName, TUint64 aAgentId)
+{
+	TRM_DebugAgentId info(aAgentId);
+	return DoControl(EControlDetachProcess,reinterpret_cast<TAny*>(&aProcessName),reinterpret_cast<TAny*>(&info));
+}
+
+inline TInt RRM_DebugDriver::DetachAgent(TUint64 aAgentId)
+{
+	TRM_DebugAgentId info(aAgentId);
+	return DoControl(EControlDetachAgent,reinterpret_cast<TAny*>(&info),0);
+}
+
+inline TInt RRM_DebugDriver::SetEventAction(TDesC8& aProcessName, Debug::TEventType aEvent, Debug::TKernelEventAction aEventAction, TUint64 aAgentId)
+{
+	TRM_DebugEventActionInfo info (aEvent,aEventAction, aAgentId);
+	return DoControl(EControlSetEventAction,reinterpret_cast<TAny*>(&aProcessName),(TAny*)&info);
+}
+
+inline TInt RRM_DebugDriver::GetList(const Debug::TListId aType, const Debug::TListScope aListScope, const TUint64 aTargetId, const TUint64 aDebugProcessId, TDes8& aBuffer, TUint32& aDataSize)
+{
+	TListInformation info(aType, aListScope, &aBuffer, &aDataSize, aTargetId);
+	return DoControl(EControlGetList, (TAny*)&info);
+}
+
+inline TInt RRM_DebugDriver::Step(const TUint32 aThreadId, const TUint32 aNumSteps)
+{
+	return DoControl(EControlStep,reinterpret_cast<TAny*>(aThreadId),reinterpret_cast<TAny*>(aNumSteps));
+}
+
+inline TInt RRM_DebugDriver::IsDebuggable(const TUint32 aProcessId)
+{
+	return DoControl(EControlIsDebuggable,reinterpret_cast<TAny*>(aProcessId),NULL);
+}
+
+inline TInt RRM_DebugDriver::KillProcess(const TUint32 aProcessId, const TInt32 aReason)
+{
+	return DoControl(EControlKillProcess,reinterpret_cast<TAny*>(aProcessId),reinterpret_cast<TAny*>(aReason));
+}
+
+#endif // __RM_DEBUG_KERNELDRIVER_H__
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/debugsrv/runmodedebug/rmdriver/src/d_debug_agent.cpp	Fri Aug 27 11:37:29 2010 +0300
@@ -0,0 +1,468 @@
+// Copyright (c) 2006-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+// Purpose: Kernel-side tracking of debug agent information associated
+// with each process being debugged.
+// 
+//
+
+#include <e32def.h>
+#include <e32def_private.h>
+#include <e32cmn.h>
+#include <e32cmn_private.h>
+#include <kernel/kernel.h> 
+#include <kernel/kern_priv.h>
+#include <nk_trace.h>
+#include <arm.h>
+
+#include "d_process_tracker.h"
+#include "debug_logging.h"
+
+#include "d_debug_agent.h"
+#include "debug_utils.h"
+
+#include "d_debug_agent.inl"
+
+using namespace Debug;
+
+// ctor
+DDebugAgent::DDebugAgent(TUint64 aId) :
+	iId(aId),
+	iRequestGetEventStatus(NULL),
+	iClientThread(0),
+	iEventQueue(KNumberOfEventsToQueue, 0),
+	iHead(0),
+	iTail(0),
+	iEventQueueLock(NULL),
+	iFreeSlots(KNumberOfEventsToQueue),
+	iIgnoringTrace(EFalse),
+	iEventBalance(0)
+	{
+	LOG_MSG2("DDebugAgent::DDebugAgent(), this=0x%x ", this);
+
+	// Initialize all the Event Actions to Ignore
+	for(TInt i=0; i<EEventsLast; i++)
+		{
+		iEventActions[i] = EActionIgnore;
+		}
+	}
+
+DDebugAgent* DDebugAgent::New(TUint64 aId)
+	{
+	LOG_MSG2("DDebugAgent::New(id=0x%lx)", aId);
+	DDebugAgent* agent = new DDebugAgent(aId);
+	if(agent == NULL)
+		{
+		return (NULL);
+		}
+	if(KErrNone != agent->Construct())
+		{
+		delete agent;
+		return (NULL);
+		}
+
+	// Use a semaphore to serialise access
+	TInt err = Kern::SemaphoreCreate(agent->iEventQueueLock, _L("RM_DebugAgentQueueLock"), 1 /* Initial count */);
+	if (err != KErrNone)
+		return NULL;
+
+	return agent;
+	}
+
+/** Standard contructor.
+ * Fills event queue with empty events
+ * @return : standard system error code
+ */
+TInt DDebugAgent::Construct()
+	{
+	// Empty the event queue
+	TDriverEventInfo emptyEvent;
+	TInt err = KErrNone;
+
+	for (TInt i=0; i<KNumberOfEventsToQueue; i++)
+		{
+		err = iEventQueue.Append(emptyEvent);
+		if (err != KErrNone)
+			{
+			LOG_MSG("Error appending blank event entry");
+			return err;
+			}
+		}
+
+	err = Kern::CreateClientDataRequest(iRequestGetEventStatus);
+	if(err != KErrNone)
+		{
+		LOG_MSG("Error creating TClientDataRequest");
+		return err;
+		}
+
+	LOG_MSG2("DDebugAgent::Construct() iRequestGetEventStatus=0x%08x", iRequestGetEventStatus);
+
+	return err;
+	}
+
+// dtor
+DDebugAgent::~DDebugAgent()
+	{
+	iEventQueue.Reset();
+
+	if (iEventQueueLock)
+		iEventQueueLock->Close(NULL);
+	
+	if(iRequestGetEventStatus)
+		Kern::DestroyClientRequest(iRequestGetEventStatus);
+	
+	}
+
+// Associate an action with a particular kernel event
+TInt DDebugAgent::SetEventAction(TEventType aEvent, TKernelEventAction aEventAction)
+	{
+	// Valid Event?
+	if (aEvent >= EEventsLast)
+		{
+		LOG_MSG2("DDebugAgent::EventAction: Bad Event number %d",aEvent);
+		return KErrArgument;
+		}
+
+	iEventActions[aEvent] = aEventAction;
+
+	return KErrNone;
+	}
+
+/** Get the aEventAction associated with aEvent
+ *
+ * @return : aEventAction (always +ve), or KErrArgument.
+ */
+TInt DDebugAgent::EventAction(TEventType aEvent)
+	{
+	// Validate the Event id
+	if (aEvent >= EEventsLast)
+		{
+		LOG_MSG2("DDebugAgent::EventAction: Bad Event number %d",aEvent);
+		return KErrArgument;
+		}
+
+	// Return the action associated with this event
+	return iEventActions[aEvent];
+	}
+
+/** Obtain the details of the latest kernel event (if it exists) and place the details in aEventInfo
+ * If there is no event in the queue for this process+agent combination, store the details
+ * so that it can be notified later when an event actually occurs.
+ * 
+ * @param aAsyncGetValueRequest - TClientDataRequest object used for pinning user memory
+ * @param aClientThread - The ThreadId of the requesting user-side process. In this case the DSS.
+ */
+void DDebugAgent::GetEvent(TClientDataRequest<TEventInfo>* aAsyncGetValueRequest, DThread* aClientThread)
+	{
+	LockEventQueue();
+
+	iRequestGetEventStatus->Reset();
+	TInt err = iRequestGetEventStatus->SetStatus( aAsyncGetValueRequest->StatusPtr() );
+	if (err != KErrNone)
+		{
+		LOG_MSG2("Error :iRequestGetEventStatus->SetStatus ret %d", err);
+		UnlockEventQueue();
+		return;
+		}
+	
+	iRequestGetEventStatus->SetDestPtr( aAsyncGetValueRequest->DestPtr() );
+
+	iEventBalance++;
+	
+	LOG_MSG5("DDebugAgent::GetEvent: this=0x%08x, iRequestGetEventStatus=0x%08x, iEventBalance=%d, destPrt=0x%08x", 
+		this, iRequestGetEventStatus, iEventBalance, aAsyncGetValueRequest->DestPtr() );
+	
+	iClientThread = aClientThread;
+	
+	if (BufferEmpty())
+		{
+		LOG_MSG2("Event buffer empty, iEventBalance=%d", iEventBalance);		
+		UnlockEventQueue();
+		return;
+		}
+
+	LOG_MSG5("Event already available at queue pos (tail)=%d, evType=%d, threadId=0x%x, actionTaken=%d", 
+	        iTail,	iEventQueue[iTail].iEventType,	
+	        iEventQueue[iTail].iThreadId, iEventQueue[iTail].iActionTaken );
+	
+	// returning the event to the client
+	err = iEventQueue[iTail].WriteEventToClientThread(iRequestGetEventStatus,iClientThread);
+	if (err != KErrNone)
+		{
+		LOG_MSG2("Error writing event info: %d", err);
+		UnlockEventQueue();
+		return;
+		}
+
+	// signal the DSS thread
+	Kern::QueueRequestComplete(iClientThread, iRequestGetEventStatus, KErrNone);
+	iEventBalance--;
+
+	iEventQueue[iTail].Reset();
+
+	// move to the next slot
+	IncrementTailPosition();
+
+	UnlockEventQueue();
+	}
+
+/**
+ * Stop waiting for an event to occur. This means events will be placed 
+ * in the iEventQueue (by setting iEventBalance to 0) until GetEvent is called. 
+ */ 
+TInt DDebugAgent::CancelGetEvent(void)
+	{
+	LOG_MSG2("DDebugAgent::CancelGetEvent. iEventBalance=%d. > QueueRequestComplete", iEventBalance);
+	Kern::QueueRequestComplete(iClientThread, iRequestGetEventStatus, KErrCancel);
+	iEventBalance=0;
+	iClientThread = 0;
+	return KErrNone;
+	}
+
+/** Signal a kernel event to the user-side DSS when it occurs, or queue it for later
+ * if the user-side has not called GetEvent (see above).
+ * 
+ * @param aEventInfo - the details of the event to queue.
+ */
+void DDebugAgent::NotifyEvent(const TDriverEventInfo& aEventInfo)
+	{
+
+	if(aEventInfo.iEventType >= EEventsLast)
+		{
+		LOG_MSG3("DDebugAgent::NotifyEvent(),iEventType %d, this=0x%x. Ignoring since > EEventsLast", aEventInfo.iEventType, this);
+		return;
+		}
+
+	LockEventQueue();
+
+	DThread* currentThread = &Kern::CurrentThread();
+	
+
+	TKernelEventAction action = iEventActions[aEventInfo.iEventType];
+
+	if (aEventInfo.iProcessId == Id() &&
+		(aEventInfo.iEventType == EEventsSwExc || aEventInfo.iEventType == EEventsHwExc ||	aEventInfo.iEventType == EEventsKillThread))
+		{
+
+		// It might be nice not to deliver *any* events about the debug agent to the agent itself, but this is a bit too drastic a change to make.
+		// There's a risk it might completely break TRK or similar, and at a more practical level it would require major rewriting of the t_rmdebug2
+		// tests.
+		//
+		// So instead, we only don't suspend&deliver events about the debug agent IF it's a thread crash event AND the thread is process
+		// critical/permanent AND (in the case of a critical thread) it's an abnormal exit. We're not worrying (yet) about the case where the entire
+		// process is set as system critical
+		// This fixes the original problem with CDS's worker thread crashing, and doesn't wreck the t_rmdebug2 tests.
+
+		TBool problematic = (
+			(aEventInfo.iThreadFlags & (KThreadFlagProcessCritical|KThreadFlagSystemCritical) && (aEventInfo.iEventType != EEventsKillThread || aEventInfo.iExitType != EExitKill)) // process or system critical, and either an exception (not a EEventsKillThread) or a non EExitKill exit
+			|| (aEventInfo.iThreadFlags & (KThreadFlagProcessPermanent|KThreadFlagSystemPermanent))
+			);
+
+		if (problematic)
+			{
+			LOG_MSG("Agent is dying - no further events will be delivered to it");
+			iAgentDying = ETrue;
+			}
+
+		}
+
+	if (iAgentDying && action == EActionSuspend)
+		{
+		LOG_MSG("Not delivering this event or suspending the thread because agent is dying");
+		action = EActionIgnore;
+		}
+
+	switch (action)
+		{
+		case EActionSuspend:
+			{
+			LOG_MSG5("DDebugAgent::NotifyEvent(), Suspend thread, iEventType %d, this=0x%x currThrd=0x%08x, iEventBalance=%d",
+				aEventInfo.iEventType, this, currentThread, iEventBalance );
+
+			switch(aEventInfo.iEventType)
+				{
+				case EEventsAddLibrary:
+				case EEventsRemoveLibrary:
+					// TomS: Anybody want to explain what is going on here??
+					currentThread = DebugUtils::OpenThreadHandle(aEventInfo.iThreadId);
+					if(currentThread)
+						{
+						currentThread->Close(NULL);
+						}
+					break;
+				default:
+					break;
+				}
+			
+			// Do not call suspend for breakpoints, since the breakpoint code that runs when deciding if an exception
+			// is a breakpoint will itself suspend the thread 
+			if( (aEventInfo.iEventType != EEventsBreakPoint) && (aEventInfo.iEventType != EEventsProcessBreakPoint) )
+			    {
+                TInt err = TheDProcessTracker.SuspendThread(currentThread, aEventInfo.FreezeOnSuspend());
+                if((err != KErrNone) && (err != KErrAlreadyExists))
+                    {
+                    // Is there anything we can do in the future to deal with this error having happened?
+                    LOG_MSG2("DDebugAgent::NotifyEvent() Problem while suspending thread: %d", err);
+                    }
+			    }
+
+			// now drop through to the continue case, which typically notifies
+			// the debug agent of the event
+			}
+		case EActionContinue:
+			{
+			if( action == EActionContinue )
+				{
+				LOG_MSG5("DDebugAgent::NotifyEvent(), Action continue, iEventType %d, this=0x%x currThrd=0x%08x, iEventBalance=%d",
+					aEventInfo.iEventType, this, currentThread, iEventBalance );
+				}
+
+			// Queue this event
+			TDriverEventInfo eventInfo = aEventInfo;
+			eventInfo.iActionTaken = action;
+			QueueEvent(eventInfo);
+
+			// Tell the user about the oldest event in the queue
+			if ( iClientThread )
+				{
+				if( iRequestGetEventStatus && (iEventBalance > 0) )
+					{
+					// Fill the event data
+					TInt err = iEventQueue[iTail].WriteEventToClientThread(iRequestGetEventStatus,iClientThread);
+					if (err != KErrNone)
+						{
+						LOG_MSG2("Error writing event info: %d", err);
+						}
+
+					// signal the debugger thread 
+					LOG_MSG4("> QueueRequestComplete iRequestGetEventStatus=0x%08x, iEventBalance=%d, iTail=%d",
+						iRequestGetEventStatus->iStatus, iEventBalance, iTail );
+					Kern::QueueRequestComplete(iClientThread, iRequestGetEventStatus, KErrNone);
+
+					iEventBalance--;
+
+					iEventQueue[iTail].Reset();
+
+					// move to the next slot
+					IncrementTailPosition();
+					}
+				else
+					{
+					if( !iRequestGetEventStatus )
+						{
+						LOG_MSG("iRequestGetEventStatus is NULL so not signalling client" );
+						}
+					else
+						{
+						LOG_MSG2("Queued event. iEventBalance=%d (unbalanced event requests vs notifications)", 
+							iEventBalance );
+						}
+					}
+				}
+			else
+				{
+				 LOG_MSG("DDebugAgent::NotifyEvent() : Not informing client since its thread is NULL");
+				}
+			break;
+			}
+		case EActionIgnore:
+		default:
+			// Ignore everything we don't understand.
+			break;
+		}
+
+	UnlockEventQueue();
+
+	}
+
+// Used to identify which Debug Agent this DDebugAgent is associated with.
+TUint64 DDebugAgent::Id(void)
+	{
+	return iId;
+	}
+
+/**
+ * Used to add an event to the event queue for this debug agent if event 
+ * queue is not at critical level. If it is at critical and it is trace event, 
+ * we start ignoring trace events and insert a lost trace event.
+ * If the buffer cannot store an event, only insert a buffer full event.
+ * @see EEventsBufferFull
+ * @see EEventsUserTracesLost
+ * @see TDriverEventInfo
+ * @see iEventQueue
+ */
+void DDebugAgent::QueueEvent(const TDriverEventInfo& aEventInfo)
+	{
+	// Have we caught the tail?
+	if(BufferFull())
+		{
+		LOG_MSG("DDebugAgent::QueueEvent : BufferFull. Not queueing");
+		return;
+		}
+
+	// Assert if we think there is space but the slot is not marked empty
+	__NK_ASSERT_DEBUG(iEventQueue[iHead].iEventType == EEventsUnknown);
+
+	const TBool bufferAtCritical = BufferAtCriticalLevel();
+
+	if(!bufferAtCritical)
+		{
+		//reset the iIgnoringTrace flag as we are not at 
+		//critical level and can store event
+		iIgnoringTrace = EFalse; 
+		
+		// Insert the event into the ring buffer at iHead
+		iEventQueue[iHead] = aEventInfo;
+		IncrementHeadPosition();
+		}
+	else if(bufferAtCritical && BufferCanStoreEvent())
+		{
+		LOG_MSG("DDebugAgent::QueueEvent : BufferCritical");
+		if(aEventInfo.iEventType == EEventsUserTrace)
+			{
+			if(!iIgnoringTrace)
+				{
+				//if this is the first time we are ignoring trace events, 
+				//we need to issue a EEventsUserTracesLost event
+				iEventQueue[iHead].Reset();
+				iEventQueue[iHead].iEventType = EEventsUserTracesLost;
+				IncrementHeadPosition();
+
+				iIgnoringTrace = ETrue;
+				}
+			else
+				{
+				//otherwise, ignore this event
+				LOG_MSG("DDebugAgent::QueueEvent : Ignore EEventsUserTrace event");
+				}
+			}
+		else
+			{
+			// Store the event since its not a trace event
+			iEventQueue[iHead] = aEventInfo;
+			IncrementHeadPosition();
+			}
+		}
+	else
+		{
+		//At critical level and cannot store new events, so 
+		//only one space left. Store a EEventsBufferFull event
+		LOG_MSG("DDebugAgent::QueueEvent : Event Buffer Full, ignoring event");
+		iEventQueue[iHead].Reset();
+		iEventQueue[iHead].iEventType = EEventsBufferFull;
+		IncrementHeadPosition();
+		}
+	}
+
+// End of file - d_debug_agent.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/debugsrv/runmodedebug/rmdriver/src/d_debug_functionality.cpp	Fri Aug 27 11:37:29 2010 +0300
@@ -0,0 +1,426 @@
+// Copyright (c) 2006-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+// Defines the DebugFunctionality class. This is responsible for
+// providing configuration data needed by a host debugger to be able
+// to correctly use the functionality provided by the run-mode debug subsystem.
+// 
+
+#include <e32def.h>
+#include <e32def_private.h>
+#include <e32cmn.h>
+#include <e32cmn_private.h>
+#include <u32std.h>
+#include <kernel/kernel.h>
+#include <rm_debug_api.h>
+#include "d_rmd_breakpoints.h"
+#include "rm_debug_kerneldriver.h"
+#include "d_debug_functionality.h"
+
+using namespace Debug;
+
+// Core
+const TTag DebugFunctionalityCoreInfo[] =
+	{
+	{ECoreEvents,ETagTypeBoolean,0,ETrue},
+	{ECoreStartStop,ETagTypeBoolean,0,ETrue},
+	{ECoreMemory,ETagTypeBoolean,0,ETrue},
+	{ECoreRegister,ETagTypeBoolean,0,ETrue},
+	{ECoreBreakpoint,ETagTypeBoolean,0,ETrue},
+	{ECoreStepping,ETagTypeBoolean,0,ETrue},
+	{ECoreLists,ETagTypeBoolean,0,ETrue},
+	{ECoreLogging,ETagTypeBoolean,0,EFalse},
+	{ECoreHardware,ETagTypeBoolean,0,EFalse},
+	{ECoreApiConstants,ETagTypeBoolean,0,ETrue},
+	{ECoreKillObjects,ETagTypeBoolean,0,ETrue},
+	{ECoreSecurity,ETagTypeBoolean,0,ETrue},	
+	};
+
+const TSubBlock DebugFunctionalityCore[] =
+	{
+	ETagHeaderIdCore,ECoreLast,
+	(TTag*)DebugFunctionalityCoreInfo
+	};
+
+// Memory
+const TTag DebugFunctionalityMemoryInfo[] =
+	{
+	{EMemoryRead,ETagTypeBoolean,0,ETrue}, 
+	{EMemoryWrite,ETagTypeBoolean,0,ETrue},
+	{EMemoryAccess64,ETagTypeBoolean,0,EFalse},
+	{EMemoryAccess32,ETagTypeBoolean,0,ETrue},
+	{EMemoryAccess16,ETagTypeBoolean,0,EFalse},
+	{EMemoryAccess8,ETagTypeBoolean,0,EFalse},
+	{EMemoryBE8,ETagTypeBoolean,0,EFalse},
+	{EMemoryBE32,ETagTypeBoolean,0,EFalse},
+	{EMemoryLE8,ETagTypeBoolean,0,ETrue},
+	{EMemoryMaxBlockSize,ETagTypeTUint32,0,16 * KKilo /* 16Kbytes */}	// binaryMax size of memory requests in bytes
+	};
+
+const TSubBlock DebugFunctionalityMemory[]=
+	{
+	ETagHeaderIdMemory,EMemoryLast,
+	(TTag*)DebugFunctionalityMemoryInfo
+	};
+
+// Kill Objects
+const TTag DebugFunctionalityKillObjectsInfo[] =
+	{
+	{EFunctionalityKillThread,ETagTypeBoolean,0,EFalse}, 
+	{EFunctionalityKillProcess,ETagTypeBoolean,0,ETrue}
+	};
+
+const TSubBlock DebugFunctionalityKillObjects[]=
+	{
+	ETagHeaderIdKillObjects,EFunctionalityKillObjectLast,
+	(TTag*)DebugFunctionalityKillObjectsInfo
+	};
+
+// Core Registers
+const TTag DebugFunctionalityRegistersCoreInfo[] =
+	{
+	{ERegisterR0,ETagTypeEnum, 4,EAccessReadWrite},
+	{ERegisterR1,ETagTypeEnum, 4,EAccessReadWrite},
+	{ERegisterR2,ETagTypeEnum, 4,EAccessReadWrite},
+	{ERegisterR3,ETagTypeEnum, 4,EAccessReadWrite},
+	{ERegisterR4,ETagTypeEnum, 4,EAccessReadWrite},
+	{ERegisterR5,ETagTypeEnum, 4,EAccessReadWrite},
+	{ERegisterR6,ETagTypeEnum, 4,EAccessReadWrite},
+	{ERegisterR7,ETagTypeEnum, 4,EAccessReadWrite},
+	{ERegisterR8,ETagTypeEnum, 4,EAccessReadWrite},
+	{ERegisterR9,ETagTypeEnum, 4,EAccessReadWrite},
+	{ERegisterR10,ETagTypeEnum, 4,EAccessReadWrite},
+	{ERegisterR11,ETagTypeEnum, 4,EAccessReadWrite},
+	{ERegisterR12,ETagTypeEnum, 4,EAccessReadWrite},
+	{ERegisterR13,ETagTypeEnum, 4,EAccessReadWrite},
+	{ERegisterR14,ETagTypeEnum, 4,EAccessReadWrite},
+	{ERegisterR15,ETagTypeEnum, 4,EAccessReadWrite},
+	{ERegisterCpsr,ETagTypeEnum, 4,EAccessReadWrite},
+	{ERegisterR13Svc,ETagTypeEnum, 4,EAccessNone},
+	{ERegisterR14Svc,ETagTypeEnum, 4,EAccessNone},
+	{ERegisterSpsrSvc,ETagTypeEnum, 4,EAccessNone},
+	{ERegisterR13Abt,ETagTypeEnum, 4,EAccessNone},
+	{ERegisterR14Abt,ETagTypeEnum, 4,EAccessNone},
+	{ERegisterSpsrAbt,ETagTypeEnum, 4,EAccessNone},
+	{ERegisterR13Und,ETagTypeEnum, 4,EAccessNone},
+	{ERegisterR14Und,ETagTypeEnum, 4,EAccessNone},
+	{ERegisterSpsrUnd,ETagTypeEnum, 4,EAccessNone},
+	{ERegisterR13Irq,ETagTypeEnum, 4,EAccessNone},
+	{ERegisterR14Irq,ETagTypeEnum, 4,EAccessNone},
+	{ERegisterSpsrIrq,ETagTypeEnum, 4,EAccessNone},
+	{ERegisterR8Fiq,ETagTypeEnum, 4,EAccessNone},
+	{ERegisterR9Fiq,ETagTypeEnum, 4,EAccessNone},
+	{ERegisterR10Fiq,ETagTypeEnum, 4,EAccessNone},
+	{ERegisterR11Fiq,ETagTypeEnum, 4,EAccessNone},
+	{ERegisterR12Fiq,ETagTypeEnum, 4,EAccessNone},
+	{ERegisterR13Fiq,ETagTypeEnum, 4,EAccessNone},
+	{ERegisterR14Fiq,ETagTypeEnum, 4,EAccessNone},
+	{ERegisterSpsrFiq, ETagTypeEnum, 4,EAccessNone}
+	};
+
+const TSubBlock DebugFunctionalityRegistersCore[] =
+	{
+	ETagHeaderIdRegistersCore, ERegisterLast,
+	(TTag*)DebugFunctionalityRegistersCoreInfo
+	};
+
+// Co-processor registers
+const TTag DebugFunctionalityRegistersCoProInfo[]=
+	{
+	//this is the DACR register
+	{0x00300f01, ETagTypeTUint32, 4, EAccessReadWrite} 
+	};
+
+const TSubBlock DebugFunctionalityRegistersCoPro[]=
+	{
+	ETagHeaderIdCoProRegisters,1,
+	(TTag*)DebugFunctionalityRegistersCoProInfo
+	};
+
+// Breakpoints
+const TTag DebugFunctionalityBreakpointsInfo[]=
+	{
+	{EBreakpointThread,ETagTypeBoolean,0,ETrue},
+	{EBreakpointProcess,ETagTypeBoolean,0,ETrue},
+	{EBreakpointSystem,ETagTypeBoolean,0,EFalse},
+	{EBreakpointArm,ETagTypeBoolean,0,ETrue},
+	{EBreakpointThumb,ETagTypeBoolean,0,ETrue},
+	{EBreakpointT2EE,ETagTypeBoolean,0,ETrue},
+	{EBreakpointArmInst,ETagTypeBoolean,0,EFalse},
+	{EBreakpointThumbInst,ETagTypeBoolean,0,EFalse},
+	{EBreakpointT2EEInst,ETagTypeBoolean,0,ETrue},
+	{EBreakpointSetArmInst,ETagTypeBoolean,0,EFalse},
+	{EBreakpointSetThumbInst,ETagTypeBoolean,0,EFalse},
+	{EBreakpointSetT2EEInst,ETagTypeBoolean,0,ETrue}
+	};
+
+const TSubBlock DebugFunctionalityBreakpoints[] =
+	{
+	ETagHeaderIdBreakpoints, EBreakpointLast,
+	(TTag*)DebugFunctionalityBreakpointsInfo
+	};
+
+// Stepping
+const TTag DebugFunctionalitySteppingInfo[]=
+	{
+	{EStep,ETagTypeBoolean,0,ETrue}
+	};
+
+const TSubBlock DebugFunctionalityStepping[] =
+	{
+	ETagHeaderIdStepping, EStepLast,
+	(TTag*)DebugFunctionalitySteppingInfo
+	};
+
+// Execution Control
+const TTag DebugFunctionalityExecutionInfo[]=
+	{
+	{EExecThreadSuspendResume,ETagTypeBoolean,0,ETrue},
+	{EExecProcessSuspendResume,ETagTypeBoolean,0,EFalse},
+	{EExecSystemSuspendResume,ETagTypeBoolean,0,EFalse},
+	};
+
+const TSubBlock DebugFunctionalityExecution[]=
+	{
+	ETagHeaderIdExecution, EExecLast,
+	(TTag*)DebugFunctionalityExecutionInfo
+	};
+
+// Events
+const TTag DebugFunctionalityEventsInfo[]=
+	{
+	{EEventsBreakPoint,ETagTypeEnum,0,EActionSuspend},
+	{EEventsProcessBreakPoint,ETagTypeEnum,0,EActionSuspend},
+	{EEventsSwExc,ETagTypeEnum,0,EActionSuspend},
+	{EEventsHwExc,ETagTypeEnum,0,EActionSuspend},
+	{EEventsKillThread,ETagTypeEnum,0,EActionContinue},
+	{EEventsAddLibrary,ETagTypeEnum,0,EActionSuspend},
+	{EEventsRemoveLibrary,ETagTypeEnum,0,EActionSuspend},
+	{EEventsUserTrace,ETagTypeEnum,0,EActionSuspend},
+	{EEventsStartThread,ETagTypeEnum,0,EActionSuspend},
+	{EEventsBufferFull,ETagTypeEnum,0,EActionContinue},
+	{EEventsUnknown,ETagTypeEnum,0,EActionContinue},
+	{EEventsUserTracesLost, ETagTypeEnum, 0, EActionContinue},
+	{EEventsAddProcess,ETagTypeEnum,0,EActionContinue},
+	{EEventsRemoveProcess,ETagTypeEnum,0,EActionContinue}
+	};
+
+const TSubBlock DebugFunctionalityEvents[] =
+	{
+	ETagHeaderIdEvents, EEventsLast,
+	(TTag*)DebugFunctionalityEventsInfo
+	};
+
+// API Constants
+const TTag DebugFunctionalityApiConstantsInfo[]=
+	{
+	{EApiConstantsTEventInfoSize,ETagTypeTUint32,0,sizeof(TEventInfo)},
+	};
+
+const TSubBlock DebugFunctionalityApiConstants[] =
+	{
+	ETagHeaderIdApiConstants, EApiConstantsLast,
+	(TTag*)DebugFunctionalityApiConstantsInfo
+	};
+
+// Listings
+const TTag DebugFunctionalityListInfo[] =
+	{
+	{EProcesses,ETagTypeBitField,0,EScopeGlobal},
+	{EThreads,ETagTypeBitField,0,EScopeGlobal|EScopeProcessSpecific|EScopeThreadSpecific},
+	{ECodeSegs,ETagTypeBitField,0,EScopeGlobal|EScopeProcessSpecific|EScopeThreadSpecific},
+	{EXipLibraries,ETagTypeBitField,0,EScopeGlobal},
+	{EExecutables,ETagTypeBitField,0,EScopeGlobal},
+	{ELogicalDevices,ETagTypeBitField,0,EScopeNone},
+	{EMutexes,ETagTypeBitField,0,EScopeNone},
+	{EServers,ETagTypeBitField,0,EScopeNone},
+	{ESessions,ETagTypeBitField,0,EScopeNone},
+	{ESemaphores,ETagTypeBitField,0,EScopeNone},
+	{EChunks,ETagTypeBitField,0,EScopeNone},
+	{EBreakpoints,ETagTypeBitField,0,EScopeNone},
+	{ESetBreak,ETagTypeBitField,0,EScopeNone},
+	{ERemoveBreak,ETagTypeBitField,0,EScopeNone},
+	{EModifyBreak,ETagTypeBitField,0,EScopeNone},
+	};
+
+const TSubBlock DebugFunctionalityList[] =
+	{
+	ETagHeaderList, EListLast,
+	(TTag*)DebugFunctionalityListInfo
+	};
+
+// Security
+const TTag DebugFunctionalitySecurityInfo[]=
+	{
+	{ESecurityOEMDebugToken,ETagTypeBoolean,0,ETrue}
+	};
+
+const TSubBlock DebugFunctionalitySecurity[] =
+	{
+	ETagHeaderIdSecurity, ESecurityLast,
+	(TTag*)DebugFunctionalitySecurityInfo
+	};
+
+TUint32 TDebugFunctionality::GetDebugFunctionalityBufSize(void)
+	{
+	TUint32 df_size = 0;
+
+	df_size += ComputeBlockSize((const TSubBlock&)DebugFunctionalityCore);
+	df_size += ComputeBlockSize((const TSubBlock&)DebugFunctionalityMemory);
+	df_size += ComputeBlockSize((const TSubBlock&)DebugFunctionalityRegistersCore);
+	df_size += ComputeBlockSize((const TSubBlock&)DebugFunctionalityRegistersCoPro);
+	df_size += ComputeBlockSize((const TSubBlock&)DebugFunctionalityBreakpoints);
+	df_size += ComputeBlockSize((const TSubBlock&)DebugFunctionalityStepping);
+	df_size += ComputeBlockSize((const TSubBlock&)DebugFunctionalityExecution);
+	df_size += ComputeBlockSize((const TSubBlock&)DebugFunctionalityEvents);
+	df_size += ComputeBlockSize((const TSubBlock&)DebugFunctionalityApiConstants);
+	df_size += ComputeBlockSize((const TSubBlock&)DebugFunctionalityList);
+	df_size += ComputeBlockSize((const TSubBlock&)DebugFunctionalityKillObjects);
+	df_size += ComputeBlockSize((const TSubBlock&)DebugFunctionalitySecurity);
+	
+	return df_size;
+	}
+
+TBool TDebugFunctionality::GetDebugFunctionality(TDes8& aDFBlock)
+	{
+	if (aDFBlock.MaxLength() < GetDebugFunctionalityBufSize() )
+		{
+		// Insufficient space to contain the debug functionality block
+		return EFalse;
+		}
+
+	AppendBlock((const TSubBlock&)DebugFunctionalityCore,aDFBlock);
+	AppendBlock((const TSubBlock&)DebugFunctionalityMemory,aDFBlock);
+	AppendBlock((const TSubBlock&)DebugFunctionalityRegistersCore,aDFBlock);
+	AppendBlock((const TSubBlock&)DebugFunctionalityRegistersCoPro,aDFBlock);
+	AppendBlock((const TSubBlock&)DebugFunctionalityBreakpoints,aDFBlock);
+	AppendBlock((const TSubBlock&)DebugFunctionalityStepping,aDFBlock);
+	AppendBlock((const TSubBlock&)DebugFunctionalityExecution,aDFBlock);
+	AppendBlock((const TSubBlock&)DebugFunctionalityEvents,aDFBlock);
+	AppendBlock((const TSubBlock&)DebugFunctionalityApiConstants,aDFBlock);
+	AppendBlock((const TSubBlock&)DebugFunctionalityList,aDFBlock);
+	AppendBlock((const TSubBlock&)DebugFunctionalityKillObjects,aDFBlock);
+	AppendBlock((const TSubBlock&)DebugFunctionalitySecurity,aDFBlock);
+
+	return ETrue;
+	}
+
+/**
+ * Get the register information associated with aRegisterInfo. If aRegisterInfo is
+ * an unsupported register then an entry of the form:
+ *   {aRegisterInfo, x, 0, EAccessUnknown}
+ *   will be returned where x is an arbitrary value.
+ *   
+ *   @param aRegisterInfo register id information
+ *   @param aTag The functionality information for this register.
+ *   @return One of the system wide error codes
+ */
+TInt TDebugFunctionality::GetRegister(const TRegisterInfo aRegisterInfo, TTag& aTag)
+	{
+	if(Register::IsCoreReg(aRegisterInfo))
+		{
+		for(TInt i=0; i<ERegisterLast; i++)
+			{
+			if(Register::GetCoreRegId(DebugFunctionalityRegistersCoreInfo[i].iTagId) == Register::GetCoreRegId(aRegisterInfo))
+				{
+				aTag = DebugFunctionalityRegistersCoreInfo[i];
+				return KErrNone;
+				}
+			}
+		}
+	else if(Register::IsCoproReg(aRegisterInfo))
+		{
+		//get aRegisterInfo's details
+		TUint32 crn = Register::GetCRn(aRegisterInfo);
+		TUint32 crm = Register::GetCRm(aRegisterInfo);
+		TUint32 opcode1 = Register::GetOpcode1(aRegisterInfo);
+		TUint32 opcode2 = Register::GetOpcode2(aRegisterInfo);
+		TUint32 coproNum = Register::GetCoproNum(aRegisterInfo);
+
+		for(TInt i=0; i<sizeof(DebugFunctionalityRegistersCoProInfo)/sizeof(TTag); i++)
+			{
+			TUint32 tagId = DebugFunctionalityRegistersCoProInfo[i].iTagId;
+
+			//if this entry is the DACR
+			if((Register::GetCRm(tagId) == 3) && (Register::GetCoproNum(tagId) == 15))
+				{
+				if((crm == 3) && (coproNum == 15))
+					{
+					aTag = DebugFunctionalityRegistersCoProInfo[i];
+					return KErrNone;
+					}
+				}
+			//each coprocessor register that is supported will need logic adding here
+			}
+		}
+	else // in the future there could be other types of register supported
+		{
+		//for now just fall through to unsupported case
+		}
+
+	//found an unsupported register so just return EAccessUnknown as the access level
+	aTag.iTagId = aRegisterInfo;
+	aTag.iSize = 0;
+	aTag.iValue = EAccessUnknown;
+
+	return KErrNotSupported;
+	}
+
+/**
+ * Returns the maximum memory block size which can be read or written.
+ * @return the maximum memory block size which can be read or written
+*/
+TUint32 TDebugFunctionality::GetMemoryOperationMaxBlockSize()
+	{
+	return DebugFunctionalityMemoryInfo[EMemoryMaxBlockSize].iValue;
+	}
+
+/**
+ * Helper function to append a DebugFunctionalityXXX SubBlock 
+ * into a TDes buffer
+ */
+void TDebugFunctionality::AppendBlock(const TSubBlock& aDFSubBlock, TDes8& aDFBlock)
+	{
+	// Copy the aSubDFBlock.header into aDFBlock (Note we don't put in a TSubBlock structure
+	// as the block is just that - a flat block so the pointer is not required)
+	TPtr8 SubDFBlockHdrPtr((TUint8*)&aDFSubBlock.iHeader,sizeof(TTagHeader),sizeof(TTagHeader));
+
+	aDFBlock.Append(SubDFBlockHdrPtr);
+
+	// Append all the Tags
+	for (TUint i=0; i<aDFSubBlock.iHeader.iNumTags; i++)
+		{
+		TPtr8 tmpPtr((TUint8*)&aDFSubBlock.iTagArray[i],sizeof(TTag),sizeof(TTag));
+
+		aDFBlock.Append(tmpPtr);
+		}
+	}
+
+/**
+ * Computes the size in bytes of aDFBlock
+ * @param aDFSubBlock
+ * @return TUint32 size of sub block
+ */
+TUint32 TDebugFunctionality::ComputeBlockSize(const TSubBlock& aDFSubBlock)
+	{
+	TUint32 size = 0;
+
+	// Header size
+	size += sizeof(TTagHeader);
+
+	// size of all the tags within the header:
+	size += aDFSubBlock.iHeader.iNumTags * sizeof(TTag); 
+
+	return size;
+	}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/debugsrv/runmodedebug/rmdriver/src/d_driver_event_info.cpp	Fri Aug 27 11:37:29 2010 +0300
@@ -0,0 +1,342 @@
+// Copyright (c) 2007-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+//
+
+#include "d_driver_event_info.h"
+#include "debug_logging.h"
+#include <kernel/kernel.h>
+#include <kernel/kern_priv.h>
+
+using namespace Debug;
+
+TDriverEventInfo::TDriverEventInfo()
+	{
+	Reset();
+	}
+
+void TDriverEventInfo::Reset()
+	{
+	iProcessId = 0;
+	iThreadId = 0;
+	iCurrentPC = 0;
+	iExceptionNumber = 0;
+	iFileName.Zero();
+	iPanicCategory.Zero();
+	iCodeAddress = 0;
+	iDataAddress = 0;
+	iThreadIdValid = (TUint8)EFalse;
+	iProcessIdValid = (TUint8)EFalse;
+	iEventType = EEventsUnknown;
+	iUidsValid = (TUint8)EFalse;
+	iActionTaken = EActionIgnore;
+	iThreadFlags = 0;
+	};
+
+/**
+  Copy the data from this object into the object pointed to by aEventInfo in
+  the client thread aClientThread. It is assumed that the write is performed
+  on behalf of aClientThread.
+
+  @param aClientThread client thread to write the data to
+  @param aEventInfo TEventInfo object in the client thread to populate with data
+  @param aAsyncGetValueRequest TClientDataRequest object used for pinning user memory
+
+  @return KErrNone on success, or one of the other system wide error codes
+  */
+TInt TDriverEventInfo::WriteEventToClientThread(TClientDataRequest<TEventInfo>* aAsyncGetValueRequest, DThread* aClientThread) const
+	{
+	// create a temporary TEventInfo to populate with the relevant data
+	TEventInfo eventInfo;
+	TInt err = KErrNone;	
+	
+	// populate the data that is common to all events
+	err = PopulateCommonEventInfo(eventInfo);
+
+	if(KErrNone != err)
+		{
+		return err;
+		}
+	
+	// populate the event specific data (means filling in the correct union member)
+	err = PopulateEventSpecificInfo(eventInfo);
+
+	// write the data to the client and return any error
+	if(KErrNone == err)
+		{
+		aAsyncGetValueRequest->Data() = eventInfo;
+		}
+	
+	return err;
+	}
+	
+/**
+  Write the common event values into aEventInfo
+
+  @param aEventInfo TEventInfo object to write data into
+  */
+TInt TDriverEventInfo::PopulateCommonEventInfo(TEventInfo& aEventInfo) const
+	{
+	aEventInfo.iEventType = iEventType;
+	aEventInfo.iProcessId = iProcessId;
+	aEventInfo.iProcessIdValid = iProcessIdValid;
+	aEventInfo.iThreadId = iThreadId;
+	aEventInfo.iThreadIdValid = iThreadIdValid;
+	aEventInfo.iActionTaken = iActionTaken;
+	LOG_MSG5("TDriverEventInfo:: PopulateCommon : eventType=%d, tidValid=%d, tid=0x%x, actionTaken=%d", 
+	        iEventType, iThreadIdValid, TUint(iThreadId), iActionTaken );
+	return KErrNone;
+	}
+
+/**
+  Write the event specific values into aEventInfo
+
+  @param aEventInfo TEventInfo object to write data into
+  */
+TInt TDriverEventInfo::PopulateEventSpecificInfo(TEventInfo& aEventInfo) const
+	{
+	TInt ret = KErrNone;
+	
+	switch(aEventInfo.iEventType)
+		{
+		case EEventsBreakPoint:
+			ret = PopulateThreadBreakPointInfo(aEventInfo);
+			return ret;
+		case EEventsProcessBreakPoint:
+			ret = PopulateThreadBreakPointInfo(aEventInfo);
+			return ret;
+		case EEventsSwExc:
+			ret = PopulateThreadSwExceptionInfo(aEventInfo);
+			return ret;
+		case EEventsHwExc:
+			ret = PopulateThreadHwExceptionInfo(aEventInfo);
+			return ret;
+		case EEventsKillThread:
+			ret = PopulateThreadKillInfo(aEventInfo);
+			return ret;
+		case EEventsAddLibrary:
+			ret = PopulateLibraryLoadedInfo(aEventInfo);
+			return ret;
+		case EEventsRemoveLibrary:
+			ret = PopulateLibraryUnloadedInfo(aEventInfo);
+			return ret;
+		case EEventsUserTrace:
+			ret = PopulateUserTraceInfo(aEventInfo);
+			return ret;
+		case EEventsStartThread:
+			ret = PopulateStartThreadInfo(aEventInfo);
+			return ret;
+		case EEventsUserTracesLost:
+			//no event specific data to be filled here
+			return KErrNone;
+		case EEventsAddProcess:
+			ret = PopulateAddProcessInfo(aEventInfo);
+			return ret;
+		case EEventsRemoveProcess:
+			ret = PopulateRemoveProcessInfo(aEventInfo);
+			return ret;
+		}
+	
+	return KErrArgument;
+	}
+
+/**
+  Write the event specific values for a break point event into TEventInfo
+
+  @param aEventInfo TEventInfo object to write data into
+  */
+TInt TDriverEventInfo::PopulateThreadBreakPointInfo(TEventInfo& aEventInfo) const
+	{
+	aEventInfo.iThreadBreakPointInfo.iExceptionNumber = (TExcType)iExceptionNumber;
+	TInt ret = PopulateRmdArmExcInfo(aEventInfo);
+	
+	return ret;
+	}
+
+/**
+  Write the event specific values for a thread exception event into TEventInfo
+
+  @param aEventInfo TEventInfo object to write data into
+  */
+TInt TDriverEventInfo::PopulateThreadSwExceptionInfo(TEventInfo& aEventInfo) const
+	{
+	aEventInfo.iThreadSwExceptionInfo.iCurrentPC = iCurrentPC;
+	aEventInfo.iThreadSwExceptionInfo.iExceptionNumber = (TExcType)iExceptionNumber;
+	
+	return KErrNone;
+	}
+
+/**
+  Write the event specific values for a thread exception event into TEventInfo
+
+  @param aEventInfo TEventInfo object to write data into
+  */
+TInt TDriverEventInfo::PopulateThreadHwExceptionInfo(TEventInfo& aEventInfo) const
+	{
+	aEventInfo.iThreadHwExceptionInfo.iExceptionNumber = (TExcType)iExceptionNumber;
+	TInt ret = PopulateRmdArmExcInfo(aEventInfo);
+	return ret;
+	}
+
+/**
+  Write the event specific values for a thread panic event into TEventInfo
+
+  @param aEventInfo TEventInfo object to write data into
+  */
+TInt TDriverEventInfo::PopulateThreadKillInfo(TEventInfo& aEventInfo) const
+	{
+	aEventInfo.iThreadKillInfo.iCurrentPC = iCurrentPC;
+	aEventInfo.iThreadKillInfo.iExitReason = iExceptionNumber;
+	aEventInfo.iThreadKillInfo.iExitType = iExitType;
+	aEventInfo.iThreadKillInfo.iPanicCategoryLength = iPanicCategory.Length();
+	TPtr8 panicCategoryPtr(&(aEventInfo.iThreadKillInfo.iPanicCategory[0]), iPanicCategory.Length());
+	panicCategoryPtr = iPanicCategory;
+	
+	return KErrNone;
+	}
+
+/**
+  Write the event specific values for a library loaded event into TEventInfo
+
+  @param aEventInfo TEventInfo object to write data into
+  */
+TInt TDriverEventInfo::PopulateStartThreadInfo(TEventInfo& aEventInfo) const
+	{
+	aEventInfo.iStartThreadInfo.iFileNameLength = iFileName.Length();
+	TPtr8 fileNamePtr(&(aEventInfo.iStartThreadInfo.iFileName[0]), iFileName.Length());
+	fileNamePtr = iFileName;
+	
+	return KErrNone;
+	}
+
+/**
+  Write the event specific values for an AddProcess event into TEventInfo
+
+  @param aEventInfo TEventInfo object to write data into
+  */
+TInt TDriverEventInfo::PopulateAddProcessInfo(TEventInfo& aEventInfo) const
+	{
+	aEventInfo.iAddProcessInfo.iFileNameLength = iFileName.Length();
+	TPtr8 fileNamePtr(&(aEventInfo.iAddProcessInfo.iFileName[0]), iFileName.Length());
+	fileNamePtr = iFileName;
+
+	const TInt uid3offset = 2;
+	aEventInfo.iAddProcessInfo.iUid3 = iUids.iUid[uid3offset].iUid;
+	aEventInfo.iAddProcessInfo.iCreatorThreadId = iCreatorThreadId;
+
+	return KErrNone;
+	}
+
+/**
+  Write the event specific values for a RemoveProcess event into TEventInfo
+
+  @param aEventInfo TEventInfo object to write data into
+  */
+TInt TDriverEventInfo::PopulateRemoveProcessInfo(TEventInfo& aEventInfo) const
+	{
+	aEventInfo.iRemoveProcessInfo.iFileNameLength = iFileName.Length();
+	TPtr8 fileNamePtr(&(aEventInfo.iRemoveProcessInfo.iFileName[0]), iFileName.Length());
+	fileNamePtr = iFileName;
+	
+	return KErrNone;
+	}
+
+/**
+  Write the event specific values for a library loaded event into TEventInfo
+
+  @param aEventInfo TEventInfo object to write data into
+  */
+TInt TDriverEventInfo::PopulateLibraryLoadedInfo(TEventInfo& aEventInfo) const
+	{
+	aEventInfo.iLibraryLoadedInfo.iCodeAddress = iCodeAddress;
+	aEventInfo.iLibraryLoadedInfo.iDataAddress = iDataAddress;
+	aEventInfo.iLibraryLoadedInfo.iFileNameLength = iFileName.Length();
+	TPtr8 fileNamePtr(&(aEventInfo.iLibraryLoadedInfo.iFileName[0]), iFileName.Length());
+	fileNamePtr = iFileName;
+	
+	return KErrNone;
+	}
+
+/**
+  Write the event specific values for a library unloaded event into TEventInfo
+
+  @param aEventInfo TEventInfo object to write data into
+  */
+TInt TDriverEventInfo::PopulateLibraryUnloadedInfo(TEventInfo& aEventInfo) const
+	{
+	aEventInfo.iLibraryUnloadedInfo.iFileNameLength = iFileName.Length();
+	TPtr8 fileNamePtr(&(aEventInfo.iLibraryUnloadedInfo.iFileName[0]), iFileName.Length());
+	fileNamePtr = iFileName;
+	
+	return KErrNone;
+	}
+
+/**
+  Write the ArmExcInfo values into TEventInfo
+
+  @param aEventInfo TEventInfo object to write data into
+  */
+TInt TDriverEventInfo::PopulateRmdArmExcInfo(TEventInfo& aEventInfo) const
+	{
+	switch(iEventType)
+		{
+		case EEventsProcessBreakPoint:
+		case EEventsBreakPoint:
+			aEventInfo.iThreadBreakPointInfo.iRmdArmExcInfo = iRmdArmExcInfo;
+			break;
+		case EEventsHwExc:
+			aEventInfo.iThreadHwExceptionInfo.iRmdArmExcInfo = iRmdArmExcInfo;
+			break;
+		}
+	
+	return KErrNone;
+	}
+
+/**
+ * Writes the user trace into TEventInfo
+ * 
+ * @param aEventInfo TEventInfo object to write data into
+ */
+TInt TDriverEventInfo::PopulateUserTraceInfo(TEventInfo& aEventInfo) const
+	{	
+	aEventInfo.iUserTraceInfo.iUserTraceLength = (TInt)iArg2;
+	
+	TPtr8 ptr(aEventInfo.iUserTraceInfo.iUserTraceText, (TInt)iArg2, TUserTraceSize );
+	ptr.Copy(iUserTraceText, (TInt)iArg2);
+		
+	return KErrNone;
+	}
+
+TBool TDriverEventInfo::FreezeOnSuspend() const
+	{
+	switch(iEventType)
+		{
+		case EEventsHwExc:
+		case EEventsBreakPoint:
+		case EEventsProcessBreakPoint:
+			return ETrue;
+		case EEventsKillThread:
+			{
+			return (iExitType == EExitPanic);
+			}
+		}
+	return EFalse;
+	}
+
+TBool TDriverEventInfo::TookException() const
+	{
+	return iExitType == EExitPanic &&
+		iExceptionNumber == ECausedException &&
+		iPanicCategory == KLitKernExec;
+	}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/debugsrv/runmodedebug/rmdriver/src/d_list_manager.cpp	Fri Aug 27 11:37:29 2010 +0300
@@ -0,0 +1,996 @@
+// Copyright (c) 2007-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+// Provides a class to manage the generation of lists
+// 
+//
+
+#include "d_list_manager.h"
+#include "d_process_tracker.h"
+#include "debug_utils.h"
+#include "plat_priv.h"
+#include "debug_logging.h"
+#include <arm.h>
+
+// make accessing DThread's MState more intuitive
+#define iMState iWaitLink.iSpare1
+// make accessing NThread's NState more intuitive
+#define iNState iSpare3
+
+//constants to match against a rom entry's attributes,
+//these are defined in the file server (can't be included kernel side)
+//and in the ROM tools (also inaccessible) so redefined here
+const TUint KEntryAttXIP=0x0080;
+const TUint KEntryAttDir=0x0010;
+
+using namespace Debug;
+
+/**
+  Get thread listing for the specified thread, if the thread data will not fit
+  in the buffer then an error is returned.
+
+  @param aBuffer buffer to put data in
+  @param aDataSize on return will contain size of data
+  @param aTargetThreadId thread ID to return listing for
+
+  @return KErrNone on success,
+  KErrTooBig if data won't fit in aBuffer
+  or one of the other system wide error codes on failure
+  */
+TInt TListManager::GetThreadListForThread(TDes8& aBuffer, TUint32& aDataSize, const TUint64 aTargetThreadId) const
+	{
+	LOG_MSG("TListManager::GetThreadListForThread()");
+
+	// open a handle to check whether the thread actually exists
+	NKern::ThreadEnterCS();
+	DThread* thread = DebugUtils::OpenThreadHandle(aTargetThreadId);
+	TUint64 processId = 0;
+	if (thread)
+		{
+		processId = thread->iOwningProcess->iId;
+		thread->Close(NULL);
+		}
+	NKern::ThreadLeaveCS();
+	if (!thread)
+		{
+		return KErrArgument;
+		}
+
+	//request a process specific list
+	return GetThreadListForProcess(aBuffer, aDataSize, processId);
+	}
+
+TInt TListManager::GetThreadListForProcess(TDes8& aBuffer, TUint32& aDataSize, const TUint64 aTargetProcessId) const
+	{
+	LOG_MSG("TListManager::GetThreadListForProcess()");
+
+	// open a handle to check whether the process actually exists
+	DProcess* process = DebugUtils::OpenProcessHandle(aTargetProcessId);
+	if(!process)
+		{
+		return KErrArgument;
+		}
+	process->Close(NULL);
+
+	//request a process specific list
+	return GetThreadList(aBuffer, aDataSize, EFalse, aTargetProcessId);
+	}
+
+/**
+  Get global thread listing
+
+  @param aBuffer buffer to put data in
+  @param aDataSize on return will contain size of data
+
+  @return KErrNone on success,
+  KErrTooBig if data won't fit in aBuffer
+  or one of the other system wide error codes on failure
+  */
+TInt TListManager::GetGlobalThreadList(TDes8& aBuffer, TUint32& aDataSize) const
+	{
+	LOG_MSG("TListManager::GetGlobalThreadList()");
+
+	//request a global list
+	return GetThreadList(aBuffer, aDataSize, ETrue, 0);
+	}
+
+/**
+  Get thread listing, if the thread data will not fit
+  in the buffer then an error is returned.
+
+  @param aBuffer buffer to put data in
+  @param aDataSize on return will contain size of data
+  @param aGlobal whether or not the listing should be global or thread specific
+  @param aTargetProcessId process ID to return listing for, relevant only if aGlobal == ETrue
+
+  @return KErrNone on success,
+  KErrTooBig if data won't fit in aBuffer
+  or one of the other system wide error codes on failure
+  */
+TInt TListManager::GetThreadList(TDes8& aBuffer, TUint32& aDataSize, TBool aGlobal, const TUint64 aTargetProcessId) const
+	{
+	LOG_MSG("TListManager::GetThreadList\n");
+
+	NKern::ThreadEnterCS();
+	DObjectCon *threads = Kern::Containers()[EThread];
+	threads->Wait();
+
+	aDataSize = 0;
+	aBuffer.SetLength(0);
+	//iterate through the threads adding them to the buffer
+	for(TInt i=0; i<threads->Count(); i++)
+		{
+		DThread* thread = (DThread*)(*threads)[i];
+
+		//skip this thread pointer is the thread is NULL
+		if(thread)
+			{
+			NThread& nThread = thread->iNThread;
+
+			// if the thread is marked as being dead then don't return information about it in the listing
+#ifndef __SMP__
+			if((NThread::EDead != nThread.iNState) && (DThread::EDead != thread->iMState))
+#else
+ 			if((!nThread.IsDead()) && (DThread::EDead != thread->iMState))
+#endif
+				{
+				if( aGlobal || (aTargetProcessId == (TUint64)thread->iOwningProcess->iId))
+					{
+					//store the data in the buffer
+					AppendThreadData(aBuffer, aDataSize, thread);
+					}
+				}
+			}
+		}
+
+	//leave critical section
+	threads->Signal();
+	NKern::ThreadLeaveCS();
+
+	//return indication of whether the kernel's data was too big
+	return (aDataSize > aBuffer.Length()) ? KErrTooBig : KErrNone;
+	}
+
+/**
+  Helper function for writing thread data into a buffer
+
+  @pre call in a critical section
+  @pre call only on threads which have NThread state not equal to NThread::EDead
+
+  @param aBuffer buffer to put data in
+  @param aDataSize on return will contain size of data
+  @param aThread thread object to include information about
+
+  @return KErrNone on success, or one of the other system wide error codes
+*/
+void TListManager::AppendThreadData(TDes8& aBuffer, TUint32& aDataSize, DThread* aThread) const
+	{
+	LOG_MSG3("TListManager::AppendThreadData for thrd 0x%08x, currThrd=0x%08x", 
+			aThread->iId, Kern::CurrentThread().iId );
+	
+	//get aThread's name
+	TFileName fileName;
+	aThread->FullName(fileName);
+	TUint16 nameLength = fileName.Length();
+
+	//increase aDataSize by the size of this entry
+	aDataSize = Align4(aDataSize + (2*nameLength) + sizeof(TThreadListEntry) - sizeof(TUint16));
+	//if the data would not cause overflow then add it to the buffer
+	if(aDataSize <= aBuffer.MaxLength())
+		{
+		//Create a TThreadListEntry which references the buffer.
+		TThreadListEntry& entry = *(TThreadListEntry*)(aBuffer.Ptr()+aBuffer.Length());
+		//add data to entry
+		entry.iProcessId = (TUint64)aThread->iOwningProcess->iId;
+		entry.iThreadId = (TUint64)aThread->iId;
+		entry.iSupervisorStackBase = (TUint32)aThread->iSupervisorStack;
+		entry.iSupervisorStackBaseValid = ETrue;
+		entry.iSupervisorStackSize = aThread->iSupervisorStackSize;
+		entry.iSupervisorStackSizeValid = ETrue;
+		entry.iNameLength = nameLength;
+
+		entry.iSupervisorStackPtrValid = EInValid;
+		entry.iSupervisorStackPtr = 0;
+		
+		if(aThread->iId != Kern::CurrentThread().iId)
+			{
+			NThread& nThread = aThread->iNThread;
+
+			TArmRegSet regSet;
+			TUint32 flags;
+			NKern::ThreadGetSystemContext(&nThread, &regSet, flags);
+			entry.iSupervisorStackPtr = (TUint32)regSet.iR13;
+			//need to check that the stack pointer flag is valid
+			if(flags & (1<<EArmSp))
+				{
+				entry.iSupervisorStackPtrValid = EValid;
+				}
+			}
+
+		//copy name data into the buffer
+		TUint16* ptr = &(entry.iName[0]);
+		const TUint8* ptr8 = fileName.Ptr();
+		const TUint8* ptr8End = ptr8 + nameLength;
+		while(ptr8 < ptr8End)
+			{
+			*ptr++ = (TUint16)*ptr8++;
+			}
+ 
+		aBuffer.SetLength(aDataSize);
+		}
+	}
+
+/**
+  Get global process listing
+
+  @param aBuffer buffer to put data in
+  @param aDataSize on return will contain size of data
+
+  @return KErrNone on success,
+  KErrTooBig if data won't fit in aBuffer
+  or one of the other system wide error codes on failure
+  */
+TInt TListManager::GetProcessList(TDes8& aBuffer, TUint32& aDataSize) const
+	{
+	LOG_MSG("TListManager::GetProcessList()");
+
+	//get a pointer to the kernel's process list
+	DObjectCon* processes = Kern::Containers()[EProcess];
+
+	if(processes == NULL)
+		{
+		//if can't get container then something is seriously wrong
+		return KErrNotFound;
+		}
+
+	//have to read the processes in a critical section
+	NKern::ThreadEnterCS();
+	processes->Wait();
+
+	aDataSize = 0;
+	//iterate through the processes adding them to the buffer
+	for(TInt i=0; i<processes->Count(); i++)
+		{
+		DProcess* process = (DProcess*)(*processes)[i];
+		if(process)
+			{
+			//get process's file name length
+			DCodeSeg* codeSeg = process->iCodeSeg;
+			TUint16 fileNameLength = (codeSeg) ? (*codeSeg->iFileName).Length() : 0;
+
+			//get process's dynamic name length and name
+			TFullName fullName;
+			process->FullName(fullName);
+			TUint16 dynamicNameLength = fullName.Length();
+
+			//increase aDataSize to reflect size of entry
+			aDataSize = Align4(aDataSize + (2*fileNameLength) + (2*dynamicNameLength) + sizeof(TProcessListEntry) - sizeof(TUint16));
+			//if the data would not cause overflow then add it to the buffer
+			if(aDataSize <= aBuffer.MaxLength())
+				{
+				//Create a TProcessListEntry which references the buffer.
+				TProcessListEntry& entry = *(TProcessListEntry*)(aBuffer.Ptr() + aBuffer.Length());
+
+				//set values
+				entry.iProcessId = (TUint64)process->iId;
+				entry.iFileNameLength = fileNameLength;
+				entry.iDynamicNameLength = dynamicNameLength;
+				entry.iUid3 = process->iUids.iUid[2].iUid;
+
+				if(codeSeg)
+					{
+					//create TPtr to where the file name should be written
+					TPtr name = TPtr((TUint8*)&(entry.iNames[0]), fileNameLength*2, fileNameLength*2);
+					//copy the file name
+					TInt err = CopyAndExpandDes(*codeSeg->iFileName, name);
+					if(err != KErrNone)
+						{
+						processes->Signal();
+						NKern::ThreadLeaveCS();
+						return KErrGeneral;
+						}
+					}
+
+				//create TPtr to where the dynamic name should be written
+				TPtr name = TPtr((TUint8*)(&(entry.iNames[0]) + fileNameLength), dynamicNameLength*2, dynamicNameLength*2);
+				//copy the dynamic name
+				TInt err = CopyAndExpandDes(fullName, name);
+				if(err != KErrNone)
+					{
+					processes->Signal();
+					NKern::ThreadLeaveCS();
+					return KErrGeneral;
+					}
+
+				//set length same as aDataSize
+				aBuffer.SetLength(aDataSize);
+				}
+			}
+		}
+
+	//leave critical section
+	processes->Signal();
+	NKern::ThreadLeaveCS();
+
+	//return indication of whether the kernel's data was too big
+	return (aDataSize > aBuffer.Length()) ? KErrTooBig : KErrNone;
+	}
+
+/**
+  Copy the descriptor aSrc to aDest and converting each byte from aSrc
+  into the two-byte equivalent. For example if aSrc contains 'XYZ' then
+  aDest will be filled with 'X\0Y\0Z\0' where \0 is the null character.
+  The length of aDest is set to twice the length of aSrc.
+
+  @param aSrc source descriptor
+  @param aDest destination descriptor to copy and expand aSrc into
+
+  @return KErrNone on success,
+  KErrArgument if the max length of aDest is less than twice the length of aSrc
+  */
+TInt TListManager::CopyAndExpandDes(const TDesC& aSrc, TDes& aDest) const
+	{
+	//check bounds
+	if(aSrc.Length() * 2 > aDest.MaxLength())
+		{
+		return KErrArgument;
+		}
+
+	//get a pointer to the start of the destination descriptor
+	TUint16* destPtr = (TUint16*)aDest.Ptr();
+
+	//get pointers to the start and end of the aSrc descriptor
+	const TUint8* srcPtr = aSrc.Ptr();
+	const TUint8* srcEnd = srcPtr + aSrc.Length();
+
+	//copy the characters from aSrc into aDest, expanding to make them 16-bit characters
+	while(srcPtr < srcEnd)
+		{
+		*destPtr = (TUint16)*srcPtr;
+		destPtr++;
+		srcPtr++;
+		}
+
+	//set aDest's length to reflect the new contents
+	aDest.SetLength(2*aSrc.Length());
+	return KErrNone;
+	}
+
+/**
+  Get global code segment listing
+
+  @param aBuffer buffer to put data in
+  @param aDataSize on return will contain size of data
+
+  @return KErrNone on success,
+  KErrTooBig if data won't fit in aBuffer,
+  or one of the other system wide error codes
+  */
+TInt TListManager::GetGlobalCodeSegList(TDes8& aBuffer, TUint32& aDataSize) const
+	{
+	LOG_MSG("TListManager::GetGlobalCodeSegList()");
+
+	// Acquire code seg lock mutex
+	NKern::ThreadEnterCS();
+	DMutex* codeMutex = Kern::CodeSegLock();
+	Kern::MutexWait(*codeMutex);
+
+	//get global code seg list
+	SDblQue* codeSegList = Kern::CodeSegList();
+
+	//create a memory info object for use in the loop
+	TModuleMemoryInfo memoryInfo;
+
+	//iterate through the list
+	aDataSize = 0;
+	for (SDblQueLink* codeSegPtr= codeSegList->First(); codeSegPtr!=(SDblQueLink*) (codeSegList); codeSegPtr=codeSegPtr->iNext)
+		{
+		DEpocCodeSeg* codeSeg = (DEpocCodeSeg*)_LOFF(codeSegPtr,DCodeSeg, iLink);
+		//the code seg shouldn't be null as we're in critical section, ignore if it is null
+		if(codeSeg)
+			{
+			//get the memory info
+			TInt err = codeSeg->GetMemoryInfo(memoryInfo, NULL);
+			if(err != KErrNone)
+				{
+				// Release the codeseglock mutex again
+				Kern::MutexSignal(*codeMutex);
+				NKern::ThreadLeaveCS();
+
+				//there's been an error so return it
+				return err;
+				}
+			//calculate data values
+			TFileName fileName(codeSeg->iFileName->Ptr());
+			TBool isXip = (TBool)(codeSeg->iXIP);
+
+			//get the code seg type, can ignore error as have already checked codeSeg is not NULL
+			TCodeSegType type = EUnknownCodeSegType;
+			err = GetCodeSegType(codeSeg, type);
+			if(err != KErrNone)
+				{
+				LOG_MSG("TListManager::GetGlobalCodeSegList() : code seg is NULL");
+				}
+
+			TUint32 uid3 = codeSeg->iUids.iUid[2].iUid;
+			//append data to buffer
+			err = AppendCodeSegData(aBuffer, aDataSize, memoryInfo, isXip, type, fileName, uid3);
+			if(err != KErrNone)
+				{
+				// Release the codeseglock mutex again
+				Kern::MutexSignal(*codeMutex);
+				NKern::ThreadLeaveCS();
+
+				return KErrGeneral;
+				}
+			}
+		}
+
+	// Release the codeseglock mutex again
+	Kern::MutexSignal(*codeMutex);
+	NKern::ThreadLeaveCS();
+
+	return (aDataSize > aBuffer.MaxLength()) ? KErrTooBig : KErrNone;
+	}
+
+/**
+  Get code segment list for a thread
+
+  @param aBuffer buffer to store data in
+  @param aDataSize size of kernel's data
+  @param thread ID to get listing for
+
+  @return KErrNone on success,
+  KErrTooBig if data won't fit in aBuffer,
+  or one of the other system wide error codes
+  */
+TInt TListManager::GetCodeSegListForThread(TDes8& aBuffer, TUint32& aDataSize, const TUint64 aTargetThreadId) const
+	{
+	LOG_MSG("TListManager::GetCodeSegListForThread()");
+
+	TUint64 processId = 0;
+	NKern::ThreadEnterCS();
+	DThread* thread = DebugUtils::OpenThreadHandle(aTargetThreadId);
+	if (thread)
+		{
+		processId = thread->iOwningProcess->iId;
+		thread->Close(NULL);
+		}
+	NKern::ThreadLeaveCS();
+
+	if (processId == 0)
+		{
+		return KErrArgument;
+		}
+
+	return GetCodeSegListForProcess(aBuffer, aDataSize, processId);
+	}
+
+/**
+  Get code segment list for a process
+
+  @param aBuffer buffer to store data in
+  @param aDataSize size of kernel's data
+  @param process ID to get listing for
+
+  @return KErrNone on success,
+  KErrTooBig if data won't fit in aBuffer,
+  or one of the other system wide error codes
+  */
+TInt TListManager::GetCodeSegListForProcess(TDes8& aBuffer, TUint32& aDataSize, const TUint64 aTargetProcessId) const
+	{
+	LOG_MSG("TListManager::GetCodeSegListForProcess()");
+
+	NKern::ThreadEnterCS();
+
+	//get the process
+	DProcess* process = DebugUtils::OpenProcessHandle(aTargetProcessId);
+
+	if(!process)
+		{
+		NKern::ThreadLeaveCS();
+		return KErrArgument;
+		}
+
+	// acquire code segment mutex
+	Kern::AccessCode();
+
+	//memory info object to use in loop
+	TModuleMemoryInfo memoryInfo;
+
+	//get code seg list
+	SDblQue queue;
+	process->TraverseCodeSegs(&queue, NULL, DCodeSeg::EMarkDebug, DProcess::ETraverseFlagAdd);
+
+	//iterate through the list
+	aDataSize = 0;
+	TInt err = KErrNone;
+	for(SDblQueLink* codeSegPtr= queue.First(); codeSegPtr!=(SDblQueLink*) (&queue); codeSegPtr=codeSegPtr->iNext)
+		{
+		//get the code seg
+		DEpocCodeSeg* codeSeg = (DEpocCodeSeg*)_LOFF(codeSegPtr,DCodeSeg, iTempLink);
+
+		//the code seg shouldn't be null as we're in critical section, ignore if it is null
+		if(codeSeg)
+			{
+			err = codeSeg->GetMemoryInfo(memoryInfo, NULL);
+			if (err) break;
+
+			TFileName fileName(codeSeg->iFileName->Ptr());
+			TBool isXip = (TBool)(codeSeg->iXIP);
+
+			//get the code seg type, can ignore error as have already checked codeSeg is not NULL
+			TCodeSegType type = EUnknownCodeSegType;
+			err = GetCodeSegType(codeSeg, type);
+			if(err != KErrNone)
+				{
+				LOG_MSG("TListManager::GetCodeSegListForProcess() : code seg is NULL");
+				}
+
+			TUint32 uid3 = codeSeg->iUids.iUid[2].iUid;
+			//append data to buffer
+			err = AppendCodeSegData(aBuffer, aDataSize, memoryInfo, isXip, type, fileName, uid3);
+			if (err) break;
+			}
+		}
+
+	//un mark the code segs that we've iterated over
+	DCodeSeg::EmptyQueue(queue, DCodeSeg::EMarkDebug);
+
+	//release mutex
+	Kern::EndAccessCode();
+
+	process->Close(NULL);
+	NKern::ThreadLeaveCS();
+	return (aDataSize > aBuffer.MaxLength()) ? KErrTooBig : err;
+	}
+
+/**
+  Appends data to a specified buffer and puts the resulting size in aDataSize.
+  If the data won't fit then aDataSize is updated to reflect what the new length
+  would be.
+
+  @param aBuffer buffer to append data to
+  @param aDataSize will contain buffer size (or the size the buffer would be) on return
+  @param aMemoryInfo info to append to buffer
+  @param aIsXip boolean indicating whether the code segment is XIP
+  @param aFileName file name to append to buffer
+
+  @return KErrNone on success, or one of the other system wide error codes
+  */
+TInt TListManager::AppendCodeSegData(TDes8& aBuffer, TUint32& aDataSize, const TModuleMemoryInfo& aMemoryInfo, const TBool aIsXip, const TCodeSegType aCodeSegType, const TDesC8& aFileName, const TUint32 aUid3) const
+	{
+	//get some data elements to put in buffer
+	TUint16 fileNameLength = aFileName.Length();
+
+	//calculate the resultant size
+	aDataSize = Align4(aDataSize + sizeof(TCodeSegListEntry) + (2*fileNameLength) - sizeof(TUint16));
+	if(aDataSize <= aBuffer.MaxLength())
+		{
+		//Create a TCodeSegListEntry which references the buffer.
+		TCodeSegListEntry& entry = *(TCodeSegListEntry*)(aBuffer.Ptr() + aBuffer.Length());
+		entry.iCodeBase = aMemoryInfo.iCodeBase;
+		entry.iCodeSize = aMemoryInfo.iCodeSize;
+		entry.iConstDataSize = aMemoryInfo.iConstDataSize;
+		entry.iInitialisedDataBase = aMemoryInfo.iInitialisedDataBase;
+		entry.iInitialisedDataSize = aMemoryInfo.iInitialisedDataSize;
+		entry.iUninitialisedDataSize = aMemoryInfo.iUninitialisedDataSize;
+		entry.iIsXip = aIsXip;
+		entry.iCodeSegType = aCodeSegType;
+		entry.iNameLength = fileNameLength;
+		entry.iUid3 = aUid3;
+
+		//have to convert the stored name to 16 bit unicode
+		TPtr name = TPtr((TUint8*)&(entry.iName[0]), fileNameLength*2, fileNameLength*2);
+		TInt err = CopyAndExpandDes(aFileName, name);
+		if(err != KErrNone)
+			{
+			return KErrGeneral;
+			}
+
+		//increase length
+		aBuffer.SetLength(aDataSize);
+		}
+
+	return KErrNone;
+	}
+
+/**
+  Get global XIP libraries list. The ROM file system is searched for files in
+  z:\sys\bin. The files are filtered to only include library files which
+  correspond to the correct hardware variant.
+
+  In the rom, a directory is represented as a list of TRomEntrys, corresponding to
+  the files and directories in that directory. A TRomEntry corresponding to a file
+  contains a pointer to that file's location in the rom. If the TRomEntry
+  corresponds to a directory then it contains a pointer to that directory in the
+  ROM header. As such, from a pointer to the root directory of the z: drive, it is
+  possible to extract the directory contents for a particular directory (i.e. z:\sys\bin)
+  by recursively finding the subdirectories (i.e. find 'sys' in 'z:', then 'bin' in 'sys')
+  and then listing the contents of that directory.
+
+  @param aBuffer buffer to store data in
+  @param aDataSize size of kernel's data
+
+  @return KErrNone on success,
+  KErrTooBig if data won't fit in aBuffer,
+  or one of the other system wide error codes
+  */
+TInt TListManager::GetXipLibrariesList(TDes8& aBuffer, TUint32& aDataSize) const
+	{
+	LOG_MSG("TListManager::GetXipLibrariesList()");
+
+	// z:\sys\bin expressed as 16 bit unicode..
+	_LIT(KZSysBin, "z\0:\0\\\0s\0y\0s\0\\\0b\0i\0n\0\\\0");
+
+	//array to store pointers to directory entries in
+	RPointerArray<TRomEntry> entries;
+	//get the entries in KZSysBin
+	TInt err = GetDirectoryEntries(entries, KZSysBin());
+	if(KErrNone != err)
+		{
+		entries.Close();
+		return err;
+		}
+
+	aDataSize = 0;
+	for(TInt i=0; i<entries.Count(); i++)
+		{
+		//if the entry is XIP and it's not a directory then it's a candidate to add
+		if( (entries[i]->iAtt & KEntryAttXIP) && ! (entries[i]->iAtt & KEntryAttDir) )
+			{
+			//get a reference to the dll's header
+			const TRomImageHeader& header = *(const TRomImageHeader*)(entries[i]->iAddressLin);
+
+			//check that it's uid1 value corresponds to that for a library
+			if(header.iUid1 == KDynamicLibraryUidValue)
+				{
+				//get the current hardware variant
+				TSuperPage& superPage = Kern::SuperPage();
+				TUint variant = superPage.iActiveVariant;
+				TUint cpu = (variant >> 16) & 0xff;
+				TUint asic = (variant >> 24);
+
+				//check this dll is compatible with the current variant
+				if(THardwareVariant(header.iHardwareVariant).IsCompatibleWith(cpu,asic,variant))
+					{
+					const TInt fileNameLength16 = entries[i]->iNameLength;
+					const TInt fullNameLength16 = (KZSysBin().Length() / 2) + fileNameLength16;
+					aDataSize += Align4((2 * fullNameLength16) + sizeof(TXipLibraryListEntry) - sizeof(TUint16));
+
+					if(aDataSize <= aBuffer.MaxLength())
+						{
+						//Create a TXipLibraryListEntry which references the buffer.
+						TXipLibraryListEntry& libraryInfo = *(TXipLibraryListEntry*)(aBuffer.Ptr() + aBuffer.Length());
+
+						//add the data
+						libraryInfo.iCodeBase = header.iCodeAddress;
+						libraryInfo.iCodeSize = header.iTextSize;
+						libraryInfo.iConstDataSize = header.iCodeSize - header.iTextSize;
+						libraryInfo.iInitialisedDataBase = header.iDataBssLinearBase;
+						libraryInfo.iInitialisedDataSize = header.iDataSize;
+						libraryInfo.iUninitialisedDataSize = header.iBssSize;
+						libraryInfo.iNameLength = fullNameLength16;
+
+						//create a TPtr8 to contain the fully qualified name (i.e. z:\sys\bin\ prefixed)
+						TPtr8 name((TUint8*)&(libraryInfo.iName[0]), 0, 2 * fullNameLength16);
+						name.Append(KZSysBin());
+						name.Append(TPtr8((TUint8*)&(entries[i]->iName), 2 * fileNameLength16, 2 * fileNameLength16));
+
+						//increase the buffer's length to reflect the new data size
+						aBuffer.SetLength(aDataSize);
+						}
+					}
+				}
+			}
+		}
+	entries.Close();
+	return (aDataSize == aBuffer.Length()) ? KErrNone : KErrTooBig;
+	}
+
+/**
+Get the list of TRomEntry objects in the specified directory aDirectory
+
+@param aRomEntryArray array to store pointers to the TRomEntry objects in
+@param aDirectoryName directory to get contents of. The passed in string should be
+16 bit unicode and should begin with z:. Single backslashes should be used as delimiters
+rather than forward slashes and a terminating backslash is optional.
+For example: z:\sys\bin
+
+@return KErrNone on success, or one of the other system wide error codes
+*/
+TInt TListManager::GetDirectoryEntries(RPointerArray<TRomEntry>& aRomEntryArray, const TDesC& aDirectoryName) const
+	{
+	LOG_MSG("TListManager::GetDirectoryEntries()");
+
+	//definition in 16 bit unicode
+	_LIT(KForwardSlash, "/\0");
+
+	//if directory has forward slashes then exit
+	if(aDirectoryName.Find(KForwardSlash()) != KErrNotFound)
+		{
+		return KErrArgument;
+		}
+
+	//create an array to hold the folders in aDirectoryName
+	RArray<TPtr8> folders;
+
+	//split the directory up into its folders, i.e. z:\sys\bin is split into { 'z:', 'sys', 'bin' }
+	TInt err = SplitDirectoryName(aDirectoryName, folders);
+	if(KErrNone != err)
+		{
+		folders.Close();
+		return err;
+		}
+
+	if(folders.Count() == 0)
+		{
+		folders.Close();
+		//empty string passed in
+		return KErrArgument;
+		}
+
+	// z: as 16 bit unicode
+	_LIT(KZColon, "z\0:\0");
+	if(folders[0].CompareF(KZColon()) != 0)
+		{
+		//first argument must be z: otherwise not in rom
+		folders.Close();
+		return KErrArgument;
+		}
+	//remove z: from array
+	folders.Remove(0);
+	for(TInt i=0; i<folders.Count(); i++)
+		{
+		if(folders[i].Length() == 0)
+			{
+			// there were two backslashes in a row
+			folders.Close();
+			return KErrArgument;
+			}
+		}
+
+	//get a pointer to the start of the rom root directory list
+	TLinAddr romRootDirectoryList = Epoc::RomHeader().iRomRootDirectoryList;
+
+	//the first 4 bytes of the rom root directory list is a count of how many sections (rom roots) there are
+	TUint32 rootDirectoryCount = (TUint32)*(TLinAddr*)romRootDirectoryList;
+
+	//rootDirectoryPointer will be shifted through the rom root directory list and will contain pointers to the sections in the rom
+	TLinAddr rootDirectoryPointer = romRootDirectoryList;
+	for(TInt i=0; i<rootDirectoryCount; i++)
+		{
+		//the address of the section is stored in the second four bytes of the 8 byte pair reserved for each section
+		rootDirectoryPointer += 8;
+
+		//romRoot contains the address of the root of the section
+		TLinAddr romRoot = *(TLinAddr*)rootDirectoryPointer;
+
+		//append the directory entries from romRoot's z:\sys\bin subdirectory
+		TInt err = GetDirectoryEntries(aRomEntryArray, folders, romRoot);
+		if(KErrNone != err)
+			{
+			folders.Close();
+			return err;
+			}
+		}
+	folders.Close();
+	return KErrNone;
+	}
+
+/**
+  Recursively finds the subdirectories in aArray and stores references to the
+  entries in the most derived subdirectory in aRomEntryArray
+
+  @param aRomEntryArray on return will contain the entries in the directory corresponding to aArray
+  @param aArray an array containing the directory to get the entries for, i.e. { 'sys', 'bin' }
+  @param aAddress address in rom to being searching from
+
+  @param KErrNone on success, or one of the other system wide error codes
+*/
+TInt TListManager::GetDirectoryEntries(RPointerArray<TRomEntry>& aRomEntryArray, RArray<TPtr8>& aArray, TLinAddr& aAddress) const
+	{
+	LOG_MSG2("TListManager::GetDirectoryEntries() aAddress: 0x%08x", aAddress);
+
+	//find the next subdirectory and store its address in aAddress, return error if we can't find it
+	TInt err = FindDirectory(aArray[0], aAddress);
+	if(err != KErrNone)
+		{
+		return err;
+		}
+
+	//if this is the most derived sub-directory (i.e. the bin of z:\sys\bin) then get the dir contents
+	if(aArray.Count() == 1)
+		{
+		return GetDirectoryContents(aRomEntryArray, aAddress);
+		}
+	else
+		{
+		//get the next subdirectory's contents
+		aArray.Remove(0);
+		return GetDirectoryEntries(aRomEntryArray, aArray, aAddress);
+		}
+	}
+
+/**
+Return the entries of a directory in the rom
+
+@param aRomEntryArray array to store the entries in
+@param aAddress address of a directory block in the rom
+*/
+TInt TListManager::GetDirectoryContents(RPointerArray<TRomEntry>& aRomEntryArray, const TLinAddr aAddress) const
+	{
+	LOG_MSG("TListManager::GetDirectoryContents()");
+
+	TLinAddr address = aAddress;
+
+	//get the size in bytes of the block of rom to iterate over
+	const TUint32 sizeInBytes = *(TUint32*)aAddress;
+
+	//get address of first TRomEntry
+	const TLinAddr initialAddress = aAddress + sizeof(TUint32);
+
+	//get pointer to subdir count
+	address = initialAddress + sizeInBytes;
+
+	//the upper two bytes of this entry contain the number of files in this directory, and the lower two bytes
+	//contains the number of subdirectories in this directory
+	TUint32 filesAndDirectories = *(TUint32*)address;
+
+	//get number of subdirectories in this directory
+	const TUint16 subDirCount = filesAndDirectories & 0xFFFF;
+
+	//get the number of files in this dir
+	const TUint16 filesCount = filesAndDirectories >> 16;
+
+	//get total number of entries in dir
+	const TUint numDirectoryEntries = subDirCount + filesCount;
+
+	//set address to start of first entry
+	address = initialAddress;
+
+	for(TInt i=0; i<numDirectoryEntries; i++)
+		{
+		TRomEntry* romEntry = (TRomEntry*)address;
+
+		//store the entry
+		TInt err = aRomEntryArray.Append(romEntry);
+		if(KErrNone != err)
+			{
+			return err;
+			}
+
+		//length of the name of the rom entry
+		TInt nameLength = romEntry->iNameLength;
+
+		//get the size of the entry including the name
+		TUint32 romEntrySize = sizeof(TRomEntry) - sizeof(romEntry->iName) + (2 * nameLength);
+		//adjust the address to the next entry
+		address += Align4(romEntrySize);
+		}
+	return KErrNone;
+	}
+
+/**
+  Finds the subdirectory with name aDirectory in the directory at aAddress
+
+  @param aDirectory name of subdirectory to search for (i.e. 'bin')
+  @param aAddress address in rom of containing directory (i.e. address of 'sys' directory)
+
+  @param KErrNone if aDirectory could be found in aAddress, KErrNotFound if it could not be found
+  */
+TInt TListManager::FindDirectory(const TDesC& aDirectory, TLinAddr& aAddress) const
+	{
+	LOG_MSG3("TListManager::FindDirectory() aDirectory: %S, aAddress: 0x%08x", &aDirectory, aAddress);
+
+	//get the directory's contents
+	RPointerArray<TRomEntry> dirContents;
+	TInt err = GetDirectoryContents(dirContents, aAddress);
+	if(KErrNone != err)
+		{
+		dirContents.Close();
+		return err;
+		}
+	for(TInt i=0; i<dirContents.Count(); i++)
+		{
+		//create a reference to the TRomEntry in the rom to access its attributes
+		TRomEntry& romEntry = *(dirContents[i]);
+		if(romEntry.iAtt & KEntryAttDir)
+			{
+			// this entry's a directory so check if it matches aDirectory
+			const TInt nameLength = romEntry.iNameLength;
+			TPtr8 name((TUint8*)&(romEntry.iName), nameLength * 2, nameLength * 2);
+			if(0 == aDirectory.CompareF(name))
+				{
+				// names matched so get the address of this directory's contents
+				aAddress = romEntry.iAddressLin;
+				dirContents.Close();
+				return KErrNone;
+				}
+			}
+		}
+	dirContents.Close();
+	//couldn't find it so return error
+	return KErrNotFound;
+	}
+
+/**
+  Helper function to get code seg type.
+
+  @param aCodeSeg code seg to get type of
+  @param aType will contain type on return
+
+  @return KErrNone on success, KErrNotFound if aCodeSeg is NULL
+  */
+TInt TListManager::GetCodeSegType(const DCodeSeg* aCodeSeg, TCodeSegType& aType) const
+	{
+	if(!aCodeSeg)
+		{
+		return KErrNotFound;
+		}
+
+	if(aCodeSeg->IsExe())
+		{
+		aType = EExeCodeSegType;
+		return KErrNone;
+		}
+
+	if(aCodeSeg->IsDll())
+		{
+		aType = EDllCodeSegType;
+		return KErrNone;
+		}
+
+	aType = EUnknownCodeSegType;
+	return KErrNone;
+	}
+
+
+/**
+  Split a directory name into its subdirectories, using a 16-bit backslash ('\\\0') as a delimiter.
+  For example z:\sys\bin would be split into { 'z:', 'sys', 'bin' }
+
+  @param aDirectoryName directory name to split into subdirectories
+  @param aSubDirectories array to store the subdirectories in
+  */
+TInt TListManager::SplitDirectoryName(const TDesC& aDirectoryName, RArray<TPtr8>& aSubDirectories) const
+	{
+	//definition in 16 bit unicode
+	_LIT(KBackSlash, "\\\0");
+
+	//split the directory up into its folders, i.e. z:\sys\bin is split into 
+	TPtr8 string((TUint8*)aDirectoryName.Ptr(), aDirectoryName.Length(), aDirectoryName.Length());
+	while(string.Ptr() < aDirectoryName.Ptr() + aDirectoryName.Length())
+		{
+		TInt offset = string.Find(KBackSlash());
+		if(offset == KErrNotFound)
+			{
+			//reached the end of the string
+			offset = string.Length();
+			}
+		//adjustedOffset takes account of the end of the string case
+		TInt adjustedOffset = (offset == string.Length()) ? offset : offset + KBackSlash().Length();
+		//add sub-folder name
+		TInt err = aSubDirectories.Append(TPtr8((TUint8*)string.Ptr(), offset, offset));
+		if(KErrNone != err)
+			{
+			return err;
+			}
+		//remove the sub-folder name and continue
+		string.Set((TUint8*)string.Ptr() + adjustedOffset, string.Length() - adjustedOffset, string.Length() - adjustedOffset);
+		}
+	return KErrNone;
+	}
+
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/debugsrv/runmodedebug/rmdriver/src/d_process_tracker.cpp	Fri Aug 27 11:37:29 2010 +0300
@@ -0,0 +1,664 @@
+// Copyright (c) 2006-2010 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+// Purpose: The DProcessTracker object tracks which processes are being
+// debugged. The DProcessTracker class uses a DTargetProcess object for
+// each process being debugged.
+// Note: Although TheDProcessTracker object is a global, it will be unique
+// as only the Debug Security Server can load and use rm_debug.ldd.
+// 
+//
+
+#include <e32def.h>
+#include <e32def_private.h>
+#include <e32cmn.h>
+#include <e32cmn_private.h>
+#include <kernel/kernel.h>
+#include <kernel/kern_priv.h>
+
+#include <rm_debug_api.h>
+#include "debug_logging.h"
+#include "d_process_tracker.h"
+#include "debug_utils.h"
+
+// Global Run-mode debugged process tracking object
+DProcessTracker TheDProcessTracker;
+
+// ctor
+DProcessTracker::DProcessTracker()
+	{
+	}
+
+/**
+ * dtor
+ * Go through forzen thread list and resume each one before clearing our structures
+ * @internalTechnology
+ */
+DProcessTracker::~DProcessTracker()
+	{
+
+	for(TInt i=0; i<iFrozenThreadSemaphores.Count(); i++)
+		{
+		LOG_MSG2("~DProcessTracker Resuming frozen NThread 0x%08x via FSSignal ", iFrozenThreadSemaphores[i]->iOwningThread );
+		NKern::FSSignal(iFrozenThreadSemaphores[i]);
+		}
+
+	NKern::ThreadEnterCS();
+	// The ResetAndDestroy() will call the individual deletes for all objects in the containers
+	iFrozenThreadSemaphores.ResetAndDestroy();
+	iProcesses.ResetAndDestroy();
+	iAgentsAttachedToAll.ResetAndDestroy();
+	NKern::ThreadLeaveCS();
+	}
+
+/**
+ * @internalTechnology
+ *
+ * Creates and stores an internal mapping of debug agent to debugged process.
+ * Note that an individual process may be mapped to a number of debug agents.
+ *
+ * @param aProcessName - The fullly qualified path of the debugged process. E.g. z:\sys\bin\hello_world.exe
+ * @param aAgentId - The process id of the debug agent which is attaching to aProcessName, as returned by RProcess.Id()
+ * @return KErrNone if there are no errors. KErrArgument if the processname is too long/short for a valid filepath.
+ *  KErrNoMemory if there is insufficient memory.
+ */
+TInt DProcessTracker::AttachProcess(const TDesC8& aProcessName,TUint64 aAgentId)
+	{
+	LOG_MSG3("DProcessTracker::AttachProcess name=%S agentId=0x%lx", 
+		&aProcessName, aAgentId);
+
+	// Valid ProcessName?
+	if (aProcessName.Length() < 1 || aProcessName.Length() >= KMaxPath)
+		{
+		return KErrArgument;
+		}
+
+	if (aProcessName == _L8("*"))
+		{
+		DDebugAgent* agent = FindAgentForProcessAndId( aProcessName, aAgentId );
+		if(agent != NULL)
+			{
+			LOG_MSG("Found agent already attached to all");
+			return KErrAlreadyExists;
+			}
+
+		agent = DDebugAgent::New(aAgentId);
+		if(agent == NULL)
+			{
+			LOG_MSG("DProcessTracker::AttachProcess() couldn't allocate memory for DDebugAgent");
+			return KErrNoMemory;
+			}
+		
+		return iAgentsAttachedToAll.Append(agent);
+
+		}
+
+	// Not attach all, but for a specific process/exe
+
+	// Create an DTargetProcess to store
+	DTargetProcess* tmpProcess = new DTargetProcess;
+	if (tmpProcess == 0)
+		{
+		return KErrNoMemory;
+		}
+	LOG_MSG2(" AttachProcess: < new DTargetProcess=0x%08x", tmpProcess );
+	
+	// Set the name
+	TInt err = KErrNone;
+	err = tmpProcess->SetProcessName(aProcessName);
+	if (err != KErrNone)
+		{
+		LOG_MSG2(" AttachProcess: < SetProcessName returned %d", err );
+		return err;
+		}
+
+	// Is this process being debugged (ie already attached?)
+	TInt found = KErrNotFound;
+	const TInt numberOfProcesses = iProcesses.Count();
+	for (TInt index = 0; index < numberOfProcesses; index++)
+		{
+		if (iProcesses[index]->ProcessName().CompareF(aProcessName) == 0)
+			{
+			LOG_MSG3(" Proc count=%d, found proc in iProcesses at %d. Count=%d",
+				index, iProcesses.Count() );
+			found = index;
+			break;
+			}
+		}
+
+	if (found != KErrNotFound)
+		{
+		// Yes, it is being debugged
+
+		// Add the agent to the list of agents for this process
+		LOG_MSG3(" > AddAgent(agent id %d) to existing iProcesses[%d]", I64LOW(aAgentId), found); 
+
+		iProcesses[found]->AddAgent(aAgentId);
+
+		return KErrNone;
+		}
+	else
+		{
+		// No, it is not being debugged
+			
+		// Add the agent to the list of agents for this process
+		LOG_MSG2(" > AddAgent(agent %d) to new proc at index 0", I64LOW(aAgentId) ); 
+
+		tmpProcess->AddAgent(aAgentId);
+
+		// Add the process to the list of processes being debugged
+		return iProcesses.Append(tmpProcess);
+		}
+	}
+
+/**
+ * @internalTechnology
+ * 
+ * Removes a previously created mapping between a debug agent and a debugged process,
+ * as created by AttachProcess.
+ *
+ * @param aProcessName - The fully qualified path of the debugged process. E.g. z:\sys\bin\hello_world.exe
+ * @param aAgentId - The process id of the debug agent which is attaching to aProcessName, as returned by RProcess.Id()
+ * @return KErrNone if there are no problems. KErrArgument if the processname is too long/short for a valid filepath.
+ * KErrNotFound if the mapping does not exist (and therefore cannot be removed).
+ */
+TInt DProcessTracker::DetachProcess(const TDesC8& aProcessName, TUint64 aAgentId)
+	{
+	LOG_MSG3("DProcessTracker::DetachProcess name=%S agentId=0x%lx", 
+		&aProcessName, aAgentId);
+
+	// Valid ProcessName?
+	if (aProcessName.Length() < 1 || aProcessName.Length() >= KMaxPath)
+		{
+		return KErrArgument;
+		}
+
+	if (aProcessName == _L8("*"))
+		{
+		TInt const agentCount = iAgentsAttachedToAll.Count();
+		LOG_MSG2(" iAgentsAttachedToAll size=%d", agentCount );
+
+		for (TInt i = 0; i < agentCount; i++)
+			{
+			if (iAgentsAttachedToAll[i]->Id() == aAgentId)
+				{
+				LOG_MSG2(" Agent id found at index %d, deleting it", i);
+				delete iAgentsAttachedToAll[i];
+				iAgentsAttachedToAll.Remove(i);
+				return KErrNone;
+				}
+			}
+
+		//Not found, so error condition
+		return KErrNotFound;
+		}
+
+	// Are we debugging this process?
+	const TInt numberOfProcesses = iProcesses.Count();
+	TInt foundIdx = KErrNotFound;
+	for(TInt i = 0; i < numberOfProcesses; i++)
+		{
+		if (iProcesses[i]->ProcessName().CompareF(aProcessName) == 0)
+			{
+			foundIdx = i;
+			break;
+			}
+		}
+
+	if (foundIdx == KErrNotFound)
+		{
+		return KErrNotFound;
+		}
+
+	// remove the agent from the process
+	iProcesses[foundIdx]->RemoveAgent(aAgentId);
+
+	// Found it, are there any more attached agents, or suspended threads in the process?
+
+	
+	if (iProcesses[foundIdx]->AgentCount() == 0)
+		{
+		// Delete the process as no more agents are still attached
+		delete iProcesses[foundIdx];
+
+		// Remove the now obsolete pointer from our array.
+		iProcesses.Remove(foundIdx);
+		}
+
+	return KErrNone;
+	}
+
+/**
+ * @internalTechnology
+ *
+ * Detachs a debug agent from every process being debugged. Used when a debug agent is being detached
+ * from the debug security server and has not supplied a specific process name from which to detach.
+ */
+TInt DProcessTracker::DetachAgent(const TUint64 aAgentId)
+	{
+	
+	LOG_MSG2("DProcessTracker::DetachAgent 0x%lx", aAgentId);
+	
+	// Remove this agent from all the processes being tracked.
+	TInt numberOfProcesses = iProcesses.Count();
+	for(TInt i=0; i<numberOfProcesses; i++)
+		{
+		// remove the agent from the process (we don't care about the return code)
+		iProcesses[i]->RemoveAgent(aAgentId);
+		}
+
+	// Increment down through the array as we then don't have to worry about
+	// missing entries which have been shifted after deletes.
+	// The initial value of i correspnds to the index of the final element 
+	// in the array.
+	for(TInt i = iProcesses.Count()-1; i>=0; i--)
+		{
+		if (iProcesses[i]->AgentCount() == 0)
+			{
+			// No agents remain for this process. Delete the
+			// process object and remove the pointer from the array
+			delete iProcesses[i];
+			iProcesses.Remove(i);
+			}
+		}
+
+	TInt const agentCount = iAgentsAttachedToAll.Count();
+	for (TInt i = 0; i < agentCount; i++)
+		{
+		if (iAgentsAttachedToAll[i]->Id() == aAgentId)
+			{
+			LOG_MSG2(" Agent id found at index %d, deleting it", i);
+			delete iAgentsAttachedToAll[i];
+			iAgentsAttachedToAll.Remove(i);
+			}
+		}
+		
+	return KErrNone;
+	}
+
+/**
+ * @internalTechnology
+ *
+ * Returns a pointer to a DTargetProcess object representing the mapping of a debugged process
+ * with all the relevant debug agents interested in that process, as determined
+ * by AttachProcess.
+ *
+ * @param aProcessName - The fully qualified path of the debugged process. E.g. z:\sys\bin\hello_world.exe
+ * @return DTargetProcess* pointer to an object representing the internal mapping of a process to all associated
+ * debug agents. Returns 0 if the mapping cannot be found or the aProcessName is invalid.
+ */
+DTargetProcess* DProcessTracker::FindProcess(const TDesC8& aProcessName) const
+	{
+	// Valid ProcessName?
+	if (aProcessName.Length() < 1 || aProcessName.Length() >= KMaxPath)
+		{
+		return NULL;
+		}
+
+	// Can we find this in the array?
+
+	// Are we debugging this process?
+	const TInt numberOfProcesses = iProcesses.Count();
+	DTargetProcess* found = NULL;
+	for(TInt i = 0; i < numberOfProcesses; i++)
+		{
+		if (iProcesses[i]->ProcessName().CompareF(aProcessName) == 0)
+			{
+			found = iProcesses[i];
+			LOG_EVENT_MSG3("DProcessTracker::FindProcess(%S) found at list pos %i", 
+				&aProcessName, i);
+			break;
+			}
+		}
+
+	if (found == NULL)
+		{
+		LOG_EVENT_MSG2("DProcessTracker::FindProcess(%S), not found", &aProcessName);
+		}
+
+	return found;
+	}
+
+/**
+ * @internalTechnology
+ *
+ * Returns a pointer to a DTargetProcess object representing the mapping of a debugged process
+ * with all the relevant debug agents interested in that process, as determined
+ * by AttachProcess.
+ *
+ * Note: This does not attempt an exact match, because the AddProcess event does not provide
+ * a fully-qualified path, it provides something like [t_rmdebug_security0.exe].
+ *
+ * So for the purposes of dealing with this event, we need a "fuzzier" match which does not use the complete
+ * path.
+ *
+ * @param aProcessName - The fully qualified path of the debugged process. E.g. z:\sys\bin\hello_world.exe
+ * @return DTargetProcess* pointer to an object representing the internal mapping of a process to all associated
+ * debug agents. Returns 0 if the mapping cannot be found or the aProcessName is invalid.
+ */
+DTargetProcess*	DProcessTracker::FuzzyFindProcess(const TDesC8& aProcessName)
+	{
+	// Valid ProcessName?
+	if (aProcessName.Length() < 1 || aProcessName.Length() >= KMaxPath)
+		{
+		return 0;	// not found
+		}
+
+	// Can we find this in the array?
+	TBool found = EFalse;
+	DTargetProcess* foundProcess = 0;
+	const TChar KBackSlash('\\');
+
+	TInt numberOfProcesses = iProcesses.Count();
+	for(TInt i=0; i < numberOfProcesses; i++)
+		{
+		foundProcess = iProcesses[i];
+
+		TInt procListBackSlash = foundProcess->ProcessName().LocateReverse( KBackSlash );
+		if( procListBackSlash == KErrNotFound )
+			{
+			procListBackSlash = 0;
+			}
+		else
+			{
+			//Now move to the char after the backlash
+			procListBackSlash++;
+			}
+
+		TInt eventBackSlash = aProcessName.LocateReverse( KBackSlash );
+		if( eventBackSlash == KErrNotFound )
+			{
+			eventBackSlash = 0;
+			}
+		else
+			{
+			//Now move to the char after the backlash
+			eventBackSlash++;
+			}
+
+		if( ( procListBackSlash == 0 ) && ( eventBackSlash == 0 ) )
+			{
+			//There were no backslashes on either name, so no point in continuing
+			break;
+			}
+
+		TPtrC8 eventCleanName( aProcessName.Mid( eventBackSlash ) );		
+		TPtrC8 procListCleanName( foundProcess->ProcessName().Mid( procListBackSlash ) );
+
+		if ( eventCleanName.CompareF( procListCleanName ) == 0 )
+			{
+			LOG_MSG2("DProcessTracker::FuzzyFindProcess() found a match : process list[%d]", i );
+			found = ETrue;
+			break;
+			}
+		}
+
+	if (found == EFalse)
+		{
+		return 0;	// not found
+		}
+
+	return foundProcess;
+	}
+
+/**
+  Freeze the current thread
+
+  @return KErrNone if the thread is successfully suspended,
+  KErrAlreadyExists if the agent has already suspended the thread,
+  or one of the other system wide error codes
+
+  This marks the current thread for waiting on a Fast Semaphore
+  when exception handling for this thread has completed - see
+  rm_debug_eventhandler.cpp for details.
+  */
+TInt DProcessTracker::FreezeThread()
+	{
+	// create and store a fast semaphore to stop the thread on
+	TInt err = KErrGeneral;
+	NKern::ThreadEnterCS();
+	NFastSemaphore* sem = new NFastSemaphore( &(Kern::CurrentThread().iNThread) );
+	if( sem != NULL )
+		{
+		LOG_MSG3("DProcessTracker::FreezeThread(): new NFastSemaphore(curr NThread=0x%08x), DThread=0x%08x", 
+			sem->iOwningThread, &(Kern::CurrentThread()) );
+		err = iFrozenThreadSemaphores.Append(sem); 
+		}
+	else
+		{
+		LOG_MSG("DProcessTracker::FreezeThread(): Error : could not allocate NFastSemaphore"); 
+		err = KErrNoMemory;
+		}
+
+	NKern::ThreadLeaveCS();
+	return err;
+	}
+
+/**
+ Waits the current thread on a Fast Semaphore.
+
+ This is useful for situations where the current thread
+ has hit a breakpoint within a critical section, and
+ otherwise could not be suspended at this point.
+
+ Note that the Fast Semaphore structure on which the thread
+ waits must be a member data item of this class instance,
+ as it needs to be FSSignal()'d by another thread to resume
+ again.
+ */
+void DProcessTracker::FSWait()
+	{
+	NThread* currentNThread = &(Kern::CurrentThread().iNThread);	
+	for(TInt i=0; i<iFrozenThreadSemaphores.Count(); i++)
+		{
+		if(iFrozenThreadSemaphores[i]->iOwningThread == currentNThread)
+			{
+			LOG_MSG4("DProcessTracker::FSWait(): > FSWait frozen sem %d, currentNThread=0x%08x, id=0x%x", 
+				i, currentNThread, Kern::CurrentThread().iId );
+			NKern::FSWait(iFrozenThreadSemaphores[i]);
+			return;
+			}
+		}
+	}
+	
+/**
+  Resume the specified frozen thread
+
+  @param aThread thread to resume
+
+  @return KErrNone if the thread has previously been suspended and is resumed,
+  KErrNotFound if the thread has not previously been suspended
+  */
+TInt DProcessTracker::ResumeFrozenThread(DThread* aThread)
+	{
+	for(TInt i=0; i<iFrozenThreadSemaphores.Count(); i++)
+		{
+		if(iFrozenThreadSemaphores[i]->iOwningThread == &(aThread->iNThread))
+			{
+			LOG_MSG2("DProcessTracker::ResumeFrozenThread 0x%08x, signalling then deleting this FastSem", aThread->iId );
+			NKern::FSSignal(iFrozenThreadSemaphores[i]);
+			NKern::ThreadEnterCS();
+			delete iFrozenThreadSemaphores[i];
+			NKern::ThreadLeaveCS();
+			iFrozenThreadSemaphores.Remove(i);
+			return KErrNone;
+			}
+		}
+	return KErrNotFound;
+	}
+	
+TInt DProcessTracker::SuspendThread(DThread* aTargetThread, TBool aFreezeThread)
+	{
+	LOG_MSG5("DProcessTracker::SuspendThread() id 0x%08x, iCsCount=%d, , iCsFunction=%d, iSuspendCount=%d ", 
+			aTargetThread->iId, aTargetThread->iNThread.iCsCount, aTargetThread->iNThread.iCsFunction, aTargetThread->iNThread.iSuspendCount );
+	if( !aFreezeThread )
+		{		
+		if(!aTargetThread)
+			{
+			LOG_MSG("DProcessTracker::SuspendThread()  > Kern::ThreadSuspend NullThrd Ptr!!");
+			return KErrBadHandle;
+			}
+		
+		Kern::ThreadSuspend(*aTargetThread, 1);
+		return KErrNone;
+		}
+
+	if( Kern::CurrentThread().iId != aTargetThread->iId )
+		{
+		LOG_MSG2("DProcessTracker::SuspendThread() Error: Freeze for thread 0x%08x, but different from current thread", 
+				aTargetThread->iId);
+		return KErrBadHandle;
+		}
+
+	return FreezeThread();
+	}
+
+
+TInt DProcessTracker::ResumeThread(DThread* aTargetThread)
+	{
+	LOG_MSG5("DProcessTracker::ResumeThread() id 0x%08x, iCsCount=%d, , iCsFunction=%d, iSuspendCount=%d ", 
+			aTargetThread->iId, aTargetThread->iNThread.iCsCount, aTargetThread->iNThread.iCsFunction, aTargetThread->iNThread.iSuspendCount );
+
+	TInt err = ResumeFrozenThread( aTargetThread );
+	if( err == KErrNotFound ) 
+		{
+		LOG_MSG(" ResumeThread() : not found in frozen list. Using Kern::ThreadResume" );
+		Kern::ThreadResume(*aTargetThread);
+		return KErrNone;
+		}
+
+	return err;
+	}
+
+/**
+  Get a thread's originating file name
+
+  @param aThread the thread to get the file name for
+
+  @return a pointer to the thread's file name, if there are problems accessing
+  the file name then NULL will be returned
+  */
+const TDesC* DProcessTracker::GetFileName(DThread* aThread) const
+	{
+	//check if the thread is NULL and return if so
+	if(!aThread)
+		{
+		return NULL;
+		}
+
+	//get the owning process and return if it is NULL
+	DProcess* process = aThread->iOwningProcess;
+	if(!process)
+		{
+		return NULL;
+		}
+
+	//get the process' code seg and return if it is NULL
+	DCodeSeg* codeSeg = process->iCodeSeg;
+	if(!codeSeg)
+		{
+		return NULL;
+		}
+
+	//return the code seg's stored file name (which could theoretically be NULL)
+	return codeSeg->iFileName;
+	}
+
+/**
+If any agent has called AttachToAll, return the most recently attached one.
+*/
+DDebugAgent* DProcessTracker::GetCurrentAgentAttachedToAll() const
+	{
+	if (iAgentsAttachedToAll.Count() > 0)
+		{
+		return iAgentsAttachedToAll[iAgentsAttachedToAll.Count()-1];
+		}
+	else
+		{
+		return NULL;
+		}
+	}
+
+/**
+Returns ETrue if at least one agent was found for this process (either a specifically-attached 
+one or a current attached to all). Search specifically attached first, since these have 
+priority over attach all.
+*/
+TBool DProcessTracker::NotifyAgentsForProcessEvent(const TDesC8& aProcessName, const TDriverEventInfo& aEvent, TBool aAllowFuzzy)
+	{
+	TBool foundAgent = EFalse;
+
+	DTargetProcess* process = FindProcess(aProcessName);
+	if (process == NULL && aAllowFuzzy)
+		{
+		process = FuzzyFindProcess(aProcessName);
+		}
+
+	if (process)
+		{
+		LOG_MSG3("DProcessTracker::NotifyAgentsForProcessEvent name=%S eventtype=%d", 
+			&aProcessName, aEvent.iEventType);
+		process->NotifyEvent(aEvent);
+		return ETrue;
+		}
+
+	// Since no specifically attached agents were found, try the attach all
+
+	DDebugAgent* currentAll = GetCurrentAgentAttachedToAll();
+	if (currentAll)
+		{
+		foundAgent = ETrue;
+		LOG_MSG4("DProcessTracker::NotifyAgentsForProcessEvent via AttachAll name=%S eventtype=%d, agent 0x%lx", 
+			&aProcessName, aEvent.iEventType, currentAll->Id());
+		currentAll->NotifyEvent(aEvent);
+		}
+
+	return foundAgent;
+	}
+
+/**
+ * Find the agent that matches this exe/proc name. Name could be the attachall indicator "*", 
+ * in which case it returns the agent that matched the pid from the attach all list
+ */
+DDebugAgent* DProcessTracker::FindAgentForProcessAndId(const TDesC8& aProcessName, TUint64 aAgentId) const
+	{
+
+	if (aProcessName == _L8("*"))
+		{
+		TInt const agentCount = iAgentsAttachedToAll.Count();
+		
+		LOG_MSG3("FindAgentForProcessAndId : Searching for agent id 0x%lx, iAgentsAttachedToAll size=%d", 
+			aAgentId, agentCount );
+		
+		// Then check the attached to all list. Should not have more than one entry
+		// for each agent, but just in case we search backwards to match the append
+		//
+		for (TInt i = agentCount - 1 ; i >= 0; i--)
+			{
+			DDebugAgent* agent = iAgentsAttachedToAll[i];
+			if (agent->Id() == aAgentId)
+				{
+				return agent;
+				}
+			}
+		}
+	else
+		{
+		DTargetProcess* process = FindProcess(aProcessName);
+		if (process)
+			{
+			return process->Agent(aAgentId);
+			}
+		}
+	return NULL;
+	}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/debugsrv/runmodedebug/rmdriver/src/d_rmd_breakpoints.cpp	Fri Aug 27 11:37:29 2010 +0300
@@ -0,0 +1,1816 @@
+// Copyright (c) 2004-2010 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+//
+
+
+#include <e32def.h>
+#include <e32def_private.h>
+#include <e32cmn.h>
+#include <e32cmn_private.h>
+#include <u32std.h>
+#include <kernel/kernel.h>
+#include <kernel/kern_priv.h>
+#include <nk_trace.h>
+#include <arm.h>
+#include <kernel/cache.h>
+#include <platform.h>
+#include <nkern.h>
+#include <u32hal.h>
+
+#include <rm_debug_api.h>
+#include "d_rmd_breakpoints.h"
+#include "d_process_tracker.h"
+#include "d_rmd_stepping.h"
+#include "rm_debug_kerneldriver.h"	// needed to access DRM_DebugChannel
+#include "rm_debug_driver.h"
+#include "debug_utils.h"
+#include "debug_logging.h"
+
+using namespace Debug;
+
+/* @internalTechnology
+ *
+ * Checks whether aAddress is correctly aligned for placing a breakpoint of
+ * cpu architecture aMode.
+ *
+ * @param aAddress - Virtual memory address to check
+ * @param aMode - The CPU architecture mode of the breakpoint to be placed at aAddress
+ * @return ETrue if aAddress is suitably aligned, EFalse otherwise.
+ */
+TBool D_RMD_Breakpoints::Aligned(TUint32 aAddress, Debug::TArchitectureMode aMode)
+	{
+	switch(aMode)
+		{
+		case Debug::EArmMode:
+			// ARM breakpoints must be 32-bit aligned (lower two bits must be zero)
+			if (aAddress & 0x3)
+			{
+				// Not 32-bit aligned.
+				return EFalse;
+			}
+			break;
+		case Debug::EThumbMode:
+			// Thumb breakpoints must be 16-bit aligned (low bit must be zero)
+			if (aAddress & 0x1)
+			{
+				// Not 16-bit aligned
+				return EFalse;
+			}
+			break;
+		case Debug::EThumb2EEMode:
+			// Thumb-EE instructions are half-word aligned. See ARM ARM DDI0406A, section A3.2 Alignment Support
+			// Note that some instructions need to be word-aligned, but this function does not know which ones.
+			// It may also depend on the System Control register U bit.
+			if (aAddress & 0x1)
+			{
+				// Not 16-bit aligned
+				return EFalse;
+			}
+			break;
+		default:
+			{
+			// No idea
+			return EFalse;
+			}
+		}
+
+	// Must be OK
+	return ETrue;
+	};
+
+/* @internalTechnology
+ *
+ * Returns the size of a breakpoint of architecture aMode in bytes
+ * 
+ * @param aMode - The architure of the breakpoint
+ * @return The size of the breakpoints in bytes. 0 if un-recognised architecture.
+ */
+TInt D_RMD_Breakpoints::BreakSize(Debug::TArchitectureMode aMode)
+	{
+	switch(aMode)
+		{
+		case Debug::EArmMode:
+			{
+				return 4;
+			}
+		case Debug::EThumbMode:
+			{
+				return 2;
+			}
+		case Debug::EThumb2EEMode:
+			{
+			// Only needs to be two bytes in size.
+			return 2;
+			}
+		default:
+			{
+				// No idea
+				return 0;
+			}
+		}
+	};
+
+/* @internalTechnology
+ *
+ * Checks whether two TBreakEntrys overlap
+ *
+ * @param aFirst - A TBreakEntry with valid iAddress and iMode fields.
+ * @param aSecond  - A TBreakEntry with valid iAddress and iMode fields.
+ * @return ETrue if the aFirst and aSecond overlap or the overlap cannot be determined
+ *         , EFalse otherwise
+ */
+TBool D_RMD_Breakpoints::BreakpointsOverlap(TBreakEntry& aFirst, TBreakEntry& aSecond)
+	{
+	TInt firstSize = BreakSize(aFirst.iMode);
+	TInt secondSize = BreakSize(aSecond.iMode);
+
+	// Do we know the size of each breakpoint?
+	if ((firstSize <= 0) || (secondSize <= 0))
+		{
+		// We don't know the size of the breakpoint, so assume they overlap
+		return ETrue;
+		}
+
+	TInt firstStartAddress = aFirst.iAddress;
+	TInt secondStartAddress = aSecond.iAddress;
+	TInt firstEndAddress = firstStartAddress + firstSize - 1;
+	TInt secondEndAddress = secondStartAddress + secondSize - 1;
+
+	// If second breakpoint is past the end of the first then we're ok
+	if(firstEndAddress < secondStartAddress)
+		{
+		return EFalse;
+		}
+
+	// If first breakpoint is past the end of the second then we're ok
+	if(secondEndAddress < firstStartAddress)
+		{
+		return EFalse;
+		}
+
+	// The breakpoints overlap
+	return ETrue;
+	}
+
+/* @internalTechnology
+ * 
+ * Returns the breakpoint bitpattern to use for each architecture type
+ *
+ * @param aMode - the cpu architecture type
+ * @return The bit-pattern to use for the specified architecture, or 0 if unsupported.
+ */
+TUint32 D_RMD_Breakpoints::BreakInst(Debug::TArchitectureMode aMode)
+	{
+	switch(aMode)
+		{
+		case Debug::EArmMode:
+			{
+				return KArmBreakPoint;
+			}
+		case Debug::EThumbMode:
+			{
+				return KThumbBreakPoint;
+			}
+		case Debug::EThumb2EEMode:
+			{
+			return KT2EEBreakPoint;
+			}
+		default:
+			{
+				// No idea what the breakpoint should be
+				return 0;
+			}
+		}
+	};
+
+/**
+Constructor. Initialises its internal list of empty breakpoints.
+*/
+D_RMD_Breakpoints::D_RMD_Breakpoints(DRM_DebugChannel* aChannel)
+: iBreakPointList(NUMBER_OF_TEMP_BREAKPOINTS, 0),
+  iNextBreakId(NUMBER_OF_TEMP_BREAKPOINTS),
+  iChannel(aChannel),
+  iInitialised(EFalse)
+	{
+	iBreakPointList.Reset();	
+	TBreakEntry emptyTempBreak;
+	
+	for (TInt i = 0; i < NUMBER_OF_TEMP_BREAKPOINTS; i++)
+		{
+		emptyTempBreak.iBreakId = i;
+		
+		if (KErrNone != iBreakPointList.Append(emptyTempBreak))
+			{
+			LOG_MSG("D_RMD_Breakpoints::D_RMD_Breakpoints() - Error appending blank temp break entry");
+			}
+		}
+	}
+
+/**
+Destructor. Clears all the breakpoints in the system, deletes its internal list of breakpoints,
+and closes the exclusivity semaphore.
+*/
+D_RMD_Breakpoints::~D_RMD_Breakpoints()
+	{
+	ClearAllBreakPoints();
+	
+	// close the breakpoint list and free the memory associated with it
+	iBreakPointList.Close();
+
+	if (iLock)
+		iLock->Close(NULL);
+	}
+
+/**
+Initialises the breakpoint list exclusion semaphore. This should be called once immediately after
+the constructor.
+
+@return KErrNone if successful, one of the other system wide error codes otherwise.
+*/
+TInt D_RMD_Breakpoints::Init()
+	{
+	TInt err = KErrNone;
+
+	// Only create a semaphore if we are not initialised
+	if(!iInitialised)
+		{
+		// Initialise the semaphore ensuring exclusive access to the breakpoint list
+		err = Kern::SemaphoreCreate(iLock, _L("RM_DebugBreakpointLock"), 1 /* Initial count */);
+		if (err == KErrNone)
+			{
+			iInitialised = ETrue;
+			}
+		}
+	else
+		{
+		err = KErrNone;
+		}
+
+	return err;
+	}
+
+/** 
+Public member function which sets a thread-specific breakpoint in the specified thread
+and returns an opaque handle to the caller.
+
+Note 1:
+This function ensures exclusive access to the breakpoint data structures
+by using a semaphore to serialise access.
+
+@see priv_DoSetBreak
+
+Note 2:
+As implied by Note 1, the caller must have previously called Init() or this
+function will return KErrNotReady;
+ 
+@param aBreakId - Reference to a TUint32 into which the function will return a unique breakpoint Id.
+@param aThreadId - The thread Id in which to place the breakpoint
+@param aAddress - Address to place the breakpoint
+@param aMode - The cpu instruction set architecture type breakpoint (e.g. EArmMode or EThumbMode)
+@return KErrNone if successful, otherwise one of the other system wide error codes.
+*/
+TInt D_RMD_Breakpoints::DoSetBreak(TInt32 &aBreakId, const TUint64 aId, const TBool aThreadSpecific, const TUint32 aAddress, const TArchitectureMode aMode)
+	{
+	// Ensure we have a valid semaphore
+	if (!iInitialised || !iLock)
+		{
+		return KErrNotReady;
+		}
+
+	// Acquire the lock
+	NKern::ThreadEnterCS();
+	Kern::SemaphoreWait(*iLock);
+
+	// Really do the work
+	TInt err = priv_DoSetBreak(aBreakId, aId, aThreadSpecific, aAddress,aMode);
+	
+	// Release the lock
+	Kern::SemaphoreSignal(*iLock);
+	NKern::ThreadLeaveCS();
+	
+	return err;
+	}
+/**
+Private member function which sets a thread-specific breakpoint in the specified thread
+and returns an opaque handle to the caller.
+
+@see DoSetBreak
+
+@param aBreakId - Reference to a TUint32 into which the function will return a unique breakpoint Id.
+@param aThreadId - The thread Id in which to place the breakpoint
+@param aAddress - Address to place the breakpoint
+@param aMode - The cpu instruction set architecture type breakpoint (e.g. EArmMode or EThumbMode)
+@return KErrNone if successful, otherwise one of the other system wide error codes.
+*/
+TInt D_RMD_Breakpoints::priv_DoSetBreak(TInt32 &aBreakId, const TUint64 aId, const TBool aThreadSpecific, const TUint32 aAddress, const TArchitectureMode aMode)
+	{
+	LOG_MSG4("D_RMD_Breakpoints::priv_DoSetBreak(aThreadId = 0x%lx, aAddress = 0x%08x, aMode = %d)",aId,aAddress,aMode);
+
+	// EThumb2EEMode breakpoints are not supported
+	if (EThumb2EEMode == aMode)
+		{
+		LOG_MSG("D_RMD_Breakpoints::priv_DoSetBreak() - EThumb2EEMode breakpoints are not supported");
+		return KErrNotSupported;
+		}
+
+	// Check how many breakpoints we have in existence
+	if ((iBreakPointList.Count()+1) >= NUMBER_OF_MAX_BREAKPOINTS)
+		{
+		// Too many breakpoints are set!
+		LOG_MSG("D_RMD_Breakpoints::priv_DoSetBreak() - Too many breakpoints set");
+		return KErrOverflow;
+		}
+
+	// check the alignment of the breakpoint
+	if (!Aligned(aAddress,aMode))
+		{
+		LOG_MSG("D_RMD_Breakpoints::priv_DoSetBreak() - Unaligned address");
+		return KErrArgument;
+		}
+
+	// make sure there is not already a breakpoint at this address
+	for (TInt i = NUMBER_OF_TEMP_BREAKPOINTS; i < iBreakPointList.Count(); i++)
+		{
+		/* We need to check if the breakpoint overlaps the address at all,
+		 * and this depends upon the size of the two breakpoints as well as 
+		 * their address.
+		 */
+
+		// newInstSize = size in bytes of new breakpoint
+		TInt newInstSize = BreakSize(aMode);
+		if (newInstSize == 0)
+			{
+			LOG_MSG("D_RMD_Breakpoints::priv_DoSetBreak() - Unknown architecture type for new breakpoint");
+			return KErrNotSupported;
+			}
+
+		// oldInstSize = size in bytes of the existing breakpoint
+		TInt oldInstSize = BreakSize(iBreakPointList[i].iMode);
+		if (oldInstSize == 0)
+			{
+			LOG_MSG("D_RMD_Breakpoints::priv_DoSetBreak() - : Unknown architecture type of existing breakpoint");
+			return KErrNotSupported;
+			}
+
+		// Overlap checking - temp is used as the new breakpoint description for checking purposes only
+		TBreakEntry temp;
+
+		temp.iAddress = aAddress;
+		temp.iMode = aMode;
+
+		// do they overlap?
+		if ( BreakpointsOverlap(temp,iBreakPointList[i]) )
+			{
+			// Yes
+			if(iBreakPointList[i].iThreadSpecific && aThreadSpecific)
+				{
+				if(aId == iBreakPointList[i].iId)
+					{
+					LOG_MSG("D_RMD_Breakpoints::priv_DoSetBreak() - New thread specific breakpoint overlaps an existing thread specific breakpoint");
+					return KErrAlreadyExists;
+					}
+				}
+			else if(!iBreakPointList[i].iThreadSpecific && aThreadSpecific)
+				{
+				NKern::ThreadEnterCS();
+				DThread* thread = DebugUtils::OpenThreadHandle(aId);
+				TInt err = KErrNone;
+				if (!thread)
+					{
+					err = KErrNotFound;
+					}
+				if (!err && thread->iOwningProcess->iId == iBreakPointList[i].iId)
+					{
+					LOG_MSG("D_RMD_Breakpoints::priv_DoSetBreak() - New thread specific breakpoint overlaps an existing breakpoint");
+					err = KErrAlreadyExists;
+					}
+				thread->Close(NULL);
+				NKern::ThreadLeaveCS();
+				if (err) return err;
+				}
+			else if(iBreakPointList[i].iThreadSpecific && !aThreadSpecific)
+				{
+				NKern::ThreadEnterCS();
+				DThread* thread = DebugUtils::OpenThreadHandle(iBreakPointList[i].iId);
+				TInt err = KErrNone;
+				if (!thread)
+					{
+					err = KErrNotFound;
+					}
+				if (!err && thread->iOwningProcess->iId == aId)
+					{
+					LOG_MSG("D_RMD_Breakpoints::priv_DoSetBreak() - New breakpoint overlaps an existing thread specific breakpoint");
+					err = KErrAlreadyExists;
+					}
+				if (thread) thread->Close(NULL);
+				NKern::ThreadLeaveCS();
+				if (err) return err;
+				}
+			else // !iBreakPointList[i].iThreadSpecific && !aThreadSpecific
+				{
+				if(iBreakPointList[i].iId == aId)
+					{
+					LOG_MSG("D_RMD_Breakpoints::priv_DoSetBreak() - New breakpoint overlaps an existing breakpoint");
+					return KErrAlreadyExists;
+					}
+				}
+			}
+		}
+
+	// increment the break id
+	aBreakId = iNextBreakId++;	
+
+	// create the new breakpoint entry
+	TBreakEntry breakEntry(aBreakId, aId, aThreadSpecific, aAddress, aMode);
+
+	TInt err = priv_DoEnableBreak(breakEntry, ETrue);
+	if (KErrNone != err)
+		{
+		LOG_MSG("D_RMD_Breakpoints::priv_DoSetBreak() - Could not enable the breakpoint");
+		
+		return err;
+		}
+
+	err = iBreakPointList.Append(breakEntry);
+	if (err != KErrNone)
+		{
+		LOG_MSG("D_RMD_Breakpoints::priv_DoSetBreak() - Failed to append breakpoint");
+		}
+
+	LOG_MSG2("D_RMD_Breakpoints::priv_DoSetBreak(breakId = 0x%08x) done",aBreakId);
+
+	return err;
+	}
+
+/**
+Public member function which enables a previously set breakpoint.
+
+Note 1:
+This function ensures exclusive access to the breakpoint data structures
+by using a semaphore to serialise access.
+
+@see priv_DoEnableBreak
+
+Note 2:
+As implied by Note 1, the caller must have previously called Init() or this
+function will return KErrNotReady;
+
+Note 3
+Historically, this function accepted a reference to a TBreakEntry in the class' own
+iBreakPointList. It now checks whether the reference is to an element of its own list,
+or one invented by the caller.
+
+@param aEntry reference to a TBreakEntry datastructure describing the breakpoint to be re-enabled.
+@param aSaveOldInstruction ETrue preserves the instruction at the breakpoint address, EFalse otherwise.
+@return KErrNone if successful, otherwise one of the other system wide error codes.
+*/
+TInt D_RMD_Breakpoints::DoEnableBreak(TBreakEntry &aEntry, TBool aSaveOldInstruction)
+	{
+	// Ensure we have a valid semaphore
+	if (!iInitialised || !iLock)
+		{
+		return KErrNotReady;
+		}
+
+	// Acquire the lock
+	NKern::ThreadEnterCS();
+	Kern::SemaphoreWait(*iLock);
+
+	// Really do the work
+	TInt err = priv_DoEnableBreak(aEntry,aSaveOldInstruction);
+	
+	// Release the lock
+	Kern::SemaphoreSignal(*iLock);
+	NKern::ThreadLeaveCS();
+
+	return err;
+	}
+
+/**
+Private member function which enables a previously set breakpoint, as per DoEnableBreak, but
+does not serialise access.
+
+@see DoEnableBreak
+
+@param aEntry reference to a TBreakEntry datastructure describing the breakpoint to be re-enabled.
+@param aSaveOldInstruction ETrue preserves the instruction at the breakpoint address, EFalse otherwise.
+@return KErrNone if successful, otherwise one of the other system wide error codes.
+*/
+TInt D_RMD_Breakpoints::priv_DoEnableBreak(TBreakEntry &aEntry, TBool aSaveOldInstruction)
+	{
+	LOG_MSG("D_RMD_Breakpoints::DoEnableBreak()");
+
+	TUint32 inst = BreakInst(aEntry.iMode);	
+	TInt instSize = BreakSize(aEntry.iMode);
+	if (instSize == 0 || inst == 0)
+		{
+		// not supported
+		LOG_MSG("D_RMD_Breakpoints::priv_DoEnableBreak - unsupported breakpoint architecture");
+		return KErrNotSupported;
+		}
+
+	TInt err = KErrNone;
+
+	// Get thread id
+	TUint64 threadId = aEntry.iId + (aEntry.iThreadSpecific ? 0 : 1);
+	NKern::ThreadEnterCS();
+	DThread* threadObj = DebugUtils::OpenThreadHandle(threadId);
+	if (!threadObj)
+		{
+		LOG_MSG("D_RMD_Breakpoints::priv_DoEnableBreak - bad handle. Could not identify a threadObj");
+		NKern::ThreadLeaveCS();
+		return KErrBadHandle;
+		}
+
+	if (aSaveOldInstruction)
+		{
+		TUint32 instruction;
+
+		// read the instruction at the address so we can store it in the break entry for when we clear this breakpoint
+		// trap exceptions in case the address is invalid
+		XTRAPD(r, XT_DEFAULT, err = iChannel->TryToReadMemory(threadObj, (TAny *)aEntry.iAddress, (TAny *)&instruction, instSize));
+
+		//consider the leave as more important than the error code so store the leave if it's not KErrNone
+		if(KErrNone != r)
+			{
+			err = r;
+			}
+
+		if(KErrNone != err)
+			{
+			threadObj->Close(NULL);
+			NKern::ThreadLeaveCS();
+			LOG_MSG("D_RMD_Breakpoints::priv_DoEnableBreak() - failed to read memory");
+			return err;
+			}
+
+		aEntry.iInstruction.Copy((TUint8 *)&instruction, instSize);
+		}
+
+	TBool breakpointAlredySet = EFalse;
+	for (TInt i = NUMBER_OF_TEMP_BREAKPOINTS; i < iBreakPointList.Count(); i++)
+		{
+		if(iBreakPointList[i].iAddress == aEntry.iAddress && !iBreakPointList[i].iDisabledForStep )
+			{
+			breakpointAlredySet = ETrue;
+			break;
+			}
+		}
+	if(!breakpointAlredySet)
+		{
+	
+		LOG_MSG5("D_RMD_Breakpoints::DoEnableBreak() tId=0x%x, addr=0x%x, instSize=%d, inst=0x%x", 
+			threadObj->iId, aEntry.iAddress, instSize, instSize == 4 ? (TUint32)inst : (TUint16)inst );
+		XTRAPD(r, XT_DEFAULT, err = DebugSupport::ModifyCode(threadObj, aEntry.iAddress, instSize, inst, DebugSupport::EBreakpointGlobal));
+		if(r != DebugSupport::EBreakpointGlobal)
+			{
+			err = r;
+			}
+		}
+	else
+		{
+		LOG_MSG5("D_RMD_Breakpoints::DoEnableBreak() ALREADY SET: tId=0x%x, addr=0x%x, instSize=%d, inst=0x%x", 
+				threadObj->iId, aEntry.iAddress, instSize, instSize == 4 ? (TUint32)inst : (TUint16)inst );
+
+		}
+
+	// Close the thread handle which has been opened by OpenThreadHandle
+	threadObj->Close(NULL);
+	NKern::ThreadLeaveCS();
+	return err;
+	}
+
+/**
+Public member function which clears a previously set breakpoint.
+
+Note 1:
+This function ensures exclusive access to the breakpoint data structures
+by using a semaphore to serialise access.
+
+@see priv_DoClearBreak
+
+Note 2:
+As implied by Note 1, the caller must have previously called Init() or this
+function will return KErrNotReady;
+
+@param aBreakId A breakpoint Id as previously returned by DoSetBreak.
+@return KErrNone if successful, otherwise one of the other system wide error codes.
+*/
+TInt D_RMD_Breakpoints::DoClearBreak(const TInt32 aBreakId, TBool aIgnoreTerminatedThreads)
+	{
+	// Ensure we have a valid semaphore
+	if (!iInitialised || !iLock)
+		{
+		return KErrNotReady;
+		}
+
+	// Acquire the lock
+	NKern::ThreadEnterCS();
+	Kern::SemaphoreWait(*iLock);
+
+	// Really do the work
+	TInt err = priv_DoClearBreak(aBreakId, aIgnoreTerminatedThreads);
+	
+	// Release the lock
+	Kern::SemaphoreSignal(*iLock);
+	NKern::ThreadLeaveCS();
+
+	return err;
+	}
+
+/**
+Private member function which clears a previously set breakpoint, as per DoClearBreak, but
+does not serialise access.
+
+@see DoClearBreak
+
+@param aBreakId A breakpoint Id as previously returned by DoSetBreak.
+@return KErrNone if successful, otherwise one of the other system wide error codes.
+*/
+TInt D_RMD_Breakpoints::priv_DoClearBreak(const TInt32 aBreakId, TBool aIgnoreTerminatedThreads)
+	{
+	LOG_MSG3("D_RMD_Breakpoints::priv_DoClearBreak(0x%08x), aIgnoreTerminatedThreads=%d",
+	        aBreakId, aIgnoreTerminatedThreads);
+
+	// find the break entry matching this id.  note that the breakpoints are already sorted in ascending order by id
+	TBreakEntry entry;
+	entry.iBreakId = aBreakId;
+	TInt index = iBreakPointList.FindInSignedKeyOrder(entry);
+
+	TInt err = KErrNone;
+	if (index >= 0)
+		{	
+ 		// if this breakpoint was set in a library and that library has already been unloaded, don't try to clear it
+		if (!iBreakPointList[index].iObsoleteLibraryBreakpoint)
+			{
+			NKern::ThreadEnterCS();
+			DThread* threadObj = DebugUtils::OpenThreadHandle(iBreakPointList[index].iId + (iBreakPointList[index].iThreadSpecific ? 0 : 1));
+			if (threadObj)
+				{
+				LOG_MSG2("priv_DoClearBreak() OpenThreadHandle ret thread 0x%08x", threadObj->iId );
+				TBool needToCallCodeModifier = ETrue;
+				for (TInt i = NUMBER_OF_TEMP_BREAKPOINTS; i < iBreakPointList.Count(); i++)
+					{
+					if (i != index)
+						{
+						if ( BreakpointsOverlap(iBreakPointList[index],iBreakPointList[i]) )
+							{
+							needToCallCodeModifier = EFalse;
+							break;
+							}
+						}
+					}
+				if(needToCallCodeModifier)
+					{
+					XTRAPD(r, XT_DEFAULT, err = DebugSupport::RestoreCode(threadObj, iBreakPointList[index].iAddress));
+					if (r != KErrNone)
+						{
+						LOG_MSG2("D_RMD_Breakpoints::priv_DoClearBreak() - restore code trap harness returned error %d",r);
+						}
+					if (err == KErrNotFound)
+						{
+						LOG_MSG("restore code reported the breakpoint not found, continuing");
+						err = KErrNone;
+						}
+					else if (err != KErrNone)
+						{
+						LOG_MSG2("D_RMD_Breakpoints::priv_DoClearBreak() - restore code returned error %d",err);
+						}
+					err = (KErrNone == r) ? err : r;
+					}
+
+				// Close the thread handle opened by OpenThreadHandle
+				threadObj->Close(NULL);
+				}
+			else
+				{
+				LOG_MSG("D_RMD_Breakpoints::OpenThreadHandle ret null thread");
+				err = KErrBadHandle;
+				}
+			NKern::ThreadLeaveCS();
+			}
+		
+		LOG_MSG4("D_RMD_Breakpoints::priv_DoClearBreak() - Clearing breakpoint at address: %x, err: %d, ignore terminated: %d", iBreakPointList[index].iAddress, err, aIgnoreTerminatedThreads?1:0);
+		if ((aIgnoreTerminatedThreads && KErrBadHandle == err) || KErrNone == err)
+			{
+			// if this is a temp breakpoint, just clear out the values, otherwise remove it from the list
+			err = KErrNone;
+			if (index < NUMBER_OF_TEMP_BREAKPOINTS)
+				{
+                // if this is a temp breakpoint, just clear out the values, otherwise remove it from the list
+                LOG_MSG2("D_RMD_Breakpoints::priv_DoClearBreak() - Reseting temp breakpoint[%d]",index);
+				iBreakPointList[index].Reset();
+				}
+			else
+				{
+				LOG_MSG2("D_RMD_Breakpoints::priv_DoClearBreak() - Removing breakpoint[%d]",index);
+				iBreakPointList.Remove(index);
+				}			
+			}
+		else
+		    {
+            LOG_MSG3("D_RMD_Breakpoints::priv_DoClearBreak() - *** Not removing breakpoint[%d] due to error=%d",index, err);
+		    }
+				
+		return err;
+		}
+
+	LOG_MSG2("D_RMD_Breakpoints::priv_DoClearBreak() - Break Id %d not found", aBreakId);
+
+	return KErrNotFound;
+	}
+
+/**
+Public member function which modifies a previously set breakpoint.
+
+Note 1:
+This function ensures exclusive access to the breakpoint data structures
+by using a semaphore to serialise access.
+
+@see priv_DoModifyBreak
+
+Note 2:
+As implied by Note 1, the caller must have previously called Init() or this
+function will return KErrNotReady;
+
+@param aBreakInfo A TModifyBreakInfo describing the breakpoint properties that are wanted.
+@return KErrNone if successful, otherwise one of the other system wide error codes.
+*/
+TInt D_RMD_Breakpoints::DoModifyBreak(TModifyBreakInfo* aBreakInfo)
+	{
+	// Ensure we have a valid semaphore
+	if (!iInitialised || !iLock)
+		{
+		return KErrNotReady;
+		}
+
+	// Acquire the lock
+	NKern::ThreadEnterCS();
+	Kern::SemaphoreWait(*iLock); 
+
+	// Really do the work
+	TInt err = priv_DoModifyBreak(aBreakInfo);
+	
+	// Release the lock
+	Kern::SemaphoreSignal(*iLock);
+	NKern::ThreadLeaveCS();
+
+	return err;
+	}
+
+/**
+Private member function which modifies a previously set breakpoint, as per DoModifyBreak, but
+does not serialise access.
+
+@see DoModifyBreak
+
+@param aBreakInfo A TModifyBreakInfo describing the breakpoint properties that are wanted.
+@return KErrNone if successful, otherwise one of the other system wide error codes.
+*/
+TInt D_RMD_Breakpoints::priv_DoModifyBreak(TModifyBreakInfo* aBreakInfo)
+	{
+	LOG_MSG("D_RMD_Breakpoints::priv_DoModifyBreak()");
+
+	// Check arguments
+	if (!aBreakInfo)
+		{
+		LOG_MSG("D_RMD_Breakpoints::priv_DoModifyBreak() was passed a NULL argument");
+		return KErrArgument;
+		}
+
+	//User side memory is not accessible directly
+	TSetBreakInfo info;
+	TInt err = Kern::ThreadRawRead(iChannel->iClientThread, aBreakInfo, (TUint8*)&info, sizeof(TSetBreakInfo));
+	if (err != KErrNone)
+		{
+		LOG_MSG("D_RMD_Breakpoints::priv_DoModifyBreak() was passed a bad argument");
+		return err;
+		}
+
+	// EThumb2EEMode breakpoints are not supported
+	if (EThumb2EEMode == info.iMode)
+		{
+		LOG_MSG("D_RMD_Breakpoints::priv_DoModifyBreak() - EThumb2EEMode breakpoints are not supported");
+		return KErrNotSupported;
+		}
+
+	// find the break entry matching this id.  note that the breakpoints are already sorted in ascending order by id
+	TBreakEntry entry;
+	entry.iBreakId = (TUint32)info.iBreakId;
+	TInt index = iBreakPointList.FindInSignedKeyOrder(entry);
+	if (index < 0)
+		{
+		// Could not find the breakpoint
+		LOG_MSG2("D_RMD_Breakpoints::priv_DoModifyBreak() - Could not find the breakpoint id 0x%08x",(TUint32)info.iBreakId);
+		return KErrNotFound;
+		}
+
+	// first check its not obsolete
+	if (!iBreakPointList[index].iObsoleteLibraryBreakpoint)
+		{
+		// its still a valid breakpoint
+
+		// remove the old breakpoint
+		NKern::ThreadEnterCS();
+		DThread* threadObj = DebugUtils::OpenThreadHandle(iBreakPointList[index].iId);
+		if (threadObj)
+			{
+			LOG_MSG2("D_RMD_Breakpoints::priv_DoModifyBreak - Unsetting breakpoint at address 0x%08x",iBreakPointList[index].iAddress);
+
+			XTRAPD(r, XT_DEFAULT, err = DebugSupport::RestoreCode(threadObj, iBreakPointList[index].iAddress));
+			if (r != 0)
+				{
+				LOG_MSG("Failed to construct trap handler for DebugSupport::RestoreCode");
+				}
+
+			// Close the thread handle which has been opened by OpenThreadHandle
+			threadObj->Close(NULL);
+			NKern::ThreadLeaveCS();
+			}
+		else
+			{
+			// Bad handle
+			LOG_MSG("D_RMD_Breakpoints::priv_DoModifyBreak - Could not identify the breakpoint thread id");
+			NKern::ThreadLeaveCS();
+			return KErrBadHandle;
+			}
+		}
+
+	// make sure there is not already a breakpoint at the new address
+	for (TInt i = NUMBER_OF_TEMP_BREAKPOINTS; i < iBreakPointList.Count(); i++)
+		{
+		// Ignore data for the breakpoint entry being modified.
+		if (i != index)
+			{
+			/* We need to check if the breakpoint overlaps the address at all,
+			 * and this depends upon the size of the two breakpoints as well as 
+			 * their address.
+			 */
+
+			// newInstSize = size in bytes of new breakpoint
+			TInt newInstSize = BreakSize(info.iMode);
+			if (newInstSize == 0)
+			{
+				LOG_MSG("D_RMD_Breakpoints::priv_DoModifyBreak - Unknown architecture type for new breakpoint");
+				return KErrNotSupported;
+			}
+
+			// oldInstSize = size in bytes of the existing breakpoint
+			TInt oldInstSize = BreakSize(iBreakPointList[i].iMode);
+			if (oldInstSize == 0)
+			{
+				LOG_MSG("D_RMD_Breakpoints::priv_DoModifyBreak - Unknown architecture type of existing breakpoint");
+				return KErrNotSupported;
+			}
+
+			// Overlap checking - temp is used as the new breakpoint description for checking purposes only
+			TBreakEntry temp;
+
+			temp.iAddress = info.iAddress;
+			temp.iMode = info.iMode;
+
+			// do they overlap?
+			if ( BreakpointsOverlap(temp,iBreakPointList[i]) )
+				{
+				// Yes
+				LOG_MSG("D_RMD_Breakpoints::priv_DoModifyBreak() - New breakpoint overlaps an existing breakpoint");
+				return KErrAlreadyExists;
+				}
+			}
+		}
+
+	// Prepare iBreakPointList[index] with the new information, then set the breakpoint
+	iBreakPointList[index].iId = info.iId;
+	iBreakPointList[index].iAddress = info.iAddress;
+	iBreakPointList[index].iMode = info.iMode;
+
+	TBreakEntry& newBreakEntry = iBreakPointList[index];
+
+	// Decide the size of the breakpoint instruction
+	TUint32 inst = BreakInst(newBreakEntry.iMode);
+	TInt instSize = BreakSize(newBreakEntry.iMode);
+
+	if (inst == 0 || instSize == 0)
+		{
+		// Unsupported architecture
+		LOG_MSG("D_RMD_Breakpoints::priv_DoModifyBreak - unsupported breakpoint architecture");
+		return KErrNotSupported;
+		}
+
+
+	//if thread id is 0xFFFFFFFF, then the breakpoint is not thread specific
+	if (newBreakEntry.iId != 0xFFFFFFFF)
+		{
+		newBreakEntry.iThreadSpecific = ETrue;
+		}
+
+	// Get thread id from the process that we are debugging
+	TProcessInfo * proc = NULL;
+	TUint64 threadId = NULL;
+
+	threadId = newBreakEntry.iId;
+
+	NKern::ThreadEnterCS();
+	DThread* threadObj = DebugUtils::OpenThreadHandle(threadId);
+	//if we don't have the right thread id for the address, 
+	//then try with the thread id of the process that we are debugging 	
+	if (!threadObj && iChannel->iDebugProcessList.Count())
+		{
+		proc = &iChannel->iDebugProcessList[0];
+		if (proc)
+			{
+			threadId = proc->iId+1;	
+			}
+		threadObj = DebugUtils::OpenThreadHandle(threadId);
+		}
+
+	if(!threadObj)
+		{
+		LOG_MSG("D_RMD_Breakpoints::priv_DoModifyBreak() - bad handle. Could not identify a threadObj");
+		NKern::ThreadLeaveCS();
+		return KErrBadHandle;
+		}
+
+	// save the old instruction
+	TUint32 instruction;
+
+	// read the instruction at the address so we can store it in the break entry for when we clear this breakpoint
+	// trap exceptions in case the address is invalid
+	XTRAPD(r, XT_DEFAULT, err = iChannel->TryToReadMemory(threadObj, (TAny *)newBreakEntry.iAddress, (TAny *)&instruction, instSize));
+
+	//consider the leave as more important than the error code so store the leave if it's not KErrNone
+	if(KErrNone != r)
+		{
+		err = r;
+		}
+	if(KErrNone != err)
+		{
+		threadObj->Close(NULL);
+		NKern::ThreadLeaveCS();
+		return err;
+		}
+
+	newBreakEntry.iInstruction.Copy((TUint8 *)&instruction, instSize);
+
+	newBreakEntry.iId = threadId; //set the thread ID here 
+	LOG_MSG3("ModifyCode2 instSize:%d, inst: 0x%08x", instSize, inst);
+	XTRAPD(s, XT_DEFAULT, err = DebugSupport::ModifyCode(threadObj, newBreakEntry.iAddress, instSize, inst, DebugSupport::EBreakpointGlobal));
+	if(s != DebugSupport::EBreakpointGlobal)
+		{
+		err = s;
+		}
+
+	// Close the thread handle which has been opened by OpenThreadHandle
+	threadObj->Close(NULL);
+	NKern::ThreadLeaveCS();
+	return err;
+	}	
+
+//
+// D_RMD_Breakpoints::DoModifyProcessBreak
+//
+TInt D_RMD_Breakpoints::DoModifyProcessBreak(TModifyProcessBreakInfo* aBreakInfo)
+	{
+	// Ensure we have a valid semaphore
+	if (!iInitialised || !iLock)
+		{
+		return KErrNotReady;
+		}
+
+	// Acquire the lock
+	NKern::ThreadEnterCS();
+	Kern::SemaphoreWait(*iLock); 
+
+	// Really do the work
+	TInt err = priv_DoModifyProcessBreak(aBreakInfo);
+	
+	// Release the lock
+	Kern::SemaphoreSignal(*iLock);
+	NKern::ThreadLeaveCS();
+
+	return err;
+	}
+	
+TInt D_RMD_Breakpoints::priv_DoModifyProcessBreak(TModifyProcessBreakInfo* aBreakInfo)
+	{	
+	LOG_MSG("D_RMD_Breakpoints::priv_DoModifyProcessBreak()");
+
+	// Check arguments
+	if (!aBreakInfo)
+		{
+		LOG_MSG("D_RMD_Breakpoints::priv_DoModifyProcessBreak() was passed a NULL argument");
+		return KErrArgument;
+		}
+
+	//User side memory is not accessible directly
+	TSetBreakInfo info;
+	TInt err = Kern::ThreadRawRead(iChannel->iClientThread, aBreakInfo, (TUint8*)&info, sizeof(TModifyProcessBreakInfo));
+	if (err != KErrNone)
+		{
+		LOG_MSG("D_RMD_Breakpoints::priv_DoModifyProcessBreak() was passed a bad argument");
+		return err;
+		}
+
+	// EThumb2EEMode breakpoints are not supported
+	if (EThumb2EEMode == info.iMode)
+		{
+		LOG_MSG("D_RMD_Breakpoints::priv_DoModifyProcessBreak() - EThumb2EEMode breakpoints are not supported");
+		return KErrNotSupported;
+		}
+
+	// find the break entry matching this id.  note that the breakpoints are already sorted in ascending order by id
+	TBreakEntry entry;
+	entry.iBreakId = (TUint32)info.iBreakId;
+	TInt index = iBreakPointList.FindInSignedKeyOrder(entry);
+	if (index < 0)
+		{
+		// Could not find the breakpoint
+		LOG_MSG2("D_RMD_Breakpoints::priv_DoModifyProcessBreak() - Could not find the breakpoint id 0x%08x",(TUint32)info.iBreakId);
+		return KErrNotFound;
+		}
+
+	// first check its not obsolete
+	if (!iBreakPointList[index].iObsoleteLibraryBreakpoint)
+		{
+		// its still a valid breakpoint
+
+		// remove the old breakpoint
+		NKern::ThreadEnterCS();
+		DProcess *process = DebugUtils::OpenProcessHandle(iBreakPointList[index].iId);
+		DThread* threadObj = NULL;
+		if(process)
+			{
+			threadObj = DebugUtils::OpenFirstThreadForProcess(process);
+			process->Close(NULL);
+			}
+
+		if (threadObj)
+			{
+			LOG_MSG2("D_RMD_Breakpoints::priv_DoModifyProcessBreak() - Unsetting breakpoint at address 0x%08x",iBreakPointList[index].iAddress);
+
+			XTRAPD(r, XT_DEFAULT, /*err =*/ DebugSupport::RestoreCode(threadObj, iBreakPointList[index].iAddress)); // Any error here is not important. The semantics of ModifyBreakpoint are such that if it fails the previous breakpoint location is removed, which means that a further call to ModifyBreakpoint shouldn't fail because the CodeModifier doesn't know about it.
+			if (r != 0)
+				{
+				LOG_MSG("D_RMD_Breakpoints::priv_DoModifyProcessBreak() - Failed to construct trap handler for DebugSupport::RestoreCode");
+				}
+
+			// Close the thread handle which has been opened by OpenThreadHandle
+			threadObj->Close(NULL);
+			}
+		else
+			{
+			// Bad handle
+			LOG_MSG("D_RMD_Breakpoints::priv_DoModifyProcessBreak() - Could not identify the breakpoint process id");
+			err = KErrBadHandle;
+			}
+		NKern::ThreadLeaveCS();
+		if (err) return err;
+		}
+
+	// make sure there is not already a breakpoint at the new address
+	for (TInt i = NUMBER_OF_TEMP_BREAKPOINTS; i < iBreakPointList.Count(); i++)
+		{
+		// Ignore data for the breakpoint entry being modified.
+		if (i != index)
+			{
+			/* We need to check if the breakpoint overlaps the address at all,
+			 * and this depends upon the size of the two breakpoints as well as 
+			 * their address.
+			 */
+
+			// newInstSize = size in bytes of new breakpoint
+			TInt newInstSize = BreakSize(info.iMode);
+			if (newInstSize == 0)
+				{
+				LOG_MSG("D_RMD_Breakpoints::priv_DoModifyProcessBreak() - Unknown architecture type for new breakpoint");
+				return KErrNotSupported;
+				}
+
+			// oldInstSize = size in bytes of the existing breakpoint
+			TInt oldInstSize = BreakSize(iBreakPointList[i].iMode);
+			if (oldInstSize == 0)
+				{
+				LOG_MSG("D_RMD_Breakpoints::priv_DoModifyProcessBreak() - : Unknown architecture type of existing breakpoint");
+				return KErrNotSupported;
+				}
+
+			// Overlap checking - temp is used as the new breakpoint description for checking purposes only
+			TBreakEntry temp;
+
+			temp.iAddress = info.iAddress;
+			temp.iMode = info.iMode;
+
+			// do they overlap?
+			if ( BreakpointsOverlap(temp,iBreakPointList[i]) )
+				{
+				// Yes
+				LOG_MSG("D_RMD_Breakpoints::priv_DoModifyProcessBreak() - New breakpoint overlaps an existing breakpoint");
+				return KErrAlreadyExists;
+				}
+			}
+		}
+
+	// Prepare iBreakPointList[index] with the new information, then set the breakpoint
+	iBreakPointList[index].iId = info.iId;
+	iBreakPointList[index].iAddress = info.iAddress;
+	iBreakPointList[index].iMode = info.iMode;
+
+	TBreakEntry& newBreakEntry = iBreakPointList[index];
+
+	// Decide the size of the breakpoint instruction
+	TUint32 inst = BreakInst(newBreakEntry.iMode);
+	TInt instSize = BreakSize(newBreakEntry.iMode);
+
+	if (inst == 0 || instSize == 0)
+		{
+		// Unsupported architecture
+		LOG_MSG("D_RMD_Breakpoints::priv_DoModifyProcessBreak() - unsupported breakpoint architecture");
+		return KErrNotSupported;
+		}
+
+	newBreakEntry.iThreadSpecific = EFalse;
+
+	DThread* threadObj = NULL;
+	NKern::ThreadEnterCS();
+	DProcess* process = DebugUtils::OpenProcessHandle(newBreakEntry.iId);
+	if (process)
+		{
+		threadObj = DebugUtils::OpenFirstThreadForProcess(process);
+		if (!threadObj) err = KErrNotFound;
+		process->Close(NULL);
+		}
+	else
+		{
+		LOG_MSG("D_RMD_Breakpoints::priv_DoModifyProcessBreak() - bad handle. Could not identify a process");
+		err = KErrBadHandle;
+		}
+
+	if (err)
+		{
+		NKern::ThreadLeaveCS();
+		return err;
+		}
+
+	// save the old instruction
+	TUint32 instruction;
+
+	// read the instruction at the address so we can store it in the break entry for when we clear this breakpoint
+	// trap exceptions in case the address is invalid
+	XTRAPD(r, XT_DEFAULT, err = iChannel->TryToReadMemory(threadObj, (TAny *)newBreakEntry.iAddress, (TAny *)&instruction, instSize));
+
+	//consider the leave as more important than the error code so store the leave if it's not KErrNone
+	if(KErrNone != r)
+		{
+		err = r;
+		}
+	if(KErrNone != err)
+		{
+		threadObj->Close(NULL);
+		NKern::ThreadLeaveCS();
+		return err;
+		}
+
+	newBreakEntry.iInstruction.Copy((TUint8 *)&instruction, instSize);
+
+	XTRAPD(s, XT_DEFAULT, err = DebugSupport::ModifyCode(threadObj, newBreakEntry.iAddress, instSize, inst, DebugSupport::EBreakpointGlobal));
+	if(s != DebugSupport::EBreakpointGlobal)
+		{
+		err = s;
+		}
+
+	// Close the thread handle which has been opened by OpenThreadHandle
+	threadObj->Close(NULL);
+	NKern::ThreadLeaveCS();
+	return err;
+	}
+
+/**
+Public member function which returns information about a previously set breakpoint.
+
+Note 1:
+This function ensures exclusive access to the breakpoint data structures
+by using a semaphore to serialise access.
+
+@see priv_DoBreakInfo
+
+Note 2:
+As implied by Note 1, the caller must have previously called Init() or this
+function will return KErrNotReady;
+
+@param aBreakInfo Address of aBreakInfo structure in user-side memory within the DSS client thread. CAN ONLY BE ACCESSED VIA Kern::ThreadRawRead()
+@return KErrNone if successful, otherwise one of the other system wide error codes.
+*/
+TInt D_RMD_Breakpoints::DoBreakInfo(TGetBreakInfo* aBreakInfo)
+	{
+	// Ensure we have a valid semaphore
+	if (!iInitialised || !iLock)
+		{
+		return KErrNotReady;
+		}
+
+	// Acquire the lock
+	NKern::ThreadEnterCS();
+	Kern::SemaphoreWait(*iLock);
+
+	// Really do the work
+	TInt err = priv_DoBreakInfo(aBreakInfo);
+	
+	// Release the lock
+	Kern::SemaphoreSignal(*iLock);
+	NKern::ThreadLeaveCS();
+
+	return err;
+	}
+
+/**
+Private member function function which returns information about a previously set breakpoint..
+
+@see DoBreakInfo
+
+@param aBreakInfo Address of aBreakInfo structure in user-side memory within the DSS client thread. CAN ONLY BE ACCESSED VIA Kern::ThreadRawRead()
+@return KErrNone if successful, otherwise one of the other system wide error codes.
+*/
+TInt D_RMD_Breakpoints::priv_DoBreakInfo(TGetBreakInfo* aBreakInfo)
+	{
+	LOG_MSG("D_RMD_Breakpoints::priv_DoBreakInfo()");
+
+	if (!aBreakInfo)
+		{
+		LOG_MSG("D_RMD_Breakpoints::priv_DoBreakInfo() was passed a NULL argument");
+
+		return KErrArgument;
+		}
+
+	//User side memory is not accessible directly
+	TGetBreakInfo info;
+	TInt err = Kern::ThreadRawRead(iChannel->iClientThread, aBreakInfo, (TUint8*)&info, sizeof(TGetBreakInfo));
+	if (err != KErrNone)
+		{
+		LOG_MSG("D_RMD_Breakpoints::priv_DoBreakInfo() was passed a bad argument");
+
+		return err;
+		}
+
+	// find the break entry matching this id.  note that the breakpoints are already sorted in ascending order by id
+	TBreakEntry entry;
+	entry.iBreakId = (TUint32)info.iBreakId;
+	TInt index = iBreakPointList.FindInSignedKeyOrder(entry);
+	
+	if (index >=0)
+		{
+		// get the thread id for this breakpoint
+		TUint64 threadId = iBreakPointList[index].iId;
+
+		err = Kern::ThreadRawWrite(iChannel->iClientThread,(TUint8*)info.iId,&threadId,sizeof(TUint64));
+		if (err != KErrNone)
+			{
+			LOG_MSG("D_RMD_Breakpoints::priv_DoBreakInfo() - failed to return breakpoint iThreadId information");
+			return err;
+			}
+
+		// get the threadSpecific-ness
+		TBool threadSpecific = iBreakPointList[index].iThreadSpecific;
+
+		err = Kern::ThreadRawWrite(iChannel->iClientThread,(TUint8*)info.iThreadSpecific,&threadSpecific,sizeof(TBool));
+		if (err != KErrNone)
+			{
+			LOG_MSG("D_RMD_Breakpoints::priv_DoBreakInfo() - failed to return thread specific information");
+			return err;
+			}
+
+
+		// get the address
+		TUint32 address = iBreakPointList[index].iAddress;
+
+		err = Kern::ThreadRawWrite(iChannel->iClientThread,(TUint8*)info.iAddress,&address,sizeof(TUint32));
+		if (err != KErrNone)
+			{
+			LOG_MSG("D_RMD_Breakpoints::priv_DoBreakInfo() - failed to return breakpoint iAddress information");
+			return err;
+			}
+
+
+		// get the architecture
+		TArchitectureMode mode = iBreakPointList[index].iMode;
+
+		err = Kern::ThreadRawWrite(iChannel->iClientThread,(TUint8*)info.iMode,&mode,sizeof(TUint32));
+		if (err != KErrNone)
+			{
+			LOG_MSG("D_RMD_Breakpoints::priv_DoBreakInfo() - failed to return breakpoint iMode information");
+			return err;
+			}
+
+		return err;
+		}
+
+	LOG_MSG2("D_RMD_Breakpoints::priv_DoBreakInfo - Could not find the breakpoint id specified 0x%08x", entry.iBreakId);
+	return KErrNotFound;
+	}
+
+/**
+Public member function which clears all the breakpoints in the system. Generally used for shutting down
+the debug device driver.
+
+Note 1:
+This function ensures exclusive access to the breakpoint data structures
+by using a semaphore to serialise access.
+
+@see priv_ClearAllBreakPoints
+
+Note 2:
+As implied by Note 1, the caller must have previously called Init() or this
+function will return KErrNotReady;
+*/
+void D_RMD_Breakpoints::ClearAllBreakPoints()
+	{
+	// Ensure we have a valid semaphore
+	if (!iInitialised || !iLock)
+		{
+		return;
+		}
+
+	// Acquire the lock
+	NKern::ThreadEnterCS();
+	Kern::SemaphoreWait(*iLock);
+
+	// Really do the work
+	priv_ClearAllBreakPoints();
+	
+	// Release the lock
+	Kern::SemaphoreSignal(*iLock);
+	NKern::ThreadLeaveCS();
+	}
+
+/**
+Private member function which clears all the breakpoints in the system. Generally used for shutting down
+the debug device driver. 
+
+@see DoClearAllBreakPoints
+*/
+void D_RMD_Breakpoints::priv_ClearAllBreakPoints()
+	{
+	LOG_MSG("D_RMD_Breakpoints::priv_ClearAllBreakPoints()");
+
+	TInt err = KErrNone;
+	NKern::ThreadEnterCS();
+	for (TInt i=0; i<iBreakPointList.Count(); i++)
+		{
+		if ((iBreakPointList[i].iAddress != 0) && !iBreakPointList[i].iObsoleteLibraryBreakpoint)
+			{
+			TUint32 id = iBreakPointList[i].iId + (iBreakPointList[i].iThreadSpecific ? 0 : 1);
+	        LOG_MSG5(" Will try to clear breakpoint[%d] at address 0x%x, iId=0x%016lx, thrdSpec=%d", 
+	                i, iBreakPointList[i].iAddress, iBreakPointList[i].iId, iBreakPointList[i].iThreadSpecific);
+
+			DThread *threadObj = DebugUtils::OpenThreadHandle(id);
+			if (threadObj)
+				{
+				XTRAPD(r, XT_DEFAULT, err = DebugSupport::RestoreCode(threadObj, iBreakPointList[i].iAddress));
+				err = (KErrNone == r) ? err : r;
+				threadObj->Close(NULL);
+				}
+			else
+				{
+                LOG_MSG(" OpenThreadHandle returned NULL handle");
+				err = KErrBadHandle;
+				}
+
+			if (KErrNone != err)
+				{
+				LOG_MSG2("D_RMD_Breakpoints::priv_ClearAllBreakPoints() - Error 0x%08x while clearing breakpoint", err);
+				}
+			}
+		else if(iBreakPointList[i].iAddress == 0)
+		    {
+            LOG_MSG3("Breakpoint[%d]: address is 0, iId=0x%016lx", i, iBreakPointList[i].iId );		
+		    }
+		else
+		    {
+            LOG_MSG4("Breakpoint[%d]: Obsoleted, address =0x%x, iId=0x%016lx", i, iBreakPointList[i].iAddress, iBreakPointList[i].iId );     
+		    }
+		}
+	NKern::ThreadLeaveCS();
+
+	iBreakPointList.Reset();
+	}
+
+/**
+Public member function which disables the breakpoint at the specified address.
+
+Note 1:
+This function ensures exclusive access to the breakpoint data structures
+by using a semaphore to serialise access.
+
+@see priv_DisableBreakAtAddress
+
+Note 2:
+As implied by Note 1, the caller must have previously called Init() or this
+function will return KErrNotReady;
+
+@param aAddress Address at which to disable breakpoints (all threads)
+@return KErrNone if successful, one of the other system wide error codes otherwise.
+*/
+TInt D_RMD_Breakpoints::DisableBreakAtAddress(TUint32 aAddress)
+	{
+	// Ensure we have a valid semaphore
+	if (!iInitialised || !iLock)
+		{
+		return KErrNotReady;
+		}
+
+	// Acquire the lock
+	NKern::ThreadEnterCS();
+	Kern::SemaphoreWait(*iLock);
+
+	// Really do the work
+	TInt err = priv_DisableBreakAtAddress(aAddress);
+	
+	// Release the lock
+	Kern::SemaphoreSignal(*iLock);
+	NKern::ThreadLeaveCS();
+
+	return err;
+	}
+
+/**
+Private member function which clears all the breakpoints in the system. Generally used for shutting down
+the debug device driver. 
+
+@see DisableBreakAtAddress
+
+@param aAddress clears the breakpoint at the specified address
+@return KErrNone if successful, one of the other system wide error codes otherwise.
+*/
+TInt D_RMD_Breakpoints::priv_DisableBreakAtAddress(TUint32 aAddress)
+	{
+	LOG_MSG2("D_RMD_Breakpoints::priv_DisableBreakAtAddress(aAddress=0x%x)", aAddress);
+
+	TInt err = KErrNone;
+
+	for (TInt i = NUMBER_OF_TEMP_BREAKPOINTS; i < iBreakPointList.Count(); i++)
+		{
+		if (iBreakPointList[i].iAddress == aAddress)
+			{
+			iBreakPointList[i].iDisabledForStep = ETrue;
+			LOG_MSG2("D_RMD_Breakpoints::priv_DisableBreakAtAddress - Disabling breakpoint at address 0x%x", iBreakPointList[i].iAddress);
+
+			//clear the breakpoint with code modifier
+			//code modifier will restore the org instruction and also frees the shadow page if necessary
+			TUint64 id = iBreakPointList[i].iId + (iBreakPointList[i].iThreadSpecific ? 0 : 1);
+			DThread* threadObj = NULL;
+			NKern::ThreadEnterCS();
+			if(iBreakPointList[i].iThreadSpecific)
+				{
+				threadObj = DebugUtils::OpenThreadHandle(id);
+				}
+			else
+				{
+				DProcess* process = DebugUtils::OpenProcessHandle(iBreakPointList[i].iId);
+				if(process)
+					{
+					threadObj = DebugUtils::OpenFirstThreadForProcess(process);
+					process->Close(NULL);
+					}
+				}
+
+			if (threadObj)
+				{
+				XTRAPD(r, XT_DEFAULT, err = DebugSupport::RestoreCode(threadObj, aAddress));			
+				if(KErrNone != err || KErrNone != r)
+					{
+					LOG_MSG3("Error from DebugSupport::RestoreCode: r: %d, err: %d", r, err);
+					}
+				err = (KErrNone == r) ? err : r;
+				threadObj->Close(NULL);
+				}
+			else
+				{
+				err = KErrBadHandle;
+				LOG_MSG2("Couldn't find thread for breakpoint id %d", iBreakPointList[i].iId);
+				}
+			NKern::ThreadLeaveCS();
+			if (err) break;
+			}
+		}
+		
+	return err;
+	}
+
+/**
+Public member function which enables previously disabled breakpoints within a given thread.
+
+Note 1:
+This function ensures exclusive access to the breakpoint data structures
+by using a semaphore to serialise access. 
+
+@see priv_DoEnableDisabledBreak
+
+Note 2:
+As implied by Note 1, the caller must have previously called Init() or this
+function will return KErrNotReady;
+
+@param aThreadId Thread in which to enable all previously disabled breakpoints
+@return KErrNone if successful, one of the system wide error codes otherwise.
+*/
+TInt D_RMD_Breakpoints::DoEnableDisabledBreak(TUint64 aThreadId)
+	{
+	// Ensure we have a valid semaphore
+	if (!iInitialised || !iLock)
+		{
+		return KErrNotReady;
+		}
+
+	// Acquire the lock
+	NKern::ThreadEnterCS();
+	Kern::SemaphoreWait(*iLock);
+
+	// Really do the work
+	TInt err = priv_DoEnableDisabledBreak(aThreadId);
+	
+	// Release the lock
+	Kern::SemaphoreSignal(*iLock);
+	NKern::ThreadLeaveCS();
+
+	return err;
+	}
+
+/**
+Private member function which enables previously disabled breakpoints within a given thread.
+
+@see DoEnableDisabledBreak
+
+@param aThreadId Thread in which to enable all previously disabled breakpoints
+@return KErrNone if successful, one of the system wide error codes otherwise.
+*/
+TInt D_RMD_Breakpoints::priv_DoEnableDisabledBreak(TUint64 aThreadId)
+	{
+	LOG_MSG("D_RMD_Breakpoints::priv_DoEnableDisabledBreak()");
+	NKern::ThreadEnterCS();
+	DThread* thread = DebugUtils::OpenThreadHandle(aThreadId);
+	if(!thread)
+		{
+		LOG_MSG2("Thread: 0x%08x does not exist", aThreadId);
+		NKern::ThreadLeaveCS();
+		return KErrNotFound;
+		}
+	TUint64 processId = thread->iOwningProcess->iId;
+	thread->Close(NULL);
+	NKern::ThreadLeaveCS();
+
+	for (TInt i = NUMBER_OF_TEMP_BREAKPOINTS; i < iBreakPointList.Count(); i++)
+		{
+		TBool needsEnabling = EFalse;
+		if(iBreakPointList[i].iDisabledForStep)
+			{
+			if(iBreakPointList[i].iThreadSpecific)
+				{
+				needsEnabling = (aThreadId == iBreakPointList[i].iId);
+				}
+			else
+				{
+				needsEnabling = (processId == iBreakPointList[i].iId);
+				}
+			}
+		if (needsEnabling)
+			{
+			LOG_MSG2("Re-enabling breakpoint at address %x", iBreakPointList[i].iAddress);
+			TInt err = priv_DoEnableBreak(iBreakPointList[i], EFalse);
+			if(KErrNone != err)
+				{
+				LOG_MSG2("Error returned from DoEnableBreak: %d", err);
+				iBreakPointList[i].iDisabledForStep = EFalse;
+				return err;
+				}
+			}
+		}
+	
+	return KErrNone;
+	}
+
+/**
+Public member function which removes all the breakpoints within a given thread.
+
+Note 1:
+This function ensures exclusive access to the breakpoint data structures
+by using a semaphore to serialise access.
+
+@see priv_DoRemoveThreadBreaks
+
+Note 2:
+As implied by Note 1, the caller must have previously called Init() or this
+function will return KErrNotReady;
+
+@param aThreadId Thread from which to remove all existing breakpoints
+@return KErrNone if successful, one of the system wide error codes otherwise.
+*/
+void D_RMD_Breakpoints::DoRemoveThreadBreaks(TUint64 aThreadId)
+	{
+	// Ensure we have a valid semaphore
+	if (!iInitialised || !iLock)
+		{
+		return;
+		}
+
+	// Acquire the lock
+	NKern::ThreadEnterCS();
+	Kern::SemaphoreWait(*iLock);
+
+	// Really do the work
+	priv_DoRemoveThreadBreaks(aThreadId);
+
+	// Release the lock
+	Kern::SemaphoreSignal(*iLock);
+	NKern::ThreadLeaveCS();
+	}
+
+/**
+Private member function which removes all the breakpoints particular to a particular thread
+
+@see DoRemoveThreadBreaks
+
+@param aThreadId Thread from which to remove all existing breakpoints
+@return KErrNone if successful, one of the system wide error codes otherwise.
+*/
+void D_RMD_Breakpoints::priv_DoRemoveThreadBreaks(TUint64 aThreadId)
+	{
+	LOG_MSG2("D_RMD_Breakpoints::priv_DoRemoveThreadBreaks(aThreadId = 0x%lx)\n",aThreadId);
+
+	TInt err = KErrNone;
+	TUint64 threadId;
+
+	for (TInt i=iBreakPointList.Count()-1; i >= 0; i--)
+		{
+		if ((iBreakPointList[i].iAddress != 0) && !iBreakPointList[i].iObsoleteLibraryBreakpoint)
+			{
+			threadId = iBreakPointList[i].iId + (iBreakPointList[i].iThreadSpecific ? 0 : 1);
+			if (threadId == aThreadId)
+				{
+				LOG_MSG5("D_RMD_Breakpoints::priv_DoRemoveThreadBreaks() - Clearing breakpoint[%d],idx=%x at address 0x%08x, iId=0x%016lx", 
+				        i, iBreakPointList[i].iBreakId, iBreakPointList[i].iAddress, iBreakPointList[i].iId );
+
+				err = priv_DoClearBreak(iBreakPointList[i].iBreakId, EFalse);
+
+				if (err != KErrNone)
+					{
+					LOG_MSG2("D_RMD_Breakpoints::priv_DoRemoveThreadBreaks()  - failed to remove break id 0x%08x\n",iBreakPointList[i].iBreakId);
+					return;
+					}
+				}
+			}
+        else if(iBreakPointList[i].iAddress == 0)
+            {
+            LOG_MSG3("Breakpoint[%d]: address is 0, iId=0x%016lx", i, iBreakPointList[i].iId );     
+            }
+        else
+            {
+            LOG_MSG4("Breakpoint[%d]: Obsoleted, address =0x%x, iId=0x%016lx", i, iBreakPointList[i].iAddress, iBreakPointList[i].iId );     
+            }		
+		}	
+	}
+
+// Remove the process breakpoints for process with PID aProcessId in the range [aCodeAddress, aCodeAddress + aCodeSize)
+void D_RMD_Breakpoints::RemoveBreaksForProcess(TUint64 aProcessId, TUint32 aCodeAddress, TUint32 aCodeSize)
+	{
+	LOG_MSG4("D_RMD_Breakpoints::RemoveBreaksForProcess(), aProcId=0x%016lx, codeAddr=0x%x, codeSize=0x%x", 
+	        aProcessId,aCodeAddress, aCodeSize);
+	NKern::ThreadEnterCS();
+	for (TInt i=iBreakPointList.Count() - 1; i>=0; i--)
+		{
+        TBool remove = EFalse;
+		TBreakEntry& breakEntry = iBreakPointList[i];
+		
+		if( breakEntry.iId == 0 || breakEntry.iAddress == 0 )
+		    {
+            breakEntry.Reset();
+		    continue;
+		    }
+		
+		LOG_MSG5(" break[%d], iId=0x%016lx, threadSpec=%d, aProcessId=0x%016lx", 
+		        i, breakEntry.iId, breakEntry.iThreadSpecific, aProcessId);
+		
+		if(!breakEntry.iThreadSpecific && breakEntry.iId == aProcessId)
+		    {
+		    remove = ETrue;
+		    }
+		else if(breakEntry.iThreadSpecific)
+		    {
+            //breakEntry.iId is thread id. Get its pid, then check if aProcessId is same, then remove
+            DThread* thread = DebugUtils::OpenThreadHandle(breakEntry.iId);
+            if(!thread)
+                {
+                LOG_MSG2("Could not open handle to thread (aThreadId = 0x%016lx)",breakEntry.iId);
+                continue;
+                }
+            
+            LOG_MSG2(" thread->iOwningProcess->iId=0x%016lx", thread->iOwningProcess->iId );
+            
+            if( thread->iOwningProcess->iId == aProcessId )
+                {
+                LOG_MSG3("Thread spec breakpoint @ index[%d] matches aProcessId= 0x%016lx. Removing",i, aProcessId);
+                remove = ETrue;
+                }
+            
+            thread->Close(NULL);
+		    }
+		    
+        if ( remove && (breakEntry.iAddress >= aCodeAddress) && (breakEntry.iAddress < (aCodeAddress + aCodeSize)))
+            {
+            LOG_MSG2("Removing process breakpoint at address %x", (TUint32)breakEntry.iAddress);
+            TInt err = DoClearBreak(breakEntry.iBreakId, ETrue);
+            if(KErrNone != err)
+                {
+                LOG_MSG2("Error removing breakpoint: %d", err);
+                }
+            }
+        else
+            {
+            LOG_MSG4("Not removing breakpoint at index[%d], id=0x%016lx, address=0x%x", 
+                    i, breakEntry.iId, (TUint32)breakEntry.iAddress);
+            }
+		}
+	NKern::ThreadLeaveCS();
+	}
+
+// mark the breakpoints in the range [aCodeAddress, aCodeAddress + aCodeSize)
+void D_RMD_Breakpoints::InvalidateLibraryBreakPoints(TUint32 aCodeAddress, TUint32 aCodeSize)
+	{
+	LOG_MSG3("D_RMD_Breakpoints::InvalidateLibraryBreakPoints(aCodeAddress=0x%x, aCodeSize=0x%x)",
+	        aCodeAddress, aCodeSize );
+	
+	for (TInt i=0; i<iBreakPointList.Count(); i++)
+		{
+		if ((iBreakPointList[i].iAddress >= aCodeAddress) && (iBreakPointList[i].iAddress < (aCodeAddress + aCodeSize)))
+			{
+			LOG_MSG2("Obsoleting library breakpoint at address %x", iBreakPointList[i].iAddress);
+			iBreakPointList[i].iObsoleteLibraryBreakpoint = ETrue;
+			}
+		}
+	}
+
+TInt D_RMD_Breakpoints::BreakPointCount() const
+	{
+	return iBreakPointList.Count();
+	}
+
+/**
+  Gets next breakpoint in list.
+  @param aBreakEntry The break entry to get the successor of. If NULL then returns the first entry.
+  @return A pointer to the next break entry, or NULL if the end of the list has been reached
+  */
+TBreakEntry* D_RMD_Breakpoints::GetNextBreak(const TBreakEntry* aBreakEntry) const
+	{
+	if(!aBreakEntry)
+		{
+		return (TBreakEntry*)&(iBreakPointList[0]);
+		}
+	TInt index = iBreakPointList.FindInSignedKeyOrder(*aBreakEntry) + 1;
+	return (index < BreakPointCount()) ? (TBreakEntry*)&(iBreakPointList[index]) : NULL;
+	}
+
+TBool D_RMD_Breakpoints::IsTemporaryBreak(const TBreakEntry& aBreakEntry) const
+	{
+	// Ensure we have a valid semaphore
+	if (!iInitialised || !iLock)
+		{
+		return EFalse;
+		}
+
+	// Acquire the lock
+	NKern::ThreadEnterCS();
+	Kern::SemaphoreWait(*iLock);
+
+	// Really do the work
+	TBool tempBreak = priv_IsTemporaryBreak(aBreakEntry);
+	
+	// Release the lock
+	Kern::SemaphoreSignal(*iLock);
+	NKern::ThreadLeaveCS();
+	
+	return tempBreak;
+	}
+
+/**
+Private member function which tells us if a breakpoint is temporary
+
+@see IsTemporaryBreak
+
+@param aBreakEntry
+@return TBool indicating if the break is temporary or not
+*/
+TBool D_RMD_Breakpoints::priv_IsTemporaryBreak(const TBreakEntry& aBreakEntry) const 
+	{
+	return aBreakEntry.iBreakId < NUMBER_OF_TEMP_BREAKPOINTS;
+	}
+
+
+// End of file - d_rmd_breakpoints.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/debugsrv/runmodedebug/rmdriver/src/d_rmd_stepping.cpp	Fri Aug 27 11:37:29 2010 +0300
@@ -0,0 +1,1884 @@
+// Copyright (c) 2004-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+// This file contains stepping code refactored from rm_debug_kerneldriver.cpp/rm_debug_kerneldriver.h
+//
+
+#include <e32def.h>
+#include <e32def_private.h>
+#include <e32cmn.h>
+#include <e32cmn_private.h>
+#include <kernel/kernel.h> 
+#include <kernel/kern_priv.h>
+#include <nk_trace.h>
+#include <arm.h>
+#include <rm_debug_api.h>
+
+#include "d_rmd_stepping.h"
+#include "d_rmd_breakpoints.h"
+#include "rm_debug_kerneldriver.h"	// needed to access DRM_DebugChannel
+#include "rm_debug_driver.h"
+#include "debug_logging.h"
+
+using namespace Debug;
+
+//
+// DRMDStepping::DRMDStepping
+//
+DRMDStepping::DRMDStepping(DRM_DebugChannel* aChannel)
+:
+	iChannel(aChannel)
+	{
+	// to do
+	}
+
+//
+// DRMDStepping::~DRM_DebugChannel
+//
+DRMDStepping::~DRMDStepping()
+	{
+	// to do
+	}
+
+//
+// DRMDStepping::IsExecuted
+//
+TBool DRMDStepping::IsExecuted(TUint8 aCondition ,TUint32 aStatusRegister)
+	{
+	LOG_MSG("DRMDStepping::IsExecuted()");
+
+	TBool N = ((aStatusRegister >> 28) & 0x0000000F) & 0x00000008;
+	TBool Z = ((aStatusRegister >> 28) & 0x0000000F) & 0x00000004;
+	TBool C = ((aStatusRegister >> 28) & 0x0000000F) & 0x00000002;
+	TBool V = ((aStatusRegister >> 28) & 0x0000000F) & 0x00000001;
+
+	switch(aCondition)
+		{
+		case 0:
+			return Z;
+		case 1:
+			return !Z;
+		case 2:
+			return C;
+		case 3:
+			return !C;
+		case 4:
+			return N;
+		case 5:
+			return !N;
+		case 6:
+			return V;
+		case 7:
+			return !V;
+		case 8:
+			return (C && !Z);
+		case 9:
+			return (!C || Z);
+		case 10:
+			return (N == V);
+		case 11:
+			return (N != V);
+		case 12:
+			return ((N == V) && !Z);
+		case 13:
+			return (Z || (N != V));
+		case 14:
+		case 15:
+			return ETrue;
+		}
+	
+	return EFalse;
+	}
+
+//
+// DRMDStepping::IsPreviousInstructionMovePCToLR
+//
+TBool DRMDStepping::IsPreviousInstructionMovePCToLR(DThread *aThread)
+	{
+	LOG_MSG("DRMDStepping::IsPreviousInstructionMovePCToLR()");
+
+	TInt err = KErrNone;
+	
+	// there are several types of instructions that modify the PC that aren't
+	// designated as linked or non linked branches.  the way gcc generates the
+	// code can tell us whether or not these instructions are to be treated as
+	// linked branches.  the main cases are bx and any type of mov or load or
+	// arithmatic operation that changes the PC.  if these are really just
+	// function calls that will return, gcc will generate a mov	lr, pc
+	// instruction as the previous instruction.  note that this is just for arm
+	// and armi
+	
+	// get the address of the previous instruction
+	TUint32 address = 0;
+	err = iChannel->ReadKernelRegisterValue(aThread, PC_REGISTER, address);
+	if(err != KErrNone)
+		{
+		LOG_MSG2("Non-zero error code discarded: %d", err);
+		}
+	address -= 4;
+
+	TBuf8<4> previousInstruction;
+	err = iChannel->DoReadMemory(aThread, address, 4, previousInstruction);
+	if (KErrNone != err)
+		{
+		LOG_MSG2("Error %d reading memory at address %x", address);
+		return EFalse;
+		}
+
+	const TUint32 movePCToLRIgnoringCondition = 0x01A0E00F;
+
+	TUint32 inst = *(TUint32 *)previousInstruction.Ptr();
+	
+	if ((inst & 0x0FFFFFFF) == movePCToLRIgnoringCondition)
+		{
+		return ETrue;
+		}
+		
+	return EFalse;
+	}
+
+//
+// DRMDStepping::DecodeDataProcessingInstruction
+//
+void DRMDStepping::DecodeDataProcessingInstruction(TUint8 aOpcode, TUint32 aOp1, TUint32 aOp2, TUint32 aStatusRegister, TUint32 &aBreakAddress)
+	{
+	LOG_MSG("DRMDStepping::DecodeDataProcessingInstruction()");
+
+	switch(aOpcode)
+		{
+		case 0:
+			{
+			// AND
+			aBreakAddress = aOp1 & aOp2;
+			break;
+			}
+		case 1:
+			{
+			// EOR
+			aBreakAddress = aOp1 ^ aOp2;
+			break;
+			}
+		case 2:
+			{
+			// SUB
+			aBreakAddress = aOp1 - aOp2;
+			break;
+			}
+		case 3:
+			{
+			// RSB
+			aBreakAddress = aOp2 - aOp1;
+			break;
+			}
+		case 4:
+			{
+			// ADD
+			aBreakAddress = aOp1 + aOp2;
+			break;
+			}
+		case 5:
+			{
+			// ADC
+			aBreakAddress = aOp1 + aOp2 + (aStatusRegister & arm_carry_bit()) ? 1 : 0;
+			break;
+			}
+		case 6:
+			{
+			// SBC
+			aBreakAddress = aOp1 - aOp2 - (aStatusRegister & arm_carry_bit()) ? 0 : 1;
+			break;
+			}
+		case 7:
+			{
+			// RSC
+			aBreakAddress = aOp2 - aOp1 - (aStatusRegister & arm_carry_bit()) ? 0 : 1;
+			break;
+			}
+		case 12:
+			{
+			// ORR
+			aBreakAddress = aOp1 | aOp2;
+			break;
+			}
+		case 13:
+			{
+			// MOV
+			aBreakAddress = aOp2;
+			break;
+			}
+		case 14:
+			{
+			// BIC
+			aBreakAddress = aOp1 & ~aOp2;
+			break;
+			}
+		case 15:
+			{
+			// MVN
+			aBreakAddress = ~aOp2;
+			break;
+			}
+		}
+	}
+
+//
+// DRMDStepping::CurrentInstruction
+//
+// Returns the current instruction bitpattern (either 32-bits or 16-bits) if possible
+TInt DRMDStepping::CurrentInstruction(DThread* aThread, TUint32& aInstruction)
+	{
+	LOG_MSG("DRMDStepping::CurrentInstruction");
+
+	// What is the current PC?
+	TUint32 pc;	
+	ReturnIfError(CurrentPC(aThread,pc));
+
+	// Read it one byte at a time to ensure alignment doesn't matter
+	TUint32 inst = 0;
+	for(TInt i=3;i>=0;i--)
+		{
+
+		TBuf8<1> instruction;
+		TInt err = iChannel->DoReadMemory(aThread, (pc+i), 1, instruction); 
+		if (KErrNone != err)
+			{
+			LOG_MSG2("DRMDStepping::CurrentInstruction : Failed to read memory at current PC: return 0x%08x",pc);
+			return err;
+			}
+
+		inst = (inst << 8) | (*(TUint8 *)instruction.Ptr());
+		}
+
+	aInstruction = inst;
+
+	LOG_MSG2("DRMDStepping::CurrentInstruction 0x%08x", aInstruction);
+
+	return KErrNone;
+	}
+
+//
+// DRMDStepping::CurrentArchMode
+//
+// Determines architecture mode from the supplied cpsr
+TInt DRMDStepping::CurrentArchMode(const TUint32 aCpsr, Debug::TArchitectureMode& aMode)
+	{
+// Thumb2 work will depend on having a suitable cpu architecture to compile for...
+#ifdef ECpuJf
+	// State table as per ARM ARM DDI0406A, section A.2.5.1
+	if(aCpsr & ECpuJf)
+		{
+		if (aCpsr & ECpuThumb)
+			{
+			// ThumbEE (Thumb2)
+			aMode = Debug::EThumb2EEMode;
+			}
+		else
+			{
+			// Jazelle mode - not supported
+			return KErrNotSupported;
+			}
+		}
+	else
+#endif
+		{
+		if (aCpsr & ECpuThumb)
+			{
+			// Thumb mode
+			aMode = Debug::EThumbMode;
+			}
+		else
+			{
+			// ARM mode
+			aMode = Debug::EArmMode;
+			}
+		}
+
+	return KErrNone;
+	}
+
+//
+// DRMDStepping::PCAfterInstructionExecutes
+//
+// Note, this function pretty much ignores all the arguments except for aThread.
+// The arguments continue to exist so that the function has the same prototype as
+// the original from Nokia. In the long term this function will be re-factored
+// to remove obsolete parameters.
+//
+TUint32 DRMDStepping::PCAfterInstructionExecutes(DThread *aThread, TUint32 aCurrentPC, TUint32 aStatusRegister, TInt aInstSize, /*TBool aStepInto,*/ TUint32 &aNewRangeEnd, TBool &aChangingModes)
+	{
+	LOG_MSG("DRMDStepping::PCAfterInstructionExecutes()");
+
+	// by default we will set the breakpoint at the next instruction
+	TUint32 breakAddress = aCurrentPC + aInstSize;
+
+	TInt err = KErrNone;
+
+	// determine the architecture
+	TUint32 cpuid;
+	asm("mrc p15, 0, cpuid, c0, c0, 0 ");
+	LOG_MSG2("DRMDStepping::PCAfterInstructionExecutes() - cpuid = 0x%08x\n",cpuid);
+
+	cpuid >>= 8;
+	cpuid &= 0xFF;
+
+	// determine the architecture mode for the current instruction
+	TArchitectureMode mode = EArmMode;	// Default assumption is ARM 
+
+	// Now we must examine the CPSR to read the T and J bits. See ARM ARM DDI0406A, section B1.3.3
+	TUint32 cpsr;
+
+	ReturnIfError(CurrentCPSR(aThread,cpsr));
+	LOG_MSG2("DRMDStepping::PCAfterInstructionExecutes() - cpsr = 0x%08x\n",cpsr);
+
+	// Determine the mode
+	ReturnIfError(CurrentArchMode(cpsr,mode));
+
+	// Decode instruction based on current CPU mode
+	switch(mode)
+		{
+		case Debug::EArmMode:
+			{
+			// Obtain the current instruction bit pattern
+			TUint32 inst;
+			ReturnIfError(CurrentInstruction(aThread,inst));
+			
+			LOG_MSG2("Current instruction: %x", inst);
+
+			// check the conditions to see if this will actually get executed
+			if (IsExecuted(((inst>>28) & 0x0000000F), aStatusRegister)) 
+				{
+				switch(arm_opcode(inst)) // bits 27-25
+					{
+					case 0:
+						{
+						switch((inst & 0x00000010) >> 4) // bit 4
+							{
+							case 0:
+								{
+								switch((inst & 0x01800000) >> 23) // bits 24-23
+									{
+									case 2:
+										{
+										// move to/from status register.  pc updates not allowed
+										// or TST, TEQ, CMP, CMN which don't modify the PC
+										break;
+										}
+									default:
+										{
+										// Data processing immediate shift
+										if (arm_rd(inst) == PC_REGISTER)
+											{
+											TUint32 rn = aCurrentPC + 8;
+											if (arm_rn(inst) != PC_REGISTER) // bits 19-16
+												{
+												err = iChannel->ReadKernelRegisterValue(aThread, arm_rn(inst), rn);
+												if(err != KErrNone)
+													{
+													LOG_MSG2("Non-zero error code discarded: %d", err);
+													}
+												}
+
+											TUint32 shifter = ShiftedRegValue(aThread, inst, aCurrentPC, aStatusRegister);
+
+											DecodeDataProcessingInstruction(((inst & 0x01E00000) >> 21), rn, shifter, aStatusRegister, breakAddress);
+											}
+										break;
+										}
+									}
+								break;
+								}
+							case 1:
+								{
+								switch((inst & 0x00000080) >> 7) // bit 7
+									{
+									case 0:
+										{
+										switch((inst & 0x01900000) >> 20) // bits 24-23 and bit 20
+											{
+											case 0x10:
+												{
+												// from figure 3-3
+												switch((inst & 0x000000F0) >> 4) // bits 7-4
+													{
+													case 1:
+														{
+														if (((inst & 0x00400000) >> 22) == 0) // bit 22
+															{
+															// BX
+															// this is a strange case.  normally this is used in the epilogue to branch the the link
+															// register.  sometimes it is used to call a function, and the LR is stored in the previous
+															// instruction.  since what we want to do is different for the two cases when stepping over,
+															// we need to read the previous instruction to see what we should do
+															err = iChannel->ReadKernelRegisterValue(aThread, (inst & 0x0000000F), breakAddress);
+															if(err != KErrNone)
+																{
+																LOG_MSG2("Non-zero error code discarded: %d", err);
+																}
+
+															if ((breakAddress & 0x00000001) == 1)
+																{
+																aChangingModes = ETrue;
+																}
+
+															breakAddress &= 0xFFFFFFFE;
+															}
+														break;
+														}
+													case 3:
+														{
+														// BLX
+															{
+															err = iChannel->ReadKernelRegisterValue(aThread, (inst & 0x0000000F), breakAddress);
+															if(err != KErrNone)
+																{
+																LOG_MSG2("Non-zero error code discarded: %d", err);
+																}
+
+															if ((breakAddress & 0x00000001) == 1)
+																{
+																aChangingModes = ETrue;
+																}
+															
+															breakAddress &= 0xFFFFFFFE;
+															}
+														break;
+														}
+													default:
+														{
+														// either doesn't modify the PC or it is illegal to
+														break;
+														}
+													}
+												break;
+												}
+											default:
+												{
+												// Data processing register shift
+												if (((inst & 0x01800000) >> 23) == 2) // bits 24-23
+													{
+													// TST, TEQ, CMP, CMN don't modify the PC
+													}
+												else if (arm_rd(inst) == PC_REGISTER)
+													{
+													// destination register is the PC
+													TUint32 rn = aCurrentPC + 8;
+													if (arm_rn(inst) != PC_REGISTER) // bits 19-16
+														{
+														err = iChannel->ReadKernelRegisterValue(aThread, arm_rn(inst), rn);
+														if(err != KErrNone)
+															{
+															LOG_MSG2("Non-zero error code discarded: %d", err);
+															}
+														}
+													
+													TUint32 shifter = ShiftedRegValue(aThread, inst, aCurrentPC, aStatusRegister);
+													
+													DecodeDataProcessingInstruction(((inst & 0x01E00000) >> 21), rn, shifter, aStatusRegister, breakAddress);
+													}
+												break;
+												}
+											}
+										break;
+										}
+									default:
+										{
+										// from figure 3-2, updates to the PC illegal
+										break;
+										}
+									}
+								break;
+								}
+							}
+						break;
+						}
+					case 1:
+						{
+						if (((inst & 0x01800000) >> 23) == 2) // bits 24-23
+							{
+							// cannot modify the PC
+							break;
+							}
+						else if (arm_rd(inst) == PC_REGISTER)
+							{
+							// destination register is the PC
+							TUint32 rn;
+							err = iChannel->ReadKernelRegisterValue(aThread, arm_rn(inst), rn); // bits 19-16
+							if(err != KErrNone)
+								{
+								LOG_MSG2("Non-zero error code discarded: %d", err);
+								}
+							TUint32 shifter = ((arm_data_imm(inst) >> arm_data_rot(inst)) | (arm_data_imm(inst) << (32 - arm_data_rot(inst)))) & 0xffffffff;
+
+							DecodeDataProcessingInstruction(((inst & 0x01E00000) >> 21), rn, shifter, aStatusRegister, breakAddress);
+							}
+						break;
+						}
+					case 2:
+						{
+						// load/store immediate offset
+						if (arm_load(inst)) // bit 20
+							{
+							// loading a register from memory
+							if (arm_rd(inst) == PC_REGISTER)
+								{
+								// loading the PC register
+								TUint32 base;
+								err = iChannel->ReadKernelRegisterValue(aThread, arm_rn(inst), base);
+								if(err != KErrNone)
+									{
+									LOG_MSG2("Non-zero error code discarded: %d", err);
+									}
+
+								/* Note: At runtime the PC would be 8 further on
+								 */
+								if (arm_rn(inst) == PC_REGISTER)
+									{
+									base = aCurrentPC + 8;
+									}
+
+								TUint32 offset = 0;
+
+								if (arm_single_pre(inst))
+									{
+									// Pre-indexing
+									offset = arm_single_imm(inst);
+
+									if (arm_single_u(inst))
+										{
+										base += offset;
+										}
+									else
+										{
+										base -= offset;
+										}
+									}
+
+								TBuf8<4> destination;
+								err = iChannel->DoReadMemory(aThread, base, 4, destination);
+								
+								if (KErrNone == err)
+									{
+									breakAddress = *(TUint32 *)destination.Ptr();
+
+									if ((breakAddress & 0x00000001) == 1)
+										{
+										aChangingModes = ETrue;
+										}
+									breakAddress &= 0xFFFFFFFE;
+									}
+								else
+									{
+									LOG_MSG("Error reading memory in decoding step instruction");
+									}
+								}
+							}
+						break;
+						}
+					case 3:
+						{
+						if (((inst & 0xF0000000) != 0xF0000000) && ((inst & 0x00000010) == 0))
+							{
+							// load/store register offset
+							if (arm_load(inst)) // bit 20
+								{
+								// loading a register from memory
+								if (arm_rd(inst) == PC_REGISTER)
+									{
+									// loading the PC register
+									TUint32 base = 0;
+									if(arm_rn(inst) == PC_REGISTER)
+										{
+										base = aCurrentPC + 8;
+										}
+									else
+										{
+										err = iChannel->ReadKernelRegisterValue(aThread, arm_rn(inst), base);
+										if(err != KErrNone)
+											{
+											LOG_MSG2("Non-zero error code discarded: %d", err);
+											}
+										}
+
+									TUint32 offset = 0;
+
+									if (arm_single_pre(inst))
+										{
+										offset = ShiftedRegValue(aThread, inst, aCurrentPC, aStatusRegister);
+
+										if (arm_single_u(inst))
+											{
+											base += offset;
+											}
+										else
+											{
+											base -= offset;
+											}
+										}
+
+									TBuf8<4> destination;
+									err = iChannel->DoReadMemory(aThread, base, 4, destination);
+
+									if (KErrNone == err)
+										{
+										breakAddress = *(TUint32 *)destination.Ptr();
+
+										if ((breakAddress & 0x00000001) == 1)
+											{
+											aChangingModes = ETrue;
+											}
+										breakAddress &= 0xFFFFFFFE;
+										}
+									else
+										{
+										LOG_MSG("Error reading memory in decoding step instruction");
+										}
+									}
+								}
+							}
+						break;
+						}
+					case 4:
+						{
+						if ((inst & 0xF0000000) != 0xF0000000)
+							{
+							// load/store multiple
+							if (arm_load(inst)) // bit 20
+								{
+								// loading a register from memory
+								if (((inst & 0x00008000) >> 15))
+									{
+									// loading the PC register
+									TInt offset = 0;	
+									if (arm_block_u(inst))
+										{
+										TUint32 reglist = arm_block_reglist(inst);
+										offset = iChannel->Bitcount(reglist) * 4 - 4;
+										if (arm_block_pre(inst))
+											offset += 4;
+										}
+									else if (arm_block_pre(inst))
+										{
+										offset = -4;
+										}
+
+									TUint32 temp = 0;
+									err = iChannel->ReadKernelRegisterValue(aThread, arm_rn(inst), temp);
+									if(err != KErrNone)
+										{
+										LOG_MSG2("Non-zero error code discarded: %d", err);
+										}
+
+									temp += offset;
+
+									TBuf8<4> destination;
+									err = iChannel->DoReadMemory(aThread, temp, 4, destination);
+
+									if (KErrNone == err)
+										{
+										breakAddress = *(TUint32 *)destination.Ptr();
+										if ((breakAddress & 0x00000001) == 1)
+											{
+											aChangingModes = ETrue;
+											}
+										breakAddress &= 0xFFFFFFFE;
+										}
+									else
+										{
+										LOG_MSG("Error reading memory in decoding step instruction");
+										}
+									}
+								}
+							}
+						break;
+						}
+					case 5:
+						{
+						if ((inst & 0xF0000000) == 0xF0000000)
+							{
+							// BLX
+							breakAddress = (TUint32)arm_instr_b_dest(inst, aCurrentPC);
+
+							// Unconditionally change into Thumb mode
+							aChangingModes = ETrue;
+							breakAddress &= 0xFFFFFFFE;
+							}
+						else
+							{
+							if ((inst & 0x01000000)) // bit 24
+								{
+								// BL
+									breakAddress = (TUint32)arm_instr_b_dest(inst, aCurrentPC);
+								}
+							else
+								{
+								// B
+								breakAddress = (TUint32)arm_instr_b_dest(inst, aCurrentPC);
+								}
+							}
+						break;
+						} // case 5
+					} //switch(arm_opcode(inst)) // bits 27-25
+				} // if (IsExecuted(((inst>>28) & 0x0000000F), aStatusRegister)) 
+			} // case Debug::EArmMode:
+		break;
+
+		case Debug::EThumbMode:
+			{
+			// Thumb Mode
+			//
+			// Notes: This now includes the extra code
+			// required to decode V6T2 instructions
+			
+			LOG_MSG("DRMDStepping::PCAfterInstructionExecutes: Thumb Instruction");
+
+			TUint16 inst;
+
+			// Obtain the current instruction bit pattern
+			TUint32 inst32;
+			ReturnIfError(CurrentInstruction(aThread,inst32));
+
+			inst = static_cast<TUint16>(inst32 & 0xFFFF);
+
+			LOG_MSG2("Current Thumb instruction: 0x%x", inst);
+
+			// v6T2 instructions
+
+			// Note: v6T2 decoding is only enabled for DEBUG builds or if using an
+			// an ARM_V6T2 supporting build system. At the time of writing, no
+			// ARM_V6T2 supporting build system exists, so the stepping code cannot
+			// be said to be known to work. Hence it is not run for release builds
+
+			TBool use_v6t2_decodings = EFalse;
+
+#if defined(DEBUG) || defined(__ARMV6T2__)
+			use_v6t2_decodings = ETrue;
+#endif
+			// coverity[dead_error_line]
+			if (use_v6t2_decodings)
+				{
+				// 16-bit encodings
+
+				// A6.2.5 Misc 16-bit instructions
+				// DONE Compare and branch on zero (page A8-66)
+				// If then hints
+
+				// ARM ARM DDI0406A - section A8.6.27 CBNZ, CBZ
+				//
+				// Compare and branch on Nonzero and Compare and Branch on Zero.
+				if ((inst & 0xF500) == 0xB100)
+					{
+					LOG_MSG("ARM ARM DDI0406A - section A8.6.27 CBNZ, CBZ");
+
+					// Decoding as per ARM ARM description
+					TUint32 op = (inst & 0x0800) >> 11;
+					TUint32 i = (inst & 0x0200) >> 9;
+					TUint32 imm5 = (inst & 0x00F8) >> 3;
+					TUint32 Rn = inst & 0x0007;
+
+					TUint32 imm32 = (i << 6) | (imm5 << 1);
+
+					// Obtain value for register Rn
+					TUint32 RnVal = 0;
+					ReturnIfError(RegisterValue(aThread,Rn,RnVal));
+
+					if (op)
+						{
+						// nonzero
+						if (RnVal != 0x0)
+							{
+							// Branch
+							breakAddress = aCurrentPC + imm32;
+							}
+						}
+					else
+						{
+						// zero
+						if (RnVal == 0x0)
+							{
+							// Branch
+							breakAddress = aCurrentPC + imm32;
+							}
+						}
+				}
+
+				// ARM ARM DDI0406A - section A8.6.50 IT
+				//
+				// If Then instruction
+				if ((inst & 0xFF00) == 0xBF00)
+					{
+					LOG_MSG("ARM ARM DDI0406A - section A8.6.50 IT");
+
+					// Decoding as per ARM ARM description
+					TUint32 firstcond = inst & 0x00F0 >> 4;
+					TUint32 mask = inst & 0x000F;
+
+					if (firstcond == 0xF)
+						{
+						// unpredictable
+						LOG_MSG("ARM ARM DDI0406A - section A8.6.50 IT - Unpredictable");
+						break;
+						}
+
+					if ((firstcond == 0xE) && (BitCount(mask) != 1))
+						{
+						// unpredictable
+						LOG_MSG("ARM ARM DDI0406A - section A8.6.50 IT - Unpredictable");
+						break;
+						}
+
+					// should check if 'in-it-block'
+					LOG_MSG("Cannot step IT instructions.");
+
+					// all the conds are as per Table A8-1 (i.e. the usual 16 cases)
+					// no idea how to decode the it block 'after-the-fact'
+					// so probably need to treat instructions in the it block
+					// as 'may' be executed. So breakpoints at both possible locations
+					// depending on whether the instruction is executed or not.
+
+					// also, how do we know if we have hit a breakpoint whilst 'in' an it block?
+					// can we check the status registers to find out?
+					//
+					// see arm arm page 390.
+					//
+					// seems to depend on the itstate field. this also says what the condition code
+					// actually is, and how many instructions are left in the itblock.
+					// perhaps we can just totally ignore this state, and always do the two-instruction
+					// breakpoint thing? Not if there is any possibility that the address target
+					// would be invalid for the non-taken branch address...
+					}
+
+
+				// 32-bit encodings.
+				//
+
+				// Load word A6-23
+				// Data processing instructions a6-28
+				// 
+
+				// ARM ARM DDI0406A - section A8.6.26
+				if (inst32 & 0xFFF0FFFF == 0xE3C08F00)
+					{
+					LOG_MSG("ARM ARM DDI0406A - section A8.6.26 - BXJ is not supported");
+
+					// Decoding as per ARM ARM description
+					// TUint32 Rm = inst32 & 0x000F0000;	// not needed yet
+					}
+
+				// return from exception... SUBS PC,LR. page b6-25
+				//
+				// ARM ARM DDi046A - section B6.1.13 - SUBS PC,LR
+				//
+				// Encoding T1
+				if (inst32 & 0xFFFFFF00 == 0xF3DE8F00)
+					{
+					LOG_MSG("ARM ARM DDI0406A - section B6.1.13 - SUBS PC,LR Encoding T1");
+
+					// Decoding as per ARM ARM description
+					TUint32 imm8 = inst32 & 0x000000FF;
+					TUint32 imm32 = imm8;
+
+					// TUint32 register_form = EFalse;	// not needed for this decoding
+					// TUint32 opcode = 0x2;	// SUB	// not needed for this decoding
+					TUint32 n = 14;
+
+					// Obtain LR
+					TUint32 lrVal;
+					ReturnIfError(RegisterValue(aThread,n,lrVal));
+
+					TUint32 operand2 = imm32;	// always for Encoding T1
+					
+					TUint32 result = lrVal - operand2;
+					
+					breakAddress = result;
+					}
+
+				// ARM ARM DDI0406A - section A8.6.16 - B
+				//
+				// Branch Encoding T3
+				if (inst32 & 0xF800D000 == 0xF0008000)
+					{
+					LOG_MSG("ARM ARM DDI0406A - section A8.6.16 - B Encoding T3");
+
+					// Decoding as per ARM ARM description
+					TUint32 S = inst32 & 0x04000000 >> 26;
+					// TUint32 cond = inst32 & 0x03C00000 >> 22;	// not needed for this decoding
+					TUint32 imm6 = inst32 & 0x003F0000 >> 16;
+					TUint32 J1 = inst32 & 0x00002000 >> 13;
+					TUint32 J2 = inst32 & 0x00000800 >> 11;
+					TUint32 imm11 = inst32 & 0x000007FF;
+
+					TUint32 imm32 = S ? 0xFFFFFFFF : 0 ;
+					imm32 = (imm32 << 1) | J2;
+					imm32 = (imm32 << 1) | J1;
+					imm32 = (imm32 << 6) | imm6;
+					imm32 = (imm32 << 11) | imm11;
+					imm32 = (imm32 << 1) | 0;
+
+					breakAddress = aCurrentPC + imm32;
+					}
+
+				// ARM ARM DDI0406A - section A8.6.16 - B
+				//
+				// Branch Encoding T4
+				if (inst32 & 0xF800D000 == 0xF0009000)
+					{
+					LOG_MSG("ARM ARM DDI0406A - section A8.6.16 - B");
+
+					// Decoding as per ARM ARM description
+					TUint32 S = inst32 & 0x04000000 >> 26;
+					TUint32 imm10 = inst32 & 0x03FF0000 >> 16;
+					TUint32 J1 = inst32 & 0x00002000 >> 12;
+					TUint32 J2 = inst32 & 0x00000800 >> 11;
+					TUint32 imm11 = inst32 & 0x000003FF;
+
+					TUint32 I1 = !(J1 ^ S);
+					TUint32 I2 = !(J2 ^ S);
+
+					TUint32 imm32 = S ? 0xFFFFFFFF : 0;
+					imm32 = (imm32 << 1) | S;
+					imm32 = (imm32 << 1) | I1;
+					imm32 = (imm32 << 1) | I2;
+					imm32 = (imm32 << 10) | imm10;
+					imm32 = (imm32 << 11) | imm11;
+					imm32 = (imm32 << 1) | 0;
+
+					breakAddress = aCurrentPC + imm32;
+					}
+
+
+				// ARM ARM DDI0406A - section A8.6.225 - TBB, TBH
+				//
+				// Table Branch Byte, Table Branch Halfword
+				if (inst32 & 0xFFF0FFE0 == 0xE8D0F000)
+						{
+					LOG_MSG("ARM ARM DDI0406A - section A8.6.225 TBB,TBH Encoding T1");
+
+					// Decoding as per ARM ARM description
+					TUint32 Rn = inst32 & 0x000F0000 >> 16;
+					TUint32 H = inst32 & 0x00000010 >> 4;
+					TUint32 Rm = inst32 & 0x0000000F;
+
+					// Unpredictable?
+					if (Rm == 13 || Rm == 15)
+						{
+						LOG_MSG("ARM ARM DDI0406A - section A8.6.225 TBB,TBH Encoding T1 - Unpredictable");
+						break;
+						}
+
+					TUint32 halfwords;
+					TUint32 address;
+					ReturnIfError(RegisterValue(aThread,Rn,address));
+
+					TUint32 offset;
+					ReturnIfError(RegisterValue(aThread,Rm,offset));
+
+					if (H)
+						{
+						address += offset << 1;
+						}
+					else
+						{
+						address += offset;
+						}
+
+					ReturnIfError(ReadMem32(aThread,address,halfwords));
+
+					breakAddress = aCurrentPC + 2*halfwords;
+					break;
+					}
+
+				// ARM ARM DDI0406A - section A8.6.55 - LDMDB, LDMEA
+				//
+				// LDMDB Encoding T1
+				if (inst32 & 0xFFD02000 == 0xE9100000)
+					{
+					LOG_MSG("ARM ARM DDI0406 - section A8.6.55 LDMDB Encoding T1");
+
+					// Decoding as per ARM ARM description
+					// TUint32 W = inst32 & 0x00200000 >> 21;	// Not needed for this encoding
+					TUint32 Rn = inst32 & 0x000F0000 >> 16;
+					TUint32 P = inst32 & 0x00008000 >> 15;
+					TUint32 M = inst32 & 0x00004000 >> 14;
+					TUint32 registers = inst32 & 0x00001FFF;
+
+					//TBool wback = (W == 1);	// not needed for this encoding
+
+					// Unpredictable?
+					if (Rn == 15 || BitCount(registers) < 2 || ((P == 1) && (M==1)))
+						{
+						LOG_MSG("ARM ARM DDI0406 - section A8.6.55 LDMDB Encoding T1 - Unpredictable");
+						break;
+						}
+
+					TUint32 address;
+					ReturnIfError(RegisterValue(aThread,Rn,address));
+
+					address -= 4*BitCount(registers);
+
+					for(TInt i=0; i<15; i++)
+						{
+						if (IsBitSet(registers,i))
+							{
+							address +=4;
+							}
+						}
+
+					if (IsBitSet(registers,15))
+						{
+						TUint32 RnVal = 0;
+						ReturnIfError(ReadMem32(aThread,address,RnVal));
+
+						breakAddress = RnVal;
+						}
+					break;
+					}
+
+				// ARM ARM DDI0406A - section A8.6.121 POP
+				//
+				// POP.W Encoding T2
+				if (inst32 & 0xFFFF2000 == 0xE8BD0000)
+					{
+					LOG_MSG("ARM ARM DDI0406A - section A8.6.121 POP Encoding T2");
+
+					// Decoding as per ARM ARM description
+					TUint32 registers = inst32 & 0x00001FFF;
+					TUint32 P = inst32 & 0x00008000;
+					TUint32 M = inst32 & 0x00004000;
+
+					// Unpredictable?
+					if ( (BitCount(registers)<2) || ((P == 1)&&(M == 1)) )
+						{
+						LOG_MSG("ARM ARM DDI0406A - section A8.6.121 POP Encoding T2 - Unpredictable");
+						break;
+						}
+
+					TUint32 address;
+					ReturnIfError(RegisterValue(aThread,13,address));
+					
+					for(TInt i=0; i< 15; i++)
+						{
+						if (IsBitSet(registers,i))
+							{
+							address += 4;
+							}
+						}
+
+					// Is the PC written?
+					if (IsBitSet(registers,15))
+						{
+						// Yes
+						ReturnIfError(ReadMem32(aThread,address,breakAddress));
+						}
+					}
+
+				// POP Encoding T3
+				if (inst32 & 0xFFFF0FFFF == 0xF85D0B04)
+					{
+					LOG_MSG("ARM ARM DDI0406A - section A8.6.121 POP Encoding T3");
+
+					// Decoding as per ARM ARM description
+					TUint32 Rt = inst32 & 0x0000F000 >> 12;
+					TUint32 registers = 1 << Rt;
+
+					// Unpredictable?
+					if (Rt == 13 || Rt == 15)
+						{
+						LOG_MSG("ARM ARM DDI0406A - section A8.6.121 POP Encoding T3 - Unpredictable");
+						break;
+						}
+					
+					TUint32 address;
+					ReturnIfError(RegisterValue(aThread,13,address));
+					
+					for(TInt i=0; i< 15; i++)
+						{
+						if (IsBitSet(registers,i))
+							{
+							address += 4;
+							}
+						}
+
+					// Is the PC written?
+					if (IsBitSet(registers,15))
+						{
+						// Yes
+						ReturnIfError(ReadMem32(aThread,address,breakAddress));
+						}
+
+					break;
+					}
+
+				// ARM ARM DDI0406A - section A8.6.53 LDM
+				//
+				// Load Multiple Encoding T2 
+				if ((inst32 & 0xFFD02000) == 0xE8900000)
+					{
+					LOG_MSG("ARM ARM DDI0406A - section A8.6.53 LDM Encoding T2");
+
+					// Decoding as per ARM ARM description
+					TUint32 W = inst32 & 0x0020000 >> 21;
+					TUint32 Rn = inst32 & 0x000F0000 >> 16;
+					TUint32 P = inst32 & 0x00008000 >> 15;
+					TUint32 M = inst32 & 0x00004000 >> 14;
+					TUint32 registers = inst32 & 0x0000FFFF;
+					TUint32 register_list = inst32 & 0x00001FFF;
+				
+					// POP?
+					if ( (W == 1) && (Rn == 13) )
+						{
+						// POP instruction
+						LOG_MSG("ARM ARM DDI0406A - section A8.6.53 LDM Encoding T2 - POP");
+						}
+
+					// Unpredictable?
+					if (Rn == 15 || BitCount(register_list) < 2 || ((P == 1) && (M == 1)) )
+						{
+						LOG_MSG("ARM ARM DDI0406A - section A8.6.53 LDM Encoding T2 - Unpredictable");
+						break;
+						}
+					
+					TUint32 RnVal;
+					ReturnIfError(RegisterValue(aThread,Rn,RnVal));
+
+					TUint32 address = RnVal;
+
+					// Calculate offset of address
+					for(TInt i = 0; i < 15; i++)
+						{
+						if (IsBitSet(registers,i))
+						{
+							address += 4;
+						}
+						}
+
+					// Does it load the PC?
+					if (IsBitSet(registers,15))
+						{
+						// Obtain the value loaded into the PC
+						ReturnIfError(ReadMem32(aThread,address,breakAddress));
+						}
+					break;
+
+					}
+
+				// ARM ARM DDI0406A - section B6.1.8 RFE
+				//
+				// Return From Exception Encoding T1 RFEDB
+				if ((inst32 & 0xFFD0FFFF) == 0xE810C000)
+					{
+					LOG_MSG("ARM ARM DDI0406A - section B6.1.8 RFE Encoding T1");
+
+					// Decoding as per ARM ARM description
+					// TUint32 W = (inst32 & 0x00200000) >> 21;	// not needed for this encoding
+					TUint32 Rn = (inst32 & 0x000F0000) >> 16;
+					
+					// TBool wback = (W == 1);	// not needed for this encoding
+					TBool increment = EFalse;
+					TBool wordhigher = EFalse;
+
+					// Do calculation
+					if (Rn == 15)
+						{
+						// Unpredictable 
+						LOG_MSG("ARM ARM DDI0406A - section B6.1.8 RFE Encoding T1 - Unpredictable");
+						break;
+						}
+
+					TUint32 RnVal = 0;
+					ReturnIfError(RegisterValue(aThread,Rn,RnVal));
+
+					TUint32 address = 0;
+					ReturnIfError(ReadMem32(aThread,RnVal,address));
+
+					if (increment)
+						{
+						address -= 8;
+						}
+
+					if (wordhigher)
+						{
+						address += 4;
+						}
+
+					breakAddress = address;
+					break;
+					}
+
+				// Return From Exception Encoding T2 RFEIA
+				if ((inst32 & 0xFFD0FFFF) == 0xE990C000)
+					{
+					LOG_MSG("ARM ARM DDI0406A - section B6.1.8 RFE Encoding T2");
+
+					// Decoding as per ARM ARM description
+					// TUint32 W = (inst32 & 0x00200000) >> 21;	// not needed for this encoding
+					TUint32 Rn = (inst32 & 0x000F0000) >> 16;
+					
+					// TBool wback = (W == 1);	// not needed for this encoding
+					TBool increment = ETrue;
+					TBool wordhigher = EFalse;
+
+					// Do calculation
+					if (Rn == 15)
+						{
+						// Unpredictable 
+						LOG_MSG("ARM ARM DDI0406A - section B6.1.8 RFE Encoding T2 - Unpredictable");
+						break;
+						}
+
+					TUint32 RnVal = 0;
+					ReturnIfError(RegisterValue(aThread,Rn,RnVal));
+
+					TUint32 address = 0;
+					ReturnIfError(ReadMem32(aThread,RnVal,address));
+
+					if (increment)
+						{
+						address -= 8;
+						}
+
+					if (wordhigher)
+						{
+						address += 4;
+						}
+
+					breakAddress = RnVal;
+					break;
+					}
+
+				// Return From Exception Encoding A1 RFE<amode>
+				if ((inst32 & 0xFE50FFFF) == 0xF8100A00)
+					{
+					LOG_MSG("ARM ARM DDI0406A - section B6.1.8 RFE Encoding A1");
+
+					// Decoding as per ARM ARM description
+					TUint32 P = (inst32 & 0x01000000) >> 24;
+					TUint32 U = (inst32 & 0x00800000) >> 23;
+					// TUint32 W = (inst32 & 0x00200000) >> 21; // not needed for this encoding
+					TUint32 Rn = (inst32 & 0x000F0000) >> 16;	
+					
+					// TBool wback = (W == 1);	// not needed for this encoding
+					TBool increment = (U == 1);
+					TBool wordhigher = (P == U);
+
+					// Do calculation
+					if (Rn == 15)
+						{
+						// Unpredictable 
+						LOG_MSG("ARM ARM DDI0406A - section B6.1.8 RFE Encoding A1 - Unpredictable");
+						break;
+						}
+
+					TUint32 RnVal = 0;
+					ReturnIfError(RegisterValue(aThread,Rn,RnVal));
+
+					TUint32 address = 0;
+					ReturnIfError(ReadMem32(aThread,RnVal,address));
+
+					if (increment)
+						{
+						address -= 8;
+						}
+
+					if (wordhigher)
+						{
+						address += 4;
+						}
+
+					breakAddress = address;
+					break;
+					}
+				}
+
+			// v4T/v5T/v6T instructions
+			switch(thumb_opcode(inst))
+				{
+				case 0x08:
+					{
+					// Data-processing. See ARM ARM DDI0406A, section A6-8, A6.2.2.
+
+					if ((thumb_inst_7_15(inst) == 0x08F))
+						{
+						// BLX(2)
+						err = iChannel->ReadKernelRegisterValue(aThread, ((inst & 0x0078) >> 3), breakAddress);
+						if(err != KErrNone)
+							{
+							LOG_MSG2("Non-zero error code discarded: %d", err);
+							}
+
+						if ((breakAddress & 0x00000001) == 0)
+							{
+							aChangingModes = ETrue;
+							}
+
+						breakAddress &= 0xFFFFFFFE;
+
+						// Report how we decoded this instruction
+						LOG_MSG("DRMDStepping::PCAfterInstructionExecutes: Decoded as BLX (2)");
+						}
+					else if (thumb_inst_7_15(inst) == 0x08E)
+						{
+						// BX
+						err = iChannel->ReadKernelRegisterValue(aThread, ((inst & 0x0078) >> 3), breakAddress);
+						if(err != KErrNone)
+							{
+							LOG_MSG2("Non-zero error code discarded: %d", err);
+							}
+
+						if ((breakAddress & 0x00000001) == 0)
+							{
+							aChangingModes = ETrue;
+							}
+						
+						breakAddress &= 0xFFFFFFFE;
+
+						// Report how we decoded this instruction
+						LOG_MSG("DRMDStepping::PCAfterInstructionExecutes: Decoded as BX");
+						}
+					else if ((thumb_inst_8_15(inst) == 0x46) && ((inst & 0x87) == 0x87))
+						{
+						// MOV with PC as the destination
+						err = iChannel->ReadKernelRegisterValue(aThread, ((inst & 0x0078) >> 3), breakAddress);
+						if(err != KErrNone)
+							{
+							LOG_MSG2("Non-zero error code discarded: %d", err);
+							}
+
+						// Report how we decoded this instruction
+						LOG_MSG("DRMDStepping::PCAfterInstructionExecutes: Decoded as MOV with PC as the destination");
+						}
+					else if ((thumb_inst_8_15(inst) == 0x44) && ((inst & 0x87) == 0x87))
+						{
+						// ADD with PC as the destination
+						err = iChannel->ReadKernelRegisterValue(aThread, ((inst & 0x0078) >> 3), breakAddress);
+						if(err != KErrNone)
+							{
+							LOG_MSG2("Non-zero error code discarded: %d", err);
+							}
+						breakAddress += aCurrentPC + 4; // +4 because we need to use the PC+4 according to ARM ARM DDI0406A, section A6.1.2.
+
+						// Report how we decoded this instruction
+						LOG_MSG("DRMDStepping::PCAfterInstructionExecutes: Decoded as ADD with PC as the destination");
+						}
+					break;
+					}
+				case 0x13:
+					{
+					// Load/Store single data item. See ARM ARM DDI0406A, section A6-10
+
+					//This instruction doesn't modify the PC.
+
+					//if (thumb_inst_8_15(inst) == 0x9F)
+					//{
+						// LDR(4) with the PC as the destination
+					//	breakAddress = ReadRegister(aThread, SP_REGISTER) + (4 * (inst & 0x00FF));
+					//}
+
+					// Report how we decoded this instruction
+					LOG_MSG("DRMDStepping::PCAfterInstructionExecutes: Decoded as This instruction doesn't modify the PC.");
+					break;
+					}
+				case 0x17:
+					{
+					// Misc 16-bit instruction. See ARM ARM DDI0406A, section A6-11
+
+					if (thumb_inst_8_15(inst) == 0xBD)
+						{
+						// POP with the PC in the list
+						TUint32 regList = (inst & 0x00FF);
+						TInt offset = 0;
+						err = iChannel->ReadKernelRegisterValue(aThread,  SP_REGISTER, (T4ByteRegisterValue&)offset);
+						if(err != KErrNone)
+							{
+							LOG_MSG2("Non-zero error code discarded: %d", err);
+							}
+						offset += (iChannel->Bitcount(regList) * 4);
+
+						TBuf8<4> destination;
+						err = iChannel->DoReadMemory(aThread, offset, 4, destination);
+						
+						if (KErrNone == err)
+							{
+							breakAddress = *(TUint32 *)destination.Ptr();
+
+							if ((breakAddress & 0x00000001) == 0)
+								{
+								aChangingModes = ETrue;
+								}
+
+							breakAddress &= 0xFFFFFFFE;
+							}
+						else
+							{
+							LOG_MSG("Error reading memory in decoding step instruction");
+							}
+
+						// Report how we decoded this instruction
+						LOG_MSG("DRMDStepping::PCAfterInstructionExecutes: Decoded as POP with the PC in the list");
+						}
+					break;
+					}
+				case 0x1A:
+				case 0x1B:
+					{
+					// Conditional branch, and supervisor call. See ARM ARM DDI0406A, section A6-13
+
+					if (thumb_inst_8_15(inst) < 0xDE)
+						{
+						// B(1) conditional branch
+						if (IsExecuted(((inst & 0x0F00) >> 8), aStatusRegister))
+							{
+							TUint32 offset = ((inst & 0x000000FF) << 1);
+							if (offset & 0x00000100)
+								{
+								offset |= 0xFFFFFF00;
+								}
+							
+							breakAddress = aCurrentPC + 4 + offset;
+
+							// Report how we decoded this instruction
+							LOG_MSG("DRMDStepping::PCAfterInstructionExecutes: Decoded as B(1) conditional branch");
+							}
+						}
+					break;
+					}
+				case 0x1C:
+					{
+					// Unconditional branch, See ARM ARM DDI0406A, section A8-44.
+
+					// B(2) unconditional branch
+					TUint32 offset = (inst & 0x000007FF) << 1;
+					if (offset & 0x00000800)
+						{
+						offset |= 0xFFFFF800;
+						}
+					
+					breakAddress = aCurrentPC + 4 + offset;
+
+					// Report how we decoded this instruction
+					LOG_MSG("DRMDStepping::PCAfterInstructionExecutes: Decoded as B(2) unconditional branch");
+
+					break;
+					}
+				case 0x1D:
+					{
+					if (!(inst & 0x0001))
+						{
+						// BLX(1)
+						err = iChannel->ReadKernelRegisterValue(aThread, LINK_REGISTER, breakAddress);
+						if(err != KErrNone)
+							{
+							LOG_MSG2("Non-zero error code discarded: %d", err);
+							}
+						breakAddress +=  ((inst & 0x07FF) << 1);
+						if ((breakAddress & 0x00000001) == 0)
+							{
+							aChangingModes = ETrue;
+							}
+
+						breakAddress &= 0xFFFFFFFC;
+
+						// Report how we decoded this instruction
+						LOG_MSG("DRMDStepping::PCAfterInstructionExecutes: Decoded as BLX(1)");
+
+						}
+					break;
+					}
+				case 0x1E:
+					{
+					// Check for ARMv7 CPU
+					if(cpuid == 0xC0)
+						{
+						// BL/BLX 32-bit instruction
+						aNewRangeEnd += 4;
+
+						breakAddress = (TUint32)thumb_instr_b_dest(inst32, aCurrentPC);
+
+						if((inst32 >> 27) == 0x1D)
+							{
+							// BLX(1)
+							if ((breakAddress & 0x00000001) == 0)
+								{
+								aChangingModes = ETrue;
+								}
+
+							breakAddress &= 0xFFFFFFFC;
+
+							// Report how we decoded this instruction
+							LOG_MSG("DRMDStepping::PCAfterInstructionExecutes: Decoded as 32-bit BLX(1)");
+							}
+						else
+							{
+							// Report how we decoded this instruction
+							LOG_MSG("DRMDStepping::PCAfterInstructionExecutes: 32-bit BL instruction");
+							}
+						LOG_MSG2(" 32-bit BL/BLX instruction: breakAddress = 0x%X", breakAddress);
+						} // if(cpuid == 0xC0)
+					else
+						{
+						// BL/BLX prefix - destination is encoded in this and the next instruction
+						aNewRangeEnd += 2;
+
+						// Report how we decoded this instruction
+						LOG_MSG("DRMDStepping::PCAfterInstructionExecutes: BL/BLX prefix - destination is encoded in this and the next instruction");
+						}
+
+					break;
+					}
+				case 0x1F:
+					{
+					// BL
+					err = iChannel->ReadKernelRegisterValue(aThread, LINK_REGISTER, breakAddress);
+					if(err != KErrNone)
+						{
+						LOG_MSG2("Non-zero error code discarded: %d", err);
+						}
+					breakAddress += ((inst & 0x07FF) << 1);
+
+					// Report how we decoded this instruction
+					LOG_MSG("DRMDStepping::PCAfterInstructionExecutes: Decoded as BL");
+					break;
+					}
+				default:
+					{
+					// Don't know any better at this point!
+					LOG_MSG("DRMDStepping::PCAfterInstructionExecutes:- default to next instruction");
+					}
+					break;
+				} // switch(thumb_opcode(inst))
+			} // case Debug::EThumbMode:
+		break;
+
+		case Debug::EThumb2EEMode:
+			{
+			// Not yet supported
+			LOG_MSG("DRMDStepping::PCAfterInstructionExecutes - Debug::EThumb2Mode is not supported");
+
+			}
+			break;
+
+		default:
+			LOG_MSG("DRMDStepping::PCAfterInstructionExecutes - Cannot determine CPU mode architecture");
+		} // switch(mode)
+
+	LOG_MSG2("DRMDStepping::PCAfterInstructionExecutes : return 0x%08x",breakAddress);
+	return breakAddress;
+	}
+
+// Obtain a 32-bit memory value with minimum fuss
+TInt DRMDStepping::ReadMem32(DThread* aThread, const TUint32 aAddress, TUint32& aValue)
+	{
+	TBuf8<4> valBuf;
+	TInt err = iChannel->DoReadMemory(aThread, aAddress, 4, valBuf);
+	if (err != KErrNone)
+		{
+		LOG_MSG2("DRMDStepping::ReadMem32 failed to read memory at 0x%08x", aAddress);
+		return err;
+		}
+
+	aValue = *(TUint32 *)valBuf.Ptr();
+
+	return KErrNone;
+	}
+
+// Obtain a 16-bit memory value with minimum fuss
+TInt DRMDStepping::ReadMem16(DThread* aThread, const TUint32 aAddress, TUint16& aValue)
+	{
+	TBuf8<2> valBuf;
+	TInt err = iChannel->DoReadMemory(aThread, aAddress, 2, valBuf);
+	if (err != KErrNone)
+		{
+		LOG_MSG2("DRMDStepping::ReadMem16 failed to read memory at 0x%08x", aAddress);
+		return err;
+		}
+
+	aValue = *(TUint16 *)valBuf.Ptr();
+
+	return KErrNone;
+	}
+
+// Obtain a 16-bit memory value with minimum fuss
+TInt DRMDStepping::ReadMem8(DThread* aThread, const TUint32 aAddress, TUint8& aValue)
+	{
+	TBuf8<1> valBuf;
+	TInt err = iChannel->DoReadMemory(aThread, aAddress, 1, valBuf);
+	if (err != KErrNone)
+		{
+		LOG_MSG2("DRMDStepping::ReadMem8 failed to read memory at 0x%08x", aAddress);
+		return err;
+		}
+
+	aValue = *(TUint8 *)valBuf.Ptr();
+
+	return KErrNone;
+	}
+
+// Obtain a core register value with minimum fuss
+TInt DRMDStepping::RegisterValue(DThread *aThread, const TUint32 aKernelRegisterId, TUint32 &aValue)
+	{
+	TInt err = iChannel->ReadKernelRegisterValue(aThread, aKernelRegisterId, aValue);
+	if(err != KErrNone)
+		{
+		LOG_MSG3("DRMDStepping::RegisterValue failed to read register %d err = %d", aKernelRegisterId, err);
+		}
+		return err;
+	}
+
+
+// Encodings from ARM ARM DDI0406A, section 9.2.1
+enum TThumb2EEOpcode
+	{
+	EThumb2HDP,		// Handler Branch with Parameter
+	EThumb2UNDEF,	// UNDEFINED
+	EThumb2HB,		// Handler Branch, Handler Branch with Link
+	EThumb2HBLP,	// Handle Branch with Link and Parameter
+	EThumb2LDRF,	// Load Register from a frame
+	EThumb2CHKA,	// Check Array
+	EThumb2LDRL,	// Load Register from a literal pool
+	EThumb2LDRA,	// Load Register (array operations)
+	EThumb2STR		// Store Register to a frame
+	};
+
+//
+// DRMDStepping::ShiftedRegValue
+//
+TUint32 DRMDStepping::ShiftedRegValue(DThread *aThread, TUint32 aInstruction, TUint32 aCurrentPC, TUint32 aStatusRegister)
+	{
+	LOG_MSG("DRMDStepping::ShiftedRegValue()");
+
+	TUint32 shift = 0;
+	if (aInstruction & 0x10)	// bit 4
+		{
+		shift = (arm_rs(aInstruction) == PC_REGISTER ? aCurrentPC + 8 : aStatusRegister) & 0xFF;
+		}
+	else
+		{
+		shift = arm_data_c(aInstruction);
+		}
+	
+	TInt rm = arm_rm(aInstruction);
+	
+	TUint32 res = 0;
+	if(rm == PC_REGISTER)
+		{
+		res = aCurrentPC + ((aInstruction & 0x10) ? 12 : 8);
+		}
+	else
+		{
+		TInt err = iChannel->ReadKernelRegisterValue(aThread, rm, res);
+		if(err != KErrNone)
+			{
+			LOG_MSG2("DRMDStepping::ShiftedRegValue - Non-zero error code discarded: %d", err);
+			}
+		}
+
+	switch(arm_data_shift(aInstruction))
+		{
+		case 0:			// LSL
+			{
+			res = shift >= 32 ? 0 : res << shift;
+			break;
+			}
+		case 1:			// LSR
+			{
+			res = shift >= 32 ? 0 : res >> shift;
+			break;
+			}
+		case 2:			// ASR
+			{
+			if (shift >= 32)
+			shift = 31;
+			res = ((res & 0x80000000L) ? ~((~res) >> shift) : res >> shift);
+			break;
+			}
+		case 3:			// ROR/RRX
+			{
+			shift &= 31;
+			if (shift == 0)
+				{
+				res = (res >> 1) | ((aStatusRegister & arm_carry_bit()) ? 0x80000000L : 0);
+				}
+			else
+				{
+				res = (res >> shift) | (res << (32 - shift));
+				}
+			break;
+			}
+		}
+
+	return res & 0xFFFFFFFF;
+}
+
+//
+// DRMDStepping::CurrentPC
+//
+// 
+//
+TInt DRMDStepping::CurrentPC(DThread* aThread, TUint32& aPC)
+	{
+	LOG_MSG("DRMDStepping::CurrentPC");
+
+	TInt err = iChannel->ReadKernelRegisterValue(aThread, PC_REGISTER, aPC);
+	if(err != KErrNone)
+		{
+		// We don't know the current PC for this thread!
+		LOG_MSG("DRMDStepping::CurrentPC - Failed to read the current PC");
+		
+		return KErrGeneral;
+		}
+
+	LOG_MSG2("DRMDStepping::CurrentPC 0x%08x", aPC);
+
+	return KErrNone;
+	}
+
+//
+// DRMDStepping::CurrentCPSR
+//
+// 
+//
+TInt DRMDStepping::CurrentCPSR(DThread* aThread, TUint32& aCPSR)
+	{
+	LOG_MSG("DRMDStepping::CurrentCPSR");
+
+	TInt err = iChannel->ReadKernelRegisterValue(aThread, STATUS_REGISTER, aCPSR);
+	if(err != KErrNone)
+		{
+		// We don't know the current PC for this thread!
+		LOG_MSG("DRMDStepping::CurrentPC - Failed to read the current CPSR");
+		
+		return KErrGeneral;
+		}
+
+	LOG_MSG2("DRMDStepping::CurrentCPSR 0x%08x", aCPSR);
+	
+	return KErrNone;
+	}
+
+//
+// DRMDStepping::ModifyBreaksForStep
+//
+// Set a temporary breakpoint at the next instruction to be executed after the one at the current PC
+// Disable the breakpoint at the current PC if one exists
+//
+TInt DRMDStepping::ModifyBreaksForStep(DThread *aThread, TUint32 aRangeStart, TUint32 aRangeEnd, /*TBool aStepInto,*/ TBool aResumeOnceOutOfRange, TBool aCheckForStubs, const TUint32 aNumSteps)
+	{
+	LOG_MSG2("DRMDStepping::ModifyBreaksForStep() Numsteps 0x%d",aNumSteps);
+
+	// Validate arguments
+	if (!aThread)
+		{
+		LOG_MSG("DRMDStepping::ModifyBreaksForStep() - No aThread specified to step");
+		return KErrArgument;
+		}
+
+	// Current PC
+	TUint32 currentPC;
+
+	ReturnIfError(CurrentPC(aThread,currentPC));
+	LOG_MSG2("Current PC: 0x%x", currentPC);
+
+	// disable breakpoint at the current PC if necessary
+	ReturnIfError(iChannel->iBreakManager->DisableBreakAtAddress(currentPC));
+
+	// Current CPSR
+	TUint32 statusRegister;
+
+	ReturnIfError(CurrentCPSR(aThread,statusRegister));
+	LOG_MSG2("Current CPSR: %x", statusRegister);
+
+	TBool thumbMode = (statusRegister & ECpuThumb);
+	if (thumbMode)
+		LOG_MSG("Thumb Mode");
+
+	TInt instSize = thumbMode ? 2 : 4;
+
+	TBool changingModes = EFalse;
+
+	TUint32 breakAddress = 0;
+
+	TUint32 newRangeEnd = aRangeEnd;
+
+	breakAddress = PCAfterInstructionExecutes(aThread, currentPC, statusRegister, instSize, /* aStepInto, */ newRangeEnd, changingModes);
+
+	/*
+	If there is already a user breakpoint at this address, we do not need to set a temp breakpoint. The program
+	should simply stop at that address.	
+	*/
+	TBreakEntry* breakEntry = NULL;
+	do
+		{
+		breakEntry = iChannel->iBreakManager->GetNextBreak(breakEntry);
+		if(breakEntry && !iChannel->iBreakManager->IsTemporaryBreak(*breakEntry))
+			{
+			if ((breakEntry->iAddress == breakAddress) && ((breakEntry->iThreadSpecific && breakEntry->iId == aThread->iId) || (!breakEntry->iThreadSpecific && breakEntry->iId == aThread->iOwningProcess->iId)))
+				{
+				LOG_MSG("DRMDStepping::ModifyBreaksForStep - Breakpoint already exists at the step target address\n");
+
+				// note also that if this is the case, we will not keep stepping if we hit a real breakpoint, so may as well set
+				// the step count = 0.
+				breakEntry->iNumSteps = 0;
+
+				return KErrNone;
+				}
+			}
+		} while(breakEntry);
+
+	breakEntry = NULL;
+	do
+		{
+		breakEntry = iChannel->iBreakManager->GetNextBreak(breakEntry);
+		if(breakEntry && iChannel->iBreakManager->IsTemporaryBreak(*breakEntry))
+			{
+			if (breakEntry->iAddress == 0)
+				{
+				breakEntry->iId = aThread->iId;
+				breakEntry->iAddress = breakAddress;
+				breakEntry->iThreadSpecific = ETrue;
+
+				TBool realThumbMode = (thumbMode && !changingModes) || (!thumbMode && changingModes);
+
+				// Need to set the correct type of breakpoint for the mode we are in
+				// and the the one we are changing into
+				if(realThumbMode)
+					{
+					// We are remaining in Thumb mode
+					breakEntry->iMode = EThumbMode;
+					}
+				else
+					{
+					// We are switching to ARM mode
+					breakEntry->iMode = EArmMode;
+					}
+
+				breakEntry->iResumeOnceOutOfRange = aResumeOnceOutOfRange;
+				breakEntry->iSteppingInto = ETrue /* aStepInto */;
+				breakEntry->iRangeStart = 0;	// no longer used
+				breakEntry->iRangeEnd = 0;		// no longer used
+
+				LOG_MSG2("Adding temp breakpoint with id: %d", breakEntry->iBreakId);
+				LOG_MSG2("Adding temp breakpoint with thread id: %d", aThread->iId);
+
+				// Record how many more steps to go after we hit this one
+				breakEntry->iNumSteps = aNumSteps;
+
+				LOG_MSG3("Setting temp breakpoint id %d with %d steps to go\n", breakEntry->iBreakId, aNumSteps);
+
+				return iChannel->iBreakManager->DoEnableBreak(*breakEntry, ETrue);			
+				}
+			}
+		} while(breakEntry);
+	LOG_MSG("ModifyBreaksForStep : Failed to set suitable breakpoint for stepping");
+	return KErrNoMemory;	// should never get here
+}
+
+// End of file - d-rmd-stepping.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/debugsrv/runmodedebug/rmdriver/src/d_target_process.cpp	Fri Aug 27 11:37:29 2010 +0300
@@ -0,0 +1,157 @@
+// Copyright (c) 2006-2010 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+// Purpose: The DProcessTracker object tracks which processes are being
+// debugged. The DProcessTracker class uses a DTargetProcess object for
+// each process being debugged.
+// Note: Although TheDProcessTracker object is a global, it should be unique
+// as only the Debug Security Server should load and use this driver.
+//
+//
+
+#include <e32def.h>
+#include <e32def_private.h>
+#include <e32cmn.h>
+#include <e32cmn_private.h>
+#include <kernel/kernel.h>
+#include <kernel/kern_priv.h>
+#include "nk_priv.h"
+#include <rm_debug_api.h>
+
+#include "d_target_process.h"
+#include "debug_logging.h"
+#include "debug_utils.h"
+
+// ctor
+DTargetProcess::DTargetProcess()
+	:iProcessName(NULL)
+	{
+	}
+
+// dtor
+DTargetProcess::~DTargetProcess()
+	{
+	delete iProcessName;
+	iAgentList.ResetAndDestroy();
+	}
+
+// Compare two DTargetProcess items. They are the same if they have the same name.
+TInt DTargetProcess::Compare(const DTargetProcess& aFirst, const DTargetProcess& aSecond)
+	{
+	const TDesC& left = aFirst.iProcessName ? *aFirst.iProcessName : KNullDesC();
+	const TDesC& right = aSecond.iProcessName ? *aSecond.iProcessName : KNullDesC();
+	return left.Compare(right);
+	}
+
+// Set the name of the process we are tracking
+TInt DTargetProcess::SetProcessName(const TDesC8& aProcessName)
+	{
+	// Argument checking
+	if (aProcessName.Length() < 1)
+		{
+		return KErrArgument;
+		}
+
+	if (iProcessName) 
+		return KErrNotReady; // You can only set the processname once
+	iProcessName = HBuf8::New(aProcessName);
+	if (!iProcessName) 
+		return KErrNoMemory;
+	return KErrNone;
+	}
+
+// Obtain the name of the process being tracked
+const TDesC& DTargetProcess::ProcessName() const
+	{
+	return iProcessName ? *iProcessName : KNullDesC();
+	}
+
+// Returns a pointer to the DDebugAgent with aAgentId.
+// If the agent is not in the list, it returns NULL.
+DDebugAgent* DTargetProcess::Agent(TUint64 aAgentId)
+	{
+	for(TInt i = 0; i < iAgentList.Count(); i++)
+		{
+		if (iAgentList[i]->Id() == aAgentId)
+			{
+			return iAgentList[i];
+			}
+		}
+
+	// what do we return if we don't have any agents?
+	return NULL;
+	}
+
+// Adds aAgentId as a tracking agent for this process.
+TInt DTargetProcess::AddAgent(TUint64 aAgentId)
+	{
+	DDebugAgent* agent = DDebugAgent::New(aAgentId);
+	LOG_MSG4("DTargetProcess::AddAgent(), agentId=%d, curr iAgentList.Count=%d, new agent=0x%08x",
+		I64LOW(aAgentId), iAgentList.Count(), agent );
+
+	if(agent == NULL)
+		{
+		LOG_MSG("DTargetProcess::AddAgent() couldn't allocate memory for DDebugAgent");
+		return KErrNoMemory;
+		}
+	return iAgentList.Insert(agent,0);
+	}
+
+// Stops tracking the process with this agent
+TInt DTargetProcess::RemoveAgent(TUint64 aAgentId)
+	{
+	// We need to find and then remove the agent
+	for(TUint i = 0; i < iAgentList.Count(); i++)
+		{
+		if (iAgentList[i]->Id() == aAgentId)
+			{
+			LOG_MSG4("DTargetProcess::RemoveAgent(), deleting agent[%d], id 0x%x, address=0x%x",
+					i, I64LOW(aAgentId), iAgentList[i]); 
+			delete iAgentList[i];
+			iAgentList.Remove(i);
+			return KErrNone;
+			}
+		}
+
+	return KErrNotFound;
+	}
+
+// Index through the agents by position
+DDebugAgent* DTargetProcess::operator[](TInt aIndex)
+	{
+	return iAgentList[aIndex];
+	}
+
+// returns the number of agents tracking this process.
+TInt DTargetProcess::AgentCount() const
+	{
+	return iAgentList.Count();
+	}
+
+void DTargetProcess::NotifyEvent(const TDriverEventInfo& aEventInfo)
+	{
+	// Stuff the event info into all the tracking agents event queues
+	LOG_MSG4("DTargetProcess::NotifyEvent(): num attached agents: %d, iEventType=%d, this=0x%08x", 
+		AgentCount(), aEventInfo.iEventType, this);
+
+	for(TInt i = 0; i < AgentCount(); i++)
+		{
+		// Index through all the relevant debug agents
+		DDebugAgent* debugAgent = iAgentList[i];
+		if(debugAgent != NULL)
+			{
+			debugAgent->NotifyEvent(aEventInfo);
+			}
+		}
+	}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/debugsrv/runmodedebug/rmdriver/src/debug_utils.cpp	Fri Aug 27 11:37:29 2010 +0300
@@ -0,0 +1,134 @@
+// Copyright (c) 2004-2010 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+// Purpose: Implementation of static functions for use by debug driver classes
+//
+
+#include "debug_logging.h"
+#include "debug_utils.h"
+
+/**
+ * Given a thread ID, return a handle to the corresponding DThread. If the returned
+ * pointer is non-NULL, it is the responsibility of the caller to close the handle.
+ * 
+ * @pre caller must be in thread critical section
+ * @post if a non-NULL value is returned then a handle to the thread has been
+ * opened on the callers behalf
+ * @param aThreadId ID of the thread to return a handle for
+ * @return a DThread* to the appropriate thread, or NULL if a handle could not be
+ * opened to the specified thread
+ */
+DThread* DebugUtils::OpenThreadHandle(TUint64 aThreadId)
+	{
+	__ASSERT_CRITICAL;
+	LOG_MSG2("DebugUtils::OpenThreadHandle(0x%lx)", aThreadId);
+
+	DObjectCon& threads = *Kern::Containers()[EThread];  // Get containing holding threads
+	threads.Wait();  // Obtain the container mutex so the list does get changed under us
+
+	DThread* thread = Kern::ThreadFromId(aThreadId);
+
+	// Open a handle to the thread so that it doesn't exit while we are processing
+	if (thread)
+		{
+		// if opening a handle fails then set thread to NULL
+		if(KErrNone != thread->Open())
+			{
+			LOG_MSG2("\tCould not open handle to thread %d", (TUint32)aThreadId);
+			thread = NULL;
+			}
+		}
+	else
+		{
+		LOG_MSG2("\tThread with ID %d is NULL", (TUint32)aThreadId);
+		}
+
+	threads.Signal();  // Release the container mutex
+
+	return thread;
+	}
+
+/**
+ * Given a process ID, return a handle to the corresponding DProcess. If the returned
+ * pointer is non-NULL, it is the responsibility of the caller to close the handle.
+ * 
+ * @post if a non-NULL value is returned then a handle to the process has been
+ * opened on the callers behalf
+ * @param aProcessId ID of the process to return a handle for
+ * @return a DProcess* to the appropriate process, or NULL if a handle could not be
+ * opened to the specified process
+ */
+DProcess* DebugUtils::OpenProcessHandle(const TUint64 aProcessId)
+	{
+	// Commenting out this message as it gets printed out every time a RDebug::Printf statement is caught by the driver,
+	// which makes looking at the serial cable output irritating. Replaced it with LOG_MSG statements below to indicate if
+	// something amiss happened. By default then this function prints nothing out.
+	//LOG_MSG("DebugUtils::OpenProcessHandle()");
+
+	NKern::ThreadEnterCS();  // Prevent us from dying or suspending whilst holding a DMutex
+	DObjectCon& processes = *Kern::Containers()[EProcess];  // Get containing holding threads
+	processes.Wait();  // Obtain the container mutex so the list does get changed under us
+
+	DProcess* process = Kern::ProcessFromId(aProcessId);
+
+	// Open a handle to the process so that it doesn't exit while we are processing
+	if (process)
+		{
+		// if opening a handle fails then set process to NULL
+		if(KErrNone != process->Open())
+			{
+			LOG_MSG2("DebugUtils::OpenProcessHandle(): Could not open handle for 0x%lx", aProcessId);
+			process = NULL;
+			}
+		}
+	else
+		{
+		LOG_MSG2("DebugUtils::OpenProcessHandle(): Could not find process for 0x%lx", aProcessId);
+		}
+
+	processes.Signal();  // Release the container mutex
+	NKern::ThreadLeaveCS();  // End of critical section
+
+	return process;
+	}
+
+/**
+ * Opens a reference to the first thread of the given process. Returns NULL if
+ * there are no threads remaining in the process or if the thread couldn't be opened.
+ * 
+ * @pre Caller must be in thread context, in critical section, no fast mutexes held.
+ * @post if result is non-NULL caller is responsible for closing the handle
+ * @param aProcess The process whose first thread is to be opened
+ * @return an Open()ed pointer to the first thread in the process, or NULL.
+ */
+DThread* DebugUtils::OpenFirstThreadForProcess(DProcess* aProcess)
+	{
+	__ASSERT_CRITICAL;
+	// Copied from memspy's DMemSpyDriverOSAdaptionDProcess::OpenFirstThread()
+
+	// It appears that the system lock needs to be held while manipulating the iThreadQ
+	DThread* result = NULL;
+	NKern::LockSystem();
+	// We don't use DProcess::FirstThread() as that doesn't appear to do any checking of whether the list is empty, ie if there are no threads at all
+	SDblQueLink* threadLink = aProcess->iThreadQ.First();
+	if (threadLink != NULL && threadLink != &aProcess->iThreadQ.iA)
+		{
+		result = _LOFF(threadLink,DThread,iProcessLink);
+		if (result->Open() != KErrNone)
+			{
+			result = NULL;
+			}
+		}
+	NKern::UnlockSystem();
+    return result;
+    }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/debugsrv/runmodedebug/rmdriver/src/rm_debug_eventhandler.cpp	Fri Aug 27 11:37:29 2010 +0300
@@ -0,0 +1,177 @@
+// Copyright (c) 2004-2010 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+// Kernel Event handler for Run Mode Debug.
+//
+
+#include <e32def.h>
+#include <e32def_private.h>
+#include <e32cmn.h>
+#include <e32cmn_private.h>
+#include <kernel/arm/arm.h>
+#include <kernel/kernel.h>
+#include <kernel/kern_priv.h>
+#include <nk_trace.h>
+
+#include <rm_debug_api.h>
+#include "debug_logging.h"
+#include "d_process_tracker.h"
+#include "d_rmd_stepping.h"
+#include "rm_debug_kerneldriver.h"
+#include "rm_debug_driver.h"
+#include "rm_debug_eventhandler.h"
+
+
+DRM_DebugEventHandler::DRM_DebugEventHandler()
+	:	DKernelEventHandler(EventHandler, this)
+{
+	LOG_MSG("DRM_DebugEventHandler::DRM_DebugEventHandler()");
+
+	for(TInt i=0; i<EEventLimit; i++)
+		{
+		iEventHandlers[i] = &DRM_DebugChannel::HandleUnsupportedEvent;
+		}
+	iEventHandlers[EEventUserTrace] = &DRM_DebugChannel::HandleUserTrace;
+	iEventHandlers[EEventRemoveLibrary] = &DRM_DebugChannel::RemoveLibrary;
+	iEventHandlers[EEventAddLibrary] = &DRM_DebugChannel::AddLibrary;
+	iEventHandlers[EEventStartThread] = &DRM_DebugChannel::StartThread;
+	iEventHandlers[EEventSwExc] = &DRM_DebugChannel::HandleSwException;
+	iEventHandlers[EEventHwExc] = &DRM_DebugChannel::HandleHwException;
+	iEventHandlers[EEventKillThread] = &DRM_DebugChannel::HandleEventKillThread;
+	iEventHandlers[EEventAddProcess] = &DRM_DebugChannel::HandleAddProcessEvent;
+	iEventHandlers[EEventRemoveProcess] = &DRM_DebugChannel::HandleRemoveProcessEvent;
+}
+
+TInt DRM_DebugEventHandler::Create(DLogicalDevice* aDevice, DLogicalChannel* aChannel, DThread* aClient)
+{
+	LOG_MSG3("DRM_DebugEventHandler::Create(), aClientthread=0x%08x id=%d", aClient, aClient->iId);
+
+	TInt err;
+	err = aDevice->Open();
+	if (err != KErrNone)
+		return err;
+	iDevice = aDevice;
+	
+	iChannel = (DRM_DebugChannel*)aChannel; //Don't add ref the channel, since channel closes the event handler before it ever gets destroyed.
+
+	err = aClient->Open();
+	if (err != KErrNone)
+		return err;
+	iClientThread = aClient;
+
+	// Use a semaphore to protect our data structures from concurrent access.
+	err = Kern::SemaphoreCreate(iProtectionLock, _L("RM_DebugEventHandlerLock"), 1 /* Initial count */);
+	if (err != KErrNone)
+		return err;
+
+
+	return Add();
+}
+
+
+DRM_DebugEventHandler::~DRM_DebugEventHandler()
+{
+	LOG_MSG("DRM_DebugEventHandler::~DRM_DebugEventHandler()");
+
+	if (iProtectionLock)
+		iProtectionLock->Close(NULL);
+	
+	if (iDevice)
+		iDevice->Close(NULL);	
+	
+	if (iClientThread)
+		Kern::SafeClose((DObject*&)iClientThread, NULL);
+		
+}
+
+
+TInt DRM_DebugEventHandler::Start()
+{
+	LOG_MSG("DRM_DebugEventHandler::Start()");
+
+	iTracking = ETrue;
+
+	return KErrNone;
+}
+
+
+TInt DRM_DebugEventHandler::Stop()
+{
+	LOG_MSG("DRM_DebugEventHandler::Stop()");
+
+	iTracking = EFalse;
+
+	return KErrNone;
+}
+
+
+TUint DRM_DebugEventHandler::EventHandler(TKernelEvent aType, TAny* a1, TAny* a2, TAny* aThis)
+{
+	return ((DRM_DebugEventHandler*)aThis)->HandleEvent(aType, a1, a2);
+}
+
+
+
+TUint DRM_DebugEventHandler::HandleEvent(TKernelEvent aType, TAny* a1, TAny* a2)
+	{
+	
+	/*
+	 * Check if we are tracking things at all OR 
+	 * this event is beyond the limit of known events OR 
+	 * this event is from the debug thread itself (don't want to debug ourselves) OR
+	 * this event has a handler (there is no point in proceeding without a handler)
+	 */
+	if( (!iTracking) || 
+			(aType > (TUint32)EEventLimit) ||
+			(iClientThread == &Kern::CurrentThread()) ||
+	    (iEventHandlers[aType] == &DRM_DebugChannel::HandleUnsupportedEvent) )
+		{
+		return ERunNext;
+		}
+	
+	return HandleSpecificEvent(aType,a1,a2) && aType == EEventHwExc ? EExcHandled : ERunNext;
+
+
+	}
+
+TBool DRM_DebugEventHandler::HandleSpecificEvent(TKernelEvent aType, TAny* a1, TAny* a2)
+	{
+	TBool ret = EFalse;
+
+	NKern::ThreadEnterCS();
+	LockDataAccess();
+
+
+	if (iChannel)
+		{
+		ret = (iChannel->*(iEventHandlers[aType]))(a1, a2);
+		}
+	ReleaseDataAccess();
+	NKern::ThreadLeaveCS();
+
+	switch(aType)
+		{
+		case EEventHwExc:
+		case EEventKillThread:
+			{
+			LOG_MSG2("DRM_DebugEventHandler::HandleEvent() -> FSWait(), kernel event type: %d", (TUint32)aType);
+			TheDProcessTracker.FSWait();
+			LOG_MSG("DRM_DebugEventHandler::HandleEvent() <- FSWait()");
+			break;
+			}
+		default:
+			break;
+		}
+	return ret;
+	}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/debugsrv/runmodedebug/rmdriver/src/rm_debug_kerneldriver.cpp	Fri Aug 27 11:37:29 2010 +0300
@@ -0,0 +1,3530 @@
+// Copyright (c) 2004-2010 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+// Device driver for kernel side debug assist
+//
+
+#ifdef __WINS__
+#error - this driver cannot be built for emulation
+#endif
+
+#include <e32def.h>
+#include <e32def_private.h>
+#include <e32cmn.h>
+#include <e32cmn_private.h>
+#include <e32ldr.h>
+#include <u32std.h>
+#include <kernel/kernel.h>
+#include <kernel/kern_priv.h>
+#include <nk_trace.h>
+#include <arm.h>
+#include <kernel/cache.h>
+#include <platform.h>
+#include <nkern.h>
+#include <u32hal.h>
+#include <rm_debug_api.h>
+
+#include "debug_logging.h"
+#include "d_rmd_breakpoints.h"	// moved breakpoints code lives here
+#include "d_rmd_stepping.h"		// moved stepping code lives here
+#include "rm_debug_kerneldriver.h"
+#include "d_list_manager.h"
+#include "rm_debug_driver.h"
+#include "rm_debug_eventhandler.h"
+#include "d_debug_functionality.h"
+#include "d_process_tracker.h"
+#include "debug_utils.h"
+
+using namespace Debug;
+
+/////////////////////////////////////////////////////////////////////////
+//
+// DRM_DebugDriverFactory implementation
+//
+/////////////////////////////////////////////////////////////////////////
+
+//
+// DRM_DebugDriverFactory constructor
+//
+DRM_DebugDriverFactory::DRM_DebugDriverFactory()
+	{
+	iVersion = TVersion(KMajorVersionNumber,KMinorVersionNumber,KBuildVersionNumber);
+	}
+
+//
+// DRM_DebugDriverFactory::Create
+//
+TInt DRM_DebugDriverFactory::Create(DLogicalChannelBase*& aChannel)
+	{
+	if (iOpenChannels != 0)
+		return KErrInUse; // a channel is already open
+
+	aChannel = new DRM_DebugChannel(this);
+
+	return aChannel ? KErrNone : KErrNoMemory;
+	}
+
+//
+// DRM_DebugDriverFactory::Install
+//
+TInt DRM_DebugDriverFactory::Install()
+	{
+	return(SetName(&KRM_DebugDriverName));
+	}
+
+//
+// DRM_DebugDriverFactory::Install
+//
+void DRM_DebugDriverFactory::GetCaps(TDes8& aDes) const
+	{
+	TCapsRM_DebugDriver b;
+	b.iVersion = TVersion(KMajorVersionNumber, KMinorVersionNumber, KBuildVersionNumber);
+
+	Kern::InfoCopy(aDes,(TUint8*)&b,sizeof(b));
+	}
+
+/////////////////////////////////////////////////////////////////////////
+//
+// DRM_DebugChannel implementation
+//
+/////////////////////////////////////////////////////////////////////////
+
+//
+// DRM_DebugChannel constructor
+//
+DRM_DebugChannel::DRM_DebugChannel(DLogicalDevice* aLogicalDevice)
+	: iExcludedROMAddressStart(ROM_LINEAR_BASE),
+	iExcludedROMAddressEnd(0),
+	iPageSize(0x1000),
+	iBreakManager(0),
+	iStepper(0),
+	iStepLock(0),
+	iDfcQ(NULL),
+	iInitialisedCodeModifier(0),
+	iAsyncGetValueRequest(NULL)
+	{
+	LOG_MSG("DRM_DebugChannel::DRM_DebugChannel()");
+
+	iDevice = aLogicalDevice;
+
+	iClientThread = &Kern::CurrentThread();	
+	
+	// Opening handle to current thread, so no need to check for return-value
+	(void)iClientThread->Open();
+
+	LOG_MSG3("DRM_DebugChannel::DRM_DebugChannel() clientThread = 0x%08x, id=%d", 
+	            iClientThread, iClientThread->iId );
+
+
+	iPageSize = Kern::RoundToPageSize(1);
+	}
+
+//
+// DRM_DebugChannel destructor
+//
+DRM_DebugChannel::~DRM_DebugChannel()
+	{
+	LOG_MSG("DRM_DebugChannel::~DRM_DebugChannel()");
+
+	if (iAsyncGetValueRequest)
+		{
+		Kern::QueueRequestComplete(iClientThread, iAsyncGetValueRequest, KErrCancel); // does nothing if request not pending
+		Kern::DestroyClientRequest(iAsyncGetValueRequest);
+		}
+
+	NKern::ThreadEnterCS();
+	Kern::SafeClose((DObject*&)iClientThread, NULL);
+	NKern::ThreadLeaveCS();
+
+	// Close breakpoint manager
+	if (iBreakManager)
+		{
+		NKern::ThreadEnterCS();
+		delete iBreakManager;
+		NKern::ThreadLeaveCS();
+		}
+
+	// Close stepping manager
+	if (iStepper)
+		{
+		NKern::ThreadEnterCS();
+		delete iStepper;
+		NKern::ThreadLeaveCS();
+		}
+
+	//close the debug process list
+	iDebugProcessList.Close();
+
+	DestroyDfcQ();
+
+	//close the code modifier
+	if (iInitialisedCodeModifier)
+		{
+		DebugSupport::CloseCodeModifier();
+		}
+	}
+
+void DRM_DebugChannel::DestroyDfcQ()
+	{
+	LOG_MSG("DRM_DebugChannel::DestroyDfcQ()");
+	if (iDfcQ)
+		{
+		NKern::ThreadEnterCS();
+		iDfcQ->Destroy();
+		NKern::ThreadLeaveCS();
+		}
+	}
+
+//
+// DRM_DebugChannel::DoCreate
+//
+TInt DRM_DebugChannel::DoCreate(TInt /*aUnit*/, const TDesC* anInfo, const TVersion& aVer)
+	{
+	LOG_MSG("DRM_DebugChannel::DoCreate()");
+	TInt err = Kern::CreateClientDataRequest(iAsyncGetValueRequest);
+	if(err != KErrNone)
+		return err;
+
+	if (!Kern::QueryVersionSupported(TVersion(KMajorVersionNumber, KMinorVersionNumber, KBuildVersionNumber), aVer))
+		return KErrNotSupported;
+
+	// Do the security check here so that any arbitrary application doesn't make
+	// use of Trk kernel driver.
+	if (!DoSecurityCheck())
+		{
+		LOG_MSG("DRM_DebugChannel::DoCreate() - permission denied!");
+			return KErrPermissionDenied;
+		}
+
+	if (anInfo)
+		{
+		// this is the end address of the user library.
+		// this doesn't seem to be valid for EKA2.
+		// right now we dont need this for EKA2 since we are not worried
+		// about kernel being stopped as kernel is multithreaded.
+		// just retaining this for future use.
+		TBuf8<32> buf;
+		TInt err = Kern::ThreadRawRead(iClientThread, anInfo, &buf, 32);
+		if(err != KErrNone)
+			return err;
+		}
+
+	// Allocate a D_RMD_Breakpoints class as a breakpoint manager
+	NKern::ThreadEnterCS();
+	iBreakManager = new D_RMD_Breakpoints(this);
+	NKern::ThreadLeaveCS();
+	if (iBreakManager == NULL)
+		{
+		LOG_MSG("DRM_DebugChannel::DRM_DebugChannel - could not construct breakpoint manager");
+		return KErrNoMemory;
+		}
+
+	// Initialise the new breakpoint manager object
+	iBreakManager->Init();
+
+	// Allocate a DRMDStepping class as the stepping manager
+	NKern::ThreadEnterCS();
+	iStepper = new DRMDStepping(this);
+	NKern::ThreadLeaveCS();
+	if (iStepper == NULL)
+		{
+		LOG_MSG("DRM_DebugChannel::DRM_DebugChannel - could not construct stepper manager");
+		return KErrNoMemory;
+		}
+
+	// Initialize the code modifier for managing breakpoints.
+	TUint caps; //ignored for now
+	err = DebugSupport::InitialiseCodeModifier(caps, NUMBER_OF_MAX_BREAKPOINTS);
+	//if code modifier initializer failed,
+	//return here, since we can't set an breakpoints
+	if(err != KErrNone)
+		{
+		return err;
+		}
+	else
+		{
+		iInitialisedCodeModifier = ETrue;
+		}
+
+	//create and set the driver's Dfc queue
+	err = CreateDfcQ();
+	if(err != KErrNone)
+		{
+		LOG_MSG("DRM_DebugChannel::DoCreate() Creating Dfc queue failed.");
+		}
+	SetDfcQ(iDfcQ);
+
+	iMsgQ.Receive();
+
+	iEventHandler = new DRM_DebugEventHandler;
+	if (!iEventHandler)
+		return KErrNoMemory;
+	err = iEventHandler->Create(iDevice, this, iClientThread);
+	if (err != KErrNone)
+		return err;
+
+	//return KErrNone;
+	return iEventHandler->Start();
+	}
+
+/**
+Forward call to either synch or asynch methods while serialising all calls via lock.
+ 
+Protect access via a the event handler lock to 
+serialise all calls and protect concurrent access to data structures
+
+@param aMsg pointer to a TMessageBase object 
+
+@return error returned by called methods
+
+@see DRM_DebugEventHandler::HandleSpecificEvent where lock is also used
+@see DRM_DebugEventHandler::iProtectionLock
+
+*/
+TInt DRM_DebugChannel::SendMsg(TMessageBase* aMsg)
+	{
+	DThread * currThread = &Kern::CurrentThread();
+
+	iEventHandler->LockDataAccess();
+	LOG_MSG3("DRM_DebugChannel::SendMsg() currThread = 0x%08x, iClientThread=0x%08x", currThread, iClientThread );
+	
+	TThreadMessage& m = *(TThreadMessage*)aMsg;
+	TInt id = m.iValue;
+	TInt err = KErrNone;
+
+	if (id != (TInt)ECloseMsg && id != KMaxTInt && id < 0)
+		{
+		// DoRequest
+		TRequestStatus* pStatus = (TRequestStatus*)m.Ptr0();
+		err = SendRequest(aMsg);
+		if (err != KErrNone)
+			Kern::RequestComplete(pStatus,err);
+		}
+	else
+		{
+		err = DLogicalChannel::SendMsg(aMsg);
+		}
+	
+	iEventHandler->ReleaseDataAccess();
+	return err;
+	}
+
+//
+// DRM_DebugChannel::SendRequest
+//
+TInt DRM_DebugChannel::SendRequest(TMessageBase* aMsg)
+	{
+	LOG_MSG("DRM_DebugChannel::SendRequest()");
+
+	TThreadMessage& m = *(TThreadMessage*)aMsg;
+	TInt function = ~m.iValue;
+	TRequestStatus* pStatus = (TRequestStatus*)m.Ptr0();
+	TAny* a1 = m.Ptr1();
+
+	TInt err = KErrNotSupported;
+	switch(function)
+		{
+		case RRM_DebugDriver::ERequestGetEvent:
+			err = PreAsyncGetValue((TEventInfo*)a1,pStatus);
+			break;
+		}
+	if (err == KErrNone)
+		err = DLogicalChannel::SendMsg(aMsg);
+	return err;
+	}
+
+//
+// DRM_DebugChannel::PreAsyncGetValue
+//
+TInt DRM_DebugChannel::PreAsyncGetValue(TEventInfo* aValue, TRequestStatus* aStatus)
+	{
+	LOG_MSG3("DRM_DebugChannel::PreAsyncGetValue() TEventInfo=0x%08x, TRequestStatus=0x%08x",
+		aValue, aStatus );
+	
+	iAsyncGetValueRequest->Reset();
+	
+	TInt err = iAsyncGetValueRequest->SetStatus(aStatus);
+	if (err != KErrNone)
+		return err;
+	
+	iAsyncGetValueRequest->SetDestPtr(aValue);
+	return KErrNone;
+	}
+
+/**
+  Create the Dfc queue for receiving messages
+  */
+TInt DRM_DebugChannel::CreateDfcQ()
+	{
+	LOG_MSG("DRM_DebugChannel::CreateDfcQ()");
+	TInt r = Kern::DynamicDfcQCreate(iDfcQ, KRmDebugDriverThreadPriority, KRM_DebugDriverName);
+
+	if (r == KErrNone)
+		iDfcQ->SetRealtimeState(ERealtimeStateOff);
+	return r;
+	}
+
+//
+// DRM_DebugChannel::DoCancel
+//
+// New: The cancel call does not take an enum parameter describing
+// the request to be cancelled. Rather it supplies a pointer
+// to a user-side struct defining the cancellation
+//
+void DRM_DebugChannel::DoCancel(TInt aReqNo)
+	{
+	LOG_MSG("DRM_DebugChannel::DoCancel()");
+
+	TRMD_DebugCancelInfo info;
+
+	TInt err = Kern::ThreadRawRead(iClientThread,(TAny*)aReqNo,(TAny*)&info,sizeof(info));
+	if (err != KErrNone)
+		{
+		// How do we cancel something we know nothing about???
+		LOG_MSG("DRM_DebugChannel::DoCancel - bad arguments");
+		return;
+		}
+
+	DDebugAgent* debugAgent = TheDProcessTracker.FindAgentForProcessAndId(info.iProcessName, info.iAgentId);
+	if (debugAgent == NULL)
+		{
+		// Bad agent means there is no tracking agent
+		LOG_MSG2("Cannot locate debug agent with pid 0x%x", info.iAgentId);
+		return;
+		}
+
+	// Agent completes/pends the request as appropriate.
+	debugAgent->CancelGetEvent();
+
+	}
+
+//
+// DRM_DebugChannel::DoRequest
+//
+void DRM_DebugChannel::DoRequest(TInt aReqNo, TRequestStatus* aStatus, TAny* a1, TAny* a2)
+	{
+	LOG_MSG4("DRM_DebugChannel::DoRequest(), iClientThread=0x%08x, tid=0x%08x, TRequestStatus=0x%08x", 
+		iClientThread, I64LOW(iClientThread->iId), aStatus);
+
+	switch(aReqNo)
+		{
+		case RRM_DebugDriver::ERequestGetEvent:
+			{
+			TEventMetaData eventMetaData;
+			TInt err = Kern::ThreadRawRead(iClientThread, a2, (TUint8 *)&eventMetaData, sizeof(TEventMetaData) );
+			if (err != KErrNone)
+				{
+				LOG_MSG("Error: could not read argument data from the DSS (TEventMetaData)");
+
+				// We could not read information from the user, so the a2 argument is probably wrong
+				Kern::RequestComplete(iClientThread, aStatus, KErrArgument);
+				return;
+				}
+
+			DDebugAgent* debugAgent = TheDProcessTracker.FindAgentForProcessAndId(eventMetaData.iTargetProcessName, eventMetaData.iDebugAgentProcessId);
+			if (debugAgent == NULL)
+				{
+				// Bad agent means there is no tracking agent
+				LOG_MSG2("Cannot locate debug agent with pid 0x%x", eventMetaData.iDebugAgentProcessId);
+				Kern::RequestComplete(iClientThread, aStatus, KErrNotFound);
+				return;
+				}
+			// Agent completes/pends the request as appropriate.
+			debugAgent->GetEvent(iAsyncGetValueRequest, iClientThread);
+
+			break;
+			}
+		default:
+			{
+			// Should not get here!
+			LOG_MSG2("DRM_DebugChannel::DoRequest was passed unsupported request aReqNo=%d", aReqNo );
+			Kern::RequestComplete(iClientThread, aStatus, KErrNotSupported);
+			}
+		}
+	}
+
+//
+// DRM_DebugChannel::DoControl
+//
+TInt DRM_DebugChannel::DoControl(TInt aFunction, TAny* a1, TAny* a2)
+	{
+	LOG_MSG("DRM_DebugChannel::DoControl()");
+
+	LOG_MSG2("DoControl Function %d", aFunction);
+
+	TInt err = KErrNone;
+	DThread* threadObj = NULL;
+	// Open a thread handle for the operations that need one
+	switch (aFunction)
+		{
+		case RRM_DebugDriver::EControlSuspendThread:
+		case RRM_DebugDriver::EControlResumeThread:
+		case RRM_DebugDriver::EControlStepRange:
+		case RRM_DebugDriver::EControlReadMemory:
+		case RRM_DebugDriver::EControlWriteMemory:
+		case RRM_DebugDriver::EControlReadRegistersLegacy:
+		case RRM_DebugDriver::EControlWriteRegistersLegacy:
+		case RRM_DebugDriver::EControlReadRegisters:
+		case RRM_DebugDriver::EControlWriteRegisters:
+			{
+			NKern::ThreadEnterCS();
+			threadObj = DebugUtils::OpenThreadHandle((TUint32)a1);
+			if (!threadObj)
+				{
+				NKern::ThreadLeaveCS();
+				return KErrBadHandle;
+				}
+			break;
+			}
+		default:
+			break;
+		}
+
+	switch(aFunction)
+		{
+		/* Security first */
+		case RRM_DebugDriver::EControlIsDebuggable:
+			{
+			err = IsDebuggable((TUint32)a1);
+			break;
+			}
+		case RRM_DebugDriver::EControlSetBreak:
+			{
+			err = SetBreak((TSetBreakInfo*)a1);
+			break;
+			}
+		case RRM_DebugDriver::EControlClearBreak:
+			{
+			err = iBreakManager->DoClearBreak((TInt32)a1);
+			break;
+			}
+		case RRM_DebugDriver::EControlModifyBreak:
+			{
+			err = iBreakManager->DoModifyBreak((TModifyBreakInfo*)a1);
+			break;
+			}
+		case RRM_DebugDriver::EControlModifyProcessBreak:
+			{
+			err = iBreakManager->DoModifyProcessBreak((TModifyProcessBreakInfo*)a1);
+			break;
+			}
+		case RRM_DebugDriver::EControlBreakInfo:
+			{
+			err = iBreakManager->DoBreakInfo((TGetBreakInfo*)a1);
+			break;
+			}
+		case RRM_DebugDriver::EControlSuspendThread:
+			{
+			err = DoSuspendThread(threadObj);
+			break;
+			}
+		case RRM_DebugDriver::EControlResumeThread:
+			{
+			err = DoResumeThread(threadObj);
+			break;
+			}
+		case RRM_DebugDriver::EControlStepRange:
+			{
+			err = StepRange(threadObj, (TRM_DebugStepInfo*)a2);
+			break;
+			}
+		case RRM_DebugDriver::EControlReadMemory:
+			{
+			err = ReadMemory(threadObj, (TRM_DebugMemoryInfo*)a2);
+			break;
+			}
+		case RRM_DebugDriver::EControlWriteMemory:
+			{
+			err = WriteMemory(threadObj, (TRM_DebugMemoryInfo*)a2);
+			break;
+			}
+		case RRM_DebugDriver::EControlReadRegistersLegacy:
+			{
+			err = ReadRegistersLegacy(threadObj, (TRM_DebugRegisterInfo*)a2);
+			break;
+			}
+		case RRM_DebugDriver::EControlWriteRegistersLegacy:
+			{
+			err = WriteRegistersLegacy(threadObj, (TRM_DebugRegisterInfo*)a2);
+			break;
+			}
+		case RRM_DebugDriver::EControlReadRegisters:
+			{
+			err = ReadRegisters(threadObj, (TRM_DebugRegisterInformation*)a2);
+			break;
+			}
+		case RRM_DebugDriver::EControlWriteRegisters:
+			{
+			err = WriteRegisters(threadObj, (TRM_DebugRegisterInformation*)a2);
+			break;
+			}
+		case RRM_DebugDriver::EControlGetDebugFunctionalityBufSize:
+			{
+			LOG_MSG("RRM_DebugDriver::EControlGetDebugFunctionalityBufSize\n");
+
+			TDebugFunctionality df;
+
+			TUint size = df.GetDebugFunctionalityBufSize();
+
+			// Return size to user-side in a safe manner
+			err = Kern::ThreadRawWrite(iClientThread, a1, (TUint8*)&size, sizeof(TUint), iClientThread);
+			break;
+			}
+		case RRM_DebugDriver::EControlGetDebugFunctionality:
+			{
+			LOG_MSG("RRM_DebugDriver::EControlGetDebugFunctionality\n");
+
+			TDebugFunctionality df;
+
+			TUint32 dfsize = df.GetDebugFunctionalityBufSize();
+
+			// Alloc tmp buffer for Debug Functionality data
+			NKern::ThreadEnterCS();
+			TUint8* dfbuffer = (TUint8*)Kern::AllocZ(dfsize);
+			if (dfbuffer==NULL)
+				{
+				LOG_MSG2("Could not allocate memory for %d bytes\n",dfsize);
+				NKern::ThreadLeaveCS();
+				// could not allocate memory
+				return KErrNoMemory;
+				}
+
+			// Temporary descriptor to hold DF data
+			TPtr8 tmpPtr(dfbuffer,0,dfsize);
+
+			// Obtain the DF data
+			if (df.GetDebugFunctionality(tmpPtr) )
+				{
+				// Return the DF data to the user-side
+				err = Kern::ThreadDesWrite(iClientThread, a1, tmpPtr, 0, KChunkShiftBy0, iClientThread);
+				}
+			else
+				{
+				// Failed.
+				err = KErrGeneral;
+				}
+
+			// Free tmp buffer
+			Kern::Free(dfbuffer);
+			NKern::ThreadLeaveCS();
+			break;
+			}
+		case RRM_DebugDriver::EControlAttachProcess:
+			{
+			LOG_MSG("RRM_DebugDriver::EControlAttachProcess");
+
+			err = AttachProcess(a1,a2);
+			break;
+			}
+		case RRM_DebugDriver::EControlDetachProcess:
+			{
+			LOG_MSG("RRM_DebugDriver::EControlDetachProcess");
+
+			err = DetachProcess(a1,a2);
+			break;
+			}
+		case RRM_DebugDriver::EControlDetachAgent:
+			{
+			LOG_MSG("RRM_DebugDriver::EControlDetachAgent");
+
+			err = DetachAgent(a1,a2);
+			break;
+			}
+		case RRM_DebugDriver::EControlSetEventAction:
+			{
+			LOG_MSG("RRM_DebugDriver::EControlSetEventAction");
+
+			err = SetEventAction(a1,a2);
+			break;
+			}
+		case RRM_DebugDriver::EControlGetMemoryOperationMaxBlockSize:
+			{
+			LOG_MSG("RRM_DebugDriver::EControlGetMemoryOperationMaxBlockSize\n");
+
+			TUint32 maxSize = TDebugFunctionality::GetMemoryOperationMaxBlockSize();
+
+			// Return size to user-side in a safe manner
+			err = Kern::ThreadRawWrite(iClientThread, a1, (TUint8*)&maxSize, sizeof(TUint32), iClientThread);
+			break;
+			}
+		case RRM_DebugDriver::EControlGetList:
+			{
+			LOG_MSG("RRM_DebugDriver::EControlGetList\n");
+			err = GetList((TListInformation*)a1);
+			break;
+			}
+		case RRM_DebugDriver::EControlStep:
+			{
+			LOG_MSG("RRM_DebugDriver::EControlStep\n");
+
+			err = Step((TUint32)a1,(TUint32)a2);
+			break;
+			}
+		case RRM_DebugDriver::EControlKillProcess:
+			{
+			LOG_MSG("RRM_DebugDriver::EControlKillProcess\n");
+
+			err = KillProcess((TUint32)a1,(TUint32)a2);
+			break;
+			}
+		default:
+			{
+			err = KErrGeneral;
+			}
+		}
+
+	if (KErrNone != err)
+		{
+		LOG_MSG2("Error %d from control function", err);
+		}
+
+	if (threadObj)
+		{
+		// Close the thread handle which has been opened by DebugUtils::OpenThreadHandle
+		threadObj->Close(NULL);
+		NKern::ThreadLeaveCS();
+		}
+
+	return err;
+	}
+
+void DRM_DebugChannel::HandleMsg(TMessageBase* aMsg)
+	{
+	LOG_MSG("DRM_DebugChannel::HandleMsg()");
+
+	TThreadMessage& m = *(TThreadMessage*)aMsg;
+	TInt id = m.iValue;
+
+	if (id == (TInt)ECloseMsg)
+		{
+		if (iEventHandler)
+			{
+			iEventHandler->Stop();
+			iEventHandler->Close();
+			iEventHandler = NULL;
+			}
+		m.Complete(KErrNone, EFalse);
+		return;
+		}
+
+	if (id == KMaxTInt)
+		{
+		// DoCancel
+		DoCancel(m.Int0());
+		m.Complete(KErrNone, ETrue);
+		return;
+		}
+
+	if (id < 0)
+		{
+		// DoRequest
+		TRequestStatus* pStatus = (TRequestStatus*)m.Ptr0();
+		DoRequest(~id, pStatus, m.Ptr1(), m.Ptr2());
+		m.Complete(KErrNone, ETrue);
+		}
+	else
+		{
+		// DoControl
+		TInt err = DoControl(id, m.Ptr0(), m.Ptr1());
+		m.Complete(err, ETrue);
+		}
+	}
+
+//
+// DRM_DebugChannel::RemoveProcess
+//
+TBool DRM_DebugChannel::RemoveProcess(TAny* a1, TAny* a2)
+	{
+	LOG_MSG("DRM_DebugChannel::RemoveProcess()");
+
+	DProcess *aProcess = (DProcess*)a1;
+
+	// Sanity check
+	if (!aProcess)
+		{
+		// No process was specified!
+		LOG_MSG("DRM_DebugChannel::RemoveProcess was called with an invalid process ID");
+		return EFalse;
+		}
+
+	// this is called when a process dies.  we want to mark any breakpoints in this
+	// process space as obsolete.  the main reason for this is so we don't return
+	// an error when the host debugger tries to clear breakpoints for the process
+
+	TUint32 codeAddress = 0;
+	TUint32 codeSize = 0;
+
+	LOG_EVENT_MSG2("Process being removed, Name %S", aProcess->iName);
+
+	DCodeSeg* codeSeg = aProcess->iCodeSeg;
+
+	if (codeSeg)
+		{
+		TModuleMemoryInfo processMemoryInfo;
+		TInt err = codeSeg->GetMemoryInfo(processMemoryInfo, aProcess);
+		if (err != KErrNone)
+			{
+			codeAddress = processMemoryInfo.iCodeBase;
+			codeSize = processMemoryInfo.iCodeSize;
+			}
+		else
+			{
+			LOG_MSG2("Error in getting memory info: %d", err);
+			}
+		}
+
+	if (!codeAddress || !codeSize)
+		{
+		LOG_EVENT_MSG2("Code segment not available for process %d", aProcess->iId);
+		// make sure there is not already a breakpoint at this address
+		for (TInt i = 0; i < iDebugProcessList.Count(); i++)
+			{
+			if (iDebugProcessList[i].iId == aProcess->iId)
+				{
+				codeAddress = iDebugProcessList[i].iCodeAddress;
+				codeSize = iDebugProcessList[i].iCodeSize;
+
+				//now remove from the list
+				iDebugProcessList.Remove(i);
+				break;
+				}
+			}
+		}
+
+	if (!codeAddress || !codeSize)
+		{
+		return EFalse;
+		}
+
+	iBreakManager->RemoveBreaksForProcess(aProcess->iId, codeAddress, codeSize);
+	return EFalse;
+	}
+
+//
+// DRM_DebugChannel::StartThread
+//
+TBool DRM_DebugChannel::StartThread(TAny* a1, TAny* a2)
+	{
+	LOG_EVENT_MSG("DRM_DebugChannel::StartThread()");
+
+	DThread *aThread = (DThread*)a1;
+	if(!aThread)
+		{
+		LOG_MSG("Error getting DThread object");
+		__NK_ASSERT_DEBUG(aThread);
+		return EFalse;
+		}
+
+	//a2 points to the thread creating the new thread.
+	//We have no use for it at the moment so just ignore it for now
+
+	TDriverEventInfo info;
+	info.iEventType = EEventsStartThread;
+	info.iThreadId = aThread->iId;
+	info.iThreadIdValid = ETrue;
+	DProcess* owningProcess = aThread->iOwningProcess;
+	if(owningProcess)
+		{
+		info.iProcessId = owningProcess->iId;
+		info.iProcessIdValid = ETrue;
+		DCodeSeg* p = owningProcess->iCodeSeg;
+		if(p && p->iFileName)
+			{
+			info.iFileName.Copy(*(p->iFileName));
+			TheDProcessTracker.NotifyAgentsForProcessEvent(*p->iFileName, info);
+			}
+		else
+			{
+			if(p)
+				{
+				LOG_EVENT_MSG("\tCode segment name missing");
+				}
+			else
+				{
+				LOG_EVENT_MSG("\tCode segment is NULL");
+				}
+			}
+		}
+	return EFalse;
+	}
+
+//
+// DRM_DebugChannel::HandleAddProcessEvent
+//
+TBool DRM_DebugChannel::HandleAddProcessEvent(TAny* a1, TAny* a2)
+	{
+	LOG_EVENT_MSG("DRM_DebugChannel::AddProcess()");
+
+	DProcess *aProcess = (DProcess*)a1;
+	// a2 points to the thread creating the new process.
+	DThread *aThread = (DThread*)a2;
+
+	if(!aProcess)
+		{
+		LOG_MSG("Error getting DProcess object");
+		__NK_ASSERT_DEBUG(aProcess);
+		return EFalse;
+		}
+
+	TDriverEventInfo info;
+	info.iEventType = EEventsAddProcess;
+	info.iProcessId = aProcess->iId;
+
+	info.iCreatorThreadId  = aThread ? aThread->iId : 0;
+	info.iProcessIdValid = ETrue;
+
+	// Copy TUids
+	info.iUids = aProcess->iUids;
+
+	info.iUidsValid = ETrue;
+
+	// copy name of the process
+	if (aProcess->iName)
+		{
+		// copy the name of the process
+		info.iFileName.Copy(*aProcess->iName);
+		// AddProcess event does not have fully-qualified path, it has "filename.exe"
+		// So we allow a less-precise match by passing in ETrue
+		TheDProcessTracker.NotifyAgentsForProcessEvent(*aProcess->iName, info, ETrue);
+		}
+	else
+		{
+		LOG_EVENT_MSG("DRM_DebugChannel::AddProcess - No iName for this process");
+		}
+
+	return EFalse;
+	}
+
+//
+// DRM_DebugChannel::HandleRemoveProcessEvent
+//
+TBool DRM_DebugChannel::HandleRemoveProcessEvent(TAny* a1, TAny* a2)
+	{
+	LOG_MSG("DRM_DebugChannel::HandleRemoveProcessEvent()");
+
+	DProcess *aProcess = (DProcess*)a1;
+	if(!aProcess)
+		{
+		LOG_MSG("Error getting DProcess object");
+		__NK_ASSERT_DEBUG(aProcess);
+		return EFalse;
+		}
+
+	// a2 points to the thread creating the new process.
+	// We have no use for it at the moment so just ignore it for now
+	// Also, it may not be known and therefore NULL
+
+	TDriverEventInfo info;
+	info.iEventType = EEventsRemoveProcess;
+	info.iProcessId = aProcess->iId;
+	info.iProcessIdValid = ETrue;
+
+	// copy name of the process
+	if (aProcess->iName)
+		{
+		info.iFileName.Copy(*aProcess->iName);
+
+		// RemoveProcess event does not have fully-qualified path, it has "filename.exe"
+		// So we allow a less-precise match by passing in ETrue
+		TheDProcessTracker.NotifyAgentsForProcessEvent(*aProcess->iName, info, ETrue);
+		}
+	else
+		{
+		LOG_EVENT_MSG("DRM_DebugChannel::AddProcess - No iName for this process");
+		}
+
+	return EFalse;
+	}
+
+//
+// DRM_DebugChannel::AddLibrary
+//
+TBool DRM_DebugChannel::AddLibrary(TAny* a1, TAny* a2)
+	{
+	LOG_EVENT_MSG("DRM_DebugChannel::AddLibrary()");
+
+	DLibrary *aLibrary = (DLibrary*)a1;
+	DThread *aThread = (DThread*)a2;
+
+	// sanity check
+	if (!aLibrary)
+		{
+		LOG_EVENT_MSG("DRM_DebugChannel::AddLibrary called with no library specified");
+		return EFalse;
+		}
+
+	if (!aThread)
+		{
+		LOG_EVENT_MSG("DRM_DebugChannel::AddLibrary called with no thread specified");
+		return EFalse;
+		}
+
+#ifdef __LOG_EVENTS__
+	TFullName threadName;
+	aThread->FullName(threadName);
+	LOG_EVENT_MSG3(("Lib %S loaded by %S"), aLibrary->iName, &threadName);
+#endif
+
+	if (aThread)
+		{
+		// make sure this is not the debugger thread
+		if ((aThread != iClientThread) && (aThread->iOwningProcess->iId != iClientThread->iOwningProcess->iId))
+			{
+			TDriverEventInfo info;
+
+			info.iEventType = EEventsAddLibrary;
+			info.iProcessId = aThread->iOwningProcess->iId;
+			info.iProcessIdValid = ETrue;
+			info.iThreadId = aThread->iId;
+			info.iThreadIdValid = ETrue;
+
+			//get the code address
+			DCodeSeg* codeSeg = aLibrary->iCodeSeg;
+			if (!codeSeg)
+				{
+				LOG_EVENT_MSG2("Code segment not available for library %S", aLibrary->iName);
+				return EFalse;
+				}
+
+			// Uid3
+			info.iUids = codeSeg->iUids;
+			info.iUidsValid = ETrue;
+
+			TModuleMemoryInfo memoryInfo;
+			TInt err = codeSeg->GetMemoryInfo(memoryInfo, NULL); //NULL for DProcess should be ok;
+			if (err != KErrNone)
+				{
+				LOG_EVENT_MSG2("Error in getting memory info: %d", err);
+				return EFalse;
+				}
+
+			info.iCodeAddress = memoryInfo.iCodeBase;
+			info.iDataAddress = memoryInfo.iInitialisedDataBase;
+
+			info.iFileName.Copy(*(aLibrary->iName)); //just the name, without uid info.
+
+			//queue up or complete the event
+			info.iArg1 = a1;
+			info.iArg2 = a2;
+			NotifyAgentsFromEventPid(info);
+			}
+
+		}
+	return EFalse;
+	}
+
+//
+// DRM_DebugChannel::RemoveLibrary
+//
+TBool DRM_DebugChannel::RemoveLibrary(TAny* a1, TAny* a2)
+	{
+	LOG_EVENT_MSG("DRM_DebugChannel::RemoveLibrary()");
+	DLibrary *aLibrary = (DLibrary*)a1;
+
+	// sanity check
+	if (!aLibrary)
+		{
+		LOG_EVENT_MSG("DRM_DebugChannel::RemoveLibrary called with no library specified");
+		return EFalse;
+		}
+
+	LOG_EVENT_MSG2(("Lib unloaded: %S"), aLibrary->iName);
+
+	// this is called when all handles to this library have been closed.  this can happen when a process dies, or when a dll is
+	// unloaded while the process lives on.  in former case, we don't need to notify the host debugger because that process is
+	// dying anyway.  for the latter case, we do need to notify the host so it can unload the symbolics, etc.
+
+	DThread* aThread = &Kern::CurrentThread();
+
+	if ((aThread) &&
+			(aThread != iClientThread) &&
+			(aThread->iOwningProcess->iId != iClientThread->iOwningProcess->iId))
+		{
+		//the library gets unloaded only when the mapcount is 0.
+		if (aLibrary->iMapCount != 0)
+			return EFalse;
+
+		DCodeSeg* codeSeg = aLibrary->iCodeSeg;
+		if (!codeSeg)
+			{
+			LOG_EVENT_MSG2("Code segment not available for library %S", aLibrary->iName);
+			return EFalse;
+			}
+
+		TModuleMemoryInfo processMemoryInfo;
+		TInt err = codeSeg->GetMemoryInfo(processMemoryInfo, NULL); //passing NULL for the DProcess argument should be ok;
+		if (err != KErrNone)
+			{
+			LOG_EVENT_MSG2("Error in getting memory info: %d", err);
+			return EFalse;
+			}
+
+		TUint32 codeAddress = processMemoryInfo.iCodeBase;
+		TUint32 codeSize = processMemoryInfo.iCodeSize;
+
+		// first invalidate all breakpoints that were set in the library code
+		iBreakManager->InvalidateLibraryBreakPoints(codeAddress, codeSize);
+		DProcess *process = &Kern::CurrentProcess();
+		RArray<SCodeSegEntry>* dynamicCode = &(process->iDynamicCode);
+
+		for (TInt j=0; j<dynamicCode->Count(); j++)
+			{
+			if ((*dynamicCode)[j].iLib == aLibrary)
+				{
+				TDriverEventInfo info;
+
+				info.iEventType = EEventsRemoveLibrary;
+				info.iFileName.Copy(*(aLibrary->iName)); //lib name without uid info
+				//info.iFileName.ZeroTerminate();
+				info.iProcessId = process->iId;
+				info.iProcessIdValid = ETrue;
+				info.iThreadId = 0xFFFFFFFF; // don't care!
+				info.iThreadIdValid = EFalse;
+				// Uid3
+				info.iUids = codeSeg->iUids;
+				info.iUidsValid = ETrue;
+
+				//queue up or complete the event
+				info.iArg1 = a1;
+				info.iArg2 = a2;
+				NotifyAgentsFromEventPid(info);
+				}
+			}
+		}
+	return EFalse;
+	}
+
+//
+// DRM_DebugChannel::HandleEventKillThread
+//
+TBool DRM_DebugChannel::HandleEventKillThread(TAny* a1, TAny* a2)
+	{
+	DThread* currentThread = &Kern::CurrentThread();
+
+	// a1 should point to the current thread, check this to make sure it does
+	__NK_ASSERT_DEBUG((DThread*)a1 == currentThread);
+
+	TDriverEventInfo info;
+
+	LOG_MSG5(" HandleEventKillThread for thread 0x%x, CritScount=%d, suspCnt=%d, waitObj=0x%x", 
+			currentThread->iId, 
+			currentThread->iNThread.iCsCount, 
+			currentThread->iNThread.iSuspendCount,
+			currentThread->iWaitObj);
+
+	info.iProcessId = currentThread->iOwningProcess->iId;
+	info.iProcessIdValid = ETrue;
+	info.iThreadId = currentThread->iId;
+	info.iThreadIdValid = ETrue;
+	
+	TInt err = ReadKernelRegisterValue(currentThread, 14, info.iCurrentPC);
+	if(err != KErrNone)
+		{
+		LOG_EVENT_MSG2("DRM_DebugChannel::HandleEventKillThread - Non-zero error code discarded: %d", err);
+		}
+
+	LOG_MSG5(" HandleEventKillThread for thread exit category=%S reason=%d, exitType=0x%x, PC=0x%x",
+			&currentThread->iExitCategory,
+	 	 	 currentThread->iExitReason, 
+	 		 currentThread->iExitType,
+			 info.iCurrentPC);
+			
+	if (currentThread->iExitType == EExitPanic)
+		{
+		info.iPanicCategory.Copy(currentThread->iExitCategory);
+		}
+	info.iExceptionNumber = currentThread->iExitReason;
+	info.iExitType = currentThread->iExitType;
+	info.iEventType = EEventsKillThread;
+	info.iThreadFlags = currentThread->iFlags;
+
+	// remove all the breakpoints in this thread, whether we are debugging it or not.
+	iBreakManager->DoRemoveThreadBreaks(info.iThreadId);
+
+	info.iArg1 = a1;
+	info.iArg2 = a2;
+	NotifyAgentsFromEventPid(info);
+
+	return ETrue;
+	}
+
+//
+// DRM_DebugChannel::HandleSwException
+//
+TBool DRM_DebugChannel::HandleSwException(TAny* a1, TAny* a2)
+	{
+	LOG_EVENT_MSG("DRM_DebugChannel::HandleSwException");
+	TExcType aExcType = (TExcType)(TInt)a1;
+
+	TDriverEventInfo info;
+
+	DThread* currentThread = &Kern::CurrentThread();
+	if (!currentThread)
+		{
+		LOG_MSG("Error getting current thread");
+		__NK_ASSERT_DEBUG(currentThread);
+		return EFalse;
+		}
+
+	info.iProcessId = currentThread->iOwningProcess->iId;
+	info.iProcessIdValid = ETrue;
+	info.iThreadId = currentThread->iId;
+	info.iThreadIdValid = ETrue;
+	TInt err = ReadKernelRegisterValue(currentThread, PC_REGISTER, info.iCurrentPC);
+	if(err != KErrNone)
+		{
+		LOG_EVENT_MSG2("DRM_DebugChannel::HandleSwException - Non-zero error code discarded: %d", err);
+		}
+	info.iExceptionNumber = aExcType;
+	info.iEventType = EEventsSwExc;
+	info.iThreadFlags = currentThread->iFlags;
+	info.iArg1 = a1;
+	info.iArg2 = a2;
+
+	NotifyAgentsFromEventPid(info);
+
+	return EFalse;
+	}
+
+//
+// DRM_DebugChannel::HandleHwException
+//
+TBool DRM_DebugChannel::HandleHwException(TAny* a1, TAny* a2)
+	{
+	TArmExcInfo* aExcInfo = (TArmExcInfo*)a1;
+
+	// sanity check
+	if (!aExcInfo)
+		{
+		LOG_MSG("DRM_DebugChannel::HandleHwException called with no aExcInfo");
+		__NK_ASSERT_DEBUG(aExcInfo);
+		return EFalse;
+		}
+
+	TDriverEventInfo info;
+
+	DThread* currentThread = &Kern::CurrentThread();
+
+	if (!currentThread)
+		{
+		LOG_MSG("Error getting current thread");
+		__NK_ASSERT_DEBUG(currentThread);
+		return EFalse;
+		}
+
+	info.iProcessId = currentThread->iOwningProcess->iId;
+	info.iProcessIdValid = ETrue;
+	info.iThreadId = currentThread->iId;
+	info.iThreadIdValid = ETrue;
+	info.iRmdArmExcInfo.iFaultAddress= aExcInfo->iFaultAddress;
+	info.iRmdArmExcInfo.iFaultStatus= aExcInfo->iFaultStatus;
+
+	LOG_MSG5("DRM_DebugChannel::HandleHwException current thread = 0x%08x, CritSect count=%d,\n"
+		" iFaultAddress=0x%08x, iFaultStatus=0x%08x",
+		currentThread, currentThread->iNThread.iCsCount, aExcInfo->iFaultAddress, aExcInfo->iFaultStatus);
+
+
+	LOG_MSG3(" HandleHwException CsFunc=%d, suspCount=%d",
+			currentThread->iNThread.iCsFunction, currentThread->iNThread.iSuspendCount );  
+		
+	info.iRmdArmExcInfo.iR0= aExcInfo->iR0;
+	info.iRmdArmExcInfo.iR1= aExcInfo->iR1;
+	info.iRmdArmExcInfo.iR2= aExcInfo->iR2;
+	info.iRmdArmExcInfo.iR3= aExcInfo->iR3;
+
+	info.iRmdArmExcInfo.iR4= aExcInfo->iR4;
+	info.iRmdArmExcInfo.iR5= aExcInfo->iR5;
+	info.iRmdArmExcInfo.iR6= aExcInfo->iR6;
+	info.iRmdArmExcInfo.iR7= aExcInfo->iR7;
+	info.iRmdArmExcInfo.iR8= aExcInfo->iR8;
+	info.iRmdArmExcInfo.iR9= aExcInfo->iR9;
+	info.iRmdArmExcInfo.iR10= aExcInfo->iR10;
+	info.iRmdArmExcInfo.iR11= aExcInfo->iR11;
+	info.iRmdArmExcInfo.iR12= aExcInfo->iR12;
+
+	info.iRmdArmExcInfo.iR13= aExcInfo->iR13;
+	info.iRmdArmExcInfo.iR14= aExcInfo->iR14;
+	info.iRmdArmExcInfo.iR15= aExcInfo->iR15;
+
+	info.iRmdArmExcInfo.iCpsr= aExcInfo->iCpsr;
+	info.iRmdArmExcInfo.iR13Svc= aExcInfo->iR13Svc;
+	info.iRmdArmExcInfo.iR14Svc= aExcInfo->iR14Svc;
+	info.iRmdArmExcInfo.iSpsrSvc= aExcInfo->iSpsrSvc;
+	LOG_MSG5(" iCpsr=0x%x, iExcCode=0x%x, R14=0x%x, R15=0x%x",
+			aExcInfo->iCpsr, aExcInfo->iExcCode, aExcInfo->iR14, aExcInfo->iR15);
+
+	switch (aExcInfo->iExcCode)
+		{
+		case 0:
+			info.iExceptionNumber = EExcCodeAbort;
+			LOG_MSG(" iExcCode == 0 => EExcCodeAbort");
+			break;
+		case 1:
+			info.iExceptionNumber = EExcDataAbort;
+			LOG_MSG(" iExcCode == 1 => EExcDataAbort");
+			break;
+		case 2:
+			info.iExceptionNumber = EExcInvalidOpCode;
+			LOG_MSG(" iExcCode == 2 => EExcInvalidOpCode");
+			break;
+		default:
+			// new event? Something gone wrong?
+			__NK_ASSERT_DEBUG(EFalse);
+			return EFalse;
+		}
+
+	info.iEventType = EEventsHwExc;
+	info.iThreadFlags = currentThread->iFlags;
+
+	info.iArg1 = a1;
+	info.iArg2 = a2;
+
+	if(EExcInvalidOpCode == info.iExceptionNumber)
+		{
+		return HandleInvalidOpCodeException(info, currentThread);
+		}
+
+	NotifyAgentsFromEventPid(info);
+	return EFalse;
+	}
+
+//
+// DRM_DebugChannel::HandUserTrace
+//
+TBool DRM_DebugChannel::HandleUserTrace(TAny* a1, TAny* a2)
+	{
+	LOG_EVENT_MSG("DRM_DebugChannel::HandleUserTrace()");
+
+	DThread* currentThread = &Kern::CurrentThread();
+	if (!currentThread)
+		{
+		LOG_EVENT_MSG("Error getting current thread");
+		__NK_ASSERT_DEBUG(currentThread);
+		return EFalse;
+		}
+
+	TDriverEventInfo info;
+	info.iProcessId = currentThread->iOwningProcess->iId;
+	info.iProcessIdValid = ETrue;
+	info.iThreadId = currentThread->iId;
+	info.iThreadIdValid = ETrue;
+	info.iEventType = EEventsUserTrace;
+	info.iArg1 = a1;
+	info.iArg2 = a2;
+
+	TInt err = KErrNone;
+
+	//User Trace info
+	XTRAP(err, XT_DEFAULT, kumemget(info.iUserTraceText, info.iArg1, (TInt)a2));
+	if(KErrNone != err)
+		{
+		return EFalse;
+		}
+
+	info.iMessageStatus = ESingleMessage;
+
+	NotifyAgentsFromEventPid(info);
+
+	return EFalse;
+	}
+
+//
+// DRM_DebugChannel::HandleException
+//
+TBool DRM_DebugChannel::HandleInvalidOpCodeException(TDriverEventInfo& aEventInfo, DThread* aCurrentThread)
+	{
+	LOG_MSG("DRM_DebugChannel::HandleInvalidOpCodeException()");
+
+	TInt err = KErrNone;
+
+	TUint32 inst = KArmBreakPoint;
+	TInt instSize = 4;
+
+	// change these for thumb mode
+	TUint32 regValue;
+	err = ReadKernelRegisterValue(aCurrentThread, STATUS_REGISTER, regValue);
+	if(err != KErrNone)
+		{
+		LOG_MSG2("DRM_DebugChannel::HandleInvalidOpCodeException - Non-zero error code discarded: %d", err);
+		}
+
+	if (regValue & ECpuThumb)
+		{
+		inst = KThumbBreakPoint;
+		instSize = 2;
+		}
+
+	TUint32 instruction = 0;
+	err = Kern::ThreadRawRead(aCurrentThread, (TUint32 *)aEventInfo.iRmdArmExcInfo.iR15, (TUint8 *)&instruction, instSize);
+
+	if (KErrNone != err)
+		LOG_MSG2("Error reading instruction at currentpc: %d", err);
+
+	if (!memcompare((TUint8 *)&inst, instSize, (TUint8 *)&instruction, instSize))
+		{
+		TInt err = DoSuspendThread(aCurrentThread);
+		if(! ((KErrNone == err) || (KErrAlreadyExists == err)) )
+			{
+			LOG_MSG2("DRM_DebugChannel::HandleInvalidOpCodeException() Thread with id 0x%08x could not be suspended.", aCurrentThread->iId);
+			return EFalse;
+			}
+
+		// the exception was a breakpoint instruction.  see if we have a breakpoint at that address
+		TBreakEntry* breakEntry = NULL;
+		do
+			{
+			breakEntry = iBreakManager->GetNextBreak(breakEntry);
+			if (breakEntry && ((breakEntry->iThreadSpecific && breakEntry->iId == aEventInfo.iThreadId) || (!breakEntry->iThreadSpecific && breakEntry->iId == aEventInfo.iProcessId)) && breakEntry->iAddress == aEventInfo.iRmdArmExcInfo.iR15)
+				{
+				LOG_MSG2("Breakpoint with Id %d has been hit", breakEntry->iBreakId);
+
+				TBreakEntry tempBreakEntry = *breakEntry;
+
+				//change the event type to breakpoint type
+				aEventInfo.iEventType = breakEntry->iThreadSpecific ? EEventsBreakPoint : EEventsProcessBreakPoint;
+
+				// enable any breakpoints we had to disable for this thread
+				err = iBreakManager->DoEnableDisabledBreak(aEventInfo.iThreadId);
+				if (KErrNone != err)
+					LOG_MSG2("Error %d enabling disabled breakpoints", err);
+
+				// see if this is a temp breakpoint
+				if (iBreakManager->IsTemporaryBreak(*breakEntry))
+					{
+					// this was a temp breakpoint, so we need to clear it now
+					err = iBreakManager->DoClearBreak(breakEntry->iBreakId);
+					if (KErrNone != err)
+						LOG_MSG2("Error %d clearing temp breakpoint", err);
+
+					// Find out how many steps remain to be done
+
+					// reduce the number of steps to complete by 1
+					tempBreakEntry.iNumSteps--;
+
+					LOG_MSG2("There are %d steps remaining\n", tempBreakEntry.iNumSteps);
+
+					// New. If we have not finished do all the steps, continue stepping and don't notify event
+					if (tempBreakEntry.iNumSteps)
+						{
+						LOG_MSG("Continuing stepping...not telling the agent yet\n");
+						err = DoStepRange(aCurrentThread, aEventInfo.iRmdArmExcInfo.iR15, aEventInfo.iRmdArmExcInfo.iR15, ETrue, tempBreakEntry.iResumeOnceOutOfRange /*EFalse*/, tempBreakEntry.iNumSteps, ETrue);
+						if (err != KErrNone)
+							{
+							LOG_EVENT_MSG("Failed to continue stepping\n");
+
+							// what do we do? might as well stop here and tell the user
+							NotifyAgentsFromEventPid(aEventInfo);
+
+							return ETrue;
+							}
+
+						// continue as though no event occured. No need to suspend/resume anything...
+						LOG_MSG("Continuing to step\n");
+						return ETrue;
+						}
+
+					// Is this a case where we just want to continue?
+					if (tempBreakEntry.iResumeOnceOutOfRange)
+						{
+						LOG_MSG("PC is out of range, continuing thread");
+						DoResumeThread(aCurrentThread);
+
+						return ETrue;
+						}
+					}
+
+				// if the breakpoint is thread specific, make sure it's the right thread
+				// if not, just continue the thread.  take special care if it's the debugger
+				// thread.  if it hits a regular breakpoint, we NEVER want to stop at it.  if
+				// it hits a temp breakpoint, we're probably just stepping past a real breakpoint
+				// and we do need to handle it.
+				TBool needToResume = (tempBreakEntry.iThreadSpecific && tempBreakEntry.iId != aEventInfo.iThreadId) ||
+					(!tempBreakEntry.iThreadSpecific && tempBreakEntry.iId != aEventInfo.iProcessId);
+
+				if (needToResume)
+					{
+					LOG_MSG("breakpoint does not match threadId, calling DoResumeThread");
+					err = DoResumeThread(aCurrentThread);
+					if (KErrNone != err)
+						LOG_MSG2("Error in DoResumeThread: %d", err);
+
+					return EFalse;
+					}
+
+				//normal user break point, just notify the event
+				break;
+				}
+			} while(breakEntry);
+		}
+
+	NotifyAgentsFromEventPid(aEventInfo);
+
+	return (aEventInfo.iEventType == EEventsBreakPoint) || (aEventInfo.iEventType == EEventsProcessBreakPoint);
+	}
+
+//
+// DRM_DebugChannel::SetBreak
+//
+TInt DRM_DebugChannel::SetBreak(TSetBreakInfo* aBreakInfo)
+	{
+	LOG_MSG("DRM_DebugChannel::SetBreak()");
+
+	TInt err = KErrNone;
+
+	if (!aBreakInfo)
+		{
+		LOG_MSG("DRM_DebugChannel::SetBreak() was passed a NULL argument");
+		return KErrArgument;
+		}
+
+	//User side memory is not accessible directly
+	TSetBreakInfo info;
+	err = Kern::ThreadRawRead(iClientThread, aBreakInfo, (TUint8*)&info, sizeof(TSetBreakInfo));
+	if (err != KErrNone)
+		{
+		LOG_MSG("DRM_DebugChannel::SetBreak() was passed a bad argument");
+		return err;
+		}
+
+	DProcess* process = NULL;
+	NKern::ThreadEnterCS();
+	if(info.iThreadSpecific)
+		{
+		DThread* thread = DebugUtils::OpenThreadHandle(info.iId);
+		if(!thread)
+			{
+			LOG_MSG2("DRM_DebugChannel::SetBreak() Thread with id 0x%08x not found", info.iId);
+			}
+		else
+			{
+			process = DebugUtils::OpenProcessHandle(thread->iOwningProcess->iId);
+			thread->Close(NULL);
+			}
+		}
+	else
+		{
+		process = DebugUtils::OpenProcessHandle(info.iId);
+		if(!process)
+			{
+			LOG_MSG2("DRM_DebugChannel::SetBreak() Process with id 0x%08x not found", info.iId);
+			}
+		}
+
+	if (process == NULL)
+		{
+		NKern::ThreadLeaveCS();
+		return KErrNotFound;
+		}
+
+	TBool found = EFalse;
+	for(TInt i=0; i<iDebugProcessList.Count(); i++)
+		{
+		if(process->iId == iDebugProcessList[i].iId)
+			{
+			found = ETrue;
+			}
+		}
+
+	if(!found)
+		{
+		DCodeSeg* codeSeg = process->iCodeSeg;
+		if (!codeSeg)
+			{
+			LOG_MSG2("DRM_DebugChannel::SetBreak() Code seg for process with id 0x%08x not found", process->iId);
+			err = KErrNotFound;
+			}
+
+		TModuleMemoryInfo memoryInfo;
+		if (!err)
+			{
+			err = codeSeg->GetMemoryInfo(memoryInfo, process);
+			if (err != KErrNone)
+				{
+				LOG_MSG2("DRM_DebugChannel::SetBreak() Error getting memory info for process with id 0x%08x", process->iId);
+				}
+			}
+
+		if (!err)
+			{
+			//add this process to the list of processes that we are debugging
+			TProcessInfo processInfo(process->iId, memoryInfo.iCodeBase, memoryInfo.iCodeSize, memoryInfo.iInitialisedDataBase);
+			iDebugProcessList.Append(processInfo);
+			}
+		}
+
+	process->Close(NULL);
+	NKern::ThreadLeaveCS();
+
+	if (!info.iBreakId) //first check if the iId address is valid
+		return KErrArgument;
+
+	if (err == KErrNone)
+		{
+		TInt32 iBreakId;
+
+		err = iBreakManager->DoSetBreak(iBreakId, info.iId, info.iThreadSpecific, info.iAddress, info.iMode );
+
+		if (err == KErrNone)
+			{
+			err = Kern::ThreadRawWrite(iClientThread, (TUint8 *)info.iBreakId, &iBreakId, sizeof(TInt32), iClientThread);
+			}
+		}
+
+	return err;
+	}
+
+//
+// DRM_DebugChannel::StepRange
+//
+TInt DRM_DebugChannel::StepRange(DThread* aThread, TRM_DebugStepInfo* aStepInfo)
+	{
+	LOG_MSG("DRM_DebugChannel::StepRange()");
+
+	TInt err = KErrNone;
+
+	if (!aStepInfo)
+		return KErrArgument;
+
+	TRM_DebugStepInfo info(0, 0, 0);
+	err = Kern::ThreadRawRead(iClientThread, aStepInfo, (TUint8*)&info, sizeof(TRM_DebugStepInfo));
+
+	if (err != KErrNone)
+		return err;
+
+	err = DoStepRange(aThread, info.iStartAddress, info.iStopAddress, info.iStepInto, EFalse, ETrue);
+
+	return err;
+	}
+
+/**
+Read memory from a target thread and return the data to the client. If the
+memory block has breakpoints in it then the correct values are placed in the
+returned data
+
+@param aThread pointer to thread whose memory space the memory is to be read from
+@param aMemoryInfo information about what memory to read
+
+@return KErrNone if memory read successfully,
+        KErrArgument if aMemoryInfo is not initialised correctly,
+        KErrNoMemory if a temporary buffer could not be allocated,
+        KErrBadHandle if aThread is invalid,
+        or another of the system wide error codes
+*/
+TInt DRM_DebugChannel::ReadMemory(DThread* aThread, TRM_DebugMemoryInfo* aMemoryInfo)
+	{
+	LOG_MSG("DRM_DebugChannel::ReadMemory()");
+
+	TInt err = KErrNone;
+
+	if (!aMemoryInfo)
+		return KErrArgument;
+
+	TRM_DebugMemoryInfo info(0, 0, 0);
+	err = Kern::ThreadRawRead(iClientThread, aMemoryInfo, (TUint8*)&info, sizeof(TRM_DebugMemoryInfo));
+	if (err != KErrNone)
+		{
+		LOG_MSG2("DRM_DebugChannel::ReadMemory returning error %d after Kern::ThreadRawRead()", err);
+		return err;
+		}
+
+	if (!info.iData)
+		return KErrArgument;
+
+	NKern::ThreadEnterCS();
+	TUint8 *data = (TUint8*)Kern::Alloc(info.iLength);
+	NKern::ThreadLeaveCS();
+	if (!data)
+		{
+		return KErrNoMemory;
+		}
+
+	TPtr8 dataDes(data, info.iLength);
+
+	err = DoReadMemory(aThread, info.iAddress, info.iLength, dataDes);
+	if (err == KErrNone)
+		{
+		err = Kern::ThreadDesWrite(iClientThread, info.iData, dataDes, 0, KChunkShiftBy0, iClientThread);
+		if (err)
+			{
+			LOG_MSG2("DRM_DebugChannel::ReadMemory - Kern::ThreadDesWrite() returned error %d", err);
+			}
+		}
+
+	NKern::ThreadEnterCS();
+	Kern::Free(data);
+	NKern::ThreadLeaveCS();
+
+	return err;
+	}
+
+/**
+Attempt to write memory to aThread's address space
+
+@param aThread thread to whose address space memory is to be written
+@param aMemoryInfo memory info object representing the data to write
+
+@return KErrNone if memory written successfully,
+        KErrNoMemory if memory could not be allocated
+        KErrArgument if aMemoryInfo is NULL, if aMemoryInfo.iData is NULL,
+        if aMemoryInfo.iLength is greater than than the length of the passed
+        in descrptor
+        KErrBadHandle if aThread is invalid,
+	or another of the system wide error codes
+*/
+TInt DRM_DebugChannel::WriteMemory(DThread* aThread, TRM_DebugMemoryInfo* aMemoryInfo)
+	{
+	LOG_MSG("DRM_DebugChannel::WriteMemory()");
+
+	TInt err = KErrNone;
+
+	if (!aMemoryInfo)
+		return KErrArgument;
+
+	TRM_DebugMemoryInfo info(0, 0, 0);
+	err = Kern::ThreadRawRead(iClientThread, aMemoryInfo, (TUint8*)&info, sizeof(TRM_DebugMemoryInfo));
+	if (err != KErrNone)
+		return err;
+
+	if (!info.iData)
+		return KErrArgument;
+
+	NKern::ThreadEnterCS();
+	TUint8 *data = (TUint8*)Kern::Alloc(info.iLength);
+	NKern::ThreadLeaveCS();
+	if (!data)
+		{
+		return KErrNoMemory;
+		}
+
+	TPtr8 dataDes(data, info.iLength);
+
+	err = Kern::ThreadDesRead(iClientThread, info.iData, dataDes, 0);
+	if (err == KErrNone)
+		{
+		err = DoWriteMemory(aThread, info.iAddress, info.iLength, dataDes);
+		}
+
+	NKern::ThreadEnterCS();
+	Kern::Free(data);
+	NKern::ThreadLeaveCS();
+
+	return err;
+	}
+
+//
+// DRM_DebugChannel::ReadRegisters
+//
+TInt DRM_DebugChannel::ReadRegistersLegacy(DThread* aThread, TRM_DebugRegisterInfo* aRegisterInfo)
+	{
+	LOG_MSG("DRM_DebugChannel::ReadRegistersLegacy()");
+
+	TInt err = KErrNone;
+
+	if (!aRegisterInfo)
+		return KErrArgument;
+
+	TRM_DebugRegisterInfo info(0, 0, 0);
+	err = Kern::ThreadRawRead(iClientThread, aRegisterInfo, (TUint8*)&info, sizeof(TRM_DebugRegisterInfo));
+	if (err != KErrNone)
+		return err;
+
+	if (!info.iValues)
+		return KErrArgument;
+
+	TUint length = (info.iLastRegister - info.iFirstRegister + 1) * 4;
+
+	NKern::ThreadEnterCS();
+	TUint8 *values = (TUint8*)Kern::Alloc(length);
+	NKern::ThreadLeaveCS();
+	if (!values)
+		{
+		return KErrNoMemory;
+		}
+
+	TPtr8 valuesDes(values, length);
+
+	err = DoReadRegisters(aThread, info.iFirstRegister, info.iLastRegister, valuesDes);
+	if (err == KErrNone)
+		{
+		err = Kern::ThreadDesWrite(iClientThread, info.iValues, valuesDes, 0, KChunkShiftBy0, iClientThread);
+		}
+
+	NKern::ThreadEnterCS();
+	Kern::Free(values);
+	NKern::ThreadLeaveCS();
+
+	return err;
+	}
+
+/**
+Get listing information.
+
+@param aListInformation pointer to a TListInformation object containing the
+       user specified listings information
+
+@return KErrNone on success,
+        KErrTooBig if the kernel's data is too big to fit in the passed buffer,
+        KErrArgument if aListInformation is NULL,
+	or one of the other system-wide error codes
+*/
+TInt DRM_DebugChannel::GetList(TListInformation* aListInformation) const
+	{
+	LOG_MSG("DRM_DebugChannel::GetList()");
+
+	TInt err = KErrNone;
+
+	if(aListInformation == NULL)
+		{
+		return KErrArgument;
+		}
+
+	//read DSS' data into local structure
+	TListInformation info;
+	err = Kern::ThreadRawRead(iClientThread, aListInformation, (TUint8*)&info, sizeof(TListInformation));
+	if(err != KErrNone)
+		{
+		return err;
+		}
+
+	//check arguments
+	TPtr8 buffer(NULL, 0);
+	err = AllocAndReadDes(iClientThread, *info.iBuffer, buffer);
+	if(err != KErrNone)
+		{
+		//need to free the buffer if it was allocated
+		if(err != KErrNoMemory)
+			{
+			NKern::ThreadEnterCS();
+			Kern::Free((TAny*)buffer.Ptr());
+			NKern::ThreadLeaveCS();
+			}
+		return err;
+		}
+
+	//get the list
+	TUint32 dataSize = 0;
+	TListManager manager;
+	err = KErrArgument;
+	switch(info.iType)
+		{
+		case EXipLibraries:
+			if(Debug::EScopeGlobal == info.iListScope)
+				{
+				err = manager.GetXipLibrariesList(buffer, dataSize);
+				}
+			break;
+
+		case EThreads:
+			if(Debug::EScopeGlobal == info.iListScope)
+				{
+				err = manager.GetGlobalThreadList(buffer, dataSize);
+				}
+			else if(Debug::EScopeProcessSpecific == info.iListScope)
+				{
+				err = manager.GetThreadListForProcess(buffer, dataSize, info.iTargetId);
+				}
+			else if(Debug::EScopeThreadSpecific == info.iListScope)
+				{
+				err = manager.GetThreadListForThread(buffer, dataSize, info.iTargetId);
+				}
+			break;
+
+		case EProcesses:
+			if(Debug::EScopeGlobal == info.iListScope)
+				{
+				err = manager.GetProcessList(buffer, dataSize);
+				}
+			break;
+
+		case ECodeSegs:
+			if(Debug::EScopeGlobal == info.iListScope)
+				{
+				err = manager.GetGlobalCodeSegList(buffer, dataSize);
+				}
+			else if(Debug::EScopeProcessSpecific == info.iListScope)
+				{
+				err = manager.GetCodeSegListForProcess(buffer, dataSize, info.iTargetId);
+				}
+			else if(Debug::EScopeThreadSpecific == info.iListScope)
+				{
+				err = manager.GetCodeSegListForThread(buffer, dataSize, info.iTargetId);
+				}
+			break;
+
+		default:
+			err = KErrNotSupported;
+		}
+
+	if(err == KErrNone)
+		{
+		//if no error then write the buffer back
+		err = Kern::ThreadDesWrite(iClientThread, info.iBuffer, buffer, 0, KChunkShiftBy0, iClientThread);
+		}
+
+	//write back the size of the data regardless of any error
+	TInt writeErr = Kern::ThreadRawWrite(iClientThread, info.iDataSize, (TUint8*)&dataSize, sizeof(TUint32), iClientThread);
+	if(writeErr != KErrNone)
+		{
+		//if there was an error writing the size return that error instead
+		err = writeErr;
+		}
+
+	//free the buffer
+	NKern::ThreadEnterCS();
+	Kern::Free((TAny*)buffer.Ptr());
+	NKern::ThreadLeaveCS();
+
+	return err;
+	}
+
+/**
+Read registers and store register data in aRegisterInfo
+
+@param aThread thread to read registers from
+@param aRegisterInfo structure specifying which registers to read and providing
+       descriptors to write the register data into
+
+@return KErrNone if registers were read successfully. Note that this does not
+        mean that all the registers could be read, the
+        aRegisterInfo.iRegisterFlags array should be checked as to whether each
+        individual register could be read,
+        KErrArgument if aRegisterInfo is NULL, or if any of the pointers that
+        are members of aRegisterInfo are NULL, if an unknown register is
+        specified or if the passed in register values buffer is too small
+        KErrNoMemory if there is insufficient memory,
+        KErrDied, if the thread with thread ID aThreadId is dead
+*/
+TInt DRM_DebugChannel::ReadRegisters(DThread* aThread, TRM_DebugRegisterInformation* aRegisterInfo) const
+	{
+	LOG_MSG("DRM_DebugChannel::ReadRegisters()");
+
+	TInt err = KErrNone;
+
+	if (!aRegisterInfo)
+		return KErrArgument;
+
+	TRM_DebugRegisterInformation info;
+	err = Kern::ThreadRawRead(iClientThread, aRegisterInfo, (TUint8*)&info, sizeof(TRM_DebugRegisterInformation));
+	if (err != KErrNone)
+		return err;
+
+	if ((!info.iRegisterIds) || (!info.iRegisterValues) || (!info.iRegisterFlags))
+		return KErrArgument;
+
+	//read ids from client thread
+	TPtr8 ids(NULL, 0);
+	err = AllocAndReadDes(iClientThread, *info.iRegisterIds, ids);
+	if(err != KErrNone)
+		{
+		if(err == KErrNoMemory)
+			{
+			NKern::ThreadEnterCS();
+			Kern::Free((TAny*)ids.Ptr());
+			NKern::ThreadLeaveCS();
+			}
+		return err;
+		}
+
+	//read values from client thread
+	TPtr8 values(NULL, 0);
+	err = AllocAndReadDes(iClientThread, *info.iRegisterValues, values, EFalse);
+	if(err != KErrNone)
+		{
+		if(err == KErrNoMemory)
+			{
+			NKern::ThreadEnterCS();
+			Kern::Free((TAny*)values.Ptr());
+			NKern::ThreadLeaveCS();
+			}
+
+		NKern::ThreadEnterCS();
+		Kern::Free((TAny*)ids.Ptr());
+		NKern::ThreadLeaveCS();
+		return err;
+		}
+
+	//read flags from client thread
+	TPtr8 flags(NULL, 0);
+	err = AllocAndReadDes(iClientThread, *info.iRegisterFlags, flags, EFalse);
+	if(err != KErrNone)
+		{
+		if(err == KErrNoMemory)
+			{
+			NKern::ThreadEnterCS();
+			Kern::Free((TAny*)flags.Ptr());
+			NKern::ThreadLeaveCS();
+			}
+		NKern::ThreadEnterCS();
+		Kern::Free((TAny*)ids.Ptr());
+		Kern::Free((TAny*)values.Ptr());
+		NKern::ThreadLeaveCS();
+		return err;
+		}
+
+	err = DoReadRegisters(aThread, ids, values, flags);
+	if (err == KErrNone)
+		{
+		err = Kern::ThreadDesWrite(iClientThread, info.iRegisterValues, values, 0, KChunkShiftBy0, iClientThread);
+		if(err == KErrNone)
+			{
+			err = Kern::ThreadDesWrite(iClientThread, info.iRegisterFlags, flags, 0, KChunkShiftBy0, iClientThread);
+			}
+		}
+
+	NKern::ThreadEnterCS();
+	Kern::Free((TAny*)ids.Ptr());
+	Kern::Free((TAny*)values.Ptr());
+	Kern::Free((TAny*)flags.Ptr());
+	NKern::ThreadLeaveCS();
+
+	return err;
+	}
+
+/**
+@deprecated use DRM_DebugChannel::WriteRegisters(DThread* aThread, TRM_DebugRegisterInformation* aRegisterInfo) instead
+*/
+TInt DRM_DebugChannel::WriteRegistersLegacy(DThread* aThread, const TRM_DebugRegisterInfo* aRegisterInfo)
+	{
+	LOG_MSG("DRM_DebugChannel::WriteRegistersLegacy()");
+
+	TInt err = KErrNone;
+
+	if (!aRegisterInfo)
+		return KErrArgument;
+
+	TRM_DebugRegisterInfo info(0, 0, 0);
+	err = Kern::ThreadRawRead(iClientThread, aRegisterInfo, (TUint8*)&info, sizeof(TRM_DebugRegisterInfo));
+	if (err != KErrNone)
+		return err;
+
+	if (!info.iValues)
+		return KErrArgument;
+
+	TUint length = (info.iLastRegister - info.iFirstRegister + 1) * 4;
+
+	NKern::ThreadEnterCS();
+	TUint8 *values = (TUint8*)Kern::Alloc(length);
+	NKern::ThreadLeaveCS();
+	if (!values)
+		{
+		return KErrNoMemory;
+		}
+
+	TPtr8 valuesDes(values, length);
+
+	err = Kern::ThreadDesRead(iClientThread, info.iValues, valuesDes, 0);
+	if (err == KErrNone)
+		{
+		err = DoWriteRegisters(aThread, info.iFirstRegister, info.iLastRegister, valuesDes);
+		}
+
+	NKern::ThreadEnterCS();
+	Kern::Free(values);
+	NKern::ThreadLeaveCS();
+
+	return err;
+	}
+
+/**
+Write registers and store flags data in aRegisterInfo
+
+@param aThread thread to write registers to
+@param aRegisterInfo structure specifying which registers to write and providing
+       descriptors to write the register flags data into
+
+@return KErrNone if registers were written successfully. Note that this does not
+        mean that all the registers could be written, the flags array
+        should be checked as to whether each individual register could be read,
+        KErrArgument if aRegisterInfo is NULL, or if any of the pointers that
+        are members of aRegisterInfo are NULL, if an unknown register is
+        specified or if the passed in register values buffer is too small, or
+        if aThread is NULL,
+        KErrGeneral if there was a problem initialising the register set,
+        KErrNoMemory if there is insufficient memory,
+        KErrDied, if the thread with thread ID aThreadId is dead
+*/
+TInt DRM_DebugChannel::WriteRegisters(DThread* aThread, TRM_DebugRegisterInformation* aRegisterInfo) const
+	{
+	LOG_MSG("DRM_DebugChannel::WriteRegisters()");
+
+	TInt err = KErrNone;
+
+	if (!aRegisterInfo)
+		return KErrArgument;
+
+	TRM_DebugRegisterInformation info;
+	err = Kern::ThreadRawRead(iClientThread, aRegisterInfo, (TUint8*)&info, sizeof(TRM_DebugRegisterInformation));
+	if (err != KErrNone)
+		return err;
+
+	if ((!info.iRegisterIds) || (!info.iRegisterValues) ||(!info.iRegisterFlags))
+		return KErrArgument;
+
+	//read ids from client thread
+	TPtr8 ids(NULL, 0);
+	err = AllocAndReadDes(iClientThread, *info.iRegisterIds, ids);
+	if(err != KErrNone)
+		{
+		if(err == KErrNoMemory)
+			{
+			NKern::ThreadEnterCS();
+			Kern::Free((TAny*)ids.Ptr());
+			NKern::ThreadLeaveCS();
+			}
+		return err;
+		}
+
+	//read values from client thread
+	TPtr8 values(NULL, 0);
+	err = AllocAndReadDes(iClientThread, *info.iRegisterValues, values);
+	if(err != KErrNone)
+		{
+		if(err == KErrNoMemory)
+			{
+			NKern::ThreadEnterCS();
+			Kern::Free((TAny*)values.Ptr());
+			NKern::ThreadLeaveCS();
+			}
+		NKern::ThreadEnterCS();
+		Kern::Free((TAny*)ids.Ptr());
+		NKern::ThreadLeaveCS();
+		return err;
+		}
+
+	//read flags from client thread
+	TPtr8 flags(NULL, 0);
+	err = AllocAndReadDes(iClientThread, *info.iRegisterFlags, flags, EFalse);
+	if(err != KErrNone)
+		{
+		if(err == KErrNoMemory)
+			{
+			NKern::ThreadEnterCS();
+			Kern::Free((TAny*)flags.Ptr());
+			NKern::ThreadLeaveCS();
+			}
+		NKern::ThreadEnterCS();
+		Kern::Free((TAny*)ids.Ptr());
+		Kern::Free((TAny*)values.Ptr());
+		NKern::ThreadLeaveCS();
+		return err;
+		}
+
+	err = DoWriteRegisters(aThread, ids, values, flags);
+	if(err == KErrNone)
+		{
+		err = Kern::ThreadDesWrite(iClientThread, info.iRegisterFlags, flags, 0, KChunkShiftBy0, iClientThread);
+		}
+
+	NKern::ThreadEnterCS();
+	Kern::Free((TAny*)ids.Ptr());
+	Kern::Free((TAny*)values.Ptr());
+	Kern::Free((TAny*)flags.Ptr());
+	NKern::ThreadLeaveCS();
+
+	return err;
+	}
+
+/**
+Suspends execution of the specified thread.
+
+@param aThread thread to resume
+
+@return KErrNone if there were no problems or KErrArgument if aThread is NULL
+*/
+TInt DRM_DebugChannel::DoSuspendThread(DThread *aThread)
+	{
+	LOG_MSG("DRM_DebugChannel::DoSuspendThread()");
+
+	if (!aThread)
+		{
+		LOG_MSG("Invalid dthread object");
+		return KErrArgument;
+		}
+
+	return TheDProcessTracker.SuspendThread(aThread);
+	}
+
+/**
+Resumes execution of the specified thread.
+
+@param aThread thread to resume
+
+@return KErrNone if there were no problems, KErrArgument if aThread is NULL
+        or an error value returned from DoStepRange()
+*/
+TInt DRM_DebugChannel::DoResumeThread(DThread *aThread)
+	{
+	if (!aThread)
+		return KErrArgument;
+
+	// get the current PC
+	TUint32 currentPC;
+	TInt err = ReadKernelRegisterValue(aThread, PC_REGISTER, currentPC);
+	if(err != KErrNone)
+		{
+		LOG_MSG2("DRM_DebugChannel::DoResumeThread : Read PC reg error %d.", err);
+		// Set to this value because 0 is dangerous since structures are usually 0-initialised,
+		// and could thus lead to a false positive in tmp break loop below
+		currentPC = 0xFFFFFFFF;
+		}
+	else
+		{
+		LOG_MSG2("DRM_DebugChannel::DoResumeThread(), pc=0x%x", currentPC);
+		}
+
+	// if there is a breakpoint at the current PC, we need to single step past it
+	TBreakEntry* breakEntry = NULL;
+	do
+		{
+		breakEntry = iBreakManager->GetNextBreak(breakEntry);
+		if(breakEntry && !iBreakManager->IsTemporaryBreak(*breakEntry))
+			{
+			if (breakEntry->iAddress == currentPC)
+				{
+                LOG_MSG2("DRM_DebugChannel::DoResumeThread : > DoStepRange(pc+1)=0x%x, resume once out of range", currentPC+1 );
+				return DoStepRange(aThread, currentPC, currentPC+1, ETrue, 1, ETrue);
+				}
+			}
+		} while(breakEntry);
+
+	return TheDProcessTracker.ResumeThread(aThread);
+	}
+
+//
+// DRM_DebugChannel::DoStepRange
+//
+TInt DRM_DebugChannel::DoStepRange(DThread *aThread, const TUint32 aStartAddress, const TUint32 aStopAddress, TBool aStepInto, TBool aResumeOnceOutOfRange, const TUint32 aNumSteps, TBool aUserRequest)
+	{
+	LOG_MSG("DRM_DebugChannel::DoStepRange()");
+
+	if (!aThread)
+		return KErrArgument;
+
+
+	TUint32 startAddress = (aStartAddress & 0x1) ? aStartAddress + 1 : aStartAddress;
+	TUint32 stopAddress = (aStopAddress & 0x1) ? aStopAddress + 1 : aStopAddress;;
+
+	// don't allow the user to step in the excluded ROM region.  this could be called
+	// internally however.  for example, the the special breakpoints we set to handle
+	// panics, exceptions, and library loaded events are in the user library, and we
+	// will need to step past the breakpoint before continuing the thread.
+	//if (aUserRequest && (startAddress >= iExcludedROMAddressStart) && (startAddress < iExcludedROMAddressEnd))
+	//{
+	//	return KErrNotSupported;
+	//}
+
+	// set the temp breakpoint, and disable the breakpoint at the current PC if necessary
+	// if its not a user request, and we are just trying to resume from a breakpoint,
+	// then we don't need to check for stubs. The last parameter aUserRequest tells
+	// ModifyBreaksForStep to check for stubs or not. In some cases, the check for stubs
+	// is true even if its not a user request.For example, this is true in cases where
+	// we are doing a step range and the instruction in the range modified PC.
+	// in this case, DoStepRange will be called from the exception handler where
+	// we need to check for the stubs for the valid behavior. So truly, we don't need to check
+	// for stubs only when resuming from  a breakpoint.
+	ReturnIfError(iStepper->ModifyBreaksForStep(aThread, startAddress, stopAddress, aResumeOnceOutOfRange, aUserRequest, aNumSteps));
+
+	LOG_MSG("DRM_DebugChannel::DoStepRange() - resuming thread\n");
+
+	return TheDProcessTracker.ResumeThread(aThread);
+	}
+
+/**
+Read memory from the specified addres into the aData descriptor. If there is a
+breakpoint set in the region of memory returned then the correct data value is
+inserted into the descriptor
+
+@param aThread pointer to thread whose address space memory is to be read from
+@param aAddress address to start reading memory from
+@param aLength length of memory block to read
+@param aData descriptor to read memory into
+
+@return KErrNone if memory read successfully,
+        KErrNotSupported if reading from the rom section is not supported,
+        KErrBadHandle if aThread is invalid,
+        or one of the other system wide error codes
+*/
+TInt DRM_DebugChannel::DoReadMemory(const DThread *aThread, const TUint32 aAddress, const TUint32 aLength, TDes8 &aData) const
+	{
+	LOG_MSG("DRM_DebugChannel::DoReadMemory()");
+
+	// make sure the parameters are valid
+	if (aLength > aData.MaxSize())
+		return KErrArgument;
+
+	TInt err = KErrNone;
+
+	// trap exceptions in case the address is invalid
+	XTRAPD(r, XT_DEFAULT, err = TryToReadMemory(aThread, (TAny *)aAddress, (TAny *)aData.Ptr(), aLength));
+
+	err = (KErrNone == r) ? err : r;
+
+	if (KErrNone == err)
+		{
+		aData.SetLength(aLength);
+
+		TPtr8 data((TUint8 *)aData.Ptr(), aLength, aLength);
+
+		// if we have any breakpoints in this range, put the actual instruction in the buffer
+		TBreakEntry* breakEntry = NULL;
+		do
+			{
+			breakEntry = iBreakManager->GetNextBreak(breakEntry);
+			if(breakEntry && !iBreakManager->IsTemporaryBreak(*breakEntry))
+				{
+				if ((breakEntry->iAddress >= aAddress) && (breakEntry->iAddress < (aAddress + aLength)))
+					{
+					TInt instSize;
+
+					switch(breakEntry->iMode)
+						{
+						case EArmMode:
+							instSize = 4;
+							break;
+
+						case EThumbMode:
+							instSize = 2;
+							break;
+
+						case EThumb2EEMode:
+						default:
+							LOG_MSG("DRM_DebugChannel::DoReadMemory() cannot fixup breakpoints with unsupported architecture");
+							return KErrNotSupported;
+						}
+					memcpy((TAny*)&data[breakEntry->iAddress - aAddress], (TAny *)breakEntry->iInstruction.Ptr(), instSize);
+					}
+				}
+			} while(breakEntry);
+		}
+
+	return err;
+	}
+
+/**
+Attempt to write memory to aThread's address space
+
+@param aThread thread to whose address space memory is to be written
+@param aAddress memory location to write memory to
+@param aLength number of bytes of data to write
+@param aData descriptor containing memory to write
+
+@return KErrNone if memory written successfully,
+        KErrArgument if aLength is greater than than the length of the aData
+        KErrBadHandle if aThread is invalid,
+	or another of the system wide error codes
+*/
+TInt DRM_DebugChannel::DoWriteMemory(DThread *aThread, const TUint32 aAddress, const TUint32 aLength, TDes8 &aData)
+	{
+	LOG_MSG("DRM_DebugChannel::DoWriteMemory()");
+
+	// make sure the parameters are valid
+	if (aLength > aData.Length())
+		return KErrArgument;
+
+	TInt err = KErrNone;
+
+	// trap exceptions in case the address is invalid
+	XTRAPD(r, XT_DEFAULT, err = TryToWriteMemory(aThread, (TAny *)aAddress, (TAny *)aData.Ptr(), aLength));
+
+	err = (KErrNone == r) ? err : r;
+
+	// reset any breakpoints we may have just overwritten
+	if (KErrNone == err)
+		{
+		TPtr8 data((TUint8 *)aData.Ptr(), aLength, aLength);
+
+		TBreakEntry* breakEntry = NULL;
+		do
+			{
+			breakEntry = iBreakManager->GetNextBreak(breakEntry);
+			if(breakEntry && !iBreakManager->IsTemporaryBreak(*breakEntry))
+				{
+				if ((breakEntry->iAddress >= aAddress) && (breakEntry->iAddress < (aAddress + aLength)))
+					{
+					// default to arm mode
+					TUint32 inst;
+					TInt instSize;
+
+					switch (breakEntry->iMode)
+						{
+						case EArmMode:
+							inst = KArmBreakPoint;
+							instSize = 4;
+							break;
+
+						case EThumbMode:
+							inst = KThumbBreakPoint;
+							instSize = 2;
+							break;
+
+						case EThumb2EEMode:
+						default:
+							LOG_MSG("DRM_DebugChannel::DoWriteMemory() cannot fixup breakpoints of unsupported architecture type");
+
+							return KErrNotSupported;
+						}
+
+					breakEntry->iInstruction.Copy(&data[breakEntry->iAddress - aAddress], instSize);
+					memcpy((TAny*)breakEntry->iAddress, (TAny *)&inst, instSize);
+					}
+				}
+
+			} while(breakEntry);
+		}
+	return err;
+	}
+
+//
+// DRM_DebugChannel::DoReadRegisters
+//
+TInt DRM_DebugChannel::DoReadRegisters(DThread *aThread, const TInt16 aFirstRegister, const TInt16 aLastRegister, TDes8 &aValues)
+	{
+	LOG_EVENT_MSG("DRM_DebugChannel::DoReadRegisters()");
+
+	// make sure the parameters are valid
+	if (!aThread || (aFirstRegister < 0) || (aLastRegister >= (TInt16)(sizeof(TArmRegSet)/sizeof(TArmReg))))
+		return KErrArgument;
+
+	// make sure the descriptor is big enough to hold the requested data
+	if ((TInt)((aLastRegister - aFirstRegister + 1) * sizeof(TArmReg)) > (aValues.MaxSize()))
+		return KErrArgument;
+
+	TArmRegSet regSet;
+	TUint32 unused;
+
+	NKern::ThreadGetUserContext(&aThread->iNThread, &regSet, unused);
+
+	LOG_MSG2( "DRM_DebugChannel::DoReadRegistersLegacy() : unused = 0x%X\n", unused );
+
+	TArmReg *reg = &regSet.iR0;
+
+	if (!reg)
+		return KErrGeneral;
+
+	for (TInt16 i = aFirstRegister; i <= aLastRegister; i++)
+		aValues.Append((TUint8 *)&reg[i], sizeof(TArmReg));
+
+	return KErrNone;
+}
+
+/**
+  @prototype
+
+  Experimental function for determining whether a thread is suspended.
+
+  @param aThread thread to check if suspended
+
+  @return ETrue if the thread is suspended, EFalse if it isn't or does not exist
+  */
+TBool DRM_DebugChannel::CheckSuspended(const DThread *aThread) const
+	{
+	if(!aThread)
+		{
+		return EFalse;
+		}
+
+	if( (aThread->iNThread.iCsCount>0) && (aThread->iNThread.iCsFunction>0) )
+		{
+		return ETrue;
+		}
+
+	if(aThread->iNThread.iSuspendCount > 0)
+		{
+		return ETrue;
+		}
+	return EFalse;
+	}
+
+/**
+Read registers and store register values in aRegisterValues and the flags
+indicating which registers could be read in aRegisterFlags
+
+@param aThread thread to read registers from
+@param aRegisterIds array containing register IDs to read
+@param aRegisterValues array to store register values in
+@param aRegisterFlags array to store flags in
+
+@return KErrNone if registers were read successfully. Note that this does not
+        mean that all the registers could be read, the aRegisterFlags array
+        should be checked as to whether each individual register could be read,
+        KErrArgument if aThread is NULL, if an unknown register is specified in
+        aRegisterValues or if aRegisterValues is too small
+        KErrGeneral if there was a problem initialising the register set
+*/
+TInt DRM_DebugChannel::DoReadRegisters(DThread *aThread, const TDesC8 &aRegisterIds, TDes8 &aRegisterValues, TDes8& aRegisterFlags) const
+	{
+	LOG_MSG("DRM_DebugChannel::DoReadRegisters()");
+
+	// make sure the parameters are valid
+	if (!aThread)
+		return KErrArgument;
+
+	//Need to revisit this to determine whether there is a way to validate this
+#if 0
+	if ( !CheckSuspended(aThread) )
+		{
+		LOG_MSG2("DRM_DebugChannel::DoReadRegisters() thread with id 0x%08x is not suspended", aThread->iId);
+		return KErrInUse;
+		}
+#endif
+
+	//set lengths of output descriptors to 0 prior to filling
+	aRegisterValues.SetLength(0);
+	aRegisterFlags.SetLength(0);
+
+	TArmRegSet regSet;
+	TUint32 flags;
+
+	NKern::ThreadGetUserContext(&aThread->iNThread, &regSet, flags);
+
+	LOG_MSG2( "DRM_DebugChannel::DoReadRegisters() : flags = 0x%X\n", flags );
+
+	TArmReg *regPtr = &regSet.iR0;
+
+	if (!regPtr)
+		return KErrGeneral;
+
+	TUint numberOfRegisters = aRegisterIds.Length() / sizeof(TRegisterInfo);
+
+	//iterate through registers setting the relevant aFlags value
+	for(TUint i=0; i<numberOfRegisters; i++)
+		{
+		//get current register id
+		TRegisterInfo reg;
+		TInt err = GetTRegisterInfo(aRegisterIds, i, reg);
+		//exit with the error value if there was an error
+		if(err != KErrNone)
+			return err;
+
+		//if unknown register then exit as can't know how many bytes this entry will
+		//represent in aRegisterValues
+		TTag registerTag;
+		TDebugFunctionality::GetRegister(reg, registerTag);
+		if(registerTag.iValue == EAccessUnknown)
+			{
+			return KErrArgument;
+			}
+
+		//get the current register id as a kernel register
+		TArmReg armReg;
+		err = GetKernelRegisterId(reg, armReg);
+		if((err == KErrNotSupported) || (registerTag.iValue == EAccessNone) || (registerTag.iValue == EAccessWriteOnly))
+			{
+			//reading this register is not supported
+			aRegisterFlags.Append(ENotSupported);
+			//just skip over this entry in the values buffer
+			if(aRegisterValues.Length() + registerTag.iSize > aRegisterValues.MaxLength())
+				{
+				//writing this value would cause overflow so exit
+				return KErrArgument;
+				}
+			aRegisterValues.SetLength(aRegisterValues.Length() + registerTag.iSize);
+			}
+		else
+			{
+			if(registerTag.iSize == sizeof(TArmReg))
+				{
+				if(GetFlagAtOffset(flags, armReg))
+					{
+					//set flag as valid
+					aRegisterFlags.Append(EValid);
+					}
+				else
+					{
+					// Even though the flag is invalid, we can return the value of the register
+					// and let the user decide what to do
+					aRegisterFlags.Append(EInValid);
+					}
+
+				if(aRegisterValues.Length() + sizeof(TArmReg) > aRegisterValues.MaxLength())
+					{
+					//writing this value would cause overflow so exit
+					return KErrArgument;
+					}
+				//write value into register into regSet
+				aRegisterValues.Append((TUint8 *)&regPtr[armReg], registerTag.iSize);
+				}
+			else
+				{
+				//currently all kernel supported registers are 4 bytes so
+				//return EBadSize. Would need updating if/when other register
+				//value sizes are supported
+				aRegisterFlags.Append(EBadSize);
+				aRegisterValues.SetLength(aRegisterValues.Length() + registerTag.iSize);
+				}
+			}
+		}
+	return KErrNone;
+	}
+
+//
+// DRM_DebugChannel::DoWriteRegisters
+//
+TInt DRM_DebugChannel::DoWriteRegisters(DThread *aThread, const TInt16 aFirstRegister, const TInt16 aLastRegister, TDesC8 &aValues)
+	{
+	LOG_MSG("DRM_DebugChannel::DoWriteRegisters()");
+
+	// make sure the parameters are valid
+	if (!aThread || (aFirstRegister < 0) || (aLastRegister >= (TInt16)(sizeof(TArmRegSet)/sizeof(TArmReg))))
+		return KErrArgument;
+
+	// make sure the descriptor is big enough to hold the data to write
+	if ((TInt)((aLastRegister - aFirstRegister + 1) * sizeof(TArmReg)) > (aValues.Length()))
+		return KErrArgument;
+
+	TArmRegSet regSet;
+	TUint32 unused;
+
+	NKern::ThreadGetUserContext(&aThread->iNThread, &regSet, unused);
+
+	TArmReg *reg = &regSet.iR0;
+
+	for (TInt16 i = aFirstRegister; i <= aLastRegister; i++)
+		reg[i] = *(TUint32 *)&aValues[(i-aFirstRegister)*sizeof(TArmReg)];
+
+	NKern::ThreadSetUserContext(&aThread->iNThread, &regSet);
+
+	return KErrNone;
+	}
+
+/**
+Write registers and store flags indicating which registers could be read in
+aRegisterFlags
+
+@param aThread thread to write registers to
+@param aRegisterIds array containing register IDs to write
+@param aRegisterValues array containing register values to write
+@param aRegisterFlags array to store flags in
+
+@return KErrNone if registers were written successfully. Note that this does not
+        mean that all the registers could be written, the aRegisterFlags array
+        should be checked as to whether each individual register could be read,
+        KErrArgument if aThread is NULL, if the buffer passed in as
+        aRegisterValue is too small, or if an unknown register is requested,
+        KErrGeneral if there was a problem initialising the register set
+*/
+TInt DRM_DebugChannel::DoWriteRegisters(DThread *aThread, const TDesC8 &aRegisterIds, TDesC8 &aRegisterValues, TDes8 &aRegisterFlags) const
+	{
+	LOG_MSG("DRM_DebugChannel::DoWriteRegisters()");
+
+	// make sure the parameters are valid
+	if (!aThread)
+		return KErrArgument;
+
+
+	//get register values from kernel
+	TArmRegSet regSet;
+	TUint32 flags;
+	NKern::ThreadGetUserContext(&aThread->iNThread, &regSet, flags);
+
+	//set lengths of output descriptors to 0 prior to filling
+	aRegisterFlags.SetLength(0);
+
+	//pointer to first kernel register
+	TArmReg *regPtr = &regSet.iR0;
+
+	if (!regPtr)
+		return KErrGeneral;
+
+	//calculate number of registers
+	TUint numberOfRegisters = aRegisterIds.Length() / sizeof(TRegisterInfo);
+
+	//iterate through registers setting the relevant aRegisterFlags value and
+	//setting the necessary value in regSet ready to write to kernel
+	for(TUint i=0, offset = 0; i<numberOfRegisters; i++)
+		{
+		//get current register id
+		TRegisterInfo reg;
+		TInt err = GetTRegisterInfo(aRegisterIds, i, reg);
+		//exit with the error value if there was an error
+		if(err != KErrNone)
+			{
+			return err;
+			}
+
+		//if unknown register then exit as can't know how many bytes this entry will
+		//represent in aRegisterValues
+		TTag registerTag;
+		TDebugFunctionality::GetRegister(reg, registerTag);
+		if(registerTag.iValue == EAccessUnknown)
+			{
+			return KErrArgument;
+			}
+
+		//get the current register id as a kernel register
+		TArmReg armReg;
+		err = GetKernelRegisterId(reg, armReg);
+		if((err == KErrNotSupported) || (registerTag.iValue == EAccessNone) || (registerTag.iValue == EAccessReadOnly))
+			{
+			//writing to this register is not supported
+			aRegisterFlags.Append(ENotSupported);
+			}
+		else if(GetFlagAtOffset(flags, armReg))
+			{
+			if(registerTag.iSize == sizeof(TArmReg))
+				{
+				//set flag as valid
+				aRegisterFlags.Append(EValid);
+				if(offset + sizeof(TArmReg) > aRegisterValues.Length())
+					{
+					//getting this value would cause overflow so exit
+					return KErrArgument;
+					}
+				//write value into register into regSet
+				regPtr[armReg] = *(TUint32 *)&aRegisterValues[offset];
+				}
+			else
+				{
+				//currently all kernel supported registers are 4 bytes so
+				//return EBadSize. Would need updating if/when other register
+				//value sizes are supported
+				aRegisterFlags.Append(EBadSize);
+				}
+
+			}
+		else
+			{
+			//set flag as invalid as register value couldn't be read
+			aRegisterFlags.Append(EInValid);
+			}
+		offset+=registerTag.iSize;
+		}
+
+	//write the input data into the registers
+	NKern::ThreadSetUserContext(&aThread->iNThread, &regSet);
+
+	//return normally
+	return KErrNone;
+	}
+
+//
+// DRM_DebugChannel::DoSecurityCheck
+//
+TBool DRM_DebugChannel::DoSecurityCheck()
+	{
+	LOG_MSG("DRM_DebugChannel::DoSecurityCheck");
+	DProcess* clientProcess = iClientThread->iOwningProcess;
+	if (clientProcess)
+		{
+		SSecurityInfo secureInfo = clientProcess->iS;
+
+		LOG_MSG2("DoSecurityCheck - client secure id is 0x%08x",secureInfo.iSecureId);
+
+		// Ensure we really are communicating with the Debug Security Server
+		if (secureInfo.iSecureId == KUidDebugSecurityServer.iUid )
+			{
+			return ETrue;
+			}
+		}
+	return EFalse;
+	}
+
+/**
+Attempt to read memory from aThread's address space
+
+@param aThread thread from whose address space memory is to be read
+@param aSrc pointer to memory location to read memory from
+@param aDest pointer to memory location to write memory to
+@param aLength number of bytes of data to read
+
+@return KErrNone if memory read successfully,
+	or another of the system wide error codes
+*/
+TInt DRM_DebugChannel::TryToReadMemory(const DThread *aThread, const TAny *aSrc, TAny *aDest, const TUint32 aLength) const
+	{
+	LOG_MSG("DRM_DebugChannel::TryToReadMemory()");
+
+	// make sure the parameters are valid
+	if (!aThread)
+		return KErrArgument;
+
+	//Need to revisit this to determine whether there is a way to validate this
+#if 0
+	//check that the thread is suspended before reading the memory
+	if ( !CheckSuspended(aThread) )
+		{
+		LOG_MSG2("DRM_DebugChannel::TryToReadMemory() thread with id 0x%08x is not suspended", aThread->iId);
+		return KErrInUse;
+		}
+#endif
+
+	LOG_MSG2("Using Kern::ThreadRawRead to read memory at address %x", aSrc);
+	return Kern::ThreadRawRead((DThread *)aThread, aSrc, aDest, aLength);
+	}
+
+/**
+Attempt to write memory to aThread's address space
+
+@param aThread thread to whose address space memory is to be written
+@param aDest pointer to memory location to write memory to
+@param aSrc pointer to memory location to read memory from
+@param aLength number of bytes of data to write
+
+@return KErrNone if memory written successfully, or another of the system wide
+        error codes
+*/
+TInt DRM_DebugChannel::TryToWriteMemory(const DThread *aThread, TAny *aDest, const TAny *aSrc, const TUint32 aLength)
+	{
+	LOG_MSG("DRM_DebugChannel::TryToWriteMemory()");
+
+
+	LOG_MSG2("Using Kern::ThreadRawWrite to write memory at address %x", (TUint32)aDest);
+	return Kern::ThreadRawWrite((DThread *)aThread, aDest, aSrc, aLength, iClientThread);
+	}
+
+/**
+@deprecated use DRM_DebugChannel::ReadKernelRegisterValue(DThread *aThread, const TArmReg aKernelRegisterId, T4ByteRegisterValue &aValue) instead
+*/
+TInt32 DRM_DebugChannel::ReadRegister(DThread *aThread, TInt aNum)
+	{
+	LOG_MSG("DRM_DebugChannel::ReadRegister()");
+
+	if (!aThread || (aNum < 0) || (aNum >= (TInt16)(sizeof(TArmRegSet)/sizeof(TArmReg))))
+		{
+		LOG_MSG2("Invalid register number (%d) passed to ReadRegister", aNum);
+		return 0;
+		}
+
+	TArmRegSet regSet;
+	TUint32 unused;
+
+	NKern::ThreadGetUserContext(&aThread->iNThread, &regSet, unused);
+
+	TArmReg *reg = &regSet.iR0;
+
+	return ((TUint32 *)reg)[aNum];
+	}
+
+/**
+Given a TArmReg register ID, read the value of the register. The register value
+will be stored in aValue if the register could be read.
+
+@param aThread thread to read register from
+@param aKernelRegisterId ID of register to read from
+@param aValue value read from register
+
+@return KErrNone if value was successfully stored in aValue,
+        KErrNotSupported if aKernelRegister is not supported by the debug
+	security server,
+        or a return value from DRM_DebugChannel::ReadDebugRegisterValue()
+*/
+TInt32 DRM_DebugChannel::ReadKernelRegisterValue(DThread *aThread, const TArmReg aKernelRegisterId, T4ByteRegisterValue &aValue) const
+	{
+	//get register ID as a TRegisterInfo ID
+	TRegisterInfo regId;
+	TInt err = GetDebugRegisterId(aKernelRegisterId, regId);
+	if(err != KErrNone)
+		return err;
+
+	//get the value for the register
+	err = ReadDebugRegisterValue(aThread, regId, aValue);
+	return err;
+	}
+
+/**
+Given a TRegisterInfo register ID, read the value of this register. The
+register value will be stored in aValue if the register could be read.
+
+@param aThread thread to read register from
+@param aDebugRegisterId ID of register to read from
+@param aValue value read from register
+
+@return KErrNone if value was successfully stored in aValue,
+        TRegisterFlag::EInValid if value could not be read from the register,
+        TRegisterFlag::ENotSupported if the register is not supported,
+        KErrNoMemory if temporary memory could not be allocated,
+        or a return value from DRM_DebugChannel::DoReadRegisters
+*/
+TInt32 DRM_DebugChannel::ReadDebugRegisterValue(DThread *aThread, const TRegisterInfo aDebugRegisterId, T4ByteRegisterValue &aValue) const
+	{
+	//allocate temporary buffers to store data
+	NKern::ThreadEnterCS();
+	TUint8* id = (TUint8*)Kern::Alloc(sizeof(TRegisterInfo));
+	NKern::ThreadLeaveCS();
+	if(id == NULL)
+		{
+		return KErrNoMemory;
+		}
+
+	TPtr8 idPtr(id, sizeof(TRegisterInfo));
+
+	NKern::ThreadEnterCS();
+	TUint8* value = (TUint8*)Kern::Alloc(sizeof(T4ByteRegisterValue));
+	NKern::ThreadLeaveCS();
+	if(value == NULL)
+		{
+		return KErrNoMemory;
+		}
+	TPtr8 valuePtr(value, sizeof(T4ByteRegisterValue));
+
+	NKern::ThreadEnterCS();
+	TUint8* flag = (TUint8*)Kern::Alloc(sizeof(TUint8));
+	NKern::ThreadLeaveCS();
+	if(flag == NULL)
+		{
+		return KErrNoMemory;
+		}
+	TPtr8 flagPtr(flag, sizeof(TUint8));
+
+	//store register id in buffer
+	idPtr.Append((TUint8*)&aDebugRegisterId, sizeof(TRegisterInfo));
+
+	//read registers
+	TInt err = DoReadRegisters(aThread, idPtr, valuePtr, flagPtr);
+	if(err == KErrNone)
+		{
+		if(*flag == EValid)
+			{
+			//register could be read so store value
+			aValue = *(T4ByteRegisterValue*)value;
+			}
+		else
+			{
+			//register couldn't be read for some reason
+			err = *flag;
+			}
+		}
+
+	//free memory
+	NKern::ThreadEnterCS();
+	Kern::Free(id);
+	Kern::Free(value);
+	Kern::Free(flag);
+	NKern::ThreadLeaveCS();
+
+	return err;
+	}
+
+//
+// DRM_DebugChannel::NotifyAgentsFromEventPid
+//
+TBool DRM_DebugChannel::NotifyAgentsFromEventPid(const TDriverEventInfo& aEventInfo)
+	{
+
+	// Look for the relevant DTargetProcess
+	// We can find out the relevant process id from aEventInfo
+	TUint32 pid = aEventInfo.iProcessId;
+
+#ifdef	_DEBUG
+	if (aEventInfo.iEventType != EEventsUserTrace)
+		{
+		LOG_MSG3(" NotifyAgentsFromEventPid - pid = 0x%x, evType=%d", pid, aEventInfo.iEventType);
+		}
+#endif
+
+	//opening handle to process
+	DProcess* targetProcess = DebugUtils::OpenProcessHandle(pid);
+
+	if(!targetProcess)
+		{
+		LOG_EVENT_MSG("process does not exist!");
+		return EFalse;
+		}
+
+	// Are we debugging this process - decide based on iFileName
+	DCodeSeg* p = targetProcess->iCodeSeg;
+	DTargetProcess* foundProcess;
+	if (p)
+		{
+		foundProcess = TheDProcessTracker.FindProcess(*(p->iFileName));
+		}
+	else
+		{
+		// special case: may not have a code seg in some cases. in which case we tell everyone!
+		if (targetProcess->iName)
+			{
+			// copy the name of the process
+			foundProcess = TheDProcessTracker.FindProcess(*(targetProcess->iName));
+			}
+		else
+			{
+			foundProcess = NULL;
+			}
+		}
+
+    //close the handle
+    targetProcess->Close(NULL);
+
+	if (foundProcess)
+		{
+		foundProcess->NotifyEvent(aEventInfo);
+		return ETrue;
+		}
+	else
+		{
+		// Check if there's an attach-to-all handler
+		DDebugAgent* agent = TheDProcessTracker.GetCurrentAgentAttachedToAll();
+		if (agent)
+			{
+			LOG_EVENT_MSG2(" NotifyAgentsFromEventPid - found attach all agent 0x%lx", agent->Id());
+			agent->NotifyEvent(aEventInfo);
+			return ETrue;
+			}
+		}
+
+	// we are not debugging this process
+	return EFalse;
+	}
+
+DECLARE_STANDARD_LDD()
+	{
+	return new DRM_DebugDriverFactory;
+	}
+
+/**
+Helper function
+
+Allocates memory in current thread with a max length the same as aSrcDes. If
+aReadFromClient is true (as it is by default) then the data from aSrdDes is
+copied into the allocated aDestDes buffer.
+
+Use of this function should be followed at a later time by a call such as
+Kern::Free(aDestDes.Ptr())
+
+@param aThread pointer to thread to read data from
+@param aSrcDes descriptor in aThread to read data from
+@param aDestDes location to read data to. Memory is allocated at this location,
+       if memory is already allocated at this location then the function will
+       return KErrArgument
+@param aReadFromClient if false then data is not actually read from the
+       client, the memory is simply allocated
+@param aOffest offset into aSrcDes to start reading from. Default is 0.
+
+@return KErrNone if there were no problems,
+        KErrArgument if aDestDes.Ptr() != NULL or aSrcDes has max length 0,
+        KErrNoMemory if could not allocate memory,
+        or one of the other system wide error codes
+*/
+TInt DRM_DebugChannel::AllocAndReadDes(DThread *aThread, const TDesC8& aSrcDes, TPtr8& aDestDes, const TBool aReadFromClient, const TUint aOffset) const
+	{
+
+	//check thread is not null
+	if(!aThread)
+		{
+		return KErrArgument;
+		}
+
+	//check aDestDes is empty
+	if(aDestDes.Ptr() != NULL)
+		{
+		return KErrArgument;
+		}
+
+	//get the source descriptor's max length and exit if 0
+	TUint srcMaxLength = Kern::ThreadGetDesMaxLength(aThread, &aSrcDes);
+	if(srcMaxLength == 0)
+		{
+		return KErrNone;
+		}
+
+	//allocate memory and return if none available
+	NKern::ThreadEnterCS();
+	TUint8 *destPtr = (TUint8*)Kern::Alloc(srcMaxLength);
+	NKern::ThreadLeaveCS();
+	if (!destPtr)
+		{
+		return KErrNoMemory;
+		}
+
+	//point the TPtr8 at the target memory
+	aDestDes.Set(destPtr, srcMaxLength, srcMaxLength);
+
+	if(aReadFromClient)
+		{
+		//read data from the client thread and return status code
+		return Kern::ThreadDesRead(aThread, &aSrcDes, aDestDes, aOffset);
+		}
+	else
+		{
+		return KErrNone;
+		}
+	}
+
+/**
+Helper function to extract a TRegisterInfo value from a descriptor containing
+binary data.
+
+@param aRegisterIds descriptor containing register IDs
+@param aOffset offset in bytes into the descriptor to start reading data from.
+       If this value is not a multiple of sizeof(TRegisterInfo) then a
+       KErrArgument error is returned.
+@param aValue will contain the returned value
+
+@return KErrNone if aValue was set correctly, KErrArgument if bad arguments
+        were passed in
+*/
+TInt DRM_DebugChannel::GetTRegisterInfo(const TDesC8 &aRegisterIds, const TUint aIndex, TRegisterInfo &aValue) const
+	{
+	TUint length = aRegisterIds.Length();
+
+	TUint size = sizeof(TRegisterInfo);
+
+	//check that not trying to read past end of descriptor
+	if((aIndex + 1) * size > length)
+		return KErrArgument;
+
+	//get pointer to descriptor's data
+	const TUint8 *dataPtr = aRegisterIds.Ptr();
+	const TRegisterInfo *registerId = reinterpret_cast<const TRegisterInfo*>(dataPtr + (aIndex * size));
+
+	aValue = *registerId;
+
+	return KErrNone;
+	}
+
+/**
+Helper function to get the kernel register ID of the TRegisterInfo defined register.
+
+@param aDebugRegister the debug register ID to return the kernel ID for
+@param aKernelRegister corresponding value of register aDebugRegister
+
+@return KErrNone if translation occurred without problems
+        KErrNotSupported if aDebugRegister is not supported by the kernel
+*/
+TInt DRM_DebugChannel::GetKernelRegisterId(const TRegisterInfo aDebugRegister, TArmReg& aKernelRegister) const
+	{
+	if(Register::IsCoreReg(aDebugRegister))
+		{
+		TUint id = Register::GetCoreRegId(aDebugRegister);
+		//first 17 registers match the first 17 kernel registers
+		if(id < 17)
+			{
+			aKernelRegister = id;
+			}
+		else
+			{
+			return KErrNotSupported;
+			}
+		}
+	else if(Register::IsCoproReg(aDebugRegister))
+		{
+		TUint32 crn = Register::GetCRn(aDebugRegister);
+		TUint32 crm = Register::GetCRm(aDebugRegister);
+		TUint32 opcode1 = Register::GetOpcode1(aDebugRegister);
+		TUint32 opcode2 = Register::GetOpcode2(aDebugRegister);
+		TUint32 coproNum = Register::GetCoproNum(aDebugRegister);
+
+		//each coprocessor register has potentially different characteristics
+		//so need to identify each individually
+
+		//this is the DACR, the ARM ARM specifies that the CRn and the
+		//Opcodes are not relevant, section B3-24, point 3.7.3
+		if((coproNum == 15) && (crm == 3))
+			{
+			aKernelRegister = EArmDacr;
+			}
+		else
+			{
+			return KErrNotSupported;
+			}
+		}
+	else // might be supported at a later date
+		{
+		return KErrNotSupported;
+		}
+
+	return KErrNone;
+	}
+
+/**
+Helper function to get the debug register ID of the kernel defined register.
+
+@param aKernelRegister the kernel register ID to return the debug ID for
+@param aDebugRegister corresponding value of register aKernelRegister
+
+@return KErrNone if translation occured without problems
+        KErrNotSupported if aKernelRegister is not supported by the debug
+	security server
+*/
+TInt DRM_DebugChannel::GetDebugRegisterId(const TArmReg aKernelRegister, TRegisterInfo &aDebugRegister) const
+	{
+
+	// registers 0 - 15 and the CPSR share the same values as with the debug enums
+	if(aKernelRegister < 17)
+		{
+		TUint32 id = aKernelRegister;
+		aDebugRegister = id << 8;
+		}
+	//the DACR value is special and corresponds to EDF_Register_DACR
+	else if(aKernelRegister == EArmDacr)
+		{
+		aDebugRegister = 0x00300f01;
+		}
+	// must be an unsupported register, return an error as such
+	else
+		{
+		return KErrNotSupported;
+		}
+
+	//found a supported register so return KErrNone
+	return KErrNone;
+	}
+
+/**
+Helper function to find out whether the aIndex flag is set. This is equivalent
+to the aIndex bit of aFlags being non-zero.
+
+@param aFlags set of flags
+@param aIndex offset into aFlags to get flag from
+
+@return ETrue if bit is set, EFalse if not
+*/
+TBool DRM_DebugChannel::GetFlagAtOffset(const TUint32 aFlags, const TArmReg aIndex) const
+	{
+	return aFlags & (1<<aIndex);
+	}
+
+/* Register the attachment of a debug agent to a process to be debugged
+ *
+ * @param a1 - TDes8 target process name
+ * @param a2 - &TUint64 - Debug Agent Id
+ *
+ * @return - KErrNone if successful. KErrArgument if the filepath is not a valid size.
+ * KErrOutOfMemory if there is insufficient memory. Or one of the other system wide error codes
+ * if appropriate.
+ */
+TInt DRM_DebugChannel::AttachProcess(TAny* a1, TAny* a2)
+	{
+	LOG_MSG("DRM_DebugChannel::AttachProcess()");
+
+	// Validate the supplied TDes8 target process name in a1
+	TInt length = Kern::ThreadGetDesLength(iClientThread, a1);
+	if (length < 0) return length;
+
+	// Check the processname is a valid size for a filepath
+	if (length < 1 || length >= KMaxPath)
+		{
+		return KErrArgument;
+		}
+
+	// Allocate space to store the target process name in a kernel-side TPtr8
+	NKern::ThreadEnterCS();
+	TUint8* buffer = (TUint8*)Kern::AllocZ(length);
+	NKern::ThreadLeaveCS();
+	if (buffer==NULL)
+		{
+		// Out of memory
+		return KErrNoMemory;
+		}
+
+	// A temporary descriptor to store the target process name
+	TPtr8 targetProcessName(buffer,length,length);
+
+	// Read the user-side data into targetProcessName
+	TInt err = Kern::ThreadDesRead(iClientThread,a1,targetProcessName,0,KChunkShiftBy0);
+	if (err != KErrNone)
+		{
+		// Could not read the user-side descriptor containing the target process name
+		NKern::ThreadEnterCS();
+		Kern::Free(buffer);
+		NKern::ThreadLeaveCS();
+
+		return err;
+		}
+
+	// Obtain the Debug Agent Id
+	TUint64 debugAgentId = 0;
+
+	err = Kern::ThreadRawRead(iClientThread,a2,&debugAgentId,sizeof(debugAgentId));
+	if (err != KErrNone)
+		{
+		// Something bad happened so free the memory and return
+		NKern::ThreadEnterCS();
+		Kern::Free(buffer);
+		NKern::ThreadLeaveCS();
+		return err;
+		}
+
+	// Add the target process to our list of tracked processes
+	err = TheDProcessTracker.AttachProcess(targetProcessName, debugAgentId);
+
+	// Free the kernel-side memory containing targetProcessName data
+	NKern::ThreadEnterCS();
+	Kern::Free(buffer);
+	NKern::ThreadLeaveCS();
+
+	return err;
+	}
+
+/* Register the detachment of a debug agent to a process to be debugged.
+ *
+ * @param - a1 TDes8 target process name in a1
+ * @param a2 - &TUint64 - Debug Agent Id
+ *
+ * @return - KErrNone if successful. KErrArgument if the filepath is not a valid size.
+ * KErrOutOfMemory if there is insufficient memory. Or one of the other system wide error codes
+ * if appropriate.
+ */
+TInt DRM_DebugChannel::DetachProcess(TAny* a1, TAny* a2)
+	{
+	TInt length = Kern::ThreadGetDesLength(iClientThread, a1);
+	if (length < 0)
+		{
+		return length;
+		}
+
+	if (length < 1 || length >= KMaxPath)
+		{
+		return KErrArgument;
+		}
+
+	HBuf* targetProcessName = HBuf::New(length);
+	if (targetProcessName == NULL)
+		{
+		// Out of memory
+		return KErrNoMemory;
+		}
+
+	// Read the user-side data into buf
+	TInt err = Kern::ThreadDesRead(iClientThread,a1,*targetProcessName,0,KChunkShiftBy0);
+	if (err != KErrNone)
+		{
+		// Something bad happened so free the memory and return
+		delete targetProcessName;
+		return err;
+		}
+
+	// Obtain the AgentId
+	TUint64 debugAgentId = 0;
+
+	err = Kern::ThreadRawRead(iClientThread,a2,&debugAgentId,sizeof(debugAgentId));
+	if (err == KErrNone)
+		{
+		// Remove the process from our list of tracked processes
+		err = TheDProcessTracker.DetachProcess(*targetProcessName, debugAgentId);
+		}
+
+	// Free the kernel-side memory containing targetProcessName data
+	delete targetProcessName;
+	return err;
+	}
+
+/* Register the detachment of a debug agent from all processes being debugged.
+ *
+ * @param - a1 - &TUint64 Debug Agent Id.
+ * @return - KErrNone if successful. One of the system-wide error codes otherwise.
+ */
+TInt DRM_DebugChannel::DetachAgent(TAny* a1, TAny* a2)
+	{
+	// Obtain the AgentId
+	TUint64 debugAgentId = 0;
+
+	TInt err = Kern::ThreadRawRead(iClientThread,a1,&debugAgentId,sizeof(debugAgentId));
+	if (err != KErrNone)
+		{
+		return err;
+		}
+
+	// Remove the process from our list of tracked processes
+	return TheDProcessTracker.DetachAgent(debugAgentId);
+	}
+
+/* Set the action associated with a particular kernel event for a given agent and target process
+ *
+ * @param - a1 TDes8 target process name in a1
+ * @param - a2 &TRM_DebugEventActionInfo
+ * @return - KErrNone if successful. KErrArgument if the filepath is an invalid size. Or one of
+ * the other system wide error codes if appropriate.
+ */
+TInt DRM_DebugChannel::SetEventAction(TAny* a1, TAny* a2)
+	{
+	// Validate the supplied TDes8 target process name in a1
+	TInt length, maxLength;
+	TUint8* aPtr;
+
+	TInt err = Kern::ThreadGetDesInfo(iClientThread,\
+		a1,\
+		length,\
+		maxLength,\
+		aPtr,\
+		EFalse);
+	if (err != KErrNone)
+		{
+		return err;
+		}
+
+	if (length < 1 || length >= KMaxPath)
+		{
+		return KErrArgument;
+		}
+
+	if (maxLength < 1 || maxLength >= KMaxPath)
+		{
+		return KErrArgument;
+		}
+
+	// Allocate space to store the target process name in a kernelspace TPtr8
+	NKern::ThreadEnterCS();
+	TUint8* buffer = (TUint8*)Kern::AllocZ(length);
+	NKern::ThreadLeaveCS();
+	if (buffer==NULL)
+		{
+		// Out of memory
+		return KErrNoMemory;
+		}
+	TPtr8 targetProcessName(buffer,length,length);
+
+	// Read the user-side data into targetProcessName
+	err = Kern::ThreadDesRead(iClientThread,a1,targetProcessName,0,KChunkShiftBy0);
+	if (err != KErrNone)
+		{
+		// Something bad happened so free the memory and return
+		NKern::ThreadEnterCS();
+		Kern::Free(buffer);
+		NKern::ThreadLeaveCS();
+
+		return err;
+		}
+
+	// Read the Event and Action from the user-side
+	TRM_DebugEventActionInfo info(0,0,0);
+
+	err = Kern::ThreadRawRead(iClientThread, a2, &info, sizeof(info));
+	if (err != KErrNone)
+		{
+		// Could not read event action data from the user-side
+
+		// Free memory used for targetProcessName
+		NKern::ThreadEnterCS();
+		Kern::Free(buffer);
+		NKern::ThreadLeaveCS();
+
+		return err;
+		}
+	
+	DDebugAgent* debugAgent = TheDProcessTracker.FindAgentForProcessAndId( targetProcessName, info.iAgentId );
+	if (debugAgent != NULL)
+		{
+		// Set the event action
+		err = debugAgent->SetEventAction((TEventType)info.iEvent,(TKernelEventAction)info.iAction);
+		}
+	else
+		{
+		// Bad agent means there is no tracking agent
+		LOG_MSG2("Cannot locate debug agent with pid 0x%0xlx",info.iAgentId);
+		err = KErrNotFound;
+		}
+
+	// Free memory used for targetProcessName
+	NKern::ThreadEnterCS();
+	Kern::Free(buffer);
+	NKern::ThreadLeaveCS();
+
+	return err;
+
+	}
+
+TInt DRM_DebugChannel::Step(const TUint32 aThreadId, const TUint32 aNumSteps)
+	{
+	LOG_MSG3("DRM_DebugChannel::Step(aThreadId = 0x%08x, aNumSteps = 0x%08x)\n",aThreadId,aNumSteps);
+
+	DThread* thread = DebugUtils::OpenThreadHandle(aThreadId);
+
+	if (thread == NULL)
+		{
+		// The thread terminated before we could open it.
+		LOG_MSG2("DRM_DebugChannel::Step - Could not open thread %u", aThreadId);
+
+		return KErrArgument;
+		}
+
+	// We simply repeat this for desired number of steps
+	TInt err = KErrNone;
+
+	// Need to step from the current location for 'n' steps
+	TUint32 startAddress;
+
+	// We always step from the current PC.
+	err = ReadKernelRegisterValue(thread, PC_REGISTER, startAddress);
+	if(err != KErrNone)
+		{
+		LOG_MSG2("DRM_DebugChannel::Step - Could not read the PC: %d", err);
+
+		// Close the handle
+		thread->Close(NULL);
+
+		return err;
+		}
+
+	err = DoStepRange(thread, startAddress, startAddress, ETrue, EFalse, aNumSteps, ETrue);
+
+	if (err != KErrNone)
+		{
+		// There was a problem, return straightaway
+		LOG_MSG("DRM_DebugChannel::Step - failed to step");
+		}
+
+	// Close the handle
+	thread->Close(NULL);
+
+	return err;
+	}
+
+TInt DRM_DebugChannel::KillProcess(const TUint32 aProcessId, const TInt aReason)
+	{
+	LOG_MSG3("DRM_DebugChannel::KillProcess(aProcessId = 0x%08x, aReason = 0x%08x)\n",aProcessId,aReason);
+
+	DProcess* process = DebugUtils::OpenProcessHandle(aProcessId);
+
+	if (process == NULL)
+		{
+		// The process terminated before we could open it to kill it ourselves.
+		LOG_MSG2("DRM_DebugChannel::KillProcess - Could not open process %u", aProcessId);
+
+		return KErrArgument;
+		}
+
+	TInt err = KErrNone;
+
+	DebugSupport::TerminateProcess(process,aReason);
+
+	// Close the handle
+	process->Close(NULL);
+
+	return err;
+	}
+
+/* Security critical - this checks whether the specified process is debuggable or not
+ *
+ * @param aProcessId - The process id of the process to check
+ * @return KErrNone if debuggable, KErrPermissionDenied if not debuggable.
+ */
+TInt DRM_DebugChannel::IsDebuggable(const TUint32 aProcessId)
+	{
+	/* In order to ensure that only processes which are debuggable
+	 * can be debugged, this function enables the security server
+	 * to read the DProcess.iDebugAttributes field and ensure
+	 * the process was created from a debuggable executable.
+	 */
+	LOG_MSG2("DRM_DebugChannel::IsDebuggable(aProcessId 0x%08x)\n",aProcessId);
+
+	TInt err = KErrPermissionDenied;
+
+	DProcess* process = DebugUtils::OpenProcessHandle(aProcessId);
+	if (process)
+		{
+		if (process->iDebugAttributes & TProcessCreateInfo::EDebugAllowed)
+			{
+			// Yes this process exists and is debuggable
+			err = KErrNone;
+			}
+		process->Close(NULL);
+		}
+
+	if (err == KErrNone)
+		{
+		LOG_MSG2("DRM_DebugChannel::IsDebuggable(aProcessId 0x%08x) - Yes it is debuggable\n",aProcessId);
+		}
+
+	return err;
+	}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/debugsrv/runmodedebug/securityserver/group/rm_debug_svr.mmp	Fri Aug 27 11:37:29 2010 +0300
@@ -0,0 +1,51 @@
+// Copyright (c) 2006-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+//
+
+ALWAYS_BUILD_AS_ARM 
+
+target         rm_debug_svr.exe
+targettype     exe
+
+sourcepath	   	../src
+source		c_shutdown_timer.cpp
+source		c_process_pair.cpp
+source        	c_security_svr_server.cpp 
+source        	c_security_svr_session.cpp 
+source		c_security_svr_async.cpp
+source        	rm_debug_svr.cpp
+
+library		euser.lib
+library         efsrv.lib
+library         btracec.lib
+
+userinclude ../inc
+userinclude ../../rmdriver/inc
+
+SYMBIAN_BASE_SYSTEMINCLUDE(nkern)
+OS_LAYER_SYSTEMINCLUDE_SYMBIAN
+
+
+UID            0x100039CE 0x102834E2
+SECUREID       0x102834E2
+VENDORID       0x70000001
+
+
+// Enables UTrace logging of DSS public API calls
+macro SYMBIAN_TRACE_ENABLE
+
+//TCB is added for the RLocalDrive methods.
+CAPABILITY AllFiles TCB
+
+SMPSAFE
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/debugsrv/runmodedebug/securityserver/inc/c_process_pair.h	Fri Aug 27 11:37:29 2010 +0300
@@ -0,0 +1,53 @@
+// Copyright (c) 2006-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+// Provides a helper class for process security management
+// 
+//
+
+#ifndef C_PROCESS_PAIR_H
+#define C_PROCESS_PAIR_H
+
+/**
+@file
+@internalTechnology
+@released
+*/
+
+/**
+CProcessPair is a mapping between a debug agent's process Id, and
+the process fileName of a process the agent is interested in debugging.
+*/
+class CProcessPair : public CBase
+	{
+public:
+	static CProcessPair* NewL(const TDesC& aProcessName, const TProcessId aProcessId);
+	~CProcessPair();
+	TBool operator==(const CProcessPair &aProcessPair) const;
+	TBool Equals(const TDesC& aProcessName, const TProcessId aProcessId) const;
+	TBool ProcessIdMatches(const CProcessPair &aProcessPair) const;
+	TBool ProcessNameMatches(const CProcessPair &aProcessPair) const;
+	TBool ProcessIdMatches(const TProcessId &aProcessId) const;
+	TBool ProcessNameMatches(const TDesC& aProcessName) const;
+
+private:
+	CProcessPair();
+	void ConstructL(const TDesC& aProcessName, TProcessId aProcessId);
+
+private:
+	HBufC16* iProcessName;
+	TProcessId iProcessId;
+	};
+
+#endif //C_PROCESS_PAIR_H
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/debugsrv/runmodedebug/securityserver/inc/c_security_svr_async.h	Fri Aug 27 11:37:29 2010 +0300
@@ -0,0 +1,83 @@
+// Copyright (c) 2006-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+// Asynchronous security server responder active object class.
+// 
+//
+
+#ifndef C_SECURITY_SVR_ASYNC_H
+#define C_SECURITY_SVR_ASYNC_H
+
+#include <rm_debug_api.h>
+
+#include "c_security_svr_session.h"
+#include "c_security_svr_server.h"
+
+// forward declaration
+class CSecuritySvrSession;
+
+/**
+Class used to handle asynchronous events within a DSS session. Currently this
+is only used to handle GetEvent() calls. It sets up an active object when a 
+client makes a GetEvent() call, and completes it when ready, or cancels it
+if the client so wishes.
+
+Only one outstanding active object per client session is permitted.
+*/
+class CSecuritySvrAsync : public CActive
+	{
+public:
+	~CSecuritySvrAsync();
+	static CSecuritySvrAsync* NewL(CSecuritySvrSession* aSession, const TDesC8& aProcessName, TProcessId aAgentId);
+
+	void GetEvent(const RMessage2& aMessage);
+	const TDesC8& ProcessName(void);
+
+protected:
+	CSecuritySvrAsync(CSecuritySvrSession* aSession, TProcessId aAgentId);
+
+	void ConstructL(const TDesC8& aProcessName);
+
+	virtual void RunL();
+	virtual void DoCancel();
+	virtual TInt RunError(TInt aError);
+
+private:
+
+    /*
+     * The last GetEvent message details. Needed for completion by RunL()
+     */
+    RMessagePtr2 iMessage;			
+
+    /*
+     * Temporary storage area for rm_debug.ldd to return data asynchronously
+     */
+	Debug::TEventInfo iInfo;
+
+	/*
+	 * Identity of this server session. Used for completing iMessage
+	 */
+	CSecuritySvrSession* iSession;
+
+	/*
+	 * Name of the process being debugged associated with this AO
+	 */
+	RBuf8 iProcessName;
+
+	/*
+	 * Debug Agent Id
+	 */
+	TProcessId iAgentId;
+	};
+ 
+#endif	// C_SECURITY_SVR_ASYNC_H
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/debugsrv/runmodedebug/securityserver/inc/c_security_svr_server.h	Fri Aug 27 11:37:29 2010 +0300
@@ -0,0 +1,80 @@
+// Copyright (c) 2006-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+// Definitions for the security server server.
+// 
+//
+
+#ifndef C_SECURITY_SVR_SERVER_H
+#define C_SECURITY_SVR_SERVER_H
+
+/**
+@file
+@internalTechnology
+@released
+*/
+
+#include <rm_debug_api.h>
+#include "c_process_pair.h"
+#include "c_shutdown_timer.h"
+#include "rm_debug_kerneldriver.h"
+
+_LIT(KDebugDriverFileName,"rm_debug.ldd");
+class CSecuritySvrSession;
+
+/**
+Definition of a Debug Security Server. Responsible for managing all debug agent clients,
+including attachment/detachment from target executables. Keeps track of which executables
+are being debugged.
+*/
+class CSecuritySvrServer : public CServer2
+	{
+	public:
+		CSession2* NewSessionL(const TVersion& aVersion, const RMessage2& aMessage) const;
+		TInt AttachProcessL(const TDesC& aTargetProcessName, const TProcessId aDebugAgentProcessId, const TBool aPassive);
+		TInt DetachProcess(const TDesC& aTargetProcessName, const TProcessId aDebugAgentProcessId);
+		void DetachAllProcesses(const TProcessId aDebugAgentProcessId);
+		TBool CheckAttached(const TThreadId aTargetThreadId, const RMessage2& aMessage, const TBool aPassive);
+		TBool CheckAttached(const TProcessId aTargetProcessId, const RMessage2& aMessage, const TBool aPassive);
+		TBool CheckAttachedProcess(const TDesC& aTargetProcessName, const RMessage2& aMessage, const TBool aPassive) const;
+		TBool IsDebugged(const TDesC& aTargetProcessName, const TBool aPassive) const;
+		void SessionClosed();
+		void SessionOpened();
+		static CSecuritySvrServer* NewLC();
+
+		TBool OEMTokenPermitsDebugL(const TCapabilitySet aTokenCaps, const TCapabilitySet aTargetCaps);
+		TBool OEMTokenPermitsFlashAccessL(const TCapabilitySet aTokenCaps);
+
+	protected:
+		CSecuritySvrServer(CActive::TPriority aActiveObjectPriority);
+		void ConstructL();
+		
+	private:
+		~CSecuritySvrServer();
+		TBool IsActiveDebugger(const TDesC& aTargetProcessName, const TProcessId aDebugAgentProcessId) const;
+		TBool IsDebugger(const TDesC& aTargetProcessName, const TProcessId aDebugAgentProcessId) const;
+		TInt GetProcessIdFromMessage(TProcessId& aProcessId, const RMessage2& aMessage) const;
+
+	private:
+		RPointerArray<CProcessPair> iActiveDebugMap;
+		RPointerArray<CProcessPair> iPassiveDebugMap;
+		TInt iSessionCount;
+		CShutdownTimer iShutdown;
+		RRM_DebugDriver iKernelDriver;
+
+	// Declare the CSecuritySvrAsync as a friend so it can use the iKernelDriver too
+	friend class CSecuritySvrAsync;
+	friend class CSecuritySvrSession;
+	};
+
+#endif // C_SECURITY_SVR_SERVER_H
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/debugsrv/runmodedebug/securityserver/inc/c_security_svr_session.h	Fri Aug 27 11:37:29 2010 +0300
@@ -0,0 +1,204 @@
+// Copyright (c) 2006-2010 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+// Definitions for the security server server side session.
+// 
+//
+
+#ifndef C_SECURITY_SVR_SESSION_H
+#define C_SECURITY_SVR_SESSION_H
+
+/**
+@file
+@internalTechnology
+@released
+*/
+
+// forward declaration
+class CSecuritySvrAsync;
+
+#include "c_security_svr_async.h"
+#include <f32file.h>
+#include <d32locd.h>
+
+#include <rm_debug_api.h>
+
+#include "rm_debug_kerneldriver.h"
+
+// Server name
+_LIT(KDebugDriverName,"RunMode Debug Driver");
+
+class CSecuritySvrServer;
+
+/**
+Debug Security Server session. Manages the session with one debug agent and
+as many target executables as it has attached to.
+*/
+class CSecuritySvrSession : public CSession2
+	{
+public:
+	CSecuritySvrSession(const TProcessId& aDebugAgentProcessId);
+	~CSecuritySvrSession();
+	void ConstructL ();
+	void CreateL();
+
+	TInt OpenHandle(const TRM_DebugDriverInfo& aDriverInfo);
+	void ServiceL(const RMessage2& aMessage);
+	void ServiceError(const RMessage2 &aMessage, TInt aError);
+
+	void ResumeThreadL(const RMessage2& aMessage);
+	void SuspendThreadL(const RMessage2& aMessage);
+	//break
+	void SetBreakL(const RMessage2& aMessage);
+	void ClearBreakL(const RMessage2& aMessage);
+	void ModifyBreakL(const RMessage2& aMessage);
+	void BreakInfoL(const RMessage2& aMessage);
+
+	void StepRangeL(const RMessage2& aMessage);
+
+	void GetEventL(const RMessage2& aMessage);
+	void CancelGetEventL(const RMessage2& aMessage);
+
+	void AttachProcessL(const RMessage2& aMessage);
+	void DetachProcessL(const RMessage2& aMessage);
+	
+    void AttachAllL(const RMessage2& aMessage);
+    void DetachAllL(const RMessage2& aMessage);
+    
+	//debug functionality
+	void GetDebugFunctionalityBufSizeL(const RMessage2& aMessage);
+	void GetDebugFunctionalityL(const RMessage2& aMessage);
+	//memory
+	void ReadMemoryL(const RMessage2& aMessage);
+	void WriteMemoryL(const RMessage2& aMessage);
+	//registers
+	void ReadRegistersL(const RMessage2& aMessage);
+	void WriteRegistersL(const RMessage2& aMessage);
+	//event
+	void SetEventActionL(const RMessage2& aMessage);
+
+	void GetListL(const RMessage2& aMessage);
+	void StepL(const RMessage2& aMessage);
+	void TraceExecutableL(const RMessage2& aMessage);
+	
+	//crash log
+	void ReadCrashLogL(const RMessage2& aMessage);
+	void WriteCrashConfigL(const RMessage2& aMessage);
+	void EraseCrashLogL(const RMessage2& aMessage);
+	void EraseEntireCrashLogL(const RMessage2& aMessage);
+
+	void SetProcessBreakL(const RMessage2& aMessage);
+	void ModifyProcessBreakL(const RMessage2& aMessage);
+	void ProcessBreakInfoL(const RMessage2& aMessage);
+
+	void KillProcessL(const RMessage2& aMessage);
+
+	TCapabilitySet GetOEMDebugCapabilities(void) const { return iOEMDebugCapabilities; };
+
+#ifdef _DEBUG
+	void DoFailAlloc(const RMessage2& aMessage);
+#endif
+
+private:
+	CSecuritySvrServer& Server() const;
+	void HeapWatcher(const TUint32 aFunction, const TBool aEntry) const;
+	void WriteDataL(const RMessage2& aMessage, const TInt aIndex, const TAny* aPtr, const TUint32 aPtrSize) const;
+	void CheckAttachedL(const TThreadId aThreadId, const RMessage2& aMessage, const TBool aPassive) const;
+	void CheckAttachedL(const TProcessId aProcessId, const RMessage2& aMessage, const TBool aPassive) const;
+	TBool PermitDebugL(const TProcessId aDebugAgentProcessId, const TDesC& aTargetProcessName) const;
+	TBool IsDebugged(const TDesC& aFileName, const TBool aPassive) const;
+	void OpenFileHandleL(const TDesC& aFileName, RFs& aFs, RFile& aFileHandle);
+	TBool IsTraceBitSet(const TDesC8& aHeaderData, const TBool aXip);
+	TBool IsDebugBitSet(const TDesC8& aHeaderData, const TBool aXip);
+	TBool CheckSufficientData(const TDesC8& aHeaderData, const TBool aXip) const;
+
+	void ValidateMemoryInfoL(const TThreadId aThreadId, const Debug::TMemoryInfo &aMemoryInfo, const TBool aReadOperation);
+	void ValidateRegisterBuffersL(const RMessage2& aMessage, TUint32& aNumberOfRegisters);
+
+	TInt GetExecutablesListL(TDes8& aBuffer, TUint32& aSize) const;
+	void AppendExecutableData(TDes8& aBuffer, TUint32& aSize, const TDesC& aEntryName) const;
+	void GetSecureIdL(const TDesC& aFileName, TUid& aSecureId);
+	TUid GetSecureIdL(const TDesC8& aHeaderData, TBool aXip);
+
+	void IsDebuggableL(const TDesC& aFileName);
+	TThreadId ReadTThreadIdL(const RMessagePtr2& aMessage, const TInt aIndex) const;
+	TProcessId ReadTProcessIdL(const RMessagePtr2& aMessage, const TInt aIndex) const;
+	TBool IsExecutableXipL(RFile& aExecutable);
+	
+	void ConnectCrashPartitionL(void);
+
+	void GetDebugAgentOEMTokenCapsL();
+	TInt CheckFlashAccessPermissionL(const RThread& aClientThread);
+
+	// Declare the CSecuritySvrAsync as a friend so it can use the iKernelDriver too
+	friend class CSecuritySvrAsync;
+
+private:
+	/**
+	The TProcessId of the Debug Agent associated with this session. A convenience to
+	save looking it up repeatedly.
+	*/
+	TProcessId iDebugAgentProcessId;
+	/**
+	Need an array of async completion objects, one for each target executable.
+	*/
+	RPointerArray<CSecuritySvrAsync> iAsyncHandlers;
+
+	/**
+	Used to track whether the Debug Agent has been notified when closing the session.
+	*/
+	TBool iServerNotified;
+
+	/**
+	OEM Debug token support. This is only used when the Debug Agent has OEM debug 
+	authority provided by a specific authorisation token file. This token confers
+	the ability to debug certain executables which have not been built as 'Debuggable'.
+	
+	The OEM Debug token executable must be marked with 'AllFiles', as this is analogous
+	to looking 'inside' executables - with AllFiles, it could read all the data out of an
+	executable in \sys\bin\. In addition, since debug control of an executable implies the
+	ability to execute arbitrary code within the target process space, this would imply that
+	a Debug Agent could use any PlatSec capability which that target process possessed.
+	
+	Therefore, we require that the OEM Debug Token must also be marked with a superset of
+	the PlatSec capabilities of the executable which is to be debugged. This means the
+	Debug Agent is not granted more access/PlatSec capabilities than its authorisation
+	token allows, and cannot exploit a target executable to leverage greater access than
+	should be permitted.
+
+	iTargetCapabilities tracks which PlatSec capabilities the target executables may
+	possess and still be debugged by this debug agent. The capabilities are NOT those
+	of the debug agent process, they are the capabilites indicated in the OEM Debug Token
+	which describe the capabilities the debug agent is authorised to debug. E.g. a Debug
+	Agent might use CommsDD, but wish to debug a DRM capable executable. In that case, the
+	Debug Agent exe must be signed with CommsDD, but the OEM Debug Token need only possess
+	DRM and AllFiles (permission to look inside another executable).
+	*/
+	TCapabilitySet iOEMDebugCapabilities;
+	
+	//RLocalDrive to access the crash Flash
+	RLocalDrive iLocalDrive;
+	
+	//For NOR flash 
+	TLocalDriveCapsV2 iCaps;
+	
+	/**
+	 * If true means the local drive connected to the crash partition else connect 
+	 * when access required to crash flash partition for read operation
+	*/	
+	TBool iCrashConnected;
+	};
+
+
+#endif // C_SECURITY_SVR_SESSION_H
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/debugsrv/runmodedebug/securityserver/inc/c_shutdown_timer.h	Fri Aug 27 11:37:29 2010 +0300
@@ -0,0 +1,46 @@
+// Copyright (c) 2007-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+// Definitions for the security server's shutdown timer.
+// 
+//
+
+#ifndef C_SHUTDOWN_TIMER_H
+#define C_SHUTDOWN_TIMER_H
+
+/**
+@file
+@internalTechnology
+@released
+*/
+
+#include <e32base.h>
+
+const TInt KShutdownDelay = 5000000; // approx 5 seconds
+const TInt KActivePriorityShutdown = -1; // priority for shutdown AO
+
+/**
+Timer class used to manage shutdown of the DSS
+*/
+class CShutdownTimer : public CTimer
+	{
+public:
+	CShutdownTimer();
+	void ConstructL();
+	void Start();
+private:
+	void RunL();
+	};
+
+#endif // C_SHUTDOWN_TIMER_H
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/debugsrv/runmodedebug/securityserver/inc/low_mem_requests.h	Fri Aug 27 11:37:29 2010 +0300
@@ -0,0 +1,37 @@
+// Copyright (c) 2007-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+// Request numbers for use with the Debug Security Server and low mem tests
+// 
+//
+
+#ifndef LOW_MEM_REQUESTS_H
+#define LOW_MEM_REQUESTS_H
+
+/**
+@file
+@internalTechnology
+@released
+*/
+
+#ifdef _DEBUG
+// enumerators to use to call Debug Security Server in debug mode for low mem tests
+enum TLowMemDebugServRqst
+	{
+	EDebugServFailAlloc = 0x10000001,
+	EDebugServMarkEnd = 0x10000002,
+	EDebugServMarkHeap = 0x10000003
+	};
+#endif
+
+#endif //LOW_MEM_REQUESTS_H
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/debugsrv/runmodedebug/securityserver/inc/rm_debug_api.h	Fri Aug 27 11:37:29 2010 +0300
@@ -0,0 +1,2657 @@
+// Copyright (c) 2006-2010 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+// Definitions for the run mode debug agent client side sessions.
+// 
+// WARNING: This file contains some APIs which are internal and are subject
+//          to change without notice. Such APIs should therefore not be used
+//          outside the Kernel and Hardware Services package.
+//
+
+#ifndef RM_DEBUG_API_H
+#define RM_DEBUG_API_H
+
+/**
+@file
+@publishedPartner
+@released
+*/
+
+#include <e32cmn.h>
+#include <e32def_private.h>
+
+/**
+  The Debug namespace contains all API definitions used for on-target debugging.
+  */
+namespace Debug {
+
+/** This is the maximum size in bytes a user trace can be */
+const TInt TUserTraceSize = 256;
+
+/**
+  Information in the debug functionality block is represented as a concatenation
+  of pairs of TTagHeader structures and arrays of TTag objects.
+  @see TTagHeader
+  @see RSecuritySvrSession::GetDebugFunctionality
+  */
+struct TTag
+{
+	/** Tag ID, value identifying this tag. */
+	TUint32	iTagId;
+	/**
+	  Values correspond to TTagType enumerators.
+	  @see TTagType
+	  */
+	TUint16	iType;
+	/** Size of external data associated with this tag. */
+	TUint16 iSize;
+	/** Data associated with this tag. */
+	TUint32 iValue;
+};
+
+/**
+  Enumeration defining the supported tag types. These enumerators are used in TTag.iTagId.
+  @see TTag
+  */
+enum TTagType
+{
+	/** Indicates that the iValue field of a TTag structure will contain either ETrue or EFalse. */
+	ETagTypeBoolean = 0,
+	/** Indicates that the iValue field of a TTag structure will contain a value in the TUint32 range. */
+	ETagTypeTUint32 = 1,
+	/** Indicates that the iValue field of a TTag structure will contain values from an enumeration. */
+	ETagTypeEnum = 2,
+	/** Indicates that the iValue field of a TTag structure should be interpreted as a bit field. */
+	ETagTypeBitField = 3,
+	/** Indicates that the type of the iValue field of a TTag structure is unknown. */
+	ETagTypeUnknown = 4,
+	/** Indicates that the iValue field of a TTag structure will contain a pointer. */
+	ETagTypePointer = 5
+};
+
+/**
+  Information in the debug functionality block is represented as a concatenation
+  of pairs of TTagHeader structures and arrays of TTag objects.
+  @see TTag
+  @see RSecuritySvrSession::GetDebugFunctionality
+  */
+struct TTagHeader
+{
+	/** Value identifying the contents of this TTagHeader, should be interpreted as an enumerator from TTagHeaderId.
+	  @see TTagHeaderId
+	  */
+	TUint16	iTagHdrId;
+	/** The number of TTag elements in the array associated with this TTagHeader. */
+	TUint16 iNumTags;
+};
+
+/**
+  Enumeration used to identify TTagHeader structures, TTagHeader::iTagHdrId elements take these enumerators as values.
+  @see TTagHeader
+  */
+enum TTagHeaderId
+{
+	ETagHeaderIdCore = 0,            /**< Identifies a TTagHeader with associated TTag elements with iTagId values from TFunctionalityCore. */
+	ETagHeaderIdMemory = 1,          /**< Identifies a TTagHeader with associated TTag elements with iTagId values from TFunctionalityMemory. */
+	/**
+	  Identifies a TTagHeader with associated TTag elements with iTagId values from TFunctionalityRegister.
+	  These values are defined as in the document Symbian Core Dump File Format Appendix C
+	  (see SGL.TS0028.027 - Symbian Core Dump File Format v1.0.doc).
+	  The TTag objects in the associated array have an iSize value corresponding to the size of the register's data in bytes.
+	  */
+	ETagHeaderIdRegistersCore = 2,
+	/**
+	  Identifies a TTagHeader with associated TTag elements with iTagId values corresponding to coprocessor register identifiers.
+	  Coprocessor registers are defined as in the document Symbian Core Dump File Format Appendix C as follows
+	  (see SGL.TS0028.027 - Symbian Core Dump File Format v1.0.doc):
+
+	  For each 32-bit data word defining a co-pro register, the definition of the meaning of the bits follows
+	  the ARM Architecture Reference manual instruction coding
+
+	  Upper Halfword	Lower Halfword
+	  Opcode 2			CRm
+
+	  For example: The Domain Access Control Register is Register 3 of co-processor 15. The encoding is therefore
+	  CRm = 3
+	  Opcode2 = 0
+
+	  Therefore the functionality tag would be:
+	  TagID:  15			// co-processor number
+	  Type: ETagTypeTUint32
+	  Data: 0x00000003		// Opcode2 = 0, CRm = 3
+	  */
+	ETagHeaderIdCoProRegisters = 3,  /**< Identifies a TTagHeader with associated TTag elements with iTagId values from TFunctionalityRegister. */
+	ETagHeaderIdBreakpoints = 4,     /**< Identifies a TTagHeader with associated TTag elements with iTagId values from TFunctionalityBreakpoint. */
+	ETagHeaderIdStepping = 5,        /**< Identifies a TTagHeader with associated TTag elements with iTagId values from TFunctionalityStep. */
+	ETagHeaderIdExecution = 6,       /**< Identifies a TTagHeader with associated TTag elements with iTagId values from TFunctionalityExec. */
+	ETagHeaderIdEvents = 7,          /**< Identifies a TTagHeader with associated TTag elements with iTagId values from TEventType. */
+	ETagHeaderIdApiConstants = 8,    /**< Identifies a TTagHeader with associated TTag elements with iTagId values from TFunctionalityApiConstants.*/
+	ETagHeaderList = 9,              /**< Identifies a TTagHeader with associated TTag elements with iTagId values from TListId. */
+	ETagHeaderIdKillObjects = 10,    /**< Identifies a TTagHeader with associated TTag elements with iTagId values from TFunctionalityKillObject. */
+	ETagHeaderIdSecurity = 11,		 /**< Identifies a TTagHeader with associated TTag elements with iTagId values from TFunctionalitySecurity */
+	ETagHeaderIdBuffers = 12,        /**< Identifies a TTagHeader with associated TTag elements with iTagId values from TBufferType. */
+	ETagHeaderIdStopModeFunctions = 13, /**< Identifies a TTagHeader with associated TTag elements with iTagId values from TFunctionalityStopModeFunctions. */	
+};
+
+/**
+  This structure is not used in the run-mode debug API.
+  @deprecated
+  */
+struct TSubBlock
+{
+	/** Header to identify the TSubBlock. */
+	TTagHeader iHeader;
+	/** Pointer to array of TTag values associated with this TSubBlock. */
+	TTag* iTagArray;
+};
+
+/**
+  These tags define what kinds of core functionality are supported by the run-mode debug subsystem.
+  TTag structures associated with the ETagHeaderIdCore sub-block will have iTagId values from this enumeration.
+  See each enumerator for an explanation of how a TTag with that iTagId should be interpreted.
+  */
+enum TFunctionalityCore
+{
+	ECoreEvents = 0,        /**< Indicates whether events processing is supported. */
+	ECoreStartStop = 1,     /**< Indicates whether suspending and resuming threads is supported. */
+	ECoreMemory = 2,        /**< Indicates whether reading and writing memory is supported. */
+	ECoreRegister = 3,      /**< Indicates whether reading and writing register values is supported. */
+	ECoreBreakpoint = 4,    /**< Indicates whether breakpoints are supported. */
+	ECoreStepping = 5,      /**< Indicates whether stepping is supported. */
+	ECoreLists = 6,         /**< Indicates whether listings are supported. */
+	ECoreLogging = 7,       /**< Indicates whether logging is supported. */
+	ECoreHardware = 8,      /**< Indicates whether hardware support is supported. */
+	ECoreApiConstants = 9,  /**< Indicates whether the information in the ETagHeaderIdApiConstants sub-block is relevant. */
+	ECoreKillObjects = 10,  /**< Indicates whether killing objects (i.e. threads and processes) is supported. */
+	ECoreSecurity = 11,		/**< Indicates whether OEM Debug token support or other security info is supported. */
+	ECoreStopModeFunctions = 12, /**< Indicates whether Stop Mode function calling is supported. */
+	ECoreStopModeBuffers = 13, /**< Indicates whether Stop Mode buffers are supported. */
+	
+	/**
+	  @internalTechnology
+	  A debug agent should find the number of core tags from the DFBlock rather than this enumerator.
+	  */
+	ECoreLast
+};
+
+/**
+  These tags define what kind of memory operations can be performed.
+  TTag structures associated with the ETagHeaderIdMemory sub-block will have iTagId values from this enumeration.
+  See each enumerator for an explanation of how a TTag with that iTagId should be interpreted.
+ */
+enum TFunctionalityMemory
+{
+	EMemoryRead = 0,          /**< Indicates whether reading memory is supported. */
+	EMemoryWrite = 1,         /**< Indicates whether writing memory is supported. */
+	EMemoryAccess64 = 2,      /**< Indicates whether 64 bit memory access is supported. */
+	EMemoryAccess32 = 3,      /**< Indicates whether 32 bit memory access is supported. */
+	EMemoryAccess16 = 4,      /**< Indicates whether 16 bit memory access is supported. */
+	EMemoryAccess8 = 5,       /**< Indicates whether 8 bit memory access is supported. */
+	EMemoryBE8 = 6,           /**< Indicates whether reading memory as 8 bit big-endian values is supported. */
+	EMemoryBE32 = 7,          /**< Indicates whether reading memory as 32 bit big-endian values is supported. */
+	EMemoryLE8 = 8,           /**< Indicates whether reading memory as 8 bit little-endian values is supported. */
+	EMemoryMaxBlockSize = 9,  /**< Corresponds to the maximum size of a block of memory which can be requested. */
+	/**
+	  @internalTechnology
+	  A debug agent should find the number of memory tags from the DFBlock rather than this enumerator.
+	  */
+	EMemoryLast
+};
+
+/**
+  These tags define which objects can be killed by the device driver.
+  TTag structures associated with the ETagHeaderIdKillObjects sub-block will have iTagId values from this enumeration.
+  See each enumerator for an explanation of how a TTag with that iTagId should be interpreted.
+ */
+enum TFunctionalityKillObject
+{
+	EFunctionalityKillThread = 0,          /**< Indicates whether killing threads is supported. */
+	EFunctionalityKillProcess = 1,         /**< Indicates whether killing processes is supported. */
+	/**
+	  @internalTechnology
+	  A debug agent should find the number of kill object tags from the DFBlock rather than this enumerator.
+	  */
+	EFunctionalityKillObjectLast
+};
+
+/**
+  A TTag with an id from the TFunctionalityRegister enum will have a value from this enumeration.
+  The values define how a register can be accessed, if at all.
+ */
+enum TFunctionalityAccess
+{
+	EAccessNone = 0,       /**< Indicates that a register cannot be accessed. */
+	EAccessReadOnly = 1,   /**< Indicates that a register can be read, but not written to. */
+	EAccessWriteOnly = 2,  /**< Indicates that a register can be written to, but not read. */
+	EAccessReadWrite = 3,  /**< Indicates that a register can be both read and written to. */
+	EAccessUnknown = 4,    /**< Indicates that it is unspecified whether reading or writing to a register is possible. */
+};
+
+/**
+  These enumerators act as core register identifiers.
+  TTag structures associated with the ETagHeaderIdRegistersCore sub-block will have iTagId values from this enumeration.
+  The numeric value of each enumerator identifies the register according to the definitions in the Symbian Core Dump File Format Appendix B
+  (see SGL.TS0028.027 - Symbian Core Dump File Format v1.0.doc).
+  */
+enum TFunctionalityRegister
+{
+	ERegisterR0 = 0x00000000,      /**< Identifier for user mode register R0. */
+	ERegisterR1 = 0x00000100,      /**< Identifier for user mode register R1. */
+	ERegisterR2 = 0x00000200,      /**< Identifier for user mode register R2. */
+	ERegisterR3 = 0x00000300,      /**< Identifier for user mode register R3. */
+	ERegisterR4 = 0x00000400,      /**< Identifier for user mode register R4. */
+	ERegisterR5 = 0x00000500,      /**< Identifier for user mode register R5. */
+	ERegisterR6 = 0x00000600,      /**< Identifier for user mode register R6. */
+	ERegisterR7 = 0x00000700,      /**< Identifier for user mode register R7. */
+	ERegisterR8 = 0x00000800,      /**< Identifier for user mode register R8. */
+	ERegisterR9 = 0x00000900,      /**< Identifier for user mode register R9. */
+	ERegisterR10 = 0x00000a00,     /**< Identifier for user mode register R10. */
+	ERegisterR11 = 0x00000b00,     /**< Identifier for user mode register R11. */
+	ERegisterR12 = 0x00000c00,     /**< Identifier for user mode register R12. */
+	ERegisterR13 = 0x00000d00,     /**< Identifier for user mode register R13. */
+	ERegisterR14 = 0x00000e00,     /**< Identifier for user mode register R14. */
+	ERegisterR15 = 0x00000f00,     /**< Identifier for user mode register R15. */
+	ERegisterCpsr = 0x00001000,    /**< Identifier for CPSR. */
+	ERegisterR13Svc = 0x00001100,  /**< Identifier for R13 supervisor mode banked register. */
+	ERegisterR14Svc = 0x00001200,  /**< Identifier for R14 supervisor mode banked register. */
+	ERegisterSpsrSvc = 0x00001300, /**< Identifier for SPSR supervisor mode banked register. */
+	ERegisterR13Abt = 0x00001400,  /**< Identifier for R13 Abort mode banked register. */
+	ERegisterR14Abt = 0x00001500,  /**< Identifier for R14 Abort mode banked register. */
+	ERegisterSpsrAbt = 0x00001600, /**< Identifier for SPSR Abort mode banked register. */
+	ERegisterR13Und = 0x00001700,  /**< Identifier for R13 Undefined mode banked register. */
+	ERegisterR14Und = 0x00001800,  /**< Identifier for R14 Undefined mode banked register. */
+	ERegisterSpsrUnd = 0x00001900, /**< Identifier for SPSR Undefined mode banked register. */
+	ERegisterR13Irq = 0x00001a00,  /**< Identifier for R13 Interrupt mode banked register. */
+	ERegisterR14Irq = 0x00001b00,  /**< Identifier for R14 Interrupt mode banked register. */
+	ERegisterSpsrIrq = 0x00001c00, /**< Identifier for SPSR Interrupt mode banked register. */
+	ERegisterR8Fiq = 0x00001d00,   /**< Identifier for R8 Fast Interrupt mode banked register. */
+	ERegisterR9Fiq = 0x00001e00,   /**< Identifier for R9 Fast Interrupt mode banked register. */
+	ERegisterR10Fiq = 0x00001f00,  /**< Identifier for R10 Fast Interrupt mode banked register. */
+	ERegisterR11Fiq = 0x00002000,  /**< Identifier for R11 Fast Interrupt mode banked register. */
+	ERegisterR12Fiq = 0x00002100,  /**< Identifier for R12 Fast Interrupt mode banked register. */
+	ERegisterR13Fiq = 0x00002200,  /**< Identifier for R13 Fast Interrupt mode banked register. */
+	ERegisterR14Fiq = 0x00002300,  /**< Identifier for R14 Fast Interrupt mode banked register. */
+	ERegisterSpsrFiq = 0x00002400, /**< Identifier for SPSR Fast Interrupt mode banked register. */
+	/**
+	  @internalTechnology
+	  A debug agent should find the number of core registers from the DFBlock rather than this enumerator.
+	  */
+	ERegisterLast = 37
+};
+
+
+/**
+  These tags define the kind of breakpoints that are supported.
+  TTag structures associated with the ETagHeaderIdBreakpoints sub-block will have iTagId values from this enumeration.
+  See each enumerator for an explanation of how a TTag with that iTagId should be interpreted.
+ */
+enum TFunctionalityBreakpoint
+{
+	EBreakpointThread = 0,         /**< Indicates whether thread specific breakpoints are supported. */
+	EBreakpointProcess = 1,        /**< Indicates whether process specific breakpoints are supported. */
+	EBreakpointSystem = 2,         /**< Indicates whether system wide breakpoints are supported. */
+	EBreakpointArm = 3,            /**< Indicates whether ARM mode breakpoints are supported. */
+	EBreakpointThumb = 4,          /**< Indicates whether Thumb mode breakpoints are supported. */
+	EBreakpointT2EE = 5,           /**< Indicates whether Thumb2 mode breakpoints are supported. */
+	EBreakpointArmInst = 6,        /**< Reserved for future use. */
+	EBreakpointThumbInst = 7,      /**< Reserved for future use. */
+	EBreakpointT2EEInst = 8,       /**< Reserved for future use. */
+	EBreakpointSetArmInst = 9,     /**< Reserved for future use. */
+	EBreakpointSetThumbInst = 10,  /**< Reserved for future use. */
+	EBreakpointSetT2EEInst = 11,   /**< Reserved for future use. */
+	/**
+	  @internalTechnology
+	  A debug agent should find the number of breakpoint tags from the DFBlock rather than this enumerator.
+	  */
+	EBreakpointLast
+};
+
+/**
+  These enumerators provide information about the stepping capabilities of the debug sub-system.
+  TTag structures associated with the ETagHeaderIdStepping sub-block will have iTagId values from this enumeration.
+  See each enumerator for an explanation of how a TTag with that iTagId should be interpreted.
+ */
+enum TFunctionalityStep
+{
+	EStep = 0, /**< Indicates whether instruction stepping is supported. */
+	/**
+	  @internalTechnology
+	  A debug agent should find the number of stepping tags from the DFBlock rather than this enumerator.
+	  */
+	EStepLast
+};
+
+/**
+  These enumerators provide information about the execution control capabilities of the debug sub-system.
+  TTag structures associated with the ETagHeaderIdExecution sub-block will have iTagId values from this enumeration.
+  See each enumerator for an explanation of how a TTag with that iTagId should be interpreted.
+ */
+enum TFunctionalityExec
+{
+	EExecThreadSuspendResume = 0,  /**< Indicates whether suspending and resuming threads is supported. */
+	EExecProcessSuspendResume = 1, /**< Indicates whether suspending and resuming processes is supported. */
+	EExecSystemSuspendResume = 2,  /**< Indicates whether suspending and resuming the entire system is supported. */
+	/**
+	  @internalTechnology
+	  A debug agent should find the number of execution control tags from the DFBlock rather than this enumerator.
+	  */
+	EExecLast
+};
+
+/**
+  This enumeration defines the event types supported by the debug sub-system.
+  TTag structures associated with the ETagHeaderIdEvents sub-block will have
+  iTagId values from this enumeration, and iValue values from the TKernelEventAction enumeration.
+
+  These enumerators are also used by the RSecuritySvrSession API to identify events.
+  @see RSecuritySvrSession
+  @see TKernelEventAction
+ */
+enum TEventType
+{
+	EEventsBreakPoint = 0,    /**< Identifies a breakpoint event. */
+	EEventsSwExc = 1,         /**< Identifies a software exception event. */
+	EEventsHwExc = 2,         /**< Identifies a hardware exception event. */
+	EEventsKillThread = 3,    /**< Identifies a kill thread event. */
+	EEventsAddLibrary = 4,    /**< Identifies an add library event. */
+	EEventsRemoveLibrary = 5, /**< Identifies a remove library event. */
+	/**
+	 If an event is generated and there is only a single space remaining in the events queue then
+	 an event of type EEventsBufferFull will be stored in the queue and the generated event will
+	 be discarded. If further events occur while the buffer is full the events will be discarded.
+	 As such an event of type EEventsBufferFull being returned signifies that one or more events
+	 were discarded. An event of this type has no valid data associated with it.
+	 */
+	EEventsBufferFull = 6,
+	EEventsUnknown = 7,       /**< Identifies an event of unknown type. */
+	EEventsUserTrace = 8,     /**< Identifies a user trace. */
+	EEventsProcessBreakPoint = 9, /**< Identifies a process breakpoint event. */
+	EEventsStartThread = 10, /**< Identifies a start thread event. */
+	EEventsUserTracesLost = 11, /**< Identifies user traces being lost. */
+	EEventsAddProcess = 12, /**< Identifies an AddProcess event */
+	EEventsRemoveProcess = 13, /**< Identifies a RemoveProcess event */
+	/**
+	  @internalTechnology
+	  A debug agent should find the number of event types from the DFBlock rather than this enumerator.
+	  */
+	EEventsLast
+};
+
+/**
+  These enumerators provide information about constants which are used in the RSecuritySvrSession API.
+  TTag structures associated with the ETagHeaderIdApiConstants sub-block will have iTagId values from this enumeration.
+  See each enumerator for an explanation of how a TTag with that iTagId should be interpreted.
+ */
+enum TFunctionalityApiConstants
+	{
+	/**
+	  Corresponds to the size of a buffer required to store a TEventInfo.
+	  @see TEventInfo
+	  */
+	EApiConstantsTEventInfoSize = 0,
+	/**
+	  @internalTechnology
+	  A debug agent should find the number of API constants tags from the DFBlock rather than this enumerator.
+	  */
+	EApiConstantsLast,
+	};
+
+/**
+  The set of possible actions which could be taken when a kernel event occurs.
+  Not all actions are possible for all events. The debug functionality sub-block with header id ETagHeaderIdEvents
+  indicates which values are permitted for each event. The value given for that event should be
+  considered as the most intrusive action the debugger may set: with the definition that EActionSuspend is more
+  intrusive than EActionContinue, which is more intrusive than EActionIgnore.
+  @see RSecuritySvrSession
+  */
+enum TKernelEventAction
+{
+	/** If an event action is set to this value then events of that type will be
+	  ignored, and not reported to the debugger. */
+	EActionIgnore = 0,
+	/** If an event action is set to this value then events of that type will be
+	  reported to the debugger and the thread which generated the event will be
+	  allowed to continue executing. */
+	EActionContinue = 1,
+	/** If an event action is set to this value then events of that type will be
+	  reported to the debugger and the thread which generated the event will be
+	  suspended. */
+	EActionSuspend = 2,
+	/**
+	  @internalTechnology
+	  Count of event actions.
+	  */
+	EActionLast
+};
+
+/**
+  These enumerators provide information about the ability of the debug subsystem to support OEM Debug tokens.
+  TTag structures associated with the ETagHeaderIdSecurity sub-block will have iTagId values from this enumeration.
+  See each enumerator for an explanation of how a TTag with that iTagId should be interpreted.
+ */
+enum TFunctionalitySecurity
+{
+	ESecurityOEMDebugToken = 0,  /**< Indicates whether the DSS supports the use of OEM Debug Tokens. */
+
+	/**
+	  @internalTechnology
+	  A debug agent should find the number of tags from the DFBlock rather than this enumerator.
+	  */
+	ESecurityLast
+};
+
+/**
+  Used for storing the contents of a 32 bit register
+  */
+typedef TUint32 TRegisterValue32;
+
+
+/**
+ * Processor mode
+ */
+enum TArmProcessorModes
+{
+	EUserMode=0x10,    	//!< EUserMode
+    EFiqMode=0x11,  	//!< EFiqMode
+    EIrqMode=0x12,  	//!< EIrqMode
+    ESvcMode=0x13,  	//!< ESvcMode
+    EAbortMode=0x17,	//!< EAbortMode
+    EUndefMode=0x1b,	//!< EUndefMode
+    EMaskMode=0x1f  	//!< EMaskMode
+};
+
+
+
+/**
+  Structure containing information about the state of the registers when a
+  hardware exception occurred
+  */
+class TRmdArmExcInfo
+	{
+public:
+	/** Enumeration detailing the types of exception which may occur. */
+	enum TExceptionType
+		{
+		/** Enumerator signifying that a prefetch abort error has occurred. */
+		EPrefetchAbort = 0,
+		/** Enumerator signifying that a data abort error has occurred. */
+		EDataAbort = 1,
+		/** Enumerator signifying that an undefined instruction error has occurred. */
+		EUndef =2
+		};
+
+	/** Value of CPSR. */
+	TRegisterValue32 iCpsr;
+	/** Type of exception which has occurred. */
+	TExceptionType iExcCode;
+	/** Value of R13 supervisor mode banked register. */
+	TRegisterValue32 iR13Svc;
+	/** Value of user mode register R4. */
+	TRegisterValue32 iR4;
+	/** Value of user mode register R5. */
+	TRegisterValue32 iR5;
+	/** Value of user mode register R6. */
+	TRegisterValue32 iR6;
+	/** Value of user mode register R7. */
+	TRegisterValue32 iR7;
+	/** Value of user mode register R8. */
+	TRegisterValue32 iR8;
+	/** Value of user mode register R9. */
+	TRegisterValue32 iR9;
+	/** Value of user mode register R10. */
+	TRegisterValue32 iR10;
+	/** Value of user mode register R11. */
+	TRegisterValue32 iR11;
+	/** Value of R14 supervisor mode banked register. */
+	TRegisterValue32 iR14Svc;
+	/** Address which caused exception (System Control Coprocessor Fault Address Register) */
+	TRegisterValue32 iFaultAddress;
+	/** Value of System Control Coprocessor Fault Status Register. */
+	TRegisterValue32 iFaultStatus;
+	/** Value of SPSR supervisor mode banked register. */
+	TRegisterValue32 iSpsrSvc;
+	/** Value of user mode register R13. */
+	TRegisterValue32 iR13;
+	/** Value of user mode register R14. */
+	TRegisterValue32 iR14;
+	/** Value of user mode register R0. */
+	TRegisterValue32 iR0;
+	/** Value of user mode register R1. */
+	TRegisterValue32 iR1;
+	/** Value of user mode register R2. */
+	TRegisterValue32 iR2;
+	/** Value of user mode register R3. */
+	TRegisterValue32 iR3;
+	/** Value of user mode register R12. */
+	TRegisterValue32 iR12;
+	/** Value of user mode register R15, points to instruction which caused exception. */
+	TRegisterValue32 iR15;
+	};
+
+/**
+  The maximum size, in bytes, of the panic category string returned as part of a
+  TEventInfo object.
+
+  @see TEventInfo
+  @see TThreadKillInfo
+  */
+const TInt KPanicCategoryMaxName = KMaxName;
+
+/**
+  Event specific information returned as part of a TEventInfo object when
+  an agent set breakpoint is hit.
+  */
+class TThreadBreakPointInfo
+	{
+public:
+	/** Identifies the type of exception. */
+	TExcType iExceptionNumber;
+	/** Structure containing information about the ARM register values. */
+	TRmdArmExcInfo iRmdArmExcInfo;
+	};
+
+/**
+  Event specific information returned as part of a TEventInfo object when
+  a software exception occurs.
+  */
+class TThreadSwExceptionInfo
+	{
+public:
+	/** The value of the program counter. */
+	TUint32 iCurrentPC;
+	/** Identifies the type of exception. */
+	TExcType iExceptionNumber;
+	};
+
+/**
+  Event specific information returned as part of a TEventInfo object when
+  a hardware exception occurs.
+  */
+class TThreadHwExceptionInfo
+	{
+public:
+	/** Identifies the type of exception. */
+	TExcType iExceptionNumber;
+	/** Structure containing information about the ARM register values. */
+	TRmdArmExcInfo iRmdArmExcInfo;
+	};
+
+/**
+  Event specific information returned as part of a TEventInfo object when
+  a thread kill event occurs.
+  */
+class TThreadKillInfo
+	{
+public:
+	/** The value of the program counter. */
+	TUint32 iCurrentPC;
+	/** Specifies the reason for the kill thread event, this value is specific to the killed thread and does not correspond to a standard Symbian enumeration. */
+	TInt iExitReason;
+	/** Specifies the type of the thread kill event, values correspond to elements of TExitType. */
+	TUint8 iExitType;
+	/** The panic category of the killed thread. */
+	TUint8 iPanicCategory[KPanicCategoryMaxName];
+	/** Contains the length in bytes of the initialised data in iPanicCategory. */
+	TInt iPanicCategoryLength;
+	};
+
+/**
+  Event specific information returned as part of a TEventInfo object when
+  a library load event occurs.
+  */
+class TLibraryLoadedInfo
+	{
+public:
+	/** The name of the file that the library was loaded from. */
+	TUint8 iFileName[KMaxName];
+	/** Contains the length in bytes of the initialised data in iFileName. */
+	TInt iFileNameLength;
+	/** The code base address (.text). */
+	TUint32 iCodeAddress;
+	/** The base address of the initialised data section (.data). */
+	TUint32 iDataAddress;
+	};
+
+/**
+  Event specific information returned as part of a TEventInfo object when
+  a thread is started
+  */
+class TStartThreadInfo
+	{
+public:
+	/** The name of the file that the process owning the thread was created from. */
+	TUint8 iFileName[KMaxName];
+	/** Contains the length in bytes of the initialised data in iFileName. */
+	TInt iFileNameLength;
+	};
+
+/**
+  Event specific information returned as part of a TEventInfo object when
+  a process is added. Note that the Process may not be fully constructed,
+  e.g. no threads.
+  */
+class TAddProcessInfo
+	{
+public:
+	/** The name of the file that the process was created from. */
+	TUint8 iFileName[KMaxName];
+	/** Contains the length in bytes of the initialised data in iFileName. */
+	TInt iFileNameLength;
+	/** The UID3 of this process */
+	TUint32 iUid3;  
+	/** Contains the CreatorThread ID if available: May be 0 */
+	TUint64 iCreatorThreadId;  
+	};
+
+/**
+  Event specific information returned as part of a TEventInfo object when
+  a process is removed. Note that the Process may not be fully destroyed,
+  so its resources should only be accessed if you already have a handle to it.
+  */
+class TRemoveProcessInfo
+	{
+public:
+	/** The name of the file that the process was created from. */
+	TUint8 iFileName[KMaxName];
+	/** Contains the length in bytes of the initialised data in iFileName. */
+	TInt iFileNameLength;
+	TUint32 iSpare1;	// Unused
+	};
+
+/**
+  Event specific information returned as part of a TEventInfo object when
+  a library unload event occurs.
+  */
+class TLibraryUnloadedInfo
+	{
+public:
+	/** The name of the file that the library was loaded from. */
+	TUint8 iFileName[KMaxName];
+	/** Contains the length in bytes of the initialised data in iFileName. */
+	TInt iFileNameLength;
+	};
+
+/**
+ * Enum to represent the context of a user trace message
+ */ 
+enum TUserTraceMessageContext 
+{
+	ESingleMessage = 0x1,   /** Indicates this message is the only one corresponding to a given user trace */ 
+	EMultiStart = 0x2, /** Indicates this message is the start of a user trace which consists of multiple messages */
+	EMultiMid = 0x3, /** Indicates this message is one in a series of user trace messages */
+	EMultiEnd = 0x4, /** Indicates this message is the last in a series of user trace messages */
+	/**
+	  @internalTechnology
+	  A debug agent should find the number of core tags from the DFBlock rather than this enumerator.
+	  */
+	ELast = 0x5	
+};
+	
+/**
+ *   Event specific information returned as part of a TEventInfo object 
+ *   when a user trace event occurs.
+ */
+class TUserTraceInfo
+	{
+public:
+	/** The user trace text */
+	TUint8 iUserTraceText[TUserTraceSize];
+	
+	/** User trace text length */
+	TInt iUserTraceLength;
+	
+	/** The context of the message */
+	TUserTraceMessageContext iMessageStatus;
+	};
+	
+	
+/**
+  Structure used to store information about an event. An object of this type
+  is passed as an argument to the RSecuritySvrSession::GetEvent function,
+  and is filled in by the debug driver, and returned to the agent, when a
+  relevant event occurs.
+
+  The debug functionality block contains the size in bytes of the data that
+  the driver will return when a GetEvent call is issued. A debug agent should
+  ensure that this value equals the size of this TEventInfo object to ensure
+  that a compatible debug driver is being used. The value is stored as
+  EApiConstantsTEventInfoSize in the TFunctionalityApiConstants block.
+
+  @see RSecuritySvrSession::GetDebugFunctionality
+  @see RSecuritySvrSession::GetEvent
+  */
+class TEventInfo
+	{
+public:
+
+	/** Constructor sets all elements to default values. */
+	inline TEventInfo() { Reset(); };
+
+	/** Resets all values to default values. */
+	inline void Reset()
+		{
+		iProcessId = 0;
+		iProcessIdValid = EFalse;
+		iThreadId = 0;
+		iThreadIdValid = EFalse;
+		iEventType = (TEventType)NULL;
+		iActionTaken = EActionIgnore;
+		};
+
+public:
+
+	/** The process ID of the process which the event occurred in. */
+	TUint64 				iProcessId;
+	/** The thread ID of the thread which the event occurred in. */
+	TUint64 				iThreadId;
+	/** Has value ETrue if iProcessId is valid, EFalse otherwise. */
+	TUint8					iProcessIdValid;
+	/** Has value ETrue if iThreadId is valid, EFalse otherwise. */
+	TUint8					iThreadIdValid;
+	/** What action was taken by the debug system when it received the event. A TKernelEventAction */
+	TUint8					iActionTaken;
+	TUint8					iSpare;
+
+	/** Indicates the type of the event. This type should be used to determine
+	    the type of the information stored in the union which is part of this class. */
+	TEventType				iEventType;
+	union
+		{
+		/** Information which is specific to the break point event. */
+		TThreadBreakPointInfo iThreadBreakPointInfo;
+		/** Information which is specific to the software exception event. */
+		TThreadSwExceptionInfo iThreadSwExceptionInfo;
+		/** Information which is specific to the hardware exception event. */
+		TThreadHwExceptionInfo iThreadHwExceptionInfo;
+		/** Information which is specific to the thread kill event. */
+		TThreadKillInfo iThreadKillInfo;
+		/** Information which is specific to the library loaded event. */
+		TLibraryLoadedInfo iLibraryLoadedInfo;
+		/** Information which is specific to the library unloaded event. */
+		TLibraryUnloadedInfo iLibraryUnloadedInfo;
+		/** Information which is specific to the user trace event. */
+		TUserTraceInfo iUserTraceInfo;
+		/** Information which is specific to the start thread event. */
+		TStartThreadInfo iStartThreadInfo;
+		/** Information which is specific to the Add Process event. */
+		TAddProcessInfo iAddProcessInfo;
+		/** Information which is specific to the Remove Process event. */
+		TRemoveProcessInfo iRemoveProcessInfo;
+		};
+	};
+
+/**
+  @internalComponent
+  */
+class TProcessInfo
+	{
+	public:
+
+		inline TProcessInfo() { Reset(); }
+
+		inline TProcessInfo(TUint32 aId, TUint32 aCodeAddress, TUint32 aCodeSize, TUint32 aDataAddress)
+				: iId(aId),
+				  iCodeAddress(aCodeAddress),
+				  iCodeSize(aCodeSize),
+				  iDataAddress(aDataAddress) { }
+
+		inline void Reset()
+			{
+			iId = 0;
+			iCodeAddress = 0;
+			iCodeSize = 0;
+			iDataAddress = 0;
+			}
+
+	public:
+
+		TUint32 iId;
+		TUint32 iCodeAddress;
+		TUint32 iCodeSize;
+		TUint32 iDataAddress;
+	};
+
+/* Other functionality may be defined here later */
+
+/**
+Represents a register id value, in the terms of the Symbian ELF format:
+ - bits 0-7 define the class
+ - bits 8-15 define the rd_id
+ - bits 16-31 define the rd_sub_id
+
+Both the core registers (TFunctionalityRegister type) and the coprocessor registers
+follow this identifier scheme.
+*/
+typedef TUint32 TRegisterInfo;
+
+/**
+Enum representing the status flags which could be returned from a register
+access call.
+*/
+enum TRegisterFlag
+	{
+	/**
+	Default value, a register access call will never return this value
+	*/
+	ENotSet = 0,
+	/**
+	Would be returned if the register is supported by the debug driver but the kernel cannot access the register
+	*/
+	EInValid = 1,
+	/**
+	Would be returned if the register could be accessed correctly
+	*/
+	EValid = 2,
+	/**
+	Would be returned if the register is not supported by the debug driver
+	*/
+	ENotSupported = 3,
+	/**
+	Would be returned if a non-4 byte register value was requested
+	*/
+	EBadSize = 4
+	};
+
+/**
+Enum representing the different ARM CPU instruction set architectures.
+*/
+enum TArchitectureMode
+	{
+	/** Represents the ARM CPU architecture. */
+	EArmMode = 1,
+	/** Represents the Thumb CPU architecture. */
+	EThumbMode = 2,
+	/**
+	  Represents the Thumb2 CPU architecture.
+	  @prototype
+	  */
+	EThumb2EEMode = 3
+	};
+
+/**
+  Used as an identifier for breakpoints set by the RSecuritySvrSession::SetBreak function.
+  @see RSecuritySvrSession
+  */
+typedef TInt32 TBreakId;
+
+/**
+  Specifies the type of a code segment.
+  @see TCodeSegListEntry
+  */
+enum TCodeSegType
+	{
+	EUnknownCodeSegType = 0, /**< Signifies an unknown code segment type. */
+	EExeCodeSegType = 1,     /**< Signifies a code segment belonging to an executable. */
+	EDllCodeSegType = 2      /**< Signifies a code segment belonging to a library. */
+	};
+
+/**
+Structure used for extracting data from a descriptor returned by a call to
+RSecuritySvrSession::GetList() when GetList() is called with TListId::ECodeSegs
+as the first argument.
+
+@see RSecuritySvrSession::GetList()
+
+@code
+//buffer is a TDesC8 containing 4-byte aligned TCodeSegListEntry objects
+//create a pointer to the start of the data
+TUint8* ptr = (TUint8*)buffer.Ptr();
+//create a pointer to the end of the data
+const TUint8* ptrEnd = ptr + buffer.Length();
+while(ptr < ptrEnd)
+	{
+	//cast the pointer to be a TCodeSegListEntry object
+	TCodeSegListEntry& entry = *(TCodeSegListEntry*)ptr;
+	//use the TCodeSegListEntry pointer, i.e.
+	TUint16 nameLength = entry.iNameLength;
+	TPtr name(&(entry.iName[0]), nameLength, nameLength);
+	// move ptr on to point to the next TCodeSegListEntry object
+	ptr += Align4(entry.GetSize());
+	}
+@endcode
+*/
+class TCodeSegListEntry
+	{
+public:
+	TInt GetSize() const;
+public:
+	/**
+	  Address of the start of the code segment.
+	  */
+	TUint32 iCodeBase;
+	/**
+	  Size of the code segment.
+	  */
+	TUint32 iCodeSize;
+	/**
+	  Size of the const data segment
+	  */
+	TUint32 iConstDataSize;
+	/**
+	  Address of the initialised data
+	  */
+	TUint32 iInitialisedDataBase;
+	/**
+	  Size of the initialised data
+	  */
+	TUint32 iInitialisedDataSize;
+	/**
+	  Size of the uninitialised data
+	  */
+	TUint32 iUninitialisedDataSize;
+	/**
+	  Boolean indicating whether the code segment is execute in place
+	  */
+	TBool iIsXip;
+	/**
+	  Indicates whether the code segment is from an executable or a dll, or neither
+	  */
+	TCodeSegType iCodeSegType;
+	/** Uid3 of this segment. */
+	TUint32 iUid3;
+	/** Currently unused element. May be used in future to aid maintaining compatibility. */
+	TUint32 iSpare2;
+	/**
+	  Length of the code segment's name
+	  */
+	TUint16 iNameLength;
+	/**
+	  First two bytes of the code segment's name, the name should be considered to
+	  extend past the end of the TCodeSegListEntry structure to a length
+	  corresponding to iNameLength
+	  */
+	TUint16 iName[1];
+	};
+
+/**
+Returns the size of the TCodeSegListEntry, including the file name length
+
+@return the size, in bytes, of the TCodeSegListEntry and the code segment's
+file name
+*/
+inline TInt TCodeSegListEntry::GetSize() const
+	{
+	return sizeof(TCodeSegListEntry) - sizeof(iName) + (2 * iNameLength);
+	}
+
+/**
+Structure used for extracting data from a descriptor returned by a call to
+RSecuritySvrSession::GetList() when GetList() is called with TListId::EXipLibraries
+as the first argument.
+
+@see RSecuritySvrSession::GetList()
+
+@code
+//buffer is a TDesC8 containing 4-byte aligned TXipLibraryListEntry objects
+//create a pointer to the start of the data
+TUint8* ptr = (TUint8*)buffer.Ptr();
+//create a pointer to the end of the data
+const TUint8* ptrEnd = ptr + buffer.Length();
+while(ptr < ptrEnd)
+	{
+	//cast the pointer to be a TXipLibraryListEntry object
+	TXipLibraryListEntry& entry = *(TXipLibraryListEntry*)ptr;
+	//use the TXipLibraryListEntry pointer, i.e.
+	TUint16 nameLength = entry.iNameLength;
+	TPtr name(&(entry.iName[0]), nameLength, nameLength);
+	// move ptr on to point to the next TXipLibraryListEntry object
+	ptr += Align4(entry.GetSize());
+	}
+@endcode
+*/
+class TXipLibraryListEntry
+	{
+public:
+	TInt GetSize() const;
+public:
+	/**
+	  Address of the start of the library's code segment.
+	  */
+	TUint32 iCodeBase;
+	/**
+	  Size of the code segment.
+	  */
+	TUint32 iCodeSize;
+	/**
+	  Size of the const data segment
+	  */
+	TUint32 iConstDataSize;
+	/**
+	  Address of the initialised data
+	  */
+	TUint32 iInitialisedDataBase;
+	/**
+	  Size of the initialised data
+	  */
+	TUint32 iInitialisedDataSize;
+	/**
+	  Size of the uninitialised data
+	  */
+	TUint32 iUninitialisedDataSize;
+	/** Currently unused element. May be used in future to aid maintaining compatibility. */
+	TUint32 iSpare1;
+	/** Currently unused element. May be used in future to aid maintaining compatibility. */
+	TUint32 iSpare2;
+	/**
+	  Length of the library's name
+	  */
+	TUint16 iNameLength;
+	/**
+	  First two bytes of the code segment's name, the name should be considered to
+	  extend past the end of the TXipLibraryListEntry structure to a length
+	  corresponding to iNameLength
+	  */
+	TUint16 iName[1];
+	};
+
+/**
+Returns the size of the TXipLibraryListEntry, including the file name length
+
+@return the size, in bytes, of the TXipLibraryListEntry and the library's
+file name
+*/
+inline TInt TXipLibraryListEntry::GetSize() const
+	{
+	return sizeof(TXipLibraryListEntry) - sizeof(iName) + (2 * iNameLength);
+	}
+
+/**
+Structure used for extracting data from a descriptor returned by a call to
+RSecuritySvrSession::GetList() when GetList() is called with TListId::EExecutables
+as the first argument.
+
+@see RSecuritySvrSession::GetList()
+
+@code
+//buffer is a TDesC8 containing 4-byte aligned TExecutablesListEntry objects
+//create a pointer to the start of the data
+TUint8* ptr = (TUint8*)buffer.Ptr();
+//create a pointer to the end of the data
+const TUint8* ptrEnd = ptr + buffer.Length();
+while(ptr < ptrEnd)
+	{
+	//cast the pointer to be a TExecutablesListEntry object
+	TExecutablesListEntry& entry = *(TExecutablesListEntry*)ptr;
+	//use the TExecutablesListEntry pointer, i.e.
+	TUint16 nameLength = entry.iNameLength;
+	TPtr name(&(entry.iName[0]), nameLength, nameLength);
+	// move ptr on to point to the next TExecutablesListEntry object
+	ptr += Align4(entry.GetSize());
+	}
+@endcode
+*/
+class TExecutablesListEntry
+	{
+public:
+	TInt GetSize() const;
+public:
+	/**
+	  Indicates whether an agent has registered to actively debug the executable,
+	  a non-zero value indicates that an agent has attached.
+	  */
+	TUint8 iIsActivelyDebugged;
+	/**
+	  Indicates whether any agents have registered to passively debug the executable,
+	  a non-zero value indicates that at least one agent is attached passively
+	  */
+	TUint8 iIsPassivelyDebugged;
+	/** Currently unused element. May be used in future to aid maintaining compatibility. */
+	TUint32 iSpare1;
+	/** Currently unused element. May be used in future to aid maintaining compatibility. */
+	TUint32 iSpare2;
+	/**
+	  Length of the executable's name
+	  */
+	TUint16 iNameLength;
+	/**
+	  First two bytes of the executable's name, the name should be considered to
+	  extend past the end of the TExecutablesListEntry structure to a length
+	  corresponding to iNameLength
+	  */
+	TUint16 iName[1];
+	};
+
+/**
+Returns the size of the TExecutablesListEntry, including the file name length
+
+@return the size, in bytes, of the TExecutablesListEntry and the executable's
+file name
+*/
+inline TInt TExecutablesListEntry::GetSize() const
+	{
+	return sizeof(TExecutablesListEntry) - sizeof(iName) + (2*iNameLength);
+	}
+
+/**
+Structure used for extracting data from a descriptor returned by a call to
+RSecuritySvrSession::GetList() when GetList() is called with TListId::EProcesses
+as the first argument.
+
+@see RSecuritySvrSession::GetList()
+
+@code
+//buffer is a TDesC8 containing 4-byte aligned TProcessListEntry objects
+//create a pointer to the start of the data
+TUint8* ptr = (TUint8*)buffer.Ptr();
+//create a pointer to the end of the data
+const TUint8* ptrEnd = ptr + buffer.Length();
+while(ptr < ptrEnd)
+	{
+	//cast the pointer to be a TProcessListEntry object
+	TProcessListEntry& entry = *(TProcessListEntry*)ptr;
+	//use the TProcessListEntry pointer, i.e.
+	TUint16 fileNameLength = entry.iFileNameLength;
+	TPtr name(&(entry.iNames[0]), fileNameLength, fileNameLength);
+	// move ptr on to point to the next TProcessListEntry object
+	ptr += Align4(entry.GetSize());
+	}
+@endcode
+*/
+class TProcessListEntry
+	{
+	public:
+		TInt GetSize() const;
+
+	public:
+		/** Process ID */
+		TUint64 iProcessId;
+
+		/** The Uid3 of the process */
+		TUint32 iUid3;
+
+		/** 
+		 * Process Attributes
+		 * @see DProcess::TProcessAttributes
+		 */
+		TInt iAttributes;
+
+		/**
+		 * Length of fully qualified file name of the process in bytes. Note that this
+		 * entry may be 0 if the process is in the process of shutting down.
+		 */
+		TUint16 iFileNameLength;
+
+		/**
+		 * Length of current dynamic name of the process in bytes
+		 */
+		TUint16 iDynamicNameLength;
+
+		/**
+		 * First two bytes of the process' file name, the name should be considered to
+		 * extend past the end of the TProcessListEntry structure to a length
+		 * corresponding to iFileNameLength. Directly after the data corresponding to the
+		 * file name, the dynamic name is stored with a length of iDynamicNameLength characters.
+		 * Note that these names are not null terminated and are concatenated directly after each other.
+		 * 
+		 * @code
+		 * TProcessListEntry& entry; // entry is a reference to a TProcessListEntry
+		 *
+		 * //get the file name..
+		 * TPtr fileName(&(entry.iNames[0]), iFileNameLength, iFileNameLength);
+		 *
+		 * //get the dynamic name length..
+		 * TPtr dynamicName(&(entry.iNames[0]) + iFileNameLength, iDynamicNameLength, iDynamicNameLength);
+		 * @endcode
+		 */
+		TUint16 iNames[1];
+	};
+
+/**
+Returns the size of the TProcessListEntry, including the file name length and the
+dynamic name length
+
+@return the size, in bytes, of the TProcessListEntry and the executable's
+file name file name and dynamic name
+*/
+inline TInt TProcessListEntry::GetSize() const
+	{
+	return sizeof(TProcessListEntry) - sizeof(iNames) + (2 * (iFileNameLength + iDynamicNameLength));
+	}
+
+/**
+Structure used for extracting data from a descriptor returned by a call to
+RSecuritySvrSession::GetList() when GetList() is called with TListId::EThreads
+as the first argument.
+
+@see RSecuritySvrSession::GetList()
+
+@code
+//buffer is a TDesC8 containing 4-byte aligned TThreadListEntry objects
+//create a pointer to the start of the data
+TUint8* ptr = (TUint8*)buffer.Ptr();
+//create a pointer to the end of the data
+const TUint8* ptrEnd = ptr + buffer.Length();
+while(ptr < ptrEnd)
+	{
+	//cast the pointer to be a TThreadListEntry object
+	TThreadListEntry& entry = *(TThreadListEntry*)ptr;
+	//use the TThreadListEntry pointer, i.e.
+	TUint16 nameLength = entry.iNameLength;
+	TPtr name(&(entry.iName[0]), nameLength, nameLength);
+	// move ptr on to point to the next TThreadListEntry object
+	ptr += Align4(entry.GetSize());
+	}
+@endcode
+*/
+class TThreadListEntry
+	{
+public:
+	TInt GetSize() const;
+public:
+	/**
+	  Thread ID
+	  */
+	TUint64 iThreadId;
+	/**
+	  Process ID
+	  */
+	TUint64 iProcessId;
+	/**
+	  Address of the base of the supervisor stack
+	  */
+	TUint32 iSupervisorStackBase;
+	/**
+	  Size of the supervisor stack
+	  */
+	TUint32 iSupervisorStackSize;
+	/**
+	  Non-zero if iSupervisorStackBase has been set correctly
+	  */
+	TUint8 iSupervisorStackBaseValid;
+	/**
+	  Non-zero if iSupervisorStackSize has been set correctly
+	  */
+	TUint8 iSupervisorStackSizeValid;
+	/**
+	  Address of the thread's supervisor stack pointer
+	  */
+	TUint32 iSupervisorStackPtr;
+	/**
+	  Indicator of whether the value returned as iSupervisorStackPtr is valid.
+	  It is necessary, but not necessarily sufficient, that the thread be suspended
+	  for a valid value to be returned. This may be removed from the final API and
+	  the value would be extracted instead via the ReadRegisters type calls.
+	  */
+	TRegisterFlag iSupervisorStackPtrValid;
+	/** Currently unused element. May be used in future to aid maintaining compatibility. */
+	TUint32 iSpare1;
+	/** Currently unused element. May be used in future to aid maintaining compatibility. */
+	TUint32 iSpare2;
+	/**
+	  The length of the thread's name
+	  */
+	TUint16 iNameLength;
+	/**
+	  First two bytes of the thread's name, the name should be considered to
+	  extend past the end of the TThreadListEntry structure to a length
+	  corresponding to iNameLength
+	  */
+	TUint16 iName[1];
+	};
+
+/**
+Returns the size of the TThreadListEntry, including the name length
+
+@return the size, in bytes, of the TExecutablesListEntry and the thread's name
+*/
+inline TInt TThreadListEntry::GetSize() const
+	{
+	return sizeof(TThreadListEntry) - sizeof(iName) + (2 * iNameLength);
+	}
+
+/**
+Denotes which list type to return from a RSecuritySvrSession::GetList() call
+
+@see RSecuritySvrSession::GetList()
+*/
+enum TListId
+	{
+	/**
+	Indicates that the GetList() call should return a list of the processes in
+	the system. The returned buffer will contain an array of 4-byte aligned
+	TProcessListEntry objects.
+
+	@see TProcessListEntry
+	*/
+	EProcesses = 0,
+	/**
+	Indicates that the GetList() call should return a list of the threads in
+	the system. The returned buffer will contain an array of 4-byte aligned
+	TThreadListEntry objects.
+
+	@see TThreadListEntry
+	*/
+	EThreads = 1,
+	/**
+	Indicates that the GetList() call should return a list of the code segments in
+	the system. The returned buffer will contain an array of 4-byte aligned
+	TCodeSegListEntry objects.
+
+	@see TCodeSegListEntry
+	*/
+	ECodeSegs = 2,
+	/**
+	Indicates that the GetList() call should return a list of the XIP libraries in
+	the system. The returned buffer will contain an array of 4-byte aligned
+	EXipLibraries objects.
+
+	@see EXipLibraries
+	*/
+	EXipLibraries = 3,
+	/**
+	Indicates that the GetList() call should return a list of the executables in
+	the system. The returned buffer will contain an array of 4-byte aligned
+	EExecutables objects.
+
+	@see EExecutables
+	*/
+	EExecutables = 4,
+	/**
+	Indicates that the GetList() call should return a list of the logical devices in the system.
+	*/
+	ELogicalDevices = 5,
+	/**
+	Indicates that the GetList() call should return a list of the mutexes in the system.
+	*/
+	EMutexes = 6,
+	/**
+	Indicates that the GetList() call should return a list of the servers in the system.
+	*/
+	EServers = 7,
+	/**
+	Indicates that the GetList() call should return a list of the sessions in the system.
+	*/
+	ESessions = 8,
+	/**
+	Indicates that the GetList() call should return a list of the semaphores in the system.
+	*/
+	ESemaphores = 9,
+	/**
+	Indicates that the GetList() call should return a list of the chunks in the system.
+	*/
+	EChunks = 10,
+
+	/**
+	Provides a complete list of all the breakpoints in the system and their
+	current state.
+
+	@see EBreakpoints
+	*/
+	EBreakpoints = 11,
+
+	/** 
+	The following are for the possible use of kernel-side debug and SMP breakpoint
+	manipulation.
+	*/
+	ESetBreak = 12,
+	ERemoveBreak = 13,
+	EModifyBreak = 14,
+	
+	/**
+	 * Provides static information of the system
+	 */
+	EStaticInfo = 15,
+
+	/** Last listing enum. */
+	EListLast
+	};
+
+/**
+  Bit field values denoting the scope of a listing.
+
+  In the debug functionality block, the TTag::iValue element which is returned for a listing tag
+  should be considered as a union of the supported values from this enumeration for that listing.
+  */
+enum TListScope
+	{
+	EScopeNone = 0x0,             /**< Corresponds to no scope for a listing. equivalent to not supported */
+	EScopeGlobal= 0x1,            /**< Corresponds to a global scope for a listing. */
+	EScopeProcessSpecific = 0x2,  /**< Corresponds to a process specific scope for a listing. */
+	EScopeThreadSpecific = 0x4    /**< Corresponds to a thread specific scope for a listing. */
+	};
+
+/**
+@internalComponent
+
+Interface constructor for passing IPC data for the GetList call.
+*/
+class TListDetails
+	{
+public:
+	TListDetails(const TListId aListId, const TListScope aListScope, TUint64 aTargetId=0)
+		: iListId(aListId),
+		  iListScope(aListScope),
+		  iTargetId(aTargetId) {}
+public:
+	TListId iListId;
+	TListScope iListScope;
+	TUint64 iTargetId;
+	};
+
+/** Debug Security Server Secure ID */
+const TUid KUidDebugSecurityServer = { 0x102834E2 };
+
+} // end of Debug namespace declaration
+
+// the remaining functionality in this file is intended for use on user side only
+#ifndef __KERNEL_MODE__
+
+#include <e32std.h>
+
+// API definition for Debug namespace appears elsewhere in this file.
+namespace Debug {
+
+/** The name of the Debug Security Server. */
+_LIT(KSecurityServerName,"DebugSecurityServer");
+
+/** Wildcard used for attach all calls */
+_LIT(KStar, "*");
+
+// A version must be specified when creating a session with the server
+/** The Debug Security Server's major version number. */
+const TUint KDebugServMajorVersionNumber=2;
+/** The Debug Security Server's minor version number. */
+const TUint KDebugServMinorVersionNumber=5;
+/** The Debug Security Server's patch version number. */
+const TUint KDebugServPatchVersionNumber=0;
+
+/**
+Denotes how memory should be accessed
+*/
+enum TAccess
+	{
+	EAccess8 = 1,	/**< Currently unsupported, signifies 8 bit access. */
+	EAccess16 = 2,	/**< Currently unsupported, signifies 16 bit access. */
+	EAccess32 = 4	/**< Signifies 32 bit access. */
+	};
+
+/**
+Denotes how data should be interpreted
+*/
+enum TEndianess
+	{
+	EEndLE8 = 0,	/**< Signifies 8 bit little-endian. */
+	EEndBE8 = 1,	/**< Currently unsupported, signifies 8 bit big-endian. */
+	EEndBE32 = 2	/**< Currently unsupported, signifies 32 bit big-endian. */
+	};
+
+/**
+Structure used to store information about a memory operation
+
+@internalComponent
+*/
+class TMemoryInfo
+	{
+public:
+
+	TMemoryInfo(TUint32 aAddress=0, TUint32 aLength=0, TAccess aAccess=EAccess32, TEndianess aEndianess=EEndLE8)
+		: iAddress(aAddress),
+		  iSize(aLength),
+		  iAccess(aAccess),
+		  iEndianess(aEndianess)
+		{}
+
+public:
+
+	/**
+	Address to start reading/writing memory
+	*/
+	TUint32 iAddress;
+	/**
+	Number of bytes of memory to read/write
+	*/
+	TUint32	iSize;
+	/**
+	Access size for read/write
+	@see TAccess
+	*/
+	TAccess iAccess;
+	/**
+	Endianess to interpret data as
+	@see TEndianess
+	*/
+	TEndianess iEndianess;
+	};
+
+/**
+@internalComponent
+*/
+class TBreakInfo
+	{
+public:
+	TUint32 iAddress;
+	TArchitectureMode iArchitectureMode;
+	};
+
+/**
+@internalComponent
+
+Function codes (opcodes) used in message passing between client and server
+in this header file and what arguments should be passed with each of these
+*/
+enum TDebugServRqst
+	{
+	EDebugServOpen = 1,
+	EDebugServClose = 2,
+	EDebugServSuspendThread = 3,
+	EDebugServResumeThread = 4,
+	EDebugServReadMemory = 5,
+	EDebugServWriteMemory = 6,
+	EDebugServSetBreak = 7,
+	EDebugServClearBreak = 8,
+	EDebugServModifyBreak = 9,
+	EDebugServGetEvent = 10,
+	EDebugServCancelGetEvent = 11,
+	EDebugServAttachExecutable = 12,
+	EDebugServDetachExecutable = 13,
+	EDebugServGetDebugFunctionalityBufSize = 14,
+	EDebugServGetDebugFunctionality = 15,
+	EDebugServReadRegisters = 16,
+	EDebugServWriteRegisters = 17,
+	EDebugServSetEventAction = 18,
+	EDebugServBreakInfo = 19,
+	EDebugServGetList = 20,
+	EDebugServStep = 21,
+	EDebugServSetProcessBreak = 22,
+	EDebugServProcessBreakInfo = 23,
+	EDebugServKillProcess = 24,
+	EDebugServModifyProcessBreak = 25,
+	EDebugServReadCrashFlash = 26,
+	EDebugServWriteCrashFlash = 27,
+	EDebugServEraseCrashFlash = 28,
+	EDebugServEraseEntireCrashFlash = 29,
+	EDebugServAttachAll = 30,
+	EDebugServDetachAll = 31,
+	};
+
+/**
+Client side API to debug security server (DSS). Interaction with the DSS should
+be conducted through this class only.
+*/
+class RSecuritySvrSession : public RSessionBase
+	{
+public:
+	RSecuritySvrSession();
+	TVersion Version() const;
+
+	TInt AttachExecutable(const TDesC& aProcessName, TBool aPassive);
+	TInt DetachExecutable(const TDesC& aProcessName);
+
+	TInt GetDebugFunctionalityBufSize(TUint32* aBufSize);
+	TInt GetDebugFunctionality(TDes8& aBuffer);
+
+	TInt SuspendThread(const TThreadId aThreadId);
+	TInt ResumeThread(const TThreadId aThreadId);
+
+	TInt ReadMemory(const TThreadId aThreadId, const TUint32 aAddress, const TUint32 aLength, TDes8 &aData, const TAccess aAccessSize, const TEndianess aEndianess);
+	TInt WriteMemory(const TThreadId aThreadId, const TUint32 aAddress, const TUint32 aLength, const TDesC8 &aData, const TAccess aAccessSize, const TEndianess aEndianess);
+
+	TInt ReadRegisters(const TThreadId aThreadId, const TDesC8& aRegisterIds, TDes8& aRegisterValues, TDes8& aRegisterFlags);
+	TInt WriteRegisters(const TThreadId aThreadId, const TDesC8& aRegisterIds, const TDesC8& aRegisterValues, TDes8& aRegisterFlags);
+
+	void GetEvent(const TDesC& aExecutableName, TRequestStatus &aStatus, TDes8& aEventInfo);
+	TInt CancelGetEvent(const TDesC& aExecutableName);
+	
+	TInt SetEventAction(const TDesC& aExecutableName, TEventType aEvent, TKernelEventAction aEventAction);
+
+	TInt SetBreak( TBreakId &aId, const TThreadId aThreadId, const TUint32 aAddress, const TArchitectureMode aArchitectureMode);
+	TInt ClearBreak(const TBreakId aBreakId);
+	TInt ModifyBreak(const TBreakId aBreakId, const TThreadId aThreadId, const TUint32 aAddress, const TArchitectureMode aArchitectureMode);
+	TInt BreakInfo(const TBreakId aBreakId, TThreadId& aThreadId, TUint32& aAddress, TArchitectureMode& aMode);
+	TInt SetProcessBreak( TBreakId &aId, const TProcessId aProcessId, const TUint32 aAddress, const TArchitectureMode aArchitectureMode);
+	TInt ProcessBreakInfo(const TBreakId aBreakId, TProcessId& aProcessId, TUint32& aAddress, TArchitectureMode& aMode);
+	TInt ModifyProcessBreak(const TBreakId aBreakId, const TProcessId aProcessId, const TUint32 aAddress, const TArchitectureMode aArchitectureMode);
+
+	TInt GetList(const TListId aListId, TDes8& aListData, TUint32& aDataSize);
+	TInt GetList(const TThreadId aThreadId, const TListId aListId, TDes8& aListData, TUint32& aDataSize);
+	TInt GetList(const TProcessId aProcessId, const TListId aListId, TDes8& aListData, TUint32& aDataSize);
+	TInt Step(const TThreadId aThreadId, TUint32 aNumSteps);
+	TInt KillProcess(const TProcessId aProcessId, const TInt aReason);
+	TInt ReadCrashLog(const TUint32 aPos, TDes8& aData, const TUint32 aDataSize);	
+	TInt WriteCrashConfig(const TUint32 aPos, const TDesC8& aBuffer, TUint32& aSize);
+	TInt EraseCrashLog(const TUint32 aPos, const TUint32 aBlockNumber);
+	TInt EraseCrashFlashPartition();
+
+	TInt Connect(const TVersion aVersion);
+
+	// Added in version 2.5
+    TInt AttachAll();
+    TInt DetachAll();	
+    void GetEvent(TRequestStatus &aStatus, TDes8& aEventInfo);
+    TInt CancelGetEvent();
+    TInt SetEventAction(TEventType aEvent, TKernelEventAction aEventAction);
+
+private:
+	TInt StartServer(void);
+	};
+
+/**
+Server session constructor
+*/
+inline RSecuritySvrSession::RSecuritySvrSession()
+	{
+	}
+
+/**
+Called by a client to create a session with the DSS. This method starts the
+DSS if it is not running, or connects to it if it already exists.
+
+@param aVersion version of the DSS to connect to
+
+@return KErrNone if a connection was successfully created, or one of the other
+system wide error codes
+*/
+inline TInt RSecuritySvrSession::Connect(const TVersion aVersion)
+	{
+	// Default asynch outstanding message slots for the server. Not that these are 
+	// allocated from a system-wide pool of 255, so have to be careful with resources.
+	const TUint KDefaultMessageSlots = 8;
+	
+	TInt retry=2;
+	for (;;)
+		{
+		TInt r=CreateSession(KSecurityServerName, aVersion, KDefaultMessageSlots);
+		if (r!=KErrNotFound && r!=KErrServerTerminated)
+			{
+			return r;
+			}
+		if (--retry==0)
+			{
+			return r;
+			}
+		r=StartServer();
+		if (r!=KErrNone && r!=KErrAlreadyExists)
+			{
+			return r;
+			}
+		}
+	}
+
+/**
+  Start the server
+
+  @return KErrNone on success, or one of the other system wide error codes
+  */
+inline TInt RSecuritySvrSession::StartServer()
+	{
+	// constants for the server
+	_LIT(KSecurityServerProcessName, "rm_debug_svr");
+	const TUidType serverUid(KNullUid, KNullUid, KUidDebugSecurityServer);
+
+	RProcess server;
+	TInt err = server.Create(KSecurityServerProcessName, KNullDesC, serverUid);
+
+	if(KErrNone != err)
+		{
+		return err;
+		}
+
+	// Synchronise with the process to make sure it hasn't died straight away
+	TRequestStatus stat;
+	server.Rendezvous(stat);
+	if (stat != KRequestPending)
+		{
+		// logon failed - server is not yet running, so cannot have terminated
+		server.Kill(0);             // Abort startup
+		}
+	else
+		{
+		// logon OK - start the server
+		server.Resume();
+		}
+
+	// Wait to synchronise with server - if it dies in the meantime, it
+	// also gets completed
+	User::WaitForRequest(stat);
+
+	// We can't use the 'exit reason' if the server panicked as this
+	// is the panic 'reason' and may be '0' which cannot be distinguished
+	// from KErrNone
+	err = (server.ExitType()==EExitPanic) ? KErrGeneral : stat.Int();
+	server.Close();
+	return err;
+	}
+
+/**
+Get version of RSecuritySvrSession
+
+@return a TVersion object specifying the version
+*/
+inline TVersion RSecuritySvrSession::Version(void) const
+	{
+	return (TVersion(KDebugServMajorVersionNumber, KDebugServMinorVersionNumber, KDebugServPatchVersionNumber));
+	}
+
+/**
+Suspends execution of the specified thread.
+
+@param aThreadId thread ID of the thread to suspend
+
+@return KErrNone if there were no problems, KErrPermissionDenied if security 
+        check fails or KErrArgument if the thread does not exist
+*/
+inline TInt RSecuritySvrSession::SuspendThread(const TThreadId aThreadId)
+	{
+	TPckgBuf<TThreadId> threadIdPckg(aThreadId);
+	TIpcArgs args(&threadIdPckg);
+
+	return SendReceive(EDebugServSuspendThread, args);
+	}
+
+/**
+Resumes execution of the specified thread.
+
+@param aThreadId thread ID of the thread to resume
+
+@return KErrNone if there were no problems, KErrPermissionDenied if security 
+        check fails or KErrArgument if the thread does not exist
+*/
+inline TInt RSecuritySvrSession::ResumeThread(const TThreadId aThreadId)
+	{
+	TPckgBuf<TThreadId> threadIdPckg(aThreadId);
+	TIpcArgs args(&threadIdPckg);
+
+	return SendReceive(EDebugServResumeThread, args);
+	}
+
+/**
+Purpose:
+Set a thread-specific breakpoint in an attached process. 
+
+@pre Debug Agent must be connected to the debug security server
+@pre Debug Agent must be attached to a process.
+
+@param aThreadId The thread id to which the breakpoint will apply.
+@param aAddress The virtual memory address at which to place the breakpoint.
+@param aArchitectureMode The kind of breakpoint which is to be set (e.g. ARM/Thumb/Thumb2EE)
+@param aBreakId The address to which the assigned breakpoint ID will be written by this function
+@return Any error which may be returned by RSessionBase::SendReceive()
+*/
+inline TInt RSecuritySvrSession::SetBreak( TBreakId &aBreakId,const TThreadId aThreadId, const TUint32 aAddress, const TArchitectureMode aArchitectureMode)
+	{
+	TPtr8 breakIdPtr((TUint8*)&aBreakId, sizeof(aBreakId));
+
+	TPckgBuf<TThreadId> threadIdPckg(aThreadId);
+
+	TBreakInfo breakInfo;
+	breakInfo.iAddress = aAddress;
+	breakInfo.iArchitectureMode = aArchitectureMode;
+	TPckgBuf<TBreakInfo> breakInfoPckg(breakInfo);
+
+	//call driver to attempt to set break
+	TIpcArgs args(&threadIdPckg, &breakInfoPckg, &breakIdPtr);
+	return SendReceive(EDebugServSetBreak, args);
+	}
+
+/**
+Purpose:
+Clears a previously set thread-specific or process-specific breakpoint.
+
+@pre Debug Agent must be connected to the debug security server
+@pre Debug Agent must be attached to a process.
+
+@param aBreakId The TBreakId returned by a prior SetBreak call. Must have been set by the same Debug Agent.
+@return Any error which may be returned by RSessionBase::SendReceive()
+*/
+inline TInt RSecuritySvrSession::ClearBreak(const TBreakId aBreakId)
+	{
+	TIpcArgs args(aBreakId);
+	return SendReceive(EDebugServClearBreak, args);
+	}
+
+/**
+Purpose:
+Modifies the properties of a previously set breakpoint.
+
+@pre Debug Agent must be connected to the debug security server
+@pre Debug Agent must be attached to a process.
+
+@param aBreakId the TBreakId returned by a prior SetBreak() call. Must have been set by the same Debug Agent.
+@param aThreadId the thread id of the thread to move the breakpoint to
+@param aAddress the virtual memory address at which to place the breakpoint.
+@param aArchitectureMode the kind of breakpoint which is to be set (e.g. ARM/Thumb/Thumb2EE)
+@return Any error which may be returned by RSessionBase::SendReceive()
+*/
+inline TInt RSecuritySvrSession::ModifyBreak(const TBreakId aBreakId, const TThreadId aThreadId, const TUint32 aAddress, const TArchitectureMode aArchitectureMode)
+
+	{
+	TPckgBuf<TThreadId> threadIdPckg(aThreadId);
+	TIpcArgs args(aBreakId,&threadIdPckg,aAddress,aArchitectureMode);
+	return SendReceive(EDebugServModifyBreak, args);
+	}
+
+/**
+Purpose:
+Modifies the properties of a previously set process breakpoint.
+
+@pre Debug Agent must be connected to the debug security server
+@pre Debug Agent must be attached to a process.
+
+@param aBreakId the TBreakId returned by a prior SetBreak() call. Must have been set by the same Debug Agent.
+@param aProcessId the process id of the process to move the breakpoint to
+@param aAddress the virtual memory address at which to place the breakpoint.
+@param aArchitectureMode the kind of breakpoint which is to be set (e.g. ARM/Thumb/Thumb2EE)
+@return Any error which may be returned by RSessionBase::SendReceive()
+*/
+inline TInt RSecuritySvrSession::ModifyProcessBreak(const TBreakId aBreakId, const TProcessId aProcessId, const TUint32 aAddress, const TArchitectureMode aArchitectureMode)
+
+	{
+	TPckgBuf<TProcessId> processIdPckg(aProcessId);
+	TIpcArgs args(aBreakId,&processIdPckg,aAddress,aArchitectureMode);
+	return SendReceive(EDebugServModifyProcessBreak, args);
+	}
+
+/**
+Purpose:
+Returns the properties associated with a given TBreakId. The supplied break id must previously have been allocated
+to the debug agent by a SetBreak() call.
+
+@pre Debug Agent must be connected to the debug security server
+@pre Debug Agent must be attached to a process.
+@pre The aBreakId must have been previously returned by a SetBreak() call and not subsequently cleared by ClearBreak().
+
+@param aBreakId the TBreakId returned by a prior SetBreak() call. Must have been set by the same Debug Agent.
+@param aAddress on return contains the virtual memory address of the breakpoint
+@param aThreadId on return contains the thread id of the thread that the breakpoint is set in
+@param aMode on return contains the type of this breakpoint (e.g. ARM/Thumb/Thumb2EE)
+@return Any error which may be returned by RSessionBase::SendReceive()
+*/
+inline TInt RSecuritySvrSession::BreakInfo(const TBreakId aBreakId, TThreadId& aThreadId, TUint32& aAddress, TArchitectureMode& aMode)
+	{
+	// temporary descriptors
+	TPtr8 threadId((TUint8*)&aThreadId,0,sizeof(TThreadId));
+	TPtr8 address((TUint8*)&aAddress,0,sizeof(TUint32));
+	TPtr8 mode((TUint8*)&aMode,0,sizeof(TArchitectureMode));
+
+	TIpcArgs args(aBreakId,&threadId,&address,&mode);
+	return SendReceive(EDebugServBreakInfo, args);
+	}
+
+/**
+Purpose:
+Set a process-specific breakpoint in an attached process. 
+
+@pre Debug Agent must be connected to the debug security server
+@pre Debug Agent must be attached to a process.
+
+@param aProcessId The process id to which the breakpoint will apply.
+@param aAddress The virtual memory address at which to place the breakpoint.
+@param aArchitectureMode The kind of breakpoint which is to be set (e.g. ARM/Thumb/Thumb2EE)
+@param aBreakId The address to which the assigned breakpoint ID will be written by this function
+@return Any error which may be returned by RSessionBase::SendReceive()
+*/
+inline TInt RSecuritySvrSession::SetProcessBreak( TBreakId &aBreakId, const TProcessId aProcessId, const TUint32 aAddress, const TArchitectureMode aArchitectureMode)
+	{
+	TPtr8 breakIdPtr((TUint8*)&aBreakId, sizeof(aBreakId));
+
+	TPckgBuf<TProcessId> threadIdPckg(aProcessId);
+
+	TBreakInfo breakInfo;
+	breakInfo.iAddress = aAddress;
+	breakInfo.iArchitectureMode = aArchitectureMode;
+	TPckgBuf<TBreakInfo> breakInfoPckg(breakInfo);
+
+	//call driver to attempt to set break
+	TIpcArgs args(&threadIdPckg, &breakInfoPckg, &breakIdPtr);
+	return SendReceive(EDebugServSetProcessBreak, args);
+	}
+
+/**
+Purpose:
+Returns the properties associated with a given TBreakId. The supplied break id must previously have been allocated
+to the debug agent by a SetProcessBreak() call.
+
+@pre Debug Agent must be connected to the debug security server
+@pre Debug Agent must be attached to a process.
+@pre The aBreakId must have been previously returned by a SetProcessBreak() call and not subsequently cleared by ClearBreak().
+
+@param aBreakId the TBreakId returned by a prior SetBreak() call. Must have been set by the same Debug Agent.
+@param aAddress on return contains the virtual memory address of the breakpoint
+@param aThreadId on return contains the thread id of the thread that the breakpoint is set in
+@param aMode on return contains the type of this breakpoint (e.g. ARM/Thumb/Thumb2EE)
+@return Any error which may be returned by RSessionBase::SendReceive()
+*/
+inline TInt RSecuritySvrSession::ProcessBreakInfo(const TBreakId aBreakId, TProcessId& aProcessId, TUint32& aAddress, TArchitectureMode& aMode)
+	{
+	// temporary descriptors
+	TPtr8 processId((TUint8*)&aProcessId,0,sizeof(TProcessId));
+	TPtr8 address((TUint8*)&aAddress,0,sizeof(TUint32));
+	TPtr8 mode((TUint8*)&aMode,0,sizeof(TArchitectureMode));
+
+	TIpcArgs args(aBreakId,&processId,&address,&mode);
+	return SendReceive(EDebugServProcessBreakInfo, args);
+	}
+
+/**
+Purpose:
+Wait for an event to occur to the target executable being debugged. When an event
+occurs, the TRequestStatus is completed.
+
+@pre Debug Agent must be connected to the debug security server
+@pre Debug Agent must be attached to a process.
+
+Note 1: Events are reported on a per-executable basis, not per-thread.
+
+Note 2: All the parameters must remain in scope until either CancelGetEvent is called, or
+until the request is completed. In practice, this generally
+means these parameters should not be based on the stack, as they may go out of
+scope before the call completes.
+
+Note 3: Errors are signalled by completing aStatus
+
+@param aExecutableName The name of any executable to which the Debug Agent is attached.
+@param aStatus Debug Agent request status variable.
+@param aEventInfo Descriptor containing a TEventInfo object. 
+
+*/
+inline void RSecuritySvrSession::GetEvent(const TDesC& aExecutableName, TRequestStatus &aStatus, TDes8& aEventInfo)
+	{
+	TIpcArgs args(&aExecutableName, &aEventInfo);
+
+	SendReceive(EDebugServGetEvent, args, aStatus );
+
+	}
+ 
+/**
+Purpose:
+Cancel a previously issued asynchronous RSecuritySvrSession::GetEvent call.
+
+@pre Debug Agent must be connected to the debug security server
+@pre Debug Agent should have called AttachExecutable and GetEvent for the same executable
+
+@param aExecutableName The name of the executable being debugged.
+@return Any error which may be returned by RSessionBase::SendReceive()
+*/
+inline TInt RSecuritySvrSession::CancelGetEvent(const TDesC& aExecutableName)
+{
+	TIpcArgs args(&aExecutableName);
+
+	return SendReceive(EDebugServCancelGetEvent,args);
+}
+
+
+/**
+Purpose:
+Wait for an event to occur from any process. When an event
+occurs, the TRequestStatus is completed.
+
+@pre Debug Agent must be connected to the debug security server
+@pre Debug Agent must have called AttachAll.
+
+Note 1: Events are reported on a FIFO basis
+
+Note 2: All the parameters must remain in scope until either CancelGetEvent is called, or
+until the request is completed. In practice, this generally
+means these parameters should not be based on the stack, as they may go out of
+scope before the call completes.
+
+Note 3: Errors are signalled by completing aStatus
+
+@param aStatus Debug Agent request status variable.
+@param aEventInfo Descriptor containing a TEventInfo object.
+
+*/
+inline void RSecuritySvrSession::GetEvent(TRequestStatus &aStatus, TDes8& aEventInfo)
+    {
+	TIpcArgs args(&KStar, &aEventInfo);
+
+    SendReceive(EDebugServGetEvent, args, aStatus );
+    }
+ 
+/**
+Purpose:
+Cancel a previously issued asynchronous RSecuritySvrSession::GetEvent call.
+
+@pre Debug Agent must be connected to the debug security server
+@pre Debug Agent should have called AttachAll and GetEvent
+
+@return Any error which may be returned by RSessionBase::SendReceive()
+*/
+inline TInt RSecuritySvrSession::CancelGetEvent()
+    {
+    TIpcArgs args(&KStar);
+
+    return SendReceive(EDebugServCancelGetEvent,args);
+    }
+
+
+/**
+Called by a debug agent to request debug privileges for the executable with
+file name aExecutableName.
+
+@param aExecutableName a fully qualified file name of the executable to attach to
+@param aPassive if true then the agent has reduced debug rights.
+
+@return KErrNone if attached successfully, one of the other system wide error
+	codes otherwise
+*/
+inline TInt RSecuritySvrSession::AttachExecutable(const TDesC& aExecutableName, TBool aPassive)
+	{
+	TIpcArgs args((TInt)aPassive, &aExecutableName);
+	return SendReceive(EDebugServAttachExecutable, args);
+	}
+
+/**
+Called by a debug agent to detach from the executable with file
+name aExecutableName.
+
+@param aExecutableName the fully qualified file name of the executable to detach from
+
+@return KErrNone if detached successfully, one of the other system wide error
+	codes otherwise
+*/
+inline TInt RSecuritySvrSession::DetachExecutable(const TDesC& aExecutableName)
+	{
+	TIpcArgs args(&aExecutableName);
+	return SendReceive(EDebugServDetachExecutable, args);
+	}
+
+/**
+Called by a debug agent to attach to events from all processes
+
+@return KErrNone if attached successfully, one of the other system wide error
+    codes otherwise
+*/
+inline TInt RSecuritySvrSession::AttachAll()
+    {
+    return SendReceive(EDebugServAttachAll);
+    }
+
+/**
+Called by a debug agent to detach from all events from all processes
+
+@return KErrNone if detached successfully, one of the other system wide error
+    codes otherwise
+*/
+inline TInt RSecuritySvrSession::DetachAll()
+    {
+    return SendReceive(EDebugServDetachAll);
+    }
+
+/**
+Get buffer size required to contain Functionality text block.
+
+@see in-source documentation in rm_debug_api.h
+
+@param aBufSize function will fill this with the required buffer size
+
+@return KErrNone if the call succeeded, or one of the other system wide error
+        codes if the call failed
+*/
+inline TInt RSecuritySvrSession::GetDebugFunctionalityBufSize(TUint32 *aBufSize)
+	{	
+	TInt res = KErrNone;
+
+	TPtr8 stuff((TUint8*)aBufSize,4, 4);
+
+	TIpcArgs args(&stuff);
+
+	res = SendReceive(EDebugServGetDebugFunctionalityBufSize, args);
+	
+	return res;
+	}
+
+/**
+Get debug functionality text block and place it into aBuffer.
+
+The debug functionality block (DFBlock) is used to provide information about the functionality
+(i.e. features) which are supported by the rm_debug.ldd device driver.
+
+Calling this function with a suitably sized buffer aBuffer will result in the debug
+functionality information being stored in aBuffer. The necessary size of aBuffer can
+be determined by calling DebugFunctionalityBufSize().
+
+The format of the DFBlock is:
+
+@code
+Sub-block 0
+Sub-block 1
+...
+Sub-block N-1
+@endcode
+
+The data which will be returned by a call to GetDebugFunctionality() is constant so is
+guaranteed to fit exactly into the aBuffer allocated, assuming that the size of aBuffer
+corresponds to the value returned from GetDebugFunctionalityBufSize().
+
+Each sub-block is composed of a TTagHeader object followed by a C-style array of TTag objects.
+The sub-block contains information about a particular aspect of the debug sub-system, for example
+information about the manner in which memory can be accessed.
+The TTagHeader is comprised of an identifier which determines the type of data
+it contains, together with the number of TTag elements in the array following the TTagHeader.
+Each TTag in a sub-block has a unique ID, stored in the TTag::iTagId member variable.
+
+The only sub-block that is guaranteed to exist has TTagHeader::iTagHdrId = ETagHeaderIdCore, all other
+sub-blocks are optional. The ETagHeaderIdCore sub-block is the first sub-block within the DFBlock.
+Other sub-blocks may appear in any order after the ETagHeaderIdCore sub-block.
+
+The following is a diagrammatic representation of a sub-block the DFBlock:
+
+@code
+The HHHH represents the tag header ID of a sub-block (TTagHeader::iTagHdrId)
+The NNNN represents the number of TTag elements in the sub-block (TTagHeader::iNumTags)
+The IIIIIIII represents the ID of the TTag (TTag::iTagId)
+The TTTT represents the type of the TTag (TTag::iType)
+The SSSS represents the size of the TTag's associated data (TTag::iSize)
+The VVVVVVVV represents the TTag's value (TTag::iValue)
+
+0xNNNNHHHH	TTagHeader element for first sub-block (has N1 TTag elements)
+0xIIIIIIII	\
+0xSSSSTTTT	-- TTag 0
+0xVVVVVVVV	/
+0xIIIIIIII	\
+0xSSSSTTTT	-- TTag 1
+0xVVVVVVVV	/
+...
+0xIIIIIIII	\
+0xSSSSTTTT	-- TTag N1 - 1
+0xVVVVVVVV	/
+0xNNNNHHHH	TTagHeader element for second sub-block (has N2 TTag elements)
+0xIIIIIIII	\
+0xSSSSTTTT	-- TTag 0
+0xVVVVVVVV	/
+...
+0xIIIIIIII	\
+0xSSSSTTTT	-- TTag N2 - 1
+0xVVVVVVVV	/
+...
+0xNNNNHHHH	TTagHeader element for last sub-block (has NX TTag elements)
+0xIIIIIIII	\
+0xSSSSTTTT	-- TTag 0
+0xVVVVVVVV	/
+...
+0xIIIIIIII	\
+0xSSSSTTTT	-- TTag NX - 1
+0xVVVVVVVV	/
+@endcode
+
+The following example DFBlock contains two sub-blocks (values taken from enums below):
+- ETagHeaderIdCore
+- ETagHeaderIdMemory
+
+@code
+Binary		Meaning					Value
+
+0x000A0000	iTagHdrId, iNumTags		ETagHeaderIdCore, ECoreLast
+0x00000000	iTagId					ECoreEvents
+0x00000000	iType, iSize			ETagTypeBoolean, 0
+0x00000001	iValue					ETrue
+0x00000001	iTagId					ECoreStartStop
+0x00000000	iType, iSize			ETagTypeBoolean, 0
+0x00000001	iValue					ETrue
+...
+0x00000008	iTagId					ECoreHardware
+0x00000000	iType, iSize			ETagTypeBoolean, 0
+0x00000000	iValue					EFalse
+0x00000009	iTagId					ECoreApiConstants
+0x00000000	iType, iSize			ETagTypeBoolean, 0
+0x00000001	iValue					ETrue
+
+0x000A0001	iTagHdrId, iNumTags		ETagHeaderIdMemory, EMemoryLast
+0x00000000	iTagId					EMemoryRead
+0x00000000	iType, iSize			ETagTypeBoolean, 0
+0x00000001	iValue					ETrue
+0x00000001	iTagId					EMemoryWrite
+0x00000000	iType, iSize			ETagTypeBoolean, 0
+0x00000001	iValue					ETrue
+...
+0x00000008	iTagId					EMemoryLE8
+0x00000000	iType, iSize			ETagTypeBoolean, 0
+0x00000001	iValue					ETrue
+0x00000009	iTagId					EMemoryMaxBlockSize
+0x00000001	iType, iSize			ETagTypeTUint32, 0
+0x00004000	iValue					0x4000
+@endcode
+
+- Debug Agent DFBlock Processing:
+
+Debug Agents MUST understand and process the ETagHeaderIdCore block. The other
+blocks may be ignored if not recognised. Tags within each block may be ignored if
+not recognised.
+
+@pre aBuffer.MaxLength() >= *aBufSize where aBufSize is set by a call to: 
+     RSecuritySvrSession::GetDebugFunctionalityBufSize(TUint32 *aBufSize)
+
+@param aBuffer buffer to store functionality block in
+
+@return KErrNone if call succeeded, 
+        KErrNoMemory if temporary memory could not be allocated, 
+        KErrGeneral if debug functionality block could not be accessed
+*/
+inline TInt RSecuritySvrSession::GetDebugFunctionality(TDes8& aBuffer)
+	{
+	TIpcArgs args(&aBuffer);
+
+	TInt res = KErrNone;
+
+	res = SendReceive(EDebugServGetDebugFunctionality, args);
+
+	return res;
+	}
+
+/**
+Read a block of memory from the target debug thread defined by aThreadId.
+
+@pre the client should attach to the process containing the target thread
+@pre aData.MaxLength() >= aLength
+
+@param aThreadId thread ID of the thread to read memory from
+@param aAddress address to start reading memory from
+@param aLength number of bytes of memory to read
+@param aData descriptor to read memory into
+@param aAccessSize access size for memory reads, default is TAccess::EAccess32
+@param aEndianess interpretation of endianess of target data, default is
+       TEndianess::EEndLE8
+
+@return KErrNone if memory read successfully, or one of the other system wide error codes
+*/
+inline TInt RSecuritySvrSession::ReadMemory(const TThreadId aThreadId, const TUint32 aAddress, const TUint32 aLength, TDes8 &aData, const TAccess aAccessSize, const TEndianess aEndianess)
+	{
+	TPckgBuf<TThreadId> threadIdPckg(aThreadId);
+	//set up memory info object
+	TMemoryInfo memoryInfo;
+	memoryInfo.iAddress = aAddress;
+	memoryInfo.iSize = aLength;
+	memoryInfo.iAccess = aAccessSize;
+	memoryInfo.iEndianess = aEndianess;
+
+	TPckgBuf<TMemoryInfo> pckg(memoryInfo);
+
+	TIpcArgs args(&threadIdPckg, &pckg, &aData);
+
+	return SendReceive(EDebugServReadMemory, args);
+	}
+
+/**
+Write a block of memory to the target debug thread defined by aThreadId.
+
+@pre the client should attach non-passively to the process containing the
+     target thread
+
+@param aThreadId thread ID of the thread to write memory to
+@param aAddress address to start writing memory at
+@param aLength number of bytes of memory to write
+@param aData descriptor to read memory from
+@param aAccessSize access size for memory writes, default is TAccess::EAccess32
+@param aEndianess interpretation of endianess of target data, default is
+       TEndianess::EEndLE8
+
+@return KErrNone if memory written successfully, or one of the other system wide error codes
+*/
+inline TInt RSecuritySvrSession::WriteMemory(const TThreadId aThreadId, const TUint32 aAddress, const TUint32 aLength, const TDesC8 &aData, const TAccess aAccessSize, const TEndianess aEndianess)
+	{
+	TPckgBuf<TThreadId> threadIdPckg(aThreadId);
+	//create memory info object
+	TMemoryInfo memoryInfo;
+	memoryInfo.iAddress = aAddress;
+	memoryInfo.iSize = aLength;
+	memoryInfo.iAccess = aAccessSize;
+	memoryInfo.iEndianess = aEndianess;
+
+	TPckgBuf<TMemoryInfo> pckg(memoryInfo);
+
+	TIpcArgs args(&threadIdPckg, &pckg, &aData);
+
+	return SendReceive(EDebugServWriteMemory, args);
+	}
+
+/**
+Read register values from the thread with thread ID aThreadId. The IDs of the
+registers to read are stored as an array of TRegisterInfo objects in 
+aRegisterIds. If the nth register requested could be read then the value of the 
+register will be appended to aRegisterValues and EValid stored at 
+offset n in aRegisterFlags. If the register is supported but could not be read 
+then EInValid will be stored at offset n in aRegisterFlags and arbitrary data 
+appended in aRegisterValues. If reading the specified register is not
+supported by the kernel then ENotSupported will be stored at offset n in 
+aRegisterFlags and arbitrary data appended to aRegisterValues. If an unknown
+register is specified then EUnknown will be put in aRegisterFlags and 
+arbitrary data placed in aRegisterValues.
+
+@pre the client should attach to the process containing the target thread
+
+@see the register ID format is defined in: 
+     SGL.TS0028.027 - Symbian Core Dump File Format v1.0.doc
+
+@param aThreadId thread ID of the thread to read register values from
+@param aRegisterIds descriptor containing array of TFunctionalityRegister defined 
+       register IDs
+@param aRegisterValues descriptor to contain register values
+@param aRegisterFlags descriptor containing array of TUint8 flags, with values 
+       taken from TRegisterFlag
+
+@return KErrNone if registers were read successfully, or one of the other system wide error codes
+*/
+inline TInt RSecuritySvrSession::ReadRegisters(const TThreadId aThreadId, const TDesC8& aRegisterIds, TDes8& aRegisterValues, TDes8& aRegisterFlags)
+	{
+	TPckgBuf<TThreadId> threadIdPckg(aThreadId);
+	TIpcArgs args(&threadIdPckg, &aRegisterIds, &aRegisterValues, &aRegisterFlags);
+
+	return SendReceive(EDebugServReadRegisters, args);
+	}
+
+/**
+Write register values to the thread with thread ID aThreadId. The IDs of the 
+registers to write are stored as an array of TRegisterInfo objects in 
+aRegisterIds. The values to put in the registers are stored as an array of 
+objects in aRegisterValues. If the nth register to write could be 
+written then EValid stored at offset n in aRegisterFlags. If the register is 
+supported but could not be written then EInValid will be stored at offset n in 
+aRegisterFlags. If writing to the specified register is not supported by the 
+kernel then ENotSupported will be stored at offset n in aRegisterFlags. If an 
+unknown register is specified then EUnknown will be put in aRegisterFlags.
+
+@pre the client should attach non-passively to the process containing the 
+     target thread
+
+@see the register ID format is defined in: 
+     SGL.TS0028.027 - Symbian Core Dump File Format v1.0.doc
+
+@param aThreadId thread ID of the thread to write register values to
+@param aRegisterIds descriptor containing array of TFunctionalityRegister defined 
+       register IDs
+@param aRegisterValues descriptor containing array of register values
+@param aRegisterFlags descriptor containing array of TUint8 flags, with values 
+       taken from TRegisterFlag
+
+@return KErrNone if registers were written successfully, or one of the other system wide error codes
+*/
+inline TInt RSecuritySvrSession::WriteRegisters(const TThreadId aThreadId, const TDesC8& aRegisterIds, const TDesC8& aRegisterValues, TDes8& aRegisterFlags)
+	{
+	TPckgBuf<TThreadId> threadIdPckg(aThreadId);
+	TIpcArgs args(&threadIdPckg, &aRegisterIds, &aRegisterValues, &aRegisterFlags);
+
+	return SendReceive(EDebugServWriteRegisters, args);
+	}
+
+/**
+Purpose:
+Set the requisite actions to be taken when a particular event occurs.
+The events are defined in Debug::TEventType and the
+actions are defined in Debug::TKernelEventAction.
+
+The default action for all events is EActionIgnore.
+
+@pre Debug Agent must be connected to the debug security server
+@pre Debug Agent must be attached to the executable specified by aExecutableName.
+
+Note: Event actions are on a per-executable basis. This is
+to ensure that events such as EEventStartThread are notified to the Debug
+Agent, even though the debug agent cannot be aware of the existence
+of a new thread at the time the event occurs.
+
+@param aExecutableName The name of the executable to which the Debug Agent is attached.
+@param aEvent A TEventType enum defined in rm_debug_api.h:Debug::TEventType
+@param aEventAction Any TKernelEventAction permitted by the DFBlock.
+@return Any error which may be returned by RSessionBase::SendReceive()
+*/
+inline TInt RSecuritySvrSession::SetEventAction(const TDesC& aExecutableName, TEventType aEvent, TKernelEventAction aEventAction)
+{
+	TInt res = KErrNone;
+
+	TIpcArgs args(&aExecutableName,aEvent,aEventAction);
+
+	res = SendReceive(EDebugServSetEventAction, args);
+	
+	return res;
+}
+ 
+/**
+Purpose:
+Set the requisite actions to be taken when a particular event occurs that is not 
+associated with any particular process or executable.
+
+The events are defined in Debug::TEventType and the
+actions are defined in Debug::TKernelEventAction.
+
+The default action for all events is EActionIgnore.
+
+@pre Debug Agent must be connected to the debug security server
+@pre Debug Agent must have called AttachAll.
+
+@param aEvent A TEventType enum defined in rm_debug_api.h:Debug::TEventType
+@param aEventAction Any TKernelEventAction permitted by the DFBlock.
+@return Any error which may be returned by RSessionBase::SendReceive()
+*/
+inline TInt RSecuritySvrSession::SetEventAction(TEventType aEvent, TKernelEventAction aEventAction)
+    {
+    TInt res = KErrNone;
+
+    TIpcArgs args(&KStar, aEvent, aEventAction);
+
+    res = SendReceive(EDebugServSetEventAction, args);
+
+    return res;
+    }
+
+/**
+Returns a global listing corresponding to the type specified as aListId. The structure
+of the returned data depends on the value of aListId, see TListId for details.
+If aListData is not large enough to contain the listings data then
+the necessary buffer size is stored in aDataSize and the function returns
+KErrTooBig. In this case the contents of aListData will not contain useful data.
+
+Note that if the aListData buffer was too small to hold the data then the value
+returned as aDataSize corresponds to the size of the data at that particular
+instance. The size of the data will vary over time, for example the thread list
+will increase and decrease in size as threads are created and destroyed, so
+re-requesting data with a buffer with max length aDataSize will not necessarily
+succeed if a list has increased in size between the two calls.
+
+@see TListId
+
+@param aListId enum from TListId signifying which type of listing to return
+@param aListData buffer provided by the debug agent in which data can be returned by the debug system
+@param aDataSize if aListData was not large enough to contain the requested
+       data then the necessary buffer size is stored in aDataSize. If aListData
+       was large enough then the value of aDataSize is the length of aListData
+
+@return KErrNone if data was returned successfully,
+        KErrTooBig if aListData is too small to hold the data,
+	one of the other system-wide error codes
+*/
+inline TInt RSecuritySvrSession::GetList(const TListId aListId, TDes8& aListData, TUint32& aDataSize)
+	{
+	//second argument of ETrue implies a global listing
+	TListDetails info(aListId, EScopeGlobal);
+	TPtr8 infoBuf((TUint8*)&info, sizeof(TListDetails), sizeof(TListDetails));
+	TPtr8 dataSizeBuf((TUint8*)&aDataSize, sizeof(TUint32), sizeof(TUint32));
+	TIpcArgs args(&infoBuf, &aListData, &dataSizeBuf);
+	return SendReceive(EDebugServGetList, args);
+	}
+
+/**
+Returns a thread-specific listing corresponding to the type specified as aListId. The structure
+of the returned data depends on the value of aListId, see TListId for details.
+If aListData is not large enough to contain the listings data then
+the necessary buffer size is stored in aDataSize and the function returns
+KErrTooBig. In this case the contents of aListData will not contain useful data.
+
+Note that if the aListData buffer is too small to hold the data then the value
+returned as aDataSize corresponds to the size of the data at that particular
+instant. The size of the data will vary over time, for example the thread list
+will increase and decrease in size as threads are created and destroyed, so
+re-requesting data with a buffer with max length aDataSize will not necessarily
+succeed if a list has increased in size between the two calls.
+
+@see TListId
+
+@param aThreadId thread to return the listing for
+@param aListId member of TListId signifying which type of listing to return
+@param aListData buffer provided by the debug agent in which data can be returned by the debug system.
+@param aDataSize if aListData was not large enough to contain the requested
+       data then the necessary buffer size is stored in aDataSize. If aListData
+       was large enough then the value of aDataSize is the length of aListData
+
+@return KErrNone if data was returned successfully,
+        KErrTooBig if aListData is too small to hold the data,
+	one of the other system-wide error codes
+*/
+inline TInt RSecuritySvrSession::GetList(const TThreadId aThreadId, const TListId aListId, TDes8& aListData, TUint32& aDataSize)
+	{
+	TListDetails info(aListId, EScopeThreadSpecific, aThreadId.Id());
+	TPtr8 infoBuf((TUint8*)&info, sizeof(TListDetails), sizeof(TListDetails));
+	TPtr8 dataSizeBuf((TUint8*)&aDataSize, sizeof(TUint32), sizeof(TUint32));
+	TIpcArgs args(&infoBuf, &aListData, &dataSizeBuf);
+	return SendReceive(EDebugServGetList, args);
+	}
+
+/**
+Returns a process-specific listing corresponding to the type specified as aListId. The structure
+of the returned data depends on the value of aListId, see TListId for details.
+If aListData is not large enough to contain the listings data then
+the necessary buffer size is stored in aDataSize and the function returns
+KErrTooBig. In this case the contents of aListData will not contain useful data.
+
+Note that if the aListData buffer is too small to hold the data then the value
+returned as aDataSize corresponds to the size of the data at that particular
+instant. The size of the data will vary over time, for example the thread list
+will increase and decrease in size as threads are created and destroyed, so
+re-requesting data with a buffer with max length aDataSize will not necessarily
+succeed if a list has increased in size between the two calls.
+
+@see TListId
+
+@param aProcessId process to return the listing for
+@param aListId member of TListId signifying which type of listing to return
+@param aListData buffer provided by the debug agent in which data can be returned by the debug system.
+@param aDataSize if aListData was not large enough to contain the requested
+       data then the necessary buffer size is stored in aDataSize. If aListData
+       was large enough then the value of aDataSize is the length of aListData
+
+@return KErrNone if data was returned successfully,
+        KErrTooBig if aListData is too small to hold the data,
+	one of the other system-wide error codes
+*/
+inline TInt RSecuritySvrSession::GetList(const TProcessId aProcessId, const TListId aListId, TDes8& aListData, TUint32& aDataSize)
+	{
+	TListDetails info(aListId, EScopeProcessSpecific, aProcessId.Id());
+	TPtr8 infoBuf((TUint8*)&info, sizeof(TListDetails), sizeof(TListDetails));
+	TPtr8 dataSizeBuf((TUint8*)&aDataSize, sizeof(TUint32), sizeof(TUint32));
+	TIpcArgs args(&infoBuf, &aListData, &dataSizeBuf);
+	return SendReceive(EDebugServGetList, args);
+	}
+
+/**
+Purpose:
+Step one or more CPU instructions in the specified thread from the current PC.
+
+@pre Debug Agent must be connected to the debug security server
+@pre Debug Agent must be attached to a process.
+@pre The thread being stepped must be suspended by the Debug Agent.
+
+@param aThreadId the id of the thread which is to be stepped
+@param aNumSteps how many machine-level instructions are to be stepped.
+@return Any error which may be returned by RSessionBase::SendReceive()
+*/
+inline TInt RSecuritySvrSession::Step(const TThreadId aThreadId, const TUint32 aNumSteps)
+	{
+	TPckgBuf<TThreadId> threadIdPckg(aThreadId);
+	TInt res = KErrNone;
+
+	TIpcArgs args(&threadIdPckg,aNumSteps);
+
+	res = SendReceive(EDebugServStep,args);
+
+	return res;
+	}
+
+/**
+Purpose:
+Kill the specified process with the supplied reason. Reason codes are equivalent
+to those in RProcess.Kill().
+
+@pre Debug Agent must be connected to the debug security server
+@pre Debug Agent must be attached to a process.
+
+@param aProcessId the id of the process which is to be killed
+@param aReason The reason to be associated with the ending of this process
+@return Any error which may be returned by RSessionBase::SendReceive()
+*/
+inline TInt RSecuritySvrSession::KillProcess(const TProcessId aProcessId, const TInt aReason)
+	{
+	TPckgBuf<TProcessId> processIdPckg(aProcessId);
+	TInt res = KErrNone;
+
+	TIpcArgs args(&processIdPckg,aReason);
+
+	res = SendReceive(EDebugServKillProcess,args);
+
+	return res;
+	}
+
+/**
+Purpose
+Method to read data from the crash flash
+
+@pre aData buffer to retrieve the data from the crash flash
+@pre aDataSize Size of the data
+
+@return Any error which may be returned by RSessionBase::SendReceive()
+*/
+inline TInt RSecuritySvrSession::ReadCrashLog(const TUint32 aPos, TDes8& aData, const TUint32 aDataSize)
+	{		
+		TIpcArgs args(aPos, &aData, aDataSize);		
+		TInt res = SendReceive(EDebugServReadCrashFlash,args);
+		return res;
+	}
+
+/**
+ * @internalTechnology
+ * @prototype
+ * 
+Purpose:
+Method to write the crash flash config
+
+@return Any error which may be returned by RSessionBase::SendReceive()
+*/
+inline TInt RSecuritySvrSession::WriteCrashConfig(const TUint32 aPos, const TDesC8& aBuffer, TUint32& aSize)
+	{
+		TPtr8 sizePtr((TUint8*)&aSize,4, 4);
+		TIpcArgs args(aPos, &aBuffer, &sizePtr);
+		TInt res = SendReceive(EDebugServWriteCrashFlash, args);
+		return res;
+	}
+/**
+Purpose:
+Method to erase a block in the crash flash
+
+@return Any error which may be returned by RSessionBase::SendReceive()
+*/
+inline TInt RSecuritySvrSession::EraseCrashLog(const TUint32 aPos, const TUint32 aBlockNumber)
+	{	
+		TIpcArgs args(aPos, aBlockNumber);
+		TInt res = SendReceive(EDebugServEraseCrashFlash, args);
+		return res;
+	}
+
+/**
+Purpose:
+Method to erase entire flash partition
+
+@return Any error which may be returned by RSessionBase::SendReceive()
+*/
+inline TInt RSecuritySvrSession::EraseCrashFlashPartition()
+	{
+	TInt res = SendReceive(EDebugServEraseEntireCrashFlash);
+	return res;
+	}
+
+} // end of Debug namespace declaration
+
+#endif // #ifndef __KERNEL_MODE__
+
+#endif // RM_DEBUG_API_H
+
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/debugsrv/runmodedebug/securityserver/inc/rm_debug_logging.h	Fri Aug 27 11:37:29 2010 +0300
@@ -0,0 +1,83 @@
+// Copyright (c) 2006-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+// Logging macros for use in debug subsystem
+// 
+//
+
+#ifndef RM_DEBUG_LOGGING_H
+#define RM_DEBUG_LOGGING_H
+
+/* Debug messages
+ * 
+ * Debug messages are only generated for debug builds.
+ * 
+ * For kernel mode, use __KTRACE_OPT(KDEBUGGER, Kern::Printf(), 
+ * for user mode use RDebug::Printf(). 
+ * 
+ */
+
+#ifdef _DEBUG
+
+  #ifdef __KERNEL_MODE__
+
+    #include <kernel/kernel.h>
+    #include <nkern/nk_trace.h>
+
+    #define LOG_MSG(args...)			__KTRACE_OPT(KDEBUGGER, Kern::Printf(args))
+	#define LOG_ENTRY()					__KTRACE_OPT(KDEBUGGER, Kern::Printf("+%s", __PRETTY_FUNCTION__))
+	#define LOG_EXIT()					__KTRACE_OPT(KDEBUGGER, Kern::Printf("-%s", __PRETTY_FUNCTION__))
+	#define LOG_ARGS(fmt, args...)		__KTRACE_OPT(KDEBUGGER, Kern::Printf("+%s " fmt, __PRETTY_FUNCTION__, args))
+	#define LOG_RETURN(x)				__KTRACE_OPT(KDEBUGGER, Kern::Printf("Returning %d from [%s]", x, __PRETTY_FUNCTION__)
+
+	// These kept for compatability
+    #define LOG_MSG2( a, b )			__KTRACE_OPT(KDEBUGGER, Kern::Printf( a, b ))
+    #define LOG_MSG3( a, b, c )			__KTRACE_OPT(KDEBUGGER, Kern::Printf( a, b, c ))
+    #define LOG_MSG4( a, b, c, d )		__KTRACE_OPT(KDEBUGGER, Kern::Printf( a, b, c, d ))
+    #define LOG_MSG5( a, b, c, d, e )	__KTRACE_OPT(KDEBUGGER, Kern::Printf( a, b, c, d, e ))
+  #else
+
+    #include <e32debug.h>
+
+    #define LOG_MSG(args...)			RDebug::Printf(args)
+	#define LOG_DES(args...)			RDebug::Print(args) // For wide descriptors
+	#define LOG_ENTRY()					RDebug::Printf("+%s", __PRETTY_FUNCTION__)
+	#define LOG_EXIT()					RDebug::Printf("-%s", __PRETTY_FUNCTION__)
+	#define LOG_ARGS(fmt, args...)		RDebug::Printf("+%s " fmt, __PRETTY_FUNCTION__, args)
+	#define LOG_RETURN(x)				RDebug::Printf("Returning %d from [%s]", x, __PRETTY_FUNCTION__)
+
+    #define LOG_MSG2( a, b )			RDebug::Printf( a, b )
+    #define LOG_MSG3( a, b, c )			RDebug::Printf( a, b, c )
+    #define LOG_MSG4( a, b, c, d )		RDebug::Printf( a, b, c, d )
+    #define LOG_MSG5( a, b, c, d, e )	RDebug::Printf( a, b, c, d, e )
+
+  #endif
+
+#else
+
+	#define LOG_MSG(args...)
+	#define LOG_DES(args...)
+	#define LOG_ENTRY()
+	#define LOG_EXIT()
+	#define LOG_ARGS(fmt, args...)
+	#define LOG_RETURN(x)
+
+	#define LOG_MSG2( a, b )
+	#define LOG_MSG3( a, b, c )
+	#define LOG_MSG4( a, b, c, d )
+	#define LOG_MSG5( a, b, c, d, e )
+
+#endif
+
+#endif //RM_DEBUG_LOGGING_H
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/debugsrv/runmodedebug/securityserver/src/c_process_pair.cpp	Fri Aug 27 11:37:29 2010 +0300
@@ -0,0 +1,132 @@
+// Copyright (c) 2006-2010 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+// Provides a helper class for process security management
+// 
+//
+
+#include <e32base.h>
+#include <e32base_private.h>
+
+// Required for logging
+#include <rm_debug_api.h>
+
+#include "c_process_pair.h"
+#include "rm_debug_logging.h"
+
+
+CProcessPair* CProcessPair::NewL(const TDesC& aProcessName, const TProcessId aProcessId)
+	{
+	CProcessPair* self=new (ELeave) CProcessPair();
+	CleanupStack::PushL(self);
+	self->ConstructL(aProcessName, aProcessId);
+	CleanupStack::Pop(self);
+	return self;
+	}
+
+void CProcessPair::ConstructL(const TDesC& aProcessName, const TProcessId aProcessId)
+	{
+	//allocate the process name buffer and fill with aProcessName
+	iProcessName = aProcessName.Alloc();
+	if(iProcessName == NULL)
+		User::Leave(KErrNoMemory);
+
+	LOG_MSG2( "CProcessPair::ConstructL() process name: %S", &TPtr8((TUint8*)iProcessName->Ptr(), 2*iProcessName->Length(), 2*iProcessName->Length()) );
+
+	//set process id
+	iProcessId = aProcessId;
+	}
+
+CProcessPair::CProcessPair(): 
+        iProcessName(NULL)
+	{
+	}
+
+CProcessPair::~CProcessPair()
+	{
+	delete iProcessName;
+	}
+
+/**
+Check whether two CProcessPair objects are equal
+
+@param aProcessPair a CProcessPair object to match with this one
+
+@return 0 if process ids and names do not match, non-zero if they do
+*/
+TBool CProcessPair::operator==(const CProcessPair &aProcessPair) const
+	{
+	return Equals(*aProcessPair.iProcessName, aProcessPair.iProcessId);
+	}
+	
+/**
+Check whether this CProcessPair object has these values set
+
+@param aProcessName process name to check
+@param aProcessId process id to check
+
+@return 0 if process ids and names do not match, non-zero if they do
+*/
+TBool CProcessPair::Equals(const TDesC& aProcessName, const TProcessId aProcessId) const
+	{
+	return (ProcessIdMatches(aProcessId) && (ProcessNameMatches(aProcessName)));
+	}
+
+/**
+Check whether the process ids of two objects match
+
+@param aProcessPair a CProcessPair object to compare with this one
+
+@return 0 if process ids do not match, non-zero if they do
+*/
+TBool CProcessPair::ProcessIdMatches(const CProcessPair &aProcessPair) const
+	{
+	return ProcessIdMatches(aProcessPair.iProcessId);
+	}
+
+/**
+Check whether two process ids match
+
+@param aProcessId a process ID to compare with this pair's process ID
+
+@return 0 if process ids do not match, non-zero if they do
+*/
+TBool CProcessPair::ProcessIdMatches(const TProcessId &aProcessId) const
+	{
+	return iProcessId == aProcessId;
+	}
+
+/**
+Check whether the process names of two objects match in-case-sensitively
+
+@param aProcessPair a CProcessPair object to compare with this one
+
+@return 0 if process names do not match, non-zero if they do
+*/
+TBool CProcessPair::ProcessNameMatches(const CProcessPair &aProcessPair) const
+	{
+	return ProcessNameMatches(*aProcessPair.iProcessName);
+	}
+
+/**
+Check whether two strings match in-case-sensitively
+
+@param aProcessName a process name to compare with this pair's process name
+
+@return 0 if process names do not match, non-zero if they do
+*/
+TBool CProcessPair::ProcessNameMatches(const TDesC& aProcessName) const
+	{
+	return iProcessName->CompareF(aProcessName) == 0;
+	}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/debugsrv/runmodedebug/securityserver/src/c_security_svr_async.cpp	Fri Aug 27 11:37:29 2010 +0300
@@ -0,0 +1,154 @@
+// Copyright (c) 2006-2010 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+// Asynchronous security server active object class.
+// 
+//
+
+#include <e32base.h>
+#include <e32base_private.h>
+
+#include "c_security_svr_async.h"
+#include "rm_debug_logging.h"
+
+using namespace Debug;
+
+__ASSERT_COMPILE(_FOFF(TEventInfo, iEventType) == 20); // Checking that adding iActionTaken hasn't resized the class
+
+CSecuritySvrAsync::CSecuritySvrAsync(CSecuritySvrSession* aSession, TProcessId aAgentId)
+	: CActive(CActive::EPriorityStandard),
+	iSession(aSession),
+	iProcessName(NULL),
+	iAgentId(aAgentId)
+	{
+	LOG_MSG2("CSecuritySvrAsync::CSecuritySvrAsync(aAgentId=0x%x)", TUint(aAgentId.Id()));
+	CActiveScheduler::Add(this);
+	}
+
+// returns a CSecuritySvrAsync active object associated with
+// the specified agent and debugged process.
+CSecuritySvrAsync* CSecuritySvrAsync::NewL(CSecuritySvrSession* aSession, const TDesC8& aProcessName, TProcessId aAgentId)
+	{
+	CSecuritySvrAsync* me = new (ELeave) CSecuritySvrAsync(aSession, aAgentId);
+
+	CleanupStack::PushL(me);
+
+	me->ConstructL(aProcessName);
+
+	CleanupStack::Pop(me);
+	LOG_MSG2("CSecuritySvrAsync::NewL() obj addr=0x%x", me);
+	return (me);
+	}
+
+// dtor
+CSecuritySvrAsync::~CSecuritySvrAsync()
+	{
+	LOG_MSG("CSecuritySvrAsync::~CSecuritySvrAsync()");
+
+	// NOTE: the Cancel() function calls DoCancel() which may rely on class members so be careful not
+	// to destroy/close data members before this call if they are needed
+	Cancel();
+	iProcessName.Close();
+	}
+
+// Associates the agent id and process name with the Active Object being constructed
+void CSecuritySvrAsync::ConstructL(const TDesC8& aProcessName)
+	{
+	LOG_MSG("CSecuritySvrAsync::ConstructL()");
+	iProcessName.CreateL(aProcessName.Length());
+	iProcessName.Copy(aProcessName);
+	}
+
+// RunL() completes a previously issued call (currently only GetEvent() completion)
+void CSecuritySvrAsync::RunL()
+	{
+
+	LOG_MSG4("CSecuritySvrAsync::RunL() &iInfo=0x%08x,  iAgentId.Id()=0x%x, iEventType=%d", 
+	        (TUint8*)&iInfo, iAgentId.Id(), iInfo.iEventType);
+    LOG_MSG5(" RunL() : iProcessIdValid=%d, iThreadId=0x%x, iProcessId=0x%x, &iStatus=0x%x",
+            iInfo.iProcessIdValid, TUint(iInfo.iThreadId) , TUint(iInfo.iProcessId), &iStatus );
+    
+	// Something bad happened in the driver
+	User::LeaveIfError(iStatus.Int());
+
+	// Write back the event data to the debug agent.
+	// For compatibility we need to check the size of the buffer that the
+	// client has passed in as the size of TEventInfo will increase over time.
+	// Clients can calculate the required size from the EApiConstantsTEventInfoSize entry 
+	// in the Debug Functionality block but may still pass in buffers which
+	// are smaller than the Debug Security Server's calculation of sizeof(TEventInfo), 
+	// returning KErrTooBig in this case would be
+	// inappropriate as we would break compatibility.
+	TInt dataLengthToReturn = sizeof(TEventInfo);
+	TInt maxLengthClientSide = iMessage.GetDesMaxLengthL(1);
+	if(maxLengthClientSide < dataLengthToReturn)
+		{
+		dataLengthToReturn = maxLengthClientSide;
+		}
+
+
+	TPtr8 data((TUint8*)&iInfo, dataLengthToReturn, dataLengthToReturn);
+	iMessage.WriteL(1, data, 0);
+	iMessage.Complete(KErrNone);
+	}
+
+// Cancels the oustanding GetEvent call. May cope with other async calls in future.
+void CSecuritySvrAsync::DoCancel()
+	{
+	LOG_MSG("CSecuritySvrAsync::DoCancel()");
+	iSession->Server().iKernelDriver.CancelGetEvent(iProcessName,iAgentId.Id());
+
+	iMessage.Complete(KErrCancel);
+	}
+
+// Report any leave to the client if possible.
+TInt CSecuritySvrAsync::RunError(TInt aError)
+	{
+	LOG_MSG2("CSecuritySvrAsync::RunError()=%d", aError);
+	iMessage.Complete(aError);
+
+	return KErrNone;
+	}
+
+/**
+ * Start an asynchronous GetEvent call to the debug driver
+ * and activates this active object. 
+ * If active object already active, completes the message with error KErrInUse
+ * and takes no further action. 
+ */
+void CSecuritySvrAsync::GetEvent(const RMessage2& aMessage)
+	{
+ 	if( !IsActive() )
+ 		{
+		iMessage = aMessage;
+		LOG_MSG4("CSecuritySvrAsync::GetEvent() this = 0x%08x, iInfo=0x%08x, iStatus=0x%08x", this, &iInfo, &iStatus);
+		
+		SetActive();
+		iSession->Server().iKernelDriver.GetEvent(iProcessName,iAgentId.Id(),iStatus,iInfo);
+		}
+	else
+		{
+		LOG_MSG2("CSecuritySvrAsync::GetEvent() this = 0x%08x: ! Warning: ActiveObject is active. Returning with no effect",
+			this );
+		aMessage.Complete( KErrInUse );
+		}
+	}
+
+// Used for identifying which AO is associated with a debugged process
+const TDesC8& CSecuritySvrAsync::ProcessName(void)
+	{
+	return iProcessName;
+	}
+
+// End of file - c_security_svr_async.cpp
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/debugsrv/runmodedebug/securityserver/src/c_security_svr_server.cpp	Fri Aug 27 11:37:29 2010 +0300
@@ -0,0 +1,685 @@
+// Copyright (c) 2006-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+// Provides the debug security server server implementation.
+// 
+//
+
+/**
+ @file
+ @internalTechnology
+ @released
+*/
+
+#include <e32base.h>
+#include <e32base_private.h>
+#include <rm_debug_api.h>
+#include "c_process_pair.h"
+#include "c_security_svr_session.h"
+#include "c_security_svr_server.h"
+#include "rm_debug_logging.h"
+
+using namespace Debug;
+
+/**
+Server constructor, sessions are created as ESharableSessions, meaning that
+each session will be used by at most one debug agent
+*/
+CSecuritySvrServer::CSecuritySvrServer(CActive::TPriority aActiveObjectPriority)
+	: CServer2(aActiveObjectPriority, ESharableSessions),
+	  iSessionCount(0),
+	  iShutdown()
+	{
+	LOG_MSG("CSecuritySvrServer::CSecuritySvrServer()\n");
+	}
+
+/**
+Standard implementation
+
+@return pointer to new CSecuritySvrServer object
+*/
+CSecuritySvrServer* CSecuritySvrServer::NewLC()
+	{
+	LOG_MSG("CSecuritySvrServer::NewLC()\n");
+
+	CSecuritySvrServer* self=new(ELeave) CSecuritySvrServer(EPriorityStandard);
+	CleanupStack::PushL(self);
+	self->ConstructL();
+	return self;
+	}
+
+/**
+Server destructor, performs cleanup for the server
+*/
+CSecuritySvrServer::~CSecuritySvrServer()
+	{
+	LOG_MSG("CSecuritySvrServer::~CSecuritySvrServer()\n");
+
+	// stop the kernel side driver
+	iKernelDriver.Close();
+	User::FreeLogicalDevice(KDebugDriverName);
+
+	//deallocate both the debug maps
+	iPassiveDebugMap.ResetAndDestroy();
+	iActiveDebugMap.ResetAndDestroy();
+	}
+
+/**
+Starts the server and constructs and starts the servers shutdown timer
+*/
+void CSecuritySvrServer::ConstructL()
+	{
+	LOG_MSG("CSecuritySvrServer::ConstructL()");
+
+	StartL(KSecurityServerName);
+	iShutdown.ConstructL();
+	iShutdown.Start();
+
+	//load the kernel driver
+	TInt err = User::LoadLogicalDevice(KDebugDriverFileName);
+	if(! ((KErrNone == err) || (KErrAlreadyExists == err)))
+		{
+		User::Leave(err);
+		}
+	//create an information object for initialising the driver
+	TRM_DebugDriverInfo driverInfo;
+	driverInfo.iUserLibraryEnd = 0;
+	User::LeaveIfError(iKernelDriver.Open(driverInfo));
+	}
+
+/**
+Creates a new session with the DSS. A version check is done to ensure that an
+up to date version of the DSS is available (according to the DA's needs).
+The device driver is loaded if necessary and a session with the server and a 
+handle to the driver opened.
+
+@param aRequiredVersion the minimal version of the DSS required by the DA
+
+@return a pointer to the new sever session, or NULL if any of the 
+        initialisation process failed
+*/
+CSession2* CSecuritySvrServer::NewSessionL(const TVersion& aRequiredVersion, const RMessage2& aMessage) const
+//
+// Session constructor
+//
+	{
+	LOG_ARGS("version=%d.%d.%d", aRequiredVersion.iMajor, aRequiredVersion.iMinor, aRequiredVersion.iBuild);
+
+	//assert compatible version
+	TVersion currentVersion(KDebugServMajorVersionNumber, KDebugServMinorVersionNumber, KDebugServPatchVersionNumber);
+	if(!User::QueryVersionSupported(currentVersion, aRequiredVersion))
+		{
+		LOG_MSG("Requested version not compatible with this version. Asked for %d.%d.%d but this is %d.%d.%d", aRequiredVersion.iMajor, aRequiredVersion.iMinor, aRequiredVersion.iBuild, KDebugServMajorVersionNumber, KDebugServMinorVersionNumber, KDebugServPatchVersionNumber);
+		User::Leave(KErrNotSupported);
+		}
+	
+	//get the debug agent's process id
+	RThread clientThread;
+	User::LeaveIfError(aMessage.Client(clientThread));
+	CleanupClosePushL(clientThread);
+	RProcess clientProcess;
+	User::LeaveIfError(clientThread.Process(clientProcess));
+	CleanupStack::PopAndDestroy(&clientThread);
+	TProcessId processId = clientProcess.Id();
+	clientProcess.Close();
+
+	//create session
+	LOG_MSG("About to call new(ELeave) CSecuritySvrSession()");
+	CSecuritySvrSession* servSession = new(ELeave) CSecuritySvrSession(processId);
+
+	CleanupStack::PushL(servSession);
+	servSession->ConstructL();
+	CleanupStack::Pop(servSession);
+	return servSession;
+	}
+
+/**
+Manages requests from debug agents to attach to target debug processes
+
+Given the debug agent process ID and the target process name:
+(1) checks whether the pair is already in either of the debug maps, if so
+    then returns KErrAlreadyExists
+(2) if aPassive == ETrue then just add the pair to the passive map and return
+    whatever the return value of the array write was
+(3) if aPassive == EFalse then check whether the target debug process is 
+    already reserved by another debug agent. If it is then return KErrInUse,
+    otherwise add the pair to the active debug map and return the status 
+    value of the array write.
+
+@param aTargetProcessName original FileName of the process to attach to
+@param aDebugAgentProcessId process ID of the debug agent
+@param aPassive ETrue if wish to attach passively, EFalse otherwise
+
+@return KErrNone if successfully attached, otherwise another system wide error
+        code as above
+*/
+TInt CSecuritySvrServer::AttachProcessL(const TDesC& aTargetProcessName, const TProcessId aDebugAgentProcessId, const TBool aPassive)
+	{
+	//store the pair of values
+	LOG_MSG3("CSecuritySvrServer::AttachProcessL() 0x%lx aPassive=%d", aDebugAgentProcessId.Id(), aPassive);
+
+	CProcessPair *processPair = CProcessPair::NewL(aTargetProcessName, aDebugAgentProcessId);
+	if(processPair == NULL)
+		return KErrNoMemory;
+
+	//check whether the pair already exists in the active debug map
+	for(TInt i=0; i<iActiveDebugMap.Count(); i++)
+		{
+        // Note that the equality is of the debug agent id and the proc name
+		if(*processPair == *(iActiveDebugMap[i]))
+			{
+			//process already exists
+			LOG_MSG( "  AttachProcessL() error : KErrAlreadyExists in active map\n" );
+			delete processPair;
+			return KErrAlreadyExists;
+			}
+		}
+
+	//check whether the pair already exists in the passive map
+	for(TInt i=0; i<iPassiveDebugMap.Count(); i++)
+		{
+		if(*processPair == *(iPassiveDebugMap[i]))
+			{
+			//process already exists
+			LOG_MSG( "  AttachProcessL() error : KErrAlreadyExists in passive map\n" );
+			delete processPair;
+			return KErrAlreadyExists;
+			}
+		}
+
+	if(aPassive)
+		{
+		//just add the pair and return
+		TInt err = iPassiveDebugMap.Append(processPair);
+		if(err != KErrNone)
+			{
+			// couldn't add pair for some unknown reason, so delete the pair
+			LOG_MSG2( "  AttachProcessL() error %d appending passive process pair", err );
+			delete processPair;
+			}
+		return err;
+		}
+	else
+		{
+		//check whether the process Id has already been reserved
+		for(TInt i=0; i<iActiveDebugMap.Count(); i++)
+			{
+            // Now check if this is already debugged, but only if its for a particular process.
+            // We can have several entries from AttachAll calls, and its ok to add them
+			if( (!processPair->ProcessNameMatches(_L("*"))) &&
+			    (processPair->ProcessNameMatches(*(iActiveDebugMap[i])) ) )
+				{
+				//process already being debugged
+				LOG_MSG( "  AttachProcessL() error : process already being debugged" );
+				delete processPair;
+				return KErrInUse;
+				}
+			}
+		//try to add the pair. 
+		TInt err = iActiveDebugMap.Append(processPair);
+		if(err != KErrNone)
+			{
+			// couldn't add pair for some unknown reason, so delete the pair
+			LOG_MSG2( "  AttachProcessL() error %d inserting active process pair", err );
+			delete processPair;
+			}
+		return err;
+		}
+	}
+
+/*
+Detach from debugging the specified process
+
+@param aTargetProcessName name of the process to detach from
+@param aDebugAgentProcessId process ID of the debug agent
+
+@return KErrNone if successfully detached, KErrNotFound if an attempt is made
+        to detach from a process which the debug agent hasn't previously attached to
+*/
+TInt CSecuritySvrServer::DetachProcess(const TDesC& aTargetProcessName, const TProcessId aDebugAgentProcessId)
+	{
+    LOG_MSG2( "CSecuritySvrServer::DetachProcess() for agent with id 0x%lx", aDebugAgentProcessId.Id() );
+
+	//check whether the pair is in the active debug map
+	for(TInt i=0; i<iActiveDebugMap.Count(); i++)
+		{
+		if(iActiveDebugMap[i]->Equals(aTargetProcessName, aDebugAgentProcessId))
+			{
+			//remove the process pair from the active debug map
+			delete iActiveDebugMap[i];
+			iActiveDebugMap.Remove(i);
+			return KErrNone;
+			}
+		}
+
+	//check whether the pair is in the passive debug map
+	for(TInt i=0; i<iPassiveDebugMap.Count(); i++)
+		{
+		if(iPassiveDebugMap[i]->Equals(aTargetProcessName, aDebugAgentProcessId))
+			{
+			//remove the process pair from the active debug map
+			delete iPassiveDebugMap[i];
+			iPassiveDebugMap.Remove(i);
+			return KErrNone;
+			}
+		}
+
+	//process pair wasn't in either map
+	return KErrNotFound;
+	}
+
+/**
+Given a debug agent process ID, removes all references to that debug agent
+from the debug maps
+
+@param aMessage message from the debug agent
+
+@return returns KErrNone if successful, another system wide error code otherwise
+*/
+void CSecuritySvrServer::DetachAllProcesses(const TProcessId aDebugAgentProcessId)
+	{
+	//check whether the debug agent process ID is in the active debug map
+	for(TInt i=iActiveDebugMap.Count()-1; i>=0; i--)
+		{
+		if(iActiveDebugMap[i]->ProcessIdMatches(aDebugAgentProcessId))
+			{
+			//remove the process pair from the active debug map
+			delete iActiveDebugMap[i];
+			iActiveDebugMap.Remove(i);
+			}
+		}
+
+	//check whether the debug agent process ID is in the passive debug map
+	for(TInt i=iPassiveDebugMap.Count()-1; i>=0; i--)
+		{
+		if(iPassiveDebugMap[i]->ProcessIdMatches(aDebugAgentProcessId))
+			{
+			//remove the process pair from the passive debug map
+			delete iPassiveDebugMap[i];
+			iPassiveDebugMap.Remove(i);
+			}
+		}
+	}
+
+/*
+Check whether the specified debug agent is attaced to the specfied target
+process.
+
+@param aTargetThreadId thread ID of a thread in the target process
+@param aMessage a message which originates with the debug agent
+@param aPassive if EFalse then checks whether the debug agent is the active
+       debugger of the target process. If ETrue then checks whether the debug
+       agent is attached to the target process, irrespective of whether it is
+       attached passively or actively
+
+@return ETrue if attached, EFalse otherwise
+*/
+TBool CSecuritySvrServer::CheckAttached(const TThreadId aTargetThreadId, const RMessage2& aMessage, const TBool aPassive)
+	{
+	
+	//get a handle to the target thread
+	RThread targetThread;
+	TInt err = targetThread.Open(aTargetThreadId);
+	if(err != KErrNone)
+		{
+		return EFalse;
+		}
+
+	//get a handle to the target process
+	RProcess targetProcess;
+	err = targetThread.Process(targetProcess);
+	//finshed with the thread handle so close it
+	targetThread.Close();
+	if(err != KErrNone)
+		return EFalse;
+
+	//get the target process' file name
+	TFileName targetFileName = targetProcess.FileName();
+
+	// Tamperproofing. Ensure that the debug agent really has a superset
+	// of the target process PlatSec capabilities, as authorised
+	// by an OEM Debug Token (if any)
+
+	TSecurityInfo targetSecInfo(targetProcess);
+
+	// Now compare the capabilities, to ensure the DebugAgent has been authorised with
+	// sufficient capabilities from its OEM Debug token
+	CSecuritySvrSession* session = (CSecuritySvrSession*)aMessage.Session();
+
+	// Presume we need to check the target process is debuggable unless a valid OEM Debug token in effect?
+	if (!OEMTokenPermitsDebugL(session->GetOEMDebugCapabilities(), targetSecInfo.iCaps) )
+		{
+		// No debug token therefore check if the process is debuggable
+		err = iKernelDriver.IsDebuggable(targetProcess.Id());
+		}
+
+	//finished with the process handle so close it
+	targetProcess.Close();
+
+	if (err != KErrNone)
+	{
+		// The process was not marked as debuggable by the loader, and the OEM
+		// debug token did not override the lack of a debuggable bit.
+		// The process was not marked as debuggable by the loader
+		return EFalse;
+	}
+
+	return CheckAttachedProcess(targetFileName, aMessage, aPassive);
+	}
+
+/*
+Check whether the specified debug agent is attaced to the specfied target
+process.
+
+@param aTargetProcessId process ID of the target process
+@param aMessage a message which originates with the debug agent
+@param aPassive if EFalse then checks whether the debug agent is the active
+       debugger of the target process. If ETrue then checks whether the debug
+       agent is attached to the target process, irrespective of whether it is
+       attached passively or actively
+
+@return ETrue if attached, EFalse otherwise
+*/
+TBool CSecuritySvrServer::CheckAttached(const TProcessId aTargetProcessId, const RMessage2& aMessage, const TBool aPassive)
+	{
+	//get a handle to the target process
+	RProcess targetProcess;
+	TInt err =targetProcess.Open(aTargetProcessId);
+	if(err != KErrNone)
+		{
+		return EFalse;
+		}
+
+	//get the target process' file name
+	TFileName targetFileName = targetProcess.FileName();
+
+	// Tamperproofing. Ensure that the debug agent really has a superset
+	// of the target process PlatSec capabilities, as authorised
+	// by an OEM Debug Token (if any)
+
+	TSecurityInfo targetSecInfo(targetProcess);
+
+	// Now compare the capabilities, to ensure the DebugAgent has been authorised with
+	// sufficient capabilities from its OEM Debug token
+	CSecuritySvrSession* session = (CSecuritySvrSession*)aMessage.Session();
+
+	// Presume we need to check the target process is debuggable unless a valid OEM Debug token in effect?
+	if ( !OEMTokenPermitsDebugL(session->GetOEMDebugCapabilities(), targetSecInfo.iCaps) )
+		{
+		// No debug token therefore check if the process is debuggable
+		err = iKernelDriver.IsDebuggable(targetProcess.Id());
+		}
+
+	//finished with the process handle so close it
+	targetProcess.Close();
+
+	if (err != KErrNone)
+	{
+		return EFalse;
+	}
+
+	return CheckAttachedProcess(targetFileName, aMessage, aPassive);
+	}
+
+/*
+Check whether the specified debug agent is attaced to the specfied target
+process.
+
+@param aTargetProcessName 
+@param aMessage a message which originates with the debug agent
+
+@return ETrue if attached, EFalse otherwise
+*/
+TBool CSecuritySvrServer::CheckAttachedProcess(const TDesC& aTargetProcessName, const RMessage2& aMessage, const TBool aPassive) const
+	{
+	//get the debug agent's process id
+	TProcessId clientProcessId = 0;
+	TInt err = GetProcessIdFromMessage(clientProcessId, aMessage);
+	if(err != KErrNone)
+		return EFalse;
+
+	//check permissions
+	if(aPassive)
+		return IsDebugger(aTargetProcessName, clientProcessId);
+	else
+		return IsActiveDebugger(aTargetProcessName, clientProcessId);
+	}
+
+/**
+Tests whether the debug agent is attached actively to the target debug process
+
+@param aTargetProcessName target debug process' FileName
+@param aDebugAgentProcessId process ID of a debug agent
+
+@return ETrue if the specified debug agent is actively attached to the 
+        specified target debug process, EFalse otherwise
+*/
+TBool CSecuritySvrServer::IsActiveDebugger(const TDesC& aTargetProcessName, const TProcessId aDebugAgentProcessId) const
+	{
+	//check whether the pair is in the active debug map
+	for(TInt i=0; i<iActiveDebugMap.Count(); i++)
+		{
+		// If both match, which can include aTargetProcessName being "*"
+		if(iActiveDebugMap[i]->Equals(aTargetProcessName, aDebugAgentProcessId))
+			{
+			LOG_MSG2( "CSecuritySvrServer::IsActiveDebugger() for agent id 0x%lx matches name and pid", 
+					aDebugAgentProcessId.Id() );			
+			return ETrue;
+			}
+		// if the pid matches and the name in the map is "*", indicating that 
+		// this is an attach all agent, and thus debugging 
+		if( iActiveDebugMap[i]->ProcessIdMatches(aDebugAgentProcessId) &&
+			iActiveDebugMap[i]->ProcessNameMatches(_L("*")) )
+			{
+			LOG_MSG2( "CSecuritySvrServer::IsActiveDebugger() for AttachAll agent id 0x%lx", 
+				aDebugAgentProcessId.Id() );
+			return ETrue;
+			}
+		}
+	//not found so return false
+	return EFalse;
+	}
+
+/**
+Tests whether the target process is being debugged
+
+@param aTargetProcessName target process' FileName
+@param aPassive indicates whether to check for the process being actively debugged,
+or passively debugged
+
+@return ETrue if the specified target process is being debugged,
+        EFalse otherwise
+*/
+TBool CSecuritySvrServer::IsDebugged(const TDesC& aTargetProcessName, const TBool aPassive) const
+	{
+	//get a reference to the appropriate list
+	const RPointerArray<CProcessPair>& map = (aPassive) ? iPassiveDebugMap : iActiveDebugMap;
+
+	//iterate through the map trying to match the aTargetProcessName
+	for(TInt i=0; i<map.Count(); i++)
+		{
+		if(map[i]->ProcessNameMatches(aTargetProcessName))
+			{
+			return ETrue;
+			}
+		}
+	return EFalse;
+	}
+
+/**
+Tests whether the debug agent is attached to the target debug process
+
+@param aTargetProcessName target debug process' FileName
+@param aDebugAgentProcessId process ID of a debug agent
+
+@return ETrue if the specified debug agent is attached to the 
+        specified target debug process (regardless of whether it is attached
+	passively or actively), EFalse otherwise
+*/
+TBool CSecuritySvrServer::IsDebugger(const TDesC& aTargetProcessName, const TProcessId aDebugAgentProcessId) const
+	{
+	//check whether the pair is in the active debug map
+	if(IsActiveDebugger(aTargetProcessName, aDebugAgentProcessId))
+		return ETrue; 
+
+	//check whether the pair is in the passive debug map
+	for(TInt i=0; i<iPassiveDebugMap.Count(); i++)
+		{
+		if(iPassiveDebugMap[i]->Equals(aTargetProcessName, aDebugAgentProcessId))
+			return ETrue;
+		}
+	//not found so return false
+	return EFalse;
+	}
+
+/**
+Decrements the server's count of how many sessions are connected to it and
+starts the shutdown timer if there are no sessions connected
+*/
+void CSecuritySvrServer::SessionClosed()
+	{
+	if(--iSessionCount < 1)
+		{
+		iShutdown.Start();
+		}
+	}
+
+/**
+Increments the servers count of how many sessions are connected to it and
+cancels the shutdown timer if it is running
+*/
+void CSecuritySvrServer::SessionOpened()
+	{
+	iSessionCount++;
+	iShutdown.Cancel();
+	}
+
+/** 
+  Get the process id of the thread which sent aMessage
+  @param aProcessId process id of the thread which sent aMessage
+  @param aMessage message object sent by thread 
+
+  @return KErrNone if aProcessId could be set, or one of the system wide error codes if not
+  */
+TInt CSecuritySvrServer::GetProcessIdFromMessage(TProcessId& aProcessId, const RMessage2& aMessage) const
+	{
+	//get the debug agent's thread
+	RThread clientThread;
+	TInt err = aMessage.Client(clientThread);
+	if(err != KErrNone)
+		{
+		return err;
+		}
+
+	//get the debug agent's process
+	RProcess clientProcess;
+	err = clientThread.Process(clientProcess);
+
+	//finished with the thread handle so close it
+	clientThread.Close();
+
+	//check if there was an error from getting the process
+	if(err != KErrNone)
+		{
+		return err;
+		}
+
+	//get the debug agent's process id
+	aProcessId = clientProcess.Id();
+
+	//finished with the process handle so close it
+	clientProcess.Close();
+
+	return KErrNone;
+	}
+
+/**
+  Helper function which determines whether the capabilities of the
+  OEM Token are sufficient to permit debug of an application.
+
+  Normally, we use the AllFiles capability as a proxy which
+  means a Debug Agent can debug non-debuggable executables,
+  provided it has a superset of the capabilities of the executable
+  to be debugged.
+ 
+  However, this causes the problem that all OEM Debug Tokens implicitly
+  give the power to debug an AllFiles executable, even if all that
+  is really needed is the power to debug an app with no capabilities,
+  or capabilities other than AllFiles.
+  
+  To address this, we treat the AllFiles capability in a special way.
+  The AllFiles capability in a token is taken to mean that an OEM has
+  signed the token, and hence can debug other executables. But this does
+  not inclue the ability to debug an AllFiles executable. To debug an AllFiles
+  executable, the token must also have TCB.
+
+  @param aTokenCaps - The PlatSec capabilities of a token
+  @param aTargetCaps - The PlatSec capabilities of a target app to be debugged
+
+  @return ETrue if authorised for debugging, EFalse otherwise.
+
+  @leave Any system error code.
+  */
+TBool CSecuritySvrServer::OEMTokenPermitsDebugL(const TCapabilitySet aTokenCaps, const TCapabilitySet aTargetCaps)
+	{	
+	LOG_MSG("CSecuritySvrSession::OEMTokenPermitsDebugL\n");
+
+	// Is the token valid - i.e. does it have AllFiles.
+	if ( !aTokenCaps.HasCapability(ECapabilityAllFiles) )
+		{
+		// Token is not valid, as it does not have AllFiles.
+		LOG_MSG("CSecuritySvrSession::OEMTokenPermitsDebugL - Token does not have AllFiles\n");
+			
+		return EFalse;
+		}
+
+	// Token MUST have a strict superset of capabilities
+	if ( !aTokenCaps.HasCapabilities(aTargetCaps) )
+		{
+		// Token does not have at least all the capabilities of the target
+		LOG_MSG("CSecuritySvrSession::OEMTokenPermitsDebugL - Token does not have superset of target capabilities\n");
+
+		return EFalse;
+		}
+
+	// Special case: If the target has AllFiles, the Token must have TCB
+	if ( aTargetCaps.HasCapability(ECapabilityAllFiles) )
+		{
+		// Target has AllFiles, so does the Token have TCB?
+		if ( !aTokenCaps.HasCapability(ECapabilityTCB) )
+			{
+			// Token does not have TCB.
+			LOG_MSG("CSecuritySvrSession::OEMTokenPermitsDebugL - Token does not have TCB when target has AllFiles\n");
+	
+			return EFalse;
+			}
+		}
+
+	// If we have passed all the above tests, the token permits debug
+	return ETrue;
+	}
+
+/**
+ * This looks at a debug tokens capability and ensures it is sufficient 
+ * to provide access to the flash partition
+ * @param aTokenCaps Capabilties of the Token
+ * @return TBool Whether or not flash access is permitted
+ */
+TBool CSecuritySvrServer::OEMTokenPermitsFlashAccessL(const TCapabilitySet aTokenCaps)
+	{	
+	//Must have TCB to access flash
+	return aTokenCaps.HasCapability(ECapabilityTCB);
+	}
+
+//eof
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/debugsrv/runmodedebug/securityserver/src/c_security_svr_session.cpp	Fri Aug 27 11:37:29 2010 +0300
@@ -0,0 +1,2653 @@
+// Copyright (c) 2006-2010 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+// Provides the debug security server session implementation.
+// 
+//
+
+/**
+ @file
+ @internalTechnology
+ @released
+*/
+
+// Needed so we get the text strings for capabilities
+#define __INCLUDE_CAPABILITY_NAMES__
+
+#include <e32std.h>
+#include <e32std_private.h>
+#include <e32btrace.h>
+#include <d32btrace.h>
+#include <e32base.h>
+#include <e32base_private.h>
+#include <e32uid.h>
+#include <f32file.h>
+#include <e32capability.h>
+#include <rm_debug_api.h>
+
+// required for direct parsing of e32image/tromimage headers
+#include <f32image.h>
+#include <e32rom.h>
+
+//added for direct access to media driver
+#include <partitions.h>
+#include <ftlcontrolio.h>
+
+#include "c_security_svr_session.h"
+#include "c_security_svr_server.h"
+#include "c_security_svr_async.h"
+#include "rm_debug_logging.h"
+#ifdef _DEBUG
+#include "low_mem_requests.h"
+#endif
+
+using namespace Debug;
+
+CSecuritySvrSession::CSecuritySvrSession(const TProcessId& aDebugAgentProcessId)
+	: iDebugAgentProcessId(aDebugAgentProcessId),
+	  iServerNotified(EFalse),
+	  iCrashConnected(EFalse)
+	{
+	// Ensure that this debug agent has no target capability override
+	// by default
+	iOEMDebugCapabilities.SetEmpty();
+	}
+
+void CSecuritySvrSession::ServiceError(const RMessage2 &aMessage, TInt aError)
+	{
+	LOG_MSG2("CSecuritySvrSession::ServiceError(), aError: %d\n", aError);
+
+	//insert ending heap markers
+	HeapWatcher(aMessage.Function(), EFalse);
+
+	aMessage.Complete(aError);
+	}
+
+/**
+Called by the client/server framework as part of session creation.
+
+Notifies the server that a session is being created
+*/
+void CSecuritySvrSession::CreateL()
+	{
+	LOG_MSG("CSecuritySvrSession::CreateL()\n");
+
+	//notify the server that the session has been opened
+	Server().SessionOpened();
+	iServerNotified = ETrue;
+	}
+
+/**
+  Returns a reference to the DSS
+
+  @return a reference to the DSS
+  */
+CSecuritySvrServer& CSecuritySvrSession::Server() const
+    {
+    return *static_cast<CSecuritySvrServer*>(const_cast<CServer2*>(CSession2::Server()));
+    }
+
+/**
+Session destructor. Performs necessary cleanup and notifies the server that the
+session is being closed
+*/
+CSecuritySvrSession::~CSecuritySvrSession()
+	{
+	LOG_MSG("CSecuritySvrSession::~CSecuritySvrSession!()\n");
+
+	// Cancel any outstanding async objects.
+	iAsyncHandlers.ResetAndDestroy();
+		
+	// Inform the device driver of the agent detach.
+	Server().iKernelDriver.DetachAgent(iDebugAgentProcessId.Id());
+
+	LOG_MSG( "CSecuritySvrSession::~CSecuritySvrSession() : -> securityServer.DetachAllProcesses()\n" );
+	Server().DetachAllProcesses(iDebugAgentProcessId);
+
+	//notify the server that the session has closed
+	if(iServerNotified)
+		{
+		Server().SessionClosed();
+		}
+	}
+
+void CSecuritySvrSession::ConstructL()
+	{
+	// nothing to do
+	}
+
+/**
+  Used to insert heap checking markers.
+
+  @param aFunction The function that heap markers should be added for
+  @param aEntry if ETrue indicates that heap checking is starting, if EFalse
+  that heap checking is ending.
+  */
+void CSecuritySvrSession::HeapWatcher(const TUint32 aFunction, const TBool aEntry) const
+	{
+	switch(aFunction)
+		{
+		case EDebugServAttachExecutable:
+			return;
+		case EDebugServDetachExecutable:
+			return;
+		case EDebugServSuspendThread:
+			return;
+		case EDebugServResumeThread:
+			return;
+		case EDebugServAttachAll:
+			return;
+		case EDebugServDetachAll:
+			return;
+// used for out-of-memory testing in debug mode
+#ifdef _DEBUG
+		// start heap marking in on entry, do nothing on exit
+		case EDebugServMarkHeap:
+			{
+			if(aEntry)
+				{
+				__UHEAP_MARK;
+				}
+			return;
+			}
+		// stop heap marking on exit, do nothing on entry
+		case EDebugServMarkEnd:
+			{
+			if(!aEntry)
+				{
+				__UHEAP_MARKEND;
+				}
+			return;
+			}
+#endif
+		default:
+			if(aEntry)
+				{
+				__UHEAP_MARK;
+				}
+			else
+				{
+				__UHEAP_MARKEND;
+				}
+			return;
+		}
+	}
+
+void CSecuritySvrSession::ServiceL(const RMessage2& aMessage)
+//
+// Session service handler
+//
+	{
+	//insert starting heap markers
+	HeapWatcher(aMessage.Function(), ETrue);
+
+	switch(aMessage.Function())
+		{
+		case EDebugServResumeThread:
+			LOG_MSG( "CSecuritySvrSession::ServiceL() EDebugServResumeThread\n" );
+			ResumeThreadL(aMessage);
+			break;
+
+		case EDebugServSuspendThread:
+			LOG_MSG( "CSecuritySvrSession::ServiceL() EDebugServSuspendThread\n" );
+			SuspendThreadL(aMessage);
+			break;
+
+		case EDebugServReadMemory:
+			LOG_MSG( "CSecuritySvrSession::ServiceL() EDebugServReadMemory\n" );
+			ReadMemoryL(aMessage);
+			break;
+
+		case EDebugServWriteMemory:
+			LOG_MSG( "CSecuritySvrSession::ServiceL() EDebugServWriteMemory\n" );
+			WriteMemoryL(aMessage);
+			break;
+
+		case EDebugServSetBreak:
+			LOG_MSG( "CSecuritySvrSession::ServiceL() EDebugServSetBreak\n" );
+			SetBreakL(aMessage);
+			break;
+
+		case EDebugServClearBreak:
+			LOG_MSG( "CSecuritySvrSession::ServiceL() EDebugServClearBreak\n" );
+			ClearBreakL(aMessage);
+			break;
+
+		case EDebugServModifyBreak:
+			LOG_MSG( "CSecuritySvrSession::ServiceL() EDebugServModifyBreak\n" );
+			ModifyBreakL(aMessage);
+			break;
+
+		case EDebugServModifyProcessBreak:
+			LOG_MSG( "CSecuritySvrSession::ServiceL() EDebugServModifyProcessBreak\n" );
+			ModifyProcessBreakL(aMessage);
+			break;
+
+		case EDebugServBreakInfo:
+			LOG_MSG( "CSecuritySvrSession::ServiceL() EDebugServBreakInfo\n" );
+			BreakInfoL(aMessage);
+			break;
+
+		case EDebugServReadRegisters:
+			LOG_MSG( "CSecuritySvrSession::ServiceL() EDebugServReadRegisters\n" );
+			ReadRegistersL(aMessage);
+			break;
+
+		case EDebugServWriteRegisters:
+			LOG_MSG( "CSecuritySvrSession::ServiceL() EDebugServWriteRegisters\n" );
+			WriteRegistersL(aMessage);
+			break;
+
+		case EDebugServGetEvent:
+			LOG_MSG( "CSecuritySvrSession::ServiceL() EDebugServGetEvent\n" );
+			GetEventL(aMessage);
+			break;
+
+		case EDebugServCancelGetEvent:
+			LOG_MSG( "CSecuritySvrSession::ServiceL() EDebugServCancelGetEvent\n" );
+			CancelGetEventL(aMessage);
+			break;
+
+		case EDebugServAttachExecutable:
+			LOG_MSG( "CSecuritySvrSession::ServiceL() EDebugServAttachExecutable\n" );
+			AttachProcessL(aMessage);
+			break;
+
+		case EDebugServDetachExecutable:
+			LOG_MSG( "CSecuritySvrSession::ServiceL() EDebugServDetachExecutable\n" );
+			DetachProcessL(aMessage);
+			break;
+
+		case EDebugServAttachAll:
+			LOG_MSG( "CSecuritySvrSession::ServiceL() EDebugServAttachAll\n" );
+			AttachAllL(aMessage);
+			break;
+
+		case EDebugServDetachAll:
+			LOG_MSG( "CSecuritySvrSession::ServiceL() EDebugServDetachAll\n" );
+			DetachAllL(aMessage);
+			break;			
+			
+		case EDebugServGetDebugFunctionalityBufSize:
+			LOG_MSG( "CSecuritySvrSession::ServiceL() EDebugServGetDebugFunctionalityBufSize\n" );
+			GetDebugFunctionalityBufSizeL(aMessage);
+			break;
+
+		case EDebugServGetDebugFunctionality:
+			LOG_MSG( "CSecuritySvrSession::ServiceL() EDebugServGetDebugFunctionality\n" );
+			GetDebugFunctionalityL(aMessage);
+			break;
+
+		case EDebugServSetEventAction:
+			LOG_MSG( "CSecuritySvrSession::ServiceL() EDebugServSetEventAction\n" );
+			SetEventActionL(aMessage);
+			break;
+
+		case EDebugServGetList:
+			LOG_MSG( "CSecuritySvrSession::ServiceL() EDebugServGetList\n" );
+			GetListL(aMessage);
+			break;
+
+		case EDebugServStep:
+			LOG_MSG("CSecuritySvrSession::ServiceL() EDebugServStep\n");
+			StepL(aMessage);
+			break;
+
+		case EDebugServSetProcessBreak:
+			LOG_MSG("CSecuritySvrSession::ServiceL() EDebugServSetProcessBreak\n");
+			SetProcessBreakL(aMessage);
+			break;
+		
+		case EDebugServProcessBreakInfo:
+			LOG_MSG("CSecuritySvrSession::ServiceL() EDebugServProcessBreakInfo\n");
+			ProcessBreakInfoL(aMessage);
+			break;
+
+		case EDebugServKillProcess:
+			LOG_MSG("CSecuritySvrSession::ServiceL() EDebugServKillProcess\n");
+			KillProcessL(aMessage);
+			break;
+
+#ifdef _DEBUG
+		case EDebugServMarkHeap:
+			LOG_MSG("CSecuritySvrSession::ServiceL() EDebugServMarkHeap\n");
+			// all taken care of in HeapWatcher
+			aMessage.Complete(KErrNone);
+			break;
+
+		case EDebugServMarkEnd:
+			LOG_MSG("CSecuritySvrSession::ServiceL() EDebugServMarkEnd\n");
+			// all taken care of in HeapWatcher
+			aMessage.Complete(KErrNone);
+			break;
+
+		case EDebugServFailAlloc:
+			LOG_MSG("CSecuritySvrSession::ServiceL() EDebugServFailAlloc\n");
+			DoFailAlloc(aMessage);
+			break;
+#endif
+		case EDebugServReadCrashFlash:
+			ReadCrashLogL(aMessage);
+			break;		
+		case EDebugServWriteCrashFlash:
+			LOG_MSG("CSecuritySvrSession::ServiceL() EDebugServWriteCrashFlash\n");
+			WriteCrashConfigL(aMessage);
+			break;
+		case EDebugServEraseCrashFlash:
+			LOG_MSG("CSecuritySvrSession::ServiceL() EDebugServEraseCrashFlash\n");
+			EraseCrashLogL(aMessage);
+			break;
+		case EDebugServEraseEntireCrashFlash:
+			LOG_MSG("CSecuritySvrSession::ServiceL() EDebugServEraseEntireCrashFlash\n");
+			EraseEntireCrashLogL(aMessage);
+			break;
+		default:
+			LOG_MSG( "CSecuritySvrSession::ServiceL() Unknown request, calling User::Leave(KErrNotSupported);\n" );
+			User::Leave(KErrNotSupported);
+			break;
+		}
+
+	//insert ending heap markers
+	HeapWatcher(aMessage.Function(), EFalse);
+	
+	LOG_EXIT();
+	}
+
+#ifdef _DEBUG
+/**
+  Used to control heap failure in debug mode.
+  @param aMessage If aMessage.Int0 is non-zero then heap will be set to fail on that allocation.
+  If aMessage.Int0 is zero then the heap failure count is reset
+  */
+void CSecuritySvrSession::DoFailAlloc(const RMessage2& aMessage)
+	{
+	TInt count = aMessage.Int0();
+	if(count == 0)
+		{
+		__UHEAP_RESET;
+		}
+	else
+		{
+		__UHEAP_FAILNEXT(count);
+		}
+	aMessage.Complete(KErrNone);
+	}
+#endif
+
+/**
+Suspends execution of the specified thread.
+
+@param aMessage contains an integer representation of the target thread's
+       thread ID at offset 0.
+
+@leave KErrPermissionDenied if security check fails or KErrArgument if the
+       thread does not exist
+*/
+void CSecuritySvrSession::SuspendThreadL(const RMessage2& aMessage)
+	{
+
+	LOG_MSG( "CSecuritySvrSession::SuspendThreadL()\n" );
+
+	//get thread ID
+	TThreadId threadId = ReadTThreadIdL(aMessage, 0);
+	//check attached
+	CheckAttachedL(threadId, aMessage, EFalse);
+
+	//security check passed so can perform actions
+	User::LeaveIfError(Server().iKernelDriver.SuspendThread(threadId));
+
+	aMessage.Complete(KErrNone);
+	}
+
+/**
+Resumes execution of the specified thread.
+
+@param aMessage contains an integer representation of the target thread's
+       thread ID at offset 0.
+
+@leave KErrPermissionDenied if security check fails or KErrArgument if the
+       thread does not exist
+*/
+void CSecuritySvrSession::ResumeThreadL(const RMessage2& aMessage)
+	{
+	LOG_MSG( "CSecuritySvrSession::ResumeThreadL()\n" );
+
+	//get thread ID
+	TThreadId threadId = ReadTThreadIdL(aMessage, 0);
+
+	//check attached
+	CheckAttachedL(threadId, aMessage, EFalse);
+	
+	//security check passed so can perform actions
+	TInt err = Server().iKernelDriver.ResumeThread(threadId);
+	aMessage.Complete(err);
+	}
+
+void CSecuritySvrSession::GetDebugFunctionalityBufSizeL(const RMessage2& aMessage)
+//
+// Retrieve size of functionality data buffer in bytes which must be allocated
+// by the client
+//
+	{
+	LOG_MSG( "CSecuritySvrSession::GetDebugFunctionalityBufSizeL()\n" );
+
+	TUint32 result = 0;
+	// Get Buffer size from the kernel driver
+	User::LeaveIfError(Server().iKernelDriver.GetDebugFunctionalityBufSize(result));
+
+	TPtr8 stuff((TUint8*)&result,4, 4);
+
+	aMessage.WriteL(0,stuff);
+
+	aMessage.Complete(KErrNone);
+	}
+
+void CSecuritySvrSession::GetDebugFunctionalityL(const RMessage2& aMessage)
+//
+// Retrieve the functionality data and place it in a buffer
+// allocated by the client.
+//
+	{
+	LOG_MSG( "CSecuritySvrSession::GetDebugFunctionalityL()\n" );
+
+	TUint32 dfsize = 0;
+
+	// Get Buffer size from the kernel driver
+	User::LeaveIfError(Server().iKernelDriver.GetDebugFunctionalityBufSize(dfsize));
+
+	// Allocate space for the functionality data
+	HBufC8* dftext = HBufC8::NewLC(dfsize);
+
+	const TPtr8& dfPtr = dftext->Des();
+
+	// Extract said data from the device driver
+	User::LeaveIfError(Server().iKernelDriver.GetDebugFunctionality((TDes8&)dfPtr));
+
+	// Return data to client
+	aMessage.WriteL(0,dfPtr);
+
+	// Free buffer
+	CleanupStack::PopAndDestroy(dftext);
+
+	aMessage.Complete(KErrNone);
+	}
+
+/**
+Reads memory from a specified thread using the passed parameters. The user 
+should ensure that the TPtr8 that is passed in has size greater than or equal
+to the size of the memory that is trying to be read.
+
+@param aMessage The RMessage2 object should be constructed as follows:
+    * aMessage.Int0() is the thread ID of the target debug app
+    * aMessage.Ptr1() is a TMemoryInfo object which contains the following:
+        * the address of the memory to be read from the target debug thread
+        * the size of the memory block to be read from the target debug thread
+	* the access size to use
+	* the endianess to interpret the data as
+    * aMessage.Ptr2() is the address of the buffer in the debug agent thread 
+      that the data from the target debug app should be written into 
+
+@leave KErrPermissionDenied if client is not attached to the target
+       thread's process,
+       KErrNoMemory if memory could not be allocated,
+       KErrArgument if there are problems with the aMessage object,
+       KErrBadHandle if the thread represented by aMessage.Ptr0() is invalid,
+       an error value from CSecuritySvrSession::ValidateMemoryInfo if checking
+       the memory attributes failed,
+       or another of the system wide error codes
+*/
+void CSecuritySvrSession::ReadMemoryL(const RMessage2& aMessage)
+	{
+	LOG_MSG( "CSecuritySvrSession::ReadMemoryL()\n" );
+
+	//get debug app thread ID
+	TThreadId threadId = ReadTThreadIdL(aMessage, 0);
+
+	CheckAttachedL(threadId, aMessage, ETrue);
+
+	//create and initialise the memory info object
+	TMemoryInfo targetMemory;
+	TPtr8 targetMemoryPtr( (TUint8 *)&targetMemory, sizeof(TMemoryInfo) );
+
+	aMessage.ReadL(1,targetMemoryPtr);
+
+	//check memory info is acceptable
+	ValidateMemoryInfoL(threadId, targetMemory, ETrue);
+
+	RBuf8 data;
+	data.CreateL(targetMemory.iSize);
+	data.CleanupClosePushL();
+
+	//fill buffer with data from target debug thread
+	User::LeaveIfError(Server().iKernelDriver.ReadMemory(threadId, targetMemory.iAddress, targetMemory.iSize, data));
+
+	//attempt to write the data from the target debug thread back to the agent
+	aMessage.WriteL(2, data);
+
+	//delete temporary buffer
+	CleanupStack::PopAndDestroy(&data);
+
+	aMessage.Complete(KErrNone);
+	}
+
+/**
+Writes memory to a specified thread using the passed parameters. 
+
+@param aMessage The RMessage2 object should be constructed as follows:
+    * aMessage.Ptr0() is the thread ID of the target debug app
+    * aMessage.Ptr1() is a TMemoryInfo object which contains the following:
+        * the address of the memory to be written to the target debug thread
+        * the size of the memory block to be written to the target debug thread
+	* the access size to use
+	* the endianess to interpret the data as
+    * aMessage.Ptr2() is the address of the buffer in the debug agent thread 
+      that the data to write to the target debug app should be read from
+
+@leave KErrPermissionDenied if client is not attached (actively) to the target
+       thread's process,
+       KErrNoMemory if memory could not be allocated,
+       KErrArgument if there are problems with the aMessage object,
+       KErrBadHandle if the thread represented by aMessage.Ptr0() is invalid,
+       an error value from CSecuritySvrSession::ValidateMemoryInfo if checking
+       the memory attributes failed,
+       or another of the system wide error codes
+*/
+void CSecuritySvrSession::WriteMemoryL(const RMessage2& aMessage)
+	{
+	LOG_MSG( "CSecuritySvrSession::WriteMemoryL()\n" );
+
+	//get debug app thread ID
+	TThreadId threadId = ReadTThreadIdL(aMessage, 0);
+
+	CheckAttachedL(threadId, aMessage, EFalse);
+
+	//create and initialise the memory info object
+	TMemoryInfo targetMemory;
+	TPtr8 targetMemoryPtr( (TUint8 *)&targetMemory, sizeof(TMemoryInfo) );
+
+	aMessage.ReadL(1,targetMemoryPtr);
+
+	//check memory info is acceptable
+	ValidateMemoryInfoL(threadId, targetMemory, EFalse);
+
+	//create temporary buffer and read data from client
+	RBuf8 data;
+	data.CreateL(targetMemory.iSize);
+	data.CleanupClosePushL();
+	
+	aMessage.ReadL(2, data);
+
+	// what about telling the driver about endianess/access size?
+	User::LeaveIfError(Server().iKernelDriver.WriteMemory(threadId, targetMemory.iAddress, targetMemory.iSize, data));
+
+	//free temporary buffer
+	CleanupStack::PopAndDestroy(&data);
+
+	aMessage.Complete(KErrNone);
+	}
+
+/**
+@internalTechnology
+
+Notes: This call is used to set a thread specific breakpoint. Its input arguments
+are the thread id, address and architecture type of the breakpoint. It returns success
+or failure, and if successful, it sets the TBreakId in the Debug Agent to the 
+breakpoint id by which it can be referenced in future calls to ModifyBreak,ClearBreak and
+BreakInfo.
+
+@param aMessage.Ptr0() - aThreadId is thread id of the target debug process
+@param aMessage.Ptr1() - Address of a TBreakInfo in the Debug Agent
+@param aMessage.Ptr2() - Address of a TBreakId in the Debug Agent
+@leave KErrPermissionDenied if the security check fails.
+ KErrAlreadyExists if there is a breakpoint overlapping the desired address.
+ KErrNotSupported if the architecture type is unrecognised.
+ KErrNoMemory if there is no more memory to complete the operation.
+ KErrArgument if the breakpoint address alignment is unsuitable for the requested
+ breakpoint.
+ KErrOverflow if there are too many breakpoints set.
+*/
+void CSecuritySvrSession::SetBreakL(const RMessage2& aMessage)
+	{
+	LOG_MSG( "CSecuritySvrSession::SetBreakL!()\n" );
+
+	//get debug app thread ID
+	TThreadId threadId = ReadTThreadIdL(aMessage, 0);
+
+	//check that the agent has attached to the target process
+	CheckAttachedL(threadId, aMessage, EFalse);
+
+	//create and initialise the break info object
+	TBreakInfo breakInfo;
+	TPtr8 breakInfoPtr( (TUint8 *)&breakInfo, sizeof(TBreakInfo) );
+
+	aMessage.ReadL(1,breakInfoPtr);
+
+	LOG_MSG4( "CSecuritySvrSession::SetBreakL, threadId=0x%lx, addr=0x%x, mode=%d", 
+			threadId.Id(), breakInfo.iAddress, breakInfo.iArchitectureMode);
+			
+	//set break in target app
+	TBreakId breakId = 0;
+	User::LeaveIfError(Server().iKernelDriver.SetBreak(breakId, threadId, breakInfo.iAddress, breakInfo.iArchitectureMode));
+
+	//attempt to write the break id back to the debug agent
+	WriteDataL(aMessage, 2, &breakId, sizeof(breakId));
+
+	aMessage.Complete(KErrNone);
+	}
+
+/**
+Clears a breakpoint previously set by a SetBreak() call.
+
+@param aMessage.Int0() - TBreakId of the breakpoint to be removed.
+*/
+void CSecuritySvrSession::ClearBreakL(const RMessage2& aMessage)
+	{
+	LOG_MSG( "CSecuritySvrSession::ClearBreakL()\n" );
+
+	const TInt breakId = aMessage.Int0();
+
+	// Check that the breakpoint exists
+	TUint64 objectId;
+	TUint32 address;
+	TArchitectureMode mode;
+	TBool threadSpecific = EFalse;
+
+	User::LeaveIfError(Server().iKernelDriver.BreakInfo(breakId,objectId,address,mode,threadSpecific));
+
+	if(threadSpecific)
+		{
+		// Check that the debug agent is attached to the thread for which the
+		// breakpoint is currently set.
+		LOG_MSG4( "CSecuritySvrSession::ClearBreakL( brkId=%d), addr=0x%x, tId=0x%x", 
+			breakId, address, I64LOW(objectId) );		
+		CheckAttachedL(TThreadId(objectId), aMessage, EFalse);		
+		}
+	else
+		{
+		// Check that the debug agent is attached to the process for which the
+		// breakpoint is currently set.
+		LOG_MSG4( "CSecuritySvrSession::ClearBreakL( brkId=%d), addr=0x%x, pId=0x%x", 
+			breakId, address, I64LOW(objectId) );		
+		CheckAttachedL(TProcessId(objectId), aMessage, EFalse);
+		}
+
+	// Finally clear the breakpoint
+	User::LeaveIfError(Server().iKernelDriver.ClearBreak(breakId));
+
+	aMessage.Complete(KErrNone);
+	}
+
+/**
+@param aMessage.Int0() - Breakpoint Id of interest
+@param aMessage.Ptr1() - Address in Debug Agent to place threadId of the breakpoint
+@param aMessage.Ptr2() - Address in Debug Agent to place address of the breakpoint
+@param aMessage.Ptr3() - Address in Debug Agent to place the architecture mode of the breakpoint
+@leave Any error which may be returned by RSessionBase::SendReceive()
+*/
+void CSecuritySvrSession::BreakInfoL(const RMessage2& aMessage)
+	{
+	const TBreakId breakId = (TBreakId)aMessage.Int0();
+
+	TThreadId threadId;
+	TUint32 address;
+	TArchitectureMode mode;
+	TBool threadSpecific = ETrue;
+
+	TUint64 threadIdData;
+	User::LeaveIfError(Server().iKernelDriver.BreakInfo(breakId,threadIdData,address,mode,threadSpecific));
+
+	if(!threadSpecific)
+		{
+		User::Leave(KErrNotFound);
+		}
+
+	threadId = TThreadId(threadIdData);
+
+	//check that the agent has attached to the target process
+	CheckAttachedL(threadId, aMessage, EFalse);
+
+	// return the threadId
+	WriteDataL(aMessage, 1, &threadId, sizeof(threadId));
+
+	// return the address
+	WriteDataL(aMessage, 2, &address, sizeof(address));
+
+	// return the mode
+	WriteDataL(aMessage, 3, &mode, sizeof(mode));
+
+	aMessage.Complete(KErrNone);
+	}
+
+/**
+@internalTechnology
+
+Modify a previously set breakpoint.
+
+@param aMessage.Int0() - The breakpoint id of the breakpoint to modify
+@param aMessage.Ptr1() - The new Thread Id for the breakpoint
+@param aMessage.Int2() - The new virtual memory address for the breakpoint
+@param aMessage.Int3() - The new architecture mode for the breakpoint
+@return KErrNone if succesful. KErrPermissionDenied if the security check fails.
+ KErrAlreadyExists if there is a breakpoint overlapping the desired address.
+ KErrNotSupported if the architecture type is unrecognised.
+ KErrNoMemory if there is no more memory to complete the operation.
+ KErrArgument if the breakpoint address alignment is unsuitable for the requested
+ breakpoint.
+ KErrOverflow if there are too many breakpoints set.
+*/
+void CSecuritySvrSession::ModifyBreakL(const RMessage2& aMessage)
+	{
+	const TBreakId breakId = (TBreakId)aMessage.Int0();
+	const TThreadId threadId = ReadTThreadIdL(aMessage, 1);
+	const TUint32 address = aMessage.Int2();
+	const TArchitectureMode mode = (TArchitectureMode)aMessage.Int3();
+
+	// Get information on the breakpoint to check the security status
+	TUint64 checkThreadId;
+	TUint32 checkAddress;
+	TArchitectureMode checkMode;
+	TBool threadSpecific;
+
+	User::LeaveIfError(Server().iKernelDriver.BreakInfo(breakId,checkThreadId,checkAddress,checkMode,threadSpecific));
+
+	LOG_MSG4( "CSecuritySvrSession::ModifyBreakL(brkId=%d) tId=0x%x, addr=0x%x", 
+			breakId, I64LOW(threadId.Id()), address );
+			
+	// Security check that the thread Id is associated with the debug agent
+
+	//check that the agent has attached to the target process
+	CheckAttachedL(TThreadId(checkThreadId), aMessage, EFalse);
+
+	// now check that the thread Id which is being set is permitted
+	//check that the agent has attached to the target process
+	CheckAttachedL(threadId, aMessage, EFalse);
+
+	User::LeaveIfError(Server().iKernelDriver.ModifyBreak(breakId,threadId,address,mode));
+
+	aMessage.Complete(KErrNone);
+	}
+
+/**
+@internalTechnology
+
+Notes: This call is used to set a process wide breakpoint. Its input arguments
+are the process id, address and architecture type of the breakpoint. It returns success
+or failure, and if successful, it sets the TBreakId in the Debug Agent to the 
+breakpoint id by which it can be referenced in future calls to ModifyBreak,ClearBreak and
+BreakInfo.
+
+@param aMessage.Ptr0() - aProcessId is process id of the target debug process
+@param aMessage.Ptr1() - Address of a TBreakInfo in the Debug Agent
+@param aMessage.Ptr2() - Address of a TBreakId in the Debug Agent
+@leave KErrPermissionDenied if the security check fails.
+ KErrAlreadyExists if there is a breakpoint overlapping the desired address.
+ KErrNotSupported if the architecture type is unrecognised.
+ KErrNoMemory if there is no more memory to complete the operation.
+ KErrArgument if the breakpoint address alignment is unsuitable for the requested
+ breakpoint.
+ KErrOverflow if there are too many breakpoints set.
+*/
+void CSecuritySvrSession::SetProcessBreakL(const RMessage2& aMessage)
+	{
+	LOG_MSG( "CSecuritySvrSession::SetProcessBreakL()\n" );
+
+	//get debug app thread ID
+	TProcessId procId = ReadTProcessIdL(aMessage, 0);
+
+	//check that the agent has attached to the target process
+	CheckAttachedL(procId, aMessage, EFalse);
+
+	//create and initialise the memory info object
+	TBreakInfo breakInfo;
+	TPtr8 breakInfoPtr( (TUint8 *)&breakInfo, sizeof(TBreakInfo) );
+
+	aMessage.ReadL(1,breakInfoPtr);
+
+	LOG_MSG4( "CSecuritySvrSession::SetProcessBreakL pId=0x%x, addr=0x%x, mode=%d ", 
+			I64LOW(procId.Id()), breakInfo.iAddress, breakInfo.iArchitectureMode );
+
+	//set break in target app
+	TBreakId breakId = 0;
+	User::LeaveIfError(Server().iKernelDriver.SetProcessBreak(breakId, procId, breakInfo.iAddress, breakInfo.iArchitectureMode));
+
+	//attempt to write the break id back to the debug agent
+	WriteDataL(aMessage, 2, &breakId, sizeof(breakId));
+
+	aMessage.Complete(KErrNone);
+	}
+
+/**
+@internalTechnology
+
+Modify a previously set process breakpoint.
+
+@param aMessage.Int0() - The breakpoint id of the breakpoint to modify
+@param aMessage.Ptr1() - The new Process Id for the breakpoint
+@param aMessage.Int2() - The new virtual memory address for the breakpoint
+@param aMessage.Int3() - The new architecture mode for the breakpoint
+@return KErrNone if succesful. KErrPermissionDenied if the security check fails.
+ KErrAlreadyExists if there is a breakpoint overlapping the desired address.
+ KErrNotSupported if the architecture type is unrecognised.
+ KErrNoMemory if there is no more memory to complete the operation.
+ KErrArgument if the breakpoint address alignment is unsuitable for the requested
+ breakpoint.
+ KErrOverflow if there are too many breakpoints set.
+*/
+void CSecuritySvrSession::ModifyProcessBreakL(const RMessage2& aMessage)
+	{
+	const TBreakId breakId = (TBreakId)aMessage.Int0();
+	const TProcessId processId = ReadTProcessIdL(aMessage, 1);
+	const TUint32 address = aMessage.Int2();
+	const TArchitectureMode mode = (TArchitectureMode)aMessage.Int3();
+
+	// Get information on the breakpoint to check the security status
+	TUint64 checkProcessId;
+	TUint32 checkAddress;
+	TArchitectureMode checkMode;
+	TBool threadSpecific;
+
+	User::LeaveIfError(Server().iKernelDriver.BreakInfo(breakId,checkProcessId,checkAddress,checkMode,threadSpecific));
+
+	LOG_MSG4( "CSecuritySvrSession::ModifyProcessBreakL(brkId=%d) pId=0x%x, addr=0x%x", 
+			breakId, I64LOW(processId.Id()), address );
+
+
+	// Security check that the process Id is associated with the debug agent
+
+	//check that the agent has attached to the target process
+	CheckAttachedL(TProcessId(checkProcessId), aMessage, EFalse);
+
+	// now check that the process Id which is being set is permitted
+	//check that the agent has attached to the target process
+	CheckAttachedL(processId, aMessage, EFalse);
+
+	User::LeaveIfError(Server().iKernelDriver.ModifyProcessBreak(breakId,processId,address,mode));
+
+	aMessage.Complete(KErrNone);
+	}
+
+/**
+@param aMessage.Int0() - Breakpoint Id of interest
+@param aMessage.Ptr1() - Address in Debug Agent to place process Id of the breakpoint
+@param aMessage.Ptr2() - Address in Debug Agent to place address of the breakpoint
+@param aMessage.Ptr3() - Address in Debug Agent to place the architecture mode of the breakpoint
+@leave Any error which may be returned by RSessionBase::SendReceive()
+*/
+void CSecuritySvrSession::ProcessBreakInfoL(const RMessage2& aMessage)
+	{
+	const TBreakId breakId = (TBreakId)aMessage.Int0();
+
+	TProcessId procId;
+	TUint32 address;
+	TArchitectureMode mode;
+	TBool threadSpecific;
+
+	TUint64 procIdData;
+	User::LeaveIfError(Server().iKernelDriver.BreakInfo(breakId,procIdData,address,mode,threadSpecific));
+	if(threadSpecific)
+		{
+		User::Leave(KErrNotFound);
+		}
+	procId = TProcessId(procIdData);
+
+	//check that the agent has attached to the target process
+	CheckAttachedL(procId, aMessage, EFalse);
+
+	// return the processId
+	WriteDataL(aMessage, 1, &procId, sizeof(procId));
+
+	// return the address
+	WriteDataL(aMessage, 2, &address, sizeof(address));
+
+	// return the mode
+	WriteDataL(aMessage, 3, &mode, sizeof(mode));
+
+	aMessage.Complete(KErrNone);
+	}
+
+/**
+Read register values.
+
+@param aMessage should contain:
+        * at offset 0 a pointer to the thread ID of the target thread
+        * at offset 1 a descriptor representing an array of TRegisterInfo 
+          register IDs
+        * at offset 2 a descriptor representing an array into which TRegister 
+          register values will be written
+        * at offset 3 a descriptor representing an array into which TUint8 
+          register flags will be written
+
+@leave KErrArgument if the max length of the array at offset 1 is not a 
+       multiple of sizeof(TRegisterInfo), if the max length of the array 
+       at offset 2 is not a multiple of sizeof(TRegister), if the max 
+       length of the array at offset 3 is not a multiple of sizeof(TUint8), if
+       any of the descriptors have max length of 0, or if the three 
+       descriptors do not represent the same number of registers,
+       KErrNoMemory if there is insufficient memory,
+       KErrDied, if the thread with thread ID aThreadId is dead
+*/
+void CSecuritySvrSession::ReadRegistersL(const RMessage2& aMessage)
+	{
+	LOG_MSG( "CSecuritySvrSession::ReadRegistersL()\n" );
+
+	const TThreadId threadId = ReadTThreadIdL(aMessage, 0);
+
+	//check the agent is attached to the thread
+	CheckAttachedL(threadId, aMessage, ETrue);
+
+	//number of registers being requested
+	TUint32 numberOfRegisters;
+
+	//check length of descriptors is acceptable
+	ValidateRegisterBuffersL(aMessage, numberOfRegisters);
+
+	// Passed data will be saved in this descriptor.
+	RBuf8 ids;
+	ids.CreateL(numberOfRegisters * sizeof(TRegisterInfo));
+	// Do the right cleanup if anything subsequently goes wrong
+	ids.CleanupClosePushL();
+	
+	//read the data from the client thread
+	aMessage.ReadL(1, ids);
+
+	//create buffer to fill with data from target debug thread
+	HBufC8 *data = HBufC8::NewLC(aMessage.GetDesMaxLength(2));
+	TPtr8 values(data->Des());   
+	
+	HBufC8 *flagsData = HBufC8::NewLC(numberOfRegisters * sizeof(TUint8));
+	TPtr8 flags(flagsData->Des());   
+	
+	//get register info and return relevant parts back to agent
+	User::LeaveIfError(Server().iKernelDriver.ReadRegisters(threadId, ids, values, flags));
+	aMessage.WriteL(2, values);
+	aMessage.WriteL(3, flags);
+	
+	//delete temporary buffers and return status
+	CleanupStack::PopAndDestroy(flagsData);
+	CleanupStack::PopAndDestroy(data);
+	CleanupStack::PopAndDestroy(&ids);
+
+	aMessage.Complete(KErrNone);
+	}
+
+/**
+Write register values.
+
+@param aMessage should contain:
+        * at offset 0 a pointer to the thread ID of the target thread
+        * at offset 1 a descriptor representing an array of TRegisterInfo 
+          register IDs
+        * at offset 2 a descriptor representing an array of TRegister register 
+          values
+        * at offset 3 a descriptor representing an array into which TUint8 
+          register flags will be written
+
+@leave KErrArgument if the max length of the array at offset 1 is not a 
+       multiple of sizeof(TRegisterInfo), if the max length of the array 
+       at offset 2 is not a multiple of sizeof(TRegister), if the max 
+       length of the array at offset 3 is not a multiple of sizeof(TUint8), if
+       any of the descriptors have max length of 0, or if the three 
+       descriptors do not represent the same number of registers,
+       KErrNoMemory if there is insufficient memory,
+       KErrDied, if the thread with thread ID aThreadId is dead
+*/
+void CSecuritySvrSession::WriteRegistersL(const RMessage2& aMessage)
+	{
+	LOG_MSG( "CSecuritySvrSession::WriteRegistersL()\n" );
+
+	const TThreadId threadId = ReadTThreadIdL(aMessage, 0);
+
+	CheckAttachedL(threadId, aMessage, EFalse);
+
+	//number of registers attempting to set
+	TUint32 numberOfRegisters;
+
+	//check length of descriptors is acceptable
+	ValidateRegisterBuffersL(aMessage, numberOfRegisters);
+
+	// Passed register ids will be saved in this descriptor.
+	RBuf8 ids;
+
+	//allocate buffer
+	ids.CreateL(numberOfRegisters * sizeof(TRegisterInfo));
+
+	// Do the right cleanup if anything subsequently goes wrong
+	ids.CleanupClosePushL();
+
+	//read the data from the client thread
+	aMessage.ReadL(1, ids);
+
+	// Passed register values will be saved in this descriptor.
+	RBuf8 values;
+
+	//allocate buffer
+	values.CreateL(aMessage.GetDesMaxLength(2));
+	// Do the right cleanup if anything subsequently goes wrong
+	values.CleanupClosePushL();
+	//read the data from the client thread
+	aMessage.ReadL(2,values);
+
+	HBufC8 *flagsData = HBufC8::NewLC(numberOfRegisters*sizeof(TUint8));
+	TPtr8 flags(flagsData->Des());
+
+	//get register info and return relevant parts back to agent
+	User::LeaveIfError(Server().iKernelDriver.WriteRegisters(threadId, ids, values, flags));
+
+	//write flags data back
+	aMessage.WriteL(3, flags);
+
+	CleanupStack::PopAndDestroy(flagsData);
+	CleanupStack::PopAndDestroy(&values);
+	CleanupStack::PopAndDestroy(&ids);
+
+	aMessage.Complete(KErrNone);
+	}
+
+/**
+Processes an attach request from a debug agent. Gets the target debug
+processes' original FileName as an argument. The method sets completion
+status of the aMessage argument to KErrNone if successfully attached and to
+another of the system wide error codes if there were problems.
+
+@param aMessage contains:
+       * a boolean at offset 0 which indicates whether the agent wishes to
+       attach passively
+       * a buffer at offset 1 which contains the FileName
+       of the target debug process.
+*/
+void CSecuritySvrSession::AttachProcessL(const RMessage2& aMessage)
+	{
+	LOG_MSG( "CSecuritySvrSession::AttachProcessL()\n" );
+
+	const TBool passive = aMessage.Int0();
+
+	TInt deslen = aMessage.GetDesLengthL(1);
+
+	// Passed data will be saved in this descriptor.
+	RBuf processName;
+
+	// Max length set to the value of "deslen", but current length is zero
+	processName.CreateL(deslen);
+
+	// Do the right cleanup if anything subsequently goes wrong
+	processName.CleanupClosePushL();
+
+	// Copy the client's descriptor data into our buffer.
+	aMessage.ReadL(1,processName);
+
+	//
+	// Security Check
+	//
+	// It is not permitted to debug the debug security server!
+	//
+	// get the secure id of the executable
+	TUid secureId(TUid::Null());
+	GetSecureIdL(processName, secureId);
+	if (KUidDebugSecurityServer.iUid == secureId.iUid)
+		{
+		// The debug agent has requested to debug the Debug Security Server
+		// This is either an error, or an attempt to breach security. We
+		// therefore refuse to agree to this request, and return KErrPermissionDenied
+		LOG_MSG("Debug Agent attempted to debug the Debug Security Server");
+		User::Leave(KErrPermissionDenied);
+		}
+
+	// Check the OEM Debug token capabilities 
+	GetDebugAgentOEMTokenCapsL();
+	
+	// Get the Security info via rlibrary::getinfo
+	RLibrary::TInfo info;
+	TPckg<RLibrary::TInfo> infoBuf(info);
+
+	TInt err = RLibrary::GetInfo(processName, infoBuf);
+	if (err != KErrNone)
+		{
+		LOG_MSG2("Cannot parse the target executable header, err=%d", err);
+		// Could not read the header for this executable :-(
+		CleanupStack::PopAndDestroy(&processName);
+		aMessage.Complete(err);
+		return;
+		}
+	
+	// Special case for AllFiles - OEM Debug tokens MUST have
+	// AllFiles, as this is what allows them to read contents
+	// of other executables.
+	TBool checkDebuggable = ETrue;
+
+	// Does an OEM Debug Token permit debug where it would normally not be
+	// permitted?
+	if ( Server().OEMTokenPermitsDebugL(iOEMDebugCapabilities, info.iSecurityInfo.iCaps) )
+		{
+		// OEM Debug token is valid and has sufficient capabilities
+		LOG_MSG("CSecuritySvrSession::AttachProcessL() - Debug Agent has sufficient capabilites based on OEM Debug Token");	
+		
+		checkDebuggable = EFalse;
+		}
+
+	if (checkDebuggable)
+		{
+		// OEM Debug token (if any), does not confer sufficient capabilities to
+		// debug the specified target executable. Therefore debugging can only
+		// be permitted if the target executable itself has been built as 'Debuggable'
+		LOG_MSG("CSecuritySvrSession::AttachProcessL() - Debug Agent has insufficient capabilites based on OEM Debug Token");	
+
+		IsDebuggableL(processName);
+		}
+
+	User::LeaveIfError(Server().AttachProcessL(processName, iDebugAgentProcessId, passive));
+
+	// Inform the kernel driver about the attachment, so that it
+	// can track per-agent data about the process.
+	RBuf8 processName8;
+
+	processName8.CreateL(deslen);
+
+	processName8.CleanupClosePushL();
+
+	processName8.Copy(processName);
+
+	User::LeaveIfError(Server().iKernelDriver.AttachProcess(processName8, iDebugAgentProcessId.Id()));
+
+	// Create an Active Object to handle asynchronous calls to GetEvent
+	CSecuritySvrAsync* handler = CSecuritySvrAsync::NewL(this,processName8,iDebugAgentProcessId);
+
+	err = iAsyncHandlers.Insert(handler,0);
+	if (err != KErrNone)
+		{
+		// If we don't have an asynchronous handler, we should detach
+		// the driver as well.
+		Server().iKernelDriver.DetachProcess(processName8,iDebugAgentProcessId.Id());
+		Server().DetachProcess(processName, iDebugAgentProcessId);
+		// The DSS should NEVER panic itself. If the above calls fail, so be it we will attempt to limp on
+		}
+
+	User::LeaveIfError(err);
+
+	CleanupStack::PopAndDestroy(&processName8);
+
+	CleanupStack::PopAndDestroy(&processName);
+
+	aMessage.Complete(KErrNone);
+	}
+
+
+/**
+Processes an attach request from a debug agent from all processes. 
+The method sets completion status of the aMessage argument to KErrNone 
+if successfully attached and to another of the system wide error codes 
+if there were problems.
+
+@param aMessage contains no data
+*/
+void CSecuritySvrSession::AttachAllL(const RMessage2& aMessage)
+	{
+	LOG_MSG( "CSecuritySvrSession::AttachAllL()\n" );
+
+
+	// Run the OEM Debug token, if run ok then sets iOEMDebugCapabilities
+	GetDebugAgentOEMTokenCapsL();
+
+	// Debug token must have All caps to use AttachToAll
+	TCapabilitySet allCaps;
+	allCaps.SetAllSupported();
+	if (!Server().OEMTokenPermitsDebugL(iOEMDebugCapabilities, allCaps))
+		{
+		LOG_MSG("Client's OEM token doesn't have capability ALL required for AttachAll()");
+		User::Leave(KErrPermissionDenied);
+		}
+
+
+	User::LeaveIfError(Server().AttachProcessL(_L("*"), iDebugAgentProcessId, EFalse));
+
+    TBuf8<1> KStar8=_L8("*");
+
+    User::LeaveIfError(Server().iKernelDriver.AttachProcess(KStar8, iDebugAgentProcessId.Id()));
+
+    // Create an Active Object to handle asynchronous calls to GetAllEvent
+    CSecuritySvrAsync* handler = CSecuritySvrAsync::NewL(this,KStar8,iDebugAgentProcessId);    
+    TInt err = iAsyncHandlers.Insert(handler,0);
+    if (err != KErrNone)
+        {
+        // If we don't have an asynchronous handler, we should detach
+        // the driver as well.
+        Server().iKernelDriver.DetachProcess(KStar8,iDebugAgentProcessId.Id());
+        Server().DetachProcess(_L("*"), iDebugAgentProcessId);
+        }
+
+    User::LeaveIfError(err);
+
+	aMessage.Complete(KErrNone);   
+	}
+
+
+/**
+Reads the OEM Debug Token associated with the debug agent if any. The OEM Debug Token
+allows the Debug Agent to debug certain executables which have not been built as
+'Debuggable'.
+
+This works as follows: The OEM Debug Token is an executable with a special name
+of the form "OEMDebug_<DA_SID>.exe" where <DA_SID> is the Secure ID of the Debug Agent
+in hexadecimal. For example: "OEMDebug_F123ABCD.exe" would be a valid name. This token executable
+must be signed with 'AllFiles' + X, where X is the set of PlatSec capabilities that are
+possessed by the target executable to be debugged.
+
+This function reads the capabilities possessed by the token by creating a process based
+on the executable, and reading the TSecurityInfo associated with the process. This ensures
+that the loader has validated the token has not been tampered with and that the security
+information is valid.
+
+The security information is then stored for future use as member data in iOEMDebugCapabilities.
+
+Leaves if there is an error, otherwise simply fills in the capabilities
+in iOEMDebugCapabilities.
+
+It is not an error for the OEM Debug token not to exist. In this case, the function simply returns.
+*/
+void CSecuritySvrSession::GetDebugAgentOEMTokenCapsL(void)
+	{
+	if (iOEMDebugCapabilities.HasCapability(ECapabilityAllFiles))
+		{
+		// Then we've already read the caps - wasteful to read them again
+		return;
+		}
+
+	// Obtain the security info about the debug agent process
+	//get the debug agent's process
+	RProcess debugAgentProcess;
+
+	CleanupClosePushL(debugAgentProcess);
+
+	debugAgentProcess.Open(iDebugAgentProcessId);
+
+	// We have now obtained a process handle based on the token executable, so we can check its security properties.
+	TSecurityInfo secInfo(debugAgentProcess);
+
+	// Compute the name of the OEM debug token based on the SID of the debug agent
+	_LIT(KDSSOEMDebugTokenPrefix,"OEMDebug_");
+	_LIT(KDSSOEMDebugTokenAppendFmt,"%08X.exe");
+
+	RBuf agentTokenName;
+	agentTokenName.CreateL(KDSSOEMDebugTokenPrefix().Size()+8+1);	// allow space for SID+null terminator
+	agentTokenName.CleanupClosePushL();
+
+	agentTokenName.SetLength(0);
+
+	// Add OEMDebug_
+	agentTokenName.Append(KDSSOEMDebugTokenPrefix());
+
+	// Add debug agent Secure ID
+	agentTokenName.AppendFormat(KDSSOEMDebugTokenAppendFmt,secInfo.iSecureId.iId);
+	
+	// just log the token name for the moment.
+	RBuf8 agentTokenName8;
+
+	agentTokenName8.CreateL(agentTokenName.Length()+1);
+
+	agentTokenName8.CleanupClosePushL();
+
+	agentTokenName8.Copy(agentTokenName);
+
+	agentTokenName8.Append(TChar(0));
+
+	LOG_MSG2("CSecuritySvrSession::GetDebugAgentOEMTokenCapsL() - OEM Debug Token Name is %s",agentTokenName8.Ptr()); 
+
+	// Cleanup
+	CleanupStack::PopAndDestroy(&agentTokenName8);
+
+	// Now locate and start the executable...
+	RProcess agentToken;
+	TInt err = agentToken.Create(agentTokenName, KNullDesC);
+	if (KErrNone != err)
+		{
+		// Failed to create a process based on the token, just give up
+		LOG_MSG2("CSecuritySvrSession::GetDebugAgentOEMTokenCapsL() - Could not create process based on token due to err 0x%8x\n",err);
+		
+		// Cleanup remaining items from the stack
+		CleanupStack::PopAndDestroy(&agentTokenName);
+
+		CleanupStack::PopAndDestroy(&debugAgentProcess);
+		return;
+		}
+
+	// Synchronise with the process to make sure it hasn't died straight away
+	TRequestStatus stat;
+	agentToken.Rendezvous(stat);
+	if (stat != KRequestPending)
+		{
+		// logon failed - agentToken is not yet running, so cannot have terminated
+		agentToken.Kill(0);             // Abort startup
+		}
+
+	// store the OEM Debug Token security data 
+	TSecurityInfo agentSecInfo(agentToken);
+
+	// Note capabilities for future use
+	iOEMDebugCapabilities=agentSecInfo.iCaps;
+	
+	// resume the token. It _should_ just exit, but we don't really care.
+	agentToken.Resume();
+
+	// Wait to synchronise with agentToken - if it dies in the meantime, it
+	// also gets completed
+	User::WaitForRequest(stat);
+
+	// Just close the handle to it again.
+	agentToken.Close();
+
+	// Cleanup remaining items from the stack
+	CleanupStack::PopAndDestroy(&agentTokenName);
+
+	CleanupStack::PopAndDestroy(&debugAgentProcess);
+
+	}
+
+/**
+  Checks whether the file passed in as aExecutable is XIP or not
+
+  @param aExecutable file to check
+  @return ETrue if the file is XIP, EFalse otherwise
+  */
+TBool CSecuritySvrSession::IsExecutableXipL(RFile& aExecutable)
+	{
+	TUint atts;
+	User::LeaveIfError(aExecutable.Att(atts));
+
+	return atts & KEntryAttXIP;
+	}
+
+/**
+  Gets access to the symbian crash partition for crash access operation.
+  */
+void CSecuritySvrSession::ConnectCrashPartitionL (void)
+	{
+	LOG_MSG("CSecuritySvrSession::ConnectCrashPartitionL()");
+	
+	TBool changed;
+	TInt error = KErrNone;
+	TInt i=0;
+	
+	//Intialising to EFalse
+	iCrashConnected = EFalse;
+	
+	TPckg<TLocalDriveCapsV2> capsBuf(iCaps);
+	
+	//check for the symbian crash partition
+	for (i=0; i<KMaxLocalDrives; i++)
+		{
+		error = iLocalDrive.Connect (i, changed);
+		if ( error == KErrNone)
+			{
+			error = iLocalDrive.Caps(capsBuf);
+			if ( error != KErrNone)
+				{
+				//continue if not found
+				continue;
+				}
+			if ( iCaps.iPartitionType == (TUint16)KPartitionTypeSymbianCrashLog)
+				{				
+				LOG_MSG2("Found Symbian crash log partition on drive: %d",i);
+				iCrashConnected = ETrue;
+				break;
+				}			
+			}
+		}
+	if ( i == KMaxLocalDrives)
+		{
+		LOG_MSG("No crash log partition found with valid crash log signature found.  Exiting...");
+		User::Leave (KErrNotFound);
+		}
+
+	// Nand Flash not currently supported.
+	if (iCaps.iType == EMediaNANDFlash)
+		{
+		LOG_MSG( "CSecuritySvrSession::ConnectCrashPartitionL()  Nand Flash not currently supported\n" );
+		User::Leave (KErrNotSupported);
+		}
+	}
+/** Checks that aHeaderData contains enough data to cast it to the
+  appropriate header type.
+
+  @param aHeaderData buffer containing header data read from a file
+  @param aXip boolean indicating whether the header data is for an XIP image
+
+  @return ETrue if enough data in buffer, EFalse otherwise
+  */
+TBool CSecuritySvrSession::CheckSufficientData(const TDesC8& aHeaderData, const TBool aXip) const
+	{
+	TUint minimumHeaderSize = aXip ? sizeof(TRomImageHeader) : sizeof(E32ImageHeaderV);
+	return (aHeaderData.Length() >= minimumHeaderSize);
+	}
+
+/**
+  Opens a file handle to aFileName using aFileHandle
+  @param aFileName file to open handle to
+  @param aFs file system to use to open the handle
+  @param aFileHandle file handle to open
+
+  @leave one of the system wide error codes
+  */
+void CSecuritySvrSession::OpenFileHandleL(const TDesC& aFileName, RFs& aFs, RFile& aFileHandle)
+	{
+	TInt err = aFileHandle.Open(aFs, aFileName, EFileRead | EFileShareReadersOnly);
+	if (err != KErrNone)
+		{
+		// Could not open the file for reading
+		LOG_MSG("CSecuritySvrSession::OpenFileHandleL - Failed to open executable\n");
+
+		User::Leave(err);
+		}
+	}
+
+/**
+  Checks whether an executable has the debug bit set
+
+  @param aHeaderData buffer containing the header of the executable
+  @param aXip indication of whether the executable is XIP or not
+
+  @return ETrue if debug bit is set, EFalse otherwise
+  */
+TBool CSecuritySvrSession::IsDebugBitSet(const TDesC8& aHeaderData, const TBool aXip)
+	{
+	if(!CheckSufficientData(aHeaderData, aXip))
+		{
+		return EFalse;
+		}
+
+	if (aXip)
+		{
+		TRomImageHeader* hdr = (TRomImageHeader*)aHeaderData.Ptr();
+		return (hdr->iFlags & KRomImageDebuggable);
+		}
+	else
+		{
+		// it is an epoc32 image
+		E32ImageHeaderV* hdr = (E32ImageHeaderV*)aHeaderData.Ptr();
+		return (hdr->iFlags & KImageDebuggable);
+		}
+	}
+
+/**
+Determines whether a particular executable is marked as 'debuggable'
+
+Notes:
+This function is currently hard coded to understand the format of e32 and
+TRomImage file headers. Ideally this will be replaced by a call to RLibrary::GetInfo
+which can return the 'debuggable' information. Unfortunately, this call currently
+does not provide the information for XIP executables :-(
+
+@leave KErrPermissionDenied if the debug bit is not set, or one of the other
+system wide error codes
+*/
+void CSecuritySvrSession::IsDebuggableL(const TDesC& aFileName)
+	{
+#ifndef IGNORE_DEBUGGABLE_BIT
+
+	RFs fs;
+	User::LeaveIfError(fs.Connect());
+	CleanupClosePushL(fs);
+
+	RFile targetExe;
+	OpenFileHandleL(aFileName, fs, targetExe);
+	CleanupClosePushL(targetExe);
+
+	// Read in the entire header
+	RBuf8 e32HdrBuf;
+	e32HdrBuf.CreateL(RLibrary::KRequiredImageHeaderSize);
+	e32HdrBuf.CleanupClosePushL();
+
+	// Read the entire header as far as possible
+	TInt err = targetExe.Read(e32HdrBuf);
+	if (err != KErrNone)
+		{
+		// Could not read the file 
+		LOG_MSG("CSecuritySvrSession::IsDebuggableL - Failed to read executable\n");
+
+		User::Leave(err);
+		}
+
+	if(!CheckSufficientData(e32HdrBuf, IsExecutableXipL(targetExe)))
+		{
+		User::Leave(KErrGeneral);
+		}
+
+	if(! IsDebugBitSet(e32HdrBuf, IsExecutableXipL(targetExe)))
+		{
+		User::Leave(KErrPermissionDenied);
+		}
+	CleanupStack::PopAndDestroy(3, &fs);
+
+#else
+	LOG_MSG("CSecuritySvrSession::IsDebuggableL() Debuggable bit temporarily ignored!!!");
+#endif
+	}
+
+/**
+Processes a detach request from a debug agent. Gets the target debug
+processes' original FileName as an argument. The method sets completion
+status of the aMessage argument to KErrNone if successfully detached and to
+another of the system wide error codes if there were problems.
+
+@param aMessage contains:
+       * a buffer at offset 0 which contains the FileName
+       of the target debug process.
+*/
+void CSecuritySvrSession::DetachProcessL(const RMessage2& aMessage)
+	{
+	LOG_MSG( "CSecuritySvrSession::DetachProcessL()\n" );
+
+	TInt deslen = aMessage.GetDesLengthL(0);
+	// Passed data will be saved in this descriptor.
+	RBuf processName;
+
+	// Max length set to the value of "deslen", but current length is zero
+	processName.CreateL(deslen);
+
+	// Do the right cleanup if anything subsequently goes wrong
+	processName.CleanupClosePushL();
+
+	// Copy the client's descriptor data into our buffer.
+	aMessage.ReadL(0,processName);
+
+	User::LeaveIfError(Server().DetachProcess(processName, iDebugAgentProcessId));
+
+	// Inform the kernel driver about the detachment, so that
+	// it can stop tracking per-agent data for the debugged process.
+	RBuf8 processName8;
+
+	processName8.CreateL(deslen);
+
+	processName8.CleanupClosePushL();
+
+	processName8.Copy(processName);
+
+	// Remove the Asynchronous Object associated with this process
+	for(TInt i=0; i<iAsyncHandlers.Count(); i++)
+		{
+		if (processName8.Compare(iAsyncHandlers[i]->ProcessName()) == 0)
+			{
+			delete iAsyncHandlers[i];
+			iAsyncHandlers.Remove(i);
+
+			break;
+			}
+		}
+	
+	// Inform the driver that we are no longer attached to this process
+	User::LeaveIfError(Server().iKernelDriver.DetachProcess(processName8,iDebugAgentProcessId.Id()));
+	
+	CleanupStack::PopAndDestroy(&processName8);
+	CleanupStack::PopAndDestroy(&processName);
+
+	aMessage.Complete(KErrNone);
+	}
+
+/**
+Processes a DetachAll request from a debug agent.
+The method sets completion status of the aMessage argument to 
+KErrNone if successfully detached and to
+another of the system wide error codes if there were problems.
+
+@param aMessage contains:
+       * a buffer at offset 0 which contains the FileName
+       of the target debug process.
+*/
+void CSecuritySvrSession::DetachAllL(const RMessage2& aMessage)
+	{
+	LOG_MSG( "CSecuritySvrSession::DetachAllL()" );
+
+	User::LeaveIfError(Server().DetachProcess(_L("*"), iDebugAgentProcessId));
+
+	TBuf8<1> KStar8=_L8("*");
+    
+	TBool found = EFalse;
+
+	// Remove the Asynchronous Object associated with the AttachAll, not the rest
+	for(TInt i=0; i<iAsyncHandlers.Count(); i++)
+		{
+		if (iAsyncHandlers[i]->ProcessName().Compare(KStar8) == 0)
+			{
+			delete iAsyncHandlers[i];
+			iAsyncHandlers.Remove(i);
+			User::LeaveIfError(Server().iKernelDriver.DetachProcess(KStar8,iDebugAgentProcessId.Id()));
+			found = ETrue;
+			break;
+			}
+		}
+
+	if( !found )
+		{
+		LOG_MSG2( "CSecuritySvrSession::DetachAllL() : Did not find the asynch handler for agent 0x%lx",
+				iDebugAgentProcessId.Id() );
+		User::Leave(KErrNotFound);
+		}
+
+	aMessage.Complete(KErrNone);
+	}
+
+/**
+@param aMessage The RMessage2 object is expected to contain:
+  * aMessage.Int0() - TDes8 Containing the process name.
+  * aMessage.Int1() - Address of TPtr8 containing TEventInfo
+
+*/
+void CSecuritySvrSession::GetEventL(const RMessage2& aMessage)
+	{
+	LOG_MSG( "CSecuritySvrSession::GetEventL()\n" );
+
+	// Local descriptor to contain target process name
+	TInt deslen = aMessage.GetDesLengthL(0);
+
+	RBuf processName;
+
+	processName.CreateL(deslen);
+	
+	processName.CleanupClosePushL();
+
+	// Read the target process name into processName
+	aMessage.ReadL(0,processName);
+
+	// Check if debug agent is attached to process
+	if(!Server().CheckAttachedProcess(processName, aMessage, EFalse))
+		{
+		LOG_MSG("CSecuritySvrSession::GetEventL() - Not attached to this process\n");
+
+		// Debug Agent is not attached at all to the requested process
+		User::Leave(KErrPermissionDenied);
+		}
+
+	// Identify which process is being debugged, so that
+	// we can locate the appropriate active object handler.
+	RBuf8 processName8;
+
+	processName8.CreateL(processName.Length());
+
+	processName8.CleanupClosePushL();
+
+	processName8.Copy(processName);
+
+	// Find the Asynchronous Object associated with this process,
+	// as it is permissible to have an outstanding GetEvent call
+	// for each attached process.
+	TBool foundHandler = EFalse;
+	for(TInt i=0; i<iAsyncHandlers.Count(); i++)
+		{
+		if (processName8.Compare(iAsyncHandlers[i]->ProcessName()) == 0)
+			{
+			iAsyncHandlers[i]->GetEvent(aMessage);
+			foundHandler = ETrue;
+			break;
+			}
+		}
+
+	if (foundHandler == EFalse)
+		{
+		// could not find an async handler object. Report the problem.
+		LOG_MSG("CSecuritySvrSessionL - Could not find a handler object\n");
+		User::Leave(KErrNotFound);
+		}
+
+	// Actually make the driver call, passing in the agent Id
+	// so that the driver knows which per-agent event queue
+	// to interrogate to retrieve the latest event.
+	CleanupStack::PopAndDestroy(&processName8);
+	CleanupStack::PopAndDestroy(&processName);
+	}
+
+/**
+Cancels a pre-issued GetEvent call for a specific debugged process.
+
+@param aMessage.Int0() - TDes8 containing aProcessName
+*/
+void CSecuritySvrSession::CancelGetEventL(const RMessage2& aMessage)
+	{
+	LOG_MSG( "CSecuritySvrSession::CancelGetEventL()\n" );
+
+	// Local descriptor to contain target process name
+	TInt deslen = aMessage.GetDesLengthL(0);
+
+	RBuf processName;
+
+	processName.CreateL(deslen);
+
+	processName.CleanupClosePushL();
+
+	// Read the target process name into processName
+	aMessage.ReadL(0,processName,0);
+
+	// Debug Agent is not an active debugger. Check if the DA is passively attached
+	if(!Server().CheckAttachedProcess(processName, aMessage, EFalse))
+		{
+		// Debug Agent is not attached at all to the requested process
+		User::Leave(KErrPermissionDenied);
+		}
+
+	// Identify the appropriate active object associate
+	// with this process.
+	RBuf8 processName8;
+
+	processName8.CreateL(processName.Length());
+
+	processName8.CleanupClosePushL();
+
+	processName8.Copy(processName);
+
+	// Find the Asynchronous Object associated with this process
+	TBool foundHandler = EFalse;
+	for(TInt i=0; i<iAsyncHandlers.Count(); i++)
+		{
+		if (processName8.Compare(iAsyncHandlers[i]->ProcessName()) == 0)
+			{
+
+			// Found the AO handler, so cancel the outstanding getevent call.
+			iAsyncHandlers[i]->Cancel();
+			foundHandler = ETrue;
+			break;
+			}
+		}
+
+	if(!foundHandler)
+		{
+		// We could not found a handler, so report the problem to the debug agent
+		User::Leave(KErrNotFound);
+		}
+
+	//do cleanup
+	CleanupStack::PopAndDestroy(&processName8);
+	CleanupStack::PopAndDestroy(&processName);
+
+	aMessage.Complete(KErrNone);
+	}
+
+/*
+ Purpose: Sets the required event action to be taken for a specific
+ process and event combination
+
+@param aMessage The RMessage2 object is expected to contain:
+  * aMessage.Int0() - TDes8 Containing the process name.
+  * aMessage.Int1() - TEventType
+  * aMessage.Int2() - TKernelEventAction
+  *
+*/
+void CSecuritySvrSession::SetEventActionL(const RMessage2& aMessage)
+	{
+	LOG_MSG( "CSecuritySvrSession::SetEventActionL()\n" );
+
+	// Local descriptor to contain target process name
+	TInt deslen = aMessage.GetDesLengthL(0);
+
+	RBuf processName;
+
+	processName.CreateL(deslen);
+
+	processName.CleanupClosePushL();
+
+	// Read the target process name into processName
+	aMessage.ReadL(0,processName);
+
+	//check that the agent has attached to the target process
+	if(!Server().CheckAttachedProcess(processName, aMessage, EFalse))
+		{
+		// Debug Agent is not attached at all to the requested process
+		User::Leave(KErrPermissionDenied);
+		}
+
+	// Extract and validate the arguments from aMessage
+	TUint32 event  = aMessage.Int1();
+	if (event >= EEventsLast)
+		{
+		// Supplied event Id was not recognised
+		User::Leave(KErrArgument);
+		}
+
+	TUint32 action = aMessage.Int2();
+	if(action >= EActionLast)
+	{
+		// Supplied event action was not recognised
+		User::Leave(KErrArgument);
+	}
+
+	RBuf8 processName8;
+
+	processName8.CreateL(processName.Length());
+
+	processName8.CleanupClosePushL();
+
+	processName8.Copy(processName);
+
+	// Make the call to the device driver
+	TInt err = Server().iKernelDriver.SetEventAction(processName8, \
+		(TEventType)event,\
+		(TKernelEventAction)action,\
+		iDebugAgentProcessId.Id());
+
+	User::LeaveIfError(err);
+
+	CleanupStack::PopAndDestroy(&processName8);
+	CleanupStack::PopAndDestroy(&processName);
+
+	aMessage.Complete(KErrNone);
+}
+
+/**
+Purpose: Single-step a thread for a specified number of instructions
+
+@param aMessage.Ptr0() - Thread Id of the thread to be stepped
+@param aMessage.Int1() - Number of instructions to step.
+
+@leave one of the system wide error codes
+
+*/
+void CSecuritySvrSession::StepL(const RMessage2& aMessage)
+	{
+	LOG_MSG( "CSecuritySvrSession::StepL()\n" );
+
+	const TThreadId threadId = ReadTThreadIdL(aMessage, 0);
+	const TInt32 numSteps = aMessage.Int1();
+
+	CheckAttachedL(threadId, aMessage, EFalse);
+
+	User::LeaveIfError(Server().iKernelDriver.Step( threadId, numSteps ));
+
+	aMessage.Complete(KErrNone);
+	}
+
+/**
+ * This checks whether or not the agent is permitted access to the flash partition
+ * @return KErrNone if allowed, otherwise one of the system wide error codes
+ * @leave one of the system wide error codes
+ */
+TInt CSecuritySvrSession::CheckFlashAccessPermissionL(const RThread& aClientThread)
+	{
+	// Read the OEM Debug token capabilities (if any)
+	GetDebugAgentOEMTokenCapsL();
+	
+	if(Server().OEMTokenPermitsFlashAccessL((iOEMDebugCapabilities)))
+		{
+		return KErrNone;
+		}
+
+	return KErrPermissionDenied;
+	}
+
+/**
+Purpose: Read the crash log from the crash flash partition
+@param aMessage.Int0() - Position to read from.
+@param aMessage.Ptr1() - Buffer to hold the data retrieved
+@param aMessage.Int2() - Size of the data to read.
+
+@leave one of the system wide error codes
+*/
+void CSecuritySvrSession::ReadCrashLogL (const RMessage2& aMessage)
+	{	
+	//get the debug agent's thread and push handle onto clean up stack
+	RThread clientThread;
+	User::LeaveIfError(aMessage.Client(clientThread));
+	CleanupClosePushL(clientThread);
+	
+	TInt err = CheckFlashAccessPermissionL(clientThread);
+	
+	CleanupStack::PopAndDestroy(&clientThread);
+	
+	if(KErrNone != err)
+		{
+		LOG_MSG2( "CSecuritySvrSession::ReadCrashLogL()  Access Not Granted - [%d]\n", err );
+		aMessage.Complete(err);
+		return;
+		}
+	
+	//Check whether drive connected.
+	if(!iCrashConnected)
+		ConnectCrashPartitionL();	
+
+	TInt readPosition = aMessage.Int0(); //read position
+	
+	TInt readSize = aMessage.Int2(); //read size
+	
+	RBuf8 readBuf;
+	readBuf.CreateL(readSize);
+	readBuf.CleanupClosePushL();
+	
+	err = iLocalDrive.Read (readPosition, readSize, readBuf);
+	
+	//write the list data back
+	aMessage.WriteL (1, readBuf);	
+	
+	CleanupStack::PopAndDestroy (&readBuf);	
+	
+	//Complete message
+	aMessage.Complete(err);	
+	}
+/**
+Purpose: Function to write the crash config to the crash flash partition
+
+@param aMessage.Int0() - write position in bytes from start position in flash partition.
+@param aMessage.Ptr1() - Buffer containing the data to be written onto the flash. 
+                         The size could be 0 if only flash partition size is needed. 
+@param aMessage.Int2() - returns the size of the flash partition.
+
+@leave one of the system wide error codes
+*/
+void CSecuritySvrSession::WriteCrashConfigL(const RMessage2& aMessage)
+	{
+	LOG_MSG( "CSecuritySvrSession::WriteCrashConfigL()\n" );
+	
+	//get the debug agent's thread and push handle onto clean up stack
+	RThread clientThread;
+	User::LeaveIfError(aMessage.Client(clientThread));
+	CleanupClosePushL(clientThread);
+	
+	TInt err = CheckFlashAccessPermissionL(clientThread);
+	
+	CleanupStack::PopAndDestroy(&clientThread);
+	
+	if(KErrNone != err)
+		{
+		LOG_MSG2( "CSecuritySvrSession::WriteCrashConfigL()  Access Not Granted - [%d]\n", err );
+		aMessage.Complete(err);
+		return;
+		}
+	
+	//Check whether drive connected.
+	if(!iCrashConnected)
+		ConnectCrashPartitionL();	
+	
+	// Get the length of the buffer
+	TInt deslen = aMessage.GetDesLengthL(1);
+
+	RBuf8 dataBuf;
+	dataBuf.CreateL(deslen);
+	dataBuf.CleanupClosePushL();
+
+	// data to be written to flash
+	aMessage.ReadL(1,dataBuf);
+	
+	TUint32 position = aMessage.Int0(); //position to start from
+		
+	err = iLocalDrive.Write(position,(const TDesC8&)dataBuf);
+	
+	TPtr8 dataSize((TUint8*)&deslen,4, 4);
+	
+	//write the size of the data written back
+	aMessage.WriteL(2,dataSize);
+		
+	//destroy buffer
+	CleanupStack::PopAndDestroy(&dataBuf); 
+	
+	aMessage.Complete(err);	
+	}
+/**
+Purpose: Method to erase the crash flash block
+
+@param aMessage.Int0() - write position in bytes from start position in flash partition.
+@param aMessage.Int2() - Number of blocks to erase.
+
+@leave one of the system wide error codes
+*/
+
+void CSecuritySvrSession::EraseCrashLogL(const RMessage2& aMessage)
+	{	
+	LOG_MSG( "CSecuritySvrSession::EraseCrashLogL()\n" );
+	
+	//get the debug agent's thread and push handle onto clean up stack
+	RThread clientThread;
+	User::LeaveIfError(aMessage.Client(clientThread));
+	CleanupClosePushL(clientThread);
+	
+	TInt err = CheckFlashAccessPermissionL(clientThread);
+	
+	CleanupStack::PopAndDestroy(&clientThread);
+	
+	if(KErrNone != err)
+		{
+		LOG_MSG2( "CSecuritySvrSession::EraseCrashLogL()  Access Not Granted - [%d]\n", err );
+		aMessage.Complete(err);
+		return;
+		}
+			
+	//Check whether drive connected.
+	if(!iCrashConnected)
+		ConnectCrashPartitionL();	
+	
+	TInt64 position = aMessage.Int0();	
+	TInt size = aMessage.Int1();
+	
+	//Format drive
+	err = iLocalDrive.Format(position,size*iCaps.iEraseBlockSize);		
+ 
+	aMessage.Complete(err);	
+	}
+
+/**
+Purpose: Method to erase the entire crash flash block
+@leave one of the system wide error codes
+*/
+
+void CSecuritySvrSession::EraseEntireCrashLogL(const RMessage2& aMessage)
+	{
+	LOG_MSG( "CSecuritySvrSession::EraseEntireCrashLogL()\n" );
+	
+	//get the debug agent's thread and push handle onto clean up stack
+	RThread clientThread;
+	User::LeaveIfError(aMessage.Client(clientThread));
+	CleanupClosePushL(clientThread);
+	
+	TInt err = CheckFlashAccessPermissionL(clientThread);
+	
+	CleanupStack::PopAndDestroy(&clientThread);
+	
+	if(KErrNone != err)
+		{
+		LOG_MSG2( "CSecuritySvrSession::EraseEntireCrashLogL()  Access Not Granted - [%d]\n", err );
+		aMessage.Complete(err);
+		return;
+		}	
+	
+	//Check whether drive connected.
+	if(!iCrashConnected)
+		ConnectCrashPartitionL();
+	
+	TUint numberBlocks = iCaps.iSize /iCaps.iEraseBlockSize;
+	
+	//Format drive
+	for(TInt i = 0; i < numberBlocks; i++)
+		{
+		err = iLocalDrive.Format(i*iCaps.iEraseBlockSize,iCaps.iEraseBlockSize);
+		if(KErrNone != err)
+			{
+			RDebug::Printf("err = %d", err);
+			aMessage.Complete(err);
+			return;
+			}
+		}
+	
+	
+	aMessage.Complete(err);
+	}
+
+
+/**
+Purpose: Kill a specified process
+
+@param aMessage.Ptr0() - Process Id of the thread to be stepped
+@param aMessage.Int1() - Reason code to supply when killing the process.
+
+@leave one of the system wide error codes
+
+*/
+void CSecuritySvrSession::KillProcessL(const RMessage2& aMessage)
+	{
+	LOG_MSG( "CSecuritySvrSession::KillProcessL()\n" );
+
+	const TProcessId processId = ReadTProcessIdL(aMessage, 0);
+	const TInt32 reason = aMessage.Int1();
+
+	CheckAttachedL(processId, aMessage, EFalse);
+
+	User::LeaveIfError(Server().iKernelDriver.KillProcess( processId, reason ));
+
+	aMessage.Complete(KErrNone);
+	}
+
+/** Gets the secure id of aFileName
+  @param aFileName file name of executable to get SID for
+  @param aSecureId on return will contain the SID of aFileName
+
+  @leave one of the system wide error codes
+  */
+void CSecuritySvrSession::GetSecureIdL(const TDesC& aFileName, TUid& aSecureId)
+	{
+	RFs fs;
+	User::LeaveIfError(fs.Connect());
+	CleanupClosePushL(fs);
+
+	RFile targetExe;
+	OpenFileHandleL(aFileName, fs, targetExe);
+	CleanupClosePushL(targetExe);
+
+	// Read in the entire header
+	RBuf8 e32HdrBuf;
+	e32HdrBuf.CreateL(RLibrary::KRequiredImageHeaderSize);
+	e32HdrBuf.CleanupClosePushL();
+
+	// Read the entire header as far as possible
+	TInt err = targetExe.Read(e32HdrBuf);
+	if (err != KErrNone)
+		{
+		// Could not read the file 
+		LOG_MSG("CSecuritySvrSession::GetSecureIdL - Failed to read executable\n");
+
+		User::Leave(err);
+		}
+
+	if(!CheckSufficientData(e32HdrBuf, IsExecutableXipL(targetExe)))
+		{
+		User::Leave(KErrGeneral);
+		}
+
+	aSecureId = GetSecureIdL(e32HdrBuf, IsExecutableXipL(targetExe));
+
+	CleanupStack::PopAndDestroy(3, &fs);
+	}
+
+/** Get the secure id from aHeaderData
+  @param aHeaderData an executable's header data to read SID from
+  @param aXip indication of whether the header data is from an XIP file
+
+  @return secure ID from aHeaderData
+  */
+TUid CSecuritySvrSession::GetSecureIdL(const TDesC8& aHeaderData, TBool aXip)
+	{
+	if(!CheckSufficientData(aHeaderData, aXip))
+		{
+		User::Leave(KErrGeneral);
+		}
+
+	if (aXip)
+		{
+		TRomImageHeader* hdr = (TRomImageHeader*)aHeaderData.Ptr();
+		return TUid::Uid(hdr->iS.iSecureId);
+		}
+	else
+		{
+		// it is an epoc32 image
+		E32ImageHeaderV* hdr = (E32ImageHeaderV*)aHeaderData.Ptr();
+		return TUid::Uid(hdr->iS.iSecureId);
+		}
+	}
+
+/**
+@param aMessage contains:
+ * aMessage.Ptr0() a TListDetails object
+ * aMessage.Ptr1() a client supplied TDes8 for the driver to return data in
+ * aMessage.Ptr2() a TUint32 for the driver to return the size of the requested listing's data in
+
+@leave KErrTooBig if the buffer passed as argument 1 of aMessage is too
+       small to contain the requested data,
+       KErrNoMemory if a temporary buffer could not be allocated,
+       or one of the other system wide error codes
+*/
+void CSecuritySvrSession::GetListL(const RMessage2& aMessage)
+	{
+	LOG_MSG("CSecuritySvrSession::GetListL()");
+
+	// buffer to write list data into before copying back to agent
+	RBuf8 listDetailsBuf;
+
+	//allocate buffer
+	listDetailsBuf.CreateL(sizeof(TListDetails));
+
+	// Do the right cleanup if anything subsequently goes wrong
+	listDetailsBuf.CleanupClosePushL();
+
+	//read the data from the client thread
+	aMessage.ReadL(0, listDetailsBuf);
+	TListDetails* listDetails = (TListDetails*)listDetailsBuf.Ptr();
+
+	//get the type of list requested
+	TListId type = (TListId)aMessage.Int0();
+
+	//create a buffer to store the data in
+	RBuf8 buffer;
+	buffer.CreateL(aMessage.GetDesMaxLength(1));
+	buffer.CleanupClosePushL();
+
+	//create a temporary variable to potentially store data length in
+	TUint32 size = 0;
+
+	TInt err = KErrNone;
+
+	// the executables list is generated in the DSS rather than in the driver
+	// so is treated separately
+	if(listDetails->iListId == EExecutables)
+		{
+		if(listDetails->iListScope != EScopeGlobal)
+			{
+			User::Leave(KErrArgument);
+			}
+		if(listDetails->iTargetId != 0)
+			{
+			User::Leave(KErrArgument);
+			}
+		err = GetExecutablesListL(buffer, size);
+		}
+	else
+		{
+		err = Server().iKernelDriver.GetList(listDetails->iListId, listDetails->iListScope, listDetails->iTargetId, iDebugAgentProcessId, buffer, size);
+		}
+
+	if(err == KErrNone)
+		{
+		//write the list data back
+		aMessage.WriteL(1, buffer);
+		}
+
+	TPtr8 sizePtr((TUint8*)&size, sizeof(TUint32), sizeof(TUint32));
+	//write size back to agent
+	aMessage.WriteL(2, sizePtr);
+
+	CleanupStack::PopAndDestroy(&buffer);
+	CleanupStack::PopAndDestroy(&listDetailsBuf);
+
+	aMessage.Complete(err);
+	}
+
+/**
+Gets the executables list and returns it in aBuffer if it's big enough
+
+@param aBuffer caller supplied buffer to write data into
+@param aSize on return contains the size of the data in the buffer, or the
+       size that the buffer would need to be to contain the data
+
+@return KErrNone on success, or KErrTooBig if the requested data will not fit in aBuffer
+
+@leave one of the system wide error codes
+*/
+TInt CSecuritySvrSession::GetExecutablesListL(TDes8& aBuffer, TUint32& aSize) const
+	{
+	LOG_MSG("CSecuritySvrSession::GetExecutablesList()");
+
+	//initialise values and connect to file system
+	aSize = 0;
+	aBuffer.SetLength(0);
+	RFs fs;
+	User::LeaveIfError(fs.Connect());
+	CleanupClosePushL(fs);
+
+	// uids corresponding to executable image
+	TUidType uids(KExecutableImageUid, KNullUid, KNullUid);
+
+	//create a string containing the directory name. The drive letter is represented
+	//by X but will be replaced by the appropriate drive letter for each drive
+	_LIT(KColonSysBin,":\\sys\\bin\\");
+
+	//create a modifiable copy of KColonSysBin, preceeded by an empty space for the drive letter
+	RBuf dirName;
+	dirName.CreateL(1 + KColonSysBin().Length());
+	dirName.CleanupClosePushL();
+
+	//set the length to 1 (to later fill with the drive letter) and then append KColonSysBin
+	dirName.SetLength(1);
+	dirName.Append(KColonSysBin());
+
+	//get the list of valid drives for the device
+	TDriveList driveList;
+	User::LeaveIfError(fs.DriveList(driveList));
+
+	//check each valid sys/bin directory for executables
+	for(TInt i=0; i<KMaxDrives; i++)
+		{
+		//if the drive is not valid then skip this drive
+		if(!driveList[i])
+			{
+			//skip processing this drive
+			continue;
+			}
+
+		//get the drive letter and insert it as the drive letter for dirName
+		TChar driveLetter;
+		User::LeaveIfError(fs.DriveToChar(i, driveLetter));
+		dirName[0] = (TUint)driveLetter;
+
+		//get a list of the exes in this drive's sys/bin directory
+		CDir* localDir = NULL;
+		TInt err = fs.GetDir(dirName, uids, ESortByName, localDir);
+		if(KErrNoMemory == err)
+			{
+			User::Leave(err);
+			}
+		if(!localDir)
+			{
+			//skip processing this drive
+			continue;
+			}
+
+		//push onto cleanup stack in case we leave
+		CleanupStack::PushL(localDir);
+
+		//iterate through the files
+		for(TInt j=0; j<localDir->Count(); j++)
+			{
+			//will store x:\sys\bin\<file-name> type string
+			RBuf fullPathName;
+
+			TUint16 nameLength = dirName.Length() + (*localDir)[j].iName.Length();
+			fullPathName.CreateL(nameLength);
+			fullPathName.CleanupClosePushL();
+			fullPathName.Copy(dirName);
+			fullPathName.Append((*localDir)[j].iName);
+
+			//add the data to the buffer
+			AppendExecutableData(aBuffer, aSize, fullPathName);
+
+			//do cleanup
+			CleanupStack::PopAndDestroy(&fullPathName);
+			}
+
+		//do cleanup
+		CleanupStack::PopAndDestroy(localDir);
+		}
+
+	//do cleanup
+	CleanupStack::PopAndDestroy(2, &fs);
+
+	//return appropriate value as to whether the kernel's data was too big
+	return (aSize <= aBuffer.MaxLength()) ? KErrNone : KErrTooBig;
+	}
+
+
+/**
+  Append data to aBuffer and update size of aSize if the data will fit. If it will
+  not fit then just puts the nee size in aSize.
+
+  @param aBuffer buffer to append the data to
+  @param aSize on return contains the new size of the buffer if the data could be
+  appended, otherwise aSize is updated to reflect the size the buffer would have if
+  the data had fitted.
+  @param aEntryName file name of the entry to add to the buffer
+  */
+void CSecuritySvrSession::AppendExecutableData(TDes8& aBuffer, TUint32& aSize, const TDesC& aEntryName) const
+	{
+	//update aSize to include the size of the data for this entry
+	aSize = Align4(aSize + sizeof(TExecutablesListEntry) + (2*aEntryName.Length()) - sizeof(TUint16));
+
+	//if the data will fit, and we haven't already stopped putting data in, then append the data,
+	//if we've stopped putting data in then aSize will be bigger than aBuffer.MaxLength()
+	if(aSize <= aBuffer.MaxLength())
+		{
+		TExecutablesListEntry& entry = *(TExecutablesListEntry*)(aBuffer.Ptr() + aBuffer.Length());
+		//check whether an agent has registered to actively debug fullPathName
+		TBool activelyDebugged = IsDebugged(aEntryName, EFalse);
+		entry.iIsActivelyDebugged = activelyDebugged ? 1 : 0;
+
+		//check whether any agents have registered to passively debug fullPathName
+		TBool passivelyDebugged = IsDebugged(aEntryName, ETrue);
+		entry.iIsPassivelyDebugged = passivelyDebugged ? 1 : 0;
+
+		entry.iNameLength = aEntryName.Length();
+		TPtr name(&(entry.iName[0]), aEntryName.Length(), aEntryName.Length());
+		name = aEntryName;
+		//pad the buffer to a four byte boundary
+		aBuffer.SetLength(aSize);
+		}
+	}
+/**
+Helper function
+
+Write data back to the thread that owns aMessage
+
+@param aMessage the message which is passed between processes
+@param aIndex the message slot which the data will be passed back in
+@param aPtr pointer to data in this thread to be written into aMessage
+@param aPtrSize size in bytes of the data to be written
+
+@leave one of the system wide error codes
+*/
+void CSecuritySvrSession::WriteDataL(const RMessage2& aMessage, const TInt aIndex, const TAny* aPtr, const TUint32 aPtrSize) const
+	{
+	TPtr8 dataPtr((TUint8*)aPtr, aPtrSize, aPtrSize);
+
+	aMessage.WriteL(aIndex, dataPtr);
+	}
+
+/**
+Helper function.
+
+Checks whether the debug agent (the owner of the aMessage) is attached to the
+thread with thread id of aThreadId.
+
+@param aThreadId thread ID of target debug thread
+@param aMessage message owned by the debug agent
+@param aPassive indicates whether to check if attached passively or actively
+
+@leave KErrPermissionDenied if the agent is not attached to the process,
+       KErrNoMemory if the security server could not be accessed
+*/
+void CSecuritySvrSession::CheckAttachedL(const TThreadId aThreadId, const RMessage2& aMessage, const TBool aPassive) const
+	{
+	//check that the agent has attached to the target process
+	if(! Server().CheckAttached(aThreadId, aMessage, aPassive))
+		{
+		LOG_MSG("CSecuritySvrSession::CheckAttachedL() failed");
+		User::Leave(KErrPermissionDenied);
+		}
+	}
+
+/**
+Helper function.
+
+Checks whether the debug agent (the owner of the aMessage) is attached to the
+process with process id of aProcessId.
+
+@param aProcessId process ID of target debug thread
+@param aMessage message owned by the debug agent
+@param aPassive indicates whether to check if attached passively or actively
+
+@leave KErrPermissionDenied if the agent is not attached to the process,
+       KErrNoMemory if the security server could not be accessed
+*/
+void CSecuritySvrSession::CheckAttachedL(const TProcessId aProcessId, const RMessage2& aMessage, const TBool aPassive) const
+	{
+	
+	//check that the agent has attached to the target process
+	if(! Server().CheckAttached(aProcessId, aMessage, aPassive))
+		{
+		LOG_MSG("CSecuritySvrSession::CheckAttachedL() (process) failed");
+		User::Leave(KErrPermissionDenied);
+		}
+	}
+
+/**
+Check whether the debug agent is permitted to attach to the target process.
+Note that this function does not actually attach the agent to the process, it
+simply tests whether an attach call would potentially be successful.
+
+Currently this method returns ETrue in all cases but will be updated once
+the security checking framework is in place.
+
+@param aDebugAgentProcessId process id of the debug agent
+@param aTargetProcessName original file name of the target process
+
+@return ETrue if the debug agent would be allowed to attch to the target process,
+        EFalse otherwise
+*/
+TBool CSecuritySvrSession::PermitDebugL(const TProcessId aDebugAgentProcessId, const TDesC& aTargetProcessName) const
+	{
+	return ETrue;
+	}
+
+/**
+Helper function
+
+Validates that the memory info passed in meets the debug driver's requirements
+
+@param aMemoryInfo memory info passed in from client
+
+@leave KErrArgument if:
+	  * size is zero
+	  * size is greater than the max block size
+	  * size + address > 0xffffffff
+	  * address is not access size aligned
+	  * size is not a multiple of the access size
+	KErrNotSupported if:
+	  * iAccess is not TAccess::EAccess32
+	  * iEndianess is not TEndianess::EEndLE8
+	KErrUnknown if:
+	  * the max memory block size cannot be determined
+        or one of the other system wide error codes
+*/
+void CSecuritySvrSession::ValidateMemoryInfoL(const TThreadId aThreadId, const TMemoryInfo &aMemoryInfo, const TBool aReadOperation)
+	{
+	//check size is not 0
+	if(aMemoryInfo.iSize == 0)
+		User::Leave(KErrArgument);
+
+	//get the max block size supported
+	TUint32 maxSize = 0;
+	User::LeaveIfError(Server().iKernelDriver.GetMemoryOperationMaxBlockSize(maxSize));
+
+	//check that the block size given is less than the max block size
+	if(aMemoryInfo.iSize > maxSize)
+		User::Leave(KErrArgument);
+
+	//must ensure that address + size <= 0xffffffff as will attempt to
+	//read past 0xffffffff, which wouldn't be good
+	TUint32 maxAddress = (~aMemoryInfo.iSize) + 1;
+	if(aMemoryInfo.iAddress > maxAddress)
+		User::Leave(KErrArgument);
+
+	//check that arguments are supported
+	if(aMemoryInfo.iAccess != EAccess32)
+		User::Leave(KErrNotSupported);
+
+	if(aMemoryInfo.iEndianess != EEndLE8)
+		User::Leave(KErrNotSupported);
+
+	//check that address is multiple of access size
+	TInt addressIndicator = aMemoryInfo.iAddress % aMemoryInfo.iAccess;
+	if(addressIndicator != 0)
+		{
+		User::Leave(KErrArgument);
+		}
+
+	//check that size is multiple of access size
+	TInt sizeIndicator = aMemoryInfo.iSize % aMemoryInfo.iAccess;
+	if(sizeIndicator != 0)
+		User::Leave(KErrArgument);
+	}
+
+/**
+Helper function
+
+Validates that the three buffers relating to reading register data are of
+appropriate sizes, and calculates the number of registers being requested.
+
+@param aMessage message which in offsets 1, 2 and 3 contains descriptors
+@param aNumberOfRegisters if the function returns with KErrNone this will
+       contain the number of registers being requested, guaranteed to be non-zero
+
+@leave KErrArgument if descriptors do not represent the same number of
+       registers, if any of the descriptors have max length of 0, if any of
+       the descriptors have max lengths which are not multiples of their data
+       type's size or if any of the descriptors have max lengths greater than
+       the max block size for memory operations
+       or one of the other system wide error codes if there were problems 
+       in getting the descriptors' lengths.
+*/
+void CSecuritySvrSession::ValidateRegisterBuffersL(const RMessage2& aMessage, TUint32& aNumberOfRegisters)
+	{
+	//get lengths of buffers, if error occurs returned value will be less then zero
+	TInt idsBufferLength = aMessage.GetDesMaxLength(1);
+	if(idsBufferLength < 0)
+		{
+		User::Leave(idsBufferLength);
+		}
+	TInt valuesBufferLength = aMessage.GetDesMaxLength(2);
+	if(valuesBufferLength < 0)
+		{
+		User::Leave(valuesBufferLength);
+		}
+	TInt flagsBufferLength = aMessage.GetDesMaxLength(3);
+	if(flagsBufferLength < 0)
+		{
+		User::Leave(flagsBufferLength);
+		}
+
+	//get the max block size supported
+	TUint32 maxSize = 0;
+	User::LeaveIfError(Server().iKernelDriver.GetMemoryOperationMaxBlockSize(maxSize));
+
+	//check none of the descriptors have size greater than the max block size
+	if((idsBufferLength > maxSize) || (valuesBufferLength > maxSize) || (flagsBufferLength > maxSize))
+		User::Leave(KErrArgument);
+
+	//get sizes of the three types of data the buffers represent arrays of
+	//and validate that the buffer lengths are multiples of the data sizes
+	TUint idSize = sizeof(TRegisterInfo);
+	if(idsBufferLength % idSize != 0)
+		User::Leave(KErrArgument);
+
+	TUint flagSize = sizeof(TUint8);
+	if(flagsBufferLength % flagSize != 0)
+		User::Leave(KErrArgument);
+
+	//perform check on id buffer length
+	if(idsBufferLength == 0)
+		User::Leave(KErrArgument);
+
+	//calculate number of registers being requested
+	aNumberOfRegisters = idsBufferLength / idSize;
+
+	//check flags buffer is of appropriate size
+	if(flagsBufferLength != (aNumberOfRegisters * flagSize))
+		User::Leave(KErrArgument);
+	}
+
+/**
+Establish whether any agents have registered to debug the specified aFileName
+
+@param aFileName originating file name of the target process
+@param aPassive indicates whether to check if there has been active attachment,
+or passive attachment.
+
+@return ETrue if aFileName is being debugged, EFalse otherwise
+
+*/
+TBool CSecuritySvrSession::IsDebugged(const TDesC& aFileName, const TBool aPassive) const
+	{
+	//check whether the target process is being debugged
+	return Server().IsDebugged(aFileName, aPassive);
+	}
+
+/**
+  Helper function which reads a TThreadId object from a client
+
+  @param aMessage the message object containing the reference to the TThreadId
+  @param aIndex the message argument containing the reference
+
+  @return the TThreadId passed in by the client
+  @leave KErrArgument if aIndex is outside of the valid range
+  */
+TThreadId CSecuritySvrSession::ReadTThreadIdL(const RMessagePtr2& aMessage, const TInt aIndex) const
+	{
+	//create a temporary TThreadId to read the data into
+	TThreadId tempThreadId;
+	TPtr8 threadIdPtr((TUint8*)&tempThreadId, sizeof(TThreadId));
+
+	// read the data in from the client
+	aMessage.ReadL(aIndex, threadIdPtr);
+
+	return tempThreadId;
+	}
+
+/**
+  Helper function which reads a TProcessId object from a client
+
+  @param aMessage the message object containing the reference to the TProcessId
+  @param aIndex the message argument containing the reference
+
+  @return the TProcessId passed in by the client
+  @leave KErrArgument if aIndex is outside of the valid range
+  */
+TProcessId CSecuritySvrSession::ReadTProcessIdL(const RMessagePtr2& aMessage, const TInt aIndex) const
+	{
+	//create a temporary TProcessId to read the data into
+	TProcessId tempProcessId;
+	TPtr8 processIdPtr((TUint8*)&tempProcessId, sizeof(TProcessId));
+
+	// read the data in from the client
+	aMessage.ReadL(aIndex, processIdPtr);
+
+	return tempProcessId;
+	}
+
+// End of file - c_security_svr_session.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/debugsrv/runmodedebug/securityserver/src/c_shutdown_timer.cpp	Fri Aug 27 11:37:29 2010 +0300
@@ -0,0 +1,65 @@
+// Copyright (c) 2007-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+// Provides the debug security server's shutdown timer implementation
+// 
+//
+
+/**
+ @file
+ @internalTechnology
+ @released
+*/
+
+#include <rm_debug_api.h>
+#include "c_shutdown_timer.h"
+#include "rm_debug_logging.h"
+
+/**
+Constructor. Adds the timer to the thread's active scheduler,
+*/
+CShutdownTimer::CShutdownTimer()
+	:CTimer(KActivePriorityShutdown)
+	{
+	LOG_MSG("CShutdownTimer::CShutdownTimer()\n");
+	CActiveScheduler::Add(this);
+	}
+
+/**
+Initialisation of timer
+*/
+void CShutdownTimer::ConstructL()
+	{
+	LOG_MSG("CShutdownTimer::ConstructL()\n");
+	CTimer::ConstructL();
+	}
+
+/**
+Starts the timer which would expire after KShutdownDelay
+*/
+void CShutdownTimer::Start()
+	{
+	LOG_MSG("CShutdownTimer::Start()\n");
+	After(KShutdownDelay);
+	}
+
+/**
+Stops the active scheduler. Stopping the active scheduler effectively closes
+the Debug Security Server
+*/
+void CShutdownTimer::RunL()
+	{
+	LOG_MSG("CShutdownTimer::RunL()\n");
+	CActiveScheduler::Stop();
+	}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/debugsrv/runmodedebug/securityserver/src/rm_debug_svr.cpp	Fri Aug 27 11:37:29 2010 +0300
@@ -0,0 +1,81 @@
+// Copyright (c) 2006-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+// Entry point to debug security server, sets up server/session
+// 
+//
+
+/**
+ @file
+ @internalTechnology
+ @released
+*/
+
+#include <e32base.h>
+#include <e32base_private.h>
+#include <rm_debug_api.h>
+
+#include "c_security_svr_server.h"
+#include "c_security_svr_session.h"
+#include "rm_debug_logging.h"
+
+using namespace Debug;
+
+/**
+Perform all server initialisation, in particular creation of the
+scheduler and server and then run the scheduler
+*/
+void RunServerL()
+	{
+	LOG_MSG( "rm_debug_svr.cpp::RunServerL() : -> new(ELeave) CActiveScheduler\n" );
+	CActiveScheduler* s=new(ELeave) CActiveScheduler;
+
+	LOG_MSG( "rm_debug_svr.cpp::RunServerL() : -> CleanupStack::PushL(s)\n" );
+	CleanupStack::PushL(s);
+
+	LOG_MSG( "rm_debug_svr.cpp::RunServerL() : -> CActiveScheduler::Install()\n" );
+	CActiveScheduler::Install(s);
+
+	LOG_MSG( "rm_debug_svr.cpp::RunServerL() : -> CSecuritySvrServer::NewLC()\n" );
+	CSecuritySvrServer::NewLC();
+
+	LOG_MSG( "rm_debug_svr.cpp::RunServerL() : -> Rendezvous(KErrNone)\n" );
+	// Signal whoever has started us that we have done so.
+	RProcess::Rendezvous(KErrNone);
+	LOG_MSG( "rm_debug_svr.cpp::RunServerL() : <- Rendezvous()\n" );
+
+	LOG_MSG( "rm_debug_svr.cpp::RunServerL() : -> CActiveScheduler::Start()\n" );
+	CActiveScheduler::Start();
+	LOG_MSG( "rm_debug_svr.cpp::RunServerL() <- CActiveScheduler::Start()\n" );
+
+	LOG_MSG( "rm_debug_svr.cpp::RunServerL() : -> CleanupStack::PopAndDestroy()\n" );
+	CleanupStack::PopAndDestroy(2, s);
+	LOG_MSG( "rm_debug_svr.cpp::RunServerL() : <- CleanupStack::PopAndDestroy()\n" );
+	}
+
+/**
+Entry point for debug security server
+*/
+GLDEF_C TInt E32Main()
+	{
+	__UHEAP_MARK;
+	CTrapCleanup* cleanup=CTrapCleanup::New();
+	TInt r = KErrNoMemory;
+	if (cleanup)
+		{
+		TRAP(r,RunServerL());
+		delete cleanup;
+		}
+	__UHEAP_MARKEND;
+	return r;
+	}
--- a/layers.sysdef.xml	Mon Aug 23 15:29:36 2010 +0300
+++ b/layers.sysdef.xml	Fri Aug 27 11:37:29 2010 +0300
@@ -13,6 +13,9 @@
         <component name="tracecompiler">
           <unit unitID="tools.tracecompiler" mrp="" bldFile="&layer_real_source_path;/tracefw/tracecompiler/group" name="tracecompiler" />
         </component>
+        <component name="runmodedebug">
+          <unit unitID="tools.runmodedebug" mrp="" bldFile="&layer_real_source_path;/debugsrv/runmodedebug/group" name="runmodedebug" />
+        </component>        
       </module>
     </layer>
   </systemModel>
Binary file piprofiler/group/ReleaseNotes_PIProfiler.txt has changed
--- a/piprofiler/group/bld.inf	Mon Aug 23 15:29:36 2010 +0300
+++ b/piprofiler/group/bld.inf	Fri Aug 27 11:37:29 2010 +0300
@@ -26,8 +26,15 @@
 #include "../plugins/DebugOutputWriterPlugin/group/bld.inf"
 #include "../plugins/DiskWriterPlugin/group/bld.inf"
 
+#if ( SYMBIAN_VERSION_SUPPORT >= SYMBIAN_3 )
+    #include "../plugins/PWRPlugin/group/bld.inf"
+#endif
 
 PRJ_EXPORTS
-../rom/piprofiler.iby CORE_IBY_EXPORT_PATH(tools,piprofiler.iby)
+#if ( SYMBIAN_VERSION_SUPPORT >= SYMBIAN_3 )
+    ../rom/piprofiler.iby CORE_IBY_EXPORT_PATH(tools,piprofiler.iby)
+#else
+    ../rom/piprofiler_s2.iby CORE_IBY_EXPORT_PATH(tools,piprofiler.iby)
+#endif
 ../rom/piprofiler_ldd.iby CORE_IBY_EXPORT_PATH(tools/rom,piprofiler_ldd.iby)
 
--- a/piprofiler/plugins/GeneralsPlugin/src/GppSamplerImpl.cpp	Mon Aug 23 15:29:36 2010 +0300
+++ b/piprofiler/plugins/GeneralsPlugin/src/GppSamplerImpl.cpp	Fri Aug 27 11:37:29 2010 +0300
@@ -76,7 +76,7 @@
 	{
 	LOGTEXT("GppSamplerImpl::Reset");
 	iLastPc = 0;
-	iLastThread = 0;
+	iLastThread = 0xfffffffe;
 	iRepeat = 0;
 	iIsaStatus = 0;
 	iIsaStart = 0;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/piprofiler/plugins/PWRplugin/data/2001E5B9.rss	Fri Aug 27 11:37:29 2010 +0300
@@ -0,0 +1,51 @@
+/*
+* Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+* All rights reserved.
+* This component and the accompanying materials are made available
+* under the terms of "Eclipse Public License v1.0"
+* which accompanies this distribution, and is available
+* at the URL "http://www.eclipse.org/legal/epl-v10.html".
+*
+* Initial Contributors:
+* Nokia Corporation - initial contribution.
+*
+* Contributors:
+*
+* Description:  
+*
+*/
+
+
+#include <ecom/registryinfo.rh>
+
+// Declares info for two implementations
+RESOURCE REGISTRY_INFO theInfo
+    {
+    // UID for the DLL. See mmp files
+    //__SERIES60_3X__ can't be used in resource files
+    dll_uid = 0x2001E5B9;
+
+    // Declare array of interface info. This dll contains implementations for 
+    // only one interface (CSamplerInterfaceDefinition).
+    interfaces = 
+        {
+        INTERFACE_INFO
+            {
+            // UID of interface that is implemented
+            interface_uid = 0x2001E5BC;
+
+            implementations = 
+                {
+                IMPLEMENTATION_INFO
+                    {
+                    implementation_uid = 0x2001E5B9;
+
+                    version_no = 1;
+                    display_name = "PWR Sampler";
+                    default_data = "pwr";
+                    opaque_data = "10";
+                    }
+                };
+            }
+        };
+    }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/piprofiler/plugins/PWRplugin/group/PWRPlugin.mmp	Fri Aug 27 11:37:29 2010 +0300
@@ -0,0 +1,53 @@
+/*
+* Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+* All rights reserved.
+* This component and the accompanying materials are made available
+* under the terms of "Eclipse Public License v1.0"
+* which accompanies this distribution, and is available
+* at the URL "http://www.eclipse.org/legal/epl-v10.html".
+*
+* Initial Contributors:
+* Nokia Corporation - initial contribution.
+*
+* Contributors:
+*
+* Description:  
+*
+*/
+
+
+#include <platform_paths.hrh>
+
+
+TARGET          PIProfilerPWR.dll
+TARGETTYPE      PLUGIN
+UID             0x10009D8D 0x2001E5B9
+VENDORID        VID_DEFAULT
+CAPABILITY      ALL -TCB
+SMPSAFE
+
+OS_LAYER_SYSTEMINCLUDE
+USERINCLUDE     ../inc
+USERINCLUDE     ../../../inc
+SOURCEPATH      ../src
+
+START RESOURCE  ../data/2001E5B9.rss
+TARGET PIProfilerPWR.rsc
+END
+
+SOURCE          PwrPluginImplementationTable.cpp
+SOURCE          PwrPlugin.cpp
+
+LIBRARY     euser.lib
+LIBRARY     ecom.lib
+LIBRARY     apparc.lib
+LIBRARY     cone.lib
+LIBRARY     gdi.lib
+LIBRARY     ws32.lib
+LIBRARY     efsrv.lib
+LIBRARY     charconv.lib
+LIBRARY     CommonEngine.lib
+LIBRARY     flogger.lib
+LIBRARY     centralrepository.lib
+LIBRARY     HWRMPowerClient.lib
+LIBRARY     HWRMLightClient.lib
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/piprofiler/plugins/PWRplugin/group/bld.inf	Fri Aug 27 11:37:29 2010 +0300
@@ -0,0 +1,28 @@
+/*
+* Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+* All rights reserved.
+* This component and the accompanying materials are made available
+* under the terms of "Eclipse Public License v1.0"
+* which accompanies this distribution, and is available
+* at the URL "http://www.eclipse.org/legal/epl-v10.html".
+*
+* Initial Contributors:
+* Nokia Corporation - initial contribution.
+*
+* Contributors:
+*
+* Description:  
+*
+*/
+
+#ifndef SBSV2
+PRJ_PLATFORMS
+DEFAULT
+#endif
+
+PRJ_MMPFILES
+#ifdef MARM
+  #ifndef __SERIES60_30__
+    PWRPlugin.mmp
+  #endif
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/piprofiler/plugins/PWRplugin/inc/PwrPlugin.h	Fri Aug 27 11:37:29 2010 +0300
@@ -0,0 +1,167 @@
+/*
+* Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+* All rights reserved.
+* This component and the accompanying materials are made available
+* under the terms of "Eclipse Public License v1.0"
+* which accompanies this distribution, and is available
+* at the URL "http://www.eclipse.org/legal/epl-v10.html".
+*
+* Initial Contributors:
+* Nokia Corporation - initial contribution.
+*
+* Contributors:
+*
+* Description:  
+*
+*/
+
+#ifndef BAPPEA_PWR_SAMPLER_H
+#define BAPPEA_PWR_SAMPLER_H
+
+//#define PWR_SAMPLER_BACKLIGHT
+
+//#include "PIProfilerConfigInternal.h"
+
+// system definitions
+#include <w32std.h>
+#include <e32std.h>
+
+#include <e32property.h>
+#include <HWRMPower.h>
+#include <HWRMLight.h>
+
+// user definitions
+#include <piprofiler/SamplerPluginInterface.h>
+#include <piprofiler/ProfilerGenericClassesUsr.h>
+
+// caption definitions
+_LIT8(KPWRShortName, "pwr");
+_LIT8(KPWRMediumName, "Power sampler");
+_LIT8(KPWRLongName, "Power usage sampler");
+_LIT8(KPWRDescription, "Power sampler: \nSampling power consumption on Nokia S60 devices\nHW dep: N/A\nSW dep: S60 3.0\n");
+
+// Minimum allowed sampling interval (in ms). 0 means undefined.
+const TInt KMinSampleInterval = 250;
+const TInt KReportingPeriodInfinite = 0;
+
+const TUid KGppPropertyCat={0x20201F70};
+enum TGppPropertyKeys
+    {
+    EGppPropertySyncSampleNumber
+    };
+
+const TUid KPwrNotifierUid = { 0x2001E5B9 };
+class CProfilerPowerListener;
+
+/*
+ *
+ * PWR sampler plug-in definition
+ *
+ */
+
+class CPwrPlugin : public CSamplerPluginInterface
+{
+public:
+    static  CPwrPlugin* NewL(const TUid aImplementationUid, TAny* aInitParams);
+            ~CPwrPlugin();
+
+    TInt    ResetAndActivateL(CProfilerSampleStream& aStream);
+    TInt    StopSampling();
+    TBool   Enabled() { return iEnabled; }
+    void    SetEnabled(TBool aEnabled);
+    TInt    GetSamplerType();
+
+    TInt    CreateFirstSample();
+
+    void    GetAttributesL(CArrayFixFlat<TSamplerAttributes>* aAttributes);
+    TInt    SetAttributesL(TSamplerAttributes aAttributes);
+    void    InitiateSamplerAttributesL();
+
+    TInt    ConvertRawSettingsToAttributes(CDesC8ArrayFlat* aSingleSettingArray);
+
+    TInt    DoSetSamplerSettings(CDesC8ArrayFlat* aAllSettings, TDesC8& aSamplerName, TInt aIndex);
+    void    SaveSettingToAttributes(const TDesC8& aSetting, TInt aIndex);
+
+    TUid    Id(TInt aSubId) const;
+
+    // subsampler settings, i.e. samplers implemented within a plugin
+    // no sub samplers, from CSamplerPluginInterface
+    TInt    SubId(TUid aId) const {return KErrNotFound;}
+    TInt    GetSubSamplers(TDes* aDes){return KErrNotFound;}
+
+private:
+            CPwrPlugin();
+    void    ConstructL();
+
+private:
+    TUint8                  iVersion[20];
+    TPtr8                   iVersionDescriptor;
+
+    TInt                    iSamplerType;
+
+    CProfilerPowerListener* iPowerListener;
+
+    TInt                    iPeriod;
+    CArrayFixFlat<TSamplerAttributes>* iSamplerAttributes;
+public:
+    TUint32*                iSampleTime;
+};
+
+#ifdef PWR_SAMPLER_BACKLIGHT
+class CProfilerPowerListener : public MHWRMBatteryPowerObserver, public MHWRMLightObserver
+#else
+class CProfilerPowerListener : public MHWRMBatteryPowerObserver
+#endif
+{
+public:
+    static  CProfilerPowerListener* NewL(CPwrPlugin* aSampler);
+            ~CProfilerPowerListener();
+
+private:
+            CProfilerPowerListener(CPwrPlugin* aSampler);
+    void    ConstructL();
+
+public:
+    TInt    StartL(const TDesC8& aBuf);
+    TInt    Stop();
+    TInt    DisplayNotifierL(const TDesC& aLine1, const TDesC& aLine2, const TDesC& aButton1, const TDesC& aButton2);
+
+    // From MHWRMBatteryPowerObserver
+    virtual void PowerMeasurement(TInt aErr, CHWRMPower::TBatteryPowerMeasurementData& aMeasurement);
+#ifdef PWR_SAMPLER_BACKLIGHT
+    // From MHWRMLightObserver
+    virtual void LightStatusChanged(TInt aTarget, CHWRMLight::TLightStatus aStatus);
+#endif
+
+private:
+    void    Sample();
+
+public:
+    TInt                    iPwrSamplingPeriod;
+    TInt                    iSampleStartTime;
+    // Value that is read from Central Repository and restored after sampling
+    TInt                    iOriginalReportingPeriod;
+
+private:
+
+#ifdef PWR_SAMPLER_BACKLIGHT
+    TUint8                  iSample[13];
+#else
+    TUint8                  iSample[12];
+#endif
+
+    TUint16                 iNominalCapa;
+    TUint16                 iVoltage;
+    TUint16                 iCurrent;
+
+    CPwrPlugin*             iSampler;
+    CHWRMPower*             iPowerAPI;
+
+#ifdef PWR_SAMPLER_BACKLIGHT
+    CHWRMLight*             iLightAPI;
+    CHWRMLight::TLightStatus iBackLightStatus;
+#endif
+};
+
+#endif
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/piprofiler/plugins/PWRplugin/sis/PWRPlugin.pkg	Fri Aug 27 11:37:29 2010 +0300
@@ -0,0 +1,44 @@
+;
+; Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+; All rights reserved.
+; This component and the accompanying materials are made available
+; under the terms of "Eclipse Public License v1.0"
+; which accompanies this distribution, and is available
+; at the URL "http://www.eclipse.org/legal/epl-v10.html".
+;
+; Initial Contributors:
+; Nokia Corporation - initial contribution.
+;
+; Contributors:
+;
+; Description:
+;
+; ShapeImplementation_30_gcce.pkg
+;
+
+;Language - standard language definitions
+&EN
+
+; standard sis file header
+#{"Shape plugin"},(0xE01F614F),2,0,0
+
+
+;
+;Localised Vendor name
+;
+%{"Forum Nokia"}
+
+;
+;Unique Vendor name
+;
+:"Forum Nokia"
+
+;
+;Supports Series 60 v 3.0
+;
+[0x101F7961], 0, 0, 0, {"Series60ProductID"}
+
+
+;Files to include. Check the source paths they match your SDK setup. 
+"\Symbian\9.1\S60_3rd_MR\Epoc32\release\gcce\urel\shapeimplementation.dll"     -   "!:\sys\bin\shapeimplementation.dll"
+"\Symbian\9.1\S60_3rd_MR\epoc32\data\Z\Resource\plugins\shapeimplementation.rsc"   -   "!:\Resource\Plugins\shapeimplementation.RSC"
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/piprofiler/plugins/PWRplugin/src/PwrPlugin.cpp	Fri Aug 27 11:37:29 2010 +0300
@@ -0,0 +1,623 @@
+/*
+* Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+* All rights reserved.
+* This component and the accompanying materials are made available
+* under the terms of "Eclipse Public License v1.0"
+* which accompanies this distribution, and is available
+* at the URL "http://www.eclipse.org/legal/epl-v10.html".
+*
+* Initial Contributors:
+* Nokia Corporation - initial contribution.
+*
+* Contributors:
+*
+* Description:  
+*
+*/
+
+#include "PwrPlugin.h"
+#include <piprofiler/ProfilerTraces.h>
+
+#include <centralrepository.h>
+#include <HWRMPower.h>
+#include <HWRMLight.h>
+#include <hwrm/hwrmpowerdomaincrkeys.h>
+
+
+// texts for notes
+_LIT(KPowerTextLine1, "Power sampler:");
+_LIT(KPowerTextLine2, "Failed to start power measurement");
+_LIT(KPowerTextErrorSampling, "Error receiving measurement data");
+_LIT(KButtonOk, "Ok");
+
+// LITERALS
+
+_LIT8(KSamplingPeriodMs, "sampling_period_ms");
+
+// CONSTANTS
+// Use this UID if plugin is PwrPlugin:
+const TUid KSamplerPwrPluginUid = { 0x2001E5B9 };
+
+/*
+ *
+ * class CPwrPlugin implementation
+ * 
+ */
+ 
+CPwrPlugin* CPwrPlugin::NewL(const TUid /*aImplementationUid*/, TAny* aInitParams)
+    {
+    LOGTEXT(_L("CPwrPlugin::NewL() - entry"));
+    CPwrPlugin* self = new (ELeave) CPwrPlugin();
+    CleanupStack::PushL( self );
+    self->ConstructL();
+    CleanupStack::Pop();
+    LOGTEXT(_L("CPwrPlugin::NewL() - exit"));
+    return self;
+    }
+
+CPwrPlugin::CPwrPlugin() :
+    iVersionDescriptor(&(this->iVersion[1]),0,19),
+    iSamplerType(PROFILER_USER_MODE_SAMPLER)
+    {
+    iPeriod = 250;
+    iSamplerId = PROFILER_PWR_SAMPLER_ID;
+    iEnabled = EFalse;
+    iPowerListener = NULL;
+    LOGTEXT(_L("CPwrPlugin::CPwrPlugin() - konstruktori"));
+
+    }
+
+void CPwrPlugin::ConstructL() 
+    {
+    LOGTEXT(_L("CPwrPlugin::ConstructL() - entry"));
+    // initiate sampler attributes array
+    iSamplerAttributes = new(ELeave) CArrayFixFlat<TSamplerAttributes>(1); // only one sampler
+
+    // insert default attributes to array
+    InitiateSamplerAttributesL();
+
+    LOGTEXT(_L("CPwrPlugin::ConstructL() - exit"));
+    }
+
+CPwrPlugin::~CPwrPlugin()
+    {
+    LOGTEXT(_L("CPwrPlugin::~CPwrPlugin() - entry"));
+    if(iPowerListener)
+        {
+        if(Enabled())
+            {
+            iPowerListener->Stop();
+            }
+        delete iPowerListener;
+        iPowerListener = NULL;
+        }
+
+    if(iSamplerAttributes)
+        {
+        iSamplerAttributes->Reset();
+        delete iSamplerAttributes;
+        iSamplerAttributes = NULL;
+        }
+
+    LOGTEXT(_L("CPwrPlugin::~CPwrPlugin() - exit"));
+    }
+
+TUid CPwrPlugin::Id(TInt /*aSubId*/) const
+    {
+    LOGSTRING2( "CPwrPlugin::Id():0x%X", KSamplerPwrPluginUid.iUid );
+    return KSamplerPwrPluginUid;
+    }
+
+void CPwrPlugin::InitiateSamplerAttributesL()
+    {
+    // create TSamplerAttributes
+    TSamplerAttributes attr(KSamplerPwrPluginUid.iUid,
+            KPWRShortName(),
+            KPWRLongName(),
+            KPWRDescription(),
+            250,
+            EFalse,
+            EFalse,
+            0); 
+    this->iSamplerAttributes->AppendL(attr);
+    }
+
+void CPwrPlugin::SetEnabled(TBool aEnabled)
+    {
+    iEnabled = aEnabled;
+    }
+
+// returns setting array
+void CPwrPlugin::GetAttributesL(CArrayFixFlat<TSamplerAttributes>* aAttributes)
+    {
+    aAttributes->AppendL(iSamplerAttributes->At(0));
+    }
+
+TInt CPwrPlugin::SetAttributesL(TSamplerAttributes aAttributes)
+    {
+    TSamplerAttributes attr;
+
+    attr = iSamplerAttributes->At(0);
+    // replace the old attribute container
+    iSamplerAttributes->Delete(0);
+    iSamplerAttributes->InsertL(0, aAttributes);
+    return KErrNone;
+    }
+
+/* 
+ * Method for parsing and transforming text array settings into TSamplerAttributes (per each sub sampler),
+ * called by CSamplerController class
+ * 
+ * @param array of raw text setting lines, e.g. [gpp]\nenabled=true\nsampling_period_ms=1\n
+ */
+TInt CPwrPlugin::ConvertRawSettingsToAttributes(CDesC8ArrayFlat* aAllSettingsArray)
+    {
+    // local literals
+    _LIT8(KPWRShort, "pwr");
+
+    TInt err(KErrNone);
+    TBuf8<16> samplerSearchName;
+    samplerSearchName.Copy(KPWRShort);
+
+    // get sampler specific settings  
+    err = DoSetSamplerSettings(aAllSettingsArray, samplerSearchName, 0);
+
+    // returns KErrNone if settings found, otherwise KErrNotFound
+    return err;
+    }
+
+TInt CPwrPlugin::DoSetSamplerSettings(CDesC8ArrayFlat* aAllSettings, TDesC8& aSamplerName, TInt aIndex)
+    {
+    // 
+    TBuf8<16> samplerSearch;
+    samplerSearch.Copy(KBracketOpen);
+    samplerSearch.Append(aSamplerName);
+    samplerSearch.Append(KBracketClose);
+
+    // read a line
+    for (TInt i(0); i<aAllSettings->MdcaCount(); i++)
+        {
+        // check if this line has a setting block start, i.e. contains [xxx] in it
+        if (aAllSettings->MdcaPoint(i).CompareF(samplerSearch) == 0)
+            {
+            // right settings block found, now loop until the next block is found
+            for(TInt j(i+1);j<aAllSettings->MdcaCount();j++)
+                {
+                // check if the next settings block was found
+                if(aAllSettings->MdcaPoint(j).Left(1).CompareF(KBracketOpen) != 0)
+                    {
+                    // save found setting value directly to its owners attributes
+                    SaveSettingToAttributes(aAllSettings->MdcaPoint(j), aIndex);
+                    }
+                else
+                    {
+                    // next block found, return KErrNone
+                    return KErrNone;
+                    }
+                }
+            }
+        }
+
+    return KErrNotFound;
+    }
+
+/**
+ * Method for setting a specific descriptor (from settings file) to attribute structure
+ * 
+ * @param aSetting  
+ * @param aName  
+ */
+void CPwrPlugin::SaveSettingToAttributes(const TDesC8& aSetting, TInt aIndex)
+    {
+    // find the equal mark from the setting line
+    TInt sepPos = aSetting.Find(KSettingItemSeparator);
+    // check that '=' is found
+    if (sepPos > 0)
+        {
+        // check that the element matches
+        if (aSetting.Left(sepPos).CompareF(KEnabled) == 0)
+            {
+            TBool en;
+            CSamplerPluginInterface::Str2Bool(aSetting.Right(aSetting.Length()-sepPos-1), en);
+            if(en != iSamplerAttributes->At(aIndex).iEnabled)
+                {
+                iSamplerAttributes->At(aIndex).iEnabled = en;
+                }
+            }
+        else if (aSetting.Left(sepPos).CompareF(KSamplingPeriodMs) == 0)
+            {
+            TInt sr;
+            CSamplerPluginInterface::Str2Int(aSetting.Right(aSetting.Length()-sepPos-1), sr);
+            if(sr != iSamplerAttributes->At(aIndex).iSampleRate)
+                {
+                iSamplerAttributes->At(aIndex).iSampleRate = sr;
+                }
+            }
+        }
+    }
+
+TInt CPwrPlugin::GetSamplerType()
+    {
+    return iSamplerType;
+    }
+
+TInt CPwrPlugin::ResetAndActivateL(CProfilerSampleStream& aStream) 
+    {
+    LOGTEXT(_L("CPwrPlugin::ResetAndActivate() - entry"));
+    // check if sampler enabled
+    if(iSamplerAttributes->At(0).iEnabled)
+        {
+        // create a new listener instance for every trace, destroy it on stop
+        iPowerListener = CProfilerPowerListener::NewL(this);
+
+        iStream = &aStream;
+        TInt length = this->CreateFirstSample();
+        iVersion[0] = (TUint8)length;
+        LOGSTRING2("CPwrPlugin::ResetAndActivate() - AddSample, length %d", length);
+        TInt ret = this->AddSample(iVersion, length+1, 0);
+
+        LOGSTRING2("CPwrPlugin::ConstructL() - sampling period %d", this->iPeriod);
+
+        HBufC8* iBufRes = HBufC8::NewMaxLC(10);
+        TPtr8 iPtrRes = iBufRes->Des();
+
+        // check if sampling rate set to something reasonable, relevant only in SYNC case
+        if(iSamplerAttributes->At(0).iSampleRate != -1)
+            {
+            iPtrRes.Num(iSamplerAttributes->At(0).iSampleRate);
+            }
+        else
+            {
+            iPtrRes.Append(KNullDesC8);
+            }
+
+        // set disabled
+        SetEnabled(ETrue); 
+
+        // activate power listener
+        ret = iPowerListener->StartL(iPtrRes);
+        LOGTEXT(_L("CPwrPlugin::ResetAndActivate() - exit"));
+
+        CleanupStack::PopAndDestroy();
+        
+        if(ret != KErrNone)
+            return ret;
+        }
+    return KErrNone;
+    }
+
+TInt CPwrPlugin::CreateFirstSample() 
+    {
+    LOGTEXT(_L("CPwrPlugin::CreateFirstSample - entry"));
+    this->iVersionDescriptor.Zero();
+    this->iVersionDescriptor.Append(_L8("Bappea_PWR_V"));
+    this->iVersionDescriptor.Append(PROFILER_PWR_SAMPLER_VERSION);
+    LOGTEXT(_L("CPwrPlugin::CreateFirstSample - exit"));
+    return (TInt)(this->iVersionDescriptor.Length());
+    }
+
+TInt CPwrPlugin::StopSampling() 
+    {
+    if(iPowerListener)
+        {
+        iPowerListener->Stop();
+        delete iPowerListener;
+        iPowerListener = NULL;
+        }
+
+    // set disabled
+    SetEnabled(EFalse);
+
+    return KErrNone;
+    }
+
+
+/*
+ *
+ * class CProfilerPowerListener implementation
+ * 
+ */
+
+CProfilerPowerListener::CProfilerPowerListener(CPwrPlugin* aSampler) :
+    iPwrSamplingPeriod(0),
+    iOriginalReportingPeriod(0),
+    iNominalCapa(0),
+    iVoltage(0), 
+    iCurrent(0),
+    iPowerAPI(0)
+#ifdef PWR_SAMPLER_BACKLIGHT
+    ,iLightAPI(0),
+    iBackLightStatus(CHWRMLight::ELightStatusUnknown)
+#endif
+
+    {
+    LOGTEXT(_L("CProfilerPowerListener::CProfilerPowerListener() - konstuktori"));
+    this->iSampler = aSampler;
+    LOGTEXT(_L("CProfilerPowerListener::CProfilerPowerListener() - konstuktori exit"));
+    }
+
+CProfilerPowerListener* CProfilerPowerListener::NewL(CPwrPlugin* aSampler)
+    {
+    LOGTEXT(_L("CProfilerPowerListener::NewL() - entry"));
+    CProfilerPowerListener* self = new (ELeave) CProfilerPowerListener(aSampler);
+    CleanupStack::PushL( self );
+    self->ConstructL();
+    CleanupStack::Pop();
+    LOGTEXT(_L("CProfilerPowerListener::NewL() - exit"));
+    return self;
+    }
+
+void CProfilerPowerListener::ConstructL()
+    {
+    LOGTEXT(_L("CProfilerPowerListener::ConstructL() - entry"));
+    iSampleStartTime = 0;
+    LOGTEXT(_L("CProfilerPowerListener::ConstructL() - exit"));
+    }
+
+CProfilerPowerListener::~CProfilerPowerListener() 
+    {
+    LOGTEXT(_L("CProfilerPowerListener::~CProfilerPowerListener() - entry"));
+
+    if (iPowerAPI)
+        {
+        delete iPowerAPI;
+        iPowerAPI = 0;
+        }
+#ifdef PWR_SAMPLER_BACKLIGHT
+    if (iLightAPI)
+        {
+        delete iLightAPI;
+        iLightAPI = 0;
+        }
+#endif
+
+    LOGTEXT(_L("CProfilerPowerListener::~CProfilerPowerListener() - exit"));
+    }
+
+TInt CProfilerPowerListener::DisplayNotifierL(const TDesC& aLine1, const TDesC& aLine2, const TDesC& aButton1, const TDesC& aButton2)
+    {
+    RNotifier notifier;
+    TRequestStatus stat;
+
+    TInt buttonValue(0);
+
+    User::LeaveIfError(notifier.Connect());
+
+    notifier.Notify(aLine1, aLine2, aButton1, aButton2, buttonValue, stat);
+    User::WaitForRequest(stat);
+
+    notifier.Close();
+    return buttonValue;
+    }
+
+
+TInt CProfilerPowerListener::StartL(const TDesC8& aBuf)
+    {
+    LOGTEXT(_L("CProfilerPowerListener::StartL() - entry"));
+
+    // get the property value
+    TInt r = RProperty::Get(KGppPropertyCat, EGppPropertySyncSampleNumber, iSampleStartTime);
+    if(r != KErrNone)
+        {
+        LOGSTRING2("CProfilerPowerListener::StartL() - getting iSyncOffset failed, error %d", r);
+        }
+
+   // check if given sampling period is valid
+    if(aBuf.CompareF(KNullDesC8)!= 0)
+        {
+        TLex8* lex = new TLex8(aBuf);
+        lex->Val(iPwrSamplingPeriod);
+        delete lex;
+        }
+    else
+        {
+        // set default period
+        iPwrSamplingPeriod = 250;
+        }
+
+    // Check that sampling period is in allowed range
+    if (KMinSampleInterval > 0 && iPwrSamplingPeriod < KMinSampleInterval)
+        {
+        iPwrSamplingPeriod = KMinSampleInterval;
+        }
+
+    LOGSTRING2("CProfilerPowerListener::StartL() - Sampling period %d", iPwrSamplingPeriod);
+
+    // Start monitoring voltage and current
+    iPowerAPI = CHWRMPower::NewL();
+    iPowerAPI->SetPowerReportObserver(this);
+
+    // Read HWRM reporting settings from central repository
+    CRepository* centRep = CRepository::NewL(KCRUidPowerSettings);
+    TInt baseInterval(0);
+    User::LeaveIfError(centRep->Get(KPowerBaseTimeInterval, baseInterval));
+    User::LeaveIfError(centRep->Get(KPowerMaxReportingPeriod, iOriginalReportingPeriod));
+
+    LOGSTRING2("CProfilerPowerListener::StartL() - HWRM base power report interval: %d", baseInterval);
+    LOGSTRING2("CProfilerPowerListener::StartL() - Original HWRM max power reporting period: %d", iOriginalReportingPeriod);
+
+    User::LeaveIfError(centRep->Set(KPowerMaxReportingPeriod, KReportingPeriodInfinite));
+
+    // Power reporting interval reading may return too low value sometimes. Minimum value expected to be 250ms.
+    if ( baseInterval < KMinSampleInterval )
+        {
+        baseInterval = KMinSampleInterval;
+        LOGSTRING2("CProfilerPowerListener::StartL() - Power report interval too low. Changed to: %d", baseInterval);
+        }
+
+    // Power reporting period is multiplier of HWRM base period
+    TInt intervalMultiplier = iPwrSamplingPeriod / baseInterval;
+
+    if (intervalMultiplier < 1)
+        {
+        intervalMultiplier = 1;
+        }
+
+    LOGSTRING2("CProfilerPowerListener::StartL() - Reporting period multiplier: %d", intervalMultiplier);
+
+    TRequestStatus status(KRequestPending);
+    iPowerAPI->StartAveragePowerReporting(status, intervalMultiplier);
+    User::WaitForRequest(status);
+
+    if (status.Int() != KErrNone)
+        {
+        LOGTEXT(_L("CProfilerPowerListener::StartL() - Failed to initialize power reporting"));
+
+        DisplayNotifierL(KPowerTextLine1, KPowerTextLine2, KButtonOk, KNullDesC);
+
+        return status.Int();
+        }
+
+#ifdef PWR_SAMPLER_BACKLIGHT
+    // Start monitoring backlight status
+    iLightAPI = CHWRMLight::NewL(this);
+#endif
+
+    LOGTEXT(_L("CProfilerPowerListener::StartL() - exit"));
+    return KErrNone;
+    }
+
+void CProfilerPowerListener::Sample()
+    {
+    LOGTEXT(_L("CProfilerPowerListener::Sample() - entry"));
+
+    TRequestStatus status;
+    CHWRMPower::TBatteryConsumptionData consumptionData;
+
+    iPowerAPI->GetBatteryInfo(status, consumptionData);
+    User::WaitForRequest(status);
+
+    // Data is valid only if status == KErrNone 
+    if (status.Int() != KErrNone)
+        {
+        LOGSTRING2("CProfilerPowerListener::Sample() - Getting battery info failed with code: ", status.Int());
+        iNominalCapa = 0;
+        }
+    else
+        {
+        iNominalCapa = consumptionData.iNominalCapacity;
+        }
+
+    // Space for GPP sample time        
+    //TUint32 sampleTime = iSampler->iStream->iSampler->GetSampleTime();
+    TUint32 sampleTime = User::NTickCount() - iSampleStartTime;
+    LOGSTRING2("CProfilerPowerListener::Sample() - Sample time: %d", sampleTime);
+    LOGSTRING2("CProfilerPowerListener::Sample() - Nominal capacitance: %d", iNominalCapa);
+    LOGSTRING2("CProfilerPowerListener::Sample() - Voltage: %d", iVoltage);
+    LOGSTRING2("CProfilerPowerListener::Sample() - Current: %d", iCurrent);
+#ifdef PWR_SAMPLER_BACKLIGHT
+    LOGSTRING2("CProfilerPowerListener::Sample() - Backlight status: %d", (TUint8)iBackLightStatus);
+#endif
+
+    iSample[0] = iNominalCapa;
+    iSample[1] = iNominalCapa >> 8;
+    iSample[2] = iVoltage;
+    iSample[3] = iVoltage >> 8;
+    iSample[4] = iCurrent;
+    iSample[5] = iCurrent >> 8;
+    iSample[6] = iCurrent >> 16;
+    iSample[7] = iCurrent >> 24;
+#ifdef PWR_SAMPLER_BACKLIGHT
+    iSample[8] = (TUint8)iBackLightStatus;
+    iSample[9] = sampleTime;
+    iSample[10] = sampleTime >> 8;
+    iSample[11] = sampleTime >> 16;
+    iSample[12] = sampleTime >> 24;
+
+    iSampler->AddSample(iSample, 13, 0);
+#else
+    iSample[8] = sampleTime;
+    iSample[9] = sampleTime >> 8;
+    iSample[10] = sampleTime >> 16;
+    iSample[11] = sampleTime >> 24;
+
+    iSampler->AddSample(iSample, 12, 0);
+#endif
+
+    LOGTEXT(_L("CProfilerPowerListener::Sample() - exit"));
+    }
+
+TInt CProfilerPowerListener::Stop() 
+    {
+    LOGTEXT(_L("CProfilerPowerListener::Stop() - entry"));
+
+    if (iPowerAPI)
+        {
+        TRAPD(err, iPowerAPI->StopAveragePowerReportingL());
+        if(err != KErrNone)
+            {
+            LOGSTRING2("CProfilerPowerListener::Stop() - Failed to stop power reporting: %d", err);
+            }
+        else
+            {
+            LOGTEXT(_L("CProfilerPowerListener::Stop() - Stopped power monitoring"));
+            }
+        delete iPowerAPI;
+        iPowerAPI = 0;
+
+        // Restore original value to max sampling period
+        CRepository* centRep = 0;
+        TRAP(err, centRep = CRepository::NewL(KCRUidPowerSettings));
+        if (err != KErrNone)
+            {
+            LOGSTRING2("CProfilerPowerListener::Stop() - Failed to open Central Repository: %d", err);
+            }
+        else
+            {
+            err = centRep->Set(KPowerMaxReportingPeriod, iOriginalReportingPeriod);
+            if(err != KErrNone)
+                {
+                LOGSTRING2("CProfilerPowerListener::Stop() - Failed to restore max sampling period: %d", err);
+                }
+            }
+        }
+#ifdef PWR_SAMPLER_BACKLIGHT
+    if (iLightAPI)
+        {
+        delete iLightAPI;
+        iLightAPI = 0;
+        }
+#endif
+
+    LOGTEXT(_L("CProfilerPowerListener::Stop() - exit"));
+    return KErrNone;
+    }
+
+void CProfilerPowerListener::PowerMeasurement(TInt aErr, CHWRMPower::TBatteryPowerMeasurementData& aMeasurement)
+    {
+    LOGTEXT(_L("CProfilerPowerListener::PowerMeasurement - entry"));
+
+    if (aErr == KErrNone)
+        {
+        LOGSTRING3("CProfilerPowerListener::PowerMeasurement - Previous values - Voltage: %d Current: %d", iVoltage, iCurrent);
+        iVoltage = aMeasurement.iAverageVoltage;
+        iCurrent = aMeasurement.iAverageCurrent;
+        LOGSTRING3("CProfilerPowerListener::PowerMeasurement - New values - Voltage: %d Current: %d", iVoltage, iCurrent);
+
+        this->Sample();
+        }
+    else
+        {
+        LOGSTRING2("CProfilerPowerListener::PowerMeasurement - Failed with error code: %d", aErr);
+        DisplayNotifierL(KPowerTextLine1, KPowerTextErrorSampling, KButtonOk, KNullDesC);
+        }
+    LOGTEXT(_L("CProfilerPowerListener::PowerMeasurement - exit"));
+    }
+
+#ifdef PWR_SAMPLER_BACKLIGHT
+void CProfilerPowerListener::LightStatusChanged(TInt aTarget, CHWRMLight::TLightStatus aStatus)
+    {
+    LOGTEXT(_L("CProfilerPowerListener::LightStatusChanged - entry"));
+    LOGSTRING3("CProfilerPowerListener::LightStatusChanged - Target: %d Status: %d", aTarget, aStatus);
+
+    if (aTarget == CHWRMLight::EPrimaryDisplay)
+        {
+        LOGSTRING2("CProfilerPowerListener::LightStatusChanged - Previous light status: %d", iBackLightStatus);
+        iBackLightStatus = aStatus;
+        LOGSTRING2("CProfilerPowerListener::LightStatusChanged - New light status: %d", iBackLightStatus);
+
+        this->Sample();
+        }
+    LOGTEXT(_L("CProfilerPowerListener::LightStatusChanged - exit"));
+    }
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/piprofiler/plugins/PWRplugin/src/PwrPluginImplementationTable.cpp	Fri Aug 27 11:37:29 2010 +0300
@@ -0,0 +1,39 @@
+/*
+* Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+* All rights reserved.
+* This component and the accompanying materials are made available
+* under the terms of "Eclipse Public License v1.0"
+* which accompanies this distribution, and is available
+* at the URL "http://www.eclipse.org/legal/epl-v10.html".
+*
+* Initial Contributors:
+* Nokia Corporation - initial contribution.
+*
+* Contributors:
+*
+* Description:  
+*
+*/
+
+
+// INCLUDE FILES
+#include <e32std.h>
+#include <ecom/implementationproxy.h>
+
+#include "PwrPlugin.h"
+
+
+// Provides a key value pair table, this is used to identify
+// the correct construction function for the requested interface.
+const TImplementationProxy ImplementationTable[] =
+{
+         IMPLEMENTATION_PROXY_ENTRY(0x2001E5B9,  CPwrPlugin::NewL),
+};
+
+// Function used to return an instance of the proxy table.
+EXPORT_C const TImplementationProxy* ImplementationGroupProxy(TInt& aTableCount)
+{
+    aTableCount = sizeof(ImplementationTable) / sizeof(TImplementationProxy);
+    return ImplementationTable;
+}
+
--- a/piprofiler/rom/piprofiler.iby	Mon Aug 23 15:29:36 2010 +0300
+++ b/piprofiler/rom/piprofiler.iby	Fri Aug 27 11:37:29 2010 +0300
@@ -22,11 +22,11 @@
 // PI Profiler Engine itself 
 file=ABI_DIR\BUILD_DIR\PIProfilerEngine.exe						sys\bin\PIProfilerEngine.exe
 file=ABI_DIR\BUILD_DIR\PIProfiler.exe							sys\bin\PIProfiler.exe
-data=ZSYSTEM\Install\PIProfiler_stub.sis						system\install\PIProfiler_stub.sis
 
 // sampler plugins
 // NOTE: Mandatory kernel driver included in piprofiler_ldd.iby
 ECOM_PLUGIN(PIProfilerGenerals.dll, PIProfilerGenerals.rsc)
+ECOM_PLUGIN(PIProfilerPWR.dll, PIProfilerPWR.rsc)
 
 ECOM_PLUGIN(PIProfilerBUP.dll, PIProfilerBUP.rsc)
 file=ABI_DIR\BUILD_DIR\PIProfilerTouchEventAnim.dll				sys\bin\PIProfilerTouchEventAnim.dll
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/piprofiler/rom/piprofiler_s2.iby	Fri Aug 27 11:37:29 2010 +0300
@@ -0,0 +1,37 @@
+/*
+* Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+* All rights reserved.
+* This component and the accompanying materials are made available
+* under the terms of "Eclipse Public License v1.0"
+* which accompanies this distribution, and is available
+* at the URL "http://www.eclipse.org/legal/epl-v10.html".
+*
+* Initial Contributors:
+* Nokia Corporation - initial contribution.
+*
+* Contributors:
+*
+* Description:  
+*
+*/
+
+
+#ifndef __PIPROFILER__
+#define __PIPROFILER__
+
+// PI Profiler Engine itself 
+file=ABI_DIR\BUILD_DIR\PIProfilerEngine.exe						sys\bin\PIProfilerEngine.exe
+file=ABI_DIR\BUILD_DIR\PIProfiler.exe							sys\bin\PIProfiler.exe
+
+// sampler plugins
+// NOTE: Mandatory kernel driver included in piprofiler_ldd.iby
+ECOM_PLUGIN(PIProfilerGenerals.dll, PIProfilerGenerals.rsc)
+
+ECOM_PLUGIN(PIProfilerBUP.dll, PIProfilerBUP.rsc)
+file=ABI_DIR\BUILD_DIR\PIProfilerTouchEventAnim.dll				sys\bin\PIProfilerTouchEventAnim.dll
+
+// Writer plugins
+ECOM_PLUGIN(piprofilerdebugwriter.dll, piprofilerdebugwriter.rsc)
+ECOM_PLUGIN(piprofilerdiskwriter.dll, piprofilerdiskwriter.rsc)
+
+#endif //__PIPROFILER__
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/piprofiler/symbian_version.hrh	Fri Aug 27 11:37:29 2010 +0300
@@ -0,0 +1,43 @@
+/*
+* Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+* All rights reserved.
+* This component and the accompanying materials are made available
+* under the terms of "Eclipse Public License v1.0"
+* which accompanies this distribution, and is available
+* at the URL "http://www.eclipse.org/legal/epl-v10.html".
+*
+* Initial Contributors:
+* Nokia Corporation - initial contribution.
+*
+* Contributors:
+*
+* Description: Symbian version configuration file 
+*
+*/
+
+#ifndef __SYMBIAN_VERSION_HRH
+#define __SYMBIAN_VERSION_HRH
+
+// S60 and Symbian version number enumeration definitions
+
+#define S60_30                                              30
+#define S60_31                                              31
+#define S60_32                                              32
+#define S60_50                                              50
+#define S60_51                                              91
+#define S60_52                                              92
+#define SYMBIAN_1                                           50
+#define SYMBIAN_2                                           91
+#define SYMBIAN_3                                           92
+#define SYMBIAN_4                                           101
+
+
+/**
+ * Defines the S60 or Symbian version used by this component. This flag can be
+ * used to variate the source code based on the SDK in use. The value of the
+ * flag should be always changed to reflect the current build environment.
+ */
+#define SYMBIAN_VERSION_SUPPORT                              SYMBIAN_4
+
+
+#endif  // __SYMBIAN_VERSION_HRH