debugsrv/runmodedebug/rmdriver/src/d_process_tracker.cpp
branchRCL_3
changeset 20 ca8a1b6995f6
equal deleted inserted replaced
19:07b41fa8d1dd 20:ca8a1b6995f6
       
     1 // Copyright (c) 2006-2010 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 // Purpose: The DProcessTracker object tracks which processes are being
       
    15 // debugged. The DProcessTracker class uses a DTargetProcess object for
       
    16 // each process being debugged.
       
    17 // Note: Although TheDProcessTracker object is a global, it will be unique
       
    18 // as only the Debug Security Server can load and use rm_debug.ldd.
       
    19 // 
       
    20 //
       
    21 
       
    22 #include <e32def.h>
       
    23 #include <e32def_private.h>
       
    24 #include <e32cmn.h>
       
    25 #include <e32cmn_private.h>
       
    26 #include <kernel/kernel.h>
       
    27 #include <kernel/kern_priv.h>
       
    28 
       
    29 #include <rm_debug_api.h>
       
    30 #include "debug_logging.h"
       
    31 #include "d_process_tracker.h"
       
    32 #include "debug_utils.h"
       
    33 
       
    34 // Global Run-mode debugged process tracking object
       
    35 DProcessTracker TheDProcessTracker;
       
    36 
       
    37 // ctor
       
    38 DProcessTracker::DProcessTracker()
       
    39 	{
       
    40 	}
       
    41 
       
    42 /**
       
    43  * dtor
       
    44  * Go through forzen thread list and resume each one before clearing our structures
       
    45  * @internalTechnology
       
    46  */
       
    47 DProcessTracker::~DProcessTracker()
       
    48 	{
       
    49 
       
    50 	for(TInt i=0; i<iFrozenThreadSemaphores.Count(); i++)
       
    51 		{
       
    52 		LOG_MSG2("~DProcessTracker Resuming frozen NThread 0x%08x via FSSignal ", iFrozenThreadSemaphores[i]->iOwningThread );
       
    53 		NKern::FSSignal(iFrozenThreadSemaphores[i]);
       
    54 		}
       
    55 
       
    56 	NKern::ThreadEnterCS();
       
    57 	// The ResetAndDestroy() will call the individual deletes for all objects in the containers
       
    58 	iFrozenThreadSemaphores.ResetAndDestroy();
       
    59 	iProcesses.ResetAndDestroy();
       
    60 	iAgentsAttachedToAll.ResetAndDestroy();
       
    61 	NKern::ThreadLeaveCS();
       
    62 	}
       
    63 
       
    64 /**
       
    65  * @internalTechnology
       
    66  *
       
    67  * Creates and stores an internal mapping of debug agent to debugged process.
       
    68  * Note that an individual process may be mapped to a number of debug agents.
       
    69  *
       
    70  * @param aProcessName - The fullly qualified path of the debugged process. E.g. z:\sys\bin\hello_world.exe
       
    71  * @param aAgentId - The process id of the debug agent which is attaching to aProcessName, as returned by RProcess.Id()
       
    72  * @return KErrNone if there are no errors. KErrArgument if the processname is too long/short for a valid filepath.
       
    73  *  KErrNoMemory if there is insufficient memory.
       
    74  */
       
    75 TInt DProcessTracker::AttachProcess(const TDesC8& aProcessName,TUint64 aAgentId)
       
    76 	{
       
    77 	LOG_MSG3("DProcessTracker::AttachProcess name=%S agentId=0x%lx", 
       
    78 		&aProcessName, aAgentId);
       
    79 
       
    80 	// Valid ProcessName?
       
    81 	if (aProcessName.Length() < 1 || aProcessName.Length() >= KMaxPath)
       
    82 		{
       
    83 		return KErrArgument;
       
    84 		}
       
    85 
       
    86 	if (aProcessName == _L8("*"))
       
    87 		{
       
    88 		DDebugAgent* agent = FindAgentForProcessAndId( aProcessName, aAgentId );
       
    89 		if(agent != NULL)
       
    90 			{
       
    91 			LOG_MSG("Found agent already attached to all");
       
    92 			return KErrAlreadyExists;
       
    93 			}
       
    94 
       
    95 		agent = DDebugAgent::New(aAgentId);
       
    96 		if(agent == NULL)
       
    97 			{
       
    98 			LOG_MSG("DProcessTracker::AttachProcess() couldn't allocate memory for DDebugAgent");
       
    99 			return KErrNoMemory;
       
   100 			}
       
   101 		
       
   102 		return iAgentsAttachedToAll.Append(agent);
       
   103 
       
   104 		}
       
   105 
       
   106 	// Not attach all, but for a specific process/exe
       
   107 
       
   108 	// Create an DTargetProcess to store
       
   109 	DTargetProcess* tmpProcess = new DTargetProcess;
       
   110 	if (tmpProcess == 0)
       
   111 		{
       
   112 		return KErrNoMemory;
       
   113 		}
       
   114 	LOG_MSG2(" AttachProcess: < new DTargetProcess=0x%08x", tmpProcess );
       
   115 	
       
   116 	// Set the name
       
   117 	TInt err = KErrNone;
       
   118 	err = tmpProcess->SetProcessName(aProcessName);
       
   119 	if (err != KErrNone)
       
   120 		{
       
   121 		LOG_MSG2(" AttachProcess: < SetProcessName returned %d", err );
       
   122 		return err;
       
   123 		}
       
   124 
       
   125 	// Is this process being debugged (ie already attached?)
       
   126 	TInt found = KErrNotFound;
       
   127 	const TInt numberOfProcesses = iProcesses.Count();
       
   128 	for (TInt index = 0; index < numberOfProcesses; index++)
       
   129 		{
       
   130 		if (iProcesses[index]->ProcessName().CompareF(aProcessName) == 0)
       
   131 			{
       
   132 			LOG_MSG3(" Proc count=%d, found proc in iProcesses at %d. Count=%d",
       
   133 				index, iProcesses.Count() );
       
   134 			found = index;
       
   135 			break;
       
   136 			}
       
   137 		}
       
   138 
       
   139 	if (found != KErrNotFound)
       
   140 		{
       
   141 		// Yes, it is being debugged
       
   142 
       
   143 		// Add the agent to the list of agents for this process
       
   144 		LOG_MSG3(" > AddAgent(agent id %d) to existing iProcesses[%d]", I64LOW(aAgentId), found); 
       
   145 
       
   146 		iProcesses[found]->AddAgent(aAgentId);
       
   147 
       
   148 		return KErrNone;
       
   149 		}
       
   150 	else
       
   151 		{
       
   152 		// No, it is not being debugged
       
   153 			
       
   154 		// Add the agent to the list of agents for this process
       
   155 		LOG_MSG2(" > AddAgent(agent %d) to new proc at index 0", I64LOW(aAgentId) ); 
       
   156 
       
   157 		tmpProcess->AddAgent(aAgentId);
       
   158 
       
   159 		// Add the process to the list of processes being debugged
       
   160 		return iProcesses.Append(tmpProcess);
       
   161 		}
       
   162 	}
       
   163 
       
   164 /**
       
   165  * @internalTechnology
       
   166  * 
       
   167  * Removes a previously created mapping between a debug agent and a debugged process,
       
   168  * as created by AttachProcess.
       
   169  *
       
   170  * @param aProcessName - The fully qualified path of the debugged process. E.g. z:\sys\bin\hello_world.exe
       
   171  * @param aAgentId - The process id of the debug agent which is attaching to aProcessName, as returned by RProcess.Id()
       
   172  * @return KErrNone if there are no problems. KErrArgument if the processname is too long/short for a valid filepath.
       
   173  * KErrNotFound if the mapping does not exist (and therefore cannot be removed).
       
   174  */
       
   175 TInt DProcessTracker::DetachProcess(const TDesC8& aProcessName, TUint64 aAgentId)
       
   176 	{
       
   177 	LOG_MSG3("DProcessTracker::DetachProcess name=%S agentId=0x%lx", 
       
   178 		&aProcessName, aAgentId);
       
   179 
       
   180 	// Valid ProcessName?
       
   181 	if (aProcessName.Length() < 1 || aProcessName.Length() >= KMaxPath)
       
   182 		{
       
   183 		return KErrArgument;
       
   184 		}
       
   185 
       
   186 	if (aProcessName == _L8("*"))
       
   187 		{
       
   188 		TInt const agentCount = iAgentsAttachedToAll.Count();
       
   189 		LOG_MSG2(" iAgentsAttachedToAll size=%d", agentCount );
       
   190 
       
   191 		for (TInt i = 0; i < agentCount; i++)
       
   192 			{
       
   193 			if (iAgentsAttachedToAll[i]->Id() == aAgentId)
       
   194 				{
       
   195 				LOG_MSG2(" Agent id found at index %d, deleting it", i);
       
   196 				delete iAgentsAttachedToAll[i];
       
   197 				iAgentsAttachedToAll.Remove(i);
       
   198 				return KErrNone;
       
   199 				}
       
   200 			}
       
   201 
       
   202 		//Not found, so error condition
       
   203 		return KErrNotFound;
       
   204 		}
       
   205 
       
   206 	// Are we debugging this process?
       
   207 	const TInt numberOfProcesses = iProcesses.Count();
       
   208 	TInt foundIdx = KErrNotFound;
       
   209 	for(TInt i = 0; i < numberOfProcesses; i++)
       
   210 		{
       
   211 		if (iProcesses[i]->ProcessName().CompareF(aProcessName) == 0)
       
   212 			{
       
   213 			foundIdx = i;
       
   214 			break;
       
   215 			}
       
   216 		}
       
   217 
       
   218 	if (foundIdx == KErrNotFound)
       
   219 		{
       
   220 		return KErrNotFound;
       
   221 		}
       
   222 
       
   223 	// remove the agent from the process
       
   224 	iProcesses[foundIdx]->RemoveAgent(aAgentId);
       
   225 
       
   226 	// Found it, are there any more attached agents, or suspended threads in the process?
       
   227 
       
   228 	
       
   229 	if (iProcesses[foundIdx]->AgentCount() == 0)
       
   230 		{
       
   231 		// Delete the process as no more agents are still attached
       
   232 		delete iProcesses[foundIdx];
       
   233 
       
   234 		// Remove the now obsolete pointer from our array.
       
   235 		iProcesses.Remove(foundIdx);
       
   236 		}
       
   237 
       
   238 	return KErrNone;
       
   239 	}
       
   240 
       
   241 /**
       
   242  * @internalTechnology
       
   243  *
       
   244  * Detachs a debug agent from every process being debugged. Used when a debug agent is being detached
       
   245  * from the debug security server and has not supplied a specific process name from which to detach.
       
   246  */
       
   247 TInt DProcessTracker::DetachAgent(const TUint64 aAgentId)
       
   248 	{
       
   249 	
       
   250 	LOG_MSG2("DProcessTracker::DetachAgent 0x%lx", aAgentId);
       
   251 	
       
   252 	// Remove this agent from all the processes being tracked.
       
   253 	TInt numberOfProcesses = iProcesses.Count();
       
   254 	for(TInt i=0; i<numberOfProcesses; i++)
       
   255 		{
       
   256 		// remove the agent from the process (we don't care about the return code)
       
   257 		iProcesses[i]->RemoveAgent(aAgentId);
       
   258 		}
       
   259 
       
   260 	// Increment down through the array as we then don't have to worry about
       
   261 	// missing entries which have been shifted after deletes.
       
   262 	// The initial value of i correspnds to the index of the final element 
       
   263 	// in the array.
       
   264 	for(TInt i = iProcesses.Count()-1; i>=0; i--)
       
   265 		{
       
   266 		if (iProcesses[i]->AgentCount() == 0)
       
   267 			{
       
   268 			// No agents remain for this process. Delete the
       
   269 			// process object and remove the pointer from the array
       
   270 			delete iProcesses[i];
       
   271 			iProcesses.Remove(i);
       
   272 			}
       
   273 		}
       
   274 
       
   275 	TInt const agentCount = iAgentsAttachedToAll.Count();
       
   276 	for (TInt i = 0; i < agentCount; i++)
       
   277 		{
       
   278 		if (iAgentsAttachedToAll[i]->Id() == aAgentId)
       
   279 			{
       
   280 			LOG_MSG2(" Agent id found at index %d, deleting it", i);
       
   281 			delete iAgentsAttachedToAll[i];
       
   282 			iAgentsAttachedToAll.Remove(i);
       
   283 			}
       
   284 		}
       
   285 		
       
   286 	return KErrNone;
       
   287 	}
       
   288 
       
   289 /**
       
   290  * @internalTechnology
       
   291  *
       
   292  * Returns a pointer to a DTargetProcess object representing the mapping of a debugged process
       
   293  * with all the relevant debug agents interested in that process, as determined
       
   294  * by AttachProcess.
       
   295  *
       
   296  * @param aProcessName - The fully qualified path of the debugged process. E.g. z:\sys\bin\hello_world.exe
       
   297  * @return DTargetProcess* pointer to an object representing the internal mapping of a process to all associated
       
   298  * debug agents. Returns 0 if the mapping cannot be found or the aProcessName is invalid.
       
   299  */
       
   300 DTargetProcess* DProcessTracker::FindProcess(const TDesC8& aProcessName) const
       
   301 	{
       
   302 	// Valid ProcessName?
       
   303 	if (aProcessName.Length() < 1 || aProcessName.Length() >= KMaxPath)
       
   304 		{
       
   305 		return NULL;
       
   306 		}
       
   307 
       
   308 	// Can we find this in the array?
       
   309 
       
   310 	// Are we debugging this process?
       
   311 	const TInt numberOfProcesses = iProcesses.Count();
       
   312 	DTargetProcess* found = NULL;
       
   313 	for(TInt i = 0; i < numberOfProcesses; i++)
       
   314 		{
       
   315 		if (iProcesses[i]->ProcessName().CompareF(aProcessName) == 0)
       
   316 			{
       
   317 			found = iProcesses[i];
       
   318 			LOG_EVENT_MSG3("DProcessTracker::FindProcess(%S) found at list pos %i", 
       
   319 				&aProcessName, i);
       
   320 			break;
       
   321 			}
       
   322 		}
       
   323 
       
   324 	if (found == NULL)
       
   325 		{
       
   326 		LOG_EVENT_MSG2("DProcessTracker::FindProcess(%S), not found", &aProcessName);
       
   327 		}
       
   328 
       
   329 	return found;
       
   330 	}
       
   331 
       
   332 /**
       
   333  * @internalTechnology
       
   334  *
       
   335  * Returns a pointer to a DTargetProcess object representing the mapping of a debugged process
       
   336  * with all the relevant debug agents interested in that process, as determined
       
   337  * by AttachProcess.
       
   338  *
       
   339  * Note: This does not attempt an exact match, because the AddProcess event does not provide
       
   340  * a fully-qualified path, it provides something like [t_rmdebug_security0.exe].
       
   341  *
       
   342  * So for the purposes of dealing with this event, we need a "fuzzier" match which does not use the complete
       
   343  * path.
       
   344  *
       
   345  * @param aProcessName - The fully qualified path of the debugged process. E.g. z:\sys\bin\hello_world.exe
       
   346  * @return DTargetProcess* pointer to an object representing the internal mapping of a process to all associated
       
   347  * debug agents. Returns 0 if the mapping cannot be found or the aProcessName is invalid.
       
   348  */
       
   349 DTargetProcess*	DProcessTracker::FuzzyFindProcess(const TDesC8& aProcessName)
       
   350 	{
       
   351 	// Valid ProcessName?
       
   352 	if (aProcessName.Length() < 1 || aProcessName.Length() >= KMaxPath)
       
   353 		{
       
   354 		return 0;	// not found
       
   355 		}
       
   356 
       
   357 	// Can we find this in the array?
       
   358 	TBool found = EFalse;
       
   359 	DTargetProcess* foundProcess = 0;
       
   360 	const TChar KBackSlash('\\');
       
   361 
       
   362 	TInt numberOfProcesses = iProcesses.Count();
       
   363 	for(TInt i=0; i < numberOfProcesses; i++)
       
   364 		{
       
   365 		foundProcess = iProcesses[i];
       
   366 
       
   367 		TInt procListBackSlash = foundProcess->ProcessName().LocateReverse( KBackSlash );
       
   368 		if( procListBackSlash == KErrNotFound )
       
   369 			{
       
   370 			procListBackSlash = 0;
       
   371 			}
       
   372 		else
       
   373 			{
       
   374 			//Now move to the char after the backlash
       
   375 			procListBackSlash++;
       
   376 			}
       
   377 
       
   378 		TInt eventBackSlash = aProcessName.LocateReverse( KBackSlash );
       
   379 		if( eventBackSlash == KErrNotFound )
       
   380 			{
       
   381 			eventBackSlash = 0;
       
   382 			}
       
   383 		else
       
   384 			{
       
   385 			//Now move to the char after the backlash
       
   386 			eventBackSlash++;
       
   387 			}
       
   388 
       
   389 		if( ( procListBackSlash == 0 ) && ( eventBackSlash == 0 ) )
       
   390 			{
       
   391 			//There were no backslashes on either name, so no point in continuing
       
   392 			break;
       
   393 			}
       
   394 
       
   395 		TPtrC8 eventCleanName( aProcessName.Mid( eventBackSlash ) );		
       
   396 		TPtrC8 procListCleanName( foundProcess->ProcessName().Mid( procListBackSlash ) );
       
   397 
       
   398 		if ( eventCleanName.CompareF( procListCleanName ) == 0 )
       
   399 			{
       
   400 			LOG_MSG2("DProcessTracker::FuzzyFindProcess() found a match : process list[%d]", i );
       
   401 			found = ETrue;
       
   402 			break;
       
   403 			}
       
   404 		}
       
   405 
       
   406 	if (found == EFalse)
       
   407 		{
       
   408 		return 0;	// not found
       
   409 		}
       
   410 
       
   411 	return foundProcess;
       
   412 	}
       
   413 
       
   414 /**
       
   415   Freeze the current thread
       
   416 
       
   417   @return KErrNone if the thread is successfully suspended,
       
   418   KErrAlreadyExists if the agent has already suspended the thread,
       
   419   or one of the other system wide error codes
       
   420 
       
   421   This marks the current thread for waiting on a Fast Semaphore
       
   422   when exception handling for this thread has completed - see
       
   423   rm_debug_eventhandler.cpp for details.
       
   424   */
       
   425 TInt DProcessTracker::FreezeThread()
       
   426 	{
       
   427 	// create and store a fast semaphore to stop the thread on
       
   428 	TInt err = KErrGeneral;
       
   429 	NKern::ThreadEnterCS();
       
   430 	NFastSemaphore* sem = new NFastSemaphore( &(Kern::CurrentThread().iNThread) );
       
   431 	if( sem != NULL )
       
   432 		{
       
   433 		LOG_MSG3("DProcessTracker::FreezeThread(): new NFastSemaphore(curr NThread=0x%08x), DThread=0x%08x", 
       
   434 			sem->iOwningThread, &(Kern::CurrentThread()) );
       
   435 		err = iFrozenThreadSemaphores.Append(sem); 
       
   436 		}
       
   437 	else
       
   438 		{
       
   439 		LOG_MSG("DProcessTracker::FreezeThread(): Error : could not allocate NFastSemaphore"); 
       
   440 		err = KErrNoMemory;
       
   441 		}
       
   442 
       
   443 	NKern::ThreadLeaveCS();
       
   444 	return err;
       
   445 	}
       
   446 
       
   447 /**
       
   448  Waits the current thread on a Fast Semaphore.
       
   449 
       
   450  This is useful for situations where the current thread
       
   451  has hit a breakpoint within a critical section, and
       
   452  otherwise could not be suspended at this point.
       
   453 
       
   454  Note that the Fast Semaphore structure on which the thread
       
   455  waits must be a member data item of this class instance,
       
   456  as it needs to be FSSignal()'d by another thread to resume
       
   457  again.
       
   458  */
       
   459 void DProcessTracker::FSWait()
       
   460 	{
       
   461 	NThread* currentNThread = &(Kern::CurrentThread().iNThread);	
       
   462 	for(TInt i=0; i<iFrozenThreadSemaphores.Count(); i++)
       
   463 		{
       
   464 		if(iFrozenThreadSemaphores[i]->iOwningThread == currentNThread)
       
   465 			{
       
   466 			LOG_MSG4("DProcessTracker::FSWait(): > FSWait frozen sem %d, currentNThread=0x%08x, id=0x%x", 
       
   467 				i, currentNThread, Kern::CurrentThread().iId );
       
   468 			NKern::FSWait(iFrozenThreadSemaphores[i]);
       
   469 			return;
       
   470 			}
       
   471 		}
       
   472 	}
       
   473 	
       
   474 /**
       
   475   Resume the specified frozen thread
       
   476 
       
   477   @param aThread thread to resume
       
   478 
       
   479   @return KErrNone if the thread has previously been suspended and is resumed,
       
   480   KErrNotFound if the thread has not previously been suspended
       
   481   */
       
   482 TInt DProcessTracker::ResumeFrozenThread(DThread* aThread)
       
   483 	{
       
   484 	for(TInt i=0; i<iFrozenThreadSemaphores.Count(); i++)
       
   485 		{
       
   486 		if(iFrozenThreadSemaphores[i]->iOwningThread == &(aThread->iNThread))
       
   487 			{
       
   488 			LOG_MSG2("DProcessTracker::ResumeFrozenThread 0x%08x, signalling then deleting this FastSem", aThread->iId );
       
   489 			NKern::FSSignal(iFrozenThreadSemaphores[i]);
       
   490 			NKern::ThreadEnterCS();
       
   491 			delete iFrozenThreadSemaphores[i];
       
   492 			NKern::ThreadLeaveCS();
       
   493 			iFrozenThreadSemaphores.Remove(i);
       
   494 			return KErrNone;
       
   495 			}
       
   496 		}
       
   497 	return KErrNotFound;
       
   498 	}
       
   499 	
       
   500 TInt DProcessTracker::SuspendThread(DThread* aTargetThread, TBool aFreezeThread)
       
   501 	{
       
   502 	LOG_MSG5("DProcessTracker::SuspendThread() id 0x%08x, iCsCount=%d, , iCsFunction=%d, iSuspendCount=%d ", 
       
   503 			aTargetThread->iId, aTargetThread->iNThread.iCsCount, aTargetThread->iNThread.iCsFunction, aTargetThread->iNThread.iSuspendCount );
       
   504 	if( !aFreezeThread )
       
   505 		{		
       
   506 		if(!aTargetThread)
       
   507 			{
       
   508 			LOG_MSG("DProcessTracker::SuspendThread()  > Kern::ThreadSuspend NullThrd Ptr!!");
       
   509 			return KErrBadHandle;
       
   510 			}
       
   511 		
       
   512 		Kern::ThreadSuspend(*aTargetThread, 1);
       
   513 		return KErrNone;
       
   514 		}
       
   515 
       
   516 	if( Kern::CurrentThread().iId != aTargetThread->iId )
       
   517 		{
       
   518 		LOG_MSG2("DProcessTracker::SuspendThread() Error: Freeze for thread 0x%08x, but different from current thread", 
       
   519 				aTargetThread->iId);
       
   520 		return KErrBadHandle;
       
   521 		}
       
   522 
       
   523 	return FreezeThread();
       
   524 	}
       
   525 
       
   526 
       
   527 TInt DProcessTracker::ResumeThread(DThread* aTargetThread)
       
   528 	{
       
   529 	LOG_MSG5("DProcessTracker::ResumeThread() id 0x%08x, iCsCount=%d, , iCsFunction=%d, iSuspendCount=%d ", 
       
   530 			aTargetThread->iId, aTargetThread->iNThread.iCsCount, aTargetThread->iNThread.iCsFunction, aTargetThread->iNThread.iSuspendCount );
       
   531 
       
   532 	TInt err = ResumeFrozenThread( aTargetThread );
       
   533 	if( err == KErrNotFound ) 
       
   534 		{
       
   535 		LOG_MSG(" ResumeThread() : not found in frozen list. Using Kern::ThreadResume" );
       
   536 		Kern::ThreadResume(*aTargetThread);
       
   537 		return KErrNone;
       
   538 		}
       
   539 
       
   540 	return err;
       
   541 	}
       
   542 
       
   543 /**
       
   544   Get a thread's originating file name
       
   545 
       
   546   @param aThread the thread to get the file name for
       
   547 
       
   548   @return a pointer to the thread's file name, if there are problems accessing
       
   549   the file name then NULL will be returned
       
   550   */
       
   551 const TDesC* DProcessTracker::GetFileName(DThread* aThread) const
       
   552 	{
       
   553 	//check if the thread is NULL and return if so
       
   554 	if(!aThread)
       
   555 		{
       
   556 		return NULL;
       
   557 		}
       
   558 
       
   559 	//get the owning process and return if it is NULL
       
   560 	DProcess* process = aThread->iOwningProcess;
       
   561 	if(!process)
       
   562 		{
       
   563 		return NULL;
       
   564 		}
       
   565 
       
   566 	//get the process' code seg and return if it is NULL
       
   567 	DCodeSeg* codeSeg = process->iCodeSeg;
       
   568 	if(!codeSeg)
       
   569 		{
       
   570 		return NULL;
       
   571 		}
       
   572 
       
   573 	//return the code seg's stored file name (which could theoretically be NULL)
       
   574 	return codeSeg->iFileName;
       
   575 	}
       
   576 
       
   577 /**
       
   578 If any agent has called AttachToAll, return the most recently attached one.
       
   579 */
       
   580 DDebugAgent* DProcessTracker::GetCurrentAgentAttachedToAll() const
       
   581 	{
       
   582 	if (iAgentsAttachedToAll.Count() > 0)
       
   583 		{
       
   584 		return iAgentsAttachedToAll[iAgentsAttachedToAll.Count()-1];
       
   585 		}
       
   586 	else
       
   587 		{
       
   588 		return NULL;
       
   589 		}
       
   590 	}
       
   591 
       
   592 /**
       
   593 Returns ETrue if at least one agent was found for this process (either a specifically-attached 
       
   594 one or a current attached to all). Search specifically attached first, since these have 
       
   595 priority over attach all.
       
   596 */
       
   597 TBool DProcessTracker::NotifyAgentsForProcessEvent(const TDesC8& aProcessName, const TDriverEventInfo& aEvent, TBool aAllowFuzzy)
       
   598 	{
       
   599 	TBool foundAgent = EFalse;
       
   600 
       
   601 	DTargetProcess* process = FindProcess(aProcessName);
       
   602 	if (process == NULL && aAllowFuzzy)
       
   603 		{
       
   604 		process = FuzzyFindProcess(aProcessName);
       
   605 		}
       
   606 
       
   607 	if (process)
       
   608 		{
       
   609 		LOG_MSG3("DProcessTracker::NotifyAgentsForProcessEvent name=%S eventtype=%d", 
       
   610 			&aProcessName, aEvent.iEventType);
       
   611 		process->NotifyEvent(aEvent);
       
   612 		return ETrue;
       
   613 		}
       
   614 
       
   615 	// Since no specifically attached agents were found, try the attach all
       
   616 
       
   617 	DDebugAgent* currentAll = GetCurrentAgentAttachedToAll();
       
   618 	if (currentAll)
       
   619 		{
       
   620 		foundAgent = ETrue;
       
   621 		LOG_MSG4("DProcessTracker::NotifyAgentsForProcessEvent via AttachAll name=%S eventtype=%d, agent 0x%lx", 
       
   622 			&aProcessName, aEvent.iEventType, currentAll->Id());
       
   623 		currentAll->NotifyEvent(aEvent);
       
   624 		}
       
   625 
       
   626 	return foundAgent;
       
   627 	}
       
   628 
       
   629 /**
       
   630  * Find the agent that matches this exe/proc name. Name could be the attachall indicator "*", 
       
   631  * in which case it returns the agent that matched the pid from the attach all list
       
   632  */
       
   633 DDebugAgent* DProcessTracker::FindAgentForProcessAndId(const TDesC8& aProcessName, TUint64 aAgentId) const
       
   634 	{
       
   635 
       
   636 	if (aProcessName == _L8("*"))
       
   637 		{
       
   638 		TInt const agentCount = iAgentsAttachedToAll.Count();
       
   639 		
       
   640 		LOG_MSG3("FindAgentForProcessAndId : Searching for agent id 0x%lx, iAgentsAttachedToAll size=%d", 
       
   641 			aAgentId, agentCount );
       
   642 		
       
   643 		// Then check the attached to all list. Should not have more than one entry
       
   644 		// for each agent, but just in case we search backwards to match the append
       
   645 		//
       
   646 		for (TInt i = agentCount - 1 ; i >= 0; i--)
       
   647 			{
       
   648 			DDebugAgent* agent = iAgentsAttachedToAll[i];
       
   649 			if (agent->Id() == aAgentId)
       
   650 				{
       
   651 				return agent;
       
   652 				}
       
   653 			}
       
   654 		}
       
   655 	else
       
   656 		{
       
   657 		DTargetProcess* process = FindProcess(aProcessName);
       
   658 		if (process)
       
   659 			{
       
   660 			return process->Agent(aAgentId);
       
   661 			}
       
   662 		}
       
   663 	return NULL;
       
   664 	}