libraries/memoryaccess/fdebuggerkernel.h
changeset 0 7f656887cf89
equal deleted inserted replaced
-1:000000000000 0:7f656887cf89
       
     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