sl@0
|
1 |
// Copyright (c) 2004-2009 Nokia Corporation and/or its subsidiary(-ies).
|
sl@0
|
2 |
// All rights reserved.
|
sl@0
|
3 |
// This component and the accompanying materials are made available
|
sl@0
|
4 |
// under the terms of the License "Eclipse Public License v1.0"
|
sl@0
|
5 |
// which accompanies this distribution, and is available
|
sl@0
|
6 |
// at the URL "http://www.eclipse.org/legal/epl-v10.html".
|
sl@0
|
7 |
//
|
sl@0
|
8 |
// Initial Contributors:
|
sl@0
|
9 |
// Nokia Corporation - initial contribution.
|
sl@0
|
10 |
//
|
sl@0
|
11 |
// Contributors:
|
sl@0
|
12 |
//
|
sl@0
|
13 |
// Description:
|
sl@0
|
14 |
// Refactored class containing breakpoint related code from rm_debug_kerneldriver.cpp
|
sl@0
|
15 |
//
|
sl@0
|
16 |
|
sl@0
|
17 |
|
sl@0
|
18 |
|
sl@0
|
19 |
/**
|
sl@0
|
20 |
@file
|
sl@0
|
21 |
@internalComponent
|
sl@0
|
22 |
@released
|
sl@0
|
23 |
*/
|
sl@0
|
24 |
|
sl@0
|
25 |
#ifndef D_RMD_BREAKPOINTS_H
|
sl@0
|
26 |
#define D_RMD_BREAKPOINTS_H
|
sl@0
|
27 |
|
sl@0
|
28 |
#include <rm_debug_api.h>
|
sl@0
|
29 |
#include <kernel/kern_priv.h>
|
sl@0
|
30 |
#include "rm_debug_kerneldriver.h"
|
sl@0
|
31 |
|
sl@0
|
32 |
// fwd declaration of friend classes needed due to re-factoring
|
sl@0
|
33 |
class DRM_DebugChannel;
|
sl@0
|
34 |
|
sl@0
|
35 |
class DRMDStepper;
|
sl@0
|
36 |
|
sl@0
|
37 |
//
|
sl@0
|
38 |
// Macros
|
sl@0
|
39 |
//
|
sl@0
|
40 |
const TUint32 KArmBreakPoint = 0xE7F123F4;
|
sl@0
|
41 |
const TUint16 KThumbBreakPoint = 0xDE56;
|
sl@0
|
42 |
const TUint16 KT2EEBreakPoint = 0xC100; // From ARM ARM DDI0406A, section A9.2.1 Undefined instruction encoding for Thumb2-EE.
|
sl@0
|
43 |
|
sl@0
|
44 |
#define NUMBER_OF_TEMP_BREAKPOINTS 10
|
sl@0
|
45 |
|
sl@0
|
46 |
#define NUMBER_OF_MAX_BREAKPOINTS 100
|
sl@0
|
47 |
|
sl@0
|
48 |
//
|
sl@0
|
49 |
// class TBreakEntry
|
sl@0
|
50 |
//
|
sl@0
|
51 |
class TBreakEntry
|
sl@0
|
52 |
{
|
sl@0
|
53 |
public:
|
sl@0
|
54 |
|
sl@0
|
55 |
inline TBreakEntry() { Reset(); };
|
sl@0
|
56 |
|
sl@0
|
57 |
inline TBreakEntry(Debug::TBreakId aBreakId, TUint64 aId, TBool aThreadSpecific, TUint32 aAddress, Debug::TArchitectureMode aMode)
|
sl@0
|
58 |
: iBreakId(aBreakId),
|
sl@0
|
59 |
iId(aId),
|
sl@0
|
60 |
iAddress(aAddress),
|
sl@0
|
61 |
iMode(aMode),
|
sl@0
|
62 |
iThreadSpecific(aThreadSpecific)
|
sl@0
|
63 |
{
|
sl@0
|
64 |
iInstruction.FillZ(4);
|
sl@0
|
65 |
iPageAddress = 0;
|
sl@0
|
66 |
iDisabledForStep = EFalse;
|
sl@0
|
67 |
iObsoleteLibraryBreakpoint = EFalse;
|
sl@0
|
68 |
iResumeOnceOutOfRange = EFalse;
|
sl@0
|
69 |
iSteppingInto = EFalse;
|
sl@0
|
70 |
iRangeStart = 0;
|
sl@0
|
71 |
iRangeEnd = 0;
|
sl@0
|
72 |
iStepTarget = EFalse;
|
sl@0
|
73 |
iNumSteps = 0;
|
sl@0
|
74 |
};
|
sl@0
|
75 |
|
sl@0
|
76 |
inline void Reset()
|
sl@0
|
77 |
{
|
sl@0
|
78 |
iId = 0;
|
sl@0
|
79 |
iAddress = 0;
|
sl@0
|
80 |
iMode = Debug::EArmMode;
|
sl@0
|
81 |
iInstruction.FillZ(4);
|
sl@0
|
82 |
iPageAddress = 0;
|
sl@0
|
83 |
iDisabledForStep = EFalse;
|
sl@0
|
84 |
iObsoleteLibraryBreakpoint = EFalse;
|
sl@0
|
85 |
iResumeOnceOutOfRange = EFalse;
|
sl@0
|
86 |
iSteppingInto = EFalse;
|
sl@0
|
87 |
iRangeStart = 0;
|
sl@0
|
88 |
iRangeEnd = 0;
|
sl@0
|
89 |
iStepTarget = EFalse;
|
sl@0
|
90 |
iNumSteps = 0;
|
sl@0
|
91 |
};
|
sl@0
|
92 |
|
sl@0
|
93 |
public:
|
sl@0
|
94 |
// Unique Id for this breakpoint. Assigned by D_RMD_Breakpoints::DoSetBreak(). @see D_RMD_Breakpoints::DoSetBreak
|
sl@0
|
95 |
TInt32 iBreakId;
|
sl@0
|
96 |
// Consider making the iId into a union of TProcessId, TThreadId, global etc. to make things more obvious
|
sl@0
|
97 |
// Object Id in which this breakpoint should operate.
|
sl@0
|
98 |
TUint64 iId;
|
sl@0
|
99 |
// Address at which this breakpoint should operate
|
sl@0
|
100 |
TUint32 iAddress;
|
sl@0
|
101 |
// CPU ISA which this breakpoint uses, e.g. EArmMode/EThumbMode.
|
sl@0
|
102 |
Debug::TArchitectureMode iMode;
|
sl@0
|
103 |
// The original instruction which was stored at iAddress.
|
sl@0
|
104 |
TBuf8<4> iInstruction;
|
sl@0
|
105 |
TUint32 iPageAddress; //not used: BC if we remove it
|
sl@0
|
106 |
|
sl@0
|
107 |
// Indicates whether this breakpoint has been temporarily replaced with original instruction to enable step-off this breakpoint
|
sl@0
|
108 |
TBool iDisabledForStep;
|
sl@0
|
109 |
/* This is used when libraries and processes are removed, so that
|
sl@0
|
110 |
* the driver can say 'ok' when requested to remove breakpoints
|
sl@0
|
111 |
* that existed in these cases, rather than 'Not Found'.
|
sl@0
|
112 |
*
|
sl@0
|
113 |
* Its not logical, but its a BC break if we change it :-(
|
sl@0
|
114 |
*/
|
sl@0
|
115 |
TBool iObsoleteLibraryBreakpoint;
|
sl@0
|
116 |
// Indicates whether this thread should be resumed after stepping off this breakpoint
|
sl@0
|
117 |
TBool iResumeOnceOutOfRange;
|
sl@0
|
118 |
TBool iSteppingInto;
|
sl@0
|
119 |
TUint32 iRangeStart;
|
sl@0
|
120 |
TUint32 iRangeEnd;
|
sl@0
|
121 |
TBool iThreadSpecific;
|
sl@0
|
122 |
TBool iStepTarget;
|
sl@0
|
123 |
|
sl@0
|
124 |
// Indicates how many more instruction steps should occur after hitting this breakpoint
|
sl@0
|
125 |
TInt iNumSteps;
|
sl@0
|
126 |
};
|
sl@0
|
127 |
/**
|
sl@0
|
128 |
@internalTechnology
|
sl@0
|
129 |
|
sl@0
|
130 |
This class encapsulates all the data concerning run-mode and stop mode breakpoints
|
sl@0
|
131 |
as understood by the run-mode and stop-mode debug system.
|
sl@0
|
132 |
|
sl@0
|
133 |
Note:
|
sl@0
|
134 |
The internal list of breakpoints is currently divided into two sections. The range from
|
sl@0
|
135 |
0...NUMBER_OF_TEMP_BREAKPOINTS is used internally by the debug driver for implementing
|
sl@0
|
136 |
stepping. The range from NUMBER_OF_TEMP_BREAKPOINTS to NUMBER_OF_MAX_BREAKPOINTS is used
|
sl@0
|
137 |
to store information about breakpoints set by the client debug agents.
|
sl@0
|
138 |
|
sl@0
|
139 |
In future, this should change, so that each breakpoint knows what kind of breakpoint it
|
sl@0
|
140 |
is (user/temp etc).
|
sl@0
|
141 |
|
sl@0
|
142 |
|
sl@0
|
143 |
*/
|
sl@0
|
144 |
class D_RMD_Breakpoints : public DBase
|
sl@0
|
145 |
{
|
sl@0
|
146 |
public:
|
sl@0
|
147 |
D_RMD_Breakpoints(DRM_DebugChannel* aChannel);
|
sl@0
|
148 |
~D_RMD_Breakpoints();
|
sl@0
|
149 |
|
sl@0
|
150 |
TInt Init();
|
sl@0
|
151 |
|
sl@0
|
152 |
// from rm_debug_driver.h
|
sl@0
|
153 |
TInt DoSetBreak(TInt32 &aBreakId, const TUint64 aId, const TBool aThreadSpecific, const TUint32 aAddress, const Debug::TArchitectureMode aMode );
|
sl@0
|
154 |
TInt DoEnableBreak(TBreakEntry &aEntry, TBool aSaveOldInstruction);
|
sl@0
|
155 |
TInt DoClearBreak(const TInt32 aBreakId, TBool aIgnoreTerminatedThreads=EFalse);
|
sl@0
|
156 |
TInt DoModifyBreak(TModifyBreakInfo* aBreakInfo);
|
sl@0
|
157 |
TInt DoModifyProcessBreak(TModifyProcessBreakInfo* aBreakInfo);
|
sl@0
|
158 |
TInt DoBreakInfo(TGetBreakInfo* aBreakInfo);
|
sl@0
|
159 |
void ClearAllBreakPoints();
|
sl@0
|
160 |
TInt DisableBreakAtAddress(TUint32 aAddress);
|
sl@0
|
161 |
TInt DoEnableDisabledBreak(TUint64 aThreadId);
|
sl@0
|
162 |
|
sl@0
|
163 |
void DoRemoveThreadBreaks(TUint64 aThreadId);
|
sl@0
|
164 |
void RemoveBreaksForProcess(TUint64 aProcessId, TUint32 aCodeAddress, TUint32 aCodeSize);
|
sl@0
|
165 |
void InvalidateLibraryBreakPoints(TUint32 aCodeAddress, TUint32 aCodeSize);
|
sl@0
|
166 |
TInt BreakPointCount() const;
|
sl@0
|
167 |
TBreakEntry* GetNextBreak(const TBreakEntry* aBreakEntry) const;
|
sl@0
|
168 |
TBool IsTemporaryBreak(const TBreakEntry& aBreakEntry) const;
|
sl@0
|
169 |
|
sl@0
|
170 |
TInt DoGetBreakList(TUint32* aBuffer, const TUint32 aBufSize, const TUint32 aElement, TUint32& aLastElement);
|
sl@0
|
171 |
|
sl@0
|
172 |
private:
|
sl@0
|
173 |
// Locked versions of public functions
|
sl@0
|
174 |
TInt priv_DoSetBreak(TInt32 &aBreakId, const TUint64 aId, const TBool aThreadSpecific, const TUint32 aAddress, const Debug::TArchitectureMode aMode );
|
sl@0
|
175 |
TInt priv_DoEnableBreak(TBreakEntry &aEntry, TBool aSaveOldInstruction);
|
sl@0
|
176 |
TInt priv_DoClearBreak(const TInt32 aBreakId, TBool aIgnoreTerminatedThreads);
|
sl@0
|
177 |
TInt priv_DoModifyBreak(TModifyBreakInfo* aBreakInfo);
|
sl@0
|
178 |
TInt priv_DoModifyProcessBreak(TModifyProcessBreakInfo* aBreakInfo);
|
sl@0
|
179 |
TInt priv_DoBreakInfo(TGetBreakInfo* aBreakInfo);
|
sl@0
|
180 |
TInt priv_DisableBreakAtAddress(TUint32 aAddress);
|
sl@0
|
181 |
TInt priv_DoEnableDisabledBreak(TUint64 aThreadId);
|
sl@0
|
182 |
void priv_DoRemoveThreadBreaks(TUint64 aThreadId);
|
sl@0
|
183 |
void priv_ClearAllBreakPoints();
|
sl@0
|
184 |
TBool priv_IsTemporaryBreak(const TBreakEntry& aBreakEntry) const;
|
sl@0
|
185 |
|
sl@0
|
186 |
// helper functions
|
sl@0
|
187 |
TBool Aligned(TUint32 aAddress, Debug::TArchitectureMode aMode);
|
sl@0
|
188 |
TInt BreakSize(Debug::TArchitectureMode aMode);
|
sl@0
|
189 |
TBool BreakpointsOverlap(TBreakEntry& aFirst, TBreakEntry& aSecond);
|
sl@0
|
190 |
TUint32 BreakInst(Debug::TArchitectureMode aMode);
|
sl@0
|
191 |
|
sl@0
|
192 |
private:
|
sl@0
|
193 |
RArray<TBreakEntry> iBreakPointList;
|
sl@0
|
194 |
TInt iNextBreakId;
|
sl@0
|
195 |
|
sl@0
|
196 |
DRM_DebugChannel* iChannel; // temporary reference back to DRM_DebugChannel to help with refactoring
|
sl@0
|
197 |
|
sl@0
|
198 |
/* Protect access to the breakpoint list with a DSemaphore
|
sl@0
|
199 |
*
|
sl@0
|
200 |
* This means that stop-mode debuggers know when the list is being updated by the run-mode debug subsystem.
|
sl@0
|
201 |
*/
|
sl@0
|
202 |
DSemaphore* iLock;
|
sl@0
|
203 |
|
sl@0
|
204 |
TBool iInitialised;
|
sl@0
|
205 |
};
|
sl@0
|
206 |
|
sl@0
|
207 |
#endif
|