diff -r a151135b0cf9 -r aa2539c91954 debugsrv/runmodedebug/rmdebug_test/rm_debug/basic_tests/t_rmdebug2.cpp --- a/debugsrv/runmodedebug/rmdebug_test/rm_debug/basic_tests/t_rmdebug2.cpp Wed Sep 29 17:45:35 2010 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,4985 +0,0 @@ -// 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(); - }