|
1 // fdebuggerkernel.h |
|
2 // |
|
3 // Copyright (c) 2010 Accenture. All rights reserved. |
|
4 // This component and the accompanying materials are made available |
|
5 // under the terms of the "Eclipse Public License v1.0" |
|
6 // which accompanies this distribution, and is available |
|
7 // at the URL "http://www.eclipse.org/legal/epl-v10.html". |
|
8 // |
|
9 // Initial Contributors: |
|
10 // Accenture - Initial contribution |
|
11 // |
|
12 #ifndef FDEBUGGERKERNEL_H |
|
13 #define FDEBUGGERKERNEL_H |
|
14 |
|
15 #include <nkern.h> |
|
16 #include <kernel.h> |
|
17 #include <kern_priv.h> |
|
18 |
|
19 #include <fshell/common.mmh> |
|
20 #include "memoryaccess.h" |
|
21 class TDynDfcQueWrapper; |
|
22 |
|
23 class MDebuggerEventClient |
|
24 { |
|
25 public: |
|
26 virtual void BreakpointHit(TDes& aPkg) =0; |
|
27 }; |
|
28 |
|
29 NONSHARABLE_CLASS(DDebuggerEventHandler) : public DKernelEventHandler |
|
30 { |
|
31 public: |
|
32 static DDebuggerEventHandler* New(TDfcQue* aQue); |
|
33 |
|
34 TInt GetZombieMode(); |
|
35 TInt SetZombieMode(TInt aMode); |
|
36 HBuf* GetZombieThreadIds(); |
|
37 TInt ReleaseZombie(DThread* aThread); |
|
38 TInt SuspendThread(DThread* aThread); |
|
39 |
|
40 TInt RegisterForBreakpointNotification(MDebuggerEventClient* aClient); |
|
41 void UnregisterForBreakpointNotification(MDebuggerEventClient* aClient); |
|
42 |
|
43 TInt SetBreakpoint(DThread* aThread, TLinAddr aAddress, const RMemoryAccess::TPredicate& aCondition); |
|
44 TInt SetSymbolicBreakpoint(DThread* aThread, HBuf* aCodesegName, TUint32 aOffset, const RMemoryAccess::TPredicate& aCondition); |
|
45 TInt RegisterPersistantBreakpoint(DThread* aThread, TLinAddr aAddress); |
|
46 TInt SetBreakpointEnabled(TInt aBreakpointId, TBool aEnabled); |
|
47 TInt ClearBreakpoint(TInt aBreakpointId); |
|
48 TInt ContinueFromBreakpoint(DThread* aThread, TLinAddr aExceptionAddress); |
|
49 HBuf* GetBreakpoints(); |
|
50 |
|
51 TUint GetCreatorThread(TUint aThreadId); // Returns 0 if not known |
|
52 |
|
53 private: |
|
54 DDebuggerEventHandler(TDfcQue* aQue); |
|
55 ~DDebuggerEventHandler(); |
|
56 static TUint Event(TKernelEvent aEvent, TAny* a1, TAny* a2, TAny* aPrivateData); |
|
57 TUint DoEvent(TKernelEvent aEvent, TAny* a1, TAny* a2); |
|
58 void CompleteZombies(); |
|
59 void Lock(); |
|
60 void Unlock(); |
|
61 void BreakpointLock(); |
|
62 void BreakpointUnlock(); |
|
63 struct SZombie; |
|
64 SZombie* FindZombie(DThread* aThread); |
|
65 void ReleaseZombie(SZombie* aZombie); |
|
66 void ReleaseZombieAndUnlock(SZombie* aZombie); |
|
67 void UnsuspendThread(SZombie* aZombie); |
|
68 TInt Zombify(TLinAddr aBreakpointAddr=0); |
|
69 struct SBreakpoint; |
|
70 SBreakpoint* FindBreakpointByAddress(/*DThread* aThread,*/ TLinAddr aAddress); |
|
71 SBreakpoint* FindBreakpointById(TInt aId); |
|
72 SBreakpoint* FindBreakpointUsingHardwareContextRegister(TInt aRegister); |
|
73 SBreakpoint* FindHardwareBreakpoint(DThread* aThread, TLinAddr aAddress); |
|
74 enum TBreakpointPolicy |
|
75 { |
|
76 EWhatever, |
|
77 EHardwareOnly, |
|
78 ESoftwareOnly, |
|
79 }; |
|
80 TInt ApplyBreakpoint(SBreakpoint* aBreakpoint, TBreakpointPolicy aPolicy=EWhatever); |
|
81 void UnapplyBreakpoint(SBreakpoint* aBreakpoint); |
|
82 void ClearBreakpoint(SBreakpoint* aBreakpoint, TBool aResumeAllBlocked=EFalse); |
|
83 TInt SetProgramCounter(DThread* aThread, TLinAddr aAddress); |
|
84 void ClearAllBreakpoints(); |
|
85 void RemoveAllHardwareBreakpointsForThread(DThread* aThread); |
|
86 void HandleRestoreCode(TLinAddr aAddress); |
|
87 static void HandleCodesegRemoved(TAny* aPtr); |
|
88 void DoHandleCodesegRemoved(); |
|
89 TInt ReadInstructions(DThread* aThread, TLinAddr aAddress, TInt aLength, TDes8& aData); |
|
90 TInt ApplyHardwareBreakpoint(SBreakpoint* aBreakpoint); |
|
91 TInt DoApplyHardwareBreakpoint(SBreakpoint* aBreakpoint, TInt aContextReg); |
|
92 static TUint32 GetArmContextIdForThread(DThread* aThread); |
|
93 TInt MoveBreakpointToNextInstructionForThread(DThread* aThread, SBreakpoint* aBreakpoint); |
|
94 #ifdef __EABI__ |
|
95 void DoClearHardwareBreakpoint(SBreakpoint* aBreakpoint); |
|
96 void SetDscr(TUint32 aVal); |
|
97 void SetBreakpointPair(TInt aRegister, TUint aBvrValue, TUint aBcrValue); |
|
98 TUint ReadBcr(TInt aRegister); |
|
99 void SetContextIdBrp(TInt aRegister, TUint aContextId); |
|
100 |
|
101 // Ones from the-TLA-that-dare-not-speak-its-name |
|
102 TInt ReadKernelRegisterValue(DThread* aThread, TInt aRegister, TUint32& aResult); |
|
103 TInt DoReadMemory(DThread* aThread, TLinAddr aAddress, TInt aLength, TDes8& aResult); |
|
104 TBool IsPreviousInstructionMovePCToLR(DThread *aThread); |
|
105 TInt CurrentInstructionArm(DThread* aThread, TUint32& aInstruction); |
|
106 TInt CurrentInstructionThumb(DThread* aThread, TUint32& aInstruction); |
|
107 TUint32 PCAfterInstructionExecutes(DThread *aThread, TUint32 aCurrentPC, TUint32 /*aStatusRegister*/, TInt aInstSize, TUint32 &aNewRangeEnd, TBool &aChangingModes); |
|
108 TUint32 ShiftedRegValue(DThread *aThread, TUint32 aInstruction, TUint32 aCurrentPC, TUint32 aStatusRegister); |
|
109 TInt CurrentPC(DThread* aThread, TUint32& aPC); |
|
110 TInt CurrentCPSR(DThread* aThread, TUint32& aCPSR); |
|
111 TInt ReadMem32(DThread* aThread, const TUint32 aAddress, TUint32& aValue); |
|
112 TInt ReadMem16(DThread* aThread, const TUint32 aAddress, TUint16& aValue); |
|
113 TInt RegisterValue(DThread *aThread, const TUint32 aKernelRegisterId, TUint32 &aValue); |
|
114 #endif |
|
115 |
|
116 #ifdef FSHELL_ARM_MEM_MAPPED_DEBUG |
|
117 TUint32 ReadRegister(TInt aRegisterOffset); |
|
118 void WriteRegister(TInt aRegisterOffset, TUint32 aValue); |
|
119 #endif |
|
120 |
|
121 private: |
|
122 enum TZombieMode |
|
123 { |
|
124 EDisabled = 0, |
|
125 EAbnormalExit = 1, |
|
126 EAllExits = 2, |
|
127 }; |
|
128 TZombieMode iZombieMode; |
|
129 |
|
130 struct SZombie |
|
131 { |
|
132 DThread* iThread; |
|
133 SDblQueLink iLink; |
|
134 DSemaphore* iBlocker; // Null if thread manually suspended via SuspendThread |
|
135 TLinAddr iBreakpointAddress; // > 0 if the thread is blocked on a breakpoint |
|
136 }; |
|
137 SDblQue iZombies; |
|
138 TInt iZombieCount; |
|
139 NFastMutex iLock; // For iZombies and other non-breakpoint-related structures |
|
140 |
|
141 struct SBreakpoint |
|
142 { |
|
143 SBreakpoint(DThread* aThread, TInt aBreakpointId, TLinAddr aAddress, const RMemoryAccess::TPredicate& aCondition); |
|
144 void SetThreadMatchPattern(HBuf* aMatch); |
|
145 TBool MatchesThread(DThread* aThread) const; |
|
146 ~SBreakpoint(); // Note this DOESNT deque from the breakpoint list - do that first! |
|
147 |
|
148 TBool HasModifiedCode() const; |
|
149 TBool IsHardware() const; |
|
150 |
|
151 DThread* iThread; |
|
152 TInt iBreakpointId; |
|
153 TLinAddr iAddress; // If the breakpoint is pending, this is actually the codeseg offset |
|
154 TBuf8<4> iOrigInstruction; |
|
155 SDblQueLink iLink; |
|
156 TAny* iCodeSeg; // If the breakpoint is pending, an HBuf* which is the name of the codeseg. For a persistant breakpoint, NULL. For anything that HasModifiedCode(), the DCodeSeg* that the address is in |
|
157 enum TFlags |
|
158 { |
|
159 EDisabledPendingCodesegLoad = 1, |
|
160 EDisabledByUser = 2, |
|
161 EDisabledDuringContinue = 4, |
|
162 EDisabled = EDisabledPendingCodesegLoad|EDisabledByUser|EDisabledDuringContinue, |
|
163 |
|
164 EPersistant = 8, // Meaning the actual code has an invalid instruction, so hasn't been ModifyCoded, so we should resume to the next instruction. |
|
165 EThumb = 16, |
|
166 EHardware = 32, // Implies EThreadSpecific |
|
167 ETempContinue = 64, |
|
168 EThreadSpecific = 128, // Only match a single specified thread. |
|
169 }; |
|
170 TUint iFlags; |
|
171 SBreakpoint* iRealBreakpoint; // If iFlags&ETempContinue, points to the breakpoint we're temping for. Otherwise, this indicates that the breakpoint hasn't called ModifyCode because (currently) there is another breakpoint (in a different thread) at the same address that has done it for us. |
|
172 TInt iHardwareBreakpointId; // Only relevant if iFlags&EHardware |
|
173 TInt iHardwareBreakpointContextReg; // Ditto. Value is either 4 or 5 |
|
174 //TInt iContinueCount; |
|
175 HBuf* iMatch; |
|
176 RMemoryAccess::TPredicate iCondition; |
|
177 |
|
178 private: |
|
179 SBreakpoint(); // No copying allowed |
|
180 }; |
|
181 TBool iCodeModifierInited; |
|
182 SDblQue iBreakpoints; |
|
183 TInt iNextBreakpointId; |
|
184 MDebuggerEventClient* iBreakpointNotifyClient; |
|
185 /* Rules for the breakpoint lock: Any manipulation of iBreakpoints, or of any breakpoint on the iBreakpoints list, must be protected by this lock. |
|
186 * Ditto iFreeHwBreakpoints. SBreakpoint objects not on the list can be manipulated without needing the lock held |
|
187 */ |
|
188 DMutex* iBreakpointMutex; |
|
189 TDfc iHandleCodesegRemovedDfc; |
|
190 struct SRemovedCodeseg |
|
191 { |
|
192 DProcess* iProcess; |
|
193 DCodeSeg* iCodeseg; |
|
194 SDblQueLink iLink; |
|
195 }; |
|
196 SDblQue iRemovedCodesegs; // Protected by iLock |
|
197 TUint32 iFreeHwBreakpoints; |
|
198 DPlatChunkHw* iDebugRegistersChunk; |
|
199 |
|
200 class TCreatorInfo |
|
201 { |
|
202 public: |
|
203 TCreatorInfo(TUint aThreadId, TUint aCreatorThreadId) |
|
204 : iThreadId(aThreadId), iCreatorThreadId(aCreatorThreadId) |
|
205 {} |
|
206 |
|
207 TUint iThreadId; |
|
208 TUint iCreatorThreadId; |
|
209 }; |
|
210 RArray<TCreatorInfo> iCreatorInfo; |
|
211 }; |
|
212 |
|
213 #endif // FDEBUGGERKERNEL_H |