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