diff -r 000000000000 -r c6b0df440bee dbgagents/trkagent/engine/TrkDispatchLayer.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dbgagents/trkagent/engine/TrkDispatchLayer.cpp Tue Mar 02 10:33:16 2010 +0530 @@ -0,0 +1,3577 @@ +/* +* Copyright (c) 2004 Nokia Corporation and/or its subsidiary(-ies). +* All rights reserved. +* This component and the accompanying materials are made available +* under the terms of "Eclipse Public License v1.0" +* which accompanies this distribution, and is available +* at the URL "http://www.eclipse.org/legal/epl-v10.html". +* +* Initial Contributors: +* Nokia Corporation - initial contribution. +* +* Contributors: +* +* Description: +* +*/ + + +#include "TrkEngine.h" +#include "TrkDispatchLayer.h" +#include "DateTimeConverter.h" + +#ifndef __TEXT_SHELL__ +#include "TrkSwInstall.h" +#endif + +// +// Macros +// + +// +// Version Information +// + +#define MAJOR_VERSION_NUMBER 3 +#define MINOR_VERSION_NUMBER 2 +#define BUILD_NUMBER 4 + + +// +// Support Information +// + +#define DS_SUPPORT_MASK_00_07 0x7E // kDSConnect, kDSDisconnect, kDSReset, kDSVersions, kDSSupportMask, kDSCPUType */ +#define DS_SUPPORT_MASK_08_0F 0x00 +#define DS_SUPPORT_MASK_10_17 0x4f // R/W Memory, R/W Registers, FlushCache +#define DS_SUPPORT_MASK_18_1F 0x5f // kDSContinue, kDSStep, kDSStop, kDSSetBreak, kDSClearBreak +#define DS_SUPPORT_MASK_20_27 0x01 // kDSNotifyFileInput +#define DS_SUPPORT_MASK_28_2F 0x00 +#define DS_SUPPORT_MASK_30_37 0x00 +#define DS_SUPPORT_MASK_38_3F 0x00 +#define DS_SUPPORT_MASK_40_47 0x0f // OS Create/Delete Item, OS Read/Write Info +#define DS_SUPPORT_MASK_48_4F 0x1f // OS Read/Write/Open/Close/Position File +#define DS_SUPPORT_MASK_50_57 0x00 +#define DS_SUPPORT_MASK_58_5F 0x00 +#define DS_SUPPORT_MASK_60_67 0x00 +#define DS_SUPPORT_MASK_68_6F 0x00 +#define DS_SUPPORT_MASK_70_77 0x00 +#define DS_SUPPORT_MASK_78_7F 0x00 +#define DS_SUPPORT_MASK_80_87 0x01 // kDSReplyACK +#define DS_SUPPORT_MASK_88_8F 0x00 +#define DS_SUPPORT_MASK_90_97 0x11 // kDSNotifyStopped, kDSNotifyStopped2 +#define DS_SUPPORT_MASK_98_9F 0x00 +#define DS_SUPPORT_MASK_A0_A7 0x03 // kDSOSNotifyCreated, kDSOSNotifyDeleted +#define DS_SUPPORT_MASK_A8_AF 0x00 +#define DS_SUPPORT_MASK_B0_B7 0x00 +#define DS_SUPPORT_MASK_B8_BF 0x00 +#define DS_SUPPORT_MASK_C0_C7 0x00 +#define DS_SUPPORT_MASK_C8_CF 0x00 +#define DS_SUPPORT_MASK_D0_D7 0x03 // kDSWriteFile, kDSReadFile +#define DS_SUPPORT_MASK_D8_DF 0x00 +#define DS_SUPPORT_MASK_E0_E7 0x00 +#define DS_SUPPORT_MASK_E8_EF 0x00 +#define DS_SUPPORT_MASK_F0_F7 0x00 +#define DS_SUPPORT_MASK_F8_FF 0x80 // kDSReplyNAK + +#define KProcessKilled 0x4B696C6C // "Kill" + +#ifdef EKA2 +#define EUSER_LIBPATH _L("Z:\\Sys\\Bin\\euser.dll") +#else +#define EUSER_LIBPATH _L("Z:\\System\\Libs\\euser.dll") +#endif + +#ifdef __OEM_TRK__ +#define TRK_TYPE_DESCRIPTION _L8("System TRK") +#else +#define TRK_TYPE_DESCRIPTION _L8("Application TRK") +#endif + + +// +// Swap2 +// +// Byte-swaps a 2-byte value. Used to convert to/from little/big endian. +// +static TUint16 Swap2(TUint16 aSource) +{ + TUint16 dest = 0; + for (TInt i=0; i<2; i++) + { + dest <<= 8; + dest |= aSource & 0xFF; + aSource >>= 8; + } + + return dest; +} + +// +// Swap4 +// +// Byte-swaps a 4-byte value. Used to convert to/from little/big endian. +// +static TUint32 Swap4(TUint32 aSource) +{ + TUint32 dest = 0; + for (TInt i=0; i<4; i++) + { + dest <<= 8; + dest |= aSource & 0xFF; + aSource >>= 8; + } + + return dest; +} + +// +// Swap4xN +// +// Byte-swaps N 4-byte values *in place*. Used to convert to/from little/big endian. +// +void Swap4xN(TUint32 *aSource, TInt aCount) +{ + while (aCount--) + { + TUint32 temp = Swap4(*aSource); + *aSource++ = temp; + } +} + + +// +// +// CExitTrapper implementation +// +// + +// +// CExitTrapper constructor +// +// Accepts CTrkDispatchLayer interface and the process ID of the +// process to watch +// +CExitTrapper::CExitTrapper(CTrkDispatchLayer *aDispatch, TUint32 aProcessId) + : CActive(EPriorityStandard), + iProcessId(aProcessId), + iDispatch(aDispatch) +{ + CActiveScheduler::Add(this); + + TInt error = iProcess.Open(iProcessId); + if (KErrNone != error) + User::Panic(_L("Unable to open process"), __LINE__); +} + +// +// CExitTrapper destructor +// +CExitTrapper::~CExitTrapper() +{ + Cancel(); + Deque(); + iProcess.Close(); +} + +// +// CExitTrapper::Watch +// +// Watch for the process to exit +// +void CExitTrapper::Watch() +{ + iProcess.Logon(iStatus); + SetActive(); +} + +// +// CExitTrapper::RunL +// +// Called when the process exits +// +void CExitTrapper::RunL() +{ + // sometimes this is run when the process has yet to exit + if (iProcess.ExitType() == EExitPending) + { + iProcess.LogonCancel(iStatus); + Watch(); + } + else + { + iDispatch->DoNotifyProcessDiedL(iProcessId, iProcess.ExitReason()); + } +} + +// +// CExitTrapper::DoCancel +// +// Stop waiting for this process to exit +// +void CExitTrapper::DoCancel() +{ + iProcess.LogonCancel(iStatus); +} + + +// +// +// CEventTrapper implementation +// +// + +// +// CEventTrapper constructor +// +// Accepts CTrkDispatchLayer interface +// +CEventTrapper::CEventTrapper(CTrkDispatchLayer *aDispatch) + : CActive(CActive::EPriorityStandard), + iDispatch(aDispatch) +{ + CActiveScheduler::Add(this); +} + +// +// CEventTrapper destructor +// +CEventTrapper::~CEventTrapper() +{ + Cancel(); + Deque(); +} + +// +// CEventTrapper::Watch +// +// Start listening for events +// +void CEventTrapper::Watch() +{ + iDispatch->iKernelDriver.GetEvent(iStatus, iEventInfo); + SetActive(); +} + +// +// CEventTrapper::RunL +// +// Called when an event occurs +// +void CEventTrapper::RunL() +{ + // determine the type of event and handle accordingly + switch (iEventInfo.iEventType) + { + case SEventInfo::EThreadBreakPoint: + { + iDispatch->DoNotifyStoppedL(iEventInfo.iProcessId, iEventInfo.iThreadId, iEventInfo.iCurrentPC, KNullDesC8); + break; + } + case SEventInfo::EThreadException: + { + TBuf8<100> buf; + + switch(iEventInfo.iExceptionNumber) + { + case EExcIntegerDivideByZero: + { + buf.Format(_L8("An integer divide by zero exception has occurred.")); + break; + } + case EExcIntegerOverflow: + { + buf.Format(_L8("An integer overflow exception has occurred.")); + break; + } + case EExcBoundsCheck: + { + buf.Format(_L8("An bounds check exception has occurred.")); + break; + } + case EExcInvalidOpCode: + { + buf.Format(_L8("An invalid instruction exception has occurred.")); + break; + } + case EExcDoubleFault: + { + buf.Format(_L8("A double fault exception has occurred.")); + break; + } + case EExcStackFault: + { + buf.Format(_L8("A stack fault exception has occurred.")); + break; + } + case EExcAccessViolation: + { + buf.Format(_L8("An access violation exception has occurred.")); + break; + } + case EExcPrivInstruction: + { + buf.Format(_L8("A priveledged instruction exception has occurred.")); + break; + } + case EExcAlignment: + { + buf.Format(_L8("An alignment exception has occurred.")); + break; + } + case EExcPageFault: + { + buf.Format(_L8("A page fault exception has occurred.")); + break; + } + case EExcFloatDenormal: + case EExcFloatDivideByZero: + case EExcFloatInexactResult: + case EExcFloatInvalidOperation: + case EExcFloatOverflow: + case EExcFloatStackCheck: + case EExcFloatUnderflow: + { + buf.Format(_L8("A floating point exception has occurred.")); + break; + } + case EExcAbort: + { + buf.Format(_L8("An abort exception has occurred.")); + break; + } + case EExcUserInterrupt: + { + buf.Format(_L8("A user interrupt exception has occurred.")); + break; + } + case EExcDataAbort: + { + buf.Format(_L8("A data abort exception has occurred.")); + break; + } + case EExcCodeAbort: + { + buf.Format(_L8("A code abort exception has occurred.")); + break; + } + case EExcGeneral: + case EExcSingleStep: + case EExcBreakPoint: + case EExcKill: + case EExcMaxNumber: + case EExcInvalidVector: + default: + { + buf.Format(_L8("An unknown exception (%d) has occurred."), iEventInfo.iExceptionNumber); + break; + } + } + + iDispatch->DoNotifyStoppedL(iEventInfo.iProcessId, iEventInfo.iThreadId, iEventInfo.iCurrentPC, buf); + break; + } + case SEventInfo::EThreadPanic: + { + TBuf8<100> buf; +// buf.Format(_L8("Thread 0x%x has panicked.\nCategory: %S\nReason: %d"), iEventInfo.iThreadId, &iEventInfo.iPanicCategory, iEventInfo.iExceptionNumber); + buf.Format(_L8("Thread 0x%x has panicked. Category: %S; Reason: %d"), iEventInfo.iThreadId, &iEventInfo.iPanicCategory, iEventInfo.iPanicReason); + + iDispatch->DoNotifyStoppedL(iEventInfo.iProcessId, iEventInfo.iThreadId, iEventInfo.iCurrentPC, buf, true, iEventInfo.iExceptionNumber); + break; + } + case SEventInfo::EProcessPanic: + { + TBuf8<100> buf; + buf.Format(_L8("Process 0x%x has panicked.\nCategory: %S\nReason: %d"), iEventInfo.iProcessId, &iEventInfo.iPanicCategory, iEventInfo.iExceptionNumber); + + iDispatch->DoNotifyStoppedL(iEventInfo.iProcessId, iEventInfo.iThreadId, iEventInfo.iCurrentPC, buf); + break; + } + case SEventInfo::ELibraryLoaded: + { + // a library has been loaded. we get statically linked library loaded notifications + // the very first time the process is created. we want to ignore these because we + // handle static libs in another way. if the process the library was loaded for is + // not being debugging, just resume the thread and ignore the event. if the process + // is being debugged but it hasn't yet been created, then this must be a static lib + // and we ignore it. note that we do not bother resuming the thread since it has not + // been started yet! + + TBool created = EFalse; + TBool found = EFalse; + + for (TInt i=0; iiDebugProcessList.Count(); i++) + { + if (iDispatch->iDebugProcessList[i]->ProcessId() == iEventInfo.iProcessId) + { + created = iDispatch->iDebugProcessList[i]->iReadyForLibraryLoadNotification; + found = ETrue; + break; + } + } + + #ifndef EKA2 + if (!iEventInfo.iCodeAddress) + { + TBuf libName; + libName.Copy(iEventInfo.iFileName); + + RLibrary lib; + TInt err = lib.LoadRomLibrary(libName, KNullDesC); + if (KErrNone == err) + { + iEventInfo.iCodeAddress = (TUint32)lib.EntryPoint(); + lib.Close(); + } + } + #endif + + if (!created || !iEventInfo.iCodeAddress || !found) + { + iDispatch->iKernelDriver.ResumeThread(iEventInfo.iThreadId); + } + else + { + iDispatch->DoNotifyLibraryLoadedL(iEventInfo.iFileName, iEventInfo.iProcessId, iEventInfo.iThreadId, iEventInfo.iCodeAddress, iEventInfo.iDataAddress); + } + break; + } + case SEventInfo::ELibraryUnloaded: + { + TBool found = EFalse; + + for (TInt i=0; iiDebugProcessList.Count(); i++) + { + if (iDispatch->iDebugProcessList[i]->ProcessId() == iEventInfo.iProcessId) + { + found = ETrue; + break; + } + } + + if (!found) + { + iDispatch->iKernelDriver.ResumeThread(iEventInfo.iThreadId); + } + else + { + iDispatch->DoNotifyLibraryUnloadedL(iEventInfo.iFileName, iEventInfo.iProcessId, iEventInfo.iThreadId); + } + + break; + } + case SEventInfo::EUserTrace: + { + iDispatch->DoNotifyUserTraceL(iEventInfo.iTraceData); + break; + } + case SEventInfo::EProcessAdded: + { + iDispatch->DoNotifyProcessAddedL(iEventInfo.iFileName, iEventInfo.iProcessId, + iEventInfo.iThreadId, iEventInfo.iUid, + iEventInfo.iCodeAddress, iEventInfo.iDataAddress); + break; + } + case SEventInfo::EUnknown: + default: + User::Panic(_L("Unknown event type"), __LINE__); + break; + } + + // reset the values + iEventInfo.Reset(); + + // keep listening for more events + Watch(); +} + +// +// CEventTrapper::DoCancel +// +// Stop listening for events +// +void CEventTrapper::DoCancel() +{ + iDispatch->iKernelDriver.CancelGetEvent(); +} + + +// +// +// CDebugProcess implementation +// +// + +// +// CDebugProcess::NewL +// +// Accepts CTrkDispatchLayer interface and the process ID and main +// thread ID of a process being debugged +// +CDebugProcess* CDebugProcess::NewL(CTrkDispatchLayer *aDispatch, TUint32 aProcessId, TUint32 aMainThreadId) +{ + CDebugProcess* self = new(ELeave) CDebugProcess(); + self->ConstructL(aDispatch, aProcessId, aMainThreadId); + return self; +} + +// +// CDebugProcess::ConstructL +// +// Accepts CTrkDispatchLayer interface and the process ID and main +// thread ID of a process being debugged +// +void CDebugProcess::ConstructL(CTrkDispatchLayer *aDispatch, TUint32 aProcessId, TUint32 aMainThreadId) +{ + iProcessId = aProcessId; + iMainThreadId = aMainThreadId; + iReadyForLibraryLoadNotification = EFalse; + + // start waiting for this process to exit + iExitTrapper = new(ELeave) CExitTrapper(aDispatch, aProcessId); + iExitTrapper->Watch(); +} + +// +// CDebugProcess destructor +// +CDebugProcess::~CDebugProcess() +{ + SafeDelete(iExitTrapper); +} + +#ifndef __TEXT_SHELL__ + +// +// CPhoneInfo implementation +// +CPhoneInfo::CPhoneInfo(): + CActive(EPriorityStandard), + iPhoneIdV1Pckg(iPhoneIdV1), + iDispatchLayer(NULL) +{ + CActiveScheduler::Add(this); +} + +CPhoneInfo* CPhoneInfo::NewL() +{ + CPhoneInfo* self = new(ELeave) CPhoneInfo(); + CleanupStack::PushL(self); + self->ConstructL(); + CleanupStack::Pop(); + return self; +} + +void CPhoneInfo::ConstructL() +{ + iTelephony = CTelephony::NewL(); +} + +CPhoneInfo::~CPhoneInfo() +{ + Cancel(); + Deque(); + SafeDelete(iTelephony); +} + +void CPhoneInfo::GetPhoneName(CTrkDispatchLayer* aDispatchLayer) +{ + iDispatchLayer = aDispatchLayer; + iTelephony->GetPhoneId(iStatus, iPhoneIdV1Pckg); + SetActive(); +} + +void CPhoneInfo::RunL() +{ + if(iStatus == KErrNone) + { + iDispatchLayer->UpdatePhoneNameInfo(iPhoneIdV1.iModel); + } +} + +void CPhoneInfo::DoCancel() +{ + iTelephony->CancelAsync(CTelephony::EGetPhoneIdCancel); +} +#endif + +// +// +// CTrkDispatchLayer implementation +// +// + +// +// CTrkDispatchLayer constructor +// +CTrkDispatchLayer::CTrkDispatchLayer() + : iEngine(NULL), + iFramingLayer(NULL), +#ifndef __TEXT_SHELL__ + iPhoneInfo(NULL), +#endif + iFileState(EFileUnknown), + iDebugProcessList(1), + iProcessList(1), + iThreadList(1), + iSuspendedThreadList(1), + iEventTrapper(NULL), + iIsConnected(EFalse), + iPhoneNameInfoAvailable(EFalse) + +#ifdef __OEM_TRK__ + ,iUseTcbServer(EFalse) +#endif +{ +} + +// +// CTrkDispatchLayer::NewL +// +CTrkDispatchLayer* CTrkDispatchLayer::NewL(CTrkCommPort *aPort, CTrkEngine* aEngine) +{ + CTrkDispatchLayer* self = new(ELeave) CTrkDispatchLayer(); + self->ConstructL(aPort, aEngine); + return self; +} + +// +// CTrkDispatchLayer destructor +// +CTrkDispatchLayer::~CTrkDispatchLayer() +{ + SafeDelete(iFramingLayer); + + SafeDelete(iInputBuffer); + SafeDelete(iReplyBuffer); +#ifndef __TEXT_SHELL__ + SafeDelete(iPhoneInfo); +#endif + // just in case a disconnect never happened + SafeDelete(iEventTrapper); + +#ifndef __WINS__ + iKernelDriver.Close(); +#endif + + CloseTcbServer(); + iProcessList.Close(); + iThreadList.Close(); + iSuspendedThreadList.Close(); + + iDebugProcessList.ResetAndDestroy(); + iDebugProcessList.Close(); + //Notify the server that Debugging is ended + if (iEngine) + iEngine->DebuggingEnded(); + +} +// +// CTrkDispathcLayer::CloseTcbServer() +// +void CTrkDispatchLayer::CloseTcbServer() +{ +#ifdef __OEM_TRK__ + //Shutdown the tcb server. + if (iUseTcbServer) + { + iTrkTcbSession.ShutDownServer(); + iTrkTcbSession.Close(); + iUseTcbServer = EFalse; + } +#endif + +} + +// +// CTrkDispatchLayer::ConstructL +// +void CTrkDispatchLayer::ConstructL(CTrkCommPort *aPort, CTrkEngine* aEngine) +{ + iEngine = aEngine; + + // create the framing layer interface + iFramingLayer = new CTrkFramingLayer(aPort); + + // At a minimum, we assume that the host debugger supports 3.3 version of the protocol + // From 3.0 to 3.3, TRK is backwards compatible. Starting with version 3.4, TRK sends + // process created notifications as part of notify created event. Unless the host + // debugger sets the supported protocol version to 3.4, we are not going to send this + // new notification. Going forward, we should check for the protocol version before + // we send new notifications. + iHostVersion.iMajor = DS_PROTOCOL_MAJOR_VERSION_3; + iHostVersion.iMinor = DS_PROTOCOL_MINOR_VERSION_3; + + //To find the sw version runnning in the phone + FindPhoneSWVersion(); + + // On techview, this functionality is not available for some reason. + // This needs to be investigated further, but this functionality is not critical for techview platform right now. +#ifdef __S60__ + // To find the name of the phone. + TRAPD(err1, FindPhoneNameL()); + if (err1 != KErrNone) +#endif + { + iPhoneNameInfoAvailable = EFalse; + } +} + +// +// CTrkDispathLayer::FindPhoneSWVersion() +// +// Finds out the software version of the phone +// +void CTrkDispatchLayer::FindPhoneSWVersion() +{ +#ifndef __TEXT_SHELL__ + TBuf version; + if (SysUtil::GetSWVersion( version ) == KErrNone ) + { + iPhoneVersion.Copy(version); + } +#endif +} + +// +// CTrkDispathLayer::FindPhoneName() +// +// Finds the name of the phone +// +void CTrkDispatchLayer::FindPhoneNameL() +{ +#ifndef __TEXT_SHELL__ + iPhoneInfo = CPhoneInfo::NewL(); + iPhoneInfo->GetPhoneName(this); +#endif +} + +// +// CTrkDispatchLayer::Listen +// +// Start listening to the communications port for messages from the host debugger +// +void CTrkDispatchLayer::Listen() +{ + iFramingLayer->Listen(this); +} + +// +// CTrkDispatchLayer::StopListening +// +// Stop listening to the communications port for messages from the host debugger +// +void CTrkDispatchLayer::StopListening() +{ + // just in case the user quit MetroTrk while something was being debugged. + RProcess process; + for (TInt i=0; iProcessId())) + { + #ifdef EKA2 + process.Kill(KErrNone); + #else + process.Kill(KProcessKilled); + #endif + process.Close(); + } + } + + iFramingLayer->StopListening(); +} + +// +// CTrkDispatchLayer::GetVersionInfo +// +// Get the current version of MetroTrk +// +void CTrkDispatchLayer::GetVersionInfo(TInt &aMajorVersion, TInt &aMinorVersion, TInt &aMajorAPIVersion, TInt &aMinorAPIVersion, TInt &aBuildNumber) +{ + aMajorVersion = MAJOR_VERSION_NUMBER; + aMinorVersion = MINOR_VERSION_NUMBER; + aMajorAPIVersion = DS_PROTOCOL_MAJOR_VERSION; + aMinorAPIVersion = DS_PROTOCOL_MINOR_VERSION; + aBuildNumber = BUILD_NUMBER; +} + +// +// CTrkDispatchLayer::HandleMsg +// +// Handle a command sent by the host debugger +// +void CTrkDispatchLayer::HandleMsg(const TDesC8& aMsg) +{ + TInt error = KErrNone; + + // reset the input buffer and set it to the new unframed message + SafeDelete(iInputBuffer); + iInputBuffer = aMsg.Alloc(); + + if (!iInputBuffer) + User::Panic(_L("Failed to allocate input buffer"), __LINE__); + + TRAP(error, DispatchMsgL()); + + if (error < 0) + { + // its a symbian os error + error = kDSReplyOsError; + } + + // handle errors raised during command execution + switch(error) + { + // no error and ack was sent by handler + case kDSReplyNoError: + break; + + // there was a problem with the packet received + case kDSReplyPacketSizeError: + case kDSReplyEscapeError: + case kDSReplyBadFCS: + case kDSReplyOverflow: + case kDSReplySequenceMissing: + iFramingLayer->RespondErr(kDSReplyNAK, error); + break; + + // command and format were OK, but failed for some other reason + default: + iFramingLayer->RespondErr(kDSReplyACK, error); + } +} + +// +// CTrkDispatchLayer::DispatchMsgL +// +// Handle the command sent by the host debugger +// +void CTrkDispatchLayer::DispatchMsgL() +{ + // make sure the input buffer is setup + User::LeaveIfNull(iInputBuffer); + + // iInputBuffer holds the unframed message from the host + switch (iInputBuffer->Ptr()[0]) + { + case kDSPing: + { + // nothing to do + iFramingLayer->RespondOkL(KNullDesC8); + break; + } + case kDSConnect: + { + DoConnectL(); + break; + } + case kDSDisconnect: + { + DoDisconnectL(); + break; + } + case kDSVersions: + { + DoVersionsL(); + break; + } + case kDSVersions2: + { + DoVersions2L(); + break; + } + case kDSVersions3: + { + DoVersions3L(); + break; + } + case kDSHostVersions: + { + DoHostVersionsL(); + break; + } + case kDSSupportMask: + { + DoSupportMaskL(); + break; + } + case kDSCPUType: + { + DoCPUTypeL(); + break; + } + case kDSReadMemory: + { + DoReadMemoryL(); + break; + } + case kDSWriteMemory: + { + DoWriteMemoryL(); + break; + } + case kDSReadRegisters: + { + DoReadRegistersL(); + break; + } + case kDSWriteRegisters: + { + DoWriteRegistersL(); + break; + } + case kDSContinue: + { + DoContinueL(); + break; + } + case kDSStep: + { + DoStepL(); + break; + } + case kDSStop: + { + DoStopL(); + break; + } + case kDSSetBreak: + { + DoSetBreakL(); + break; + } + case kDSClearBreak: + { + DoClearBreakL(); + break; + } + case kDSModifyBreakThread: + { + DoModifyBreakThreadL(); + break; + } + case kDSOSCreateItem: + { + DoCreateItemL(); + break; + } + case kDSOSDeleteItem: + { + DoDeleteItemL(); + break; + } + case kDSOSReadInfo: + { + DoReadInfoL(); + break; + } + case kDSOSWriteInfo: + { + DoWriteInfoL(); + break; + } + case kDSOSWriteFile: + { + DoWriteFileL(); + break; + } + case kDSOSReadFile: + { + DoReadFileL(); + break; + } + case kDSOSOpenFile: + { + DoOpenFileL(); + break; + } + case kDSOSCloseFile: + { + DoCloseFileL(); + break; + } + case kDSOSPositionFile: + { + DoPositionFileL(); + break; + } + case kDSOSInstallFile: + { + DoInstallFileL(); + break; + } + case kDSOSInstallFile2: + { + DoInstallFile2L(); + break; + } + case kDSOSPhoneSWVersion: + { + DoGetPhoneSWVersionL(); + break; + } + case kDSOSPhoneName: + { + DoGetPhoneNameL(); + break; + } + + case kDSReplyACK: + case kDSReplyNAK: + break; + + case kDSReset: + case kDSFillMemory: + case kDSCopyMemory: + case kDSFlushCache: + case kDSDownload: + case kDSNotifyFileInput: + default: + { + // unsupported command + iFramingLayer->RespondErr(kDSReplyACK, kDSReplyUnsupportedCommandError); + break; + } + } +} + +// +// CTrkDispatchLayer::DoConnectL +// +// The host debugger is starting a new debug session +// +void CTrkDispatchLayer::DoConnectL() +{ + // make sure we got here from DispatchMsgL + TUint8 command = 0; + GetDataFromBufferL(&command, 1); + + if (kDSConnect != command) + User::Leave(kDSReplyError); + + // if we're already connected for some reason, we need to cleanup so we're ready + // for a new debug session + if (iIsConnected) + { + // reset the sequence ids for the next debug session + iFramingLayer->ResetSequenceIDs(); + + //stop listening for events + SafeDelete(iEventTrapper); + + // let the kernel side driver cleanup + iKernelDriver.Close(); + + iIsConnected = EFalse; + } + + // reset the lists so that they are ready for use + iProcessList.Reset(); + iThreadList.Reset(); + iSuspendedThreadList.Reset(); + iDebugProcessList.ResetAndDestroy(); + + TMetroTrkDriverInfo info; +#ifndef EKA2 + RLibrary euser; + User::LeaveIfError(euser.Load(EUSER_LIBPATH)); + CleanupClosePushL(euser); + + info.iPanic1Address = (TUint32)euser.Lookup(812); // RThread::Panic + info.iPanic2Address = (TUint32)euser.Lookup(813); // RProcess::Panic + info.iException1Address = (TUint32)euser.Lookup(868); // RThread::RaiseException + info.iException2Address = (TUint32)euser.Lookup(520); // User::HandleException + info.iLibraryLoadedAddress = (TUint32)euser.Lookup(636); // UserSvr::LibraryLoaded + + // calculate the end address of the user library. breakpoints and stepping will not + // be allowed from the start of ROM to the end of the user library since stopping a + // kernel thread could end up freezing the target + RFs fs; + User::LeaveIfError(fs.Connect()); + CleanupClosePushL(fs); + + RFile file; + User::LeaveIfError(file.Open(fs, EUSER_LIBPATH, EFileStream|EFileRead|EFileShareReadersOnly)); + CleanupClosePushL(file); + + TInt size; + User::LeaveIfError(file.Size(size)); + + info.iUserLibraryEnd = (TUint32)euser.EntryPoint() + size; + + CleanupStack::PopAndDestroy(); // file + CleanupStack::PopAndDestroy(); // fs + CleanupStack::PopAndDestroy(); // euser +#endif + + // start the kernel side driver + User::LeaveIfError(iKernelDriver.Open(info)); + + // start listening for events + iEventTrapper = new(ELeave) CEventTrapper(this); + iEventTrapper->Watch(); + + iIsConnected = ETrue; +#ifdef __S60__ + // now close close crash logger + CloseCrashLogger(); +#endif + + if (iEngine) + iEngine->DebuggingStarted(); + + iFramingLayer->RespondOkL(KNullDesC8); +} + +// +// CTrkDispatchLayer::DoDisconnectL +// +// The host debugger is stopping the current debug session +// +void CTrkDispatchLayer::DoDisconnectL() +{ + // make sure we got here from DispatchMsgL + TUint8 command = 0; + GetDataFromBufferL(&command, 1); + + if (kDSDisconnect != command) + User::Leave(kDSReplyError); + + // make sure we're connected + if (!iIsConnected) + { + User::Leave(KErrCouldNotDisconnect); + } + + //stop listening for events + SafeDelete(iEventTrapper); + + iIsConnected = EFalse; + + iFramingLayer->RespondOkL(KNullDesC8); + + // let the kernel side driver cleanup + iKernelDriver.Close(); + + //Shutdown the tcb server. + CloseTcbServer(); + + // send the callback to the trk server + if (iEngine) + iEngine->DebuggingEnded(); + +} + +// +// CTrkDispatchLayer::DoVersionsL +// +// The host debugger is requesting MetroTrk version information +// +void CTrkDispatchLayer::DoVersionsL() +{ + // make sure we got here from DispatchMsgL + TUint8 command = 0; + GetDataFromBufferL(&command, 1); + + if (kDSVersions != command) + User::Leave(kDSReplyError); + + TUint8 kernelMajorVersion = MAJOR_VERSION_NUMBER; + TUint8 kernelMinorVersion = MINOR_VERSION_NUMBER; + TUint8 protocolMajorVersion = DS_PROTOCOL_MAJOR_VERSION; + TUint8 protocolMinorVersion = DS_PROTOCOL_MINOR_VERSION; + + AddToReplyBufferL(kernelMajorVersion, true); + AddToReplyBufferL(kernelMinorVersion); + AddToReplyBufferL(protocolMajorVersion); + AddToReplyBufferL(protocolMinorVersion); + + RespondOkL(); +} + +// +// CTrkDispatchLayer::DoVersionsL +// +// The host debugger is requesting MetroTrk version information +// +void CTrkDispatchLayer::DoVersions2L() +{ + // make sure we got here from DispatchMsgL + TUint8 command = 0; + GetDataFromBufferL(&command, 1); + + if (kDSVersions2 != command) + User::Leave(kDSReplyError); + + TUint8 kernelMajorVersion = MAJOR_VERSION_NUMBER; + TUint8 kernelMinorVersion = MINOR_VERSION_NUMBER; + TUint8 protocolMajorVersion = DS_PROTOCOL_MAJOR_VERSION; + TUint8 protocolMinorVersion = DS_PROTOCOL_MINOR_VERSION; + TUint8 buildNumber = BUILD_NUMBER; + + AddToReplyBufferL(kernelMajorVersion, true); + AddToReplyBufferL(kernelMinorVersion); + AddToReplyBufferL(protocolMajorVersion); + AddToReplyBufferL(protocolMinorVersion); + AddToReplyBufferL(buildNumber); + + RespondOkL(); +} + +// +// CTrkDispatchLayer::DoVersions3L +// +// The host debugger is requesting MetroTrk version information +// +void CTrkDispatchLayer::DoVersions3L() +{ + // make sure we got here from DispatchMsgL + TUint8 command = 0; + GetDataFromBufferL(&command, 1); + + if (kDSVersions3 != command) + User::Leave(kDSReplyError); + + TUint8 kernelMajorVersion = MAJOR_VERSION_NUMBER; + TUint8 kernelMinorVersion = MINOR_VERSION_NUMBER; + TUint8 protocolMajorVersion = DS_PROTOCOL_MAJOR_VERSION; + TUint8 protocolMinorVersion = DS_PROTOCOL_MINOR_VERSION; + TUint8 buildNumber = BUILD_NUMBER; + + AddToReplyBufferL(kernelMajorVersion, true); + AddToReplyBufferL(kernelMinorVersion); + AddToReplyBufferL(protocolMajorVersion); + AddToReplyBufferL(protocolMinorVersion); + AddToReplyBufferL(buildNumber); + + TUint16 len = TRK_TYPE_DESCRIPTION.Length(); + + AddToReplyBufferL(len); + AddToReplyBufferL(TRK_TYPE_DESCRIPTION); + + RespondOkL(); +} + +// +// CTrkDispatchLayer::DoHostVersionsL +// +// The host debugger is sending the supported protocol version +// +void CTrkDispatchLayer::DoHostVersionsL() +{ + // make sure we got here from DispatchMsgL + TUint8 command = 0; + GetDataFromBufferL(&command, 1); + + if (kDSHostVersions != command) + User::Leave(kDSReplyError); + + GetDataFromBufferL(&iHostVersion.iMajor, 1); + GetDataFromBufferL(&iHostVersion.iMinor, 1); + + iFramingLayer->RespondOkL(KNullDesC8); +} + +// +// CTrkDispatchLayer::DoSupportMaskL +// +// The host debugger is requesting MetroTrk capabilities +// +void CTrkDispatchLayer::DoSupportMaskL() +{ + // make sure we got here from DispatchMsgL + TUint8 command = 0; + GetDataFromBufferL(&command, 1); + + if (kDSSupportMask != command) + User::Leave(kDSReplyError); + + TBuf8<32> supportMask; + TUint8 level = DS_PROTOCOL_RTOS; + + supportMask.Zero(); + supportMask.Append(DS_SUPPORT_MASK_00_07); + supportMask.Append(DS_SUPPORT_MASK_08_0F); + supportMask.Append(DS_SUPPORT_MASK_10_17); + supportMask.Append(DS_SUPPORT_MASK_18_1F); + supportMask.Append(DS_SUPPORT_MASK_20_27); + supportMask.Append(DS_SUPPORT_MASK_28_2F); + supportMask.Append(DS_SUPPORT_MASK_30_37); + supportMask.Append(DS_SUPPORT_MASK_38_3F); + supportMask.Append(DS_SUPPORT_MASK_40_47); + supportMask.Append(DS_SUPPORT_MASK_48_4F); + supportMask.Append(DS_SUPPORT_MASK_50_57); + supportMask.Append(DS_SUPPORT_MASK_58_5F); + supportMask.Append(DS_SUPPORT_MASK_60_67); + supportMask.Append(DS_SUPPORT_MASK_68_6F); + supportMask.Append(DS_SUPPORT_MASK_70_77); + supportMask.Append(DS_SUPPORT_MASK_78_7F); + supportMask.Append(DS_SUPPORT_MASK_80_87); + supportMask.Append(DS_SUPPORT_MASK_88_8F); + supportMask.Append(DS_SUPPORT_MASK_90_97); + supportMask.Append(DS_SUPPORT_MASK_98_9F); + supportMask.Append(DS_SUPPORT_MASK_A0_A7); + supportMask.Append(DS_SUPPORT_MASK_A8_AF); + supportMask.Append(DS_SUPPORT_MASK_B0_B7); + supportMask.Append(DS_SUPPORT_MASK_B8_BF); + supportMask.Append(DS_SUPPORT_MASK_C0_C7); + supportMask.Append(DS_SUPPORT_MASK_C8_CF); + supportMask.Append(DS_SUPPORT_MASK_D0_D7); + supportMask.Append(DS_SUPPORT_MASK_D8_DF); + supportMask.Append(DS_SUPPORT_MASK_E0_E7); + supportMask.Append(DS_SUPPORT_MASK_E8_EF); + supportMask.Append(DS_SUPPORT_MASK_F0_F7); + supportMask.Append(DS_SUPPORT_MASK_F8_FF); + + AddToReplyBufferL(supportMask, true); + AddToReplyBufferL(level); + + RespondOkL(); +} + +// +// CTrkDispatchLayer::DoCPUTypeL +// +// The host debugger is requesting cpu information +// +void CTrkDispatchLayer::DoCPUTypeL() +{ + // make sure we got here from DispatchMsgL + TUint8 command = 0; + GetDataFromBufferL(&command, 1); + + if (kDSCPUType != command) + User::Leave(kDSReplyError); + + TUint8 cpuMajor = DS_CPU_MAJOR_ARM; + TUint8 cpuMinor = 0; + TUint8 bigEndian = iFramingLayer->IsBigEndian() ? 1 : 0; + TUint8 defaultTypeSize = 4; + TUint8 fpTypeSize = 0; + TUint8 extended1TypeSize = 0; + TUint8 extended2TypeSize = 0; + + AddToReplyBufferL(cpuMajor, true); + AddToReplyBufferL(cpuMinor); + AddToReplyBufferL(bigEndian); + AddToReplyBufferL(defaultTypeSize); + AddToReplyBufferL(fpTypeSize); + AddToReplyBufferL(extended1TypeSize); + AddToReplyBufferL(extended2TypeSize); + + RespondOkL(); +} + +// +// CTrkDispatchLayer::DoReadMemoryL +// +// Read memory from the target device and return to the host +// +void CTrkDispatchLayer::DoReadMemoryL() +{ + // make sure we're connected + if (!iIsConnected) + { + User::Leave(KErrGeneral); + } + + // make sure we got here from DispatchMsgL + TUint8 command = 0; + GetDataFromBufferL(&command, 1); + + if (kDSReadMemory != command) + User::Leave(kDSReplyError); + + // get the options + TUint8 options = 0; + GetDataFromBufferL(&options, 1); + + if ((options & DS_MSG_MEMORY_EXTENDED) != 0) + User::Leave(kDSReplyUnsupportedOptionError); + + // get the length to read + TUint16 length = 0; + GetDataFromBufferL(&length, 2); + + if (length > DS_MAXREADWRITELENGTH) + User::Leave(kDSReplyParameterError); + + // get the start address + TUint32 address = 0; + GetDataFromBufferL(&address, 4); + + // get the process id + TUint32 processId = 0; + GetDataFromBufferL(&processId, 4); + + // get the thread id + TUint32 threadId = 0; + GetDataFromBufferL(&threadId, 4); + + // allocate enough room for the data + HBufC8 *data = HBufC8::NewLC(length); + TPtr8 ptr(data->Des()); + + TInt err = iKernelDriver.ReadMemory(threadId, address, length, ptr); + if (KErrNone != err) + { + CleanupStack::PopAndDestroy(data); + User::Leave(err); + } + + AddToReplyBufferL(length, true); + AddToReplyBufferL(ptr); + + RespondOkL(); + + CleanupStack::PopAndDestroy(data); +} + +// +// CTrkDispatchLayer::DoWriteMemoryL +// +// Write memory from the host to the target device +// +void CTrkDispatchLayer::DoWriteMemoryL() +{ + // make sure we're connected + if (!iIsConnected) + { + User::Leave(KErrGeneral); + } + + // make sure we got here from DispatchMsgL + TUint8 command = 0; + GetDataFromBufferL(&command, 1); + + if (kDSWriteMemory != command) + User::Leave(kDSReplyError); + + // get the options + TUint8 options = 0; + GetDataFromBufferL(&options, 1); + + if ((options & DS_MSG_MEMORY_EXTENDED) != 0) + User::Leave(kDSReplyUnsupportedOptionError); + + // get the length to write + TUint16 length = 0; + GetDataFromBufferL(&length, 2); + + if (length > DS_MAXREADWRITELENGTH) + User::Leave(kDSReplyParameterError); + + // get the start address + TUint32 address = 0; + GetDataFromBufferL(&address, 4); + + // get the process id + TUint32 processId = 0; + GetDataFromBufferL(&processId, 4); + + // get the thread id + TUint32 threadId = 0; + GetDataFromBufferL(&threadId, 4); + + User::LeaveIfError(iKernelDriver.WriteMemory(threadId, address, length, *iInputBuffer)); + + AddToReplyBufferL(length, true); + + RespondOkL(); +} + +// +// CTrkDispatchLayer::DoReadRegistersL +// +// Read registers from the target device and return to the host +// +void CTrkDispatchLayer::DoReadRegistersL() +{ + // make sure we're connected + if (!iIsConnected) + { + User::Leave(KErrGeneral); + } + + // make sure we got here from DispatchMsgL + TUint8 command = 0; + GetDataFromBufferL(&command, 1); + + if (kDSReadRegisters != command) + User::Leave(kDSReplyError); + + // get the options + TUint8 options = 0; + GetDataFromBufferL(&options, 1); + + if (DS_MSG_REGISTERS_TYPE(options) != kDSRegistersDefault) + User::Leave(kDSReplyUnsupportedOptionError); + + // get the first register + TInt16 firstRegister = 0; + GetDataFromBufferL(&firstRegister, 2); + + // get the last register + TInt16 lastRegister = 0; + GetDataFromBufferL(&lastRegister, 2); + + if ((firstRegister < 0) || (lastRegister > 16)) + User::Leave(kDSReplyInvalidRegisterRange); + + // get the process id + TUint32 processId = 0; + GetDataFromBufferL(&processId, 4); + + // get the thread id + TUint32 threadId = 0; + GetDataFromBufferL(&threadId, 4); + + // allocate enough space to hold the values + HBufC8 *values = HBufC8::NewLC((lastRegister - firstRegister + 1) * 4); + TPtr8 ptr(values->Des()); + + TInt err = iKernelDriver.ReadRegisters(threadId, firstRegister, lastRegister, ptr); + if (KErrNone != err) + { + CleanupStack::PopAndDestroy(values); + User::Leave(err); + } + + for (int i=0; i<=lastRegister - firstRegister; i++) + AddToReplyBufferL(*(TUint32 *)&ptr.Ptr()[i*4], i==0 ? true : false); + + RespondOkL(); + + CleanupStack::PopAndDestroy(values); +} + +// +// CTrkDispatchLayer::DoWriteRegistersL +// +// Write registers from the host to the target device +// +void CTrkDispatchLayer::DoWriteRegistersL() +{ + // make sure we're connected + if (!iIsConnected) + { + User::Leave(KErrGeneral); + } + + // make sure we got here from DispatchMsgL + TUint8 command = 0; + GetDataFromBufferL(&command, 1); + + if (kDSWriteRegisters != command) + User::Leave(kDSReplyError); + + // get the options + TUint8 options = 0; + GetDataFromBufferL(&options, 1); + + if (DS_MSG_REGISTERS_TYPE(options) != kDSRegistersDefault) + User::Leave(kDSReplyUnsupportedOptionError); + + // get the first register + TInt16 firstRegister = 0; + GetDataFromBufferL(&firstRegister, 2); + + // get the last register + TInt16 lastRegister = 0; + GetDataFromBufferL(&lastRegister, 2); + + if ((firstRegister < 0) || (lastRegister > 16)) + User::Leave(kDSReplyInvalidRegisterRange); + + // get the process id + TUint32 processId = 0; + GetDataFromBufferL(&processId, 4); + + // get the thread id + TUint32 threadId = 0; + GetDataFromBufferL(&threadId, 4); + + // MetroTrk register values come in as big endian so we may need to swap them + if (!iFramingLayer->IsBigEndian()) + { + Swap4xN((TUint32 *)iInputBuffer->Ptr(), lastRegister-firstRegister + 1); + } + + User::LeaveIfError(iKernelDriver.WriteRegisters(threadId, firstRegister, lastRegister, *iInputBuffer)); + + iFramingLayer->RespondOkL(KNullDesC8); +} + +// +// CTrkDispatchLayer::DoContinueL +// +// Resume thread execution +// +void CTrkDispatchLayer::DoContinueL() +{ + // make sure we're connected + if (!iIsConnected) + { + User::Leave(KErrGeneral); + } + + // make sure we got here from DispatchMsgL + TUint8 command = 0; + GetDataFromBufferL(&command, 1); + + if (kDSContinue != command) + User::Leave(kDSReplyError); + + // get the process id + TUint32 processId = 0; + GetDataFromBufferL(&processId, 4); + + // get the thread id + TUint32 threadId = 0; + GetDataFromBufferL(&threadId, 4); + + // see if this thread is in the the suspended threads list + // if so, remove it and resume. otherwise we need to handle + // the special case of the first time a thread is resumed + TInt index = iSuspendedThreadList.Find(threadId); + if (index >= 0) + { + iSuspendedThreadList.Remove(index); + User::LeaveIfError(iKernelDriver.ResumeThread(threadId)); + iFramingLayer->RespondOkL(KNullDesC8); + } + else + { + // if it's not in the suspended list then this is the first time it has been + // resumed (the process has just been created). see if there are statically + // linked libraries that we need to report to the host debugger. if so, we + // don't really want to resume yet. let the host debugger set any breakpoints + // in the libraries first. it will call resume again once it's done. + + // since we never mark it as suspended, we'll actually get here when the host + // debugger calls resume the second time. we really don't want to mark it as + // suspended because then the host debugger will try to draw the thread window + TBool found = EFalse; + for (TInt i=0; iProcessId() == processId) + { + found = ETrue; + // if we're already marked it as ready, just resume and return + if (iDebugProcessList[i]->iReadyForLibraryLoadNotification) + { + User::LeaveIfError(iKernelDriver.ResumeThread(threadId)); + iFramingLayer->RespondOkL(KNullDesC8); + return; + } + + iDebugProcessList[i]->iReadyForLibraryLoadNotification = ETrue; + break; + } + } + // For RUN mode, we created the process but we didn't put it into the list + // therefore we do not want to notify the host debugger about static libraries + // so just resume and return (see DoCreateExeL) + // The host debugger will soon disconnect in this mode + if (!found) + { + User::LeaveIfError(iKernelDriver.ResumeThread(threadId)); + iFramingLayer->RespondOkL(KNullDesC8); + return; + } + + // the process has been created and the host debugger is listening for messages + // see if there are any statically linked libraries for this process. if so, let + // the host debugger know about them now. note that the host debugger will send + // another resume command once it's handled the static libraries. if there are + // not static libraries for this process, we really do need to resume the thread. + + TInt err = KErrNone; + TInt i = 0; + for (i=0; KErrNone==err; i++) + { + SEventInfo info; + info.iProcessId = processId; + info.iThreadId = threadId; + err = iKernelDriver.GetStaticLibraryInfo(i, info); + + if (KErrNone == err) + { + DoNotifyLibraryLoadedL(info.iFileName, info.iProcessId, 0xFFFFFFFF, info.iCodeAddress, info.iDataAddress); + } + //else if (0 == i) + //{ + // there are no static libraries for this process + //User::LeaveIfError(iKernelDriver.ResumeThread(threadId)); + //} + } + //Always resume the thread instead of asking the host debugger to resume when sending the last static library notification. + User::LeaveIfError(iKernelDriver.ResumeThread(threadId)); + iFramingLayer->RespondOkL(KNullDesC8); + } +} + +// +// CTrkDispatchLayer::DoStepL +// +// Execute one instruction in a thread +// +void CTrkDispatchLayer::DoStepL() +{ + // make sure we're connected + if (!iIsConnected) + { + User::Leave(KErrGeneral); + } + + // make sure we got here from DispatchMsgL + TUint8 command = 0; + GetDataFromBufferL(&command, 1); + + if (kDSStep != command) + User::Leave(kDSReplyError); + + // get the options + TUint8 options = 0; + GetDataFromBufferL(&options, 1); + + // we only support stepping out of a range of instructions + if ((kDSStepIntoRange != options) && (kDSStepOverRange != options)) + { + User::Leave(kDSReplyUnsupportedOptionError); + } + + // get the range start address + TUint32 startAddress = 0; + GetDataFromBufferL(&startAddress, 4); + + // get the range stop address + TUint32 stopAddress = 0; + GetDataFromBufferL(&stopAddress, 4); + + // get the process id + TUint32 processId = 0; + GetDataFromBufferL(&processId, 4); + + // get the thread id + TUint32 threadId = 0; + GetDataFromBufferL(&threadId, 4); + + User::LeaveIfError(iKernelDriver.StepRange(threadId, startAddress, stopAddress, (kDSStepIntoRange == options))); + + iFramingLayer->RespondOkL(KNullDesC8); +} + +// +// CTrkDispatchLayer::DoStopL +// +// Stop the execution of a thread +// +void CTrkDispatchLayer::DoStopL() +{ + // make sure we're connected + if (!iIsConnected) + { + User::Leave(KErrGeneral); + } + + // make sure we got here from DispatchMsgL + TUint8 command = 0; + GetDataFromBufferL(&command, 1); + + if (kDSStop != command) + User::Leave(kDSReplyError); + + // get the options + TUint8 options = 0; + GetDataFromBufferL(&options, 1); + + TUint32 processId = 0; + TUint32 threadId = 0; + + switch(options) + { + case kDSStopThread: + { + // get the process id + GetDataFromBufferL(&processId, 4); + + // get the thread id + GetDataFromBufferL(&threadId, 4); + + User::LeaveIfError(iKernelDriver.SuspendThread(threadId)); + + break; + } + case kDSStopSystem: + case kDSStopProcess: + default: + { + User::Leave(kDSReplyUnsupportedOptionError); + break; + } + } + + iFramingLayer->RespondOkL(KNullDesC8); + + TBuf8<4> currentPC; + + User::LeaveIfError(iKernelDriver.ReadRegisters(threadId, 15, 15, currentPC)); + + DoNotifyStoppedL(processId, threadId, *(TUint32 *)currentPC.Ptr(), KNullDesC8); +} + +// +// CTrkDispatchLayer::DoSetBreakL +// +// Set a breakpoint +// +void CTrkDispatchLayer::DoSetBreakL() +{ + // make sure we're connected + if (!iIsConnected) + { + User::Leave(KErrGeneral); + } + + // make sure we got here from DispatchMsgL + TUint8 command = 0; + GetDataFromBufferL(&command, 1); + + if (kDSSetBreak != command) + User::Leave(kDSReplyError); + + // get the options - unused + TUint8 options = 0; + GetDataFromBufferL(&options, 1); + + // get the mode + TUint8 thumbMode = 0; + GetDataFromBufferL(&thumbMode, 1); + + // get the address + TUint32 address = 0; + GetDataFromBufferL(&address, 4); + + // get the length + TUint32 length = 0; + GetDataFromBufferL(&length, 4); + + // get the count + TUint32 count = 0; + GetDataFromBufferL(&count, 4); + + // get the process id + TUint32 processId = 0; + GetDataFromBufferL(&processId, 4); + + // get the thread id + TUint32 threadId = 0; + GetDataFromBufferL(&threadId, 4); + + TInt32 breakId = 0; + User::LeaveIfError(iKernelDriver.SetBreak(processId, threadId, address, thumbMode, breakId)); + + // return the id of this breakpoint to the host debugger + AddToReplyBufferL((TUint32)breakId, true); + + RespondOkL(); +} + +// +// CTrkDispatchLayer::DoClearBreakL +// +// Clear a breakpoint +// +void CTrkDispatchLayer::DoClearBreakL() +{ + // make sure we're connected + if (!iIsConnected) + { + User::Leave(KErrGeneral); + } + + // make sure we got here from DispatchMsgL + TUint8 command = 0; + GetDataFromBufferL(&command, 1); + + if (kDSClearBreak != command) + User::Leave(kDSReplyError); + + // get the breakpoint id + TUint32 breakId = 0; + GetDataFromBufferL(&breakId, 4); + + User::LeaveIfError(iKernelDriver.ClearBreak(breakId)); + + iFramingLayer->RespondOkL(KNullDesC8); +} + +// +// CTrkDispatchLayer::DoModifyBreakThreadL +// +// Change the thread(s) that a breakpoint is associated with +// +void CTrkDispatchLayer::DoModifyBreakThreadL() +{ + // make sure we're connected + if (!iIsConnected) + { + User::Leave(KErrGeneral); + } + + // make sure we got here from DispatchMsgL + TUint8 command = 0; + GetDataFromBufferL(&command, 1); + + if (kDSModifyBreakThread != command) + User::Leave(kDSReplyError); + + // get the breakpoint id + TUint32 breakId = 0; + GetDataFromBufferL(&breakId, 4); + + // get the thread id + TUint32 threadId = 0; + GetDataFromBufferL(&threadId, 4); + + User::LeaveIfError(iKernelDriver.ChangeBreakThread(threadId, breakId)); + + iFramingLayer->RespondOkL(KNullDesC8); +} + +// +// CTrkDispatchLayer::DoCreateItemL +// +// Create a new OS item on the target device +// +void CTrkDispatchLayer::DoCreateItemL() +{ + // make sure we're connected + if (!iIsConnected) + { + User::Leave(KErrGeneral); + } + + // make sure we got here from DispatchMsgL + TUint8 command = 0; + GetDataFromBufferL(&command, 1); + + if (kDSOSCreateItem != command) + User::Leave(kDSReplyError); + + // get the item type + TUint16 type = 0; + GetDataFromBufferL(&type, 2); + + switch(type) + { + case kDSOSProcessItem: + { + DoCreateProcessL(); + break; + } + case kDSOSProcRunItem: + { + DoCreateProcessL(ETrue); + break; + } + case kDSOSProcAttachItem: + { + DoAttachProcessL(kDSOSProcAttachItem); + break; + } + case kDSOSProcAttach2Item: + { + DoAttachProcessL(kDSOSProcAttach2Item); + break; + } + case kDSOSProcAttach3Item: + { + DoAttachProcessL(kDSOSProcAttach3Item); + break; + } + case kDSOSThreadItem: + case kDSOSDLLItem: + case kDSOSAppItem: + case kDSOSMemBlockItem: + case kDSOSThreadAttachItem: + default: + { + User::Leave(kDSReplyUnsupportedOptionError); + break; + } + } +} + +// +// CTrkDispatchLayer::DoDeleteItemL +// +// Delete an OS item from the target device +// +void CTrkDispatchLayer::DoDeleteItemL() +{ + // make sure we're connected + if (!iIsConnected) + { + User::Leave(KErrGeneral); + } + + // make sure we got here from DispatchMsgL + TUint8 command = 0; + GetDataFromBufferL(&command, 1); + + if (kDSOSDeleteItem != command) + User::Leave(kDSReplyError); + + // get the item type + TUint16 type = 0; + GetDataFromBufferL(&type, 2); + + switch(type) + { + case kDSOSProcessItem: + { + DoKillProcessL(); + break; + } + case kDSOSProcAttachItem: + { + DoDetachProcessL(); + break; + } + case kDSOSThreadItem: + case kDSOSDLLItem: + case kDSOSAppItem: + case kDSOSMemBlockItem: + case kDSOSThreadAttachItem: + default: + { + User::Leave(kDSReplyUnsupportedOptionError); + break; + } + } +} + +// +// CTrkDispatchLayer::DoReadInfoL +// +// Read OS information from the target device +// +void CTrkDispatchLayer::DoReadInfoL() +{ + // make sure we're connected + if (!iIsConnected) + { + User::Leave(KErrGeneral); + } + + // make sure we got here from DispatchMsgL + TUint8 command = 0; + GetDataFromBufferL(&command, 1); + + if (kDSOSReadInfo != command) + User::Leave(kDSReplyError); + + // get the type of info requested + TUint16 type = 0; + GetDataFromBufferL(&type, 2); + + // get the start index + TUint32 index = 0; + GetDataFromBufferL(&index, 4); + + switch(type) + { + case kDSOSProcessList: + { + DoReadProcessListL(index); + break; + } + case kDSOSThreadList: + { + DoReadThreadListL(index); + break; + } + case kDSOSDLLInfo: + { + TUint16 nameLength = 0; + GetDataFromBufferL(&nameLength, 2); + + // make sure the length of the message is correct + if (iInputBuffer->Length() != nameLength) + User::Leave(kDSReplyPacketSizeError); + + TBuf8 fileName; + fileName.Copy(*iInputBuffer); + fileName.ZeroTerminate(); + + DoReadLibraryInfoL(fileName); + break; + } + case kDSOSProcessInfo: + { + TUint32 uid3 = 0; + GetDataFromBufferL(&uid3, 4); + TUint16 nameLength = 0; + GetDataFromBufferL(&nameLength, 2); + + // make sure the length of the message is correct + if (iInputBuffer->Length() != nameLength) + User::Leave(kDSReplyPacketSizeError); + + TBuf8 fileName; + fileName.Copy(*iInputBuffer); + fileName.ZeroTerminate(); + + DoReadProcessInfoL(uid3, fileName); + break; + } + case kDSOSProcessState: + case kDSOSThreadState: + case kDSOSDLLList: + case kDSOSDLLState: + default: + { + User::Leave(kDSReplyUnsupportedOptionError); + break; + } + } +} + +// +// CTrkDispatchLayer::DoWriteInfoL +// +// Set options for the Trk +// +void CTrkDispatchLayer::DoWriteInfoL() +{ + // make sure we got here from DispatchMsgL + TUint8 command = 0; + GetDataFromBufferL(&command, 1); + + if (kDSOSWriteInfo != command) + User::Leave(kDSReplyError); + + // get the type of info requested + TUint16 type = 0; + GetDataFromBufferL(&type, 2); + + // get the start index + TUint32 index = 0; + GetDataFromBufferL(&index, 4); + + // no options supported yet. might add something for auto-target libraries later + User::Leave(kDSReplyUnsupportedOptionError); +} + +// +// CTrkDispatchLayer::DoOpenFileL +// +// Open or create a file on the target +// +void CTrkDispatchLayer::DoOpenFileL() +{ + // make sure we got here from DispatchMsgL + TUint8 command = 0; + GetDataFromBufferL(&command, 1); + + if (kDSOSOpenFile != command) + User::Leave(kDSReplyError); + + // get the file mode(s) + TUint8 modes = 0; + GetDataFromBufferL(&modes, 1); + + if ((modes & kDSFileOpenAppend) || (modes & kDSFileOpenCreate)) + modes |= kDSFileOpenWrite; + + TUint16 nameLength = 0; + GetDataFromBufferL(&nameLength, 2); + + // make sure the length of the message is correct + if (iInputBuffer->Length() != nameLength) + User::Leave(kDSReplyPacketSizeError); + + TBuf fullpath; + fullpath.Copy(*iInputBuffer); + fullpath.ZeroTerminate(); + + TUint mode = EFileShareExclusive; + + // get the file mode(s) + if (modes & kDSFileOpenRead) + mode |= EFileRead; + + if (modes & kDSFileOpenWrite) + mode |= EFileWrite; + + if (modes & kDSFileOpenAppend) + mode |= EFileWrite; + + if (modes & kDSFileOpenCreate) + mode |= EFileWrite; + + + //for getting the modification date + TTime time; + + OpenFileL(fullpath, mode, time); + + TDateTime dateTime = time.DateTime(); + + TDateTimeConverter winTime(dateTime); + + TUint32 timestamp = winTime.GetWinTimeDate(); + + TUint32 handle = 1; + TUint8 err = 0; + + AddToReplyBufferL(err, true); + AddToReplyBufferL(handle); + AddToReplyBufferL(timestamp); + + RespondOkL(); +} + +// +// CTrkDispatchLayer::OpenFileL +// +// Open a file on the target, if plat security is enabled, uses TrkTcbServer to open the file. +// +void CTrkDispatchLayer::OpenFileL(const TDesC& aFullPath, TUint aMode, TTime& aTime) +{ + +#ifdef __OEM_TRK__ + //Check to see if TCB capability is enforced, if so, connect to the tcb server as well. + if (!iUseTcbServer && PlatSec::IsCapabilityEnforced(ECapabilityTCB)) + { + if (!iTrkTcbSession.Connect()) + { + iUseTcbServer = ETrue; + } + } + + if (iUseTcbServer) + { + User::LeaveIfError(iTrkTcbSession.OpenFile(aFullPath, aMode, aTime)); + } + else +#endif + { + #ifndef __OEM_TRK__ + if (IsRestrictedFolder(aFullPath)) + User::Leave(KErrAccessDenied); + #endif + // connect to the file server + User::LeaveIfError(iFs.Connect()); + + TInt error = iFs.MkDirAll(aFullPath); + + if ((KErrNone != error) && (KErrAlreadyExists != error)) + { + iFs.Close(); + User::Leave(error); + } + + error = iFile.Open(iFs, aFullPath, aMode); + + if (KErrNone != error) + User::LeaveIfError(iFile.Replace(iFs, aFullPath, aMode)); + + User::LeaveIfError(iFile.Modified(aTime)); + iFileState = EFileOpened; + } +} + +// +// CTrkDispatchLayer::DoReadFileL +// +// Read data from a file on the target +// +void CTrkDispatchLayer::DoReadFileL() +{ + // make sure we got here from DispatchMsgL + TUint8 command = 0; + GetDataFromBufferL(&command, 1); + + if (kDSOSReadFile != command) + User::Leave(kDSReplyError); + + // make sure the length of the message is correct + if (iInputBuffer->Length() != 6) + User::Leave(kDSReplyPacketSizeError); + + // remove the handle + iInputBuffer->Des().Delete(0, 4); + + // get the length + TUint8 err = 0; + TUint16 length = 0; + GetDataFromBufferL(&length, 2); + + // allocate a buffer large enough for the data + HBufC8 *buffer = HBufC8::NewLC(length); + TPtr8 ptr(buffer->Des()); + + // CleanupStack::PushL(buffer); + + TInt error = ReadFileL(length, ptr); + if (KErrNone != error) + { + CleanupStack::PopAndDestroy(buffer); + User::Leave(error); + } + + length = buffer->Length(); + + AddToReplyBufferL(err, true); + AddToReplyBufferL(length); +// AddToReplyBufferL(buffer[0], length); + AddToReplyBufferL(ptr); + RespondOkL(); + + CleanupStack::PopAndDestroy(buffer); +} + +// +// CTrkDispatchLayer::ReadFileL +// +// Reads data from a file on the target +// +TInt CTrkDispatchLayer::ReadFileL(TUint16 aLength, TPtr8& aData) +{ + TInt error = KErrNone; + +#ifdef __OEM_TRK__ + if (iUseTcbServer) + { + User::LeaveIfError(iTrkTcbSession.ReadFile(aLength, aData)); + } + else +#endif + { + iFileState = EFileReading; + error = iFile.Read(aData); + } + return error; +} + +// +// CTrkDispatchLayer::DoWriteFileL +// +// Write data to a file on the target +// +void CTrkDispatchLayer::DoWriteFileL() +{ + // make sure we got here from DispatchMsgL + TUint8 command = 0; + GetDataFromBufferL(&command, 1); + + if (kDSOSWriteFile != command) + User::Leave(kDSReplyError); + + // get the length + TUint32 handle = 0; + GetDataFromBufferL(&handle, 4); + + if (handle != 1) + User::Leave(kDSReplyParameterError); + + // get the length + TUint8 err = 0; + TUint16 length = 0; + GetDataFromBufferL(&length, 2); + + // make sure the length of the message is correct + if (iInputBuffer->Length() != length) + User::Leave(kDSReplyPacketSizeError); + + WriteFileL(*iInputBuffer); + + length = iInputBuffer->Length(); + + AddToReplyBufferL(err, true); + AddToReplyBufferL(length); + RespondOkL(); +} + +// +// CTrkDispatchLayer::WriteFileL +// +// Write data to a file on the target. If plat sec is enabled, uses Trk Tcb Server. +// +void CTrkDispatchLayer::WriteFileL(TDesC8& aData) +{ +#ifdef __OEM_TRK__ + if (iUseTcbServer) + { + User::LeaveIfError(iTrkTcbSession.WriteFile(aData)); + } + else +#endif + { + if (iFileState == EFileOpened) + { + iFile.SetSize(0); + iFileState = EFileWriting; + } + User::LeaveIfError(iFile.Write(aData)); + User::LeaveIfError(iFile.Flush()); + } +} + +// +// CTrkDispatchLayer::DoPositionFileL +// +// Change the current file position of a file on the target +// +void CTrkDispatchLayer::DoPositionFileL() +{ + // make sure we got here from DispatchMsgL + TUint8 command = 0; + GetDataFromBufferL(&command, 1); + + if (kDSOSPositionFile != command) + User::Leave(kDSReplyError); + + // make sure the length of the message is correct + if (iInputBuffer->Length() != 9) + User::Leave(kDSReplyPacketSizeError); + + // get the positioning mode + TUint8 mode = 0; + GetDataFromBufferL(&mode, 1); + + // remove the handle + iInputBuffer->Des().Delete(0, 4); + + TUint8 err = 0; + TUint32 offset = 0; + GetDataFromBufferL(&offset, 4); + + TSeek seek; + + // convert mode to native parameter and set the position accordingly + switch(mode) + { + default: + case kDSFileSeekSet: + { + seek = ESeekStart; + break; + } + case kDSFileSeekCur: + { + seek = ESeekCurrent; + break; + } + case kDSFileSeekEnd: + { + seek = ESeekEnd; + break; + } + } + + PositionFileL(seek, (TInt &)offset); + + AddToReplyBufferL(err, true); + + RespondOkL(); +} + +// +// CTrkDispatchLayer::PositionFileL +// +// Change the current file position of a file on the target. If plat sec is enabled, +// uses Trk Tcb Server. +// +void CTrkDispatchLayer::PositionFileL(TSeek aSeek, TInt& aOffset) +{ +#ifdef __OEM_TRK__ + if (iUseTcbServer) + { + User::LeaveIfError(iTrkTcbSession.PositionFile(aSeek, aOffset)); + } + else +#endif + { + User::LeaveIfError(iFile.Seek(aSeek, aOffset)); + } +} + + +// +// CTrkDispatchLayer::DoCloseFileL +// +// Close a file on the target +// +void CTrkDispatchLayer::DoCloseFileL() +{ + // make sure we got here from DispatchMsgL + TUint8 command = 0; + GetDataFromBufferL(&command, 1); + + if (kDSOSCloseFile != command) + User::Leave(kDSReplyError); + + // make sure the length of the message is correct + if (iInputBuffer->Length() != 8) + User::Leave(kDSReplyPacketSizeError); + + // remove the handle + iInputBuffer->Des().Delete(0, 4); + + TUint8 err = 0; + TUint32 timestamp = 0; + GetDataFromBufferL(×tamp, 4); + + TDateTimeConverter epocTime(timestamp); + + CloseFileL(epocTime.GetEpocTimeDate()); + + AddToReplyBufferL(err, true); + + RespondOkL(); +} + +// +// CTrkDispatchLayer::CloseFileL +// +// Close a file on the target. If plat sec is enabled, uses Trk Tcb Server. +// +void CTrkDispatchLayer::CloseFileL(const TTime& aModifiedTime) +{ +#ifdef __OEM_TRK__ + if (iUseTcbServer) + { + User::LeaveIfError(iTrkTcbSession.CloseFile(aModifiedTime)); + } + else +#endif + { + User::LeaveIfError(iFile.SetModified(aModifiedTime)); + User::LeaveIfError(iFile.Flush()); + + iFile.Close(); + iFs.Close(); + iFileState = EFileClosed; + } +} + +// +// CTrkDispatchLayer::DoInstallFileL +// +// Install the application, supplied as a SIS file. +// +void CTrkDispatchLayer::DoInstallFileL() +{ + // make sure we're connected + if (!iIsConnected) + { + User::Leave(KErrGeneral); + } + +#ifndef __TEXT_SHELL__ + // make sure we got here from DispatchMsgL + TUint8 command = 0; + GetDataFromBufferL(&command, 1); + + if (kDSOSInstallFile != command) + User::Leave(kDSReplyError); + + // get the installation drive + TUint8 drive = 'C'; + GetDataFromBufferL(&drive, 1); + + TChar installDrive(drive); + + TUint16 nameLength = 0; + GetDataFromBufferL(&nameLength, 2); + + // make sure the length of the message is correct + if (iInputBuffer->Length() != nameLength) + User::Leave(kDSReplyPacketSizeError); + + TBuf fullpath; + fullpath.Copy(*iInputBuffer); + fullpath.ZeroTerminate(); + + TUint8 err = 0; + // Temporarily disable the lib loaded event before launching the SW Installer. + // This is necessary when launching the SIS installer since launching the + // installer causes several libraries to be loaded. The driver suspends the + // thread thats loaded the library. This suspension might potentially cause + // a deadlock as the event handling active object will never get a chance to + // run as the Install function below blocks until the installation is completed. + User::LeaveIfError(iKernelDriver.DisableLibLoadedEvent()); + + // now launch the installer + User::LeaveIfError(CTrkSwInstall::SilentInstallL(fullpath, installDrive)); + + // now enable the lib loaded event + iKernelDriver.EnableLibLoadedEvent(); + + AddToReplyBufferL(err, true); + RespondOkL(); +#else + User::LeaveIfError(-1); +#endif +} + +// +// CTrkDispatchLayer::DoInstallFileL +// +// Install the application, supplied as a SIS file. +// +void CTrkDispatchLayer::DoInstallFile2L() +{ + // make sure we're connected + if (!iIsConnected) + { + User::Leave(KErrGeneral); + } + +#ifndef __TEXT_SHELL__ + // make sure we got here from DispatchMsgL + TUint8 command = 0; + GetDataFromBufferL(&command, 1); + + if (kDSOSInstallFile2 != command) + User::Leave(kDSReplyError); + + TUint16 nameLength = 0; + GetDataFromBufferL(&nameLength, 2); + + // make sure the length of the message is correct + if (iInputBuffer->Length() != nameLength) + User::Leave(kDSReplyPacketSizeError); + + TBuf fullpath; + fullpath.Copy(*iInputBuffer); + fullpath.ZeroTerminate(); + + TUint8 err = 0; + // Temporarily disable the lib loaded event before launching the SW Installer. + // This is necessary when launching the SIS installer since launching the + // installer causes several libraries to be loaded. The driver suspends the + // thread thats loaded the library. This suspension might potentially cause + // a deadlock as the event handling active object will never get a chance to + // run as the Install function below blocks until the installation is completed. + User::LeaveIfError(iKernelDriver.DisableLibLoadedEvent()); + + // now launch the installer + User::LeaveIfError(CTrkSwInstall::Install(fullpath)); + + // now enable the lib loaded event + iKernelDriver.EnableLibLoadedEvent(); + + AddToReplyBufferL(err); + RespondOkL(); +#else + User::LeaveIfError(-1); +#endif +} + + +// +// CTrkDispathLayer::DoGetPhoneSWVesionL() +// +// sends the software version of the phone to reply buffer +// +void CTrkDispatchLayer::DoGetPhoneSWVersionL() +{ + // make sure we got here from DispatchMsgL + + TUint8 command = 0; + GetDataFromBufferL(&command, 1); + + if (kDSOSPhoneSWVersion != command) + { + User::Leave(kDSReplyError); + } +#ifndef __TEXT_SHELL__ + if (iPhoneVersion.Size()>0 ) + { + TUint16 versionNameLength = iPhoneVersion.Length(); + AddToReplyBufferL(versionNameLength, ETrue); + AddToReplyBufferL(iPhoneVersion); + RespondOkL(); + } + else +#endif + { + User::Leave(KErrGeneral); + } + +} + + +// +//CTrkDispathLayer::DoGetPhoneNameL() +// +//sends the phone model name to the reply buffer +// +void CTrkDispatchLayer::DoGetPhoneNameL() +{ + TUint8 command = 0; + GetDataFromBufferL(&command, 1); + + if (kDSOSPhoneName != command) + { + User::Leave(kDSReplyError); + } + +#ifndef __TEXT_SHELL__ + if (iPhoneNameInfoAvailable) + { + TUint16 phoneModelLen = iPhoneModel.Length(); + AddToReplyBufferL(phoneModelLen, true); + AddToReplyBufferL(iPhoneModel); + RespondOkL(); + } + else +#endif + { + User::Leave(KErrGeneral); + } +} +// +//To Update the phone model name +// +//callback function from the CPhoneInfo +// +void CTrkDispatchLayer::UpdatePhoneNameInfo(TDesC16& aPhoneModel) +{ +#ifndef __TEXT_SHELL__ + iPhoneModel.Copy(aPhoneModel); + iPhoneNameInfoAvailable = ETrue; +#endif +} + +// +// CTrkDispatchLayer::DoCreateProcessL +// +// Create a new process on the target device +// +void CTrkDispatchLayer::DoCreateProcessL(TBool aRun) +{ + // remove the options - currently unused + iInputBuffer->Des().Delete(0, 1); + + // get the length of the data + TUint16 length = 0; + GetDataFromBufferL(&length, 2); + + // make sure the length of the message is correct + if (iInputBuffer->Length() != length) + User::Leave(kDSReplyPacketSizeError); + + // extract the filename and path, command line args, and working directory + TPtrC8 exec8(iInputBuffer->Ptr()); + TPtrC8 args8(exec8.Ptr() + exec8.Length() + 1); + + // convert the filename and args to unicode descriptors + HBufC* exec = HBufC::NewLC(exec8.Length()); + exec->Des().Copy(exec8); + + HBufC* args = HBufC::NewLC(args8.Length()); + args->Des().Copy(args8); + + // open the file and get the type (app, exe, etc.) + RFs fs; + + // connect to the file server + User::LeaveIfError(fs.Connect()); + + TEntry entry; + + User::LeaveIfError(fs.Entry(*exec, entry)); + + fs.Close(); + + TCreateProcessData data; + + switch(entry[0].iUid) + { + case 0x1000007a: + { + // EXE + DoCreateExeL(*exec, *args, data, aRun); + break; + } + default: + User::Leave(KErrGeneral); + } + + CleanupStack::PopAndDestroy(args); + CleanupStack::PopAndDestroy(exec); + + AddToReplyBufferL(data.iProcessId, true); + AddToReplyBufferL(data.iMainThreadId); + if (!aRun) + { + AddToReplyBufferL(data.iCodeAddr); + AddToReplyBufferL(data.iDataAddr); + } + + RespondOkL(); +} + +// +// CTrkDispatchLayer::DoCreateExeL +// +// Create a new executable on the target device +// +void CTrkDispatchLayer::DoCreateExeL(const TDesC& aPath, const TDesC& aArgs, TCreateProcessData& aData, TBool aRun) +{ + RProcess process; + User::LeaveIfError(process.Create(aPath, aArgs)); + CleanupClosePushL(process); + + aData.iProcessId = process.Id(); + + HBufC* threadName = HBufC::NewLC(KMaxFullName); + + *threadName = process.Name(); + _LIT(KMainThreadSuffix, "::Main"); + threadName->Des().Append(KMainThreadSuffix); + + // this function should be (indirectly) called when the debuggee + // has been created but not yet resumed. So it should have a main + // thread whose name ends with "::Main", and so the following call + // should not fail. + RThread thread; + User::LeaveIfError(thread.Open(*threadName)); + + aData.iMainThreadId = thread.Id(); + thread.Close(); + + if (!aRun) + { + CDebugProcess *proc = CDebugProcess::NewL(this, aData.iProcessId, aData.iMainThreadId); + iDebugProcessList.Append(proc); + + User::LeaveIfError(iKernelDriver.GetProcessAddresses(aData.iMainThreadId, aData.iCodeAddr, aData.iDataAddr)); + } + + CleanupStack::PopAndDestroy(threadName); + CleanupStack::PopAndDestroy(); // process +} + +// +// CTrkDispatchLayer::DoKillProcessL +// +// Kill an existing process +// +void CTrkDispatchLayer::DoKillProcessL() +{ + // get the process id + TUint32 processId = 0; + GetDataFromBufferL(&processId, 4); + + RProcess process; + User::LeaveIfError(process.Open(processId)); +#ifdef EKA2 + process.Kill(KErrNone); +#else + process.Kill(KProcessKilled); +#endif + process.Close(); + + iFramingLayer->RespondOkL(KNullDesC8); +} + +// +// CTrkDispatchLayer::DoAttachProcessL +// +// Create a new process on the target device +// +void CTrkDispatchLayer::DoAttachProcessL(DSOSItemTypes aAttachType) +{ + // remove the options - currently unused + iInputBuffer->Des().Delete(0, 1); + + // get the length of the data + TUint32 processId = 0; + GetDataFromBufferL(&processId, 4); + + RProcess process; + User::LeaveIfError(process.Open(processId)); + CleanupClosePushL(process); + + // do not allow attaching to a system, protected, or the MetroTrk process because + // if the user were to stop the wrong thread, the whole system could stop +#ifdef EKA2 + if ((TUint)processId == RProcess().Id()) +#else + if (process.System() || process.Protected() || ((TUint)processId == RProcess().Id())) +#endif + { + User::Leave(kDSReplyUnsupportedOptionError); + } + + TMetroTrkTaskInfo threadInfo(processId); + User::LeaveIfError(iKernelDriver.GetThreadInfo(0, threadInfo)); + + + TUint32 codeAddr; + TUint32 dataAddr; + User::LeaveIfError(iKernelDriver.GetProcessAddresses(threadInfo.iId, codeAddr, dataAddr)); + //this is necessary to get the process died notifications and also any other event for this process + CDebugProcess *proc = CDebugProcess::NewL(this, processId, threadInfo.iId); + // For processes that we are attaching, we need to set this flag to true. + // otherwise library load notifications for this process will be ignored + proc->iReadyForLibraryLoadNotification = ETrue; + iDebugProcessList.Append(proc); + + AddToReplyBufferL(threadInfo.iId, true); + if (aAttachType == kDSOSProcAttach3Item) + { + // now get the UID3 for this process + // and add it to the reply + TMetroTrkProcUidInfo procUidInfo(processId); + User::LeaveIfError(iKernelDriver.GetProcUidInfo(procUidInfo)); + AddToReplyBufferL(procUidInfo.iUid3); + } + if (aAttachType == kDSOSProcAttach3Item || aAttachType == kDSOSProcAttach2Item) + { + AddToReplyBufferL(codeAddr); + AddToReplyBufferL(dataAddr); + + TBuf8 procName; + procName.Copy(process.Name()); + TUint16 nameLength = procName.Length(); + + AddToReplyBufferL(nameLength); + AddToReplyBufferL(procName); + } + + CleanupStack::PopAndDestroy(); // process + RespondOkL(); +} + +// +// CTrkDispatchLayer::DoDetachProcessL +// +// To detach the process from the list of processes +// +void CTrkDispatchLayer::DoDetachProcessL() +{ + TUint32 processId = 0; + GetDataFromBufferL(&processId, 4); + + RProcess process; + User::LeaveIfError(process.Open(processId)); + + for (TInt i=0 ; iProcessId()== processId) + { + SafeDelete(iDebugProcessList[i]); + iDebugProcessList.Remove(i); + } + } + User::LeaveIfError(iKernelDriver.DetachProcess(processId)); + + iFramingLayer->RespondOkL(KNullDesC8); +} + + +// +// CTrkDispatchLayer::DoReadProcessListL +// +// Return a list of the current processes to the host debugger +// +void CTrkDispatchLayer::DoReadProcessListL(TInt32 aIndex) +{ + // remove the options - unused + iInputBuffer->Des().Delete(0, 1); + + // remove the filter - unused + iInputBuffer->Des().Delete(0, 4); + + // an index of zero means we start fresh. and index other than zero means + // we were not able to return all of the processes in the last round due to + // message size limitations, so we need to pick up where we left off + if (aIndex == 0) + { + DoReBuildProcessList(); + } + + TInt32 totalCount = iProcessList.Count(); + TInt32 returnedCount = 0; + TInt32 bytesRemaining = MAXMESSAGESIZE_V2 - 30; // minus the framing bytes + TInt32 restOfMsgSize = sizeof(TUint32) // process id + + sizeof(TUint32) // priority + + sizeof(TUint8); // NULL character + + for (TInt32 i=aIndex; i= (iProcessList[i].iName.Length() + restOfMsgSize)) + { + returnedCount++; + bytesRemaining -= (iProcessList[i].iName.Length() + restOfMsgSize); + } + else + break; + } + + // add values for returnedCount and totalCount + AddToReplyBufferL((TUint32)returnedCount, true); + AddToReplyBufferL((TUint32)totalCount); + + for (TInt32 i=aIndex; i<(aIndex + returnedCount); i++) + { + // add this process info to the buffer + AddToReplyBufferL(iProcessList[i].iId); + AddToReplyBufferL(iProcessList[i].iPriority); + AddToReplyBufferL(iProcessList[i].iName); + + // host expects the name to be a null terminated string + AddToReplyBufferL((TUint8)0); + } + + RespondOkL(); +} + +// +// CTrkDispatchLayer::DoReadThreadListL +// +// Return a list of the current threads for a process to the host debugger +// +void CTrkDispatchLayer::DoReadThreadListL(TInt32 aIndex) +{ + // remove the options - unused + iInputBuffer->Des().Delete(0, 1); + + // get the process id + TUint32 processId = 0; + GetDataFromBufferL(&processId, 4); + + // an index of zero means we start fresh. and index other than zero means + // we were not able to return all of the threads in the last round due to + // message size limitations, so we need to pick up where we left off + if (aIndex == 0) + { + DoReBuildThreadList(processId); + } + + TInt32 totalCount = iThreadList.Count(); + TInt32 returnedCount = 0; + TInt32 bytesRemaining = MAXMESSAGESIZE_V2 - 30; // minus the framing bytes + TInt32 restOfMsgSize = sizeof(TUint32) // process id + + sizeof(TUint32) // priority + + sizeof(TUint8) // state + + sizeof(TUint8); // NULL character + + + for (TInt32 i=aIndex; i= (iThreadList[i].iName.Length() + restOfMsgSize)) + { + returnedCount++; + bytesRemaining -= (iThreadList[i].iName.Length() + restOfMsgSize); + } + else + break; + } + + // add values for returnedCount and totalCount + AddToReplyBufferL((TUint32)returnedCount, true); + AddToReplyBufferL((TUint32)totalCount); + + for (TInt32 i=aIndex; i<(aIndex + returnedCount); i++) + { + // add this thread info to the buffer + AddToReplyBufferL(iThreadList[i].iId); + AddToReplyBufferL(iThreadList[i].iPriority); + AddToReplyBufferL(IsThreadSuspended(iThreadList[i].iId)); + AddToReplyBufferL(iThreadList[i].iName); + + // host expects the name to be a null terminated string + AddToReplyBufferL((TUint8)0); + } + + RespondOkL(); +} + +// +// CTrkDispatchLayer::DoReBuildProcessList +// +// Build a list of the current processes +// +void CTrkDispatchLayer::DoReBuildProcessList() +{ + TInt err = KErrNone; + + // reset the process list + iProcessList.Reset(); + + // fill up the process list + for (TInt i=0; KErrNone==err; i++) + { + TMetroTrkTaskInfo processInfo(0); + err = iKernelDriver.GetProcessInfo(i, processInfo); + + //Get a Handle to the process + RProcess proc; + if(KErrNone == err && KErrNone == proc.Open(TProcessId(processInfo.iId))) + { + //Only display currently running processes + if(EExitPending == proc.ExitType()) + { + iProcessList.Append(processInfo); + } + proc.Close(); + } + } +} + +// +// CTrkDispatchLayer::DoReBuildThreadList +// +// Build a list of the current threads for a process +// +void CTrkDispatchLayer::DoReBuildThreadList(TUint32 aProcessId) +{ + TInt err = KErrNone; + + // reset the thread list + iThreadList.Reset(); + + // fill up the thread list + for (TInt i=0; KErrNone==err; i++) + { + TMetroTrkTaskInfo threadInfo(aProcessId); + err = iKernelDriver.GetThreadInfo(i, threadInfo); + + //Get a Handle to the thread + RThread thread; + if(KErrNone == err && KErrNone == thread.Open(TThreadId(threadInfo.iId))) + { + //Only display currently running processes + if(EExitPending == thread.ExitType()) + { + iThreadList.Append(threadInfo); + } + thread.Close(); + } + } +} + +// CTrkDispatchLayer::DoNotifyStoppedL +// +// Notify the host debugger that a thread has stopped +// +// START_PANIC +//void CTrkDispatchLayer::DoNotifyStoppedL(TUint32 aProcessId, TUint32 aThreadId, TUint32 aCurrentPC, const TDesC8 &aDescription) +void CTrkDispatchLayer::DoNotifyStoppedL(TUint32 aProcessId, TUint32 aThreadId, TUint32 aCurrentPC, const TDesC8 &aDescription, TBool aAddException, const TUint16 aExceptionNumber) +// END_PANIC +{ + // add this thread to the suspended threads list + iSuspendedThreadList.Append(aThreadId); + +// TUint8 event = (aAddException==true) ? kDSNotifyStopped2 : kDSNotifyStopped; + TUint8 event = kDSNotifyStopped; + TUint16 descLength = aDescription.Length(); + + AddToReplyBufferL(event, true); + AddToReplyBufferL(aCurrentPC); + AddToReplyBufferL(aProcessId); + AddToReplyBufferL(aThreadId); + AddToReplyBufferL(descLength); + + if (descLength) + { + AddToReplyBufferL(aDescription); + + // host expects the string to be a null terminated string + AddToReplyBufferL((TUint8)0); + } + // START_PANIC + if (aAddException) + AddToReplyBufferL(aExceptionNumber); + // END_PANIC + + InformEventL(); +} + +// +// CTrkDispatchLayer::DoNotifyProcessDiedL +// +// Notify the host debugger that a process has exited +// +void CTrkDispatchLayer::DoNotifyProcessDiedL(TUint32 aProcessId, TInt aExitCode) +{ + // remove this process from our list + for (TInt i=0; iProcessId() == aProcessId) + { + SafeDelete(iDebugProcessList[i]); + iDebugProcessList.Remove(i); + } + } + + TUint8 event = kDSOSNotifyDeleted; + TUint16 type = kDSOSProcessItem; + + AddToReplyBufferL(event, true); + AddToReplyBufferL(type); + AddToReplyBufferL((TUint32)aExitCode); + AddToReplyBufferL(aProcessId); + + InformEventL(); +} + +// +// CTrkDispatchLayer::DoNotifyLibraryLoadedL +// +// Notify the host debugger that a library in now loaded +// +void CTrkDispatchLayer::DoNotifyLibraryLoadedL(TDesC8 &aName, TUint32 aProcessId, TUint32 aThreadId, TUint32 aCodeBaseAddress, TUint32 aDataBaseAddress) +{ + TUint8 event = kDSOSNotifyCreated; + TUint16 type = kDSOSDLLItem; + + TUint16 nameLength = aName.Length(); + + AddToReplyBufferL(event, true); + AddToReplyBufferL(type); + AddToReplyBufferL(aProcessId); + AddToReplyBufferL(aThreadId); + AddToReplyBufferL(aCodeBaseAddress); + AddToReplyBufferL(aDataBaseAddress); + AddToReplyBufferL(nameLength); + AddToReplyBufferL(aName); + + InformEventL(); +} + +// +// CTrkDispatchLayer::DoNotifyLibraryUnloadedL +// +// Notify the host debugger that a library has been unloaded +// +void CTrkDispatchLayer::DoNotifyLibraryUnloadedL(TDesC8 &aName, TUint32 aProcessId, TUint32 aThreadId) +{ + TUint8 event = kDSOSNotifyDeleted; + TUint16 type = kDSOSDLLItem; + + TUint16 nameLength = aName.Length(); + + AddToReplyBufferL(event, true); + AddToReplyBufferL(type); + AddToReplyBufferL(aProcessId); + AddToReplyBufferL(aThreadId); + AddToReplyBufferL(nameLength); + AddToReplyBufferL(aName); + + InformEventL(); +} + +// +// CTrkDispatchLayer::GetDataFromBufferL +// +// Notify the host debugger that trace data has been recieved +// +void CTrkDispatchLayer::DoNotifyUserTraceL(TDesC8 &aTrace) +{ + if (iIsConnected) + iFramingLayer->SendRawMsgL(aTrace); +} + +void CTrkDispatchLayer::DoNotifyProcessAddedL(TDesC8 &aName, TUint32 aProcessId, TUint32 aThreadId, TUint32 aUid, TUint32 aCodeBaseAddress, TUint32 aDataBaseAddress) +{ + // check to see if the host supported protocol handles this event, + // otherwise just resume the thread. If not, this thread would get suspended indefinitely. + if (iHostVersion.iMajor < 3 || (iHostVersion.iMajor == 3 && iHostVersion.iMinor <= 3)) + { + iKernelDriver.ResumeThread(aThreadId); + } + else + { + TUint8 event = kDSOSNotifyCreated; + TUint16 type = kDSOSProcessItem; + + TUint16 nameLength = aName.Length(); + + AddToReplyBufferL(event, true); + AddToReplyBufferL(type); + AddToReplyBufferL(aProcessId); + AddToReplyBufferL(aThreadId); + AddToReplyBufferL(aUid); + AddToReplyBufferL(aCodeBaseAddress); + AddToReplyBufferL(aDataBaseAddress); + AddToReplyBufferL(nameLength); + AddToReplyBufferL(aName); + + InformEventL(); + } +} + +// +// CTrkDispatchLayer::DoReadLibraryInfoL() +// +void CTrkDispatchLayer::DoReadLibraryInfoL(TDesC8& aFileName) +{ + TMetroTrkLibInfo libInfo(aFileName.Length(), &aFileName); + + TInt err = iKernelDriver.GetLibraryInfo(libInfo); + + if (err == KErrNone) + { + AddToReplyBufferL(libInfo.iCodeAddress, true); + AddToReplyBufferL(libInfo.iDataAddress); + AddToReplyBufferL(libInfo.iAttachProcessId); + AddToReplyBufferL(libInfo.iAttachThreadId); + + RespondOkL(); + } + else + { + User::Leave(err); + } +} + +// +// CTrkDispatchLayer::DoReadProcessInfoL() +// +void CTrkDispatchLayer::DoReadProcessInfoL(TUint32 aUid, TDesC8& aFileName) +{ + TMetroTrkExeInfo exeInfo(aUid, aFileName.Length(), &aFileName); + + TInt err = iKernelDriver.GetExeInfo(exeInfo); + + if (err == KErrNone) + { + AddToReplyBufferL(exeInfo.iProcessID, true); + AddToReplyBufferL(exeInfo.iThreadID); + AddToReplyBufferL(exeInfo.iCodeAddress); + AddToReplyBufferL(exeInfo.iDataAddress); + + RespondOkL(); + } + else + { + User::Leave(err); + } +} + +// +// CTrkDispatchLayer::GetDataFromBufferL +// +// Get data from the input buffer +// +void CTrkDispatchLayer::GetDataFromBufferL(TAny* aData, TInt aLength) +{ + if (aLength > iInputBuffer->Length()) + User::Leave(kDSReplyPacketSizeError); + + if (iFramingLayer->IsBigEndian()) + { + Mem::Copy(aData, iInputBuffer->Ptr(), aLength); + } + else + { + TUint8 *p = (TUint8 *)aData; + for (int i=aLength-1, j=0; i>=0; i--, j++) + p[j] = iInputBuffer->Ptr()[i]; + } + + // now remove it from the buffer + iInputBuffer->Des().Delete(0, aLength); +} + +// +// CTrkDispatchLayer::AddToReplyBufferL +// +// Add data to the buffer which will be sent back to the host as a reply +// +void CTrkDispatchLayer::AddToReplyBufferL(TUint8 aData, TBool aReset) +{ + if (aReset) + { + // free the memory associated with the old reply buffer and allocate a new one + SafeDelete(iReplyBuffer); + iReplyBuffer = HBufC8::New(sizeof(TUint8)); + } + else + { + // reallocate to make enough room for the new data + iReplyBuffer = iReplyBuffer->ReAlloc(iReplyBuffer->Length() + sizeof(TUint8)); + } + + // make sure the above worked + if (!iReplyBuffer) + User::Leave(KErrNoMemory); + + iReplyBuffer->Des().Append(aData); +} + +// +// CTrkDispatchLayer::AddToReplyBufferL +// +// Add data to the buffer which will be sent back to the host as a reply +// +void CTrkDispatchLayer::AddToReplyBufferL(TUint16 aData, TBool aReset) +{ + TUint16 temp = aData; + + if (aReset) + { + // free the memory associated with the old reply buffer and allocate a new one + SafeDelete(iReplyBuffer); + iReplyBuffer = HBufC8::New(sizeof(TUint16)); + } + else + { + // reallocate to make enough room for the new data + iReplyBuffer = iReplyBuffer->ReAlloc(iReplyBuffer->Length() + sizeof(TUint16)); + } + + // make sure the above worked + if (!iReplyBuffer) + User::Leave(KErrNoMemory); + + // the host expects all values except for raw data to be returned in big endian format + if (!iFramingLayer->IsBigEndian()) + { + temp = Swap2(aData); + } + + iReplyBuffer->Des().Append((TUint8 *)&temp, sizeof(TUint16)); +} + +// +// CTrkDispatchLayer::AddToReplyBufferL +// +// Add data to the buffer which will be sent back to the host as a reply +// +void CTrkDispatchLayer::AddToReplyBufferL(TUint32 aData, TBool aReset) +{ + TUint32 temp = aData; + + if (aReset) + { + // free the memory associated with the old reply buffer and allocate a new one + SafeDelete(iReplyBuffer); + iReplyBuffer = HBufC8::New(sizeof(TUint32)); + } + else + { + // reallocate to make enough room for the new data + iReplyBuffer = iReplyBuffer->ReAlloc(iReplyBuffer->Length() + sizeof(TUint32)); + } + + // make sure the above worked + if (!iReplyBuffer) + User::Leave(KErrNoMemory); + + // the host expects all values except for raw data to be returned in big endian format + if (!iFramingLayer->IsBigEndian()) + { + temp = Swap4(aData); + } + + iReplyBuffer->Des().Append((TUint8 *)&temp, sizeof(TUint32)); +} + +// +// CTrkDispatchLayer::AddToReplyBufferL +// +// Add data to the buffer which will be sent back to the host as a reply +// +void CTrkDispatchLayer::AddToReplyBufferL(const TDesC8 &aData, TBool aReset) +{ + if (aReset) + { + // free the memory associated with the old reply buffer and allocate a new one + SafeDelete(iReplyBuffer); + iReplyBuffer = HBufC8::New(aData.Length()); + } + else + { + // reallocate to make enough room for the new data + iReplyBuffer = iReplyBuffer->ReAlloc(iReplyBuffer->Length() + aData.Length()); + } + + // make sure the above worked + if (!iReplyBuffer) + User::Leave(KErrNoMemory); + + iReplyBuffer->Des().Append(aData); +} + +// +// CTrkDispatchLayer::IsThreadSuspended +// +// Determines whether or not a thread is suspended +// +TUint8 CTrkDispatchLayer::IsThreadSuspended(TUint32 aThreadId) +{ + if (iSuspendedThreadList.Find(aThreadId) >= 0) + return 1; + + return 0; +} + +// +// CTrkDispatchLayer::IsRestrictedFolder +// +// Check to see if the path is any of the data caged paths like \sys\ or \private\ or \resource\ +// +TBool CTrkDispatchLayer::IsRestrictedFolder(const TDesC& aPath) +{ + _LIT(KSYS, "\\sys\\"); + _LIT(KRESOURCE, "\\resource\\"); + _LIT(KPRIVATE, "\\private\\"); + + if ( (aPath.FindC(KSYS)>=0) || (aPath.FindC(KRESOURCE)>=0) || (aPath.FindC(KPRIVATE)>=0) ) + return ETrue; + + return EFalse; +} + + +TInt CTrkDispatchLayer::CloseCrashLogger() +{ + TInt err = KErrNone; + + //The old mobile crash file name is "d_exc_mc.exe" and the new one is "mc_useragent.exe" + //This is the string that needs to be passed to the RProcess::Open call to get a handle. + //The complete process name actually includes the UID info as well. + //Instead of hard coding the process name, its better to just + //search for the process and find it that way. + //_LIT16(KCrashLoggerName, "mc_useragent.exe[1020e519]0001"); + _LIT16(KOldCrashLoggerName, "d_exc_mc*"); + _LIT16(KCrashLoggerName, "mc_useragent*"); + + err = TerminateProcess(KOldCrashLoggerName); + err = TerminateProcess(KCrashLoggerName); + + return err; +} + +TInt CTrkDispatchLayer::TerminateProcess(const TDesC& aProcessName) +{ + TFindProcess find(aProcessName); + TFullName name; + + TInt err = find.Next(name); + if (KErrNone == err) + { + RProcess process; + err = process.Open(find); + + if (KErrNone == err) + { + process.Kill(KErrNone); + } + } + return err; +}