kerneltest/e32utils/d_exc/minkda.cpp
changeset 0 a41df078684a
equal deleted inserted replaced
-1:000000000000 0:a41df078684a
       
     1 // Copyright (c) 2002-2009 Nokia Corporation and/or its subsidiary(-ies).
       
     2 // All rights reserved.
       
     3 // This component and the accompanying materials are made available
       
     4 // under the terms of the License "Eclipse Public License v1.0"
       
     5 // which accompanies this distribution, and is available
       
     6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     7 //
       
     8 // Initial Contributors:
       
     9 // Nokia Corporation - initial contribution.
       
    10 //
       
    11 // Contributors:
       
    12 //
       
    13 // Description:
       
    14 // e32utils\d_exc\minkda.cpp
       
    15 // Example of LDD implementing a minimal kernel-side debug agent.
       
    16 // 
       
    17 //
       
    18 
       
    19 #include <kernel/kern_priv.h>
       
    20 #ifdef __MARM__
       
    21 #include <arm.h>
       
    22 #endif
       
    23 #include "minkda.h"
       
    24 
       
    25 // Uncomment following lines to enable traces in UREL builds
       
    26 //#undef __KTRACE_OPT
       
    27 //#define __KTRACE_OPT(c,b) b
       
    28 
       
    29 #ifdef _DEBUG
       
    30 // Panic category used for internal errors
       
    31 static const char KFault[] = "MINKDA-ERROR, line:";
       
    32 #endif
       
    33 
       
    34 // Panic category and codes used when detecting programming error in
       
    35 // user-side clients.
       
    36 _LIT(KClientPanic, "MINKDA");
       
    37 enum TPanic
       
    38 	{
       
    39 	EPanicTrapWhileRequestPending,
       
    40 	EPanicNoCrashedThread,
       
    41 	EPanicUnsupportedRequest,
       
    42 	};
       
    43 
       
    44 // As this LDD allows to bypass platform security, we need to restrict
       
    45 // access to a few trusted clients.
       
    46 const TUint32 KDexecSid = 0x101F7770;
       
    47 
       
    48 //////////////////////////////////////////////////////////////////////////////
       
    49 
       
    50 //
       
    51 // Callback invoked on thread panic/exception and associated state.
       
    52 //
       
    53 
       
    54 class DCrashHandler : public DKernelEventHandler
       
    55 	{
       
    56 public:
       
    57 	// construction & destruction
       
    58 	inline DCrashHandler();
       
    59 	TInt Create(DLogicalDevice* aDevice);
       
    60 	~DCrashHandler();
       
    61 public:
       
    62 	void Trap(TRequestStatus* aRs, TAny* aCrashInfo);
       
    63 	void CancelTrap();
       
    64 	void KillCrashedThread();
       
    65 private:
       
    66 	static TUint EventHandler(TKernelEvent aEvent, TAny* a1, TAny* a2, TAny* aThis);
       
    67 	void HandleCrash(TAny* aContext);
       
    68 	void GetCpuExcInfo(const TAny* aContext, TDbgCpuExcInfo& aInfo);
       
    69 private:
       
    70 	DMutex* iHandlerMutex;		// serialise access to crash handler
       
    71 	NFastSemaphore iSuspendSem; // for suspending crashed thread
       
    72 	DMutex* iDataMutex;			// serialise access to following members
       
    73 	DThread* iClient;			// client to signal on crash or NULL
       
    74 	TRequestStatus* iTrapRq;	// signalled on crash (NULL if none)
       
    75 	TAny* iCrashInfo;			// user-side buffer filled when crash trapped
       
    76 	DThread* iCrashedThread;	// thread which took exception (NULL if none)
       
    77 	DLogicalDevice* iDevice;	// open reference to LDD for avoiding lifetime issues
       
    78 	};
       
    79 
       
    80 inline DCrashHandler::DCrashHandler()
       
    81 	: DKernelEventHandler(EventHandler, this)
       
    82 	{
       
    83 	}
       
    84 
       
    85 //
       
    86 // second-phase c'tor.  Called in thread critical section.
       
    87 //
       
    88 
       
    89 TInt DCrashHandler::Create(DLogicalDevice* aDevice)
       
    90 	{
       
    91 	TInt r;
       
    92 	r = aDevice->Open();
       
    93 	if (r != KErrNone)
       
    94 		return r;
       
    95 	iDevice = aDevice;
       
    96 	_LIT(KHandlerMutexName, "CtHandlerMutex");
       
    97 	r = Kern::MutexCreate(iHandlerMutex, KHandlerMutexName, KMutexOrdDebug);
       
    98 	if (r != KErrNone)
       
    99 		return r;
       
   100 	_LIT(KDataMutexName, "CtDataMutex");
       
   101 	r = Kern::MutexCreate(iDataMutex, KDataMutexName, KMutexOrdDebug-1);
       
   102 	if (r != KErrNone)
       
   103 		return r;
       
   104 	return Add();
       
   105 	}
       
   106 
       
   107 
       
   108 //
       
   109 // Called when reference count reaches zero.  At that point no threads
       
   110 // are in the handler anymore and the handler has been removed from
       
   111 // the queue.
       
   112 //
       
   113 
       
   114 DCrashHandler::~DCrashHandler()
       
   115 	{
       
   116 	__KTRACE_OPT(KDEBUGGER, Kern::Printf("DCrashHandler::~DCrashHandler"));
       
   117 	if (iDataMutex)
       
   118 		iDataMutex->Close(NULL);
       
   119 	if (iHandlerMutex)
       
   120 		iHandlerMutex->Close(NULL);
       
   121 	if (iDevice)
       
   122 		iDevice->Close(NULL);
       
   123 	}
       
   124 
       
   125 inline TBool TookException(const DThread* aThread)
       
   126 	{
       
   127     return aThread->iExitType == EExitPanic && 
       
   128 			aThread->iExitReason == ECausedException && 
       
   129 			aThread->iExitCategory == KLitKernExec;
       
   130 	}
       
   131 
       
   132 //
       
   133 // Called by kernel when various kinds of events occur.  In thread critical
       
   134 // section.
       
   135 //
       
   136 
       
   137 TUint DCrashHandler::EventHandler(TKernelEvent aEvent, TAny* a1, TAny* /*a2*/, TAny* aThis)
       
   138 	{
       
   139 	DThread* pC = &Kern::CurrentThread();
       
   140 	switch (aEvent)
       
   141 		{
       
   142 	case EEventHwExc:
       
   143 		((DCrashHandler*)aThis)->HandleCrash(a1);
       
   144 		break;
       
   145 	case EEventKillThread:
       
   146 		if (pC->iExitType == EExitPanic && ! TookException(pC))
       
   147 			((DCrashHandler*)aThis)->HandleCrash(NULL);
       
   148 		break;
       
   149 	default:
       
   150 		// ignore other events
       
   151 		break;
       
   152 		}
       
   153 	return ERunNext;
       
   154 	}
       
   155 
       
   156 //
       
   157 // Called when an exception or panic occurs in context of thread which
       
   158 // took the exception/panicked.  In thread critical section.
       
   159 //
       
   160 
       
   161 void DCrashHandler::HandleCrash(TAny* aContext)
       
   162 	{
       
   163 	DThread* pC = &Kern::CurrentThread();
       
   164 	__KTRACE_OPT(KDEBUGGER, Kern::Printf("HandleCrash context=0x%08X thread=%O", aContext, pC));
       
   165 
       
   166 	// Quick exit if crashed thread is debugger (i.e. client thread
       
   167 	// which issued trap request).
       
   168 	if (pC == iClient)
       
   169 		{
       
   170 		__KTRACE_OPT(KDEBUGGER, Kern::Printf("ignoring debugger crash"));
       
   171 		return;
       
   172 		}
       
   173 
       
   174 	// Set realtime state to off to allow us to write to possibly paged debugger thread.  This is
       
   175 	// reasonable as this thread has already crashed.
       
   176 	Kern::SetRealtimeState(ERealtimeStateOff);
       
   177 
       
   178 	// Ensure that, at any time, at most one thread executes the following
       
   179 	// code.  This simplifies user-side API.
       
   180 	Kern::MutexWait(*iHandlerMutex);
       
   181 	__ASSERT_DEBUG(iCrashedThread == NULL, Kern::Fault(KFault, __LINE__));
       
   182 
       
   183 	// If there is a pending trap request, store basic information
       
   184 	// about the panic/exception in user-supplied buffer and
       
   185 	// freeze the crashed thread so it can be inspected.
       
   186 
       
   187 	Kern::MutexWait(*iDataMutex);
       
   188 	if (iTrapRq != NULL)
       
   189 		{
       
   190 		iCrashedThread = pC;
       
   191 		iSuspendSem.iOwningThread = &(iCrashedThread->iNThread);
       
   192 
       
   193 		TDbgCrashInfo info;
       
   194 		info.iTid = iCrashedThread->iId;
       
   195 		if (aContext)
       
   196 			{
       
   197 			GetCpuExcInfo(aContext, info.iCpu);
       
   198 			info.iType = TDbgCrashInfo::EException;
       
   199 			}
       
   200 		else
       
   201 			info.iType = TDbgCrashInfo::EPanic;
       
   202 		TInt r = Kern::ThreadRawWrite(iClient, iCrashInfo, &info, sizeof(info));
       
   203 		Kern::RequestComplete(iClient, iTrapRq, r);
       
   204 		iClient = NULL;
       
   205 		}
       
   206 	Kern::MutexSignal(*iDataMutex);
       
   207 
       
   208 	if (iCrashedThread)
       
   209 		{
       
   210 		__KTRACE_OPT(KDEBUGGER, Kern::Printf("freezing crashed thread"));
       
   211 		NKern::FSWait(&(iSuspendSem));
       
   212 		__KTRACE_OPT(KDEBUGGER, Kern::Printf("resuming crashed thread"));
       
   213 		Kern::MutexWait(*iDataMutex);
       
   214 		// Must protect in case a cancel executes concurrently.
       
   215 		iCrashedThread = NULL;
       
   216 		Kern::MutexSignal(*iDataMutex);
       
   217 		}
       
   218 
       
   219 	Kern::MutexSignal(*iHandlerMutex);
       
   220 	}
       
   221 
       
   222 
       
   223 void DCrashHandler::Trap(TRequestStatus* aRs, TAny* aCrashInfo)
       
   224 	{
       
   225 	if (iTrapRq != NULL)
       
   226 		Kern::PanicCurrentThread(KClientPanic, EPanicTrapWhileRequestPending);
       
   227 	NKern::ThreadEnterCS();
       
   228 	Kern::MutexWait(*iDataMutex);
       
   229 	iClient = &Kern::CurrentThread();
       
   230 	iCrashInfo = aCrashInfo;
       
   231 	iTrapRq = aRs;
       
   232 	Kern::MutexSignal(*iDataMutex);
       
   233 	NKern::ThreadLeaveCS();
       
   234 	}
       
   235 
       
   236 
       
   237 void DCrashHandler::CancelTrap()
       
   238 	{
       
   239 	__KTRACE_OPT(KDEBUGGER, Kern::Printf(">DCrashHandler::CancelTrap"));
       
   240 	NKern::ThreadEnterCS();
       
   241 	Kern::MutexWait(*iDataMutex);
       
   242 
       
   243 	__KTRACE_OPT(KDEBUGGER, Kern::Printf("cancel request (0x%08X)", iTrapRq));
       
   244 	Kern::RequestComplete(iClient, iTrapRq, KErrCancel);
       
   245 	iClient = NULL;
       
   246 
       
   247 	if (iCrashedThread != NULL)
       
   248 		{
       
   249 		__KTRACE_OPT(KDEBUGGER, Kern::Printf("resume crashed thread"));
       
   250 		NKern::FSSignal(&(iSuspendSem));
       
   251 		}
       
   252 
       
   253 	Kern::MutexSignal(*iDataMutex);
       
   254 	NKern::ThreadLeaveCS();
       
   255 	__KTRACE_OPT(KDEBUGGER, Kern::Printf("<DCrashHandler::CancelTrap"));
       
   256 	}
       
   257 
       
   258 
       
   259 void DCrashHandler::KillCrashedThread()
       
   260 	{
       
   261 	if (iCrashedThread == NULL)
       
   262 		Kern::PanicCurrentThread(KClientPanic, EPanicNoCrashedThread);
       
   263 	NKern::FSSignal(&iSuspendSem);
       
   264 	}
       
   265 
       
   266 
       
   267 void DCrashHandler::GetCpuExcInfo(const TAny* aContext, TDbgCpuExcInfo& aInfo)
       
   268 	{
       
   269 #if defined(__MARM__)
       
   270 	const TArmExcInfo* pE = (const TArmExcInfo*)aContext;
       
   271 	aInfo.iFaultPc = pE->iR15;
       
   272 	aInfo.iFaultAddress = pE->iFaultAddress;
       
   273 	aInfo.iFaultStatus = pE->iFaultStatus;
       
   274 	aInfo.iExcCode = (TDbgCpuExcInfo::TExcCode)pE->iExcCode;
       
   275 	aInfo.iR13Svc = pE->iR13Svc;
       
   276 	aInfo.iR14Svc = pE->iR14Svc;
       
   277 	aInfo.iSpsrSvc = pE->iSpsrSvc;
       
   278 #else
       
   279 	(void) aContext; // silence warnings
       
   280 	(void) aInfo;
       
   281 #endif
       
   282 	}
       
   283 
       
   284 //////////////////////////////////////////////////////////////////////////////
       
   285 
       
   286 //
       
   287 // Channel initialisation and cleanup.  Dispatcher for user-side
       
   288 // requests.  Crash-related requests are forwarded to DCrashHandler,
       
   289 // others are implemented here.
       
   290 //
       
   291 
       
   292 class DKdaChannel : public DLogicalChannelBase
       
   293 	{
       
   294 public:
       
   295 	~DKdaChannel();
       
   296 protected:
       
   297 	// from DLogicalChannelBase
       
   298 	virtual TInt DoCreate(TInt aUnit, const TDesC8* anInfo, const TVersion &aVer);
       
   299 	virtual TInt Request(TInt aFunction, TAny* a1, TAny* a2);
       
   300 private:
       
   301 	TInt ReadMem(RMinKda::TReadMemParams* aParams);
       
   302 	TInt GetThreadInfo(TUint aTid, TAny* aInfo);
       
   303 	void GetThreadCpuInfo(DThread* aThread, TDbgRegSet& aInfo);
       
   304 	TInt GetCodeSegs(RMinKda::TCodeSnapshotParams* aParams);
       
   305 	TInt GetCodeSegInfo(RMinKda::TCodeInfoParams* aParams);
       
   306 	TInt OpenTempObject(TUint aId, TObjectType aType);
       
   307 	void CloseTempObject();
       
   308 private:
       
   309 	DCrashHandler* iCrashHandler;
       
   310 	DObject* iTempObj;			// automagically closed if abnormal termination
       
   311 	};
       
   312 
       
   313 
       
   314 //
       
   315 // Called when user-side thread create new channel with LDD.  Called
       
   316 // in context of that thread, in thread critical section.
       
   317 //
       
   318 
       
   319 TInt DKdaChannel::DoCreate(TInt /*aUnit*/, const TDesC8* /*aInfo*/, const TVersion &aVer)
       
   320 	{
       
   321 	if (Kern::CurrentThread().iOwningProcess->iS.iSecureId != KDexecSid)
       
   322 		return KErrPermissionDenied;
       
   323 	if (! Kern::QueryVersionSupported(KKdaLddVersion(), aVer))
       
   324 		return KErrNotSupported;
       
   325 
       
   326 	iCrashHandler = new DCrashHandler;
       
   327 	if (iCrashHandler == NULL)
       
   328 		return KErrNoMemory;
       
   329 	return iCrashHandler->Create(iDevice);
       
   330 	}
       
   331 
       
   332 
       
   333 //
       
   334 // Called when last reference to channel is closed, in context of
       
   335 // closing thread, in thread critical section.
       
   336 //
       
   337 
       
   338 DKdaChannel::~DKdaChannel()
       
   339 	{
       
   340 	__KTRACE_OPT(KDEBUGGER, Kern::Printf("DKdaChannel::~DKdaChannel"));
       
   341 	Kern::SafeClose(iTempObj, NULL);
       
   342 	if (iCrashHandler)
       
   343 		{
       
   344 		iCrashHandler->CancelTrap();
       
   345 		iCrashHandler->Close();
       
   346 		}
       
   347 	}
       
   348 
       
   349 
       
   350 //
       
   351 // Request dispatcher. Called in context of requesting thread.
       
   352 //
       
   353 
       
   354 TInt DKdaChannel::Request(TInt aFunction, TAny* a1, TAny* a2)
       
   355 	{
       
   356 	__KTRACE_OPT(KDEBUGGER, Kern::Printf(">DKdaChannel::Request function=%d a1=0x%08X a2=0x%08X", aFunction, a1, a2));
       
   357 	
       
   358 	TInt r = KErrNone;
       
   359 	switch (aFunction)
       
   360 		{
       
   361 	case RMinKda::ETrap:
       
   362 		iCrashHandler->Trap((TRequestStatus*)a1, a2);
       
   363 		break;
       
   364 	case RMinKda::ECancelTrap:
       
   365 		iCrashHandler->CancelTrap();
       
   366 		break;
       
   367 	case RMinKda::EKillCrashedThread:
       
   368 		iCrashHandler->KillCrashedThread();
       
   369 		break;
       
   370 	case RMinKda::EGetThreadInfo:
       
   371 		r = GetThreadInfo((TUint)a1, a2);
       
   372 		break;
       
   373 	case RMinKda::EReadMem:
       
   374 		r = ReadMem((RMinKda::TReadMemParams*)a1);
       
   375 		break;
       
   376 	case RMinKda::EGetCodeSegs:
       
   377 		r = GetCodeSegs((RMinKda::TCodeSnapshotParams*)a1);
       
   378 		break;
       
   379 	case RMinKda::EGetCodeSegInfo:
       
   380 		r = GetCodeSegInfo((RMinKda::TCodeInfoParams*)a1);
       
   381 		break;
       
   382 	default:
       
   383 		Kern::PanicCurrentThread(KClientPanic, EPanicUnsupportedRequest);
       
   384 		break;
       
   385 		}
       
   386 
       
   387 	__KTRACE_OPT(KDEBUGGER, Kern::Printf("<DKdaChannel::Request r=%d", r));
       
   388 	return r;
       
   389 	}
       
   390 
       
   391 
       
   392 TInt DKdaChannel::ReadMem(RMinKda::TReadMemParams* aParams)
       
   393 	{
       
   394 	RMinKda::TReadMemParams params;
       
   395 	umemget32(&params, aParams, sizeof(params));
       
   396 
       
   397 	TInt destLen;
       
   398 	TInt destMax;
       
   399 	TUint8* destPtr = (TUint8*)Kern::KUDesInfo(*params.iDes, destLen, destMax);
       
   400 
       
   401 	TInt r = OpenTempObject(params.iTid, EThread);
       
   402 	if (r == KErrNone)
       
   403 		{
       
   404 		r = Kern::ThreadRawRead((DThread*)iTempObj, (TAny*)params.iAddr, destPtr, destMax);
       
   405 
       
   406 		if (r == KErrNone)
       
   407 			Kern::KUDesSetLength(*params.iDes, destMax);
       
   408 
       
   409 		CloseTempObject();
       
   410 		}
       
   411 
       
   412 	return r;
       
   413 	}
       
   414 
       
   415 
       
   416 TInt DKdaChannel::GetThreadInfo(TUint aTid, TAny* aInfo)
       
   417 	{
       
   418 	TInt r = OpenTempObject(aTid, EThread);
       
   419 	if (r == KErrNone)
       
   420 		{
       
   421 		DThread* pT = (DThread*)iTempObj;
       
   422 		TDbgThreadInfo info;
       
   423 		pT->FullName(info.iFullName);
       
   424 		info.iPid = pT->iOwningProcess->iId;
       
   425 		info.iStackBase = pT->iUserStackRunAddress;
       
   426 		info.iStackSize = pT->iUserStackSize;
       
   427 		info.iExitCategory = pT->iExitCategory;
       
   428 		info.iExitReason = pT->iExitReason;
       
   429 		GetThreadCpuInfo(pT, info.iCpu);
       
   430 		umemput32(aInfo, &info, sizeof(info));
       
   431 		CloseTempObject();
       
   432 		}
       
   433 	return r;
       
   434 	}
       
   435 
       
   436 // :FIXME: improve API
       
   437 TInt DKdaChannel::GetCodeSegs(RMinKda::TCodeSnapshotParams* aParams)
       
   438 	{
       
   439 	RMinKda::TCodeSnapshotParams params;
       
   440 	umemget32(&params, aParams, sizeof(params));
       
   441 
       
   442 	TInt maxcount;
       
   443 	umemget32(&maxcount, params.iCountPtr, sizeof(maxcount));
       
   444 
       
   445 	__KTRACE_OPT(KDEBUGGER, Kern::Printf(">DKdaChannel::GetCodeSegs pid=%d maxcount=%d", params.iPid, maxcount));
       
   446 	
       
   447 	__ASSERT_DEBUG(! iTempObj, Kern::Fault(KFault, __LINE__));
       
   448 	TInt r = OpenTempObject(params.iPid, EProcess);
       
   449 	if (r != KErrNone)
       
   450 		{
       
   451 		__KTRACE_OPT(KDEBUGGER, Kern::Printf("<DKdaChannel::GetCodeSegs process not found"));
       
   452 		return r;
       
   453 		}
       
   454 		
       
   455 	DProcess* pP = (DProcess*)iTempObj;
       
   456 
       
   457 	Kern::AccessCode();
       
   458 
       
   459 	SDblQue q;
       
   460 	TInt actcount = pP->TraverseCodeSegs(&q, NULL, DCodeSeg::EMarkDebug, DProcess::ETraverseFlagAdd);
       
   461 
       
   462 	CloseTempObject();
       
   463 
       
   464 	TInt n = Min(actcount, maxcount);
       
   465 	SDblQueLink* pL = q.iA.iNext;
       
   466 	r = KErrNone;
       
   467 	for (TInt i=0; i<n; ++i, pL = pL->iNext)
       
   468 		{
       
   469 		DCodeSeg* pS = _LOFF(pL, DCodeSeg, iTempLink);
       
   470 		XTRAP(r, XT_DEFAULT, umemput32(params.iHandles + i, &pS, sizeof(TAny*)));
       
   471 		if (r != KErrNone)
       
   472 			break;
       
   473 		}
       
   474 
       
   475 	DCodeSeg::EmptyQueue(q, DCodeSeg::EMarkDebug);
       
   476 
       
   477 	Kern::EndAccessCode();
       
   478 
       
   479 	if (r == KErrBadDescriptor)
       
   480 		Kern::PanicCurrentThread(KLitKernExec, ECausedException);
       
   481 	umemput32(params.iCountPtr, &actcount, sizeof(actcount));
       
   482 
       
   483 	__KTRACE_OPT(KDEBUGGER, Kern::Printf("<DKdaChannel::GetCodeSegs actcount=%d", actcount));
       
   484 	return r;
       
   485 	}
       
   486 
       
   487 
       
   488 // :FIXME: improve API
       
   489 TInt DKdaChannel::GetCodeSegInfo(RMinKda::TCodeInfoParams* aParams)
       
   490 	{
       
   491 	RMinKda::TCodeInfoParams params;
       
   492 	umemget32(&params, aParams, sizeof(params));
       
   493 
       
   494 	// :FIXME: Currently code segments are always loaded at the same
       
   495 	// location in every address space.  Consequently we can ignore
       
   496 	// the PID provided by the client.
       
   497 	DProcess* pP = NULL;
       
   498 
       
   499 	TInt r = KErrNotFound;
       
   500 	TFileName	nameBuffer;
       
   501 	nameBuffer.Zero();
       
   502 	Kern::AccessCode();
       
   503 	DCodeSeg* pS = DCodeSeg::VerifyHandle(params.iHandle);
       
   504 	if (pS)
       
   505 		{
       
   506 		TModuleMemoryInfo mmi;
       
   507 		r = pS->GetMemoryInfo(mmi, pP);
       
   508 		if (r == KErrNone)
       
   509 			{
       
   510 			params.iCodeBase = mmi.iCodeBase;
       
   511 			params.iCodeSize = mmi.iCodeSize;
       
   512 			XTRAP(r, XT_DEFAULT, nameBuffer.Append(*(pS->iFileName)));
       
   513 			}
       
   514 		}
       
   515 	Kern::EndAccessCode();
       
   516 	Kern::KUDesPut(*(params.iPathPtr), nameBuffer);
       
   517 	if (r == KErrBadDescriptor)
       
   518 		Kern::PanicCurrentThread(KLitKernExec, ECausedException);
       
   519 
       
   520 	if (r == KErrNone)
       
   521 		umemput32(aParams, &params, sizeof(params));
       
   522 
       
   523 	return r;
       
   524 	}
       
   525 
       
   526 //
       
   527 // Lookup a thread or process id and open the corresponding object.
       
   528 //
       
   529 // The object is stored in DKdaChannel::iTempObj to ensure it will be
       
   530 // closed even if the client thread terminates unexpectedly.  The
       
   531 // caller must call CloseTempObject() when it is finished with it.
       
   532 //
       
   533 
       
   534 TInt DKdaChannel::OpenTempObject(TUint aId, TObjectType aType)
       
   535 	{
       
   536 	__ASSERT_DEBUG(aType == EProcess || aType == EThread, Kern::Fault(KFault, __LINE__));
       
   537 	__ASSERT_DEBUG(! iTempObj, Kern::Fault(KFault, __LINE__));
       
   538 
       
   539 	DObjectCon* pC = Kern::Containers()[aType];
       
   540 	NKern::ThreadEnterCS();
       
   541 	pC->Wait();
       
   542 	DObject* tempObj = (aType == EProcess) ? (DObject*)Kern::ProcessFromId(aId) : (DObject*)Kern::ThreadFromId(aId);
       
   543 	NKern::LockSystem();
       
   544 	iTempObj = tempObj;
       
   545 	TInt r = KErrNotFound;
       
   546 	if (iTempObj)
       
   547 		r = iTempObj->Open();
       
   548 
       
   549 	NKern::UnlockSystem();
       
   550 	pC->Signal();
       
   551 	NKern::ThreadLeaveCS();
       
   552 	return r;
       
   553 	}
       
   554 
       
   555 void DKdaChannel::CloseTempObject()
       
   556 	{
       
   557 	__ASSERT_DEBUG(iTempObj, Kern::Fault(KFault, __LINE__));
       
   558 	NKern::ThreadEnterCS();
       
   559 	iTempObj->Close(NULL);
       
   560 	iTempObj = NULL;
       
   561 	NKern::ThreadLeaveCS();
       
   562 	}
       
   563 
       
   564 #ifdef __MARM__
       
   565 
       
   566 void DKdaChannel::GetThreadCpuInfo(DThread* aThread, TDbgRegSet& aInfo)
       
   567 	{
       
   568 	__ASSERT_DEBUG(aThread != &Kern::CurrentThread(), Kern::Fault(KFault, __LINE__));
       
   569 
       
   570 	TArmRegSet regSet;
       
   571 	TUint32 unused;
       
   572 	NKern::ThreadGetUserContext(&(aThread->iNThread), &regSet, unused);
       
   573 	aInfo.iRn[0] = regSet.iR0;
       
   574 	aInfo.iRn[1] = regSet.iR1;
       
   575 	aInfo.iRn[2] = regSet.iR2;
       
   576 	aInfo.iRn[3] = regSet.iR3;
       
   577 	aInfo.iRn[4] = regSet.iR4;
       
   578 	aInfo.iRn[5] = regSet.iR5;
       
   579 	aInfo.iRn[6] = regSet.iR6;
       
   580 	aInfo.iRn[7] = regSet.iR7;
       
   581 	aInfo.iRn[8] = regSet.iR8;
       
   582 	aInfo.iRn[9] = regSet.iR9;
       
   583 	aInfo.iRn[10] = regSet.iR10;
       
   584 	aInfo.iRn[11] = regSet.iR11;
       
   585 	aInfo.iRn[12] = regSet.iR12;
       
   586 	aInfo.iRn[13] = regSet.iR13;
       
   587 	aInfo.iRn[14] = regSet.iR14;
       
   588 	aInfo.iRn[15] = regSet.iR15;
       
   589 	aInfo.iCpsr = regSet.iFlags;
       
   590 	}
       
   591 
       
   592 #else
       
   593 
       
   594 void DKdaChannel::GetThreadCpuInfo(DThread* /*aThread*/, TDbgRegSet& /*aInfo*/)
       
   595 	{
       
   596 	}
       
   597 
       
   598 #endif
       
   599 
       
   600 
       
   601 //////////////////////////////////////////////////////////////////////////////
       
   602 
       
   603 class DCtDevice : public DLogicalDevice
       
   604 	{
       
   605 public:
       
   606 	DCtDevice();
       
   607 	// from DLogicalDevice
       
   608 	virtual TInt Install();
       
   609 	virtual void GetCaps(TDes8& aDes) const;
       
   610 	virtual TInt Create(DLogicalChannelBase*& aChannel);
       
   611 	};
       
   612 
       
   613 DCtDevice::DCtDevice()
       
   614 	{
       
   615 	// iParseMask = 0;
       
   616 	// iUnitsMask = 0;
       
   617 	iVersion = KKdaLddVersion();
       
   618 	}
       
   619 
       
   620 TInt DCtDevice::Install()
       
   621 	{
       
   622 	return SetName(&KKdaLddName);
       
   623 	}
       
   624 
       
   625 void DCtDevice::GetCaps(TDes8& /*aDes*/) const
       
   626 	{
       
   627 	}
       
   628 
       
   629 TInt DCtDevice::Create(DLogicalChannelBase*& aChannel)
       
   630 	{
       
   631 	aChannel = new DKdaChannel;
       
   632 	return (aChannel != NULL) ? KErrNone : KErrNoMemory;
       
   633 	}
       
   634 
       
   635 //////////////////////////////////////////////////////////////////////////////
       
   636 
       
   637 DECLARE_STANDARD_LDD()
       
   638 	{
       
   639 	return new DCtDevice;
       
   640 	}
       
   641