debugsrv/runmodedebug/rmdriver/src/d_rmd_breakpoints.cpp
author hgs
Fri, 08 Oct 2010 14:56:39 +0300
changeset 56 aa2539c91954
parent 42 0ff24a8f6ca2
permissions -rw-r--r--
201041
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
42
hgs
parents:
diff changeset
     1
// Copyright (c) 2004-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
56
hgs
parents: 42
diff changeset
     4
// under the terms of "Eclipse Public License v1.0"
42
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
//
hgs
parents:
diff changeset
    15
hgs
parents:
diff changeset
    16
hgs
parents:
diff changeset
    17
#include <e32def.h>
hgs
parents:
diff changeset
    18
#include <e32def_private.h>
hgs
parents:
diff changeset
    19
#include <e32cmn.h>
hgs
parents:
diff changeset
    20
#include <e32cmn_private.h>
hgs
parents:
diff changeset
    21
#include <u32std.h>
hgs
parents:
diff changeset
    22
#include <kernel/kernel.h>
hgs
parents:
diff changeset
    23
#include <kernel/kern_priv.h>
hgs
parents:
diff changeset
    24
#include <nk_trace.h>
hgs
parents:
diff changeset
    25
#include <arm.h>
hgs
parents:
diff changeset
    26
#include <kernel/cache.h>
hgs
parents:
diff changeset
    27
#include <platform.h>
hgs
parents:
diff changeset
    28
#include <nkern.h>
hgs
parents:
diff changeset
    29
#include <u32hal.h>
hgs
parents:
diff changeset
    30
hgs
parents:
diff changeset
    31
#include <rm_debug_api.h>
hgs
parents:
diff changeset
    32
#include "d_rmd_breakpoints.h"
hgs
parents:
diff changeset
    33
#include "d_process_tracker.h"
hgs
parents:
diff changeset
    34
#include "d_rmd_stepping.h"
hgs
parents:
diff changeset
    35
#include "rm_debug_kerneldriver.h"	// needed to access DRM_DebugChannel
hgs
parents:
diff changeset
    36
#include "rm_debug_driver.h"
hgs
parents:
diff changeset
    37
#include "debug_utils.h"
hgs
parents:
diff changeset
    38
#include "debug_logging.h"
hgs
parents:
diff changeset
    39
hgs
parents:
diff changeset
    40
using namespace Debug;
hgs
parents:
diff changeset
    41
56
hgs
parents: 42
diff changeset
    42
/**
42
hgs
parents:
diff changeset
    43
 *
hgs
parents:
diff changeset
    44
 * Checks whether aAddress is correctly aligned for placing a breakpoint of
hgs
parents:
diff changeset
    45
 * cpu architecture aMode.
hgs
parents:
diff changeset
    46
 *
hgs
parents:
diff changeset
    47
 * @param aAddress - Virtual memory address to check
hgs
parents:
diff changeset
    48
 * @param aMode - The CPU architecture mode of the breakpoint to be placed at aAddress
hgs
parents:
diff changeset
    49
 * @return ETrue if aAddress is suitably aligned, EFalse otherwise.
hgs
parents:
diff changeset
    50
 */
hgs
parents:
diff changeset
    51
TBool D_RMD_Breakpoints::Aligned(TUint32 aAddress, Debug::TArchitectureMode aMode)
hgs
parents:
diff changeset
    52
	{
hgs
parents:
diff changeset
    53
	switch(aMode)
hgs
parents:
diff changeset
    54
		{
hgs
parents:
diff changeset
    55
		case Debug::EArmMode:
hgs
parents:
diff changeset
    56
			// ARM breakpoints must be 32-bit aligned (lower two bits must be zero)
hgs
parents:
diff changeset
    57
			if (aAddress & 0x3)
hgs
parents:
diff changeset
    58
			{
hgs
parents:
diff changeset
    59
				// Not 32-bit aligned.
hgs
parents:
diff changeset
    60
				return EFalse;
hgs
parents:
diff changeset
    61
			}
hgs
parents:
diff changeset
    62
			break;
hgs
parents:
diff changeset
    63
		case Debug::EThumbMode:
hgs
parents:
diff changeset
    64
			// Thumb breakpoints must be 16-bit aligned (low bit must be zero)
hgs
parents:
diff changeset
    65
			if (aAddress & 0x1)
hgs
parents:
diff changeset
    66
			{
hgs
parents:
diff changeset
    67
				// Not 16-bit aligned
hgs
parents:
diff changeset
    68
				return EFalse;
hgs
parents:
diff changeset
    69
			}
hgs
parents:
diff changeset
    70
			break;
hgs
parents:
diff changeset
    71
		case Debug::EThumb2EEMode:
hgs
parents:
diff changeset
    72
			// Thumb-EE instructions are half-word aligned. See ARM ARM DDI0406A, section A3.2 Alignment Support
hgs
parents:
diff changeset
    73
			// Note that some instructions need to be word-aligned, but this function does not know which ones.
hgs
parents:
diff changeset
    74
			// It may also depend on the System Control register U bit.
hgs
parents:
diff changeset
    75
			if (aAddress & 0x1)
hgs
parents:
diff changeset
    76
			{
hgs
parents:
diff changeset
    77
				// Not 16-bit aligned
hgs
parents:
diff changeset
    78
				return EFalse;
hgs
parents:
diff changeset
    79
			}
hgs
parents:
diff changeset
    80
			break;
hgs
parents:
diff changeset
    81
		default:
hgs
parents:
diff changeset
    82
			{
hgs
parents:
diff changeset
    83
			// No idea
hgs
parents:
diff changeset
    84
			return EFalse;
hgs
parents:
diff changeset
    85
			}
hgs
parents:
diff changeset
    86
		}
hgs
parents:
diff changeset
    87
hgs
parents:
diff changeset
    88
	// Must be OK
hgs
parents:
diff changeset
    89
	return ETrue;
hgs
parents:
diff changeset
    90
	};
hgs
parents:
diff changeset
    91
56
hgs
parents: 42
diff changeset
    92
/**
42
hgs
parents:
diff changeset
    93
 *
hgs
parents:
diff changeset
    94
 * Returns the size of a breakpoint of architecture aMode in bytes
hgs
parents:
diff changeset
    95
 * 
hgs
parents:
diff changeset
    96
 * @param aMode - The architure of the breakpoint
hgs
parents:
diff changeset
    97
 * @return The size of the breakpoints in bytes. 0 if un-recognised architecture.
hgs
parents:
diff changeset
    98
 */
hgs
parents:
diff changeset
    99
TInt D_RMD_Breakpoints::BreakSize(Debug::TArchitectureMode aMode)
hgs
parents:
diff changeset
   100
	{
hgs
parents:
diff changeset
   101
	switch(aMode)
hgs
parents:
diff changeset
   102
		{
hgs
parents:
diff changeset
   103
		case Debug::EArmMode:
hgs
parents:
diff changeset
   104
			{
hgs
parents:
diff changeset
   105
				return 4;
hgs
parents:
diff changeset
   106
			}
hgs
parents:
diff changeset
   107
		case Debug::EThumbMode:
hgs
parents:
diff changeset
   108
			{
hgs
parents:
diff changeset
   109
				return 2;
hgs
parents:
diff changeset
   110
			}
hgs
parents:
diff changeset
   111
		case Debug::EThumb2EEMode:
hgs
parents:
diff changeset
   112
			{
hgs
parents:
diff changeset
   113
			// Only needs to be two bytes in size.
hgs
parents:
diff changeset
   114
			return 2;
hgs
parents:
diff changeset
   115
			}
hgs
parents:
diff changeset
   116
		default:
hgs
parents:
diff changeset
   117
			{
hgs
parents:
diff changeset
   118
				// No idea
hgs
parents:
diff changeset
   119
				return 0;
hgs
parents:
diff changeset
   120
			}
hgs
parents:
diff changeset
   121
		}
hgs
parents:
diff changeset
   122
	};
hgs
parents:
diff changeset
   123
56
hgs
parents: 42
diff changeset
   124
/**
42
hgs
parents:
diff changeset
   125
 *
hgs
parents:
diff changeset
   126
 * Checks whether two TBreakEntrys overlap
hgs
parents:
diff changeset
   127
 *
hgs
parents:
diff changeset
   128
 * @param aFirst - A TBreakEntry with valid iAddress and iMode fields.
hgs
parents:
diff changeset
   129
 * @param aSecond  - A TBreakEntry with valid iAddress and iMode fields.
hgs
parents:
diff changeset
   130
 * @return ETrue if the aFirst and aSecond overlap or the overlap cannot be determined
hgs
parents:
diff changeset
   131
 *         , EFalse otherwise
hgs
parents:
diff changeset
   132
 */
hgs
parents:
diff changeset
   133
TBool D_RMD_Breakpoints::BreakpointsOverlap(TBreakEntry& aFirst, TBreakEntry& aSecond)
hgs
parents:
diff changeset
   134
	{
hgs
parents:
diff changeset
   135
	TInt firstSize = BreakSize(aFirst.iMode);
hgs
parents:
diff changeset
   136
	TInt secondSize = BreakSize(aSecond.iMode);
hgs
parents:
diff changeset
   137
hgs
parents:
diff changeset
   138
	// Do we know the size of each breakpoint?
hgs
parents:
diff changeset
   139
	if ((firstSize <= 0) || (secondSize <= 0))
hgs
parents:
diff changeset
   140
		{
hgs
parents:
diff changeset
   141
		// We don't know the size of the breakpoint, so assume they overlap
hgs
parents:
diff changeset
   142
		return ETrue;
hgs
parents:
diff changeset
   143
		}
hgs
parents:
diff changeset
   144
hgs
parents:
diff changeset
   145
	TInt firstStartAddress = aFirst.iAddress;
hgs
parents:
diff changeset
   146
	TInt secondStartAddress = aSecond.iAddress;
hgs
parents:
diff changeset
   147
	TInt firstEndAddress = firstStartAddress + firstSize - 1;
hgs
parents:
diff changeset
   148
	TInt secondEndAddress = secondStartAddress + secondSize - 1;
hgs
parents:
diff changeset
   149
hgs
parents:
diff changeset
   150
	// If second breakpoint is past the end of the first then we're ok
hgs
parents:
diff changeset
   151
	if(firstEndAddress < secondStartAddress)
hgs
parents:
diff changeset
   152
		{
hgs
parents:
diff changeset
   153
		return EFalse;
hgs
parents:
diff changeset
   154
		}
hgs
parents:
diff changeset
   155
hgs
parents:
diff changeset
   156
	// If first breakpoint is past the end of the second then we're ok
hgs
parents:
diff changeset
   157
	if(secondEndAddress < firstStartAddress)
hgs
parents:
diff changeset
   158
		{
hgs
parents:
diff changeset
   159
		return EFalse;
hgs
parents:
diff changeset
   160
		}
hgs
parents:
diff changeset
   161
hgs
parents:
diff changeset
   162
	// The breakpoints overlap
hgs
parents:
diff changeset
   163
	return ETrue;
hgs
parents:
diff changeset
   164
	}
hgs
parents:
diff changeset
   165
56
hgs
parents: 42
diff changeset
   166
/**
42
hgs
parents:
diff changeset
   167
 * 
hgs
parents:
diff changeset
   168
 * Returns the breakpoint bitpattern to use for each architecture type
hgs
parents:
diff changeset
   169
 *
hgs
parents:
diff changeset
   170
 * @param aMode - the cpu architecture type
hgs
parents:
diff changeset
   171
 * @return The bit-pattern to use for the specified architecture, or 0 if unsupported.
hgs
parents:
diff changeset
   172
 */
hgs
parents:
diff changeset
   173
TUint32 D_RMD_Breakpoints::BreakInst(Debug::TArchitectureMode aMode)
hgs
parents:
diff changeset
   174
	{
hgs
parents:
diff changeset
   175
	switch(aMode)
hgs
parents:
diff changeset
   176
		{
hgs
parents:
diff changeset
   177
		case Debug::EArmMode:
hgs
parents:
diff changeset
   178
			{
hgs
parents:
diff changeset
   179
				return KArmBreakPoint;
hgs
parents:
diff changeset
   180
			}
hgs
parents:
diff changeset
   181
		case Debug::EThumbMode:
hgs
parents:
diff changeset
   182
			{
hgs
parents:
diff changeset
   183
				return KThumbBreakPoint;
hgs
parents:
diff changeset
   184
			}
hgs
parents:
diff changeset
   185
		case Debug::EThumb2EEMode:
hgs
parents:
diff changeset
   186
			{
hgs
parents:
diff changeset
   187
			return KT2EEBreakPoint;
hgs
parents:
diff changeset
   188
			}
hgs
parents:
diff changeset
   189
		default:
hgs
parents:
diff changeset
   190
			{
hgs
parents:
diff changeset
   191
				// No idea what the breakpoint should be
hgs
parents:
diff changeset
   192
				return 0;
hgs
parents:
diff changeset
   193
			}
hgs
parents:
diff changeset
   194
		}
hgs
parents:
diff changeset
   195
	};
hgs
parents:
diff changeset
   196
hgs
parents:
diff changeset
   197
/**
hgs
parents:
diff changeset
   198
Constructor. Initialises its internal list of empty breakpoints.
hgs
parents:
diff changeset
   199
*/
hgs
parents:
diff changeset
   200
D_RMD_Breakpoints::D_RMD_Breakpoints(DRM_DebugChannel* aChannel)
hgs
parents:
diff changeset
   201
: iBreakPointList(NUMBER_OF_TEMP_BREAKPOINTS, 0),
hgs
parents:
diff changeset
   202
  iNextBreakId(NUMBER_OF_TEMP_BREAKPOINTS),
hgs
parents:
diff changeset
   203
  iChannel(aChannel),
hgs
parents:
diff changeset
   204
  iInitialised(EFalse)
hgs
parents:
diff changeset
   205
	{
hgs
parents:
diff changeset
   206
	iBreakPointList.Reset();	
hgs
parents:
diff changeset
   207
	TBreakEntry emptyTempBreak;
hgs
parents:
diff changeset
   208
	
hgs
parents:
diff changeset
   209
	for (TInt i = 0; i < NUMBER_OF_TEMP_BREAKPOINTS; i++)
hgs
parents:
diff changeset
   210
		{
hgs
parents:
diff changeset
   211
		emptyTempBreak.iBreakId = i;
hgs
parents:
diff changeset
   212
		
hgs
parents:
diff changeset
   213
		if (KErrNone != iBreakPointList.Append(emptyTempBreak))
hgs
parents:
diff changeset
   214
			{
hgs
parents:
diff changeset
   215
			LOG_MSG("D_RMD_Breakpoints::D_RMD_Breakpoints() - Error appending blank temp break entry");
hgs
parents:
diff changeset
   216
			}
hgs
parents:
diff changeset
   217
		}
hgs
parents:
diff changeset
   218
	}
hgs
parents:
diff changeset
   219
hgs
parents:
diff changeset
   220
/**
hgs
parents:
diff changeset
   221
Destructor. Clears all the breakpoints in the system, deletes its internal list of breakpoints,
hgs
parents:
diff changeset
   222
and closes the exclusivity semaphore.
hgs
parents:
diff changeset
   223
*/
hgs
parents:
diff changeset
   224
D_RMD_Breakpoints::~D_RMD_Breakpoints()
hgs
parents:
diff changeset
   225
	{
hgs
parents:
diff changeset
   226
	ClearAllBreakPoints();
hgs
parents:
diff changeset
   227
	
hgs
parents:
diff changeset
   228
	// close the breakpoint list and free the memory associated with it
hgs
parents:
diff changeset
   229
	iBreakPointList.Close();
hgs
parents:
diff changeset
   230
hgs
parents:
diff changeset
   231
	if (iLock)
hgs
parents:
diff changeset
   232
		iLock->Close(NULL);
hgs
parents:
diff changeset
   233
	}
hgs
parents:
diff changeset
   234
hgs
parents:
diff changeset
   235
/**
hgs
parents:
diff changeset
   236
Initialises the breakpoint list exclusion semaphore. This should be called once immediately after
hgs
parents:
diff changeset
   237
the constructor.
hgs
parents:
diff changeset
   238
hgs
parents:
diff changeset
   239
@return KErrNone if successful, one of the other system wide error codes otherwise.
hgs
parents:
diff changeset
   240
*/
hgs
parents:
diff changeset
   241
TInt D_RMD_Breakpoints::Init()
hgs
parents:
diff changeset
   242
	{
hgs
parents:
diff changeset
   243
	TInt err = KErrNone;
hgs
parents:
diff changeset
   244
hgs
parents:
diff changeset
   245
	// Only create a semaphore if we are not initialised
hgs
parents:
diff changeset
   246
	if(!iInitialised)
hgs
parents:
diff changeset
   247
		{
hgs
parents:
diff changeset
   248
		// Initialise the semaphore ensuring exclusive access to the breakpoint list
hgs
parents:
diff changeset
   249
		err = Kern::SemaphoreCreate(iLock, _L("RM_DebugBreakpointLock"), 1 /* Initial count */);
hgs
parents:
diff changeset
   250
		if (err == KErrNone)
hgs
parents:
diff changeset
   251
			{
hgs
parents:
diff changeset
   252
			iInitialised = ETrue;
hgs
parents:
diff changeset
   253
			}
hgs
parents:
diff changeset
   254
		}
hgs
parents:
diff changeset
   255
	else
hgs
parents:
diff changeset
   256
		{
hgs
parents:
diff changeset
   257
		err = KErrNone;
hgs
parents:
diff changeset
   258
		}
hgs
parents:
diff changeset
   259
hgs
parents:
diff changeset
   260
	return err;
hgs
parents:
diff changeset
   261
	}
hgs
parents:
diff changeset
   262
hgs
parents:
diff changeset
   263
/** 
hgs
parents:
diff changeset
   264
Public member function which sets a thread-specific breakpoint in the specified thread
hgs
parents:
diff changeset
   265
and returns an opaque handle to the caller.
hgs
parents:
diff changeset
   266
hgs
parents:
diff changeset
   267
Note 1:
hgs
parents:
diff changeset
   268
This function ensures exclusive access to the breakpoint data structures
hgs
parents:
diff changeset
   269
by using a semaphore to serialise access.
hgs
parents:
diff changeset
   270
hgs
parents:
diff changeset
   271
@see priv_DoSetBreak
hgs
parents:
diff changeset
   272
hgs
parents:
diff changeset
   273
Note 2:
hgs
parents:
diff changeset
   274
As implied by Note 1, the caller must have previously called Init() or this
hgs
parents:
diff changeset
   275
function will return KErrNotReady;
hgs
parents:
diff changeset
   276
 
hgs
parents:
diff changeset
   277
@param aBreakId - Reference to a TUint32 into which the function will return a unique breakpoint Id.
hgs
parents:
diff changeset
   278
@param aThreadId - The thread Id in which to place the breakpoint
hgs
parents:
diff changeset
   279
@param aAddress - Address to place the breakpoint
hgs
parents:
diff changeset
   280
@param aMode - The cpu instruction set architecture type breakpoint (e.g. EArmMode or EThumbMode)
hgs
parents:
diff changeset
   281
@return KErrNone if successful, otherwise one of the other system wide error codes.
hgs
parents:
diff changeset
   282
*/
hgs
parents:
diff changeset
   283
TInt D_RMD_Breakpoints::DoSetBreak(TInt32 &aBreakId, const TUint64 aId, const TBool aThreadSpecific, const TUint32 aAddress, const TArchitectureMode aMode)
hgs
parents:
diff changeset
   284
	{
hgs
parents:
diff changeset
   285
	// Ensure we have a valid semaphore
hgs
parents:
diff changeset
   286
	if (!iInitialised || !iLock)
hgs
parents:
diff changeset
   287
		{
hgs
parents:
diff changeset
   288
		return KErrNotReady;
hgs
parents:
diff changeset
   289
		}
hgs
parents:
diff changeset
   290
hgs
parents:
diff changeset
   291
	// Acquire the lock
hgs
parents:
diff changeset
   292
	NKern::ThreadEnterCS();
hgs
parents:
diff changeset
   293
	Kern::SemaphoreWait(*iLock);
hgs
parents:
diff changeset
   294
hgs
parents:
diff changeset
   295
	// Really do the work
hgs
parents:
diff changeset
   296
	TInt err = priv_DoSetBreak(aBreakId, aId, aThreadSpecific, aAddress,aMode);
hgs
parents:
diff changeset
   297
	
hgs
parents:
diff changeset
   298
	// Release the lock
hgs
parents:
diff changeset
   299
	Kern::SemaphoreSignal(*iLock);
hgs
parents:
diff changeset
   300
	NKern::ThreadLeaveCS();
hgs
parents:
diff changeset
   301
	
hgs
parents:
diff changeset
   302
	return err;
hgs
parents:
diff changeset
   303
	}
hgs
parents:
diff changeset
   304
/**
hgs
parents:
diff changeset
   305
Private member function which sets a thread-specific breakpoint in the specified thread
hgs
parents:
diff changeset
   306
and returns an opaque handle to the caller.
hgs
parents:
diff changeset
   307
hgs
parents:
diff changeset
   308
@see DoSetBreak
hgs
parents:
diff changeset
   309
hgs
parents:
diff changeset
   310
@param aBreakId - Reference to a TUint32 into which the function will return a unique breakpoint Id.
hgs
parents:
diff changeset
   311
@param aThreadId - The thread Id in which to place the breakpoint
hgs
parents:
diff changeset
   312
@param aAddress - Address to place the breakpoint
hgs
parents:
diff changeset
   313
@param aMode - The cpu instruction set architecture type breakpoint (e.g. EArmMode or EThumbMode)
hgs
parents:
diff changeset
   314
@return KErrNone if successful, otherwise one of the other system wide error codes.
hgs
parents:
diff changeset
   315
*/
hgs
parents:
diff changeset
   316
TInt D_RMD_Breakpoints::priv_DoSetBreak(TInt32 &aBreakId, const TUint64 aId, const TBool aThreadSpecific, const TUint32 aAddress, const TArchitectureMode aMode)
hgs
parents:
diff changeset
   317
	{
hgs
parents:
diff changeset
   318
	LOG_MSG4("D_RMD_Breakpoints::priv_DoSetBreak(aThreadId = 0x%lx, aAddress = 0x%08x, aMode = %d)",aId,aAddress,aMode);
hgs
parents:
diff changeset
   319
hgs
parents:
diff changeset
   320
	// EThumb2EEMode breakpoints are not supported
hgs
parents:
diff changeset
   321
	if (EThumb2EEMode == aMode)
hgs
parents:
diff changeset
   322
		{
hgs
parents:
diff changeset
   323
		LOG_MSG("D_RMD_Breakpoints::priv_DoSetBreak() - EThumb2EEMode breakpoints are not supported");
hgs
parents:
diff changeset
   324
		return KErrNotSupported;
hgs
parents:
diff changeset
   325
		}
hgs
parents:
diff changeset
   326
hgs
parents:
diff changeset
   327
	// Check how many breakpoints we have in existence
hgs
parents:
diff changeset
   328
	if ((iBreakPointList.Count()+1) >= NUMBER_OF_MAX_BREAKPOINTS)
hgs
parents:
diff changeset
   329
		{
hgs
parents:
diff changeset
   330
		// Too many breakpoints are set!
hgs
parents:
diff changeset
   331
		LOG_MSG("D_RMD_Breakpoints::priv_DoSetBreak() - Too many breakpoints set");
hgs
parents:
diff changeset
   332
		return KErrOverflow;
hgs
parents:
diff changeset
   333
		}
hgs
parents:
diff changeset
   334
hgs
parents:
diff changeset
   335
	// check the alignment of the breakpoint
hgs
parents:
diff changeset
   336
	if (!Aligned(aAddress,aMode))
hgs
parents:
diff changeset
   337
		{
hgs
parents:
diff changeset
   338
		LOG_MSG("D_RMD_Breakpoints::priv_DoSetBreak() - Unaligned address");
hgs
parents:
diff changeset
   339
		return KErrArgument;
hgs
parents:
diff changeset
   340
		}
hgs
parents:
diff changeset
   341
hgs
parents:
diff changeset
   342
	// make sure there is not already a breakpoint at this address
hgs
parents:
diff changeset
   343
	for (TInt i = NUMBER_OF_TEMP_BREAKPOINTS; i < iBreakPointList.Count(); i++)
hgs
parents:
diff changeset
   344
		{
hgs
parents:
diff changeset
   345
		/* We need to check if the breakpoint overlaps the address at all,
hgs
parents:
diff changeset
   346
		 * and this depends upon the size of the two breakpoints as well as 
hgs
parents:
diff changeset
   347
		 * their address.
hgs
parents:
diff changeset
   348
		 */
hgs
parents:
diff changeset
   349
hgs
parents:
diff changeset
   350
		// newInstSize = size in bytes of new breakpoint
hgs
parents:
diff changeset
   351
		TInt newInstSize = BreakSize(aMode);
hgs
parents:
diff changeset
   352
		if (newInstSize == 0)
hgs
parents:
diff changeset
   353
			{
hgs
parents:
diff changeset
   354
			LOG_MSG("D_RMD_Breakpoints::priv_DoSetBreak() - Unknown architecture type for new breakpoint");
hgs
parents:
diff changeset
   355
			return KErrNotSupported;
hgs
parents:
diff changeset
   356
			}
hgs
parents:
diff changeset
   357
hgs
parents:
diff changeset
   358
		// oldInstSize = size in bytes of the existing breakpoint
hgs
parents:
diff changeset
   359
		TInt oldInstSize = BreakSize(iBreakPointList[i].iMode);
hgs
parents:
diff changeset
   360
		if (oldInstSize == 0)
hgs
parents:
diff changeset
   361
			{
hgs
parents:
diff changeset
   362
			LOG_MSG("D_RMD_Breakpoints::priv_DoSetBreak() - : Unknown architecture type of existing breakpoint");
hgs
parents:
diff changeset
   363
			return KErrNotSupported;
hgs
parents:
diff changeset
   364
			}
hgs
parents:
diff changeset
   365
hgs
parents:
diff changeset
   366
		// Overlap checking - temp is used as the new breakpoint description for checking purposes only
hgs
parents:
diff changeset
   367
		TBreakEntry temp;
hgs
parents:
diff changeset
   368
hgs
parents:
diff changeset
   369
		temp.iAddress = aAddress;
hgs
parents:
diff changeset
   370
		temp.iMode = aMode;
hgs
parents:
diff changeset
   371
hgs
parents:
diff changeset
   372
		// do they overlap?
hgs
parents:
diff changeset
   373
		if ( BreakpointsOverlap(temp,iBreakPointList[i]) )
hgs
parents:
diff changeset
   374
			{
hgs
parents:
diff changeset
   375
			// Yes
hgs
parents:
diff changeset
   376
			if(iBreakPointList[i].iThreadSpecific && aThreadSpecific)
hgs
parents:
diff changeset
   377
				{
hgs
parents:
diff changeset
   378
				if(aId == iBreakPointList[i].iId)
hgs
parents:
diff changeset
   379
					{
hgs
parents:
diff changeset
   380
					LOG_MSG("D_RMD_Breakpoints::priv_DoSetBreak() - New thread specific breakpoint overlaps an existing thread specific breakpoint");
hgs
parents:
diff changeset
   381
					return KErrAlreadyExists;
hgs
parents:
diff changeset
   382
					}
hgs
parents:
diff changeset
   383
				}
hgs
parents:
diff changeset
   384
			else if(!iBreakPointList[i].iThreadSpecific && aThreadSpecific)
hgs
parents:
diff changeset
   385
				{
hgs
parents:
diff changeset
   386
				NKern::ThreadEnterCS();
hgs
parents:
diff changeset
   387
				DThread* thread = DebugUtils::OpenThreadHandle(aId);
hgs
parents:
diff changeset
   388
				TInt err = KErrNone;
hgs
parents:
diff changeset
   389
				if (!thread)
hgs
parents:
diff changeset
   390
					{
hgs
parents:
diff changeset
   391
					err = KErrNotFound;
hgs
parents:
diff changeset
   392
					}
hgs
parents:
diff changeset
   393
				if (!err && thread->iOwningProcess->iId == iBreakPointList[i].iId)
hgs
parents:
diff changeset
   394
					{
hgs
parents:
diff changeset
   395
					LOG_MSG("D_RMD_Breakpoints::priv_DoSetBreak() - New thread specific breakpoint overlaps an existing breakpoint");
hgs
parents:
diff changeset
   396
					err = KErrAlreadyExists;
hgs
parents:
diff changeset
   397
					}
hgs
parents:
diff changeset
   398
				thread->Close(NULL);
hgs
parents:
diff changeset
   399
				NKern::ThreadLeaveCS();
hgs
parents:
diff changeset
   400
				if (err) return err;
hgs
parents:
diff changeset
   401
				}
hgs
parents:
diff changeset
   402
			else if(iBreakPointList[i].iThreadSpecific && !aThreadSpecific)
hgs
parents:
diff changeset
   403
				{
hgs
parents:
diff changeset
   404
				NKern::ThreadEnterCS();
hgs
parents:
diff changeset
   405
				DThread* thread = DebugUtils::OpenThreadHandle(iBreakPointList[i].iId);
hgs
parents:
diff changeset
   406
				TInt err = KErrNone;
hgs
parents:
diff changeset
   407
				if (!thread)
hgs
parents:
diff changeset
   408
					{
hgs
parents:
diff changeset
   409
					err = KErrNotFound;
hgs
parents:
diff changeset
   410
					}
hgs
parents:
diff changeset
   411
				if (!err && thread->iOwningProcess->iId == aId)
hgs
parents:
diff changeset
   412
					{
hgs
parents:
diff changeset
   413
					LOG_MSG("D_RMD_Breakpoints::priv_DoSetBreak() - New breakpoint overlaps an existing thread specific breakpoint");
hgs
parents:
diff changeset
   414
					err = KErrAlreadyExists;
hgs
parents:
diff changeset
   415
					}
hgs
parents:
diff changeset
   416
				if (thread) thread->Close(NULL);
hgs
parents:
diff changeset
   417
				NKern::ThreadLeaveCS();
hgs
parents:
diff changeset
   418
				if (err) return err;
hgs
parents:
diff changeset
   419
				}
hgs
parents:
diff changeset
   420
			else // !iBreakPointList[i].iThreadSpecific && !aThreadSpecific
hgs
parents:
diff changeset
   421
				{
hgs
parents:
diff changeset
   422
				if(iBreakPointList[i].iId == aId)
hgs
parents:
diff changeset
   423
					{
hgs
parents:
diff changeset
   424
					LOG_MSG("D_RMD_Breakpoints::priv_DoSetBreak() - New breakpoint overlaps an existing breakpoint");
hgs
parents:
diff changeset
   425
					return KErrAlreadyExists;
hgs
parents:
diff changeset
   426
					}
hgs
parents:
diff changeset
   427
				}
hgs
parents:
diff changeset
   428
			}
hgs
parents:
diff changeset
   429
		}
hgs
parents:
diff changeset
   430
hgs
parents:
diff changeset
   431
	// increment the break id
hgs
parents:
diff changeset
   432
	aBreakId = iNextBreakId++;	
hgs
parents:
diff changeset
   433
hgs
parents:
diff changeset
   434
	// create the new breakpoint entry
hgs
parents:
diff changeset
   435
	TBreakEntry breakEntry(aBreakId, aId, aThreadSpecific, aAddress, aMode);
hgs
parents:
diff changeset
   436
hgs
parents:
diff changeset
   437
	TInt err = priv_DoEnableBreak(breakEntry, ETrue);
hgs
parents:
diff changeset
   438
	if (KErrNone != err)
hgs
parents:
diff changeset
   439
		{
hgs
parents:
diff changeset
   440
		LOG_MSG("D_RMD_Breakpoints::priv_DoSetBreak() - Could not enable the breakpoint");
hgs
parents:
diff changeset
   441
		
hgs
parents:
diff changeset
   442
		return err;
hgs
parents:
diff changeset
   443
		}
hgs
parents:
diff changeset
   444
hgs
parents:
diff changeset
   445
	err = iBreakPointList.Append(breakEntry);
hgs
parents:
diff changeset
   446
	if (err != KErrNone)
hgs
parents:
diff changeset
   447
		{
hgs
parents:
diff changeset
   448
		LOG_MSG("D_RMD_Breakpoints::priv_DoSetBreak() - Failed to append breakpoint");
hgs
parents:
diff changeset
   449
		}
hgs
parents:
diff changeset
   450
hgs
parents:
diff changeset
   451
	LOG_MSG2("D_RMD_Breakpoints::priv_DoSetBreak(breakId = 0x%08x) done",aBreakId);
hgs
parents:
diff changeset
   452
hgs
parents:
diff changeset
   453
	return err;
hgs
parents:
diff changeset
   454
	}
hgs
parents:
diff changeset
   455
hgs
parents:
diff changeset
   456
/**
hgs
parents:
diff changeset
   457
Public member function which enables a previously set breakpoint.
hgs
parents:
diff changeset
   458
hgs
parents:
diff changeset
   459
Note 1:
hgs
parents:
diff changeset
   460
This function ensures exclusive access to the breakpoint data structures
hgs
parents:
diff changeset
   461
by using a semaphore to serialise access.
hgs
parents:
diff changeset
   462
hgs
parents:
diff changeset
   463
@see priv_DoEnableBreak
hgs
parents:
diff changeset
   464
hgs
parents:
diff changeset
   465
Note 2:
hgs
parents:
diff changeset
   466
As implied by Note 1, the caller must have previously called Init() or this
hgs
parents:
diff changeset
   467
function will return KErrNotReady;
hgs
parents:
diff changeset
   468
hgs
parents:
diff changeset
   469
Note 3
hgs
parents:
diff changeset
   470
Historically, this function accepted a reference to a TBreakEntry in the class' own
hgs
parents:
diff changeset
   471
iBreakPointList. It now checks whether the reference is to an element of its own list,
hgs
parents:
diff changeset
   472
or one invented by the caller.
hgs
parents:
diff changeset
   473
hgs
parents:
diff changeset
   474
@param aEntry reference to a TBreakEntry datastructure describing the breakpoint to be re-enabled.
hgs
parents:
diff changeset
   475
@param aSaveOldInstruction ETrue preserves the instruction at the breakpoint address, EFalse otherwise.
hgs
parents:
diff changeset
   476
@return KErrNone if successful, otherwise one of the other system wide error codes.
hgs
parents:
diff changeset
   477
*/
hgs
parents:
diff changeset
   478
TInt D_RMD_Breakpoints::DoEnableBreak(TBreakEntry &aEntry, TBool aSaveOldInstruction)
hgs
parents:
diff changeset
   479
	{
hgs
parents:
diff changeset
   480
	// Ensure we have a valid semaphore
hgs
parents:
diff changeset
   481
	if (!iInitialised || !iLock)
hgs
parents:
diff changeset
   482
		{
hgs
parents:
diff changeset
   483
		return KErrNotReady;
hgs
parents:
diff changeset
   484
		}
hgs
parents:
diff changeset
   485
hgs
parents:
diff changeset
   486
	// Acquire the lock
hgs
parents:
diff changeset
   487
	NKern::ThreadEnterCS();
hgs
parents:
diff changeset
   488
	Kern::SemaphoreWait(*iLock);
hgs
parents:
diff changeset
   489
hgs
parents:
diff changeset
   490
	// Really do the work
hgs
parents:
diff changeset
   491
	TInt err = priv_DoEnableBreak(aEntry,aSaveOldInstruction);
hgs
parents:
diff changeset
   492
	
hgs
parents:
diff changeset
   493
	// Release the lock
hgs
parents:
diff changeset
   494
	Kern::SemaphoreSignal(*iLock);
hgs
parents:
diff changeset
   495
	NKern::ThreadLeaveCS();
hgs
parents:
diff changeset
   496
hgs
parents:
diff changeset
   497
	return err;
hgs
parents:
diff changeset
   498
	}
hgs
parents:
diff changeset
   499
hgs
parents:
diff changeset
   500
/**
hgs
parents:
diff changeset
   501
Private member function which enables a previously set breakpoint, as per DoEnableBreak, but
hgs
parents:
diff changeset
   502
does not serialise access.
hgs
parents:
diff changeset
   503
hgs
parents:
diff changeset
   504
@see DoEnableBreak
hgs
parents:
diff changeset
   505
hgs
parents:
diff changeset
   506
@param aEntry reference to a TBreakEntry datastructure describing the breakpoint to be re-enabled.
hgs
parents:
diff changeset
   507
@param aSaveOldInstruction ETrue preserves the instruction at the breakpoint address, EFalse otherwise.
hgs
parents:
diff changeset
   508
@return KErrNone if successful, otherwise one of the other system wide error codes.
hgs
parents:
diff changeset
   509
*/
hgs
parents:
diff changeset
   510
TInt D_RMD_Breakpoints::priv_DoEnableBreak(TBreakEntry &aEntry, TBool aSaveOldInstruction)
hgs
parents:
diff changeset
   511
	{
hgs
parents:
diff changeset
   512
	LOG_MSG("D_RMD_Breakpoints::DoEnableBreak()");
hgs
parents:
diff changeset
   513
hgs
parents:
diff changeset
   514
	TUint32 inst = BreakInst(aEntry.iMode);	
hgs
parents:
diff changeset
   515
	TInt instSize = BreakSize(aEntry.iMode);
hgs
parents:
diff changeset
   516
	if (instSize == 0 || inst == 0)
hgs
parents:
diff changeset
   517
		{
hgs
parents:
diff changeset
   518
		// not supported
hgs
parents:
diff changeset
   519
		LOG_MSG("D_RMD_Breakpoints::priv_DoEnableBreak - unsupported breakpoint architecture");
hgs
parents:
diff changeset
   520
		return KErrNotSupported;
hgs
parents:
diff changeset
   521
		}
hgs
parents:
diff changeset
   522
hgs
parents:
diff changeset
   523
	TInt err = KErrNone;
hgs
parents:
diff changeset
   524
hgs
parents:
diff changeset
   525
	// Get thread id
hgs
parents:
diff changeset
   526
	TUint64 threadId = aEntry.iId + (aEntry.iThreadSpecific ? 0 : 1);
hgs
parents:
diff changeset
   527
	NKern::ThreadEnterCS();
hgs
parents:
diff changeset
   528
	DThread* threadObj = DebugUtils::OpenThreadHandle(threadId);
hgs
parents:
diff changeset
   529
	if (!threadObj)
hgs
parents:
diff changeset
   530
		{
hgs
parents:
diff changeset
   531
		LOG_MSG("D_RMD_Breakpoints::priv_DoEnableBreak - bad handle. Could not identify a threadObj");
hgs
parents:
diff changeset
   532
		NKern::ThreadLeaveCS();
hgs
parents:
diff changeset
   533
		return KErrBadHandle;
hgs
parents:
diff changeset
   534
		}
hgs
parents:
diff changeset
   535
hgs
parents:
diff changeset
   536
	if (aSaveOldInstruction)
hgs
parents:
diff changeset
   537
		{
hgs
parents:
diff changeset
   538
		TUint32 instruction;
hgs
parents:
diff changeset
   539
hgs
parents:
diff changeset
   540
		// read the instruction at the address so we can store it in the break entry for when we clear this breakpoint
hgs
parents:
diff changeset
   541
		// trap exceptions in case the address is invalid
hgs
parents:
diff changeset
   542
		XTRAPD(r, XT_DEFAULT, err = iChannel->TryToReadMemory(threadObj, (TAny *)aEntry.iAddress, (TAny *)&instruction, instSize));
hgs
parents:
diff changeset
   543
hgs
parents:
diff changeset
   544
		//consider the leave as more important than the error code so store the leave if it's not KErrNone
hgs
parents:
diff changeset
   545
		if(KErrNone != r)
hgs
parents:
diff changeset
   546
			{
hgs
parents:
diff changeset
   547
			err = r;
hgs
parents:
diff changeset
   548
			}
hgs
parents:
diff changeset
   549
hgs
parents:
diff changeset
   550
		if(KErrNone != err)
hgs
parents:
diff changeset
   551
			{
hgs
parents:
diff changeset
   552
			threadObj->Close(NULL);
hgs
parents:
diff changeset
   553
			NKern::ThreadLeaveCS();
hgs
parents:
diff changeset
   554
			LOG_MSG("D_RMD_Breakpoints::priv_DoEnableBreak() - failed to read memory");
hgs
parents:
diff changeset
   555
			return err;
hgs
parents:
diff changeset
   556
			}
hgs
parents:
diff changeset
   557
hgs
parents:
diff changeset
   558
		aEntry.iInstruction.Copy((TUint8 *)&instruction, instSize);
hgs
parents:
diff changeset
   559
		}
hgs
parents:
diff changeset
   560
hgs
parents:
diff changeset
   561
	TBool breakpointAlredySet = EFalse;
hgs
parents:
diff changeset
   562
	for (TInt i = NUMBER_OF_TEMP_BREAKPOINTS; i < iBreakPointList.Count(); i++)
hgs
parents:
diff changeset
   563
		{
hgs
parents:
diff changeset
   564
		if(iBreakPointList[i].iAddress == aEntry.iAddress && !iBreakPointList[i].iDisabledForStep )
hgs
parents:
diff changeset
   565
			{
hgs
parents:
diff changeset
   566
			breakpointAlredySet = ETrue;
hgs
parents:
diff changeset
   567
			break;
hgs
parents:
diff changeset
   568
			}
hgs
parents:
diff changeset
   569
		}
hgs
parents:
diff changeset
   570
	if(!breakpointAlredySet)
hgs
parents:
diff changeset
   571
		{
hgs
parents:
diff changeset
   572
	
hgs
parents:
diff changeset
   573
		LOG_MSG5("D_RMD_Breakpoints::DoEnableBreak() tId=0x%x, addr=0x%x, instSize=%d, inst=0x%x", 
hgs
parents:
diff changeset
   574
			threadObj->iId, aEntry.iAddress, instSize, instSize == 4 ? (TUint32)inst : (TUint16)inst );
hgs
parents:
diff changeset
   575
		XTRAPD(r, XT_DEFAULT, err = DebugSupport::ModifyCode(threadObj, aEntry.iAddress, instSize, inst, DebugSupport::EBreakpointGlobal));
hgs
parents:
diff changeset
   576
		if(r != DebugSupport::EBreakpointGlobal)
hgs
parents:
diff changeset
   577
			{
hgs
parents:
diff changeset
   578
			err = r;
hgs
parents:
diff changeset
   579
			}
hgs
parents:
diff changeset
   580
		}
hgs
parents:
diff changeset
   581
	else
hgs
parents:
diff changeset
   582
		{
hgs
parents:
diff changeset
   583
		LOG_MSG5("D_RMD_Breakpoints::DoEnableBreak() ALREADY SET: tId=0x%x, addr=0x%x, instSize=%d, inst=0x%x", 
hgs
parents:
diff changeset
   584
				threadObj->iId, aEntry.iAddress, instSize, instSize == 4 ? (TUint32)inst : (TUint16)inst );
hgs
parents:
diff changeset
   585
hgs
parents:
diff changeset
   586
		}
hgs
parents:
diff changeset
   587
hgs
parents:
diff changeset
   588
	// Close the thread handle which has been opened by OpenThreadHandle
hgs
parents:
diff changeset
   589
	threadObj->Close(NULL);
hgs
parents:
diff changeset
   590
	NKern::ThreadLeaveCS();
hgs
parents:
diff changeset
   591
	return err;
hgs
parents:
diff changeset
   592
	}
hgs
parents:
diff changeset
   593
hgs
parents:
diff changeset
   594
/**
hgs
parents:
diff changeset
   595
Public member function which clears a previously set breakpoint.
hgs
parents:
diff changeset
   596
hgs
parents:
diff changeset
   597
Note 1:
hgs
parents:
diff changeset
   598
This function ensures exclusive access to the breakpoint data structures
hgs
parents:
diff changeset
   599
by using a semaphore to serialise access.
hgs
parents:
diff changeset
   600
hgs
parents:
diff changeset
   601
@see priv_DoClearBreak
hgs
parents:
diff changeset
   602
hgs
parents:
diff changeset
   603
Note 2:
hgs
parents:
diff changeset
   604
As implied by Note 1, the caller must have previously called Init() or this
hgs
parents:
diff changeset
   605
function will return KErrNotReady;
hgs
parents:
diff changeset
   606
hgs
parents:
diff changeset
   607
@param aBreakId A breakpoint Id as previously returned by DoSetBreak.
hgs
parents:
diff changeset
   608
@return KErrNone if successful, otherwise one of the other system wide error codes.
hgs
parents:
diff changeset
   609
*/
hgs
parents:
diff changeset
   610
TInt D_RMD_Breakpoints::DoClearBreak(const TInt32 aBreakId, TBool aIgnoreTerminatedThreads)
hgs
parents:
diff changeset
   611
	{
hgs
parents:
diff changeset
   612
	// Ensure we have a valid semaphore
hgs
parents:
diff changeset
   613
	if (!iInitialised || !iLock)
hgs
parents:
diff changeset
   614
		{
hgs
parents:
diff changeset
   615
		return KErrNotReady;
hgs
parents:
diff changeset
   616
		}
hgs
parents:
diff changeset
   617
hgs
parents:
diff changeset
   618
	// Acquire the lock
hgs
parents:
diff changeset
   619
	NKern::ThreadEnterCS();
hgs
parents:
diff changeset
   620
	Kern::SemaphoreWait(*iLock);
hgs
parents:
diff changeset
   621
hgs
parents:
diff changeset
   622
	// Really do the work
hgs
parents:
diff changeset
   623
	TInt err = priv_DoClearBreak(aBreakId, aIgnoreTerminatedThreads);
hgs
parents:
diff changeset
   624
	
hgs
parents:
diff changeset
   625
	// Release the lock
hgs
parents:
diff changeset
   626
	Kern::SemaphoreSignal(*iLock);
hgs
parents:
diff changeset
   627
	NKern::ThreadLeaveCS();
hgs
parents:
diff changeset
   628
hgs
parents:
diff changeset
   629
	return err;
hgs
parents:
diff changeset
   630
	}
hgs
parents:
diff changeset
   631
hgs
parents:
diff changeset
   632
/**
hgs
parents:
diff changeset
   633
Private member function which clears a previously set breakpoint, as per DoClearBreak, but
hgs
parents:
diff changeset
   634
does not serialise access.
hgs
parents:
diff changeset
   635
hgs
parents:
diff changeset
   636
@see DoClearBreak
hgs
parents:
diff changeset
   637
hgs
parents:
diff changeset
   638
@param aBreakId A breakpoint Id as previously returned by DoSetBreak.
hgs
parents:
diff changeset
   639
@return KErrNone if successful, otherwise one of the other system wide error codes.
hgs
parents:
diff changeset
   640
*/
hgs
parents:
diff changeset
   641
TInt D_RMD_Breakpoints::priv_DoClearBreak(const TInt32 aBreakId, TBool aIgnoreTerminatedThreads)
hgs
parents:
diff changeset
   642
	{
hgs
parents:
diff changeset
   643
	LOG_MSG3("D_RMD_Breakpoints::priv_DoClearBreak(0x%08x), aIgnoreTerminatedThreads=%d",
hgs
parents:
diff changeset
   644
	        aBreakId, aIgnoreTerminatedThreads);
hgs
parents:
diff changeset
   645
hgs
parents:
diff changeset
   646
	// find the break entry matching this id.  note that the breakpoints are already sorted in ascending order by id
hgs
parents:
diff changeset
   647
	TBreakEntry entry;
hgs
parents:
diff changeset
   648
	entry.iBreakId = aBreakId;
hgs
parents:
diff changeset
   649
	TInt index = iBreakPointList.FindInSignedKeyOrder(entry);
hgs
parents:
diff changeset
   650
hgs
parents:
diff changeset
   651
	TInt err = KErrNone;
hgs
parents:
diff changeset
   652
	if (index >= 0)
hgs
parents:
diff changeset
   653
		{	
hgs
parents:
diff changeset
   654
 		// if this breakpoint was set in a library and that library has already been unloaded, don't try to clear it
hgs
parents:
diff changeset
   655
		if (!iBreakPointList[index].iObsoleteLibraryBreakpoint)
hgs
parents:
diff changeset
   656
			{
hgs
parents:
diff changeset
   657
			NKern::ThreadEnterCS();
hgs
parents:
diff changeset
   658
			DThread* threadObj = DebugUtils::OpenThreadHandle(iBreakPointList[index].iId + (iBreakPointList[index].iThreadSpecific ? 0 : 1));
hgs
parents:
diff changeset
   659
			if (threadObj)
hgs
parents:
diff changeset
   660
				{
hgs
parents:
diff changeset
   661
				LOG_MSG2("priv_DoClearBreak() OpenThreadHandle ret thread 0x%08x", threadObj->iId );
hgs
parents:
diff changeset
   662
				TBool needToCallCodeModifier = ETrue;
hgs
parents:
diff changeset
   663
				for (TInt i = NUMBER_OF_TEMP_BREAKPOINTS; i < iBreakPointList.Count(); i++)
hgs
parents:
diff changeset
   664
					{
hgs
parents:
diff changeset
   665
					if (i != index)
hgs
parents:
diff changeset
   666
						{
hgs
parents:
diff changeset
   667
						if ( BreakpointsOverlap(iBreakPointList[index],iBreakPointList[i]) )
hgs
parents:
diff changeset
   668
							{
hgs
parents:
diff changeset
   669
							needToCallCodeModifier = EFalse;
hgs
parents:
diff changeset
   670
							break;
hgs
parents:
diff changeset
   671
							}
hgs
parents:
diff changeset
   672
						}
hgs
parents:
diff changeset
   673
					}
hgs
parents:
diff changeset
   674
				if(needToCallCodeModifier)
hgs
parents:
diff changeset
   675
					{
hgs
parents:
diff changeset
   676
					XTRAPD(r, XT_DEFAULT, err = DebugSupport::RestoreCode(threadObj, iBreakPointList[index].iAddress));
hgs
parents:
diff changeset
   677
					if (r != KErrNone)
hgs
parents:
diff changeset
   678
						{
hgs
parents:
diff changeset
   679
						LOG_MSG2("D_RMD_Breakpoints::priv_DoClearBreak() - restore code trap harness returned error %d",r);
hgs
parents:
diff changeset
   680
						}
hgs
parents:
diff changeset
   681
					if (err == KErrNotFound)
hgs
parents:
diff changeset
   682
						{
hgs
parents:
diff changeset
   683
						LOG_MSG("restore code reported the breakpoint not found, continuing");
hgs
parents:
diff changeset
   684
						err = KErrNone;
hgs
parents:
diff changeset
   685
						}
hgs
parents:
diff changeset
   686
					else if (err != KErrNone)
hgs
parents:
diff changeset
   687
						{
hgs
parents:
diff changeset
   688
						LOG_MSG2("D_RMD_Breakpoints::priv_DoClearBreak() - restore code returned error %d",err);
hgs
parents:
diff changeset
   689
						}
hgs
parents:
diff changeset
   690
					err = (KErrNone == r) ? err : r;
hgs
parents:
diff changeset
   691
					}
hgs
parents:
diff changeset
   692
hgs
parents:
diff changeset
   693
				// Close the thread handle opened by OpenThreadHandle
hgs
parents:
diff changeset
   694
				threadObj->Close(NULL);
hgs
parents:
diff changeset
   695
				}
hgs
parents:
diff changeset
   696
			else
hgs
parents:
diff changeset
   697
				{
hgs
parents:
diff changeset
   698
				LOG_MSG("D_RMD_Breakpoints::OpenThreadHandle ret null thread");
hgs
parents:
diff changeset
   699
				err = KErrBadHandle;
hgs
parents:
diff changeset
   700
				}
hgs
parents:
diff changeset
   701
			NKern::ThreadLeaveCS();
hgs
parents:
diff changeset
   702
			}
hgs
parents:
diff changeset
   703
		
hgs
parents:
diff changeset
   704
		LOG_MSG4("D_RMD_Breakpoints::priv_DoClearBreak() - Clearing breakpoint at address: %x, err: %d, ignore terminated: %d", iBreakPointList[index].iAddress, err, aIgnoreTerminatedThreads?1:0);
hgs
parents:
diff changeset
   705
		if ((aIgnoreTerminatedThreads && KErrBadHandle == err) || KErrNone == err)
hgs
parents:
diff changeset
   706
			{
hgs
parents:
diff changeset
   707
			// if this is a temp breakpoint, just clear out the values, otherwise remove it from the list
hgs
parents:
diff changeset
   708
			err = KErrNone;
hgs
parents:
diff changeset
   709
			if (index < NUMBER_OF_TEMP_BREAKPOINTS)
hgs
parents:
diff changeset
   710
				{
hgs
parents:
diff changeset
   711
                // if this is a temp breakpoint, just clear out the values, otherwise remove it from the list
hgs
parents:
diff changeset
   712
                LOG_MSG2("D_RMD_Breakpoints::priv_DoClearBreak() - Reseting temp breakpoint[%d]",index);
hgs
parents:
diff changeset
   713
				iBreakPointList[index].Reset();
hgs
parents:
diff changeset
   714
				}
hgs
parents:
diff changeset
   715
			else
hgs
parents:
diff changeset
   716
				{
hgs
parents:
diff changeset
   717
				LOG_MSG2("D_RMD_Breakpoints::priv_DoClearBreak() - Removing breakpoint[%d]",index);
hgs
parents:
diff changeset
   718
				iBreakPointList.Remove(index);
hgs
parents:
diff changeset
   719
				}			
hgs
parents:
diff changeset
   720
			}
hgs
parents:
diff changeset
   721
		else
hgs
parents:
diff changeset
   722
		    {
hgs
parents:
diff changeset
   723
            LOG_MSG3("D_RMD_Breakpoints::priv_DoClearBreak() - *** Not removing breakpoint[%d] due to error=%d",index, err);
hgs
parents:
diff changeset
   724
		    }
hgs
parents:
diff changeset
   725
				
hgs
parents:
diff changeset
   726
		return err;
hgs
parents:
diff changeset
   727
		}
hgs
parents:
diff changeset
   728
hgs
parents:
diff changeset
   729
	LOG_MSG2("D_RMD_Breakpoints::priv_DoClearBreak() - Break Id %d not found", aBreakId);
hgs
parents:
diff changeset
   730
hgs
parents:
diff changeset
   731
	return KErrNotFound;
hgs
parents:
diff changeset
   732
	}
hgs
parents:
diff changeset
   733
hgs
parents:
diff changeset
   734
/**
hgs
parents:
diff changeset
   735
Public member function which modifies a previously set breakpoint.
hgs
parents:
diff changeset
   736
hgs
parents:
diff changeset
   737
Note 1:
hgs
parents:
diff changeset
   738
This function ensures exclusive access to the breakpoint data structures
hgs
parents:
diff changeset
   739
by using a semaphore to serialise access.
hgs
parents:
diff changeset
   740
hgs
parents:
diff changeset
   741
@see priv_DoModifyBreak
hgs
parents:
diff changeset
   742
hgs
parents:
diff changeset
   743
Note 2:
hgs
parents:
diff changeset
   744
As implied by Note 1, the caller must have previously called Init() or this
hgs
parents:
diff changeset
   745
function will return KErrNotReady;
hgs
parents:
diff changeset
   746
hgs
parents:
diff changeset
   747
@param aBreakInfo A TModifyBreakInfo describing the breakpoint properties that are wanted.
hgs
parents:
diff changeset
   748
@return KErrNone if successful, otherwise one of the other system wide error codes.
hgs
parents:
diff changeset
   749
*/
hgs
parents:
diff changeset
   750
TInt D_RMD_Breakpoints::DoModifyBreak(TModifyBreakInfo* aBreakInfo)
hgs
parents:
diff changeset
   751
	{
hgs
parents:
diff changeset
   752
	// Ensure we have a valid semaphore
hgs
parents:
diff changeset
   753
	if (!iInitialised || !iLock)
hgs
parents:
diff changeset
   754
		{
hgs
parents:
diff changeset
   755
		return KErrNotReady;
hgs
parents:
diff changeset
   756
		}
hgs
parents:
diff changeset
   757
hgs
parents:
diff changeset
   758
	// Acquire the lock
hgs
parents:
diff changeset
   759
	NKern::ThreadEnterCS();
hgs
parents:
diff changeset
   760
	Kern::SemaphoreWait(*iLock); 
hgs
parents:
diff changeset
   761
hgs
parents:
diff changeset
   762
	// Really do the work
hgs
parents:
diff changeset
   763
	TInt err = priv_DoModifyBreak(aBreakInfo);
hgs
parents:
diff changeset
   764
	
hgs
parents:
diff changeset
   765
	// Release the lock
hgs
parents:
diff changeset
   766
	Kern::SemaphoreSignal(*iLock);
hgs
parents:
diff changeset
   767
	NKern::ThreadLeaveCS();
hgs
parents:
diff changeset
   768
hgs
parents:
diff changeset
   769
	return err;
hgs
parents:
diff changeset
   770
	}
hgs
parents:
diff changeset
   771
hgs
parents:
diff changeset
   772
/**
hgs
parents:
diff changeset
   773
Private member function which modifies a previously set breakpoint, as per DoModifyBreak, but
hgs
parents:
diff changeset
   774
does not serialise access.
hgs
parents:
diff changeset
   775
hgs
parents:
diff changeset
   776
@see DoModifyBreak
hgs
parents:
diff changeset
   777
hgs
parents:
diff changeset
   778
@param aBreakInfo A TModifyBreakInfo describing the breakpoint properties that are wanted.
hgs
parents:
diff changeset
   779
@return KErrNone if successful, otherwise one of the other system wide error codes.
hgs
parents:
diff changeset
   780
*/
hgs
parents:
diff changeset
   781
TInt D_RMD_Breakpoints::priv_DoModifyBreak(TModifyBreakInfo* aBreakInfo)
hgs
parents:
diff changeset
   782
	{
hgs
parents:
diff changeset
   783
	LOG_MSG("D_RMD_Breakpoints::priv_DoModifyBreak()");
hgs
parents:
diff changeset
   784
hgs
parents:
diff changeset
   785
	// Check arguments
hgs
parents:
diff changeset
   786
	if (!aBreakInfo)
hgs
parents:
diff changeset
   787
		{
hgs
parents:
diff changeset
   788
		LOG_MSG("D_RMD_Breakpoints::priv_DoModifyBreak() was passed a NULL argument");
hgs
parents:
diff changeset
   789
		return KErrArgument;
hgs
parents:
diff changeset
   790
		}
hgs
parents:
diff changeset
   791
hgs
parents:
diff changeset
   792
	//User side memory is not accessible directly
hgs
parents:
diff changeset
   793
	TSetBreakInfo info;
hgs
parents:
diff changeset
   794
	TInt err = Kern::ThreadRawRead(iChannel->iClientThread, aBreakInfo, (TUint8*)&info, sizeof(TSetBreakInfo));
hgs
parents:
diff changeset
   795
	if (err != KErrNone)
hgs
parents:
diff changeset
   796
		{
hgs
parents:
diff changeset
   797
		LOG_MSG("D_RMD_Breakpoints::priv_DoModifyBreak() was passed a bad argument");
hgs
parents:
diff changeset
   798
		return err;
hgs
parents:
diff changeset
   799
		}
hgs
parents:
diff changeset
   800
hgs
parents:
diff changeset
   801
	// EThumb2EEMode breakpoints are not supported
hgs
parents:
diff changeset
   802
	if (EThumb2EEMode == info.iMode)
hgs
parents:
diff changeset
   803
		{
hgs
parents:
diff changeset
   804
		LOG_MSG("D_RMD_Breakpoints::priv_DoModifyBreak() - EThumb2EEMode breakpoints are not supported");
hgs
parents:
diff changeset
   805
		return KErrNotSupported;
hgs
parents:
diff changeset
   806
		}
hgs
parents:
diff changeset
   807
hgs
parents:
diff changeset
   808
	// find the break entry matching this id.  note that the breakpoints are already sorted in ascending order by id
hgs
parents:
diff changeset
   809
	TBreakEntry entry;
hgs
parents:
diff changeset
   810
	entry.iBreakId = (TUint32)info.iBreakId;
hgs
parents:
diff changeset
   811
	TInt index = iBreakPointList.FindInSignedKeyOrder(entry);
hgs
parents:
diff changeset
   812
	if (index < 0)
hgs
parents:
diff changeset
   813
		{
hgs
parents:
diff changeset
   814
		// Could not find the breakpoint
hgs
parents:
diff changeset
   815
		LOG_MSG2("D_RMD_Breakpoints::priv_DoModifyBreak() - Could not find the breakpoint id 0x%08x",(TUint32)info.iBreakId);
hgs
parents:
diff changeset
   816
		return KErrNotFound;
hgs
parents:
diff changeset
   817
		}
hgs
parents:
diff changeset
   818
hgs
parents:
diff changeset
   819
	// first check its not obsolete
hgs
parents:
diff changeset
   820
	if (!iBreakPointList[index].iObsoleteLibraryBreakpoint)
hgs
parents:
diff changeset
   821
		{
hgs
parents:
diff changeset
   822
		// its still a valid breakpoint
hgs
parents:
diff changeset
   823
hgs
parents:
diff changeset
   824
		// remove the old breakpoint
hgs
parents:
diff changeset
   825
		NKern::ThreadEnterCS();
hgs
parents:
diff changeset
   826
		DThread* threadObj = DebugUtils::OpenThreadHandle(iBreakPointList[index].iId);
hgs
parents:
diff changeset
   827
		if (threadObj)
hgs
parents:
diff changeset
   828
			{
hgs
parents:
diff changeset
   829
			LOG_MSG2("D_RMD_Breakpoints::priv_DoModifyBreak - Unsetting breakpoint at address 0x%08x",iBreakPointList[index].iAddress);
hgs
parents:
diff changeset
   830
hgs
parents:
diff changeset
   831
			XTRAPD(r, XT_DEFAULT, err = DebugSupport::RestoreCode(threadObj, iBreakPointList[index].iAddress));
hgs
parents:
diff changeset
   832
			if (r != 0)
hgs
parents:
diff changeset
   833
				{
hgs
parents:
diff changeset
   834
				LOG_MSG("Failed to construct trap handler for DebugSupport::RestoreCode");
hgs
parents:
diff changeset
   835
				}
hgs
parents:
diff changeset
   836
hgs
parents:
diff changeset
   837
			// Close the thread handle which has been opened by OpenThreadHandle
hgs
parents:
diff changeset
   838
			threadObj->Close(NULL);
hgs
parents:
diff changeset
   839
			NKern::ThreadLeaveCS();
hgs
parents:
diff changeset
   840
			}
hgs
parents:
diff changeset
   841
		else
hgs
parents:
diff changeset
   842
			{
hgs
parents:
diff changeset
   843
			// Bad handle
hgs
parents:
diff changeset
   844
			LOG_MSG("D_RMD_Breakpoints::priv_DoModifyBreak - Could not identify the breakpoint thread id");
hgs
parents:
diff changeset
   845
			NKern::ThreadLeaveCS();
hgs
parents:
diff changeset
   846
			return KErrBadHandle;
hgs
parents:
diff changeset
   847
			}
hgs
parents:
diff changeset
   848
		}
hgs
parents:
diff changeset
   849
hgs
parents:
diff changeset
   850
	// make sure there is not already a breakpoint at the new address
hgs
parents:
diff changeset
   851
	for (TInt i = NUMBER_OF_TEMP_BREAKPOINTS; i < iBreakPointList.Count(); i++)
hgs
parents:
diff changeset
   852
		{
hgs
parents:
diff changeset
   853
		// Ignore data for the breakpoint entry being modified.
hgs
parents:
diff changeset
   854
		if (i != index)
hgs
parents:
diff changeset
   855
			{
hgs
parents:
diff changeset
   856
			/* We need to check if the breakpoint overlaps the address at all,
hgs
parents:
diff changeset
   857
			 * and this depends upon the size of the two breakpoints as well as 
hgs
parents:
diff changeset
   858
			 * their address.
hgs
parents:
diff changeset
   859
			 */
hgs
parents:
diff changeset
   860
hgs
parents:
diff changeset
   861
			// newInstSize = size in bytes of new breakpoint
hgs
parents:
diff changeset
   862
			TInt newInstSize = BreakSize(info.iMode);
hgs
parents:
diff changeset
   863
			if (newInstSize == 0)
hgs
parents:
diff changeset
   864
			{
hgs
parents:
diff changeset
   865
				LOG_MSG("D_RMD_Breakpoints::priv_DoModifyBreak - Unknown architecture type for new breakpoint");
hgs
parents:
diff changeset
   866
				return KErrNotSupported;
hgs
parents:
diff changeset
   867
			}
hgs
parents:
diff changeset
   868
hgs
parents:
diff changeset
   869
			// oldInstSize = size in bytes of the existing breakpoint
hgs
parents:
diff changeset
   870
			TInt oldInstSize = BreakSize(iBreakPointList[i].iMode);
hgs
parents:
diff changeset
   871
			if (oldInstSize == 0)
hgs
parents:
diff changeset
   872
			{
hgs
parents:
diff changeset
   873
				LOG_MSG("D_RMD_Breakpoints::priv_DoModifyBreak - Unknown architecture type of existing breakpoint");
hgs
parents:
diff changeset
   874
				return KErrNotSupported;
hgs
parents:
diff changeset
   875
			}
hgs
parents:
diff changeset
   876
hgs
parents:
diff changeset
   877
			// Overlap checking - temp is used as the new breakpoint description for checking purposes only
hgs
parents:
diff changeset
   878
			TBreakEntry temp;
hgs
parents:
diff changeset
   879
hgs
parents:
diff changeset
   880
			temp.iAddress = info.iAddress;
hgs
parents:
diff changeset
   881
			temp.iMode = info.iMode;
hgs
parents:
diff changeset
   882
hgs
parents:
diff changeset
   883
			// do they overlap?
hgs
parents:
diff changeset
   884
			if ( BreakpointsOverlap(temp,iBreakPointList[i]) )
hgs
parents:
diff changeset
   885
				{
hgs
parents:
diff changeset
   886
				// Yes
hgs
parents:
diff changeset
   887
				LOG_MSG("D_RMD_Breakpoints::priv_DoModifyBreak() - New breakpoint overlaps an existing breakpoint");
hgs
parents:
diff changeset
   888
				return KErrAlreadyExists;
hgs
parents:
diff changeset
   889
				}
hgs
parents:
diff changeset
   890
			}
hgs
parents:
diff changeset
   891
		}
hgs
parents:
diff changeset
   892
hgs
parents:
diff changeset
   893
	// Prepare iBreakPointList[index] with the new information, then set the breakpoint
hgs
parents:
diff changeset
   894
	iBreakPointList[index].iId = info.iId;
hgs
parents:
diff changeset
   895
	iBreakPointList[index].iAddress = info.iAddress;
hgs
parents:
diff changeset
   896
	iBreakPointList[index].iMode = info.iMode;
hgs
parents:
diff changeset
   897
hgs
parents:
diff changeset
   898
	TBreakEntry& newBreakEntry = iBreakPointList[index];
hgs
parents:
diff changeset
   899
hgs
parents:
diff changeset
   900
	// Decide the size of the breakpoint instruction
hgs
parents:
diff changeset
   901
	TUint32 inst = BreakInst(newBreakEntry.iMode);
hgs
parents:
diff changeset
   902
	TInt instSize = BreakSize(newBreakEntry.iMode);
hgs
parents:
diff changeset
   903
hgs
parents:
diff changeset
   904
	if (inst == 0 || instSize == 0)
hgs
parents:
diff changeset
   905
		{
hgs
parents:
diff changeset
   906
		// Unsupported architecture
hgs
parents:
diff changeset
   907
		LOG_MSG("D_RMD_Breakpoints::priv_DoModifyBreak - unsupported breakpoint architecture");
hgs
parents:
diff changeset
   908
		return KErrNotSupported;
hgs
parents:
diff changeset
   909
		}
hgs
parents:
diff changeset
   910
hgs
parents:
diff changeset
   911
hgs
parents:
diff changeset
   912
	//if thread id is 0xFFFFFFFF, then the breakpoint is not thread specific
hgs
parents:
diff changeset
   913
	if (newBreakEntry.iId != 0xFFFFFFFF)
hgs
parents:
diff changeset
   914
		{
hgs
parents:
diff changeset
   915
		newBreakEntry.iThreadSpecific = ETrue;
hgs
parents:
diff changeset
   916
		}
hgs
parents:
diff changeset
   917
hgs
parents:
diff changeset
   918
	// Get thread id from the process that we are debugging
hgs
parents:
diff changeset
   919
	TProcessInfo * proc = NULL;
hgs
parents:
diff changeset
   920
	TUint64 threadId = NULL;
hgs
parents:
diff changeset
   921
hgs
parents:
diff changeset
   922
	threadId = newBreakEntry.iId;
hgs
parents:
diff changeset
   923
hgs
parents:
diff changeset
   924
	NKern::ThreadEnterCS();
hgs
parents:
diff changeset
   925
	DThread* threadObj = DebugUtils::OpenThreadHandle(threadId);
hgs
parents:
diff changeset
   926
	//if we don't have the right thread id for the address, 
hgs
parents:
diff changeset
   927
	//then try with the thread id of the process that we are debugging 	
hgs
parents:
diff changeset
   928
	if (!threadObj && iChannel->iDebugProcessList.Count())
hgs
parents:
diff changeset
   929
		{
hgs
parents:
diff changeset
   930
		proc = &iChannel->iDebugProcessList[0];
hgs
parents:
diff changeset
   931
		if (proc)
hgs
parents:
diff changeset
   932
			{
hgs
parents:
diff changeset
   933
			threadId = proc->iId+1;	
hgs
parents:
diff changeset
   934
			}
hgs
parents:
diff changeset
   935
		threadObj = DebugUtils::OpenThreadHandle(threadId);
hgs
parents:
diff changeset
   936
		}
hgs
parents:
diff changeset
   937
hgs
parents:
diff changeset
   938
	if(!threadObj)
hgs
parents:
diff changeset
   939
		{
hgs
parents:
diff changeset
   940
		LOG_MSG("D_RMD_Breakpoints::priv_DoModifyBreak() - bad handle. Could not identify a threadObj");
hgs
parents:
diff changeset
   941
		NKern::ThreadLeaveCS();
hgs
parents:
diff changeset
   942
		return KErrBadHandle;
hgs
parents:
diff changeset
   943
		}
hgs
parents:
diff changeset
   944
hgs
parents:
diff changeset
   945
	// save the old instruction
hgs
parents:
diff changeset
   946
	TUint32 instruction;
hgs
parents:
diff changeset
   947
hgs
parents:
diff changeset
   948
	// read the instruction at the address so we can store it in the break entry for when we clear this breakpoint
hgs
parents:
diff changeset
   949
	// trap exceptions in case the address is invalid
hgs
parents:
diff changeset
   950
	XTRAPD(r, XT_DEFAULT, err = iChannel->TryToReadMemory(threadObj, (TAny *)newBreakEntry.iAddress, (TAny *)&instruction, instSize));
hgs
parents:
diff changeset
   951
hgs
parents:
diff changeset
   952
	//consider the leave as more important than the error code so store the leave if it's not KErrNone
hgs
parents:
diff changeset
   953
	if(KErrNone != r)
hgs
parents:
diff changeset
   954
		{
hgs
parents:
diff changeset
   955
		err = r;
hgs
parents:
diff changeset
   956
		}
hgs
parents:
diff changeset
   957
	if(KErrNone != err)
hgs
parents:
diff changeset
   958
		{
hgs
parents:
diff changeset
   959
		threadObj->Close(NULL);
hgs
parents:
diff changeset
   960
		NKern::ThreadLeaveCS();
hgs
parents:
diff changeset
   961
		return err;
hgs
parents:
diff changeset
   962
		}
hgs
parents:
diff changeset
   963
hgs
parents:
diff changeset
   964
	newBreakEntry.iInstruction.Copy((TUint8 *)&instruction, instSize);
hgs
parents:
diff changeset
   965
hgs
parents:
diff changeset
   966
	newBreakEntry.iId = threadId; //set the thread ID here 
hgs
parents:
diff changeset
   967
	LOG_MSG3("ModifyCode2 instSize:%d, inst: 0x%08x", instSize, inst);
hgs
parents:
diff changeset
   968
	XTRAPD(s, XT_DEFAULT, err = DebugSupport::ModifyCode(threadObj, newBreakEntry.iAddress, instSize, inst, DebugSupport::EBreakpointGlobal));
hgs
parents:
diff changeset
   969
	if(s != DebugSupport::EBreakpointGlobal)
hgs
parents:
diff changeset
   970
		{
hgs
parents:
diff changeset
   971
		err = s;
hgs
parents:
diff changeset
   972
		}
hgs
parents:
diff changeset
   973
hgs
parents:
diff changeset
   974
	// Close the thread handle which has been opened by OpenThreadHandle
hgs
parents:
diff changeset
   975
	threadObj->Close(NULL);
hgs
parents:
diff changeset
   976
	NKern::ThreadLeaveCS();
hgs
parents:
diff changeset
   977
	return err;
hgs
parents:
diff changeset
   978
	}	
hgs
parents:
diff changeset
   979
hgs
parents:
diff changeset
   980
//
hgs
parents:
diff changeset
   981
// D_RMD_Breakpoints::DoModifyProcessBreak
hgs
parents:
diff changeset
   982
//
hgs
parents:
diff changeset
   983
TInt D_RMD_Breakpoints::DoModifyProcessBreak(TModifyProcessBreakInfo* aBreakInfo)
hgs
parents:
diff changeset
   984
	{
hgs
parents:
diff changeset
   985
	// Ensure we have a valid semaphore
hgs
parents:
diff changeset
   986
	if (!iInitialised || !iLock)
hgs
parents:
diff changeset
   987
		{
hgs
parents:
diff changeset
   988
		return KErrNotReady;
hgs
parents:
diff changeset
   989
		}
hgs
parents:
diff changeset
   990
hgs
parents:
diff changeset
   991
	// Acquire the lock
hgs
parents:
diff changeset
   992
	NKern::ThreadEnterCS();
hgs
parents:
diff changeset
   993
	Kern::SemaphoreWait(*iLock); 
hgs
parents:
diff changeset
   994
hgs
parents:
diff changeset
   995
	// Really do the work
hgs
parents:
diff changeset
   996
	TInt err = priv_DoModifyProcessBreak(aBreakInfo);
hgs
parents:
diff changeset
   997
	
hgs
parents:
diff changeset
   998
	// Release the lock
hgs
parents:
diff changeset
   999
	Kern::SemaphoreSignal(*iLock);
hgs
parents:
diff changeset
  1000
	NKern::ThreadLeaveCS();
hgs
parents:
diff changeset
  1001
hgs
parents:
diff changeset
  1002
	return err;
hgs
parents:
diff changeset
  1003
	}
hgs
parents:
diff changeset
  1004
	
hgs
parents:
diff changeset
  1005
TInt D_RMD_Breakpoints::priv_DoModifyProcessBreak(TModifyProcessBreakInfo* aBreakInfo)
hgs
parents:
diff changeset
  1006
	{	
hgs
parents:
diff changeset
  1007
	LOG_MSG("D_RMD_Breakpoints::priv_DoModifyProcessBreak()");
hgs
parents:
diff changeset
  1008
hgs
parents:
diff changeset
  1009
	// Check arguments
hgs
parents:
diff changeset
  1010
	if (!aBreakInfo)
hgs
parents:
diff changeset
  1011
		{
hgs
parents:
diff changeset
  1012
		LOG_MSG("D_RMD_Breakpoints::priv_DoModifyProcessBreak() was passed a NULL argument");
hgs
parents:
diff changeset
  1013
		return KErrArgument;
hgs
parents:
diff changeset
  1014
		}
hgs
parents:
diff changeset
  1015
hgs
parents:
diff changeset
  1016
	//User side memory is not accessible directly
hgs
parents:
diff changeset
  1017
	TSetBreakInfo info;
hgs
parents:
diff changeset
  1018
	TInt err = Kern::ThreadRawRead(iChannel->iClientThread, aBreakInfo, (TUint8*)&info, sizeof(TModifyProcessBreakInfo));
hgs
parents:
diff changeset
  1019
	if (err != KErrNone)
hgs
parents:
diff changeset
  1020
		{
hgs
parents:
diff changeset
  1021
		LOG_MSG("D_RMD_Breakpoints::priv_DoModifyProcessBreak() was passed a bad argument");
hgs
parents:
diff changeset
  1022
		return err;
hgs
parents:
diff changeset
  1023
		}
hgs
parents:
diff changeset
  1024
hgs
parents:
diff changeset
  1025
	// EThumb2EEMode breakpoints are not supported
hgs
parents:
diff changeset
  1026
	if (EThumb2EEMode == info.iMode)
hgs
parents:
diff changeset
  1027
		{
hgs
parents:
diff changeset
  1028
		LOG_MSG("D_RMD_Breakpoints::priv_DoModifyProcessBreak() - EThumb2EEMode breakpoints are not supported");
hgs
parents:
diff changeset
  1029
		return KErrNotSupported;
hgs
parents:
diff changeset
  1030
		}
hgs
parents:
diff changeset
  1031
hgs
parents:
diff changeset
  1032
	// find the break entry matching this id.  note that the breakpoints are already sorted in ascending order by id
hgs
parents:
diff changeset
  1033
	TBreakEntry entry;
hgs
parents:
diff changeset
  1034
	entry.iBreakId = (TUint32)info.iBreakId;
hgs
parents:
diff changeset
  1035
	TInt index = iBreakPointList.FindInSignedKeyOrder(entry);
hgs
parents:
diff changeset
  1036
	if (index < 0)
hgs
parents:
diff changeset
  1037
		{
hgs
parents:
diff changeset
  1038
		// Could not find the breakpoint
hgs
parents:
diff changeset
  1039
		LOG_MSG2("D_RMD_Breakpoints::priv_DoModifyProcessBreak() - Could not find the breakpoint id 0x%08x",(TUint32)info.iBreakId);
hgs
parents:
diff changeset
  1040
		return KErrNotFound;
hgs
parents:
diff changeset
  1041
		}
hgs
parents:
diff changeset
  1042
hgs
parents:
diff changeset
  1043
	// first check its not obsolete
hgs
parents:
diff changeset
  1044
	if (!iBreakPointList[index].iObsoleteLibraryBreakpoint)
hgs
parents:
diff changeset
  1045
		{
hgs
parents:
diff changeset
  1046
		// its still a valid breakpoint
hgs
parents:
diff changeset
  1047
hgs
parents:
diff changeset
  1048
		// remove the old breakpoint
hgs
parents:
diff changeset
  1049
		NKern::ThreadEnterCS();
hgs
parents:
diff changeset
  1050
		DProcess *process = DebugUtils::OpenProcessHandle(iBreakPointList[index].iId);
hgs
parents:
diff changeset
  1051
		DThread* threadObj = NULL;
hgs
parents:
diff changeset
  1052
		if(process)
hgs
parents:
diff changeset
  1053
			{
hgs
parents:
diff changeset
  1054
			threadObj = DebugUtils::OpenFirstThreadForProcess(process);
hgs
parents:
diff changeset
  1055
			process->Close(NULL);
hgs
parents:
diff changeset
  1056
			}
hgs
parents:
diff changeset
  1057
hgs
parents:
diff changeset
  1058
		if (threadObj)
hgs
parents:
diff changeset
  1059
			{
hgs
parents:
diff changeset
  1060
			LOG_MSG2("D_RMD_Breakpoints::priv_DoModifyProcessBreak() - Unsetting breakpoint at address 0x%08x",iBreakPointList[index].iAddress);
hgs
parents:
diff changeset
  1061
hgs
parents:
diff changeset
  1062
			XTRAPD(r, XT_DEFAULT, /*err =*/ DebugSupport::RestoreCode(threadObj, iBreakPointList[index].iAddress)); // Any error here is not important. The semantics of ModifyBreakpoint are such that if it fails the previous breakpoint location is removed, which means that a further call to ModifyBreakpoint shouldn't fail because the CodeModifier doesn't know about it.
hgs
parents:
diff changeset
  1063
			if (r != 0)
hgs
parents:
diff changeset
  1064
				{
hgs
parents:
diff changeset
  1065
				LOG_MSG("D_RMD_Breakpoints::priv_DoModifyProcessBreak() - Failed to construct trap handler for DebugSupport::RestoreCode");
hgs
parents:
diff changeset
  1066
				}
hgs
parents:
diff changeset
  1067
hgs
parents:
diff changeset
  1068
			// Close the thread handle which has been opened by OpenThreadHandle
hgs
parents:
diff changeset
  1069
			threadObj->Close(NULL);
hgs
parents:
diff changeset
  1070
			}
hgs
parents:
diff changeset
  1071
		else
hgs
parents:
diff changeset
  1072
			{
hgs
parents:
diff changeset
  1073
			// Bad handle
hgs
parents:
diff changeset
  1074
			LOG_MSG("D_RMD_Breakpoints::priv_DoModifyProcessBreak() - Could not identify the breakpoint process id");
hgs
parents:
diff changeset
  1075
			err = KErrBadHandle;
hgs
parents:
diff changeset
  1076
			}
hgs
parents:
diff changeset
  1077
		NKern::ThreadLeaveCS();
hgs
parents:
diff changeset
  1078
		if (err) return err;
hgs
parents:
diff changeset
  1079
		}
hgs
parents:
diff changeset
  1080
hgs
parents:
diff changeset
  1081
	// make sure there is not already a breakpoint at the new address
hgs
parents:
diff changeset
  1082
	for (TInt i = NUMBER_OF_TEMP_BREAKPOINTS; i < iBreakPointList.Count(); i++)
hgs
parents:
diff changeset
  1083
		{
hgs
parents:
diff changeset
  1084
		// Ignore data for the breakpoint entry being modified.
hgs
parents:
diff changeset
  1085
		if (i != index)
hgs
parents:
diff changeset
  1086
			{
hgs
parents:
diff changeset
  1087
			/* We need to check if the breakpoint overlaps the address at all,
hgs
parents:
diff changeset
  1088
			 * and this depends upon the size of the two breakpoints as well as 
hgs
parents:
diff changeset
  1089
			 * their address.
hgs
parents:
diff changeset
  1090
			 */
hgs
parents:
diff changeset
  1091
hgs
parents:
diff changeset
  1092
			// newInstSize = size in bytes of new breakpoint
hgs
parents:
diff changeset
  1093
			TInt newInstSize = BreakSize(info.iMode);
hgs
parents:
diff changeset
  1094
			if (newInstSize == 0)
hgs
parents:
diff changeset
  1095
				{
hgs
parents:
diff changeset
  1096
				LOG_MSG("D_RMD_Breakpoints::priv_DoModifyProcessBreak() - Unknown architecture type for new breakpoint");
hgs
parents:
diff changeset
  1097
				return KErrNotSupported;
hgs
parents:
diff changeset
  1098
				}
hgs
parents:
diff changeset
  1099
hgs
parents:
diff changeset
  1100
			// oldInstSize = size in bytes of the existing breakpoint
hgs
parents:
diff changeset
  1101
			TInt oldInstSize = BreakSize(iBreakPointList[i].iMode);
hgs
parents:
diff changeset
  1102
			if (oldInstSize == 0)
hgs
parents:
diff changeset
  1103
				{
hgs
parents:
diff changeset
  1104
				LOG_MSG("D_RMD_Breakpoints::priv_DoModifyProcessBreak() - : Unknown architecture type of existing breakpoint");
hgs
parents:
diff changeset
  1105
				return KErrNotSupported;
hgs
parents:
diff changeset
  1106
				}
hgs
parents:
diff changeset
  1107
hgs
parents:
diff changeset
  1108
			// Overlap checking - temp is used as the new breakpoint description for checking purposes only
hgs
parents:
diff changeset
  1109
			TBreakEntry temp;
hgs
parents:
diff changeset
  1110
hgs
parents:
diff changeset
  1111
			temp.iAddress = info.iAddress;
hgs
parents:
diff changeset
  1112
			temp.iMode = info.iMode;
hgs
parents:
diff changeset
  1113
hgs
parents:
diff changeset
  1114
			// do they overlap?
hgs
parents:
diff changeset
  1115
			if ( BreakpointsOverlap(temp,iBreakPointList[i]) )
hgs
parents:
diff changeset
  1116
				{
hgs
parents:
diff changeset
  1117
				// Yes
hgs
parents:
diff changeset
  1118
				LOG_MSG("D_RMD_Breakpoints::priv_DoModifyProcessBreak() - New breakpoint overlaps an existing breakpoint");
hgs
parents:
diff changeset
  1119
				return KErrAlreadyExists;
hgs
parents:
diff changeset
  1120
				}
hgs
parents:
diff changeset
  1121
			}
hgs
parents:
diff changeset
  1122
		}
hgs
parents:
diff changeset
  1123
hgs
parents:
diff changeset
  1124
	// Prepare iBreakPointList[index] with the new information, then set the breakpoint
hgs
parents:
diff changeset
  1125
	iBreakPointList[index].iId = info.iId;
hgs
parents:
diff changeset
  1126
	iBreakPointList[index].iAddress = info.iAddress;
hgs
parents:
diff changeset
  1127
	iBreakPointList[index].iMode = info.iMode;
hgs
parents:
diff changeset
  1128
hgs
parents:
diff changeset
  1129
	TBreakEntry& newBreakEntry = iBreakPointList[index];
hgs
parents:
diff changeset
  1130
hgs
parents:
diff changeset
  1131
	// Decide the size of the breakpoint instruction
hgs
parents:
diff changeset
  1132
	TUint32 inst = BreakInst(newBreakEntry.iMode);
hgs
parents:
diff changeset
  1133
	TInt instSize = BreakSize(newBreakEntry.iMode);
hgs
parents:
diff changeset
  1134
hgs
parents:
diff changeset
  1135
	if (inst == 0 || instSize == 0)
hgs
parents:
diff changeset
  1136
		{
hgs
parents:
diff changeset
  1137
		// Unsupported architecture
hgs
parents:
diff changeset
  1138
		LOG_MSG("D_RMD_Breakpoints::priv_DoModifyProcessBreak() - unsupported breakpoint architecture");
hgs
parents:
diff changeset
  1139
		return KErrNotSupported;
hgs
parents:
diff changeset
  1140
		}
hgs
parents:
diff changeset
  1141
hgs
parents:
diff changeset
  1142
	newBreakEntry.iThreadSpecific = EFalse;
hgs
parents:
diff changeset
  1143
hgs
parents:
diff changeset
  1144
	DThread* threadObj = NULL;
hgs
parents:
diff changeset
  1145
	NKern::ThreadEnterCS();
hgs
parents:
diff changeset
  1146
	DProcess* process = DebugUtils::OpenProcessHandle(newBreakEntry.iId);
hgs
parents:
diff changeset
  1147
	if (process)
hgs
parents:
diff changeset
  1148
		{
hgs
parents:
diff changeset
  1149
		threadObj = DebugUtils::OpenFirstThreadForProcess(process);
hgs
parents:
diff changeset
  1150
		if (!threadObj) err = KErrNotFound;
hgs
parents:
diff changeset
  1151
		process->Close(NULL);
hgs
parents:
diff changeset
  1152
		}
hgs
parents:
diff changeset
  1153
	else
hgs
parents:
diff changeset
  1154
		{
hgs
parents:
diff changeset
  1155
		LOG_MSG("D_RMD_Breakpoints::priv_DoModifyProcessBreak() - bad handle. Could not identify a process");
hgs
parents:
diff changeset
  1156
		err = KErrBadHandle;
hgs
parents:
diff changeset
  1157
		}
hgs
parents:
diff changeset
  1158
hgs
parents:
diff changeset
  1159
	if (err)
hgs
parents:
diff changeset
  1160
		{
hgs
parents:
diff changeset
  1161
		NKern::ThreadLeaveCS();
hgs
parents:
diff changeset
  1162
		return err;
hgs
parents:
diff changeset
  1163
		}
hgs
parents:
diff changeset
  1164
hgs
parents:
diff changeset
  1165
	// save the old instruction
hgs
parents:
diff changeset
  1166
	TUint32 instruction;
hgs
parents:
diff changeset
  1167
hgs
parents:
diff changeset
  1168
	// read the instruction at the address so we can store it in the break entry for when we clear this breakpoint
hgs
parents:
diff changeset
  1169
	// trap exceptions in case the address is invalid
hgs
parents:
diff changeset
  1170
	XTRAPD(r, XT_DEFAULT, err = iChannel->TryToReadMemory(threadObj, (TAny *)newBreakEntry.iAddress, (TAny *)&instruction, instSize));
hgs
parents:
diff changeset
  1171
hgs
parents:
diff changeset
  1172
	//consider the leave as more important than the error code so store the leave if it's not KErrNone
hgs
parents:
diff changeset
  1173
	if(KErrNone != r)
hgs
parents:
diff changeset
  1174
		{
hgs
parents:
diff changeset
  1175
		err = r;
hgs
parents:
diff changeset
  1176
		}
hgs
parents:
diff changeset
  1177
	if(KErrNone != err)
hgs
parents:
diff changeset
  1178
		{
hgs
parents:
diff changeset
  1179
		threadObj->Close(NULL);
hgs
parents:
diff changeset
  1180
		NKern::ThreadLeaveCS();
hgs
parents:
diff changeset
  1181
		return err;
hgs
parents:
diff changeset
  1182
		}
hgs
parents:
diff changeset
  1183
hgs
parents:
diff changeset
  1184
	newBreakEntry.iInstruction.Copy((TUint8 *)&instruction, instSize);
hgs
parents:
diff changeset
  1185
hgs
parents:
diff changeset
  1186
	XTRAPD(s, XT_DEFAULT, err = DebugSupport::ModifyCode(threadObj, newBreakEntry.iAddress, instSize, inst, DebugSupport::EBreakpointGlobal));
hgs
parents:
diff changeset
  1187
	if(s != DebugSupport::EBreakpointGlobal)
hgs
parents:
diff changeset
  1188
		{
hgs
parents:
diff changeset
  1189
		err = s;
hgs
parents:
diff changeset
  1190
		}
hgs
parents:
diff changeset
  1191
hgs
parents:
diff changeset
  1192
	// Close the thread handle which has been opened by OpenThreadHandle
hgs
parents:
diff changeset
  1193
	threadObj->Close(NULL);
hgs
parents:
diff changeset
  1194
	NKern::ThreadLeaveCS();
hgs
parents:
diff changeset
  1195
	return err;
hgs
parents:
diff changeset
  1196
	}
hgs
parents:
diff changeset
  1197
hgs
parents:
diff changeset
  1198
/**
hgs
parents:
diff changeset
  1199
Public member function which returns information about a previously set breakpoint.
hgs
parents:
diff changeset
  1200
hgs
parents:
diff changeset
  1201
Note 1:
hgs
parents:
diff changeset
  1202
This function ensures exclusive access to the breakpoint data structures
hgs
parents:
diff changeset
  1203
by using a semaphore to serialise access.
hgs
parents:
diff changeset
  1204
hgs
parents:
diff changeset
  1205
@see priv_DoBreakInfo
hgs
parents:
diff changeset
  1206
hgs
parents:
diff changeset
  1207
Note 2:
hgs
parents:
diff changeset
  1208
As implied by Note 1, the caller must have previously called Init() or this
hgs
parents:
diff changeset
  1209
function will return KErrNotReady;
hgs
parents:
diff changeset
  1210
hgs
parents:
diff changeset
  1211
@param aBreakInfo Address of aBreakInfo structure in user-side memory within the DSS client thread. CAN ONLY BE ACCESSED VIA Kern::ThreadRawRead()
hgs
parents:
diff changeset
  1212
@return KErrNone if successful, otherwise one of the other system wide error codes.
hgs
parents:
diff changeset
  1213
*/
hgs
parents:
diff changeset
  1214
TInt D_RMD_Breakpoints::DoBreakInfo(TGetBreakInfo* aBreakInfo)
hgs
parents:
diff changeset
  1215
	{
hgs
parents:
diff changeset
  1216
	// Ensure we have a valid semaphore
hgs
parents:
diff changeset
  1217
	if (!iInitialised || !iLock)
hgs
parents:
diff changeset
  1218
		{
hgs
parents:
diff changeset
  1219
		return KErrNotReady;
hgs
parents:
diff changeset
  1220
		}
hgs
parents:
diff changeset
  1221
hgs
parents:
diff changeset
  1222
	// Acquire the lock
hgs
parents:
diff changeset
  1223
	NKern::ThreadEnterCS();
hgs
parents:
diff changeset
  1224
	Kern::SemaphoreWait(*iLock);
hgs
parents:
diff changeset
  1225
hgs
parents:
diff changeset
  1226
	// Really do the work
hgs
parents:
diff changeset
  1227
	TInt err = priv_DoBreakInfo(aBreakInfo);
hgs
parents:
diff changeset
  1228
	
hgs
parents:
diff changeset
  1229
	// Release the lock
hgs
parents:
diff changeset
  1230
	Kern::SemaphoreSignal(*iLock);
hgs
parents:
diff changeset
  1231
	NKern::ThreadLeaveCS();
hgs
parents:
diff changeset
  1232
hgs
parents:
diff changeset
  1233
	return err;
hgs
parents:
diff changeset
  1234
	}
hgs
parents:
diff changeset
  1235
hgs
parents:
diff changeset
  1236
/**
hgs
parents:
diff changeset
  1237
Private member function function which returns information about a previously set breakpoint..
hgs
parents:
diff changeset
  1238
hgs
parents:
diff changeset
  1239
@see DoBreakInfo
hgs
parents:
diff changeset
  1240
hgs
parents:
diff changeset
  1241
@param aBreakInfo Address of aBreakInfo structure in user-side memory within the DSS client thread. CAN ONLY BE ACCESSED VIA Kern::ThreadRawRead()
hgs
parents:
diff changeset
  1242
@return KErrNone if successful, otherwise one of the other system wide error codes.
hgs
parents:
diff changeset
  1243
*/
hgs
parents:
diff changeset
  1244
TInt D_RMD_Breakpoints::priv_DoBreakInfo(TGetBreakInfo* aBreakInfo)
hgs
parents:
diff changeset
  1245
	{
hgs
parents:
diff changeset
  1246
	LOG_MSG("D_RMD_Breakpoints::priv_DoBreakInfo()");
hgs
parents:
diff changeset
  1247
hgs
parents:
diff changeset
  1248
	if (!aBreakInfo)
hgs
parents:
diff changeset
  1249
		{
hgs
parents:
diff changeset
  1250
		LOG_MSG("D_RMD_Breakpoints::priv_DoBreakInfo() was passed a NULL argument");
hgs
parents:
diff changeset
  1251
hgs
parents:
diff changeset
  1252
		return KErrArgument;
hgs
parents:
diff changeset
  1253
		}
hgs
parents:
diff changeset
  1254
hgs
parents:
diff changeset
  1255
	//User side memory is not accessible directly
hgs
parents:
diff changeset
  1256
	TGetBreakInfo info;
hgs
parents:
diff changeset
  1257
	TInt err = Kern::ThreadRawRead(iChannel->iClientThread, aBreakInfo, (TUint8*)&info, sizeof(TGetBreakInfo));
hgs
parents:
diff changeset
  1258
	if (err != KErrNone)
hgs
parents:
diff changeset
  1259
		{
hgs
parents:
diff changeset
  1260
		LOG_MSG("D_RMD_Breakpoints::priv_DoBreakInfo() was passed a bad argument");
hgs
parents:
diff changeset
  1261
hgs
parents:
diff changeset
  1262
		return err;
hgs
parents:
diff changeset
  1263
		}
hgs
parents:
diff changeset
  1264
hgs
parents:
diff changeset
  1265
	// find the break entry matching this id.  note that the breakpoints are already sorted in ascending order by id
hgs
parents:
diff changeset
  1266
	TBreakEntry entry;
hgs
parents:
diff changeset
  1267
	entry.iBreakId = (TUint32)info.iBreakId;
hgs
parents:
diff changeset
  1268
	TInt index = iBreakPointList.FindInSignedKeyOrder(entry);
hgs
parents:
diff changeset
  1269
	
hgs
parents:
diff changeset
  1270
	if (index >=0)
hgs
parents:
diff changeset
  1271
		{
hgs
parents:
diff changeset
  1272
		// get the thread id for this breakpoint
hgs
parents:
diff changeset
  1273
		TUint64 threadId = iBreakPointList[index].iId;
hgs
parents:
diff changeset
  1274
hgs
parents:
diff changeset
  1275
		err = Kern::ThreadRawWrite(iChannel->iClientThread,(TUint8*)info.iId,&threadId,sizeof(TUint64));
hgs
parents:
diff changeset
  1276
		if (err != KErrNone)
hgs
parents:
diff changeset
  1277
			{
hgs
parents:
diff changeset
  1278
			LOG_MSG("D_RMD_Breakpoints::priv_DoBreakInfo() - failed to return breakpoint iThreadId information");
hgs
parents:
diff changeset
  1279
			return err;
hgs
parents:
diff changeset
  1280
			}
hgs
parents:
diff changeset
  1281
hgs
parents:
diff changeset
  1282
		// get the threadSpecific-ness
hgs
parents:
diff changeset
  1283
		TBool threadSpecific = iBreakPointList[index].iThreadSpecific;
hgs
parents:
diff changeset
  1284
hgs
parents:
diff changeset
  1285
		err = Kern::ThreadRawWrite(iChannel->iClientThread,(TUint8*)info.iThreadSpecific,&threadSpecific,sizeof(TBool));
hgs
parents:
diff changeset
  1286
		if (err != KErrNone)
hgs
parents:
diff changeset
  1287
			{
hgs
parents:
diff changeset
  1288
			LOG_MSG("D_RMD_Breakpoints::priv_DoBreakInfo() - failed to return thread specific information");
hgs
parents:
diff changeset
  1289
			return err;
hgs
parents:
diff changeset
  1290
			}
hgs
parents:
diff changeset
  1291
hgs
parents:
diff changeset
  1292
hgs
parents:
diff changeset
  1293
		// get the address
hgs
parents:
diff changeset
  1294
		TUint32 address = iBreakPointList[index].iAddress;
hgs
parents:
diff changeset
  1295
hgs
parents:
diff changeset
  1296
		err = Kern::ThreadRawWrite(iChannel->iClientThread,(TUint8*)info.iAddress,&address,sizeof(TUint32));
hgs
parents:
diff changeset
  1297
		if (err != KErrNone)
hgs
parents:
diff changeset
  1298
			{
hgs
parents:
diff changeset
  1299
			LOG_MSG("D_RMD_Breakpoints::priv_DoBreakInfo() - failed to return breakpoint iAddress information");
hgs
parents:
diff changeset
  1300
			return err;
hgs
parents:
diff changeset
  1301
			}
hgs
parents:
diff changeset
  1302
hgs
parents:
diff changeset
  1303
hgs
parents:
diff changeset
  1304
		// get the architecture
hgs
parents:
diff changeset
  1305
		TArchitectureMode mode = iBreakPointList[index].iMode;
hgs
parents:
diff changeset
  1306
hgs
parents:
diff changeset
  1307
		err = Kern::ThreadRawWrite(iChannel->iClientThread,(TUint8*)info.iMode,&mode,sizeof(TUint32));
hgs
parents:
diff changeset
  1308
		if (err != KErrNone)
hgs
parents:
diff changeset
  1309
			{
hgs
parents:
diff changeset
  1310
			LOG_MSG("D_RMD_Breakpoints::priv_DoBreakInfo() - failed to return breakpoint iMode information");
hgs
parents:
diff changeset
  1311
			return err;
hgs
parents:
diff changeset
  1312
			}
hgs
parents:
diff changeset
  1313
hgs
parents:
diff changeset
  1314
		return err;
hgs
parents:
diff changeset
  1315
		}
hgs
parents:
diff changeset
  1316
hgs
parents:
diff changeset
  1317
	LOG_MSG2("D_RMD_Breakpoints::priv_DoBreakInfo - Could not find the breakpoint id specified 0x%08x", entry.iBreakId);
hgs
parents:
diff changeset
  1318
	return KErrNotFound;
hgs
parents:
diff changeset
  1319
	}
hgs
parents:
diff changeset
  1320
hgs
parents:
diff changeset
  1321
/**
hgs
parents:
diff changeset
  1322
Public member function which clears all the breakpoints in the system. Generally used for shutting down
hgs
parents:
diff changeset
  1323
the debug device driver.
hgs
parents:
diff changeset
  1324
hgs
parents:
diff changeset
  1325
Note 1:
hgs
parents:
diff changeset
  1326
This function ensures exclusive access to the breakpoint data structures
hgs
parents:
diff changeset
  1327
by using a semaphore to serialise access.
hgs
parents:
diff changeset
  1328
hgs
parents:
diff changeset
  1329
@see priv_ClearAllBreakPoints
hgs
parents:
diff changeset
  1330
hgs
parents:
diff changeset
  1331
Note 2:
hgs
parents:
diff changeset
  1332
As implied by Note 1, the caller must have previously called Init() or this
hgs
parents:
diff changeset
  1333
function will return KErrNotReady;
hgs
parents:
diff changeset
  1334
*/
hgs
parents:
diff changeset
  1335
void D_RMD_Breakpoints::ClearAllBreakPoints()
hgs
parents:
diff changeset
  1336
	{
hgs
parents:
diff changeset
  1337
	// Ensure we have a valid semaphore
hgs
parents:
diff changeset
  1338
	if (!iInitialised || !iLock)
hgs
parents:
diff changeset
  1339
		{
hgs
parents:
diff changeset
  1340
		return;
hgs
parents:
diff changeset
  1341
		}
hgs
parents:
diff changeset
  1342
hgs
parents:
diff changeset
  1343
	// Acquire the lock
hgs
parents:
diff changeset
  1344
	NKern::ThreadEnterCS();
hgs
parents:
diff changeset
  1345
	Kern::SemaphoreWait(*iLock);
hgs
parents:
diff changeset
  1346
hgs
parents:
diff changeset
  1347
	// Really do the work
hgs
parents:
diff changeset
  1348
	priv_ClearAllBreakPoints();
hgs
parents:
diff changeset
  1349
	
hgs
parents:
diff changeset
  1350
	// Release the lock
hgs
parents:
diff changeset
  1351
	Kern::SemaphoreSignal(*iLock);
hgs
parents:
diff changeset
  1352
	NKern::ThreadLeaveCS();
hgs
parents:
diff changeset
  1353
	}
hgs
parents:
diff changeset
  1354
hgs
parents:
diff changeset
  1355
/**
hgs
parents:
diff changeset
  1356
Private member function which clears all the breakpoints in the system. Generally used for shutting down
hgs
parents:
diff changeset
  1357
the debug device driver. 
hgs
parents:
diff changeset
  1358
hgs
parents:
diff changeset
  1359
@see DoClearAllBreakPoints
hgs
parents:
diff changeset
  1360
*/
hgs
parents:
diff changeset
  1361
void D_RMD_Breakpoints::priv_ClearAllBreakPoints()
hgs
parents:
diff changeset
  1362
	{
hgs
parents:
diff changeset
  1363
	LOG_MSG("D_RMD_Breakpoints::priv_ClearAllBreakPoints()");
hgs
parents:
diff changeset
  1364
hgs
parents:
diff changeset
  1365
	TInt err = KErrNone;
hgs
parents:
diff changeset
  1366
	NKern::ThreadEnterCS();
hgs
parents:
diff changeset
  1367
	for (TInt i=0; i<iBreakPointList.Count(); i++)
hgs
parents:
diff changeset
  1368
		{
hgs
parents:
diff changeset
  1369
		if ((iBreakPointList[i].iAddress != 0) && !iBreakPointList[i].iObsoleteLibraryBreakpoint)
hgs
parents:
diff changeset
  1370
			{
hgs
parents:
diff changeset
  1371
			TUint32 id = iBreakPointList[i].iId + (iBreakPointList[i].iThreadSpecific ? 0 : 1);
hgs
parents:
diff changeset
  1372
	        LOG_MSG5(" Will try to clear breakpoint[%d] at address 0x%x, iId=0x%016lx, thrdSpec=%d", 
hgs
parents:
diff changeset
  1373
	                i, iBreakPointList[i].iAddress, iBreakPointList[i].iId, iBreakPointList[i].iThreadSpecific);
hgs
parents:
diff changeset
  1374
hgs
parents:
diff changeset
  1375
			DThread *threadObj = DebugUtils::OpenThreadHandle(id);
hgs
parents:
diff changeset
  1376
			if (threadObj)
hgs
parents:
diff changeset
  1377
				{
hgs
parents:
diff changeset
  1378
				XTRAPD(r, XT_DEFAULT, err = DebugSupport::RestoreCode(threadObj, iBreakPointList[i].iAddress));
hgs
parents:
diff changeset
  1379
				err = (KErrNone == r) ? err : r;
hgs
parents:
diff changeset
  1380
				threadObj->Close(NULL);
hgs
parents:
diff changeset
  1381
				}
hgs
parents:
diff changeset
  1382
			else
hgs
parents:
diff changeset
  1383
				{
hgs
parents:
diff changeset
  1384
                LOG_MSG(" OpenThreadHandle returned NULL handle");
hgs
parents:
diff changeset
  1385
				err = KErrBadHandle;
hgs
parents:
diff changeset
  1386
				}
hgs
parents:
diff changeset
  1387
hgs
parents:
diff changeset
  1388
			if (KErrNone != err)
hgs
parents:
diff changeset
  1389
				{
hgs
parents:
diff changeset
  1390
				LOG_MSG2("D_RMD_Breakpoints::priv_ClearAllBreakPoints() - Error 0x%08x while clearing breakpoint", err);
hgs
parents:
diff changeset
  1391
				}
hgs
parents:
diff changeset
  1392
			}
hgs
parents:
diff changeset
  1393
		else if(iBreakPointList[i].iAddress == 0)
hgs
parents:
diff changeset
  1394
		    {
hgs
parents:
diff changeset
  1395
            LOG_MSG3("Breakpoint[%d]: address is 0, iId=0x%016lx", i, iBreakPointList[i].iId );		
hgs
parents:
diff changeset
  1396
		    }
hgs
parents:
diff changeset
  1397
		else
hgs
parents:
diff changeset
  1398
		    {
hgs
parents:
diff changeset
  1399
            LOG_MSG4("Breakpoint[%d]: Obsoleted, address =0x%x, iId=0x%016lx", i, iBreakPointList[i].iAddress, iBreakPointList[i].iId );     
hgs
parents:
diff changeset
  1400
		    }
hgs
parents:
diff changeset
  1401
		}
hgs
parents:
diff changeset
  1402
	NKern::ThreadLeaveCS();
hgs
parents:
diff changeset
  1403
hgs
parents:
diff changeset
  1404
	iBreakPointList.Reset();
hgs
parents:
diff changeset
  1405
	}
hgs
parents:
diff changeset
  1406
hgs
parents:
diff changeset
  1407
/**
hgs
parents:
diff changeset
  1408
Public member function which disables the breakpoint at the specified address.
hgs
parents:
diff changeset
  1409
hgs
parents:
diff changeset
  1410
Note 1:
hgs
parents:
diff changeset
  1411
This function ensures exclusive access to the breakpoint data structures
hgs
parents:
diff changeset
  1412
by using a semaphore to serialise access.
hgs
parents:
diff changeset
  1413
hgs
parents:
diff changeset
  1414
@see priv_DisableBreakAtAddress
hgs
parents:
diff changeset
  1415
hgs
parents:
diff changeset
  1416
Note 2:
hgs
parents:
diff changeset
  1417
As implied by Note 1, the caller must have previously called Init() or this
hgs
parents:
diff changeset
  1418
function will return KErrNotReady;
hgs
parents:
diff changeset
  1419
hgs
parents:
diff changeset
  1420
@param aAddress Address at which to disable breakpoints (all threads)
hgs
parents:
diff changeset
  1421
@return KErrNone if successful, one of the other system wide error codes otherwise.
hgs
parents:
diff changeset
  1422
*/
hgs
parents:
diff changeset
  1423
TInt D_RMD_Breakpoints::DisableBreakAtAddress(TUint32 aAddress)
hgs
parents:
diff changeset
  1424
	{
hgs
parents:
diff changeset
  1425
	// Ensure we have a valid semaphore
hgs
parents:
diff changeset
  1426
	if (!iInitialised || !iLock)
hgs
parents:
diff changeset
  1427
		{
hgs
parents:
diff changeset
  1428
		return KErrNotReady;
hgs
parents:
diff changeset
  1429
		}
hgs
parents:
diff changeset
  1430
hgs
parents:
diff changeset
  1431
	// Acquire the lock
hgs
parents:
diff changeset
  1432
	NKern::ThreadEnterCS();
hgs
parents:
diff changeset
  1433
	Kern::SemaphoreWait(*iLock);
hgs
parents:
diff changeset
  1434
hgs
parents:
diff changeset
  1435
	// Really do the work
hgs
parents:
diff changeset
  1436
	TInt err = priv_DisableBreakAtAddress(aAddress);
hgs
parents:
diff changeset
  1437
	
hgs
parents:
diff changeset
  1438
	// Release the lock
hgs
parents:
diff changeset
  1439
	Kern::SemaphoreSignal(*iLock);
hgs
parents:
diff changeset
  1440
	NKern::ThreadLeaveCS();
hgs
parents:
diff changeset
  1441
hgs
parents:
diff changeset
  1442
	return err;
hgs
parents:
diff changeset
  1443
	}
hgs
parents:
diff changeset
  1444
hgs
parents:
diff changeset
  1445
/**
hgs
parents:
diff changeset
  1446
Private member function which clears all the breakpoints in the system. Generally used for shutting down
hgs
parents:
diff changeset
  1447
the debug device driver. 
hgs
parents:
diff changeset
  1448
hgs
parents:
diff changeset
  1449
@see DisableBreakAtAddress
hgs
parents:
diff changeset
  1450
hgs
parents:
diff changeset
  1451
@param aAddress clears the breakpoint at the specified address
hgs
parents:
diff changeset
  1452
@return KErrNone if successful, one of the other system wide error codes otherwise.
hgs
parents:
diff changeset
  1453
*/
hgs
parents:
diff changeset
  1454
TInt D_RMD_Breakpoints::priv_DisableBreakAtAddress(TUint32 aAddress)
hgs
parents:
diff changeset
  1455
	{
hgs
parents:
diff changeset
  1456
	LOG_MSG2("D_RMD_Breakpoints::priv_DisableBreakAtAddress(aAddress=0x%x)", aAddress);
hgs
parents:
diff changeset
  1457
hgs
parents:
diff changeset
  1458
	TInt err = KErrNone;
hgs
parents:
diff changeset
  1459
hgs
parents:
diff changeset
  1460
	for (TInt i = NUMBER_OF_TEMP_BREAKPOINTS; i < iBreakPointList.Count(); i++)
hgs
parents:
diff changeset
  1461
		{
hgs
parents:
diff changeset
  1462
		if (iBreakPointList[i].iAddress == aAddress)
hgs
parents:
diff changeset
  1463
			{
hgs
parents:
diff changeset
  1464
			iBreakPointList[i].iDisabledForStep = ETrue;
hgs
parents:
diff changeset
  1465
			LOG_MSG2("D_RMD_Breakpoints::priv_DisableBreakAtAddress - Disabling breakpoint at address 0x%x", iBreakPointList[i].iAddress);
hgs
parents:
diff changeset
  1466
hgs
parents:
diff changeset
  1467
			//clear the breakpoint with code modifier
hgs
parents:
diff changeset
  1468
			//code modifier will restore the org instruction and also frees the shadow page if necessary
hgs
parents:
diff changeset
  1469
			TUint64 id = iBreakPointList[i].iId + (iBreakPointList[i].iThreadSpecific ? 0 : 1);
hgs
parents:
diff changeset
  1470
			DThread* threadObj = NULL;
hgs
parents:
diff changeset
  1471
			NKern::ThreadEnterCS();
hgs
parents:
diff changeset
  1472
			if(iBreakPointList[i].iThreadSpecific)
hgs
parents:
diff changeset
  1473
				{
hgs
parents:
diff changeset
  1474
				threadObj = DebugUtils::OpenThreadHandle(id);
hgs
parents:
diff changeset
  1475
				}
hgs
parents:
diff changeset
  1476
			else
hgs
parents:
diff changeset
  1477
				{
hgs
parents:
diff changeset
  1478
				DProcess* process = DebugUtils::OpenProcessHandle(iBreakPointList[i].iId);
hgs
parents:
diff changeset
  1479
				if(process)
hgs
parents:
diff changeset
  1480
					{
hgs
parents:
diff changeset
  1481
					threadObj = DebugUtils::OpenFirstThreadForProcess(process);
hgs
parents:
diff changeset
  1482
					process->Close(NULL);
hgs
parents:
diff changeset
  1483
					}
hgs
parents:
diff changeset
  1484
				}
hgs
parents:
diff changeset
  1485
hgs
parents:
diff changeset
  1486
			if (threadObj)
hgs
parents:
diff changeset
  1487
				{
hgs
parents:
diff changeset
  1488
				XTRAPD(r, XT_DEFAULT, err = DebugSupport::RestoreCode(threadObj, aAddress));			
hgs
parents:
diff changeset
  1489
				if(KErrNone != err || KErrNone != r)
hgs
parents:
diff changeset
  1490
					{
hgs
parents:
diff changeset
  1491
					LOG_MSG3("Error from DebugSupport::RestoreCode: r: %d, err: %d", r, err);
hgs
parents:
diff changeset
  1492
					}
hgs
parents:
diff changeset
  1493
				err = (KErrNone == r) ? err : r;
hgs
parents:
diff changeset
  1494
				threadObj->Close(NULL);
hgs
parents:
diff changeset
  1495
				}
hgs
parents:
diff changeset
  1496
			else
hgs
parents:
diff changeset
  1497
				{
hgs
parents:
diff changeset
  1498
				err = KErrBadHandle;
hgs
parents:
diff changeset
  1499
				LOG_MSG2("Couldn't find thread for breakpoint id %d", iBreakPointList[i].iId);
hgs
parents:
diff changeset
  1500
				}
hgs
parents:
diff changeset
  1501
			NKern::ThreadLeaveCS();
hgs
parents:
diff changeset
  1502
			if (err) break;
hgs
parents:
diff changeset
  1503
			}
hgs
parents:
diff changeset
  1504
		}
hgs
parents:
diff changeset
  1505
		
hgs
parents:
diff changeset
  1506
	return err;
hgs
parents:
diff changeset
  1507
	}
hgs
parents:
diff changeset
  1508
hgs
parents:
diff changeset
  1509
/**
hgs
parents:
diff changeset
  1510
Public member function which enables previously disabled breakpoints within a given thread.
hgs
parents:
diff changeset
  1511
hgs
parents:
diff changeset
  1512
Note 1:
hgs
parents:
diff changeset
  1513
This function ensures exclusive access to the breakpoint data structures
hgs
parents:
diff changeset
  1514
by using a semaphore to serialise access. 
hgs
parents:
diff changeset
  1515
hgs
parents:
diff changeset
  1516
@see priv_DoEnableDisabledBreak
hgs
parents:
diff changeset
  1517
hgs
parents:
diff changeset
  1518
Note 2:
hgs
parents:
diff changeset
  1519
As implied by Note 1, the caller must have previously called Init() or this
hgs
parents:
diff changeset
  1520
function will return KErrNotReady;
hgs
parents:
diff changeset
  1521
hgs
parents:
diff changeset
  1522
@param aThreadId Thread in which to enable all previously disabled breakpoints
hgs
parents:
diff changeset
  1523
@return KErrNone if successful, one of the system wide error codes otherwise.
hgs
parents:
diff changeset
  1524
*/
hgs
parents:
diff changeset
  1525
TInt D_RMD_Breakpoints::DoEnableDisabledBreak(TUint64 aThreadId)
hgs
parents:
diff changeset
  1526
	{
hgs
parents:
diff changeset
  1527
	// Ensure we have a valid semaphore
hgs
parents:
diff changeset
  1528
	if (!iInitialised || !iLock)
hgs
parents:
diff changeset
  1529
		{
hgs
parents:
diff changeset
  1530
		return KErrNotReady;
hgs
parents:
diff changeset
  1531
		}
hgs
parents:
diff changeset
  1532
hgs
parents:
diff changeset
  1533
	// Acquire the lock
hgs
parents:
diff changeset
  1534
	NKern::ThreadEnterCS();
hgs
parents:
diff changeset
  1535
	Kern::SemaphoreWait(*iLock);
hgs
parents:
diff changeset
  1536
hgs
parents:
diff changeset
  1537
	// Really do the work
hgs
parents:
diff changeset
  1538
	TInt err = priv_DoEnableDisabledBreak(aThreadId);
hgs
parents:
diff changeset
  1539
	
hgs
parents:
diff changeset
  1540
	// Release the lock
hgs
parents:
diff changeset
  1541
	Kern::SemaphoreSignal(*iLock);
hgs
parents:
diff changeset
  1542
	NKern::ThreadLeaveCS();
hgs
parents:
diff changeset
  1543
hgs
parents:
diff changeset
  1544
	return err;
hgs
parents:
diff changeset
  1545
	}
hgs
parents:
diff changeset
  1546
hgs
parents:
diff changeset
  1547
/**
hgs
parents:
diff changeset
  1548
Private member function which enables previously disabled breakpoints within a given thread.
hgs
parents:
diff changeset
  1549
hgs
parents:
diff changeset
  1550
@see DoEnableDisabledBreak
hgs
parents:
diff changeset
  1551
hgs
parents:
diff changeset
  1552
@param aThreadId Thread in which to enable all previously disabled breakpoints
hgs
parents:
diff changeset
  1553
@return KErrNone if successful, one of the system wide error codes otherwise.
hgs
parents:
diff changeset
  1554
*/
hgs
parents:
diff changeset
  1555
TInt D_RMD_Breakpoints::priv_DoEnableDisabledBreak(TUint64 aThreadId)
hgs
parents:
diff changeset
  1556
	{
hgs
parents:
diff changeset
  1557
	LOG_MSG("D_RMD_Breakpoints::priv_DoEnableDisabledBreak()");
hgs
parents:
diff changeset
  1558
	NKern::ThreadEnterCS();
hgs
parents:
diff changeset
  1559
	DThread* thread = DebugUtils::OpenThreadHandle(aThreadId);
hgs
parents:
diff changeset
  1560
	if(!thread)
hgs
parents:
diff changeset
  1561
		{
hgs
parents:
diff changeset
  1562
		LOG_MSG2("Thread: 0x%08x does not exist", aThreadId);
hgs
parents:
diff changeset
  1563
		NKern::ThreadLeaveCS();
hgs
parents:
diff changeset
  1564
		return KErrNotFound;
hgs
parents:
diff changeset
  1565
		}
hgs
parents:
diff changeset
  1566
	TUint64 processId = thread->iOwningProcess->iId;
hgs
parents:
diff changeset
  1567
	thread->Close(NULL);
hgs
parents:
diff changeset
  1568
	NKern::ThreadLeaveCS();
hgs
parents:
diff changeset
  1569
hgs
parents:
diff changeset
  1570
	for (TInt i = NUMBER_OF_TEMP_BREAKPOINTS; i < iBreakPointList.Count(); i++)
hgs
parents:
diff changeset
  1571
		{
hgs
parents:
diff changeset
  1572
		TBool needsEnabling = EFalse;
hgs
parents:
diff changeset
  1573
		if(iBreakPointList[i].iDisabledForStep)
hgs
parents:
diff changeset
  1574
			{
hgs
parents:
diff changeset
  1575
			if(iBreakPointList[i].iThreadSpecific)
hgs
parents:
diff changeset
  1576
				{
hgs
parents:
diff changeset
  1577
				needsEnabling = (aThreadId == iBreakPointList[i].iId);
hgs
parents:
diff changeset
  1578
				}
hgs
parents:
diff changeset
  1579
			else
hgs
parents:
diff changeset
  1580
				{
hgs
parents:
diff changeset
  1581
				needsEnabling = (processId == iBreakPointList[i].iId);
hgs
parents:
diff changeset
  1582
				}
hgs
parents:
diff changeset
  1583
			}
hgs
parents:
diff changeset
  1584
		if (needsEnabling)
hgs
parents:
diff changeset
  1585
			{
hgs
parents:
diff changeset
  1586
			LOG_MSG2("Re-enabling breakpoint at address %x", iBreakPointList[i].iAddress);
hgs
parents:
diff changeset
  1587
			TInt err = priv_DoEnableBreak(iBreakPointList[i], EFalse);
hgs
parents:
diff changeset
  1588
			if(KErrNone != err)
hgs
parents:
diff changeset
  1589
				{
hgs
parents:
diff changeset
  1590
				LOG_MSG2("Error returned from DoEnableBreak: %d", err);
hgs
parents:
diff changeset
  1591
				iBreakPointList[i].iDisabledForStep = EFalse;
hgs
parents:
diff changeset
  1592
				return err;
hgs
parents:
diff changeset
  1593
				}
hgs
parents:
diff changeset
  1594
			}
hgs
parents:
diff changeset
  1595
		}
hgs
parents:
diff changeset
  1596
	
hgs
parents:
diff changeset
  1597
	return KErrNone;
hgs
parents:
diff changeset
  1598
	}
hgs
parents:
diff changeset
  1599
hgs
parents:
diff changeset
  1600
/**
hgs
parents:
diff changeset
  1601
Public member function which removes all the breakpoints within a given thread.
hgs
parents:
diff changeset
  1602
hgs
parents:
diff changeset
  1603
Note 1:
hgs
parents:
diff changeset
  1604
This function ensures exclusive access to the breakpoint data structures
hgs
parents:
diff changeset
  1605
by using a semaphore to serialise access.
hgs
parents:
diff changeset
  1606
hgs
parents:
diff changeset
  1607
@see priv_DoRemoveThreadBreaks
hgs
parents:
diff changeset
  1608
hgs
parents:
diff changeset
  1609
Note 2:
hgs
parents:
diff changeset
  1610
As implied by Note 1, the caller must have previously called Init() or this
hgs
parents:
diff changeset
  1611
function will return KErrNotReady;
hgs
parents:
diff changeset
  1612
hgs
parents:
diff changeset
  1613
@param aThreadId Thread from which to remove all existing breakpoints
hgs
parents:
diff changeset
  1614
@return KErrNone if successful, one of the system wide error codes otherwise.
hgs
parents:
diff changeset
  1615
*/
hgs
parents:
diff changeset
  1616
void D_RMD_Breakpoints::DoRemoveThreadBreaks(TUint64 aThreadId)
hgs
parents:
diff changeset
  1617
	{
hgs
parents:
diff changeset
  1618
	// Ensure we have a valid semaphore
hgs
parents:
diff changeset
  1619
	if (!iInitialised || !iLock)
hgs
parents:
diff changeset
  1620
		{
hgs
parents:
diff changeset
  1621
		return;
hgs
parents:
diff changeset
  1622
		}
hgs
parents:
diff changeset
  1623
hgs
parents:
diff changeset
  1624
	// Acquire the lock
hgs
parents:
diff changeset
  1625
	NKern::ThreadEnterCS();
hgs
parents:
diff changeset
  1626
	Kern::SemaphoreWait(*iLock);
hgs
parents:
diff changeset
  1627
hgs
parents:
diff changeset
  1628
	// Really do the work
hgs
parents:
diff changeset
  1629
	priv_DoRemoveThreadBreaks(aThreadId);
hgs
parents:
diff changeset
  1630
hgs
parents:
diff changeset
  1631
	// Release the lock
hgs
parents:
diff changeset
  1632
	Kern::SemaphoreSignal(*iLock);
hgs
parents:
diff changeset
  1633
	NKern::ThreadLeaveCS();
hgs
parents:
diff changeset
  1634
	}
hgs
parents:
diff changeset
  1635
hgs
parents:
diff changeset
  1636
/**
hgs
parents:
diff changeset
  1637
Private member function which removes all the breakpoints particular to a particular thread
hgs
parents:
diff changeset
  1638
hgs
parents:
diff changeset
  1639
@see DoRemoveThreadBreaks
hgs
parents:
diff changeset
  1640
hgs
parents:
diff changeset
  1641
@param aThreadId Thread from which to remove all existing breakpoints
hgs
parents:
diff changeset
  1642
@return KErrNone if successful, one of the system wide error codes otherwise.
hgs
parents:
diff changeset
  1643
*/
hgs
parents:
diff changeset
  1644
void D_RMD_Breakpoints::priv_DoRemoveThreadBreaks(TUint64 aThreadId)
hgs
parents:
diff changeset
  1645
	{
hgs
parents:
diff changeset
  1646
	LOG_MSG2("D_RMD_Breakpoints::priv_DoRemoveThreadBreaks(aThreadId = 0x%lx)\n",aThreadId);
hgs
parents:
diff changeset
  1647
hgs
parents:
diff changeset
  1648
	TInt err = KErrNone;
hgs
parents:
diff changeset
  1649
	TUint64 threadId;
hgs
parents:
diff changeset
  1650
hgs
parents:
diff changeset
  1651
	for (TInt i=iBreakPointList.Count()-1; i >= 0; i--)
hgs
parents:
diff changeset
  1652
		{
hgs
parents:
diff changeset
  1653
		if ((iBreakPointList[i].iAddress != 0) && !iBreakPointList[i].iObsoleteLibraryBreakpoint)
hgs
parents:
diff changeset
  1654
			{
hgs
parents:
diff changeset
  1655
			threadId = iBreakPointList[i].iId + (iBreakPointList[i].iThreadSpecific ? 0 : 1);
hgs
parents:
diff changeset
  1656
			if (threadId == aThreadId)
hgs
parents:
diff changeset
  1657
				{
hgs
parents:
diff changeset
  1658
				LOG_MSG5("D_RMD_Breakpoints::priv_DoRemoveThreadBreaks() - Clearing breakpoint[%d],idx=%x at address 0x%08x, iId=0x%016lx", 
hgs
parents:
diff changeset
  1659
				        i, iBreakPointList[i].iBreakId, iBreakPointList[i].iAddress, iBreakPointList[i].iId );
hgs
parents:
diff changeset
  1660
hgs
parents:
diff changeset
  1661
				err = priv_DoClearBreak(iBreakPointList[i].iBreakId, EFalse);
hgs
parents:
diff changeset
  1662
hgs
parents:
diff changeset
  1663
				if (err != KErrNone)
hgs
parents:
diff changeset
  1664
					{
hgs
parents:
diff changeset
  1665
					LOG_MSG2("D_RMD_Breakpoints::priv_DoRemoveThreadBreaks()  - failed to remove break id 0x%08x\n",iBreakPointList[i].iBreakId);
hgs
parents:
diff changeset
  1666
					return;
hgs
parents:
diff changeset
  1667
					}
hgs
parents:
diff changeset
  1668
				}
hgs
parents:
diff changeset
  1669
			}
hgs
parents:
diff changeset
  1670
        else if(iBreakPointList[i].iAddress == 0)
hgs
parents:
diff changeset
  1671
            {
hgs
parents:
diff changeset
  1672
            LOG_MSG3("Breakpoint[%d]: address is 0, iId=0x%016lx", i, iBreakPointList[i].iId );     
hgs
parents:
diff changeset
  1673
            }
hgs
parents:
diff changeset
  1674
        else
hgs
parents:
diff changeset
  1675
            {
hgs
parents:
diff changeset
  1676
            LOG_MSG4("Breakpoint[%d]: Obsoleted, address =0x%x, iId=0x%016lx", i, iBreakPointList[i].iAddress, iBreakPointList[i].iId );     
hgs
parents:
diff changeset
  1677
            }		
hgs
parents:
diff changeset
  1678
		}	
hgs
parents:
diff changeset
  1679
	}
hgs
parents:
diff changeset
  1680
hgs
parents:
diff changeset
  1681
// Remove the process breakpoints for process with PID aProcessId in the range [aCodeAddress, aCodeAddress + aCodeSize)
hgs
parents:
diff changeset
  1682
void D_RMD_Breakpoints::RemoveBreaksForProcess(TUint64 aProcessId, TUint32 aCodeAddress, TUint32 aCodeSize)
hgs
parents:
diff changeset
  1683
	{
hgs
parents:
diff changeset
  1684
	LOG_MSG4("D_RMD_Breakpoints::RemoveBreaksForProcess(), aProcId=0x%016lx, codeAddr=0x%x, codeSize=0x%x", 
hgs
parents:
diff changeset
  1685
	        aProcessId,aCodeAddress, aCodeSize);
hgs
parents:
diff changeset
  1686
	NKern::ThreadEnterCS();
hgs
parents:
diff changeset
  1687
	for (TInt i=iBreakPointList.Count() - 1; i>=0; i--)
hgs
parents:
diff changeset
  1688
		{
hgs
parents:
diff changeset
  1689
        TBool remove = EFalse;
hgs
parents:
diff changeset
  1690
		TBreakEntry& breakEntry = iBreakPointList[i];
hgs
parents:
diff changeset
  1691
		
hgs
parents:
diff changeset
  1692
		if( breakEntry.iId == 0 || breakEntry.iAddress == 0 )
hgs
parents:
diff changeset
  1693
		    {
hgs
parents:
diff changeset
  1694
            breakEntry.Reset();
hgs
parents:
diff changeset
  1695
		    continue;
hgs
parents:
diff changeset
  1696
		    }
hgs
parents:
diff changeset
  1697
		
hgs
parents:
diff changeset
  1698
		LOG_MSG5(" break[%d], iId=0x%016lx, threadSpec=%d, aProcessId=0x%016lx", 
hgs
parents:
diff changeset
  1699
		        i, breakEntry.iId, breakEntry.iThreadSpecific, aProcessId);
hgs
parents:
diff changeset
  1700
		
hgs
parents:
diff changeset
  1701
		if(!breakEntry.iThreadSpecific && breakEntry.iId == aProcessId)
hgs
parents:
diff changeset
  1702
		    {
hgs
parents:
diff changeset
  1703
		    remove = ETrue;
hgs
parents:
diff changeset
  1704
		    }
hgs
parents:
diff changeset
  1705
		else if(breakEntry.iThreadSpecific)
hgs
parents:
diff changeset
  1706
		    {
hgs
parents:
diff changeset
  1707
            //breakEntry.iId is thread id. Get its pid, then check if aProcessId is same, then remove
hgs
parents:
diff changeset
  1708
            DThread* thread = DebugUtils::OpenThreadHandle(breakEntry.iId);
hgs
parents:
diff changeset
  1709
            if(!thread)
hgs
parents:
diff changeset
  1710
                {
hgs
parents:
diff changeset
  1711
                LOG_MSG2("Could not open handle to thread (aThreadId = 0x%016lx)",breakEntry.iId);
hgs
parents:
diff changeset
  1712
                continue;
hgs
parents:
diff changeset
  1713
                }
hgs
parents:
diff changeset
  1714
            
hgs
parents:
diff changeset
  1715
            LOG_MSG2(" thread->iOwningProcess->iId=0x%016lx", thread->iOwningProcess->iId );
hgs
parents:
diff changeset
  1716
            
hgs
parents:
diff changeset
  1717
            if( thread->iOwningProcess->iId == aProcessId )
hgs
parents:
diff changeset
  1718
                {
hgs
parents:
diff changeset
  1719
                LOG_MSG3("Thread spec breakpoint @ index[%d] matches aProcessId= 0x%016lx. Removing",i, aProcessId);
hgs
parents:
diff changeset
  1720
                remove = ETrue;
hgs
parents:
diff changeset
  1721
                }
hgs
parents:
diff changeset
  1722
            
hgs
parents:
diff changeset
  1723
            thread->Close(NULL);
hgs
parents:
diff changeset
  1724
		    }
hgs
parents:
diff changeset
  1725
		    
hgs
parents:
diff changeset
  1726
        if ( remove && (breakEntry.iAddress >= aCodeAddress) && (breakEntry.iAddress < (aCodeAddress + aCodeSize)))
hgs
parents:
diff changeset
  1727
            {
hgs
parents:
diff changeset
  1728
            LOG_MSG2("Removing process breakpoint at address %x", (TUint32)breakEntry.iAddress);
hgs
parents:
diff changeset
  1729
            TInt err = DoClearBreak(breakEntry.iBreakId, ETrue);
hgs
parents:
diff changeset
  1730
            if(KErrNone != err)
hgs
parents:
diff changeset
  1731
                {
hgs
parents:
diff changeset
  1732
                LOG_MSG2("Error removing breakpoint: %d", err);
hgs
parents:
diff changeset
  1733
                }
hgs
parents:
diff changeset
  1734
            }
hgs
parents:
diff changeset
  1735
        else
hgs
parents:
diff changeset
  1736
            {
hgs
parents:
diff changeset
  1737
            LOG_MSG4("Not removing breakpoint at index[%d], id=0x%016lx, address=0x%x", 
hgs
parents:
diff changeset
  1738
                    i, breakEntry.iId, (TUint32)breakEntry.iAddress);
hgs
parents:
diff changeset
  1739
            }
hgs
parents:
diff changeset
  1740
		}
hgs
parents:
diff changeset
  1741
	NKern::ThreadLeaveCS();
hgs
parents:
diff changeset
  1742
	}
hgs
parents:
diff changeset
  1743
hgs
parents:
diff changeset
  1744
// mark the breakpoints in the range [aCodeAddress, aCodeAddress + aCodeSize)
hgs
parents:
diff changeset
  1745
void D_RMD_Breakpoints::InvalidateLibraryBreakPoints(TUint32 aCodeAddress, TUint32 aCodeSize)
hgs
parents:
diff changeset
  1746
	{
hgs
parents:
diff changeset
  1747
	LOG_MSG3("D_RMD_Breakpoints::InvalidateLibraryBreakPoints(aCodeAddress=0x%x, aCodeSize=0x%x)",
hgs
parents:
diff changeset
  1748
	        aCodeAddress, aCodeSize );
hgs
parents:
diff changeset
  1749
	
hgs
parents:
diff changeset
  1750
	for (TInt i=0; i<iBreakPointList.Count(); i++)
hgs
parents:
diff changeset
  1751
		{
hgs
parents:
diff changeset
  1752
		if ((iBreakPointList[i].iAddress >= aCodeAddress) && (iBreakPointList[i].iAddress < (aCodeAddress + aCodeSize)))
hgs
parents:
diff changeset
  1753
			{
hgs
parents:
diff changeset
  1754
			LOG_MSG2("Obsoleting library breakpoint at address %x", iBreakPointList[i].iAddress);
hgs
parents:
diff changeset
  1755
			iBreakPointList[i].iObsoleteLibraryBreakpoint = ETrue;
hgs
parents:
diff changeset
  1756
			}
hgs
parents:
diff changeset
  1757
		}
hgs
parents:
diff changeset
  1758
	}
hgs
parents:
diff changeset
  1759
hgs
parents:
diff changeset
  1760
TInt D_RMD_Breakpoints::BreakPointCount() const
hgs
parents:
diff changeset
  1761
	{
hgs
parents:
diff changeset
  1762
	return iBreakPointList.Count();
hgs
parents:
diff changeset
  1763
	}
hgs
parents:
diff changeset
  1764
hgs
parents:
diff changeset
  1765
/**
hgs
parents:
diff changeset
  1766
  Gets next breakpoint in list.
hgs
parents:
diff changeset
  1767
  @param aBreakEntry The break entry to get the successor of. If NULL then returns the first entry.
hgs
parents:
diff changeset
  1768
  @return A pointer to the next break entry, or NULL if the end of the list has been reached
hgs
parents:
diff changeset
  1769
  */
hgs
parents:
diff changeset
  1770
TBreakEntry* D_RMD_Breakpoints::GetNextBreak(const TBreakEntry* aBreakEntry) const
hgs
parents:
diff changeset
  1771
	{
hgs
parents:
diff changeset
  1772
	if(!aBreakEntry)
hgs
parents:
diff changeset
  1773
		{
hgs
parents:
diff changeset
  1774
		return (TBreakEntry*)&(iBreakPointList[0]);
hgs
parents:
diff changeset
  1775
		}
hgs
parents:
diff changeset
  1776
	TInt index = iBreakPointList.FindInSignedKeyOrder(*aBreakEntry) + 1;
hgs
parents:
diff changeset
  1777
	return (index < BreakPointCount()) ? (TBreakEntry*)&(iBreakPointList[index]) : NULL;
hgs
parents:
diff changeset
  1778
	}
hgs
parents:
diff changeset
  1779
hgs
parents:
diff changeset
  1780
TBool D_RMD_Breakpoints::IsTemporaryBreak(const TBreakEntry& aBreakEntry) const
hgs
parents:
diff changeset
  1781
	{
hgs
parents:
diff changeset
  1782
	// Ensure we have a valid semaphore
hgs
parents:
diff changeset
  1783
	if (!iInitialised || !iLock)
hgs
parents:
diff changeset
  1784
		{
hgs
parents:
diff changeset
  1785
		return EFalse;
hgs
parents:
diff changeset
  1786
		}
hgs
parents:
diff changeset
  1787
hgs
parents:
diff changeset
  1788
	// Acquire the lock
hgs
parents:
diff changeset
  1789
	NKern::ThreadEnterCS();
hgs
parents:
diff changeset
  1790
	Kern::SemaphoreWait(*iLock);
hgs
parents:
diff changeset
  1791
hgs
parents:
diff changeset
  1792
	// Really do the work
hgs
parents:
diff changeset
  1793
	TBool tempBreak = priv_IsTemporaryBreak(aBreakEntry);
hgs
parents:
diff changeset
  1794
	
hgs
parents:
diff changeset
  1795
	// Release the lock
hgs
parents:
diff changeset
  1796
	Kern::SemaphoreSignal(*iLock);
hgs
parents:
diff changeset
  1797
	NKern::ThreadLeaveCS();
hgs
parents:
diff changeset
  1798
	
hgs
parents:
diff changeset
  1799
	return tempBreak;
hgs
parents:
diff changeset
  1800
	}
hgs
parents:
diff changeset
  1801
hgs
parents:
diff changeset
  1802
/**
hgs
parents:
diff changeset
  1803
Private member function which tells us if a breakpoint is temporary
hgs
parents:
diff changeset
  1804
hgs
parents:
diff changeset
  1805
@see IsTemporaryBreak
hgs
parents:
diff changeset
  1806
hgs
parents:
diff changeset
  1807
@param aBreakEntry
hgs
parents:
diff changeset
  1808
@return TBool indicating if the break is temporary or not
hgs
parents:
diff changeset
  1809
*/
hgs
parents:
diff changeset
  1810
TBool D_RMD_Breakpoints::priv_IsTemporaryBreak(const TBreakEntry& aBreakEntry) const 
hgs
parents:
diff changeset
  1811
	{
hgs
parents:
diff changeset
  1812
	return aBreakEntry.iBreakId < NUMBER_OF_TEMP_BREAKPOINTS;
hgs
parents:
diff changeset
  1813
	}
hgs
parents:
diff changeset
  1814
hgs
parents:
diff changeset
  1815
hgs
parents:
diff changeset
  1816
// End of file - d_rmd_breakpoints.cpp