# HG changeset patch
# User hgs
# Date 1282898249 -10800
# Node ID 0ff24a8f6ca29ed379b0410731a49d250104fe25
# Parent 838cdffd57cec4730b0287ba5ac5b1f94bcd0efd
201033
diff -r 838cdffd57ce -r 0ff24a8f6ca2 debugsrv/runmodedebug/build.config.xml
--- /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 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+]>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff -r 838cdffd57ce -r 0ff24a8f6ca2 debugsrv/runmodedebug/group/bld.inf
--- /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
diff -r 838cdffd57ce -r 0ff24a8f6ca2 debugsrv/runmodedebug/rmdebug_test/eabi/t_rmdebug_dllu.def
--- /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
+
diff -r 838cdffd57ce -r 0ff24a8f6ca2 debugsrv/runmodedebug/rmdebug_test/group/bld.inf
--- /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"
diff -r 838cdffd57ce -r 0ff24a8f6ca2 debugsrv/runmodedebug/rmdebug_test/group/e32test.bld
--- /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
diff -r 838cdffd57ce -r 0ff24a8f6ca2 debugsrv/runmodedebug/rmdebug_test/group/mk_rmdbg_test.bat
--- /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
diff -r 838cdffd57ce -r 0ff24a8f6ca2 debugsrv/runmodedebug/rmdebug_test/rm_debug/basic_tests/r_kernel_low_memory_security_svr_session.cpp
--- /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;
+ }
+
diff -r 838cdffd57ce -r 0ff24a8f6ca2 debugsrv/runmodedebug/rmdebug_test/rm_debug/basic_tests/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_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
+
diff -r 838cdffd57ce -r 0ff24a8f6ca2 debugsrv/runmodedebug/rmdebug_test/rm_debug/basic_tests/r_low_memory_security_svr_session.cpp
--- /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
+
+// 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;
+ }
+
diff -r 838cdffd57ce -r 0ff24a8f6ca2 debugsrv/runmodedebug/rmdebug_test/rm_debug/basic_tests/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_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
+
+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
+
diff -r 838cdffd57ce -r 0ff24a8f6ca2 debugsrv/runmodedebug/rmdebug_test/rm_debug/basic_tests/r_user_low_memory_security_svr_session.cpp
--- /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
+#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
+ }
+
diff -r 838cdffd57ce -r 0ff24a8f6ca2 debugsrv/runmodedebug/rmdebug_test/rm_debug/basic_tests/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/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
+
diff -r 838cdffd57ce -r 0ff24a8f6ca2 debugsrv/runmodedebug/rmdebug_test/rm_debug/basic_tests/t_rmdebug2.cpp
--- /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
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include "t_rmdebug_dll.h"
+
+#include
+#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 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 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 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(®), sizeof(TRegisterInfo));
+ }
+
+ TRegisterInfo reg = ERegisterR13Irq;
+ ids.Append(reinterpret_cast(®), 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(®1), 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(&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(&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 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 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(®1), 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(": 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& 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 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>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; iClientAppL());
+ __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 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 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();
+ }
diff -r 838cdffd57ce -r 0ff24a8f6ca2 debugsrv/runmodedebug/rmdebug_test/rm_debug/basic_tests/t_rmdebug2.h
--- /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& 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
diff -r 838cdffd57ce -r 0ff24a8f6ca2 debugsrv/runmodedebug/rmdebug_test/rm_debug/basic_tests/t_rmdebug2_oemtoken.cpp
--- /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
+#include
+
+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
diff -r 838cdffd57ce -r 0ff24a8f6ca2 debugsrv/runmodedebug/rmdebug_test/rm_debug/common/t_debug_logging.h
--- /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
+
+ #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
+
+ #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
diff -r 838cdffd57ce -r 0ff24a8f6ca2 debugsrv/runmodedebug/rmdebug_test/rm_debug/common/t_target_launcher.cpp
--- /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
+// +m
+// +o
+//
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#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( "Launcher Process()" );
+
+ CTrapCleanup* trap = CTrapCleanup::New();
+ if (!trap)
+ return KErrNoMemory;
+
+ TRAPD(err, MainL());
+ RDebug::Printf( "< Target launching returned %d", err);
+
+ delete trap;
+
+ return err;
+ }
diff -r 838cdffd57ce -r 0ff24a8f6ca2 debugsrv/runmodedebug/rmdebug_test/rm_debug/common/t_target_launcher.h
--- /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
diff -r 838cdffd57ce -r 0ff24a8f6ca2 debugsrv/runmodedebug/rmdebug_test/rm_debug/debug_targets/d_demand_paging.cia
--- /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
+
+// 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");
+ }
+
diff -r 838cdffd57ce -r 0ff24a8f6ca2 debugsrv/runmodedebug/rmdebug_test/rm_debug/debug_targets/d_demand_paging.h
--- /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
diff -r 838cdffd57ce -r 0ff24a8f6ca2 debugsrv/runmodedebug/rmdebug_test/rm_debug/debug_targets/d_rmdebug_bkpt_test.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
diff -r 838cdffd57ce -r 0ff24a8f6ca2 debugsrv/runmodedebug/rmdebug_test/rm_debug/debug_targets/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_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
diff -r 838cdffd57ce -r 0ff24a8f6ca2 debugsrv/runmodedebug/rmdebug_test/rm_debug/debug_targets/d_rmdebug_step_test.h
--- /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
diff -r 838cdffd57ce -r 0ff24a8f6ca2 debugsrv/runmodedebug/rmdebug_test/rm_debug/debug_targets/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.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
diff -r 838cdffd57ce -r 0ff24a8f6ca2 debugsrv/runmodedebug/rmdebug_test/rm_debug/debug_targets/d_rmdebug_step_test_armv4.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.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
diff -r 838cdffd57ce -r 0ff24a8f6ca2 debugsrv/runmodedebug/rmdebug_test/rm_debug/debug_targets/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_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
diff -r 838cdffd57ce -r 0ff24a8f6ca2 debugsrv/runmodedebug/rmdebug_test/rm_debug/debug_targets/d_rmdebugthread.cpp
--- /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
+#include
+#include
+#include "d_rmdebugthread.h"
+
+EXPORT_C TBuf8 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;
+ }
diff -r 838cdffd57ce -r 0ff24a8f6ca2 debugsrv/runmodedebug/rmdebug_test/rm_debug/debug_targets/d_rmdebugthread.h
--- /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
diff -r 838cdffd57ce -r 0ff24a8f6ca2 debugsrv/runmodedebug/rmdebug_test/rm_debug/debug_targets/d_rmdebugthread2.cpp
--- /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
+#include
+#include
+#include
+#include "d_rmdebugthread2.h"
+
+#include "d_rmdebug_step_test.h"
+#include "d_rmdebug_bkpt_test.h"
+#include "d_demand_paging.h"
+
+TBuf8 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;
+ }
diff -r 838cdffd57ce -r 0ff24a8f6ca2 debugsrv/runmodedebug/rmdebug_test/rm_debug/debug_targets/d_rmdebugthread2.h
--- /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
+
+#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
diff -r 838cdffd57ce -r 0ff24a8f6ca2 debugsrv/runmodedebug/rmdebug_test/rm_debug/debug_targets/d_rmdebugthreadasm.cia
--- /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
+//#include
+//#include
+//#include "d_rmdebugthread.h"
+
+EXPORT_C __NAKED__ void RMDebug_BranchTst1( void )
+//
+//
+//
+{
+ asm("mov r0, #0 "); // aResult==KErrNone
+ asm("bx lr "); // Return
+}
+
diff -r 838cdffd57ce -r 0ff24a8f6ca2 debugsrv/runmodedebug/rmdebug_test/rm_debug/debug_targets/d_rmdebugthreadasm2.cia
--- /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
+}
diff -r 838cdffd57ce -r 0ff24a8f6ca2 debugsrv/runmodedebug/rmdebug_test/rm_debug/debug_targets/t_rmdebug_app.cpp
--- /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
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+
+#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 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\n\t: delay in microseconds before calling target function\n");
+ RDebug::Printf("\t-f\n\t: enumerator from TDebugFunctionType representing function to call\n");
+ RDebug::Printf("\t-e\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;
+ }
+
diff -r 838cdffd57ce -r 0ff24a8f6ca2 debugsrv/runmodedebug/rmdebug_test/rm_debug/debug_targets/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_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
+
diff -r 838cdffd57ce -r 0ff24a8f6ca2 debugsrv/runmodedebug/rmdebug_test/rm_debug/debug_targets/t_rmdebug_dll.cpp
--- /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
+#include
+#include
+#include "t_rmdebug_dll.h"
+
+EXPORT_C TUid GetDSSUid()
+ {
+ return Debug::KUidDebugSecurityServer;
+ }
+
diff -r 838cdffd57ce -r 0ff24a8f6ca2 debugsrv/runmodedebug/rmdebug_test/rm_debug/debug_targets/t_rmdebug_dll.h
--- /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
+
+/**
+ 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();
diff -r 838cdffd57ce -r 0ff24a8f6ca2 debugsrv/runmodedebug/rmdebug_test/rm_debug/debug_targets/t_rmdebug_security.cpp
--- /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
+#include
+#include
+#include
+#include
+#include
+#include
+#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;
+ }
diff -r 838cdffd57ce -r 0ff24a8f6ca2 debugsrv/runmodedebug/rmdebug_test/rm_debug/debug_targets/t_rmdebug_security.h
--- /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
diff -r 838cdffd57ce -r 0ff24a8f6ca2 debugsrv/runmodedebug/rmdebug_test/rm_debug/group/bld.inf
--- /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
+
+
diff -r 838cdffd57ce -r 0ff24a8f6ca2 debugsrv/runmodedebug/rmdebug_test/rm_debug/group/mytraces_rm_debug.txt
--- /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
diff -r 838cdffd57ce -r 0ff24a8f6ca2 debugsrv/runmodedebug/rmdebug_test/rm_debug/group/mytraces_rm_debug_ekern.txt
--- /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
diff -r 838cdffd57ce -r 0ff24a8f6ca2 debugsrv/runmodedebug/rmdebug_test/rm_debug/group/rmdbg_test.pkg
--- /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"
diff -r 838cdffd57ce -r 0ff24a8f6ca2 debugsrv/runmodedebug/rmdebug_test/rm_debug/group/rmdebug.iby
--- /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
diff -r 838cdffd57ce -r 0ff24a8f6ca2 debugsrv/runmodedebug/rmdebug_test/rm_debug/group/t_multi_agent_launcher.mmp
--- /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
diff -r 838cdffd57ce -r 0ff24a8f6ca2 debugsrv/runmodedebug/rmdebug_test/rm_debug/group/t_performance_test.mmp
--- /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
diff -r 838cdffd57ce -r 0ff24a8f6ca2 debugsrv/runmodedebug/rmdebug_test/rm_debug/group/t_rmdebug.iby
--- /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
diff -r 838cdffd57ce -r 0ff24a8f6ca2 debugsrv/runmodedebug/rmdebug_test/rm_debug/group/t_rmdebug.mmp
--- /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
diff -r 838cdffd57ce -r 0ff24a8f6ca2 debugsrv/runmodedebug/rmdebug_test/rm_debug/group/t_rmdebug2.mmh
--- /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
diff -r 838cdffd57ce -r 0ff24a8f6ca2 debugsrv/runmodedebug/rmdebug_test/rm_debug/group/t_rmdebug2.mmp
--- /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
diff -r 838cdffd57ce -r 0ff24a8f6ca2 debugsrv/runmodedebug/rmdebug_test/rm_debug/group/t_rmdebug2_allcaps.mmp
--- /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
+
diff -r 838cdffd57ce -r 0ff24a8f6ca2 debugsrv/runmodedebug/rmdebug_test/rm_debug/group/t_rmdebug2_allcapstoken.mmp
--- /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
diff -r 838cdffd57ce -r 0ff24a8f6ca2 debugsrv/runmodedebug/rmdebug_test/rm_debug/group/t_rmdebug2_oem.mmp
--- /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
+
diff -r 838cdffd57ce -r 0ff24a8f6ca2 debugsrv/runmodedebug/rmdebug_test/rm_debug/group/t_rmdebug2_oem2.mmp
--- /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
+
diff -r 838cdffd57ce -r 0ff24a8f6ca2 debugsrv/runmodedebug/rmdebug_test/rm_debug/group/t_rmdebug2_oemtoken.mmp
--- /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
diff -r 838cdffd57ce -r 0ff24a8f6ca2 debugsrv/runmodedebug/rmdebug_test/rm_debug/group/t_rmdebug2_oemtoken2.mmp
--- /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
diff -r 838cdffd57ce -r 0ff24a8f6ca2 debugsrv/runmodedebug/rmdebug_test/rm_debug/group/t_rmdebug_app.mmp
--- /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
diff -r 838cdffd57ce -r 0ff24a8f6ca2 debugsrv/runmodedebug/rmdebug_test/rm_debug/group/t_rmdebug_app1.mmp
--- /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
diff -r 838cdffd57ce -r 0ff24a8f6ca2 debugsrv/runmodedebug/rmdebug_test/rm_debug/group/t_rmdebug_app10.mmp
--- /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
diff -r 838cdffd57ce -r 0ff24a8f6ca2 debugsrv/runmodedebug/rmdebug_test/rm_debug/group/t_rmdebug_app2.mmp
--- /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
diff -r 838cdffd57ce -r 0ff24a8f6ca2 debugsrv/runmodedebug/rmdebug_test/rm_debug/group/t_rmdebug_app3.mmp
--- /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
diff -r 838cdffd57ce -r 0ff24a8f6ca2 debugsrv/runmodedebug/rmdebug_test/rm_debug/group/t_rmdebug_app4.mmp
--- /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
diff -r 838cdffd57ce -r 0ff24a8f6ca2 debugsrv/runmodedebug/rmdebug_test/rm_debug/group/t_rmdebug_app5.mmp
--- /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
diff -r 838cdffd57ce -r 0ff24a8f6ca2 debugsrv/runmodedebug/rmdebug_test/rm_debug/group/t_rmdebug_app6.mmp
--- /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
diff -r 838cdffd57ce -r 0ff24a8f6ca2 debugsrv/runmodedebug/rmdebug_test/rm_debug/group/t_rmdebug_app7.mmp
--- /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
diff -r 838cdffd57ce -r 0ff24a8f6ca2 debugsrv/runmodedebug/rmdebug_test/rm_debug/group/t_rmdebug_app8.mmp
--- /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
diff -r 838cdffd57ce -r 0ff24a8f6ca2 debugsrv/runmodedebug/rmdebug_test/rm_debug/group/t_rmdebug_app9.mmp
--- /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
diff -r 838cdffd57ce -r 0ff24a8f6ca2 debugsrv/runmodedebug/rmdebug_test/rm_debug/group/t_rmdebug_dll.mmp
--- /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
diff -r 838cdffd57ce -r 0ff24a8f6ca2 debugsrv/runmodedebug/rmdebug_test/rm_debug/group/t_rmdebug_multi_agent.mmp
--- /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
diff -r 838cdffd57ce -r 0ff24a8f6ca2 debugsrv/runmodedebug/rmdebug_test/rm_debug/group/t_rmdebug_multi_target.mmp
--- /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
diff -r 838cdffd57ce -r 0ff24a8f6ca2 debugsrv/runmodedebug/rmdebug_test/rm_debug/group/t_rmdebug_performance_allcapstoken.mmp
--- /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
diff -r 838cdffd57ce -r 0ff24a8f6ca2 debugsrv/runmodedebug/rmdebug_test/rm_debug/group/t_rmdebug_security0.mmp
--- /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
diff -r 838cdffd57ce -r 0ff24a8f6ca2 debugsrv/runmodedebug/rmdebug_test/rm_debug/group/t_rmdebug_security1.mmp
--- /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
diff -r 838cdffd57ce -r 0ff24a8f6ca2 debugsrv/runmodedebug/rmdebug_test/rm_debug/group/t_rmdebug_security2.mmp
--- /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
diff -r 838cdffd57ce -r 0ff24a8f6ca2 debugsrv/runmodedebug/rmdebug_test/rm_debug/group/t_rmdebug_security3.mmp
--- /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
diff -r 838cdffd57ce -r 0ff24a8f6ca2 debugsrv/runmodedebug/rmdebug_test/rm_debug/group/t_rmdebug_target_launcher.mmp
--- /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
diff -r 838cdffd57ce -r 0ff24a8f6ca2 debugsrv/runmodedebug/rmdebug_test/rm_debug/group/t_rmdebug_tests.iby
--- /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
diff -r 838cdffd57ce -r 0ff24a8f6ca2 debugsrv/runmodedebug/rmdebug_test/rm_debug/multi_agent_tests/t_agent_eventhandler.cpp
--- /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
+#include
+#include
+
+#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!
+ }
+
diff -r 838cdffd57ce -r 0ff24a8f6ca2 debugsrv/runmodedebug/rmdebug_test/rm_debug/multi_agent_tests/t_agent_eventhandler.h
--- /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
+
+
diff -r 838cdffd57ce -r 0ff24a8f6ca2 debugsrv/runmodedebug/rmdebug_test/rm_debug/multi_agent_tests/t_multi_agent.cpp
--- /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
+#include
+#include
+#include
+#include
+#include
+
+
+#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;
+ }
+
diff -r 838cdffd57ce -r 0ff24a8f6ca2 debugsrv/runmodedebug/rmdebug_test/rm_debug/multi_agent_tests/t_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.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
+#include
+#include
+
+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 iTargetList;
+ };
+
+#endif // RMDEBUG_MULTI_AGENT_H
diff -r 838cdffd57ce -r 0ff24a8f6ca2 debugsrv/runmodedebug/rmdebug_test/rm_debug/multi_agent_tests/t_multi_agent_launcher.cpp
--- /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;
+ }
+
diff -r 838cdffd57ce -r 0ff24a8f6ca2 debugsrv/runmodedebug/rmdebug_test/rm_debug/multi_agent_tests/t_multi_agent_launcher.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.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
+
+// 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
+
diff -r 838cdffd57ce -r 0ff24a8f6ca2 debugsrv/runmodedebug/rmdebug_test/rm_debug/multi_target_tests/t_multi_target.cpp
--- /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
+#include
+
+#include
+#include
+
+#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( " 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( " 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;
+ }
diff -r 838cdffd57ce -r 0ff24a8f6ca2 debugsrv/runmodedebug/rmdebug_test/rm_debug/multi_target_tests/t_multi_target.h
--- /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
+
+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 iTargets;
+ TRequestStatus iStatus;
+ Debug::TEventInfo iEventInfo;
+ TPtr8 iEventPtr;
+ };
+
+#endif // RMDEBUG_MULTI_TARGET_H
diff -r 838cdffd57ce -r 0ff24a8f6ca2 debugsrv/runmodedebug/rmdebug_test/rm_debug/performance_test/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_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
+
+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
diff -r 838cdffd57ce -r 0ff24a8f6ca2 debugsrv/runmodedebug/rmdebug_test/rm_debug/performance_test/t_rmdebug_performance_test.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
+#include
+#include
+#include
+#include
+#include
+
+#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;
+ }
+
diff -r 838cdffd57ce -r 0ff24a8f6ca2 debugsrv/runmodedebug/rmdebug_test/rm_debug/performance_test/t_rmdebug_performance_test.h
--- /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
+#include
+#include
+
+/* 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 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 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
+
diff -r 838cdffd57ce -r 0ff24a8f6ca2 debugsrv/runmodedebug/rmdebug_test/rm_debug/scripts/tef_execute_rtests.script
--- /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 ***
diff -r 838cdffd57ce -r 0ff24a8f6ca2 debugsrv/runmodedebug/rmdriver/group/bld.inf
--- /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
diff -r 838cdffd57ce -r 0ff24a8f6ca2 debugsrv/runmodedebug/rmdriver/group/rm_debug_kerneldriver.mmh
--- /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
+
+
+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
diff -r 838cdffd57ce -r 0ff24a8f6ca2 debugsrv/runmodedebug/rmdriver/group/rm_debug_kerneldriver.mmp
--- /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
diff -r 838cdffd57ce -r 0ff24a8f6ca2 debugsrv/runmodedebug/rmdriver/group/rm_debug_svr.iby
--- /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__
diff -r 838cdffd57ce -r 0ff24a8f6ca2 debugsrv/runmodedebug/rmdriver/group/sis/eula.txt
--- /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.
diff -r 838cdffd57ce -r 0ff24a8f6ca2 debugsrv/runmodedebug/rmdriver/group/sis/mk_rmdbg.bat
--- /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
diff -r 838cdffd57ce -r 0ff24a8f6ca2 debugsrv/runmodedebug/rmdriver/group/sis/rmdbg.pkg
--- /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
diff -r 838cdffd57ce -r 0ff24a8f6ca2 debugsrv/runmodedebug/rmdriver/inc/d_debug_agent.h
--- /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
+#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* 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* iRequestGetEventStatus;
+
+ DThread* iClientThread;
+
+ /**
+ * Ring buffer of pending events. Access to it is controlled by
+ * @see iEventQueueLock
+ */
+ RArray 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
+
diff -r 838cdffd57ce -r 0ff24a8f6ca2 debugsrv/runmodedebug/rmdriver/inc/d_debug_agent.inl
--- /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
diff -r 838cdffd57ce -r 0ff24a8f6ca2 debugsrv/runmodedebug/rmdriver/inc/d_debug_functionality.h
--- /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
diff -r 838cdffd57ce -r 0ff24a8f6ca2 debugsrv/runmodedebug/rmdriver/inc/d_driver_event_info.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
+#include
+
+/**
+@file
+@internalComponent
+*/
+
+class TDriverEventInfo
+ {
+public:
+ TDriverEventInfo();
+ void Reset();
+ TInt WriteEventToClientThread(TClientDataRequest* 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 iFileName;
+ TBuf8 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
diff -r 838cdffd57ce -r 0ff24a8f6ca2 debugsrv/runmodedebug/rmdriver/inc/d_list_manager.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
+#include
+#include
+
+/**
+@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& aRomEntryArray, const TLinAddr aAddress) const;
+ TInt GetDirectoryEntries(RPointerArray& aRomEntryArray, const TDesC& aDirectoryName) const;
+ TInt FindDirectory(const TDesC& aDirectory, TLinAddr& aAddress) const;
+ TInt GetDirectoryEntries(RPointerArray& aRomEntryArray, RArray& 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& aSubDirectories) const;
+};
+
+#endif //T_LIST_MANAGER_H
+
diff -r 838cdffd57ce -r 0ff24a8f6ca2 debugsrv/runmodedebug/rmdriver/inc/d_process_tracker.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 iProcesses;
+ RPointerArray iAgentsAttachedToAll;
+ RPointerArray iFrozenThreadSemaphores;
+ };
+
+// static global object
+extern DProcessTracker TheDProcessTracker;
+
+#endif // D_PROCESS_TRACKER_H
diff -r 838cdffd57ce -r 0ff24a8f6ca2 debugsrv/runmodedebug/rmdriver/inc/d_rmd_breakpoints.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
+#include
+#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 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
diff -r 838cdffd57ce -r 0ff24a8f6ca2 debugsrv/runmodedebug/rmdriver/inc/d_rmd_breakpoints_debug.inl
--- /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 );
+ }
+ }
diff -r 838cdffd57ce -r 0ff24a8f6ca2 debugsrv/runmodedebug/rmdriver/inc/d_rmd_stepping.h
--- /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
diff -r 838cdffd57ce -r 0ff24a8f6ca2 debugsrv/runmodedebug/rmdriver/inc/d_rmd_stepping.inl
--- /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
diff -r 838cdffd57ce -r 0ff24a8f6ca2 debugsrv/runmodedebug/rmdriver/inc/d_target_process.h
--- /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 iAgentList;
+
+ RArray iSuspendedThreads;
+
+ RPointerArray iFrozenThreadSemaphores;
+
+};
+
+#endif // D_TARGET_PROCESS_H
+
diff -r 838cdffd57ce -r 0ff24a8f6ca2 debugsrv/runmodedebug/rmdriver/inc/debug_logging.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
+ #include
+
+ #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
+
+ #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
+
diff -r 838cdffd57ce -r 0ff24a8f6ca2 debugsrv/runmodedebug/rmdriver/inc/debug_utils.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
+#include
+
+class DebugUtils
+ {
+public:
+ static DThread* OpenThreadHandle(TUint64 aThreadId);
+ static DProcess* OpenProcessHandle(TUint64 aProcessId);
+ static DThread* OpenFirstThreadForProcess(DProcess* aProcess);
+ };
+
+#endif //DEBUG_UTILS_H
+
diff -r 838cdffd57ce -r 0ff24a8f6ca2 debugsrv/runmodedebug/rmdriver/inc/rm_debug_driver.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 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* iAsyncGetValueRequest;
+};
+
+#endif //__RM_DEBUG_DRIVER_H__
diff -r 838cdffd57ce -r 0ff24a8f6ca2 debugsrv/runmodedebug/rmdriver/inc/rm_debug_eventhandler.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__
diff -r 838cdffd57ce -r 0ff24a8f6ca2 debugsrv/runmodedebug/rmdriver/inc/rm_debug_kerneldriver.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
+
+/**
+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 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 iProcessName;
+ TUint64 iAgentId;
+};
+
+class TEventMetaData
+ {
+public:
+ TBuf8 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(&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(&info),0);
+}
+
+inline TInt RRM_DebugDriver::ClearBreak(const Debug::TBreakId aBreakId)
+{
+ return DoSvControl(EControlClearBreak, reinterpret_cast(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(&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(&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(&info), 0);
+}
+
+inline TInt RRM_DebugDriver::SuspendThread(const TUint32 aThreadId)
+{
+ return DoControl(EControlSuspendThread, reinterpret_cast(aThreadId));
+}
+
+inline TInt RRM_DebugDriver::ResumeThread(const TUint32 aThreadId)
+{
+ return DoSvControl(EControlResumeThread, reinterpret_cast(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(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(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(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(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(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(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(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(&info));
+}
+
+inline TInt RRM_DebugDriver::GetStaticLibraryInfo(const TInt aIndex, Debug::TEventInfo &aInfo)
+{
+ return DoControl(EControlGetStaticLibraryInfo, reinterpret_cast(aIndex), (TAny*)&aInfo);
+}
+
+inline TInt RRM_DebugDriver::GetDebugFunctionalityBufSize(TUint32 &aBufSize)
+{
+ return DoControl(EControlGetDebugFunctionalityBufSize, reinterpret_cast(&aBufSize));
+}
+
+inline TInt RRM_DebugDriver::GetDebugFunctionality(TDes8& aDebugFunctionality)
+{
+ return DoControl(EControlGetDebugFunctionality,reinterpret_cast(&aDebugFunctionality));
+}
+
+inline TInt RRM_DebugDriver::GetMemoryOperationMaxBlockSize(TUint32 &aMaxSize)
+{
+ return DoControl(EControlGetMemoryOperationMaxBlockSize, reinterpret_cast(&aMaxSize));
+}
+
+inline TInt RRM_DebugDriver::AttachProcess(TDesC8& aProcessName, TUint64 aAgentId)
+{
+ TRM_DebugAgentId info(aAgentId);
+ return DoControl(EControlAttachProcess,reinterpret_cast(&aProcessName),reinterpret_cast(&info));
+}
+
+inline TInt RRM_DebugDriver::DetachProcess(TDesC8& aProcessName, TUint64 aAgentId)
+{
+ TRM_DebugAgentId info(aAgentId);
+ return DoControl(EControlDetachProcess,reinterpret_cast(&aProcessName),reinterpret_cast(&info));
+}
+
+inline TInt RRM_DebugDriver::DetachAgent(TUint64 aAgentId)
+{
+ TRM_DebugAgentId info(aAgentId);
+ return DoControl(EControlDetachAgent,reinterpret_cast(&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(&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(aThreadId),reinterpret_cast(aNumSteps));
+}
+
+inline TInt RRM_DebugDriver::IsDebuggable(const TUint32 aProcessId)
+{
+ return DoControl(EControlIsDebuggable,reinterpret_cast(aProcessId),NULL);
+}
+
+inline TInt RRM_DebugDriver::KillProcess(const TUint32 aProcessId, const TInt32 aReason)
+{
+ return DoControl(EControlKillProcess,reinterpret_cast(aProcessId),reinterpret_cast(aReason));
+}
+
+#endif // __RM_DEBUG_KERNELDRIVER_H__
+
diff -r 838cdffd57ce -r 0ff24a8f6ca2 debugsrv/runmodedebug/rmdriver/src/d_debug_agent.cpp
--- /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
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#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; iConstruct())
+ {
+ 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; iClose(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* 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
diff -r 838cdffd57ce -r 0ff24a8f6ca2 debugsrv/runmodedebug/rmdriver/src/d_debug_functionality.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
+#include
+#include
+#include
+#include
+#include
+#include
+#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
+#include
+
+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* 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;
+ }
+
diff -r 838cdffd57ce -r 0ff24a8f6ca2 debugsrv/runmodedebug/rmdriver/src/d_list_manager.cpp
--- /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
+
+// 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; iCount(); 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, ®Set, flags);
+ entry.iSupervisorStackPtr = (TUint32)regSet.iR13;
+ //need to check that the stack pointer flag is valid
+ if(flags & (1<Wait();
+
+ aDataSize = 0;
+ //iterate through the processes adding them to the buffer
+ for(TInt i=0; iCount(); 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 entries;
+ //get the entries in KZSysBin
+ TInt err = GetDirectoryEntries(entries, KZSysBin());
+ if(KErrNone != err)
+ {
+ entries.Close();
+ return err;
+ }
+
+ aDataSize = 0;
+ for(TInt i=0; iiAtt & 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& 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 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& aRomEntryArray, RArray& 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& 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; iiNameLength;
+
+ //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 dirContents;
+ TInt err = GetDirectoryContents(dirContents, aAddress);
+ if(KErrNone != err)
+ {
+ dirContents.Close();
+ return err;
+ }
+ for(TInt i=0; iIsExe())
+ {
+ 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& 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;
+ }
+
+
+
diff -r 838cdffd57ce -r 0ff24a8f6ca2 debugsrv/runmodedebug/rmdriver/src/d_process_tracker.cpp
--- /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
+#include
+#include
+#include
+#include
+#include
+
+#include
+#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; iiOwningThread );
+ 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; iRemoveAgent(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; iiOwningThread == 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; iiOwningThread == &(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;
+ }
diff -r 838cdffd57ce -r 0ff24a8f6ca2 debugsrv/runmodedebug/rmdriver/src/d_rmd_breakpoints.cpp
--- /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
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include