1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/os/kernelhwsrv/kernel/eka/drivers/debug/rmdebug/rm_debug_kerneldriver.cpp Fri Jun 15 03:10:57 2012 +0200
1.3 @@ -0,0 +1,3760 @@
1.4 +// Copyright (c) 2004-2009 Nokia Corporation and/or its subsidiary(-ies).
1.5 +// All rights reserved.
1.6 +// This component and the accompanying materials are made available
1.7 +// under the terms of the License "Eclipse Public License v1.0"
1.8 +// which accompanies this distribution, and is available
1.9 +// at the URL "http://www.eclipse.org/legal/epl-v10.html".
1.10 +//
1.11 +// Initial Contributors:
1.12 +// Nokia Corporation - initial contribution.
1.13 +//
1.14 +// Contributors:
1.15 +//
1.16 +// Description:
1.17 +// Device driver for kernel side debug assist
1.18 +//
1.19 +
1.20 +#ifdef __WINS__
1.21 +#error - this driver cannot be built for emulation
1.22 +#endif
1.23 +
1.24 +#include <e32def.h>
1.25 +#include <e32def_private.h>
1.26 +#include <e32cmn.h>
1.27 +#include <e32cmn_private.h>
1.28 +#include <e32ldr.h>
1.29 +#include <u32std.h>
1.30 +#include <kernel/kernel.h>
1.31 +#include <kernel/kern_priv.h>
1.32 +#include <nk_trace.h>
1.33 +#include <arm.h>
1.34 +#include <kernel/cache.h>
1.35 +#include <platform.h>
1.36 +#include <nkern.h>
1.37 +#include <u32hal.h>
1.38 +#include <kernel/kdebug.h>
1.39 +#include <rm_debug_api.h>
1.40 +
1.41 +#include "debug_logging.h"
1.42 +#include "d_rmd_breakpoints.h" // moved breakpoints code lives here
1.43 +#include "d_rmd_stepping.h" // moved stepping code lives here
1.44 +#include "rm_debug_kerneldriver.h"
1.45 +#include "d_list_manager.h"
1.46 +#include "rm_debug_driver.h"
1.47 +#include "rm_debug_eventhandler.h"
1.48 +#include "d_debug_functionality.h"
1.49 +#include "d_process_tracker.h"
1.50 +#include "debug_utils.h"
1.51 +#include "d_buffer_manager.h"
1.52 +
1.53 +using namespace Debug;
1.54 +
1.55 +/////////////////////////////////////////////////////////////////////////
1.56 +//
1.57 +// DRM_DebugDriverFactory implementation
1.58 +//
1.59 +/////////////////////////////////////////////////////////////////////////
1.60 +
1.61 +//
1.62 +// DRM_DebugDriverFactory constructor
1.63 +//
1.64 +DRM_DebugDriverFactory::DRM_DebugDriverFactory()
1.65 +{
1.66 + iVersion = TVersion(KMajorVersionNumber,KMinorVersionNumber,KBuildVersionNumber);
1.67 +}
1.68 +
1.69 +//
1.70 +// DRM_DebugDriverFactory::Create
1.71 +//
1.72 +TInt DRM_DebugDriverFactory::Create(DLogicalChannelBase*& aChannel)
1.73 +{
1.74 + if (iOpenChannels != 0)
1.75 + return KErrInUse; // a channel is already open
1.76 +
1.77 + aChannel = new DRM_DebugChannel(this);
1.78 +
1.79 + return aChannel ? KErrNone : KErrNoMemory;
1.80 +}
1.81 +
1.82 +//
1.83 +// DRM_DebugDriverFactory::Install
1.84 +//
1.85 +TInt DRM_DebugDriverFactory::Install()
1.86 +{
1.87 + return(SetName(&KRM_DebugDriverName));
1.88 +}
1.89 +
1.90 +//
1.91 +// DRM_DebugDriverFactory::Install
1.92 +//
1.93 +void DRM_DebugDriverFactory::GetCaps(TDes8& aDes) const
1.94 +{
1.95 + TCapsRM_DebugDriver b;
1.96 + b.iVersion = TVersion(KMajorVersionNumber, KMinorVersionNumber, KBuildVersionNumber);
1.97 +
1.98 + Kern::InfoCopy(aDes,(TUint8*)&b,sizeof(b));
1.99 +}
1.100 +
1.101 +/////////////////////////////////////////////////////////////////////////
1.102 +//
1.103 +// DRM_DebugChannel implementation
1.104 +//
1.105 +/////////////////////////////////////////////////////////////////////////
1.106 +
1.107 +//
1.108 +// DRM_DebugChannel constructor
1.109 +//
1.110 +DRM_DebugChannel::DRM_DebugChannel(DLogicalDevice* aLogicalDevice)
1.111 + : iExcludedROMAddressStart(ROM_LINEAR_BASE),
1.112 + iExcludedROMAddressEnd(0),
1.113 + iPageSize(0x1000),
1.114 + iBreakManager(0),
1.115 + iStepper(0),
1.116 + iStepLock(0),
1.117 + iDfcQ(NULL),
1.118 + iInitialisedCodeModifier(0),
1.119 + iAsyncGetValueRequest(NULL)
1.120 +{
1.121 + LOG_MSG("DRM_DebugChannel::DRM_DebugChannel()");
1.122 +
1.123 + iDevice = aLogicalDevice;
1.124 +
1.125 + iClientThread = &Kern::CurrentThread();
1.126 + iClientThread->Open();
1.127 +
1.128 + iPageSize = Kern::RoundToPageSize(1);
1.129 +}
1.130 +
1.131 +//
1.132 +// DRM_DebugChannel destructor
1.133 +//
1.134 +DRM_DebugChannel::~DRM_DebugChannel()
1.135 +{
1.136 + LOG_MSG("DRM_DebugChannel::~DRM_DebugChannel()");
1.137 +
1.138 + if (iAsyncGetValueRequest)
1.139 + {
1.140 + Kern::QueueRequestComplete(iClientThread, iAsyncGetValueRequest, KErrCancel); // does nothing if request not pending
1.141 + Kern::DestroyClientRequest(iAsyncGetValueRequest);
1.142 + }
1.143 +
1.144 + NKern::ThreadEnterCS();
1.145 + Kern::SafeClose((DObject*&)iClientThread, NULL);
1.146 + NKern::ThreadLeaveCS();
1.147 +
1.148 + // Close breakpoint manager
1.149 + if (iBreakManager)
1.150 + {
1.151 + NKern::ThreadEnterCS();
1.152 + delete iBreakManager;
1.153 + NKern::ThreadLeaveCS();
1.154 + }
1.155 +
1.156 + // Close stepping manager
1.157 + if (iStepper)
1.158 + {
1.159 + NKern::ThreadEnterCS();
1.160 + delete iStepper;
1.161 + NKern::ThreadLeaveCS();
1.162 + }
1.163 +
1.164 + //close the debug process list
1.165 + iDebugProcessList.Close();
1.166 +
1.167 + DestroyDfcQ();
1.168 +
1.169 + //close the code modifier
1.170 + if (iInitialisedCodeModifier)
1.171 + {
1.172 + DebugSupport::CloseCodeModifier();
1.173 + }
1.174 +}
1.175 +
1.176 +void DRM_DebugChannel::DestroyDfcQ()
1.177 + {
1.178 + LOG_MSG("DRM_DebugChannel::DestroyDfcQ()");
1.179 + if (iDfcQ)
1.180 + {
1.181 + NKern::ThreadEnterCS();
1.182 + iDfcQ->Destroy();
1.183 + NKern::ThreadLeaveCS();
1.184 + }
1.185 + }
1.186 +
1.187 +//
1.188 +// DRM_DebugChannel::DoCreate
1.189 +//
1.190 +TInt DRM_DebugChannel::DoCreate(TInt /*aUnit*/, const TDesC* anInfo, const TVersion& aVer)
1.191 +{
1.192 + LOG_MSG("DRM_DebugChannel::DoCreate()");
1.193 + TInt err = Kern::CreateClientDataRequest(iAsyncGetValueRequest);
1.194 + if(err != KErrNone)
1.195 + return err;
1.196 +
1.197 + if (!Kern::QueryVersionSupported(TVersion(KMajorVersionNumber, KMinorVersionNumber, KBuildVersionNumber), aVer))
1.198 + return KErrNotSupported;
1.199 +
1.200 + // Do the security check here so that any arbitrary application doesn't make
1.201 + // use of Trk kernel driver.
1.202 + if (!DoSecurityCheck())
1.203 + {
1.204 + LOG_MSG("DRM_DebugChannel::DoCreate() - permission denied!");
1.205 + return KErrPermissionDenied;
1.206 + }
1.207 +
1.208 + if (anInfo)
1.209 + {
1.210 + // this is the end address of the user library.
1.211 + // this doesn't seem to be valid for EKA2.
1.212 + // right now we dont need this for EKA2 since we are not worried
1.213 + // about kernel being stopped as kernel is multithreaded.
1.214 + // just retaining this for future use.
1.215 + TBuf8<32> buf;
1.216 + TInt err = Kern::ThreadRawRead(iClientThread, anInfo, &buf, 32);
1.217 + if(err != KErrNone)
1.218 + return err;
1.219 +
1.220 + //iExcludedROMAddressEnd = *(TUint32 *)(&(buf.Ptr()[20]));
1.221 + }
1.222 +
1.223 + // Allocate a D_RMD_Breakpoints class as a breakpoint manager
1.224 + NKern::ThreadEnterCS();
1.225 + iBreakManager = new D_RMD_Breakpoints(this);
1.226 + NKern::ThreadLeaveCS();
1.227 + if (iBreakManager == NULL)
1.228 + {
1.229 + LOG_MSG("DRM_DebugChannel::DRM_DebugChannel - could not construct breakpoint manager");
1.230 + return KErrNoMemory;
1.231 + }
1.232 +
1.233 + // Initialise the new breakpoint manager object
1.234 + iBreakManager->Init();
1.235 +
1.236 + // Allocate a DRMDStepping class as the stepping manager
1.237 + NKern::ThreadEnterCS();
1.238 + iStepper = new DRMDStepping(this);
1.239 + NKern::ThreadLeaveCS();
1.240 + if (iStepper == NULL)
1.241 + {
1.242 + LOG_MSG("DRM_DebugChannel::DRM_DebugChannel - could not construct stepper manager");
1.243 + return KErrNoMemory;
1.244 + }
1.245 +
1.246 + // Initialize the code modifier for managing breakpoints.
1.247 + TUint caps; //ignored for now
1.248 + err = DebugSupport::InitialiseCodeModifier(caps, NUMBER_OF_MAX_BREAKPOINTS);
1.249 + //if code modifier initializer failed,
1.250 + //return here, since we can't set an breakpoints
1.251 + if(err != KErrNone)
1.252 + {
1.253 + return err;
1.254 + }
1.255 + else
1.256 + {
1.257 + iInitialisedCodeModifier = ETrue;
1.258 + }
1.259 +
1.260 + //create and set the driver's Dfc queue
1.261 + err = CreateDfcQ();
1.262 + if(err != KErrNone)
1.263 + {
1.264 + LOG_MSG("DRM_DebugChannel::DoCreate() Creating Dfc queue failed.");
1.265 + }
1.266 + SetDfcQ(iDfcQ);
1.267 +
1.268 + iMsgQ.Receive();
1.269 +
1.270 + iEventHandler = new DRM_DebugEventHandler;
1.271 + if (!iEventHandler)
1.272 + return KErrNoMemory;
1.273 + err = iEventHandler->Create(iDevice, this, iClientThread);
1.274 + if (err != KErrNone)
1.275 + return err;
1.276 +
1.277 + //return KErrNone;
1.278 + return iEventHandler->Start();
1.279 +}
1.280 +
1.281 +//
1.282 +// DRM_DebugChannel::SendMsg
1.283 +//
1.284 +TInt DRM_DebugChannel::SendMsg(TMessageBase* aMsg)
1.285 + {
1.286 + LOG_MSG("DRM_DebugChannel::SendMsg()");
1.287 +
1.288 + TThreadMessage& m = *(TThreadMessage*)aMsg;
1.289 + TInt id = m.iValue;
1.290 + TInt err = KErrNone;
1.291 +
1.292 + if (id != (TInt)ECloseMsg && id != KMaxTInt && id < 0)
1.293 + {
1.294 + // DoRequest
1.295 + TRequestStatus* pStatus = (TRequestStatus*)m.Ptr0();
1.296 + err = SendRequest(aMsg);
1.297 + if (err != KErrNone)
1.298 + Kern::RequestComplete(pStatus,err);
1.299 + }
1.300 + else
1.301 + {
1.302 + err = DLogicalChannel::SendMsg(aMsg);
1.303 + }
1.304 + return err;
1.305 + }
1.306 +
1.307 +//
1.308 +// DRM_DebugChannel::SendRequest
1.309 +//
1.310 +TInt DRM_DebugChannel::SendRequest(TMessageBase* aMsg)
1.311 + {
1.312 + LOG_MSG("DRM_DebugChannel::SendRequest()");
1.313 +
1.314 + TThreadMessage& m = *(TThreadMessage*)aMsg;
1.315 + TInt function = ~m.iValue;
1.316 + TRequestStatus* pStatus = (TRequestStatus*)m.Ptr0();
1.317 + TAny* a1 = m.Ptr1();
1.318 +
1.319 + TInt err = KErrNotSupported;
1.320 + switch(function)
1.321 + {
1.322 + case RRM_DebugDriver::ERequestGetEvent:
1.323 + err = PreAsyncGetValue((TEventInfo*)a1,pStatus);
1.324 + break;
1.325 + }
1.326 + if (err == KErrNone)
1.327 + err = DLogicalChannel::SendMsg(aMsg);
1.328 + return err;
1.329 + }
1.330 +
1.331 +//
1.332 +// DRM_DebugChannel::PreAsyncGetValue
1.333 +//
1.334 +TInt DRM_DebugChannel::PreAsyncGetValue(TEventInfo* aValue, TRequestStatus* aStatus)
1.335 + {
1.336 + LOG_MSG("DRM_DebugChannel::PreAsyncGetValue()");
1.337 +
1.338 + iAsyncGetValueRequest->Reset();
1.339 +
1.340 + TInt err = iAsyncGetValueRequest->SetStatus(aStatus);
1.341 + if (err != KErrNone)
1.342 + return err;
1.343 +
1.344 + iAsyncGetValueRequest->SetDestPtr(aValue);
1.345 + return KErrNone;
1.346 + }
1.347 +
1.348 +/**
1.349 + Create the Dfc queue for receiving messages
1.350 + */
1.351 +TInt DRM_DebugChannel::CreateDfcQ()
1.352 + {
1.353 + LOG_MSG("DRM_DebugChannel::CreateDfcQ()");
1.354 + TInt r = Kern::DynamicDfcQCreate(iDfcQ, KRmDebugDriverThreadPriority, KRM_DebugDriverName);
1.355 + // Fix to stop t_rmdebug2 etc crashing the device.
1.356 + // This should be removed once the rm debug driver has been updated for WDP.
1.357 + if (r == KErrNone)
1.358 + iDfcQ->SetRealtimeState(ERealtimeStateOff);
1.359 + return r;
1.360 + }
1.361 +
1.362 +//
1.363 +// DRM_DebugChannel::DoCancel
1.364 +//
1.365 +// New: The cancel call does not take an enum parameter describing
1.366 +// the request to be cancelled. Rather it supplies a pointer
1.367 +// to a user-side struct defining the cancellation
1.368 +//
1.369 +void DRM_DebugChannel::DoCancel(TInt aReqNo)
1.370 +{
1.371 + LOG_MSG("DRM_DebugChannel::DoCancel()");
1.372 +
1.373 + TRMD_DebugCancelInfo info;
1.374 +
1.375 + TInt err = Kern::ThreadRawRead(iClientThread,(TAny*)aReqNo,(TAny*)&info,sizeof(info));
1.376 + if (err != KErrNone)
1.377 + {
1.378 + // How do we cancel something we know nothing about???
1.379 + LOG_MSG("DRM_DebugChannel::DoCancel - bad arguments");
1.380 + return;
1.381 + }
1.382 +
1.383 + // Find the process
1.384 + DTargetProcess* pProcess = TheDProcessTracker.FindProcess(info.iProcessName);
1.385 + if (pProcess == NULL)
1.386 + {
1.387 + // We are doomed. We don't know which event to cancel..
1.388 + LOG_MSG2("Cannot determine which process is being debugged: %S", &(info.iProcessName));
1.389 +
1.390 + return;
1.391 + }
1.392 +
1.393 + // Find the agent
1.394 + DDebugAgent* debugAgent = pProcess->Agent(info.iAgentId);
1.395 + if (debugAgent == NULL)
1.396 + {
1.397 + // Bad agent means there is no tracking agent
1.398 + LOG_MSG2("Cannot locate debug agent with pid 0x%0x16lx",info.iAgentId);
1.399 + return;
1.400 + }
1.401 +
1.402 + // Agent completes/pends the request as appropriate.
1.403 + debugAgent->CancelGetEvent();
1.404 +
1.405 +}
1.406 +
1.407 +//
1.408 +// DRM_DebugChannel::DoRequest
1.409 +//
1.410 +void DRM_DebugChannel::DoRequest(TInt aReqNo, TRequestStatus* aStatus, TAny* a1, TAny* a2)
1.411 +{
1.412 + LOG_MSG("DRM_DebugChannel::DoRequest()");
1.413 +
1.414 + switch(aReqNo)
1.415 + {
1.416 + case RRM_DebugDriver::ERequestGetEvent:
1.417 + {
1.418 + TEventMetaData eventMetaData;
1.419 + TInt err = Kern::ThreadRawRead(iClientThread, a2, (TUint8 *)&eventMetaData, sizeof(TEventMetaData) );
1.420 + if (err != KErrNone)
1.421 + {
1.422 + LOG_MSG("Error: could not read argument data from the DSS (TEventMetaData)");
1.423 +
1.424 + // We could not read information from the user, so the a2 argument is probably wrong
1.425 + Kern::RequestComplete(iClientThread, aStatus, KErrArgument);
1.426 + return;
1.427 + }
1.428 +
1.429 + // Find the process
1.430 + DTargetProcess* pProcess = TheDProcessTracker.FindProcess(eventMetaData.iTargetProcessName);
1.431 + if (pProcess == NULL)
1.432 + {
1.433 + LOG_MSG("Cannot identify process being debugged");
1.434 +
1.435 + // We could not locate the process, so the user asked for the wrong one.
1.436 + Kern::RequestComplete(iClientThread, aStatus, KErrArgument);
1.437 + return;
1.438 + }
1.439 +
1.440 + // Find the agent
1.441 + DDebugAgent* debugAgent = pProcess->Agent(eventMetaData.iDebugAgentProcessId);
1.442 + if (debugAgent == NULL)
1.443 + {
1.444 + // Bad agent means there is no tracking agent
1.445 + LOG_MSG2("Cannot locate debug agent with pid 0x%0x16lx",eventMetaData.iDebugAgentProcessId);
1.446 + return;
1.447 + }
1.448 + // Agent completes/pends the request as appropriate.
1.449 + debugAgent->GetEvent(iAsyncGetValueRequest, (TEventInfo*)a1, iClientThread);
1.450 +
1.451 + break;
1.452 + }
1.453 + default:
1.454 + {
1.455 + // Don't know what to do, should not get here!
1.456 + LOG_MSG("DRM_DebugChannel::DoRequest was passed an unsupported request aReqNo");
1.457 +
1.458 + Kern::RequestComplete(iClientThread, aStatus, KErrNotSupported);
1.459 + }
1.460 + }
1.461 +}
1.462 +
1.463 +//
1.464 +// DRM_DebugChannel::DoControl
1.465 +//
1.466 +TInt DRM_DebugChannel::DoControl(TInt aFunction, TAny* a1, TAny* a2)
1.467 +{
1.468 + LOG_MSG("DRM_DebugChannel::DoControl()");
1.469 +
1.470 + LOG_MSG2("DoControl Function %d", aFunction);
1.471 +
1.472 + TInt err = KErrBadHandle;
1.473 + DThread* threadObj = NULL;
1.474 +
1.475 + switch(aFunction)
1.476 + {
1.477 + /* Security first */
1.478 + case RRM_DebugDriver::EControlIsDebuggable:
1.479 + {
1.480 + err = IsDebuggable((TUint32)a1);
1.481 + break;
1.482 + }
1.483 + case RRM_DebugDriver::EControlSetBreak:
1.484 + {
1.485 + err = SetBreak((TSetBreakInfo*)a1);
1.486 + break;
1.487 + }
1.488 + case RRM_DebugDriver::EControlClearBreak:
1.489 + {
1.490 + err = iBreakManager->DoClearBreak((TInt32)a1);
1.491 + break;
1.492 + }
1.493 + case RRM_DebugDriver::EControlModifyBreak:
1.494 + {
1.495 + err = iBreakManager->DoModifyBreak((TModifyBreakInfo*)a1);
1.496 + break;
1.497 + }
1.498 + case RRM_DebugDriver::EControlModifyProcessBreak:
1.499 + {
1.500 + err = iBreakManager->DoModifyProcessBreak((TModifyProcessBreakInfo*)a1);
1.501 + break;
1.502 + }
1.503 + case RRM_DebugDriver::EControlBreakInfo:
1.504 + {
1.505 + err = iBreakManager->DoBreakInfo((TGetBreakInfo*)a1);
1.506 + break;
1.507 + }
1.508 + case RRM_DebugDriver::EControlSuspendThread:
1.509 + {
1.510 + threadObj = DebugUtils::OpenThreadHandle((TUint32)a1);
1.511 + if (threadObj)
1.512 + {
1.513 + err = DoSuspendThread(threadObj);
1.514 + }
1.515 + break;
1.516 + }
1.517 + case RRM_DebugDriver::EControlResumeThread:
1.518 + {
1.519 + threadObj = DebugUtils::OpenThreadHandle((TUint32)a1);
1.520 + if (threadObj)
1.521 + {
1.522 + err = DoResumeThread(threadObj);
1.523 + }
1.524 + break;
1.525 + }
1.526 + case RRM_DebugDriver::EControlStepRange:
1.527 + {
1.528 + threadObj = DebugUtils::OpenThreadHandle((TUint32)a1);
1.529 + if (threadObj)
1.530 + {
1.531 + err = StepRange(threadObj, (TRM_DebugStepInfo*)a2);
1.532 + }
1.533 + break;
1.534 + }
1.535 + case RRM_DebugDriver::EControlReadMemory:
1.536 + {
1.537 + threadObj = DebugUtils::OpenThreadHandle((TUint32)a1);
1.538 + if (threadObj)
1.539 + {
1.540 + err = ReadMemory(threadObj, (TRM_DebugMemoryInfo*)a2);
1.541 + }
1.542 + break;
1.543 + }
1.544 + case RRM_DebugDriver::EControlWriteMemory:
1.545 + {
1.546 + threadObj = DebugUtils::OpenThreadHandle((TUint32)a1);
1.547 + if (threadObj)
1.548 + {
1.549 + err = WriteMemory(threadObj, (TRM_DebugMemoryInfo*)a2);
1.550 + }
1.551 + break;
1.552 + }
1.553 + case RRM_DebugDriver::EControlReadRegistersLegacy:
1.554 + {
1.555 + threadObj = DebugUtils::OpenThreadHandle((TUint32)a1);
1.556 + if (threadObj)
1.557 + {
1.558 + err = ReadRegistersLegacy(threadObj, (TRM_DebugRegisterInfo*)a2);
1.559 + }
1.560 + break;
1.561 + }
1.562 + case RRM_DebugDriver::EControlWriteRegistersLegacy:
1.563 + {
1.564 + threadObj = DebugUtils::OpenThreadHandle((TUint32)a1);
1.565 + if (threadObj)
1.566 + {
1.567 + err = WriteRegistersLegacy(threadObj, (TRM_DebugRegisterInfo*)a2);
1.568 + }
1.569 + break;
1.570 + }
1.571 + case RRM_DebugDriver::EControlReadRegisters:
1.572 + {
1.573 + threadObj = DebugUtils::OpenThreadHandle((TUint32)a1);
1.574 + if (threadObj)
1.575 + {
1.576 + err = ReadRegisters(threadObj, (TRM_DebugRegisterInformation*)a2);
1.577 + }
1.578 + break;
1.579 + }
1.580 + case RRM_DebugDriver::EControlWriteRegisters:
1.581 + {
1.582 + threadObj = DebugUtils::OpenThreadHandle((TUint32)a1);
1.583 + if (threadObj)
1.584 + {
1.585 + err = WriteRegisters(threadObj, (TRM_DebugRegisterInformation*)a2);
1.586 + }
1.587 + break;
1.588 + }
1.589 + case RRM_DebugDriver::EControlGetDebugFunctionalityBufSize:
1.590 + {
1.591 + LOG_MSG("RRM_DebugDriver::EControlGetDebugFunctionalityBufSize\n");
1.592 +
1.593 + TDebugFunctionality df;
1.594 +
1.595 + TUint size = df.GetDebugFunctionalityBufSize();
1.596 +
1.597 + // Return size to user-side in a safe manner
1.598 + err = Kern::ThreadRawWrite(iClientThread, a1, (TUint8*)&size, sizeof(TUint), iClientThread);
1.599 + break;
1.600 + }
1.601 + case RRM_DebugDriver::EControlGetDebugFunctionality:
1.602 + {
1.603 + LOG_MSG("RRM_DebugDriver::EControlGetDebugFunctionality\n");
1.604 +
1.605 + TDebugFunctionality df;
1.606 +
1.607 + TUint32 dfsize = df.GetDebugFunctionalityBufSize();
1.608 +
1.609 + // Alloc tmp buffer for Debug Functionality data
1.610 + NKern::ThreadEnterCS();
1.611 + TUint8* dfbuffer = (TUint8*)Kern::AllocZ(dfsize);
1.612 + NKern::ThreadLeaveCS();
1.613 + if (dfbuffer==NULL)
1.614 + {
1.615 + LOG_MSG2("Could not allocate memory for %d bytes\n",dfsize);
1.616 +
1.617 + // could not allocate memory
1.618 + return KErrNoMemory;
1.619 + }
1.620 +
1.621 + // Temporary descriptor to hold DF data
1.622 + TPtr8 tmpPtr(dfbuffer,0,dfsize);
1.623 +
1.624 + // Obtain the DF data
1.625 + if (df.GetDebugFunctionality(tmpPtr) )
1.626 + {
1.627 + // Return the DF data to the user-side
1.628 + err = Kern::ThreadDesWrite(iClientThread, a1, tmpPtr, 0, KChunkShiftBy0, iClientThread);
1.629 + }
1.630 + else
1.631 + {
1.632 + // Failed.
1.633 + err = KErrGeneral;
1.634 + }
1.635 +
1.636 + // Free tmp buffer
1.637 + NKern::ThreadEnterCS();
1.638 + Kern::Free(dfbuffer);
1.639 + NKern::ThreadLeaveCS();
1.640 + break;
1.641 + }
1.642 + case RRM_DebugDriver::EControlAttachProcess:
1.643 + {
1.644 + LOG_MSG("RRM_DebugDriver::EControlAttachProcess");
1.645 +
1.646 + err = AttachProcess(a1,a2);
1.647 + break;
1.648 + }
1.649 + case RRM_DebugDriver::EControlDetachProcess:
1.650 + {
1.651 + LOG_MSG("RRM_DebugDriver::EControlDetachProcess");
1.652 +
1.653 + err = DetachProcess(a1,a2);
1.654 + break;
1.655 + }
1.656 + case RRM_DebugDriver::EControlDetachAgent:
1.657 + {
1.658 + LOG_MSG("RRM_DebugDriver::EControlDetachAgent");
1.659 +
1.660 + err = DetachAgent(a1,a2);
1.661 + break;
1.662 + }
1.663 + case RRM_DebugDriver::EControlSetEventAction:
1.664 + {
1.665 + LOG_MSG("RRM_DebugDriver::EControlSetEventAction");
1.666 +
1.667 + err = SetEventAction(a1,a2);
1.668 + break;
1.669 + }
1.670 + case RRM_DebugDriver::EControlGetMemoryOperationMaxBlockSize:
1.671 + {
1.672 + LOG_MSG("RRM_DebugDriver::EControlGetMemoryOperationMaxBlockSize\n");
1.673 +
1.674 + TUint32 maxSize = TDebugFunctionality::GetMemoryOperationMaxBlockSize();
1.675 +
1.676 + // Return size to user-side in a safe manner
1.677 + err = Kern::ThreadRawWrite(iClientThread, a1, (TUint8*)&maxSize, sizeof(TUint32), iClientThread);
1.678 + break;
1.679 + }
1.680 + case RRM_DebugDriver::EControlGetList:
1.681 + {
1.682 + LOG_MSG("RRM_DebugDriver::EControlGetList\n");
1.683 + err = GetList((TListInformation*)a1);
1.684 + break;
1.685 + }
1.686 + case RRM_DebugDriver::EControlStep:
1.687 + {
1.688 + LOG_MSG("RRM_DebugDriver::EControlStep\n");
1.689 +
1.690 + err = Step((TUint32)a1,(TUint32)a2);
1.691 + break;
1.692 + }
1.693 + case RRM_DebugDriver::EControlKillProcess:
1.694 + {
1.695 + LOG_MSG("RRM_DebugDriver::EControlKillProcess\n");
1.696 +
1.697 + err = KillProcess((TUint32)a1,(TUint32)a2);
1.698 + break;
1.699 + }
1.700 + default:
1.701 + {
1.702 + err = KErrGeneral;
1.703 + }
1.704 + }
1.705 +
1.706 + if (KErrNone != err)
1.707 + {
1.708 + LOG_MSG2("Error %d from control function", err);
1.709 + }
1.710 +
1.711 + if (threadObj)
1.712 + {
1.713 + // Close the thread handle which has been opened by DebugUtils::OpenThreadHandle
1.714 + threadObj->Close(NULL);
1.715 + }
1.716 +
1.717 + return err;
1.718 +}
1.719 +
1.720 +void DRM_DebugChannel::HandleMsg(TMessageBase* aMsg)
1.721 +{
1.722 + LOG_MSG("DRM_DebugChannel::HandleMsg()");
1.723 +
1.724 + TThreadMessage& m = *(TThreadMessage*)aMsg;
1.725 + TInt id = m.iValue;
1.726 +
1.727 + if (id == (TInt)ECloseMsg)
1.728 + {
1.729 + if (iEventHandler)
1.730 + {
1.731 + iEventHandler->Stop();
1.732 + iEventHandler->Close();
1.733 + iEventHandler = NULL;
1.734 + }
1.735 + m.Complete(KErrNone, EFalse);
1.736 + return;
1.737 + }
1.738 +
1.739 + if (id == KMaxTInt)
1.740 + {
1.741 + // DoCancel
1.742 + DoCancel(m.Int0());
1.743 + m.Complete(KErrNone, ETrue);
1.744 + return;
1.745 + }
1.746 +
1.747 + if (id < 0)
1.748 + {
1.749 + // DoRequest
1.750 + TRequestStatus* pStatus = (TRequestStatus*)m.Ptr0();
1.751 + DoRequest(~id, pStatus, m.Ptr1(), m.Ptr2());
1.752 + m.Complete(KErrNone, ETrue);
1.753 + }
1.754 + else
1.755 + {
1.756 + // DoControl
1.757 + TInt err = DoControl(id, m.Ptr0(), m.Ptr1());
1.758 + m.Complete(err, ETrue);
1.759 + }
1.760 +}
1.761 +
1.762 +//
1.763 +// DRM_DebugChannel::RemoveProcess
1.764 +//
1.765 +TBool DRM_DebugChannel::RemoveProcess(TAny* a1, TAny* a2)
1.766 + {
1.767 + LOG_EVENT_MSG("DRM_DebugChannel::RemoveProcess()");
1.768 +
1.769 + DProcess *aProcess = (DProcess*)a1;
1.770 +
1.771 + // Sanity check
1.772 + if (!aProcess)
1.773 + {
1.774 + // No process was specified!
1.775 + LOG_MSG("DRM_DebugChannel::RemoveProcess was called with an invalid process ID");
1.776 + return EFalse;
1.777 + }
1.778 +
1.779 + // this is called when a process dies. we want to mark any breakpoints in this
1.780 + // process space as obsolete. the main reason for this is so we don't return
1.781 + // an error when the host debugger tries to clear breakpoints for the process
1.782 +
1.783 + TUint32 codeAddress = 0;
1.784 + TUint32 codeSize = 0;
1.785 +
1.786 + LOG_EVENT_MSG2("Process being removed, Name %S", aProcess->iName);
1.787 +
1.788 + DCodeSeg* codeSeg = aProcess->iCodeSeg;
1.789 +
1.790 + if (codeSeg)
1.791 + {
1.792 + TModuleMemoryInfo processMemoryInfo;
1.793 + TInt err = codeSeg->GetMemoryInfo(processMemoryInfo, aProcess);
1.794 + if (err != KErrNone)
1.795 + {
1.796 + codeAddress = processMemoryInfo.iCodeBase;
1.797 + codeSize = processMemoryInfo.iCodeSize;
1.798 + }
1.799 + else
1.800 + {
1.801 + LOG_MSG2("Error in getting memory info: %d", err);
1.802 + }
1.803 +
1.804 + }
1.805 +
1.806 + if (!codeAddress || !codeSize)
1.807 + {
1.808 + LOG_EVENT_MSG2("Code segment not available for process %d", aProcess->iId);
1.809 + // make sure there is not already a breakpoint at this address
1.810 + for (TInt i = 0; i < iDebugProcessList.Count(); i++)
1.811 + {
1.812 + if (iDebugProcessList[i].iId == aProcess->iId)
1.813 + {
1.814 + codeAddress = iDebugProcessList[i].iCodeAddress;
1.815 + codeSize = iDebugProcessList[i].iCodeSize;
1.816 +
1.817 + //now remove from the list
1.818 + iDebugProcessList.Remove(i);
1.819 + break;
1.820 + }
1.821 + }
1.822 + }
1.823 +
1.824 + if (!codeAddress || !codeSize)
1.825 + {
1.826 + return EFalse;
1.827 + }
1.828 +
1.829 + iBreakManager->RemoveBreaksForProcess(aProcess->iId, codeAddress, codeSize);
1.830 + return EFalse;
1.831 + }
1.832 +
1.833 +//
1.834 +// DRM_DebugChannel::StartThread
1.835 +//
1.836 +TBool DRM_DebugChannel::StartThread(TAny* a1, TAny* a2)
1.837 +{
1.838 + LOG_EVENT_MSG("DRM_DebugChannel::StartThread()");
1.839 +
1.840 + DThread *aThread = (DThread*)a1;
1.841 + if(!aThread)
1.842 + {
1.843 + LOG_MSG("Error getting DThread object");
1.844 + __NK_ASSERT_DEBUG(aThread);
1.845 + return EFalse;
1.846 + }
1.847 +
1.848 + //a2 points to the thread creating the new thread.
1.849 + //We have no use for it at the moment so just ignore it for now
1.850 +
1.851 + TDriverEventInfo info;
1.852 + info.iEventType = EEventsStartThread;
1.853 + info.iThreadId = aThread->iId;
1.854 + info.iThreadIdValid = ETrue;
1.855 + DProcess* owningProcess = aThread->iOwningProcess;
1.856 + if(owningProcess)
1.857 + {
1.858 + info.iProcessId = owningProcess->iId;
1.859 + info.iProcessIdValid = ETrue;
1.860 + DCodeSeg* p = owningProcess->iCodeSeg;
1.861 + if(p && p->iFileName)
1.862 + {
1.863 + info.iFileName.Copy(*(p->iFileName));
1.864 + DTargetProcess* foundProcess = TheDProcessTracker.FindProcess(*(p->iFileName));
1.865 + if(foundProcess)
1.866 + {
1.867 + foundProcess->NotifyEvent(info);
1.868 + }
1.869 + else
1.870 + {
1.871 + LOG_EVENT_MSG2("Couldn't find process with name [%S]", p->iFileName);
1.872 + }
1.873 + }
1.874 + else
1.875 + {
1.876 + if(p)
1.877 + {
1.878 + LOG_EVENT_MSG("\tCode segment name missing");
1.879 + }
1.880 + else
1.881 + {
1.882 + LOG_EVENT_MSG("\tCode segment is NULL");
1.883 + }
1.884 + }
1.885 + }
1.886 + return EFalse;
1.887 +}
1.888 +
1.889 +//
1.890 +// DRM_DebugChannel::HandleAddProcessEvent
1.891 +//
1.892 +TBool DRM_DebugChannel::HandleAddProcessEvent(TAny* a1, TAny* a2)
1.893 +{
1.894 + LOG_EVENT_MSG("DRM_DebugChannel::AddProcess()");
1.895 +
1.896 + DProcess *aProcess = (DProcess*)a1;
1.897 + // a2 points to the thread creating the new process.
1.898 + DThread *aThread = (DThread*)a2;
1.899 +
1.900 + if(!aProcess)
1.901 + {
1.902 + LOG_MSG("Error getting DProcess object");
1.903 + __NK_ASSERT_DEBUG(aProcess);
1.904 + return EFalse;
1.905 + }
1.906 +
1.907 + TDriverEventInfo info;
1.908 + info.iEventType = EEventsAddProcess;
1.909 + info.iProcessId = aProcess->iId;
1.910 +
1.911 + info.iCreatorThreadId = aThread ? aThread->iId : 0;
1.912 + info.iProcessIdValid = ETrue;
1.913 +
1.914 + // Copy TUids
1.915 + info.iUids = aProcess->iUids;
1.916 +
1.917 + info.iUidsValid = ETrue;
1.918 +
1.919 + // copy name of the process
1.920 + if (aProcess->iName)
1.921 + {
1.922 + // copy the name of the process
1.923 + info.iFileName.Copy(*aProcess->iName);
1.924 +
1.925 + DTargetProcess* foundProcess = TheDProcessTracker.FindProcess(*(aProcess->iName));
1.926 + if(foundProcess)
1.927 + {
1.928 + foundProcess->NotifyEvent(info);
1.929 + }
1.930 + else
1.931 + {
1.932 + // AddProcess event does not have fully-qualified path, it has "filename.exe"
1.933 + // So we try a less-precise match
1.934 + DTargetProcess* foundProcess = TheDProcessTracker.FuzzyFindProcess(*(aProcess->iName));
1.935 + if(foundProcess)
1.936 + {
1.937 + foundProcess->NotifyEvent(info);
1.938 + }
1.939 + else
1.940 + {
1.941 + LOG_EVENT_MSG2("Couldn't find process with name [%S]", aProcess->iName);
1.942 + }
1.943 + }
1.944 + }
1.945 + else
1.946 + {
1.947 + LOG_EVENT_MSG("DRM_DebugChannel::AddProcess - No iName for this process");
1.948 + }
1.949 +
1.950 + return EFalse;
1.951 +}
1.952 +
1.953 +//
1.954 +// DRM_DebugChannel::HandleRemoveProcessEvent
1.955 +//
1.956 +TBool DRM_DebugChannel::HandleRemoveProcessEvent(TAny* a1, TAny* a2)
1.957 +{
1.958 + LOG_EVENT_MSG("DRM_DebugChannel::RemoveProcess()");
1.959 +
1.960 + DProcess *aProcess = (DProcess*)a1;
1.961 + if(!aProcess)
1.962 + {
1.963 + LOG_MSG("Error getting DProcess object");
1.964 + __NK_ASSERT_DEBUG(aProcess);
1.965 + return EFalse;
1.966 + }
1.967 +
1.968 + // a2 points to the thread creating the new process.
1.969 + // We have no use for it at the moment so just ignore it for now
1.970 + // Also, it may not be known and therefore NULL
1.971 +
1.972 + TDriverEventInfo info;
1.973 + info.iEventType = EEventsRemoveProcess;
1.974 + info.iProcessId = aProcess->iId;
1.975 + info.iProcessIdValid = ETrue;
1.976 +
1.977 + // copy name of the process
1.978 + if (aProcess->iName)
1.979 + {
1.980 + // copy the name of the process
1.981 + info.iFileName.Copy(*aProcess->iName);
1.982 +
1.983 + DTargetProcess* foundProcess = TheDProcessTracker.FindProcess(*(aProcess->iName));
1.984 + if(foundProcess)
1.985 + {
1.986 + foundProcess->NotifyEvent(info);
1.987 + }
1.988 + else
1.989 + {
1.990 + // RemoveProcess event does not have fully-qualified path, it has "filename.exe"
1.991 + // So we try a less-precise match
1.992 + DTargetProcess* foundProcess = TheDProcessTracker.FuzzyFindProcess(*(aProcess->iName));
1.993 + if(foundProcess)
1.994 + {
1.995 + foundProcess->NotifyEvent(info);
1.996 + }
1.997 + else
1.998 + {
1.999 + LOG_EVENT_MSG2("Couldn't find process with name [%S]", aProcess->iName);
1.1000 + }
1.1001 + }
1.1002 +
1.1003 + }
1.1004 + else
1.1005 + {
1.1006 + LOG_EVENT_MSG("DRM_DebugChannel::AddProcess - No iName for this process");
1.1007 + }
1.1008 +
1.1009 + return EFalse;
1.1010 +}
1.1011 +
1.1012 +//
1.1013 +// DRM_DebugChannel::AddLibrary
1.1014 +//
1.1015 +TBool DRM_DebugChannel::AddLibrary(TAny* a1, TAny* a2)
1.1016 +{
1.1017 + LOG_EVENT_MSG("DRM_DebugChannel::AddLibrary()");
1.1018 +
1.1019 + DLibrary *aLibrary = (DLibrary*)a1;
1.1020 + DThread *aThread = (DThread*)a2;
1.1021 +
1.1022 + // sanity check
1.1023 + if (!aLibrary)
1.1024 + {
1.1025 + LOG_EVENT_MSG("DRM_DebugChannel::AddLibrary called with no library specified");
1.1026 + return EFalse;
1.1027 + }
1.1028 +
1.1029 + if (!aThread)
1.1030 + {
1.1031 + LOG_EVENT_MSG("DRM_DebugChannel::AddLibrary called with no thread specified");
1.1032 + return EFalse;
1.1033 + }
1.1034 +
1.1035 + LOG_EVENT_MSG2(("Lib loaded: %S"), aLibrary->iName);
1.1036 +
1.1037 + if (aThread)
1.1038 + {
1.1039 + // make sure this is not the debugger thread
1.1040 + if ((aThread != iClientThread) && (aThread->iOwningProcess->iId != iClientThread->iOwningProcess->iId))
1.1041 + {
1.1042 + TDriverEventInfo info;
1.1043 +
1.1044 + info.iEventType = EEventsAddLibrary;
1.1045 + info.iProcessId = aThread->iOwningProcess->iId;
1.1046 + info.iProcessIdValid = ETrue;
1.1047 + info.iThreadId = aThread->iId;
1.1048 + info.iThreadIdValid = ETrue;
1.1049 +
1.1050 + //get the code address
1.1051 + DCodeSeg* codeSeg = aLibrary->iCodeSeg;
1.1052 + if (!codeSeg)
1.1053 + {
1.1054 + LOG_EVENT_MSG2("Code segment not available for library %S", aLibrary->iName);
1.1055 + return EFalse;
1.1056 + }
1.1057 +
1.1058 + // Uid3
1.1059 + info.iUids = codeSeg->iUids;
1.1060 + info.iUidsValid = ETrue;
1.1061 +
1.1062 + TModuleMemoryInfo memoryInfo;
1.1063 + TInt err = codeSeg->GetMemoryInfo(memoryInfo, NULL); //NULL for DProcess should be ok;
1.1064 + if (err != KErrNone)
1.1065 + {
1.1066 + LOG_EVENT_MSG2("Error in getting memory info: %d", err);
1.1067 + return EFalse;
1.1068 + }
1.1069 +
1.1070 + info.iCodeAddress = memoryInfo.iCodeBase;
1.1071 + info.iDataAddress = memoryInfo.iInitialisedDataBase;
1.1072 +
1.1073 + info.iFileName.Copy(*(aLibrary->iName)); //just the name, without uid info.
1.1074 +
1.1075 + //queue up or complete the event
1.1076 + info.iArg1 = a1;
1.1077 + info.iArg2 = a2;
1.1078 + NotifyEvent(info);
1.1079 + }
1.1080 +
1.1081 + }
1.1082 + return EFalse;
1.1083 +}
1.1084 +
1.1085 +//
1.1086 +// DRM_DebugChannel::RemoveLibrary
1.1087 +//
1.1088 +TBool DRM_DebugChannel::RemoveLibrary(TAny* a1, TAny* a2)
1.1089 + {
1.1090 + LOG_EVENT_MSG("DRM_DebugChannel::RemoveLibrary()");
1.1091 + DLibrary *aLibrary = (DLibrary*)a1;
1.1092 +
1.1093 + // sanity check
1.1094 + if (!aLibrary)
1.1095 + {
1.1096 + LOG_EVENT_MSG("DRM_DebugChannel::RemoveLibrary called with no library specified");
1.1097 + return EFalse;
1.1098 + }
1.1099 +
1.1100 + LOG_EVENT_MSG2(("Lib unloaded: %S"), aLibrary->iName);
1.1101 +
1.1102 + // this is called when all handles to this library have been closed. this can happen when a process dies, or when a dll is
1.1103 + // unloaded while the process lives on. in former case, we don't need to notify the host debugger because that process is
1.1104 + // dying anyway. for the latter case, we do need to notify the host so it can unload the symbolics, etc.
1.1105 +
1.1106 + DThread* aThread = &Kern::CurrentThread();
1.1107 +
1.1108 + if ((aThread) &&
1.1109 + (aThread != iClientThread) &&
1.1110 + (aThread->iOwningProcess->iId != iClientThread->iOwningProcess->iId))
1.1111 + {
1.1112 + //the library gets unloaded only when the mapcount is 0.
1.1113 + if (aLibrary->iMapCount != 0)
1.1114 + return EFalse;
1.1115 +
1.1116 + DCodeSeg* codeSeg = aLibrary->iCodeSeg;
1.1117 + if (!codeSeg)
1.1118 + {
1.1119 + LOG_EVENT_MSG2("Code segment not available for library %S", aLibrary->iName);
1.1120 + return EFalse;
1.1121 + }
1.1122 +
1.1123 + TModuleMemoryInfo processMemoryInfo;
1.1124 + TInt err = codeSeg->GetMemoryInfo(processMemoryInfo, NULL); //passing NULL for the DProcess argument should be ok;
1.1125 + if (err != KErrNone)
1.1126 + {
1.1127 + LOG_EVENT_MSG2("Error in getting memory info: %d", err);
1.1128 + return EFalse;
1.1129 + }
1.1130 +
1.1131 + TUint32 codeAddress = processMemoryInfo.iCodeBase;
1.1132 + TUint32 codeSize = processMemoryInfo.iCodeSize;
1.1133 +
1.1134 + // first invalidate all breakpoints that were set in the library code
1.1135 + iBreakManager->InvalidateLibraryBreakPoints(codeAddress, codeSize);
1.1136 + DProcess *process = &Kern::CurrentProcess();
1.1137 + RArray<SCodeSegEntry>* dynamicCode = &(process->iDynamicCode);
1.1138 +
1.1139 + for (TInt j=0; j<dynamicCode->Count(); j++)
1.1140 + {
1.1141 + if ((*dynamicCode)[j].iLib == aLibrary)
1.1142 + {
1.1143 + TDriverEventInfo info;
1.1144 +
1.1145 + info.iEventType = EEventsRemoveLibrary;
1.1146 + info.iFileName.Copy(*(aLibrary->iName)); //lib name without uid info
1.1147 + //info.iFileName.ZeroTerminate();
1.1148 + info.iProcessId = process->iId;
1.1149 + info.iProcessIdValid = ETrue;
1.1150 + info.iThreadId = 0xFFFFFFFF; // don't care!
1.1151 + info.iThreadIdValid = EFalse;
1.1152 + // Uid3
1.1153 + info.iUids = codeSeg->iUids;
1.1154 + info.iUidsValid = ETrue;
1.1155 +
1.1156 + //queue up or complete the event
1.1157 + info.iArg1 = a1;
1.1158 + info.iArg2 = a2;
1.1159 + NotifyEvent(info);
1.1160 + }
1.1161 + }
1.1162 + }
1.1163 + return EFalse;
1.1164 + }
1.1165 +
1.1166 +//
1.1167 +// DRM_DebugChannel::HandleEventKillThread
1.1168 +//
1.1169 +TBool DRM_DebugChannel::HandleEventKillThread(TAny* a1, TAny* a2)
1.1170 +{
1.1171 + LOG_EVENT_MSG("DRM_DebugChannel::HandleEventKillThread");
1.1172 +
1.1173 + DThread* currentThread = &Kern::CurrentThread();
1.1174 + if (!currentThread)
1.1175 + {
1.1176 + LOG_MSG("Error getting current thread");
1.1177 + __NK_ASSERT_DEBUG(currentThread);
1.1178 + return EFalse;
1.1179 + }
1.1180 +
1.1181 + // a1 should point to the current thread, check this to make sure it does
1.1182 + __NK_ASSERT_DEBUG((DThread*)a1 == currentThread);
1.1183 +
1.1184 + TDriverEventInfo info;
1.1185 +
1.1186 + info.iProcessId = currentThread->iOwningProcess->iId;
1.1187 + info.iProcessIdValid = ETrue;
1.1188 + info.iThreadId = currentThread->iId;
1.1189 + info.iThreadIdValid = ETrue;
1.1190 + // 14 should probably be replaced by PC_REGISTER, for some reason PC_REGISTER had been replaced with 14 in the code
1.1191 + TInt err = ReadKernelRegisterValue(currentThread, 14, info.iCurrentPC);
1.1192 + if(err != KErrNone)
1.1193 + {
1.1194 + LOG_EVENT_MSG2("DRM_DebugChannel::HandleEventKillThread - Non-zero error code discarded: %d", err);
1.1195 + }
1.1196 +
1.1197 + if (currentThread->iExitType == EExitPanic)
1.1198 + {
1.1199 + info.iPanicCategory.Copy(currentThread->iExitCategory);
1.1200 + }
1.1201 + info.iExceptionNumber = currentThread->iExitReason;
1.1202 + info.iExitType = currentThread->iExitType;
1.1203 + info.iEventType = EEventsKillThread;
1.1204 +
1.1205 + // Are we debugging this process - decide based on iFileName
1.1206 + DCodeSeg* codeSeg = currentThread->iOwningProcess->iCodeSeg;
1.1207 +
1.1208 + // remove all the breakpoints in this thread, whether we are debugging it or not.
1.1209 + iBreakManager->DoRemoveThreadBreaks(info.iThreadId);
1.1210 +
1.1211 + // if the code seg exists then get the file name from it and check we're debugging it
1.1212 + if(codeSeg)
1.1213 + {
1.1214 + DTargetProcess* foundProcess = TheDProcessTracker.FindProcess(*(codeSeg->iFileName));
1.1215 + if(!foundProcess)
1.1216 + {
1.1217 + // not debugging this process so return false
1.1218 + return EFalse;
1.1219 + }
1.1220 + }
1.1221 + else
1.1222 + {
1.1223 + // can't validate that we are debugging the thread
1.1224 + return EFalse;
1.1225 + }
1.1226 +
1.1227 + info.iArg1 = a1;
1.1228 + info.iArg2 = a2;
1.1229 + NotifyEvent(info);
1.1230 +
1.1231 + return ETrue;
1.1232 +}
1.1233 +
1.1234 +//
1.1235 +// DRM_DebugChannel::HandleSwException
1.1236 +//
1.1237 +TBool DRM_DebugChannel::HandleSwException(TAny* a1, TAny* a2)
1.1238 +{
1.1239 + LOG_EVENT_MSG("DRM_DebugChannel::HandleSwException");
1.1240 + TExcType aExcType = (TExcType)(TInt)a1;
1.1241 +
1.1242 + TDriverEventInfo info;
1.1243 +
1.1244 + DThread* currentThread = &Kern::CurrentThread();
1.1245 + if (!currentThread)
1.1246 + {
1.1247 + LOG_MSG("Error getting current thread");
1.1248 + __NK_ASSERT_DEBUG(currentThread);
1.1249 + return EFalse;
1.1250 + }
1.1251 +
1.1252 + info.iProcessId = currentThread->iOwningProcess->iId;
1.1253 + info.iProcessIdValid = ETrue;
1.1254 + info.iThreadId = currentThread->iId;
1.1255 + info.iThreadIdValid = ETrue;
1.1256 + TInt err = ReadKernelRegisterValue(currentThread, PC_REGISTER, info.iCurrentPC);
1.1257 + if(err != KErrNone)
1.1258 + {
1.1259 + LOG_EVENT_MSG2("DRM_DebugChannel::HandleSwException - Non-zero error code discarded: %d", err);
1.1260 + }
1.1261 + info.iExceptionNumber = aExcType;
1.1262 + info.iEventType = EEventsSwExc;
1.1263 + info.iArg1 = a1;
1.1264 + info.iArg2 = a2;
1.1265 +
1.1266 + NotifyEvent(info);
1.1267 +
1.1268 + return EFalse;
1.1269 +}
1.1270 +
1.1271 +//
1.1272 +// DRM_DebugChannel::HandleHwException
1.1273 +//
1.1274 +TBool DRM_DebugChannel::HandleHwException(TAny* a1, TAny* a2)
1.1275 +{
1.1276 + LOG_EVENT_MSG("DRM_DebugChannel::HandleHwException()");
1.1277 + TArmExcInfo* aExcInfo = (TArmExcInfo*)a1;
1.1278 +
1.1279 + // sanity check
1.1280 + if (!aExcInfo)
1.1281 + {
1.1282 + LOG_MSG("DRM_DebugChannel::HandleHwException called with no aExcInfo");
1.1283 + __NK_ASSERT_DEBUG(aExcInfo);
1.1284 + return EFalse;
1.1285 + }
1.1286 +
1.1287 + TDriverEventInfo info;
1.1288 +
1.1289 + DThread* currentThread = &Kern::CurrentThread();
1.1290 + LOG_EVENT_MSG2("DRM_DebugChannel::HandleHwException current thread = 0x%x", currentThread);
1.1291 +
1.1292 + if (!currentThread)
1.1293 + {
1.1294 + LOG_MSG("Error getting current thread");
1.1295 + __NK_ASSERT_DEBUG(currentThread);
1.1296 + return EFalse;
1.1297 + }
1.1298 +
1.1299 + info.iProcessId = currentThread->iOwningProcess->iId;
1.1300 + info.iProcessIdValid = ETrue;
1.1301 + info.iThreadId = currentThread->iId;
1.1302 + info.iThreadIdValid = ETrue;
1.1303 + info.iRmdArmExcInfo.iFaultAddress= aExcInfo->iFaultAddress;
1.1304 + info.iRmdArmExcInfo.iFaultStatus= aExcInfo->iFaultStatus;
1.1305 + LOG_EVENT_MSG3("DRM_DebugChannel::HandleHwException iFaultAddress=0x%x, iFaultStatus=0x%x",
1.1306 + aExcInfo->iFaultAddress, aExcInfo->iFaultStatus);
1.1307 +
1.1308 + info.iRmdArmExcInfo.iR0= aExcInfo->iR0;
1.1309 + info.iRmdArmExcInfo.iR1= aExcInfo->iR1;
1.1310 + info.iRmdArmExcInfo.iR2= aExcInfo->iR2;
1.1311 + info.iRmdArmExcInfo.iR3= aExcInfo->iR3;
1.1312 +
1.1313 + info.iRmdArmExcInfo.iR4= aExcInfo->iR4;
1.1314 + info.iRmdArmExcInfo.iR5= aExcInfo->iR5;
1.1315 + info.iRmdArmExcInfo.iR6= aExcInfo->iR6;
1.1316 + info.iRmdArmExcInfo.iR7= aExcInfo->iR7;
1.1317 + info.iRmdArmExcInfo.iR8= aExcInfo->iR8;
1.1318 + info.iRmdArmExcInfo.iR9= aExcInfo->iR9;
1.1319 + info.iRmdArmExcInfo.iR10= aExcInfo->iR10;
1.1320 + info.iRmdArmExcInfo.iR11= aExcInfo->iR11;
1.1321 + info.iRmdArmExcInfo.iR12= aExcInfo->iR12;
1.1322 +
1.1323 + info.iRmdArmExcInfo.iR13= aExcInfo->iR13;
1.1324 + info.iRmdArmExcInfo.iR14= aExcInfo->iR14;
1.1325 + info.iRmdArmExcInfo.iR15= aExcInfo->iR15;
1.1326 + LOG_EVENT_MSG5(" R12=0x%x, R13=0x%x, R14=0x%x, R15=0x%x ",
1.1327 + aExcInfo->iR12, aExcInfo->iR13, aExcInfo->iR14, aExcInfo->iR15);
1.1328 +
1.1329 + info.iRmdArmExcInfo.iCpsr= aExcInfo->iCpsr;
1.1330 + info.iRmdArmExcInfo.iR13Svc= aExcInfo->iR13Svc;
1.1331 + info.iRmdArmExcInfo.iR14Svc= aExcInfo->iR14Svc;
1.1332 + info.iRmdArmExcInfo.iSpsrSvc= aExcInfo->iSpsrSvc;
1.1333 + LOG_EVENT_MSG5(" iCpsr=0x%x, iR13Svc=0x%x, iR14Svc=0x%x, iSpsrSvc=0x%x ",
1.1334 + aExcInfo->iCpsr, aExcInfo->iR13Svc, aExcInfo->iR14Svc, aExcInfo->iSpsrSvc);
1.1335 +
1.1336 + switch (aExcInfo->iExcCode)
1.1337 + {
1.1338 + case 0:
1.1339 + info.iExceptionNumber = EExcCodeAbort;
1.1340 + LOG_EVENT_MSG(" iExcCode == 0 => EExcCodeAbort");
1.1341 + break;
1.1342 + case 1:
1.1343 + info.iExceptionNumber = EExcDataAbort;
1.1344 + LOG_EVENT_MSG(" iExcCode == 1 => EExcDataAbort");
1.1345 + break;
1.1346 + case 2:
1.1347 + info.iExceptionNumber = EExcInvalidOpCode;
1.1348 + LOG_EVENT_MSG(" iExcCode == 2 => EExcInvalidOpCode");
1.1349 + break;
1.1350 + default:
1.1351 + // new event? Something gone wrong?
1.1352 + __NK_ASSERT_DEBUG(EFalse);
1.1353 + return EFalse;
1.1354 +
1.1355 + }
1.1356 + info.iEventType = EEventsHwExc;
1.1357 +
1.1358 + info.iArg1 = a1;
1.1359 + info.iArg2 = a2;
1.1360 +
1.1361 + if(EExcInvalidOpCode == info.iExceptionNumber)
1.1362 + {
1.1363 + return HandleInvalidOpCodeException(info, currentThread);
1.1364 + }
1.1365 +
1.1366 + NotifyEvent(info);
1.1367 + return EFalse;
1.1368 +}
1.1369 +
1.1370 +//
1.1371 +// DRM_DebugChannel::HandUserTrace
1.1372 +//
1.1373 +TBool DRM_DebugChannel::HandleUserTrace(TAny* a1, TAny* a2)
1.1374 +{
1.1375 + LOG_EVENT_MSG("DRM_DebugChannel::HandleUserTrace()");
1.1376 +
1.1377 + DThread* currentThread = &Kern::CurrentThread();
1.1378 + if (!currentThread)
1.1379 + {
1.1380 + LOG_EVENT_MSG("Error getting current thread");
1.1381 + __NK_ASSERT_DEBUG(currentThread);
1.1382 + return EFalse;
1.1383 + }
1.1384 +
1.1385 + TDriverEventInfo info;
1.1386 + info.iProcessId = currentThread->iOwningProcess->iId;
1.1387 + info.iProcessIdValid = ETrue;
1.1388 + info.iThreadId = currentThread->iId;
1.1389 + info.iThreadIdValid = ETrue;
1.1390 + info.iEventType = EEventsUserTrace;
1.1391 + info.iArg1 = a1;
1.1392 + info.iArg2 = a2;
1.1393 +
1.1394 + TInt err = KErrNone;
1.1395 +
1.1396 + //User Trace info
1.1397 + XTRAP(err, XT_DEFAULT, kumemget(info.iUserTraceText, info.iArg1, (TInt)a2));
1.1398 + if(KErrNone != err)
1.1399 + {
1.1400 + return EFalse;
1.1401 + }
1.1402 +
1.1403 + info.iMessageStatus = ESingleMessage;
1.1404 +
1.1405 + NotifyEvent(info);
1.1406 +
1.1407 + return EFalse;
1.1408 +}
1.1409 +
1.1410 +//
1.1411 +// DRM_DebugChannel::HandleException
1.1412 +//
1.1413 +TBool DRM_DebugChannel::HandleInvalidOpCodeException(TDriverEventInfo& aEventInfo, DThread* aCurrentThread)
1.1414 +{
1.1415 + LOG_EVENT_MSG("DRM_DebugChannel::HandleInvalidOpCodeException()");
1.1416 +
1.1417 + TInt err = KErrNone;
1.1418 +
1.1419 + TUint32 inst = KArmBreakPoint;
1.1420 + TInt instSize = 4;
1.1421 +
1.1422 + // change these for thumb mode
1.1423 + TUint32 regValue;
1.1424 + err = ReadKernelRegisterValue(aCurrentThread, STATUS_REGISTER, regValue);
1.1425 + if(err != KErrNone)
1.1426 + {
1.1427 + LOG_EVENT_MSG2("DRM_DebugChannel::HandleInvalidOpCodeException - Non-zero error code discarded: %d", err);
1.1428 + }
1.1429 + if (regValue & ECpuThumb)
1.1430 + {
1.1431 + inst = KThumbBreakPoint;
1.1432 + instSize = 2;
1.1433 + }
1.1434 +
1.1435 + TUint32 instruction = 0;
1.1436 + err = Kern::ThreadRawRead(aCurrentThread, (TUint32 *)aEventInfo.iRmdArmExcInfo.iR15, (TUint8 *)&instruction, instSize);
1.1437 +
1.1438 + if (KErrNone != err)
1.1439 + LOG_EVENT_MSG2("Error reading instruction at currentpc: %d", err);
1.1440 +
1.1441 + if (!memcompare((TUint8 *)&inst, instSize, (TUint8 *)&instruction, instSize))
1.1442 + {
1.1443 + TInt err = DoSuspendThread(aCurrentThread);
1.1444 + if(! ((KErrNone == err) || (KErrAlreadyExists == err)) )
1.1445 + {
1.1446 + LOG_EVENT_MSG2("DRM_DebugChannel::HandleInvalidOpCodeException() Thread with id 0x%08x could not be suspended.", aCurrentThread->iId);
1.1447 + return EFalse;
1.1448 + }
1.1449 +
1.1450 + // the exception was a breakpoint instruction. see if we have a breakpoint at that address
1.1451 + TBreakEntry* breakEntry = NULL;
1.1452 + do
1.1453 + {
1.1454 + breakEntry = iBreakManager->GetNextBreak(breakEntry);
1.1455 + if (breakEntry && ((breakEntry->iThreadSpecific && breakEntry->iId == aEventInfo.iThreadId) || (!breakEntry->iThreadSpecific && breakEntry->iId == aEventInfo.iProcessId)) && breakEntry->iAddress == aEventInfo.iRmdArmExcInfo.iR15)
1.1456 + {
1.1457 + LOG_EVENT_MSG2("Breakpoint with Id %d has been hit", breakEntry->iBreakId);
1.1458 +
1.1459 + TBreakEntry tempBreakEntry = *breakEntry;
1.1460 +
1.1461 + //change the event type to breakpoint type
1.1462 + aEventInfo.iEventType = breakEntry->iThreadSpecific ? EEventsBreakPoint : EEventsProcessBreakPoint;
1.1463 +
1.1464 + // enable any breakpoints we had to disable for this thread
1.1465 + err = iBreakManager->DoEnableDisabledBreak(aEventInfo.iThreadId);
1.1466 + if (KErrNone != err)
1.1467 + LOG_MSG2("Error %d enabling disabled breakpoints", err);
1.1468 +
1.1469 + // see if this is a temp breakpoint
1.1470 + if (iBreakManager->IsTemporaryBreak(*breakEntry))
1.1471 + {
1.1472 + // this was a temp breakpoint, so we need to clear it now
1.1473 + err = iBreakManager->DoClearBreak(breakEntry->iBreakId);
1.1474 + if (KErrNone != err)
1.1475 + LOG_MSG2("Error %d clearing temp breakpoint", err);
1.1476 +
1.1477 + // Find out how many steps remain to be done
1.1478 +
1.1479 + // reduce the number of steps to complete by 1
1.1480 + tempBreakEntry.iNumSteps--;
1.1481 +
1.1482 + LOG_EVENT_MSG2("There are %d steps remaining\n", tempBreakEntry.iNumSteps);
1.1483 +
1.1484 + // New. If we have not finished do all the steps, continue stepping and don't notify event
1.1485 + if (tempBreakEntry.iNumSteps)
1.1486 + {
1.1487 + LOG_EVENT_MSG("Continuing stepping...not telling the agent yet\n");
1.1488 + err = DoStepRange(aCurrentThread, aEventInfo.iRmdArmExcInfo.iR15, aEventInfo.iRmdArmExcInfo.iR15, ETrue, tempBreakEntry.iResumeOnceOutOfRange /*EFalse*/, tempBreakEntry.iNumSteps, ETrue);
1.1489 + if (err != KErrNone)
1.1490 + {
1.1491 + LOG_EVENT_MSG("Failed to continue stepping\n");
1.1492 +
1.1493 + // what do we do? might as well stop here and tell the user
1.1494 + NotifyEvent(aEventInfo);
1.1495 +
1.1496 + return ETrue;
1.1497 + }
1.1498 +
1.1499 + // continue as though no event occured. No need to suspend/resume anything...
1.1500 + LOG_EVENT_MSG("Continuing to step\n");
1.1501 + return ETrue;
1.1502 + }
1.1503 +
1.1504 + // Is this a case where we just want to continue?
1.1505 + if (tempBreakEntry.iResumeOnceOutOfRange)
1.1506 + {
1.1507 + LOG_EVENT_MSG("PC is out of range, continuing thread");
1.1508 + DoResumeThread(aCurrentThread);
1.1509 +
1.1510 + return ETrue;
1.1511 + }
1.1512 + }
1.1513 +
1.1514 + // if the breakpoint is thread specific, make sure it's the right thread
1.1515 + // if not, just continue the thread. take special care if it's the debugger
1.1516 + // thread. if it hits a regular breakpoint, we NEVER want to stop at it. if
1.1517 + // it hits a temp breakpoint, we're probably just stepping past a real breakpoint
1.1518 + // and we do need to handle it.
1.1519 + TBool needToResume = (tempBreakEntry.iThreadSpecific && tempBreakEntry.iId != aEventInfo.iThreadId) ||
1.1520 + (!tempBreakEntry.iThreadSpecific && tempBreakEntry.iId != aEventInfo.iProcessId);
1.1521 +
1.1522 + if (needToResume)
1.1523 + {
1.1524 + LOG_EVENT_MSG("breakpoint does not match threadId, calling DoResumeThread");
1.1525 + err = DoResumeThread(aCurrentThread);
1.1526 + if (KErrNone != err)
1.1527 + LOG_EVENT_MSG2("Error in DoResumeThread: %d", err);
1.1528 +
1.1529 + return EFalse;
1.1530 + }
1.1531 +
1.1532 + //normal user break point, just notify the event
1.1533 + break;
1.1534 + }
1.1535 + } while(breakEntry);
1.1536 + }
1.1537 +
1.1538 + NotifyEvent(aEventInfo);
1.1539 +
1.1540 + return (aEventInfo.iEventType == EEventsBreakPoint) || (aEventInfo.iEventType == EEventsProcessBreakPoint);
1.1541 +}
1.1542 +
1.1543 +//
1.1544 +// DRM_DebugChannel::SetBreak
1.1545 +//
1.1546 +TInt DRM_DebugChannel::SetBreak(TSetBreakInfo* aBreakInfo)
1.1547 +{
1.1548 + LOG_MSG("DRM_DebugChannel::SetBreak()");
1.1549 +
1.1550 + TInt err = KErrNone;
1.1551 +
1.1552 + if (!aBreakInfo)
1.1553 + {
1.1554 + LOG_MSG("DRM_DebugChannel::SetBreak() was passed a NULL argument");
1.1555 + return KErrArgument;
1.1556 + }
1.1557 +
1.1558 + //User side memory is not accessible directly
1.1559 + TSetBreakInfo info;
1.1560 + err = Kern::ThreadRawRead(iClientThread, aBreakInfo, (TUint8*)&info, sizeof(TSetBreakInfo));
1.1561 + if (err != KErrNone)
1.1562 + {
1.1563 + LOG_MSG("DRM_DebugChannel::SetBreak() was passed a bad argument");
1.1564 + return err;
1.1565 + }
1.1566 +
1.1567 + DProcess* process = NULL;
1.1568 + if(info.iThreadSpecific)
1.1569 + {
1.1570 + // if the target thread is not suspended then return KErrInUse
1.1571 + if(!TheDProcessTracker.CheckSuspended(info.iId))
1.1572 + {
1.1573 + LOG_MSG2("DRM_DebugChannel::SetBreak() Thread with id 0x%08x not suspended.", info.iId);
1.1574 + return KErrInUse;
1.1575 + }
1.1576 + DThread* thread = DebugUtils::OpenThreadHandle(info.iId);
1.1577 + if(!thread)
1.1578 + {
1.1579 + LOG_MSG2("DRM_DebugChannel::SetBreak() Thread with id 0x%08x not found", info.iId);
1.1580 + return KErrNotFound;
1.1581 + }
1.1582 + process = DebugUtils::OpenProcessHandle(thread->iOwningProcess->iId);
1.1583 + thread->Close(NULL);
1.1584 + }
1.1585 + else
1.1586 + {
1.1587 + process = DebugUtils::OpenProcessHandle(info.iId);
1.1588 + }
1.1589 + if(!process)
1.1590 + {
1.1591 + LOG_MSG2("DRM_DebugChannel::SetBreak() Process with id 0x%08x not found", process->iId);
1.1592 + return KErrNotFound;
1.1593 + }
1.1594 + TBool found = EFalse;
1.1595 + for(TInt i=0; i<iDebugProcessList.Count(); i++)
1.1596 + {
1.1597 + if(process->iId == iDebugProcessList[i].iId)
1.1598 + {
1.1599 + found = ETrue;
1.1600 + }
1.1601 + }
1.1602 + if(!found)
1.1603 + {
1.1604 + DCodeSeg* codeSeg = process->iCodeSeg;
1.1605 + if (!codeSeg)
1.1606 + {
1.1607 + LOG_MSG2("DRM_DebugChannel::SetBreak() Code seg for process with id 0x%08x not found", process->iId);
1.1608 + return KErrNotFound;
1.1609 + }
1.1610 +
1.1611 + TModuleMemoryInfo memoryInfo;
1.1612 + TInt err = codeSeg->GetMemoryInfo(memoryInfo, process);
1.1613 + if (err != KErrNone)
1.1614 + {
1.1615 + LOG_MSG2("DRM_DebugChannel::SetBreak() Error getting memory info for process with id 0x%08x", process->iId);
1.1616 + return err;
1.1617 + }
1.1618 +
1.1619 + //add this process to the list of processes that we are debugging
1.1620 + TProcessInfo processInfo(process->iId, memoryInfo.iCodeBase, memoryInfo.iCodeSize, memoryInfo.iInitialisedDataBase);
1.1621 + iDebugProcessList.Append(processInfo);
1.1622 + process->Close(NULL);
1.1623 + }
1.1624 +
1.1625 + if (!info.iBreakId) //first check if the iId address is valid
1.1626 + return KErrArgument;
1.1627 +
1.1628 + if (err == KErrNone)
1.1629 + {
1.1630 + TInt32 iBreakId;
1.1631 +
1.1632 + err = iBreakManager->DoSetBreak(iBreakId, info.iId, info.iThreadSpecific, info.iAddress, info.iMode );
1.1633 +
1.1634 + if (err == KErrNone)
1.1635 + {
1.1636 + err = Kern::ThreadRawWrite(iClientThread, (TUint8 *)info.iBreakId, &iBreakId, sizeof(TInt32), iClientThread);
1.1637 + }
1.1638 + }
1.1639 + return err;
1.1640 +}
1.1641 +
1.1642 +//
1.1643 +// DRM_DebugChannel::StepRange
1.1644 +//
1.1645 +TInt DRM_DebugChannel::StepRange(DThread* aThread, TRM_DebugStepInfo* aStepInfo)
1.1646 +{
1.1647 + LOG_MSG("DRM_DebugChannel::StepRange()");
1.1648 +
1.1649 + TInt err = KErrNone;
1.1650 +
1.1651 + if(!TheDProcessTracker.CheckSuspended(aThread))
1.1652 + {
1.1653 + LOG_MSG2("DRM_DebugChannel::StepRange() Thread with id 0x%08x not suspended.", aThread->iId);
1.1654 + return KErrInUse;
1.1655 + }
1.1656 +
1.1657 + if (!aStepInfo)
1.1658 + return KErrArgument;
1.1659 +
1.1660 + TRM_DebugStepInfo info(0, 0, 0);
1.1661 + err = Kern::ThreadRawRead(iClientThread, aStepInfo, (TUint8*)&info, sizeof(TRM_DebugStepInfo));
1.1662 +
1.1663 + if (err != KErrNone)
1.1664 + return err;
1.1665 +
1.1666 + err = DoStepRange(aThread, info.iStartAddress, info.iStopAddress, info.iStepInto, EFalse, ETrue);
1.1667 +
1.1668 + return err;
1.1669 +}
1.1670 +
1.1671 +/**
1.1672 +Read memory from a target thread and return the data to the client. If the
1.1673 +memory block has breakpoints in it then the correct values are placed in the
1.1674 +returned data
1.1675 +
1.1676 +@param aThread pointer to thread whose memory space the memory is to be read from
1.1677 +@param aMemoryInfo information about what memory to read
1.1678 +
1.1679 +@return KErrNone if memory read successfully,
1.1680 + KErrArgument if aMemoryInfo is not initialised correctly,
1.1681 + KErrNoMemory if a temporary buffer could not be allocated,
1.1682 + KErrBadHandle if aThread is invalid,
1.1683 + or another of the system wide error codes
1.1684 +*/
1.1685 +TInt DRM_DebugChannel::ReadMemory(DThread* aThread, TRM_DebugMemoryInfo* aMemoryInfo)
1.1686 +{
1.1687 + LOG_MSG("DRM_DebugChannel::ReadMemory()");
1.1688 +
1.1689 + TInt err = KErrNone;
1.1690 +
1.1691 + if (!aMemoryInfo)
1.1692 + return KErrArgument;
1.1693 +
1.1694 + TRM_DebugMemoryInfo info(0, 0, 0);
1.1695 + err = Kern::ThreadRawRead(iClientThread, aMemoryInfo, (TUint8*)&info, sizeof(TRM_DebugMemoryInfo));
1.1696 + if (err != KErrNone)
1.1697 + return err;
1.1698 +
1.1699 + if (!info.iData)
1.1700 + return KErrArgument;
1.1701 +
1.1702 + NKern::ThreadEnterCS();
1.1703 + TUint8 *data = (TUint8*)Kern::Alloc(info.iLength);
1.1704 + NKern::ThreadLeaveCS();
1.1705 + if (!data)
1.1706 + {
1.1707 + return KErrNoMemory;
1.1708 + }
1.1709 +
1.1710 + TPtr8 dataDes(data, info.iLength);
1.1711 +
1.1712 + err = DoReadMemory(aThread, info.iAddress, info.iLength, dataDes);
1.1713 + if (err == KErrNone)
1.1714 + {
1.1715 + err = Kern::ThreadDesWrite(iClientThread, info.iData, dataDes, 0, KChunkShiftBy0, iClientThread);
1.1716 + }
1.1717 +
1.1718 + NKern::ThreadEnterCS();
1.1719 + Kern::Free(data);
1.1720 + NKern::ThreadLeaveCS();
1.1721 +
1.1722 + return err;
1.1723 +}
1.1724 +
1.1725 +/**
1.1726 +Attempt to write memory to aThread's address space
1.1727 +
1.1728 +@param aThread thread to whose address space memory is to be written
1.1729 +@param aMemoryInfo memory info object representing the data to write
1.1730 +
1.1731 +@return KErrNone if memory written successfully,
1.1732 + KErrNoMemory if memory could not be allocated
1.1733 + KErrArgument if aMemoryInfo is NULL, if aMemoryInfo.iData is NULL,
1.1734 + if aMemoryInfo.iLength is greater than than the length of the passed
1.1735 + in descrptor
1.1736 + KErrBadHandle if aThread is invalid,
1.1737 + or another of the system wide error codes
1.1738 +*/
1.1739 +TInt DRM_DebugChannel::WriteMemory(DThread* aThread, TRM_DebugMemoryInfo* aMemoryInfo)
1.1740 +{
1.1741 + LOG_MSG("DRM_DebugChannel::WriteMemory()");
1.1742 +
1.1743 + TInt err = KErrNone;
1.1744 +
1.1745 + if (!aMemoryInfo)
1.1746 + return KErrArgument;
1.1747 +
1.1748 + TRM_DebugMemoryInfo info(0, 0, 0);
1.1749 + err = Kern::ThreadRawRead(iClientThread, aMemoryInfo, (TUint8*)&info, sizeof(TRM_DebugMemoryInfo));
1.1750 + if (err != KErrNone)
1.1751 + return err;
1.1752 +
1.1753 + if (!info.iData)
1.1754 + return KErrArgument;
1.1755 +
1.1756 + NKern::ThreadEnterCS();
1.1757 + TUint8 *data = (TUint8*)Kern::Alloc(info.iLength);
1.1758 + NKern::ThreadLeaveCS();
1.1759 + if (!data)
1.1760 + {
1.1761 + return KErrNoMemory;
1.1762 + }
1.1763 +
1.1764 + TPtr8 dataDes(data, info.iLength);
1.1765 +
1.1766 + err = Kern::ThreadDesRead(iClientThread, info.iData, dataDes, 0);
1.1767 + if (err == KErrNone)
1.1768 + {
1.1769 + err = DoWriteMemory(aThread, info.iAddress, info.iLength, dataDes);
1.1770 + }
1.1771 +
1.1772 + NKern::ThreadEnterCS();
1.1773 + Kern::Free(data);
1.1774 + NKern::ThreadLeaveCS();
1.1775 +
1.1776 + return err;
1.1777 +}
1.1778 +
1.1779 +//
1.1780 +// DRM_DebugChannel::ReadRegisters
1.1781 +//
1.1782 +TInt DRM_DebugChannel::ReadRegistersLegacy(DThread* aThread, TRM_DebugRegisterInfo* aRegisterInfo)
1.1783 +{
1.1784 + LOG_MSG("DRM_DebugChannel::ReadRegistersLegacy()");
1.1785 +
1.1786 + TInt err = KErrNone;
1.1787 +
1.1788 + if (!aRegisterInfo)
1.1789 + return KErrArgument;
1.1790 +
1.1791 + TRM_DebugRegisterInfo info(0, 0, 0);
1.1792 + err = Kern::ThreadRawRead(iClientThread, aRegisterInfo, (TUint8*)&info, sizeof(TRM_DebugRegisterInfo));
1.1793 + if (err != KErrNone)
1.1794 + return err;
1.1795 +
1.1796 + if (!info.iValues)
1.1797 + return KErrArgument;
1.1798 +
1.1799 + TUint length = (info.iLastRegister - info.iFirstRegister + 1) * 4;
1.1800 +
1.1801 + NKern::ThreadEnterCS();
1.1802 + TUint8 *values = (TUint8*)Kern::Alloc(length);
1.1803 + NKern::ThreadLeaveCS();
1.1804 + if (!values)
1.1805 + {
1.1806 + return KErrNoMemory;
1.1807 + }
1.1808 +
1.1809 + TPtr8 valuesDes(values, length);
1.1810 +
1.1811 + err = DoReadRegisters(aThread, info.iFirstRegister, info.iLastRegister, valuesDes);
1.1812 + if (err == KErrNone)
1.1813 + {
1.1814 + err = Kern::ThreadDesWrite(iClientThread, info.iValues, valuesDes, 0, KChunkShiftBy0, iClientThread);
1.1815 + }
1.1816 +
1.1817 + NKern::ThreadEnterCS();
1.1818 + Kern::Free(values);
1.1819 + NKern::ThreadLeaveCS();
1.1820 +
1.1821 + return err;
1.1822 +}
1.1823 +
1.1824 +/**
1.1825 +Get listing information.
1.1826 +
1.1827 +@param aListInformation pointer to a TListInformation object containing the
1.1828 + user specified listings information
1.1829 +
1.1830 +@return KErrNone on success,
1.1831 + KErrTooBig if the kernel's data is too big to fit in the passed buffer,
1.1832 + KErrArgument if aListInformation is NULL,
1.1833 + or one of the other system-wide error codes
1.1834 +*/
1.1835 +TInt DRM_DebugChannel::GetList(TListInformation* aListInformation) const
1.1836 + {
1.1837 + LOG_MSG("DRM_DebugChannel::GetList()");
1.1838 +
1.1839 + TInt err = KErrNone;
1.1840 +
1.1841 + if(aListInformation == NULL)
1.1842 + {
1.1843 + return KErrArgument;
1.1844 + }
1.1845 +
1.1846 + //read DSS' data into local structure
1.1847 + TListInformation info;
1.1848 + err = Kern::ThreadRawRead(iClientThread, aListInformation, (TUint8*)&info, sizeof(TListInformation));
1.1849 + if(err != KErrNone)
1.1850 + {
1.1851 + return err;
1.1852 + }
1.1853 +
1.1854 + //check arguments
1.1855 + TPtr8 buffer(NULL, 0);
1.1856 + err = AllocAndReadDes(iClientThread, *info.iBuffer, buffer);
1.1857 + if(err != KErrNone)
1.1858 + {
1.1859 + //need to free the buffer if it was allocated
1.1860 + if(err != KErrNoMemory)
1.1861 + {
1.1862 + NKern::ThreadEnterCS();
1.1863 + Kern::Free((TAny*)buffer.Ptr());
1.1864 + NKern::ThreadLeaveCS();
1.1865 + }
1.1866 + return err;
1.1867 + }
1.1868 +
1.1869 + //get the list
1.1870 + TUint32 dataSize = 0;
1.1871 + TListManager manager;
1.1872 + err = KErrArgument;
1.1873 + switch(info.iType)
1.1874 + {
1.1875 + case EXipLibraries:
1.1876 + if(Debug::EScopeGlobal == info.iListScope)
1.1877 + {
1.1878 + err = manager.GetXipLibrariesList(buffer, dataSize);
1.1879 + }
1.1880 + break;
1.1881 +
1.1882 + case EThreads:
1.1883 + if(Debug::EScopeGlobal == info.iListScope)
1.1884 + {
1.1885 + err = manager.GetGlobalThreadList(buffer, dataSize);
1.1886 + }
1.1887 + else if(Debug::EScopeProcessSpecific == info.iListScope)
1.1888 + {
1.1889 + err = manager.GetThreadListForProcess(buffer, dataSize, info.iTargetId);
1.1890 + }
1.1891 + else if(Debug::EScopeThreadSpecific == info.iListScope)
1.1892 + {
1.1893 + err = manager.GetThreadListForThread(buffer, dataSize, info.iTargetId);
1.1894 + }
1.1895 + break;
1.1896 +
1.1897 + case EProcesses:
1.1898 + if(Debug::EScopeGlobal == info.iListScope)
1.1899 + {
1.1900 + err = manager.GetProcessList(buffer, dataSize);
1.1901 + }
1.1902 + break;
1.1903 +
1.1904 + case ECodeSegs:
1.1905 + if(Debug::EScopeGlobal == info.iListScope)
1.1906 + {
1.1907 + err = manager.GetGlobalCodeSegList(buffer, dataSize);
1.1908 + }
1.1909 + else if(Debug::EScopeProcessSpecific == info.iListScope)
1.1910 + {
1.1911 + err = manager.GetCodeSegListForProcess(buffer, dataSize, info.iTargetId);
1.1912 + }
1.1913 + else if(Debug::EScopeThreadSpecific == info.iListScope)
1.1914 + {
1.1915 + err = manager.GetCodeSegListForThread(buffer, dataSize, info.iTargetId);
1.1916 + }
1.1917 + break;
1.1918 +
1.1919 + default:
1.1920 + err = KErrNotSupported;
1.1921 + }
1.1922 +
1.1923 + if(err == KErrNone)
1.1924 + {
1.1925 + //if no error then write the buffer back
1.1926 + err = Kern::ThreadDesWrite(iClientThread, info.iBuffer, buffer, 0, KChunkShiftBy0, iClientThread);
1.1927 + }
1.1928 + //write back the size of the data regardless of any error
1.1929 + TInt writeErr = Kern::ThreadRawWrite(iClientThread, info.iDataSize, (TUint8*)&dataSize, sizeof(TUint32), iClientThread);
1.1930 + if(writeErr != KErrNone)
1.1931 + {
1.1932 + //if there was an error writing the size return that error instead
1.1933 + err = writeErr;
1.1934 + }
1.1935 +
1.1936 + //free the buffer
1.1937 + NKern::ThreadEnterCS();
1.1938 + Kern::Free((TAny*)buffer.Ptr());
1.1939 + NKern::ThreadLeaveCS();
1.1940 +
1.1941 + return err;
1.1942 + }
1.1943 +
1.1944 +/**
1.1945 +Read registers and store register data in aRegisterInfo
1.1946 +
1.1947 +@param aThread thread to read registers from
1.1948 +@param aRegisterInfo structure specifying which registers to read and providing
1.1949 + descriptors to write the register data into
1.1950 +
1.1951 +@return KErrNone if registers were read successfully. Note that this does not
1.1952 + mean that all the registers could be read, the
1.1953 + aRegisterInfo.iRegisterFlags array should be checked as to whether each
1.1954 + individual register could be read,
1.1955 + KErrArgument if aRegisterInfo is NULL, or if any of the pointers that
1.1956 + are members of aRegisterInfo are NULL, if an unknown register is
1.1957 + specified or if the passed in register values buffer is too small
1.1958 + KErrNoMemory if there is insufficient memory,
1.1959 + KErrDied, if the thread with thread ID aThreadId is dead
1.1960 +*/
1.1961 +TInt DRM_DebugChannel::ReadRegisters(DThread* aThread, TRM_DebugRegisterInformation* aRegisterInfo) const
1.1962 +{
1.1963 + LOG_MSG("DRM_DebugChannel::ReadRegisters()");
1.1964 +
1.1965 + TInt err = KErrNone;
1.1966 +
1.1967 + if (!aRegisterInfo)
1.1968 + return KErrArgument;
1.1969 +
1.1970 + TRM_DebugRegisterInformation info;
1.1971 + err = Kern::ThreadRawRead(iClientThread, aRegisterInfo, (TUint8*)&info, sizeof(TRM_DebugRegisterInformation));
1.1972 + if (err != KErrNone)
1.1973 + return err;
1.1974 +
1.1975 + if ((!info.iRegisterIds) || (!info.iRegisterValues) || (!info.iRegisterFlags))
1.1976 + return KErrArgument;
1.1977 +
1.1978 + //read ids from client thread
1.1979 + TPtr8 ids(NULL, 0);
1.1980 + err = AllocAndReadDes(iClientThread, *info.iRegisterIds, ids);
1.1981 + if(err != KErrNone)
1.1982 + {
1.1983 + if(err == KErrNoMemory)
1.1984 + {
1.1985 + NKern::ThreadEnterCS();
1.1986 + Kern::Free((TAny*)ids.Ptr());
1.1987 + NKern::ThreadLeaveCS();
1.1988 + }
1.1989 + return err;
1.1990 + }
1.1991 +
1.1992 + //read values from client thread
1.1993 + TPtr8 values(NULL, 0);
1.1994 + err = AllocAndReadDes(iClientThread, *info.iRegisterValues, values, EFalse);
1.1995 + if(err != KErrNone)
1.1996 + {
1.1997 + if(err == KErrNoMemory)
1.1998 + { NKern::ThreadEnterCS();
1.1999 + Kern::Free((TAny*)values.Ptr());
1.2000 + NKern::ThreadLeaveCS();
1.2001 + }
1.2002 + NKern::ThreadEnterCS();
1.2003 + Kern::Free((TAny*)ids.Ptr());
1.2004 + NKern::ThreadLeaveCS();
1.2005 + return err;
1.2006 + }
1.2007 +
1.2008 + //read flags from client thread
1.2009 + TPtr8 flags(NULL, 0);
1.2010 + err = AllocAndReadDes(iClientThread, *info.iRegisterFlags, flags, EFalse);
1.2011 + if(err != KErrNone)
1.2012 + {
1.2013 + if(err == KErrNoMemory)
1.2014 + {
1.2015 + NKern::ThreadEnterCS();
1.2016 + Kern::Free((TAny*)flags.Ptr());
1.2017 + NKern::ThreadLeaveCS();
1.2018 + }
1.2019 + NKern::ThreadEnterCS();
1.2020 + Kern::Free((TAny*)ids.Ptr());
1.2021 + Kern::Free((TAny*)values.Ptr());
1.2022 + NKern::ThreadLeaveCS();
1.2023 + return err;
1.2024 + }
1.2025 +
1.2026 + err = DoReadRegisters(aThread, ids, values, flags);
1.2027 + if (err == KErrNone)
1.2028 + {
1.2029 + err = Kern::ThreadDesWrite(iClientThread, info.iRegisterValues, values, 0, KChunkShiftBy0, iClientThread);
1.2030 + if(err == KErrNone)
1.2031 + {
1.2032 + err = Kern::ThreadDesWrite(iClientThread, info.iRegisterFlags, flags, 0, KChunkShiftBy0, iClientThread);
1.2033 + }
1.2034 + }
1.2035 +
1.2036 + NKern::ThreadEnterCS();
1.2037 + Kern::Free((TAny*)ids.Ptr());
1.2038 + Kern::Free((TAny*)values.Ptr());
1.2039 + Kern::Free((TAny*)flags.Ptr());
1.2040 + NKern::ThreadLeaveCS();
1.2041 +
1.2042 + return err;
1.2043 +}
1.2044 +
1.2045 +/**
1.2046 +@deprecated use DRM_DebugChannel::WriteRegisters(DThread* aThread, TRM_DebugRegisterInformation* aRegisterInfo) instead
1.2047 +*/
1.2048 +TInt DRM_DebugChannel::WriteRegistersLegacy(DThread* aThread, const TRM_DebugRegisterInfo* aRegisterInfo)
1.2049 +{
1.2050 + LOG_MSG("DRM_DebugChannel::WriteRegistersLegacy()");
1.2051 +
1.2052 + TInt err = KErrNone;
1.2053 +
1.2054 + if (!aRegisterInfo)
1.2055 + return KErrArgument;
1.2056 +
1.2057 + TRM_DebugRegisterInfo info(0, 0, 0);
1.2058 + err = Kern::ThreadRawRead(iClientThread, aRegisterInfo, (TUint8*)&info, sizeof(TRM_DebugRegisterInfo));
1.2059 + if (err != KErrNone)
1.2060 + return err;
1.2061 +
1.2062 + if (!info.iValues)
1.2063 + return KErrArgument;
1.2064 +
1.2065 + TUint length = (info.iLastRegister - info.iFirstRegister + 1) * 4;
1.2066 +
1.2067 + NKern::ThreadEnterCS();
1.2068 + TUint8 *values = (TUint8*)Kern::Alloc(length);
1.2069 + NKern::ThreadLeaveCS();
1.2070 + if (!values)
1.2071 + {
1.2072 + return KErrNoMemory;
1.2073 + }
1.2074 +
1.2075 + TPtr8 valuesDes(values, length);
1.2076 +
1.2077 + err = Kern::ThreadDesRead(iClientThread, info.iValues, valuesDes, 0);
1.2078 + if (err == KErrNone)
1.2079 + {
1.2080 + err = DoWriteRegisters(aThread, info.iFirstRegister, info.iLastRegister, valuesDes);
1.2081 + }
1.2082 +
1.2083 + NKern::ThreadEnterCS();
1.2084 + Kern::Free(values);
1.2085 + NKern::ThreadLeaveCS();
1.2086 +
1.2087 + return err;
1.2088 +}
1.2089 +
1.2090 +/**
1.2091 +Write registers and store flags data in aRegisterInfo
1.2092 +
1.2093 +@param aThread thread to write registers to
1.2094 +@param aRegisterInfo structure specifying which registers to write and providing
1.2095 + descriptors to write the register flags data into
1.2096 +
1.2097 +@return KErrNone if registers were written successfully. Note that this does not
1.2098 + mean that all the registers could be written, the flags array
1.2099 + should be checked as to whether each individual register could be read,
1.2100 + KErrArgument if aRegisterInfo is NULL, or if any of the pointers that
1.2101 + are members of aRegisterInfo are NULL, if an unknown register is
1.2102 + specified or if the passed in register values buffer is too small, or
1.2103 + if aThread is NULL,
1.2104 + KErrGeneral if there was a problem initialising the register set,
1.2105 + KErrNoMemory if there is insufficient memory,
1.2106 + KErrDied, if the thread with thread ID aThreadId is dead
1.2107 +*/
1.2108 +TInt DRM_DebugChannel::WriteRegisters(DThread* aThread, TRM_DebugRegisterInformation* aRegisterInfo) const
1.2109 +{
1.2110 + LOG_MSG("DRM_DebugChannel::WriteRegisters()");
1.2111 +
1.2112 + TInt err = KErrNone;
1.2113 +
1.2114 + if (!aRegisterInfo)
1.2115 + return KErrArgument;
1.2116 +
1.2117 + TRM_DebugRegisterInformation info;
1.2118 + err = Kern::ThreadRawRead(iClientThread, aRegisterInfo, (TUint8*)&info, sizeof(TRM_DebugRegisterInformation));
1.2119 + if (err != KErrNone)
1.2120 + return err;
1.2121 +
1.2122 + if ((!info.iRegisterIds) || (!info.iRegisterValues) ||(!info.iRegisterFlags))
1.2123 + return KErrArgument;
1.2124 +
1.2125 + //read ids from client thread
1.2126 + TPtr8 ids(NULL, 0);
1.2127 + err = AllocAndReadDes(iClientThread, *info.iRegisterIds, ids);
1.2128 + if(err != KErrNone)
1.2129 + {
1.2130 + if(err == KErrNoMemory)
1.2131 + {
1.2132 + NKern::ThreadEnterCS();
1.2133 + Kern::Free((TAny*)ids.Ptr());
1.2134 + NKern::ThreadLeaveCS();
1.2135 + }
1.2136 + return err;
1.2137 + }
1.2138 +
1.2139 + //read values from client thread
1.2140 + TPtr8 values(NULL, 0);
1.2141 + err = AllocAndReadDes(iClientThread, *info.iRegisterValues, values);
1.2142 + if(err != KErrNone)
1.2143 + {
1.2144 + if(err == KErrNoMemory)
1.2145 + {
1.2146 + NKern::ThreadEnterCS();
1.2147 + Kern::Free((TAny*)values.Ptr());
1.2148 + NKern::ThreadLeaveCS();
1.2149 + }
1.2150 + NKern::ThreadEnterCS();
1.2151 + Kern::Free((TAny*)ids.Ptr());
1.2152 + NKern::ThreadLeaveCS();
1.2153 + return err;
1.2154 + }
1.2155 +
1.2156 + //read flags from client thread
1.2157 + TPtr8 flags(NULL, 0);
1.2158 + err = AllocAndReadDes(iClientThread, *info.iRegisterFlags, flags, EFalse);
1.2159 + if(err != KErrNone)
1.2160 + {
1.2161 + if(err == KErrNoMemory)
1.2162 + {
1.2163 + NKern::ThreadEnterCS();
1.2164 + Kern::Free((TAny*)flags.Ptr());
1.2165 + NKern::ThreadLeaveCS();
1.2166 + }
1.2167 + NKern::ThreadEnterCS();
1.2168 + Kern::Free((TAny*)ids.Ptr());
1.2169 + Kern::Free((TAny*)values.Ptr());
1.2170 + NKern::ThreadLeaveCS();
1.2171 + return err;
1.2172 + }
1.2173 +
1.2174 + err = DoWriteRegisters(aThread, ids, values, flags);
1.2175 + if(err == KErrNone)
1.2176 + {
1.2177 + err = Kern::ThreadDesWrite(iClientThread, info.iRegisterFlags, flags, 0, KChunkShiftBy0, iClientThread);
1.2178 + }
1.2179 +
1.2180 + NKern::ThreadEnterCS();
1.2181 + Kern::Free((TAny*)ids.Ptr());
1.2182 + Kern::Free((TAny*)values.Ptr());
1.2183 + Kern::Free((TAny*)flags.Ptr());
1.2184 + NKern::ThreadLeaveCS();
1.2185 +
1.2186 + return err;
1.2187 +}
1.2188 +
1.2189 +/**
1.2190 +Suspends execution of the specified thread.
1.2191 +
1.2192 +@param aThread thread to resume
1.2193 +
1.2194 +@return KErrNone if there were no problems or KErrArgument if aThread is NULL
1.2195 +*/
1.2196 +TInt DRM_DebugChannel::DoSuspendThread(DThread *aThread)
1.2197 + {
1.2198 + LOG_MSG("DRM_DebugChannel::DoSuspendThread()");
1.2199 +
1.2200 + if (!aThread)
1.2201 + {
1.2202 + LOG_MSG("Invalid dthread object");
1.2203 + return KErrArgument;
1.2204 + }
1.2205 +
1.2206 + return TheDProcessTracker.SuspendThread(aThread);
1.2207 + }
1.2208 +
1.2209 +/**
1.2210 +Resumes execution of the specified thread.
1.2211 +
1.2212 +@param aThread thread to resume
1.2213 +
1.2214 +@return KErrNone if there were no problems, KErrArgument if aThread is NULL
1.2215 + or an error value returned from DoStepRange()
1.2216 +*/
1.2217 +TInt DRM_DebugChannel::DoResumeThread(DThread *aThread)
1.2218 + {
1.2219 + LOG_MSG("DRM_DebugChannel::DoResumeThread()");
1.2220 +
1.2221 + if (!aThread)
1.2222 + return KErrArgument;
1.2223 +
1.2224 + // get the current PC
1.2225 + TUint32 currentPC;
1.2226 + TInt err = ReadKernelRegisterValue(aThread, PC_REGISTER, currentPC);
1.2227 + if(err != KErrNone)
1.2228 + {
1.2229 + LOG_MSG2("DRM_DebugChannel::DoResumeThread - Non-zero error code discarded: %d", err);
1.2230 + }
1.2231 +
1.2232 + // if there is a breakpoint at the current PC, we need to single step past it
1.2233 + TBreakEntry* breakEntry = NULL;
1.2234 + do
1.2235 + {
1.2236 + breakEntry = iBreakManager->GetNextBreak(breakEntry);
1.2237 + if(breakEntry && !iBreakManager->IsTemporaryBreak(*breakEntry))
1.2238 + {
1.2239 + if (breakEntry->iAddress == currentPC)
1.2240 + {
1.2241 + return DoStepRange(aThread, currentPC, currentPC+1, ETrue, 1, ETrue);
1.2242 + }
1.2243 + }
1.2244 + } while(breakEntry);
1.2245 + return TheDProcessTracker.ResumeThread(aThread);
1.2246 + }
1.2247 +
1.2248 +//
1.2249 +// DRM_DebugChannel::DoStepRange
1.2250 +//
1.2251 +TInt DRM_DebugChannel::DoStepRange(DThread *aThread, const TUint32 aStartAddress, const TUint32 aStopAddress, TBool aStepInto, TBool aResumeOnceOutOfRange, const TUint32 aNumSteps, TBool aUserRequest)
1.2252 +{
1.2253 + LOG_MSG("DRM_DebugChannel::DoStepRange()");
1.2254 +
1.2255 + if (!aThread)
1.2256 + return KErrArgument;
1.2257 +
1.2258 + //check that the thread is suspended
1.2259 + if(!TheDProcessTracker.CheckSuspended(aThread))
1.2260 + {
1.2261 + LOG_MSG2("DRM_DebugChannel::DoStepRange() Thread with id 0x%08x not suspended.", aThread->iId);
1.2262 + return KErrInUse;
1.2263 + }
1.2264 +
1.2265 + TUint32 startAddress = (aStartAddress & 0x1) ? aStartAddress + 1 : aStartAddress;
1.2266 + TUint32 stopAddress = (aStopAddress & 0x1) ? aStopAddress + 1 : aStopAddress;;
1.2267 +
1.2268 + // don't allow the user to step in the excluded ROM region. this could be called
1.2269 + // internally however. for example, the the special breakpoints we set to handle
1.2270 + // panics, exceptions, and library loaded events are in the user library, and we
1.2271 + // will need to step past the breakpoint before continuing the thread.
1.2272 + //if (aUserRequest && (startAddress >= iExcludedROMAddressStart) && (startAddress < iExcludedROMAddressEnd))
1.2273 + //{
1.2274 + // return KErrNotSupported;
1.2275 + //}
1.2276 +
1.2277 + // set the temp breakpoint, and disable the breakpoint at the current PC if necessary
1.2278 + // if its not a user request, and we are just trying to resume from a breakpoint,
1.2279 + // then we don't need to check for stubs. The last parameter aUserRequest tells
1.2280 + // ModifyBreaksForStep to check for stubs or not. In some cases, the check for stubs
1.2281 + // is true even if its not a user request.For example, this is true in cases where
1.2282 + // we are doing a step range and the instruction in the range modified PC.
1.2283 + // in this case, DoStepRange will be called from the exception handler where
1.2284 + // we need to check for the stubs for the valid behavior. So truly, we don't need to check
1.2285 + // for stubs only when resuming from a breakpoint.
1.2286 + ReturnIfError(iStepper->ModifyBreaksForStep(aThread, startAddress, stopAddress, aResumeOnceOutOfRange, aUserRequest, aNumSteps));
1.2287 +
1.2288 + LOG_MSG("DRM_DebugChannel::DoStepRange() - resuming thread\n");
1.2289 +
1.2290 + return TheDProcessTracker.ResumeThread(aThread);
1.2291 +}
1.2292 +
1.2293 +/**
1.2294 +Read memory from the specified addres into the aData descriptor. If there is a
1.2295 +breakpoint set in the region of memory returned then the correct data value is
1.2296 +inserted into the descriptor
1.2297 +
1.2298 +@param aThread pointer to thread whose address space memory is to be read from
1.2299 +@param aAddress address to start reading memory from
1.2300 +@param aLength length of memory block to read
1.2301 +@param aData descriptor to read memory into
1.2302 +
1.2303 +@return KErrNone if memory read successfully,
1.2304 + KErrNotSupported if reading from the rom section is not supported,
1.2305 + KErrBadHandle if aThread is invalid,
1.2306 + or one of the other system wide error codes
1.2307 +*/
1.2308 +TInt DRM_DebugChannel::DoReadMemory(const DThread *aThread, const TUint32 aAddress, const TUint32 aLength, TDes8 &aData) const
1.2309 + {
1.2310 + LOG_MSG("DRM_DebugChannel::DoReadMemory()");
1.2311 +
1.2312 + // make sure the parameters are valid
1.2313 + if (aLength > aData.MaxSize())
1.2314 + return KErrArgument;
1.2315 +
1.2316 + TInt err = KErrNone;
1.2317 +
1.2318 + // trap exceptions in case the address is invalid
1.2319 + XTRAPD(r, XT_DEFAULT, err = TryToReadMemory(aThread, (TAny *)aAddress, (TAny *)aData.Ptr(), aLength));
1.2320 +
1.2321 + err = (KErrNone == r) ? err : r;
1.2322 +
1.2323 + if (KErrNone == err)
1.2324 + {
1.2325 + aData.SetLength(aLength);
1.2326 +
1.2327 + TPtr8 data((TUint8 *)aData.Ptr(), aLength, aLength);
1.2328 +
1.2329 + // if we have any breakpoints in this range, put the actual instruction in the buffer
1.2330 + TBreakEntry* breakEntry = NULL;
1.2331 + do
1.2332 + {
1.2333 + breakEntry = iBreakManager->GetNextBreak(breakEntry);
1.2334 + if(breakEntry && !iBreakManager->IsTemporaryBreak(*breakEntry))
1.2335 + {
1.2336 + if ((breakEntry->iAddress >= aAddress) && (breakEntry->iAddress < (aAddress + aLength)))
1.2337 + {
1.2338 + TInt instSize;
1.2339 +
1.2340 + switch(breakEntry->iMode)
1.2341 + {
1.2342 + case EArmMode:
1.2343 + instSize = 4;
1.2344 + break;
1.2345 +
1.2346 + case EThumbMode:
1.2347 + instSize = 2;
1.2348 + break;
1.2349 +
1.2350 + case EThumb2EEMode:
1.2351 + default:
1.2352 + LOG_MSG("DRM_DebugChannel::DoReadMemory() cannot fixup breakpoints with unsupported architecture");
1.2353 + return KErrNotSupported;
1.2354 + }
1.2355 + memcpy((TAny*)&data[breakEntry->iAddress - aAddress], (TAny *)breakEntry->iInstruction.Ptr(), instSize);
1.2356 + }
1.2357 + }
1.2358 + } while(breakEntry);
1.2359 + }
1.2360 +
1.2361 + return err;
1.2362 + }
1.2363 +
1.2364 +/**
1.2365 +Attempt to write memory to aThread's address space
1.2366 +
1.2367 +@param aThread thread to whose address space memory is to be written
1.2368 +@param aAddress memory location to write memory to
1.2369 +@param aLength number of bytes of data to write
1.2370 +@param aData descriptor containing memory to write
1.2371 +
1.2372 +@return KErrNone if memory written successfully,
1.2373 + KErrArgument if aLength is greater than than the length of the aData
1.2374 + KErrBadHandle if aThread is invalid,
1.2375 + or another of the system wide error codes
1.2376 +*/
1.2377 +TInt DRM_DebugChannel::DoWriteMemory(DThread *aThread, const TUint32 aAddress, const TUint32 aLength, TDes8 &aData)
1.2378 + {
1.2379 + LOG_MSG("DRM_DebugChannel::DoWriteMemory()");
1.2380 +
1.2381 + // make sure the parameters are valid
1.2382 + if (aLength > aData.Length())
1.2383 + return KErrArgument;
1.2384 +
1.2385 + TInt err = KErrNone;
1.2386 +
1.2387 + // trap exceptions in case the address is invalid
1.2388 + XTRAPD(r, XT_DEFAULT, err = TryToWriteMemory(aThread, (TAny *)aAddress, (TAny *)aData.Ptr(), aLength));
1.2389 +
1.2390 + err = (KErrNone == r) ? err : r;
1.2391 +
1.2392 + // reset any breakpoints we may have just overwritten
1.2393 + if (KErrNone == err)
1.2394 + {
1.2395 + TPtr8 data((TUint8 *)aData.Ptr(), aLength, aLength);
1.2396 +
1.2397 + TBreakEntry* breakEntry = NULL;
1.2398 + do
1.2399 + {
1.2400 + breakEntry = iBreakManager->GetNextBreak(breakEntry);
1.2401 + if(breakEntry && !iBreakManager->IsTemporaryBreak(*breakEntry))
1.2402 + {
1.2403 + if ((breakEntry->iAddress >= aAddress) && (breakEntry->iAddress < (aAddress + aLength)))
1.2404 + {
1.2405 + // default to arm mode
1.2406 + TUint32 inst;
1.2407 + TInt instSize;
1.2408 +
1.2409 + switch (breakEntry->iMode)
1.2410 + {
1.2411 + case EArmMode:
1.2412 + inst = KArmBreakPoint;
1.2413 + instSize = 4;
1.2414 + break;
1.2415 +
1.2416 + case EThumbMode:
1.2417 + inst = KThumbBreakPoint;
1.2418 + instSize = 2;
1.2419 + break;
1.2420 +
1.2421 + case EThumb2EEMode:
1.2422 + default:
1.2423 + LOG_MSG("DRM_DebugChannel::DoWriteMemory() cannot fixup breakpoints of unsupported architecture type");
1.2424 +
1.2425 + return KErrNotSupported;
1.2426 + }
1.2427 +
1.2428 + breakEntry->iInstruction.Copy(&data[breakEntry->iAddress - aAddress], instSize);
1.2429 + memcpy((TAny*)breakEntry->iAddress, (TAny *)&inst, instSize);
1.2430 + }
1.2431 + }
1.2432 +
1.2433 + } while(breakEntry);
1.2434 + }
1.2435 + return err;
1.2436 + }
1.2437 +
1.2438 +//
1.2439 +// DRM_DebugChannel::DoReadRegisters
1.2440 +//
1.2441 +TInt DRM_DebugChannel::DoReadRegisters(DThread *aThread, const TInt16 aFirstRegister, const TInt16 aLastRegister, TDes8 &aValues)
1.2442 +{
1.2443 + LOG_MSG("DRM_DebugChannel::DoReadRegisters()");
1.2444 +
1.2445 + // make sure the parameters are valid
1.2446 + if (!aThread || (aFirstRegister < 0) || (aLastRegister >= (TInt16)(sizeof(TArmRegSet)/sizeof(TArmReg))))
1.2447 + return KErrArgument;
1.2448 +
1.2449 + // make sure the descriptor is big enough to hold the requested data
1.2450 + if ((TInt)((aLastRegister - aFirstRegister + 1) * sizeof(TArmReg)) > (aValues.MaxSize()))
1.2451 + return KErrArgument;
1.2452 +
1.2453 + TArmRegSet regSet;
1.2454 + TUint32 unused;
1.2455 +
1.2456 + NKern::ThreadGetUserContext(&aThread->iNThread, ®Set, unused);
1.2457 +
1.2458 + LOG_MSG2( "DRM_DebugChannel::DoReadRegistersLegacy() : unused = 0x%X\n", unused );
1.2459 +
1.2460 + TArmReg *reg = ®Set.iR0;
1.2461 +
1.2462 + if (!reg)
1.2463 + return KErrGeneral;
1.2464 +
1.2465 + for (TInt16 i = aFirstRegister; i <= aLastRegister; i++)
1.2466 + aValues.Append((TUint8 *)®[i], sizeof(TArmReg));
1.2467 +
1.2468 + return KErrNone;
1.2469 +}
1.2470 +
1.2471 +/**
1.2472 + @prototype
1.2473 +
1.2474 + Experimental function for determining whether a thread is suspended.
1.2475 +
1.2476 + @param aThread thread to check if suspended
1.2477 +
1.2478 + @return ETrue if the thread is suspended, EFalse if it isn't or does not exist
1.2479 + */
1.2480 +TBool DRM_DebugChannel::CheckSuspended(const DThread *aThread) const
1.2481 + {
1.2482 + if(!aThread)
1.2483 + {
1.2484 + return EFalse;
1.2485 + }
1.2486 +
1.2487 + if( (aThread->iNThread.iCsCount>0) && (aThread->iNThread.iCsFunction>0) )
1.2488 + {
1.2489 + return ETrue;
1.2490 + }
1.2491 +
1.2492 + if(aThread->iNThread.iSuspendCount > 0)
1.2493 + {
1.2494 + return ETrue;
1.2495 + }
1.2496 + return EFalse;
1.2497 + }
1.2498 +
1.2499 +/**
1.2500 +Read registers and store register values in aRegisterValues and the flags
1.2501 +indicating which registers could be read in aRegisterFlags
1.2502 +
1.2503 +@param aThread thread to read registers from
1.2504 +@param aRegisterIds array containing register IDs to read
1.2505 +@param aRegisterValues array to store register values in
1.2506 +@param aRegisterFlags array to store flags in
1.2507 +
1.2508 +@return KErrNone if registers were read successfully. Note that this does not
1.2509 + mean that all the registers could be read, the aRegisterFlags array
1.2510 + should be checked as to whether each individual register could be read,
1.2511 + KErrArgument if aThread is NULL, if an unknown register is specified in
1.2512 + aRegisterValues or if aRegisterValues is too small
1.2513 + KErrGeneral if there was a problem initialising the register set
1.2514 +*/
1.2515 +TInt DRM_DebugChannel::DoReadRegisters(DThread *aThread, const TDesC8 &aRegisterIds, TDes8 &aRegisterValues, TDes8& aRegisterFlags) const
1.2516 +{
1.2517 + LOG_MSG("DRM_DebugChannel::DoReadRegisters()");
1.2518 +
1.2519 + // make sure the parameters are valid
1.2520 + if (!aThread)
1.2521 + return KErrArgument;
1.2522 +
1.2523 + //Need to revisit this to determine whether there is a way to validate this
1.2524 +#if 0
1.2525 + if ( !CheckSuspended(aThread) )
1.2526 + {
1.2527 + LOG_MSG2("DRM_DebugChannel::DoReadRegisters() thread with id 0x%08x is not suspended", aThread->iId);
1.2528 + return KErrInUse;
1.2529 + }
1.2530 +#endif
1.2531 +
1.2532 + //set lengths of output descriptors to 0 prior to filling
1.2533 + aRegisterValues.SetLength(0);
1.2534 + aRegisterFlags.SetLength(0);
1.2535 +
1.2536 + TArmRegSet regSet;
1.2537 + TUint32 flags;
1.2538 +
1.2539 + NKern::ThreadGetUserContext(&aThread->iNThread, ®Set, flags);
1.2540 +
1.2541 + LOG_MSG2( "DRM_DebugChannel::DoReadRegisters() : flags = 0x%X\n", flags );
1.2542 +
1.2543 + TArmReg *regPtr = ®Set.iR0;
1.2544 +
1.2545 + if (!regPtr)
1.2546 + return KErrGeneral;
1.2547 +
1.2548 + TUint numberOfRegisters = aRegisterIds.Length() / sizeof(TRegisterInfo);
1.2549 +
1.2550 + //iterate through registers setting the relevant aFlags value
1.2551 + for(TUint i=0; i<numberOfRegisters; i++)
1.2552 + {
1.2553 + //get current register id
1.2554 + TRegisterInfo reg;
1.2555 + TInt err = GetTRegisterInfo(aRegisterIds, i, reg);
1.2556 + //exit with the error value if there was an error
1.2557 + if(err != KErrNone)
1.2558 + return err;
1.2559 +
1.2560 + //if unknown register then exit as can't know how many bytes this entry will
1.2561 + //represent in aRegisterValues
1.2562 + TTag registerTag;
1.2563 + TDebugFunctionality::GetRegister(reg, registerTag);
1.2564 + if(registerTag.iValue == EAccessUnknown)
1.2565 + {
1.2566 + return KErrArgument;
1.2567 + }
1.2568 +
1.2569 + //get the current register id as a kernel register
1.2570 + TArmReg armReg;
1.2571 + err = GetKernelRegisterId(reg, armReg);
1.2572 + if((err == KErrNotSupported) || (registerTag.iValue == EAccessNone) || (registerTag.iValue == EAccessWriteOnly))
1.2573 + {
1.2574 + //reading this register is not supported
1.2575 + aRegisterFlags.Append(ENotSupported);
1.2576 + //just skip over this entry in the values buffer
1.2577 + if(aRegisterValues.Length() + registerTag.iSize > aRegisterValues.MaxLength())
1.2578 + {
1.2579 + //writing this value would cause overflow so exit
1.2580 + return KErrArgument;
1.2581 + }
1.2582 + aRegisterValues.SetLength(aRegisterValues.Length() + registerTag.iSize);
1.2583 + }
1.2584 + else
1.2585 + {
1.2586 + if(registerTag.iSize == sizeof(TArmReg))
1.2587 + {
1.2588 + if(GetFlagAtOffset(flags, armReg))
1.2589 + {
1.2590 + //set flag as valid
1.2591 + aRegisterFlags.Append(EValid);
1.2592 + }
1.2593 + else
1.2594 + {
1.2595 + // Even though the flag is invalid, we can return the value of the register
1.2596 + // and let the user decide what to do
1.2597 + aRegisterFlags.Append(EInValid);
1.2598 + }
1.2599 +
1.2600 + if(aRegisterValues.Length() + sizeof(TArmReg) > aRegisterValues.MaxLength())
1.2601 + {
1.2602 + //writing this value would cause overflow so exit
1.2603 + return KErrArgument;
1.2604 + }
1.2605 + //write value into register into regSet
1.2606 + aRegisterValues.Append((TUint8 *)®Ptr[armReg], registerTag.iSize);
1.2607 + }
1.2608 + else
1.2609 + {
1.2610 + //currently all kernel supported registers are 4 bytes so
1.2611 + //return EBadSize. Would need updating if/when other register
1.2612 + //value sizes are supported
1.2613 + aRegisterFlags.Append(EBadSize);
1.2614 + aRegisterValues.SetLength(aRegisterValues.Length() + registerTag.iSize);
1.2615 + }
1.2616 + }
1.2617 + }
1.2618 + return KErrNone;
1.2619 +}
1.2620 +
1.2621 +//
1.2622 +// DRM_DebugChannel::DoWriteRegisters
1.2623 +//
1.2624 +TInt DRM_DebugChannel::DoWriteRegisters(DThread *aThread, const TInt16 aFirstRegister, const TInt16 aLastRegister, TDesC8 &aValues)
1.2625 +{
1.2626 + LOG_MSG("DRM_DebugChannel::DoWriteRegisters()");
1.2627 +
1.2628 + // make sure the parameters are valid
1.2629 + if (!aThread || (aFirstRegister < 0) || (aLastRegister >= (TInt16)(sizeof(TArmRegSet)/sizeof(TArmReg))))
1.2630 + return KErrArgument;
1.2631 +
1.2632 + // make sure the descriptor is big enough to hold the data to write
1.2633 + if ((TInt)((aLastRegister - aFirstRegister + 1) * sizeof(TArmReg)) > (aValues.Length()))
1.2634 + return KErrArgument;
1.2635 +
1.2636 + TArmRegSet regSet;
1.2637 + TUint32 unused;
1.2638 +
1.2639 + NKern::ThreadGetUserContext(&aThread->iNThread, ®Set, unused);
1.2640 +
1.2641 + TArmReg *reg = ®Set.iR0;
1.2642 +
1.2643 + for (TInt16 i = aFirstRegister; i <= aLastRegister; i++)
1.2644 + reg[i] = *(TUint32 *)&aValues[(i-aFirstRegister)*sizeof(TArmReg)];
1.2645 +
1.2646 + NKern::ThreadSetUserContext(&aThread->iNThread, ®Set);
1.2647 +
1.2648 + return KErrNone;
1.2649 +}
1.2650 +
1.2651 +/**
1.2652 +Write registers and store flags indicating which registers could be read in
1.2653 +aRegisterFlags
1.2654 +
1.2655 +@param aThread thread to write registers to
1.2656 +@param aRegisterIds array containing register IDs to write
1.2657 +@param aRegisterValues array containing register values to write
1.2658 +@param aRegisterFlags array to store flags in
1.2659 +
1.2660 +@return KErrNone if registers were written successfully. Note that this does not
1.2661 + mean that all the registers could be written, the aRegisterFlags array
1.2662 + should be checked as to whether each individual register could be read,
1.2663 + KErrArgument if aThread is NULL, if the buffer passed in as
1.2664 + aRegisterValue is too small, or if an unknown register is requested,
1.2665 + KErrGeneral if there was a problem initialising the register set
1.2666 +*/
1.2667 +TInt DRM_DebugChannel::DoWriteRegisters(DThread *aThread, const TDesC8 &aRegisterIds, TDesC8 &aRegisterValues, TDes8 &aRegisterFlags) const
1.2668 +{
1.2669 + LOG_MSG("DRM_DebugChannel::DoWriteRegisters()");
1.2670 +
1.2671 + // make sure the parameters are valid
1.2672 + if (!aThread)
1.2673 + return KErrArgument;
1.2674 +
1.2675 + //check that the thread is suspended before reading the registers
1.2676 + if(!TheDProcessTracker.CheckSuspended(aThread))
1.2677 + {
1.2678 + LOG_MSG2("DRM_DebugChannel::DoWriteRegisters() thread with id 0x%08x is not suspended", aThread->iId);
1.2679 + return KErrInUse;
1.2680 + }
1.2681 +
1.2682 + //get register values from kernel
1.2683 + TArmRegSet regSet;
1.2684 + TUint32 flags;
1.2685 + NKern::ThreadGetUserContext(&aThread->iNThread, ®Set, flags);
1.2686 +
1.2687 + //set lengths of output descriptors to 0 prior to filling
1.2688 + aRegisterFlags.SetLength(0);
1.2689 +
1.2690 + //pointer to first kernel register
1.2691 + TArmReg *regPtr = ®Set.iR0;
1.2692 +
1.2693 + if (!regPtr)
1.2694 + return KErrGeneral;
1.2695 +
1.2696 + //calculate number of registers
1.2697 + TUint numberOfRegisters = aRegisterIds.Length() / sizeof(TRegisterInfo);
1.2698 +
1.2699 + //iterate through registers setting the relevant aRegisterFlags value and
1.2700 + //setting the necessary value in regSet ready to write to kernel
1.2701 + for(TUint i=0, offset = 0; i<numberOfRegisters; i++)
1.2702 + {
1.2703 + //get current register id
1.2704 + TRegisterInfo reg;
1.2705 + TInt err = GetTRegisterInfo(aRegisterIds, i, reg);
1.2706 + //exit with the error value if there was an error
1.2707 + if(err != KErrNone)
1.2708 + {
1.2709 + return err;
1.2710 + }
1.2711 +
1.2712 + //if unknown register then exit as can't know how many bytes this entry will
1.2713 + //represent in aRegisterValues
1.2714 + TTag registerTag;
1.2715 + TDebugFunctionality::GetRegister(reg, registerTag);
1.2716 + if(registerTag.iValue == EAccessUnknown)
1.2717 + {
1.2718 + return KErrArgument;
1.2719 + }
1.2720 +
1.2721 + //get the current register id as a kernel register
1.2722 + TArmReg armReg;
1.2723 + err = GetKernelRegisterId(reg, armReg);
1.2724 + if((err == KErrNotSupported) || (registerTag.iValue == EAccessNone) || (registerTag.iValue == EAccessReadOnly))
1.2725 + {
1.2726 + //writing to this register is not supported
1.2727 + aRegisterFlags.Append(ENotSupported);
1.2728 + }
1.2729 + else if(GetFlagAtOffset(flags, armReg))
1.2730 + {
1.2731 + if(registerTag.iSize == sizeof(TArmReg))
1.2732 + {
1.2733 + //set flag as valid
1.2734 + aRegisterFlags.Append(EValid);
1.2735 + if(offset + sizeof(TArmReg) > aRegisterValues.Length())
1.2736 + {
1.2737 + //getting this value would cause overflow so exit
1.2738 + return KErrArgument;
1.2739 + }
1.2740 + //write value into register into regSet
1.2741 + regPtr[armReg] = *(TUint32 *)&aRegisterValues[offset];
1.2742 + }
1.2743 + else
1.2744 + {
1.2745 + //currently all kernel supported registers are 4 bytes so
1.2746 + //return EBadSize. Would need updating if/when other register
1.2747 + //value sizes are supported
1.2748 + aRegisterFlags.Append(EBadSize);
1.2749 + }
1.2750 +
1.2751 + }
1.2752 + else
1.2753 + {
1.2754 + //set flag as invalid as register value couldn't be read
1.2755 + aRegisterFlags.Append(EInValid);
1.2756 + }
1.2757 + offset+=registerTag.iSize;
1.2758 + }
1.2759 +
1.2760 + //write the input data into the registers
1.2761 + NKern::ThreadSetUserContext(&aThread->iNThread, ®Set);
1.2762 +
1.2763 + //return normally
1.2764 + return KErrNone;
1.2765 + }
1.2766 +
1.2767 +//
1.2768 +// DRM_DebugChannel::DoSecurityCheck
1.2769 +//
1.2770 +TBool DRM_DebugChannel::DoSecurityCheck()
1.2771 +{
1.2772 + LOG_MSG("DRM_DebugChannel::DoSecurityCheck");
1.2773 + DProcess* clientProcess = iClientThread->iOwningProcess;
1.2774 + if (clientProcess)
1.2775 + {
1.2776 + SSecurityInfo secureInfo = clientProcess->iS;
1.2777 +
1.2778 + LOG_MSG2("DoSecurityCheck - client secure id is 0x%08x",secureInfo.iSecureId);
1.2779 +
1.2780 + // Ensure we really are communicating with the Debug Security Server
1.2781 + if (secureInfo.iSecureId == KUidDebugSecurityServer.iUid )
1.2782 + {
1.2783 + return ETrue;
1.2784 + }
1.2785 + }
1.2786 + return EFalse;
1.2787 +}
1.2788 +
1.2789 +/**
1.2790 +Attempt to read memory from aThread's address space
1.2791 +
1.2792 +@param aThread thread from whose address space memory is to be read
1.2793 +@param aSrc pointer to memory location to read memory from
1.2794 +@param aDest pointer to memory location to write memory to
1.2795 +@param aLength number of bytes of data to read
1.2796 +
1.2797 +@return KErrNone if memory read successfully,
1.2798 + or another of the system wide error codes
1.2799 +*/
1.2800 +TInt DRM_DebugChannel::TryToReadMemory(const DThread *aThread, const TAny *aSrc, TAny *aDest, const TUint32 aLength) const
1.2801 +{
1.2802 + LOG_MSG("DRM_DebugChannel::TryToReadMemory()");
1.2803 +
1.2804 + // make sure the parameters are valid
1.2805 + if (!aThread)
1.2806 + return KErrArgument;
1.2807 +
1.2808 + //Need to revisit this to determine whether there is a way to validate this
1.2809 +#if 0
1.2810 + //check that the thread is suspended before reading the memory
1.2811 + if ( !CheckSuspended(aThread) )
1.2812 + {
1.2813 + LOG_MSG2("DRM_DebugChannel::TryToReadMemory() thread with id 0x%08x is not suspended", aThread->iId);
1.2814 + return KErrInUse;
1.2815 + }
1.2816 +#endif
1.2817 +
1.2818 + LOG_MSG2("Using Kern::ThreadRawRead to read memory at address %x", aSrc);
1.2819 + return Kern::ThreadRawRead((DThread *)aThread, aSrc, aDest, aLength);
1.2820 +}
1.2821 +
1.2822 +/**
1.2823 +Attempt to write memory to aThread's address space
1.2824 +
1.2825 +@param aThread thread to whose address space memory is to be written
1.2826 +@param aDest pointer to memory location to write memory to
1.2827 +@param aSrc pointer to memory location to read memory from
1.2828 +@param aLength number of bytes of data to write
1.2829 +
1.2830 +@return KErrNone if memory written successfully, or another of the system wide
1.2831 + error codes
1.2832 +*/
1.2833 +TInt DRM_DebugChannel::TryToWriteMemory(const DThread *aThread, TAny *aDest, const TAny *aSrc, const TUint32 aLength)
1.2834 +{
1.2835 + LOG_MSG("DRM_DebugChannel::TryToWriteMemory()");
1.2836 +
1.2837 + //check that the thread is suspended before writing the memory
1.2838 + if(!TheDProcessTracker.CheckSuspended((DThread*)aThread))
1.2839 + {
1.2840 + LOG_MSG2("DRM_DebugChannel::TryToWriteMemory() thread with id 0x%08x is not suspended", aThread->iId);
1.2841 + return KErrInUse;
1.2842 + }
1.2843 +
1.2844 + LOG_MSG2("Using Kern::ThreadRawWrite to write memory at address %x", (TUint32)aDest);
1.2845 + return Kern::ThreadRawWrite((DThread *)aThread, aDest, aSrc, aLength, iClientThread);
1.2846 +}
1.2847 +
1.2848 +/**
1.2849 +@deprecated use DRM_DebugChannel::ReadKernelRegisterValue(DThread *aThread, const TArmReg aKernelRegisterId, T4ByteRegisterValue &aValue) instead
1.2850 +*/
1.2851 +TInt32 DRM_DebugChannel::ReadRegister(DThread *aThread, TInt aNum)
1.2852 +{
1.2853 + LOG_MSG("DRM_DebugChannel::ReadRegister()");
1.2854 +
1.2855 + if (!aThread || (aNum < 0) || (aNum >= (TInt16)(sizeof(TArmRegSet)/sizeof(TArmReg))))
1.2856 + {
1.2857 + LOG_MSG2("Invalid register number (%d) passed to ReadRegister", aNum);
1.2858 + return 0;
1.2859 + }
1.2860 +
1.2861 + TArmRegSet regSet;
1.2862 + TUint32 unused;
1.2863 +
1.2864 + NKern::ThreadGetUserContext(&aThread->iNThread, ®Set, unused);
1.2865 +
1.2866 + TArmReg *reg = ®Set.iR0;
1.2867 +
1.2868 + return ((TUint32 *)reg)[aNum];
1.2869 +}
1.2870 +
1.2871 +/**
1.2872 +Given a TArmReg register ID, read the value of the register. The register value
1.2873 +will be stored in aValue if the register could be read.
1.2874 +
1.2875 +@param aThread thread to read register from
1.2876 +@param aKernelRegisterId ID of register to read from
1.2877 +@param aValue value read from register
1.2878 +
1.2879 +@return KErrNone if value was successfully stored in aValue,
1.2880 + KErrNotSupported if aKernelRegister is not supported by the debug
1.2881 + security server,
1.2882 + or a return value from DRM_DebugChannel::ReadDebugRegisterValue()
1.2883 +*/
1.2884 +TInt32 DRM_DebugChannel::ReadKernelRegisterValue(DThread *aThread, const TArmReg aKernelRegisterId, T4ByteRegisterValue &aValue) const
1.2885 +{
1.2886 + //get register ID as a TRegisterInfo ID
1.2887 + TRegisterInfo regId;
1.2888 + TInt err = GetDebugRegisterId(aKernelRegisterId, regId);
1.2889 + if(err != KErrNone)
1.2890 + return err;
1.2891 +
1.2892 + //get the value for the register
1.2893 + err = ReadDebugRegisterValue(aThread, regId, aValue);
1.2894 + return err;
1.2895 + }
1.2896 +
1.2897 +/**
1.2898 +Given a TRegisterInfo register ID, read the value of this register. The
1.2899 +register value will be stored in aValue if the register could be read.
1.2900 +
1.2901 +@param aThread thread to read register from
1.2902 +@param aDebugRegisterId ID of register to read from
1.2903 +@param aValue value read from register
1.2904 +
1.2905 +@return KErrNone if value was successfully stored in aValue,
1.2906 + TRegisterFlag::EInValid if value could not be read from the register,
1.2907 + TRegisterFlag::ENotSupported if the register is not supported,
1.2908 + KErrNoMemory if temporary memory could not be allocated,
1.2909 + or a return value from DRM_DebugChannel::DoReadRegisters
1.2910 +*/
1.2911 +TInt32 DRM_DebugChannel::ReadDebugRegisterValue(DThread *aThread, const TRegisterInfo aDebugRegisterId, T4ByteRegisterValue &aValue) const
1.2912 +{
1.2913 + //allocate temporary buffers to store data
1.2914 + NKern::ThreadEnterCS();
1.2915 + TUint8* id = (TUint8*)Kern::Alloc(sizeof(TRegisterInfo));
1.2916 + NKern::ThreadLeaveCS();
1.2917 + if(id == NULL)
1.2918 + {
1.2919 + return KErrNoMemory;
1.2920 + }
1.2921 + TPtr8 idPtr(id, sizeof(TRegisterInfo));
1.2922 +
1.2923 + NKern::ThreadEnterCS();
1.2924 + TUint8* value = (TUint8*)Kern::Alloc(sizeof(T4ByteRegisterValue));
1.2925 + NKern::ThreadLeaveCS();
1.2926 + if(value == NULL)
1.2927 + {
1.2928 + return KErrNoMemory;
1.2929 + }
1.2930 + TPtr8 valuePtr(value, sizeof(T4ByteRegisterValue));
1.2931 +
1.2932 + NKern::ThreadEnterCS();
1.2933 + TUint8* flag = (TUint8*)Kern::Alloc(sizeof(TUint8));
1.2934 + NKern::ThreadLeaveCS();
1.2935 + if(flag == NULL)
1.2936 + {
1.2937 + return KErrNoMemory;
1.2938 + }
1.2939 + TPtr8 flagPtr(flag, sizeof(TUint8));
1.2940 +
1.2941 + //store register id in buffer
1.2942 + idPtr.Append((TUint8*)&aDebugRegisterId, sizeof(TRegisterInfo));
1.2943 +
1.2944 + //read registers
1.2945 + TInt err = DoReadRegisters(aThread, idPtr, valuePtr, flagPtr);
1.2946 + if(err == KErrNone)
1.2947 + {
1.2948 + if(*flag == EValid)
1.2949 + {
1.2950 + //register could be read so store value
1.2951 + aValue = *(T4ByteRegisterValue*)value;
1.2952 + }
1.2953 + else
1.2954 + {
1.2955 + //register couldn't be read for some reason
1.2956 + err = *flag;
1.2957 + }
1.2958 + }
1.2959 +
1.2960 + //free memory
1.2961 + NKern::ThreadEnterCS();
1.2962 + Kern::Free(id);
1.2963 + Kern::Free(value);
1.2964 + Kern::Free(flag);
1.2965 + NKern::ThreadLeaveCS();
1.2966 +
1.2967 + return err;
1.2968 +}
1.2969 +
1.2970 +//
1.2971 +// DRM_DebugChannel::NotifyEvent
1.2972 +//
1.2973 +void DRM_DebugChannel::NotifyEvent(const TDriverEventInfo& aEventInfo)
1.2974 +{
1.2975 + LOG_EVENT_MSG("DRM_DebugChannel::NotifyEvent()");
1.2976 +
1.2977 + // Look for the relevant DTargetProcess
1.2978 + // We can find out the relevant process id from aEventInfo
1.2979 + TUint32 pid = aEventInfo.iProcessId;
1.2980 +
1.2981 + //opening handle to process
1.2982 + DProcess* targetProcess = DebugUtils::OpenProcessHandle(pid);
1.2983 +
1.2984 + if(!targetProcess)
1.2985 + {
1.2986 + LOG_EVENT_MSG("DRM_DebugChannel::NotifyEvent - process does not exist!");
1.2987 + return;
1.2988 + }
1.2989 +
1.2990 + // Are we debugging this process - decide based on iFileName
1.2991 + DCodeSeg* p = targetProcess->iCodeSeg;
1.2992 + DTargetProcess* foundProcess;
1.2993 + if (p)
1.2994 + {
1.2995 + foundProcess = TheDProcessTracker.FindProcess(*(p->iFileName));
1.2996 + }
1.2997 + else
1.2998 + {
1.2999 + // special case: may not have a code seg in some cases. in which case we tell everyone!
1.3000 + if (targetProcess->iName)
1.3001 + {
1.3002 + // copy the name of the process
1.3003 + foundProcess = TheDProcessTracker.FindProcess(*(targetProcess->iName));
1.3004 + }
1.3005 + else
1.3006 + {
1.3007 + foundProcess = NULL;
1.3008 + }
1.3009 + }
1.3010 +
1.3011 + //close the handle
1.3012 + targetProcess->Close(NULL);
1.3013 +
1.3014 + if (!foundProcess)
1.3015 + {
1.3016 + // No: just ignore this exception
1.3017 + LOG_EVENT_MSG("DRM_DebugChannel::NotifyEvent - we are not debugging this process!");
1.3018 + return;
1.3019 + }
1.3020 +
1.3021 + foundProcess->NotifyEvent(aEventInfo);
1.3022 +}
1.3023 +
1.3024 +#ifndef __LAUNCH_AS_EXTENSION__
1.3025 +DECLARE_STANDARD_LDD()
1.3026 + {
1.3027 + return new DRM_DebugDriverFactory;
1.3028 + }
1.3029 +#else
1.3030 +
1.3031 +DStopModeExtension* TheStopModeExtension = NULL;
1.3032 +
1.3033 +DECLARE_EXTENSION_LDD()
1.3034 + {
1.3035 + return new DRM_DebugDriverFactory;
1.3036 + }
1.3037 +
1.3038 +/**
1.3039 + This value is used as an initialiser for the size of the Stop-Mode Debug API's
1.3040 + default request buffer.
1.3041 + */
1.3042 +const TInt KRequestBufferSize = 0x200;
1.3043 +/**
1.3044 + This value is used as an initialiser for the size of the Stop-Mode Debug API's
1.3045 + default response buffer.
1.3046 + */
1.3047 +const TInt KResponseBufferSize = 0x1000;
1.3048 +
1.3049 +DECLARE_STANDARD_EXTENSION()
1.3050 + {
1.3051 + __KTRACE_OPT(KBOOT,Kern::Printf("Starting RM_DEBUG extension"));
1.3052 +
1.3053 + // get a reference to the DDebuggerInfo and to the DStopModeExtension
1.3054 + TSuperPage& superPage = Kern::SuperPage();
1.3055 +
1.3056 + if(!superPage.iDebuggerInfo)
1.3057 + {
1.3058 + //kdebug has not been installed so create DDebuggerInfo using our stub constructor
1.3059 + superPage.iDebuggerInfo = new DDebuggerInfo();
1.3060 + }
1.3061 +
1.3062 + if(!TheStopModeExtension)
1.3063 + {
1.3064 + TheStopModeExtension = new DStopModeExtension();
1.3065 + }
1.3066 +
1.3067 + // create the request buffer and store a reference to it
1.3068 + TTag tag;
1.3069 + tag.iTagId = EBuffersRequest;
1.3070 + tag.iType = ETagTypePointer;
1.3071 + tag.iSize = KRequestBufferSize;
1.3072 + TInt err = TheDBufferManager.CreateBuffer(tag);
1.3073 + if(KErrNone != err)
1.3074 + {
1.3075 + return KErrNone;
1.3076 + }
1.3077 +
1.3078 + // create the response buffer and store a reference to it
1.3079 + tag.iTagId = EBuffersResponse;
1.3080 + tag.iSize = KResponseBufferSize;
1.3081 + err = TheDBufferManager.CreateBuffer(tag);
1.3082 + if(KErrNone != err)
1.3083 + {
1.3084 + return KErrNone;
1.3085 + }
1.3086 + // create the debug functionality buffer and store a reference to it
1.3087 + TDebugFunctionality df;
1.3088 + TUint dfSize = df.GetStopModeFunctionalityBufSize();
1.3089 + tag.iTagId = EBuffersFunctionality;
1.3090 + tag.iSize = dfSize;
1.3091 + err = TheDBufferManager.CreateBuffer(tag);
1.3092 + if(KErrNone != err)
1.3093 + {
1.3094 + return KErrNone;
1.3095 + }
1.3096 +
1.3097 + // fill the functionality buffer with the functionality data and store it in
1.3098 + // the super page
1.3099 + TPtr8 dfBlockPtr((TUint8*)tag.iValue, dfSize);
1.3100 + if(!df.GetStopModeFunctionality(dfBlockPtr))
1.3101 + {
1.3102 + return KErrNone;
1.3103 + }
1.3104 + TheStopModeExtension->iFunctionalityBlock = (DFunctionalityBlock*)tag.iValue;
1.3105 +
1.3106 + DStopModeExtension::Install(TheStopModeExtension);
1.3107 +
1.3108 + return KErrNone;
1.3109 + }
1.3110 +
1.3111 +/**
1.3112 + * This stub constructor is intended to be used in the case where the old deprecated
1.3113 + * stop mode api, kdebug, is not in place. It will initialise all values to NULL except
1.3114 + * the pointer to the new stop mode api extension. This allows the new stop mode solution
1.3115 + * to both co-exist and exist independantly of the existing one *
1.3116 + */
1.3117 +DDebuggerInfo::DDebuggerInfo():
1.3118 + iObjectOffsetTable(NULL),
1.3119 + iObjectOffsetTableCount(NULL),
1.3120 + iThreadContextTable(NULL),
1.3121 + iStopModeExtension(new DStopModeExtension()),
1.3122 + iContainers(NULL),
1.3123 + iCodeSegLock(NULL),
1.3124 + iCodeSegGlobalList(NULL),
1.3125 + iScheduler(NULL),
1.3126 + iShadowPages(NULL),
1.3127 + iShadowPageCount(0),
1.3128 + iCurrentThread(NULL),
1.3129 + iEventMask(),
1.3130 + iEventHandlerBreakpoint(0),
1.3131 + iMemModelObjectOffsetTable(NULL),
1.3132 + iMemModelObjectOffsetTableCount(0)
1.3133 + {
1.3134 + }
1.3135 +
1.3136 +/**
1.3137 + * Installs the stop-mode debugger extension
1.3138 + * Make the stop-mode API visible to a JTAG debugger, by publishing its
1.3139 + * existence in the superpage
1.3140 +*/
1.3141 +void DStopModeExtension::Install(DStopModeExtension* aExt)
1.3142 + {
1.3143 + Kern::SuperPage().iDebuggerInfo->iStopModeExtension = aExt;
1.3144 + }
1.3145 +
1.3146 +#endif
1.3147 +
1.3148 +/**
1.3149 +Helper function
1.3150 +
1.3151 +Allocates memory in current thread with a max length the same as aSrcDes. If
1.3152 +aReadFromClient is true (as it is by default) then the data from aSrdDes is
1.3153 +copied into the allocated aDestDes buffer.
1.3154 +
1.3155 +Use of this function should be followed at a later time by a call such as
1.3156 +Kern::Free(aDestDes.Ptr())
1.3157 +
1.3158 +@param aThread pointer to thread to read data from
1.3159 +@param aSrcDes descriptor in aThread to read data from
1.3160 +@param aDestDes location to read data to. Memory is allocated at this location,
1.3161 + if memory is already allocated at this location then the function will
1.3162 + return KErrArgument
1.3163 +@param aReadFromClient if false then data is not actually read from the
1.3164 + client, the memory is simply allocated
1.3165 +@param aOffest offset into aSrcDes to start reading from. Default is 0.
1.3166 +
1.3167 +@return KErrNone if there were no problems,
1.3168 + KErrArgument if aDestDes.Ptr() != NULL or aSrcDes has max length 0,
1.3169 + KErrNoMemory if could not allocate memory,
1.3170 + or one of the other system wide error codes
1.3171 +*/
1.3172 +TInt DRM_DebugChannel::AllocAndReadDes(DThread *aThread, const TDesC8& aSrcDes, TPtr8& aDestDes, const TBool aReadFromClient, const TUint aOffset) const
1.3173 + {
1.3174 +
1.3175 + //check thread is not null
1.3176 + if(!aThread)
1.3177 + {
1.3178 + return KErrArgument;
1.3179 + }
1.3180 +
1.3181 + //check aDestDes is empty
1.3182 + if(aDestDes.Ptr() != NULL)
1.3183 + {
1.3184 + return KErrArgument;
1.3185 + }
1.3186 +
1.3187 + //get the source descriptor's max length and exit if 0
1.3188 + TUint srcMaxLength = Kern::ThreadGetDesMaxLength(aThread, &aSrcDes);
1.3189 + if(srcMaxLength == 0)
1.3190 + {
1.3191 + return KErrNone;
1.3192 + }
1.3193 +
1.3194 + //allocate memory and return if none available
1.3195 + NKern::ThreadEnterCS();
1.3196 + TUint8 *destPtr = (TUint8*)Kern::Alloc(srcMaxLength);
1.3197 + NKern::ThreadLeaveCS();
1.3198 + if (!destPtr)
1.3199 + {
1.3200 + return KErrNoMemory;
1.3201 + }
1.3202 +
1.3203 + //point the TPtr8 at the target memory
1.3204 + aDestDes.Set(destPtr, srcMaxLength, srcMaxLength);
1.3205 +
1.3206 + if(aReadFromClient)
1.3207 + {
1.3208 + //read data from the client thread and return status code
1.3209 + return Kern::ThreadDesRead(aThread, &aSrcDes, aDestDes, aOffset);
1.3210 + }
1.3211 + else
1.3212 + {
1.3213 + return KErrNone;
1.3214 + }
1.3215 + }
1.3216 +
1.3217 +/**
1.3218 +Helper function to extract a TRegisterInfo value from a descriptor containing
1.3219 +binary data.
1.3220 +
1.3221 +@param aRegisterIds descriptor containing register IDs
1.3222 +@param aOffset offset in bytes into the descriptor to start reading data from.
1.3223 + If this value is not a multiple of sizeof(TRegisterInfo) then a
1.3224 + KErrArgument error is returned.
1.3225 +@param aValue will contain the returned value
1.3226 +
1.3227 +@return KErrNone if aValue was set correctly, KErrArgument if bad arguments
1.3228 + were passed in
1.3229 +*/
1.3230 +TInt DRM_DebugChannel::GetTRegisterInfo(const TDesC8 &aRegisterIds, const TUint aIndex, TRegisterInfo &aValue) const
1.3231 + {
1.3232 + TUint length = aRegisterIds.Length();
1.3233 +
1.3234 + TUint size = sizeof(TRegisterInfo);
1.3235 +
1.3236 + //check that not trying to read past end of descriptor
1.3237 + if((aIndex + 1) * size > length)
1.3238 + return KErrArgument;
1.3239 +
1.3240 + //get pointer to descriptor's data
1.3241 + const TUint8 *dataPtr = aRegisterIds.Ptr();
1.3242 + const TRegisterInfo *registerId = reinterpret_cast<const TRegisterInfo*>(dataPtr + (aIndex * size));
1.3243 +
1.3244 + aValue = *registerId;
1.3245 +
1.3246 + return KErrNone;
1.3247 + }
1.3248 +
1.3249 +/**
1.3250 +Helper function to get the kernel register ID of the TRegisterInfo defined register.
1.3251 +
1.3252 +@param aDebugRegister the debug register ID to return the kernel ID for
1.3253 +@param aKernelRegister corresponding value of register aDebugRegister
1.3254 +
1.3255 +@return KErrNone if translation occurred without problems
1.3256 + KErrNotSupported if aDebugRegister is not supported by the kernel
1.3257 +*/
1.3258 +TInt DRM_DebugChannel::GetKernelRegisterId(const TRegisterInfo aDebugRegister, TArmReg& aKernelRegister) const
1.3259 + {
1.3260 + if(Register::IsCoreReg(aDebugRegister))
1.3261 + {
1.3262 + TUint id = Register::GetCoreRegId(aDebugRegister);
1.3263 + //first 17 registers match the first 17 kernel registers
1.3264 + if(id < 17)
1.3265 + {
1.3266 + aKernelRegister = id;
1.3267 + }
1.3268 + else
1.3269 + {
1.3270 + return KErrNotSupported;
1.3271 + }
1.3272 + }
1.3273 + else if(Register::IsCoproReg(aDebugRegister))
1.3274 + {
1.3275 + TUint32 crn = Register::GetCRn(aDebugRegister);
1.3276 + TUint32 crm = Register::GetCRm(aDebugRegister);
1.3277 + TUint32 opcode1 = Register::GetOpcode1(aDebugRegister);
1.3278 + TUint32 opcode2 = Register::GetOpcode2(aDebugRegister);
1.3279 + TUint32 coproNum = Register::GetCoproNum(aDebugRegister);
1.3280 +
1.3281 + //each coprocessor register has potentially different characteristics
1.3282 + //so need to identify each individually
1.3283 +
1.3284 + //this is the DACR, the ARM ARM specifies that the CRn and the
1.3285 + //Opcodes are not relevant, section B3-24, point 3.7.3
1.3286 + if((coproNum == 15) && (crm == 3))
1.3287 + {
1.3288 + aKernelRegister = EArmDacr;
1.3289 + }
1.3290 + else
1.3291 + {
1.3292 + return KErrNotSupported;
1.3293 + }
1.3294 + }
1.3295 + else // might be supported at a later date
1.3296 + {
1.3297 + return KErrNotSupported;
1.3298 + }
1.3299 +
1.3300 + return KErrNone;
1.3301 + }
1.3302 +
1.3303 +/**
1.3304 +Helper function to get the debug register ID of the kernel defined register.
1.3305 +
1.3306 +@param aKernelRegister the kernel register ID to return the debug ID for
1.3307 +@param aDebugRegister corresponding value of register aKernelRegister
1.3308 +
1.3309 +@return KErrNone if translation occured without problems
1.3310 + KErrNotSupported if aKernelRegister is not supported by the debug
1.3311 + security server
1.3312 +*/
1.3313 +TInt DRM_DebugChannel::GetDebugRegisterId(const TArmReg aKernelRegister, TRegisterInfo &aDebugRegister) const
1.3314 + {
1.3315 +
1.3316 + // registers 0 - 15 and the CPSR share the same values as with the debug enums
1.3317 + if(aKernelRegister < 17)
1.3318 + {
1.3319 + TUint32 id = aKernelRegister;
1.3320 + aDebugRegister = id << 8;
1.3321 + }
1.3322 + //the DACR value is special and corresponds to EDF_Register_DACR
1.3323 + else if(aKernelRegister == EArmDacr)
1.3324 + {
1.3325 + aDebugRegister = 0x00300f01;
1.3326 + }
1.3327 + // must be an unsupported register, return an error as such
1.3328 + else
1.3329 + {
1.3330 + return KErrNotSupported;
1.3331 + }
1.3332 +
1.3333 + //found a supported register so return KErrNone
1.3334 + return KErrNone;
1.3335 + }
1.3336 +
1.3337 +/**
1.3338 +Helper function to find out whether the aIndex flag is set. This is equivalent
1.3339 +to the aIndex bit of aFlags being non-zero.
1.3340 +
1.3341 +@param aFlags set of flags
1.3342 +@param aIndex offset into aFlags to get flag from
1.3343 +
1.3344 +@return ETrue if bit is set, EFalse if not
1.3345 +*/
1.3346 +TBool DRM_DebugChannel::GetFlagAtOffset(const TUint32 aFlags, const TArmReg aIndex) const
1.3347 + {
1.3348 + return ( aFlags & (1<<aIndex) ) ? ETrue : EFalse;
1.3349 + }
1.3350 +
1.3351 +/* Register the attachment of a debug agent to a process to be debugged
1.3352 + *
1.3353 + * @param a1 - TDes8 target process name
1.3354 + * @param a2 - &TUint64 - Debug Agent Id
1.3355 + *
1.3356 + * @return - KErrNone if successful. KErrArgument if the filepath is not a valid size.
1.3357 + * KErrOutOfMemory if there is insufficient memory. Or one of the other system wide error codes
1.3358 + * if appropriate.
1.3359 + */
1.3360 +TInt DRM_DebugChannel::AttachProcess(TAny* a1, TAny* a2)
1.3361 + {
1.3362 + LOG_MSG("DRM_DebugChannel::AttachProcess()");
1.3363 +
1.3364 + // Validate the supplied TDes8 target process name in a1
1.3365 + TInt length, maxLength;
1.3366 + TUint8* aPtr;
1.3367 +
1.3368 + TInt err = Kern::ThreadGetDesInfo(iClientThread,\
1.3369 + a1,\
1.3370 + length,\
1.3371 + maxLength,\
1.3372 + aPtr,\
1.3373 + EFalse);
1.3374 + if (err != KErrNone)
1.3375 + {
1.3376 + // Could not read the descriptor information
1.3377 + return err;
1.3378 + }
1.3379 +
1.3380 + // Check the processname is a valid size for a filepath
1.3381 + if (length < 1 || length >= KMaxPath)
1.3382 + {
1.3383 + return KErrArgument;
1.3384 + }
1.3385 +
1.3386 + if (maxLength < 1 || maxLength >= KMaxPath)
1.3387 + {
1.3388 + return KErrArgument;
1.3389 + }
1.3390 +
1.3391 + // Allocate space to store the target process name in a kernel-side TPtr8
1.3392 + NKern::ThreadEnterCS();
1.3393 + TUint8* buffer = (TUint8*)Kern::AllocZ(length);
1.3394 + NKern::ThreadLeaveCS();
1.3395 + if (buffer==NULL)
1.3396 + {
1.3397 + // Out of memory
1.3398 + return KErrNoMemory;
1.3399 + }
1.3400 +
1.3401 + // A temporary descriptor to store the target process name
1.3402 + TPtr8 targetProcessName(buffer,length,length);
1.3403 +
1.3404 + // Read the user-side data into targetProcessName
1.3405 + err = Kern::ThreadDesRead(iClientThread,a1,targetProcessName,0,KChunkShiftBy0);
1.3406 + if (err != KErrNone)
1.3407 + {
1.3408 + // Could not read the user-side descriptor containing the target process name
1.3409 + NKern::ThreadEnterCS();
1.3410 + Kern::Free(buffer);
1.3411 + NKern::ThreadLeaveCS();
1.3412 +
1.3413 + return err;
1.3414 + }
1.3415 +
1.3416 + // Obtain the Debug Agent Id
1.3417 + TUint64 debugAgentId = 0;
1.3418 +
1.3419 + err = Kern::ThreadRawRead(iClientThread,a2,&debugAgentId,sizeof(debugAgentId));
1.3420 + if (err != KErrNone)
1.3421 + {
1.3422 + // Something bad happened so free the memory and return
1.3423 + NKern::ThreadEnterCS();
1.3424 + Kern::Free(buffer);
1.3425 + NKern::ThreadLeaveCS();
1.3426 + return err;
1.3427 + }
1.3428 +
1.3429 + // Add the target process to our list of tracked processes
1.3430 + err = TheDProcessTracker.AttachProcess(targetProcessName, debugAgentId);
1.3431 +
1.3432 + // Free the kernel-side memory containing targetProcessName data
1.3433 + NKern::ThreadEnterCS();
1.3434 + Kern::Free(buffer);
1.3435 + NKern::ThreadLeaveCS();
1.3436 +
1.3437 + return err;
1.3438 + }
1.3439 +
1.3440 +/* Register the detachment of a debug agent to a process to be debugged.
1.3441 + *
1.3442 + * @param - a1 TDes8 target process name in a1
1.3443 + * @param a2 - &TUint64 - Debug Agent Id
1.3444 + *
1.3445 + * @return - KErrNone if successful. KErrArgument if the filepath is not a valid size.
1.3446 + * KErrOutOfMemory if there is insufficient memory. Or one of the other system wide error codes
1.3447 + * if appropriate.
1.3448 + */
1.3449 +TInt DRM_DebugChannel::DetachProcess(TAny* a1, TAny* a2)
1.3450 + {
1.3451 + // Validate the supplied TDes8 target process name in a1
1.3452 + TInt length, maxLength;
1.3453 + TUint8* aPtr;
1.3454 +
1.3455 + TInt err = Kern::ThreadGetDesInfo(iClientThread,\
1.3456 + a1,\
1.3457 + length,\
1.3458 + maxLength,\
1.3459 + aPtr,\
1.3460 + EFalse);
1.3461 + if (err != KErrNone)
1.3462 + {
1.3463 + return err;
1.3464 + }
1.3465 +
1.3466 + if (length < 1 || length >= KMaxPath)
1.3467 + {
1.3468 + return KErrArgument;
1.3469 + }
1.3470 +
1.3471 + if (maxLength < 1 || maxLength >= KMaxPath)
1.3472 + {
1.3473 + return KErrArgument;
1.3474 + }
1.3475 +
1.3476 + // Allocate space to store the target process name in a kernel-side TPtr8
1.3477 + NKern::ThreadEnterCS();
1.3478 + TUint8* buffer = (TUint8*)Kern::AllocZ(length);
1.3479 + NKern::ThreadLeaveCS();
1.3480 + if (buffer==NULL)
1.3481 + {
1.3482 + // Out of memory
1.3483 + return KErrNoMemory;
1.3484 + }
1.3485 +
1.3486 + TPtr8 targetProcessName(buffer,length,length);
1.3487 +
1.3488 + // Read the user-side data into targetProcessName
1.3489 + err = Kern::ThreadDesRead(iClientThread,a1,targetProcessName,0,KChunkShiftBy0);
1.3490 + if (err != KErrNone)
1.3491 + {
1.3492 + // Something bad happened so free the memory and return
1.3493 + NKern::ThreadEnterCS();
1.3494 + Kern::Free(buffer);
1.3495 + NKern::ThreadLeaveCS();
1.3496 +
1.3497 + return err;
1.3498 + }
1.3499 +
1.3500 + // Obtain the AgentId
1.3501 + TUint64 debugAgentId = 0;
1.3502 +
1.3503 + err = Kern::ThreadRawRead(iClientThread,a2,&debugAgentId,sizeof(debugAgentId));
1.3504 + if (err != KErrNone)
1.3505 + {
1.3506 + // Something bad happened so free the memory and return
1.3507 + NKern::ThreadEnterCS();
1.3508 + Kern::Free(buffer);
1.3509 + NKern::ThreadLeaveCS();
1.3510 +
1.3511 + return err;
1.3512 + }
1.3513 +
1.3514 + // Remove the process from our list of tracked processes
1.3515 + err = TheDProcessTracker.DetachProcess(targetProcessName, debugAgentId);
1.3516 +
1.3517 + // Free the kernel-side memory containing targetProcessName data
1.3518 + NKern::ThreadEnterCS();
1.3519 + Kern::Free(buffer);
1.3520 + NKern::ThreadLeaveCS();
1.3521 +
1.3522 + return err;
1.3523 + }
1.3524 +
1.3525 +/* Register the detachment of a debug agent from all processes being debugged.
1.3526 + *
1.3527 + * @param - a1 - &TUint64 Debug Agent Id.
1.3528 + * @return - KErrNone if successful. One of the system-wide error codes otherwise.
1.3529 + */
1.3530 +TInt DRM_DebugChannel::DetachAgent(TAny* a1, TAny* a2)
1.3531 + {
1.3532 + // Obtain the AgentId
1.3533 + TUint64 debugAgentId = 0;
1.3534 +
1.3535 + TInt err = Kern::ThreadRawRead(iClientThread,a1,&debugAgentId,sizeof(debugAgentId));
1.3536 + if (err != KErrNone)
1.3537 + {
1.3538 + return err;
1.3539 + }
1.3540 +
1.3541 + // Remove the process from our list of tracked processes
1.3542 + return TheDProcessTracker.DetachAgent(debugAgentId);
1.3543 + }
1.3544 +
1.3545 +/* Set the action associated with a particular kernel event for a given agent and target process
1.3546 + *
1.3547 + * @param - a1 TDes8 target process name in a1
1.3548 + * @param - a2 &TRM_DebugEventActionInfo
1.3549 + * @return - KErrNone if successful. KErrArgument if the filepath is an invalid size. Or one of
1.3550 + * the other system wide error codes if appropriate.
1.3551 + */
1.3552 +TInt DRM_DebugChannel::SetEventAction(TAny* a1, TAny* a2)
1.3553 + {
1.3554 + // Validate the supplied TDes8 target process name in a1
1.3555 + TInt length, maxLength;
1.3556 + TUint8* aPtr;
1.3557 +
1.3558 + TInt err = Kern::ThreadGetDesInfo(iClientThread,\
1.3559 + a1,\
1.3560 + length,\
1.3561 + maxLength,\
1.3562 + aPtr,\
1.3563 + EFalse);
1.3564 + if (err != KErrNone)
1.3565 + {
1.3566 + return err;
1.3567 + }
1.3568 +
1.3569 + if (length < 1 || length >= KMaxPath)
1.3570 + {
1.3571 + return KErrArgument;
1.3572 + }
1.3573 +
1.3574 + if (maxLength < 1 || maxLength >= KMaxPath)
1.3575 + {
1.3576 + return KErrArgument;
1.3577 + }
1.3578 +
1.3579 + // Allocate space to store the target process name in a kernelspace TPtr8
1.3580 + NKern::ThreadEnterCS();
1.3581 + TUint8* buffer = (TUint8*)Kern::AllocZ(length);
1.3582 + NKern::ThreadLeaveCS();
1.3583 + if (buffer==NULL)
1.3584 + {
1.3585 + // Out of memory
1.3586 + return KErrNoMemory;
1.3587 + }
1.3588 + TPtr8 targetProcessName(buffer,length,length);
1.3589 +
1.3590 + // Read the user-side data into targetProcessName
1.3591 + err = Kern::ThreadDesRead(iClientThread,a1,targetProcessName,0,KChunkShiftBy0);
1.3592 + if (err != KErrNone)
1.3593 + {
1.3594 + // Something bad happened so free the memory and return
1.3595 + NKern::ThreadEnterCS();
1.3596 + Kern::Free(buffer);
1.3597 + NKern::ThreadLeaveCS();
1.3598 +
1.3599 + return err;
1.3600 + }
1.3601 +
1.3602 + // Read the Event and Action from the user-side
1.3603 + TRM_DebugEventActionInfo info(0,0,0);
1.3604 +
1.3605 + err = Kern::ThreadRawRead(iClientThread, a2, &info, sizeof(info));
1.3606 + if (err != KErrNone)
1.3607 + {
1.3608 + // Could not read event action data from the user-side
1.3609 +
1.3610 + // Free memory used for targetProcessName
1.3611 + NKern::ThreadEnterCS();
1.3612 + Kern::Free(buffer);
1.3613 + NKern::ThreadLeaveCS();
1.3614 +
1.3615 + return err;
1.3616 + }
1.3617 +
1.3618 + // Find the target process
1.3619 + DTargetProcess* pProcess = TheDProcessTracker.FindProcess(targetProcessName);
1.3620 + if (pProcess == NULL)
1.3621 + {
1.3622 + // Could not find this process
1.3623 +
1.3624 + // Free memory used for targetProcessName
1.3625 + NKern::ThreadEnterCS();
1.3626 + Kern::Free(buffer);
1.3627 + NKern::ThreadLeaveCS();
1.3628 +
1.3629 + return KErrArgument;
1.3630 + }
1.3631 +
1.3632 + TUint64 debugAgentId = info.iAgentId;
1.3633 +
1.3634 + // Find the agent
1.3635 + DDebugAgent* debugAgent = pProcess->Agent(debugAgentId);
1.3636 + if (debugAgent == NULL)
1.3637 + {
1.3638 + // Bad agent means there is no tracking agent
1.3639 + LOG_MSG2("Cannot locate debug agent with pid 0x%0x16lx",info.iAgentId);
1.3640 +
1.3641 + // Free memory used for targetProcessName
1.3642 + NKern::ThreadEnterCS();
1.3643 + Kern::Free(buffer);
1.3644 + NKern::ThreadLeaveCS();
1.3645 +
1.3646 + return KErrGeneral;
1.3647 + }
1.3648 +
1.3649 + // Set the event action
1.3650 + debugAgent->SetEventAction((TEventType)info.iEvent,(TKernelEventAction)info.iAction);
1.3651 +
1.3652 + // Free memory used for targetProcessName
1.3653 + NKern::ThreadEnterCS();
1.3654 + Kern::Free(buffer);
1.3655 + NKern::ThreadLeaveCS();
1.3656 +
1.3657 + return KErrNone;
1.3658 + }
1.3659 +
1.3660 +TInt DRM_DebugChannel::Step(const TUint32 aThreadId, const TUint32 aNumSteps)
1.3661 + {
1.3662 + LOG_MSG3("DRM_DebugChannel::Step(aThreadId = 0x%08x, aNumSteps = 0x%08x)\n",aThreadId,aNumSteps);
1.3663 +
1.3664 + DThread* thread = DebugUtils::OpenThreadHandle(aThreadId);
1.3665 +
1.3666 + if (thread == NULL)
1.3667 + {
1.3668 + // The thread terminated before we could open it.
1.3669 + LOG_MSG2("DRM_DebugChannel::Step - Could not open thread %u", aThreadId);
1.3670 +
1.3671 + return KErrArgument;
1.3672 + }
1.3673 +
1.3674 + // We simply repeat this for desired number of steps
1.3675 + TInt err = KErrNone;
1.3676 +
1.3677 + // Need to step from the current location for 'n' steps
1.3678 + TUint32 startAddress;
1.3679 +
1.3680 + // We always step from the current PC.
1.3681 + err = ReadKernelRegisterValue(thread, PC_REGISTER, startAddress);
1.3682 + if(err != KErrNone)
1.3683 + {
1.3684 + LOG_MSG2("DRM_DebugChannel::Step - Could not read the PC: %d", err);
1.3685 +
1.3686 + // Close the handle
1.3687 + thread->Close(NULL);
1.3688 +
1.3689 + return err;
1.3690 + }
1.3691 +
1.3692 + err = DoStepRange(thread, startAddress, startAddress, ETrue, EFalse, aNumSteps, ETrue);
1.3693 +
1.3694 + if (err != KErrNone)
1.3695 + {
1.3696 + // There was a problem, return straightaway
1.3697 + LOG_MSG("DRM_DebugChannel::Step - failed to step");
1.3698 + }
1.3699 +
1.3700 + // Close the handle
1.3701 + thread->Close(NULL);
1.3702 +
1.3703 + return err;
1.3704 + }
1.3705 +
1.3706 +TInt DRM_DebugChannel::KillProcess(const TUint32 aProcessId, const TInt aReason)
1.3707 + {
1.3708 + LOG_MSG3("DRM_DebugChannel::KillProcess(aProcessId = 0x%08x, aReason = 0x%08x)\n",aProcessId,aReason);
1.3709 +
1.3710 + DProcess* process = DebugUtils::OpenProcessHandle(aProcessId);
1.3711 +
1.3712 + if (process == NULL)
1.3713 + {
1.3714 + // The process terminated before we could open it to kill it ourselves.
1.3715 + LOG_MSG2("DRM_DebugChannel::KillProcess - Could not open process %u", aProcessId);
1.3716 +
1.3717 + return KErrArgument;
1.3718 + }
1.3719 +
1.3720 + TInt err = KErrNone;
1.3721 +
1.3722 + DebugSupport::TerminateProcess(process,aReason);
1.3723 +
1.3724 + // Close the handle
1.3725 + process->Close(NULL);
1.3726 +
1.3727 + return err;
1.3728 + }
1.3729 +
1.3730 +/* Security critical - this checks whether the specified process is debuggable or not
1.3731 + *
1.3732 + * @param aProcessId - The process id of the process to check
1.3733 + * @return KErrNone if debuggable, KErrPermissionDenied if not debuggable.
1.3734 + */
1.3735 +TInt DRM_DebugChannel::IsDebuggable(const TUint32 aProcessId)
1.3736 + {
1.3737 + /* In order to ensure that only processes which are debuggable
1.3738 + * can be debugged, this function enables the security server
1.3739 + * to read the DProcess.iDebugAttributes field and ensure
1.3740 + * the process was created from a debuggable executable.
1.3741 + */
1.3742 + LOG_MSG2("DRM_DebugChannel::IsDebuggable(aProcessId 0x%08x)\n",aProcessId);
1.3743 +
1.3744 + TInt err = KErrPermissionDenied;
1.3745 +
1.3746 + DProcess* process = DebugUtils::OpenProcessHandle(aProcessId);
1.3747 + if (process)
1.3748 + {
1.3749 + if (process->iDebugAttributes & TProcessCreateInfo::EDebugAllowed)
1.3750 + {
1.3751 + // Yes this process exists and is debuggable
1.3752 + err = KErrNone;
1.3753 + }
1.3754 + process->Close(NULL);
1.3755 + }
1.3756 +
1.3757 + if (err == KErrNone)
1.3758 + {
1.3759 + LOG_MSG2("DRM_DebugChannel::IsDebuggable(aProcessId 0x%08x) - Yes it is debuggable\n",aProcessId);
1.3760 + }
1.3761 +
1.3762 + return err;
1.3763 + }