diff -r 000000000000 -r 7f656887cf89 libraries/memoryaccess/fdebuggerkernel.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libraries/memoryaccess/fdebuggerkernel.h Wed Jun 23 15:52:26 2010 +0100 @@ -0,0 +1,213 @@ +// fdebuggerkernel.h +// +// Copyright (c) 2010 Accenture. All rights reserved. +// This component and the accompanying materials are made available +// under the terms of the "Eclipse Public License v1.0" +// which accompanies this distribution, and is available +// at the URL "http://www.eclipse.org/legal/epl-v10.html". +// +// Initial Contributors: +// Accenture - Initial contribution +// +#ifndef FDEBUGGERKERNEL_H +#define FDEBUGGERKERNEL_H + +#include +#include +#include + +#include +#include "memoryaccess.h" +class TDynDfcQueWrapper; + +class MDebuggerEventClient + { +public: + virtual void BreakpointHit(TDes& aPkg) =0; + }; + +NONSHARABLE_CLASS(DDebuggerEventHandler) : public DKernelEventHandler + { +public: + static DDebuggerEventHandler* New(TDfcQue* aQue); + + TInt GetZombieMode(); + TInt SetZombieMode(TInt aMode); + HBuf* GetZombieThreadIds(); + TInt ReleaseZombie(DThread* aThread); + TInt SuspendThread(DThread* aThread); + + TInt RegisterForBreakpointNotification(MDebuggerEventClient* aClient); + void UnregisterForBreakpointNotification(MDebuggerEventClient* aClient); + + TInt SetBreakpoint(DThread* aThread, TLinAddr aAddress, const RMemoryAccess::TPredicate& aCondition); + TInt SetSymbolicBreakpoint(DThread* aThread, HBuf* aCodesegName, TUint32 aOffset, const RMemoryAccess::TPredicate& aCondition); + TInt RegisterPersistantBreakpoint(DThread* aThread, TLinAddr aAddress); + TInt SetBreakpointEnabled(TInt aBreakpointId, TBool aEnabled); + TInt ClearBreakpoint(TInt aBreakpointId); + TInt ContinueFromBreakpoint(DThread* aThread, TLinAddr aExceptionAddress); + HBuf* GetBreakpoints(); + + TUint GetCreatorThread(TUint aThreadId); // Returns 0 if not known + +private: + DDebuggerEventHandler(TDfcQue* aQue); + ~DDebuggerEventHandler(); + static TUint Event(TKernelEvent aEvent, TAny* a1, TAny* a2, TAny* aPrivateData); + TUint DoEvent(TKernelEvent aEvent, TAny* a1, TAny* a2); + void CompleteZombies(); + void Lock(); + void Unlock(); + void BreakpointLock(); + void BreakpointUnlock(); + struct SZombie; + SZombie* FindZombie(DThread* aThread); + void ReleaseZombie(SZombie* aZombie); + void ReleaseZombieAndUnlock(SZombie* aZombie); + void UnsuspendThread(SZombie* aZombie); + TInt Zombify(TLinAddr aBreakpointAddr=0); + struct SBreakpoint; + SBreakpoint* FindBreakpointByAddress(/*DThread* aThread,*/ TLinAddr aAddress); + SBreakpoint* FindBreakpointById(TInt aId); + SBreakpoint* FindBreakpointUsingHardwareContextRegister(TInt aRegister); + SBreakpoint* FindHardwareBreakpoint(DThread* aThread, TLinAddr aAddress); + enum TBreakpointPolicy + { + EWhatever, + EHardwareOnly, + ESoftwareOnly, + }; + TInt ApplyBreakpoint(SBreakpoint* aBreakpoint, TBreakpointPolicy aPolicy=EWhatever); + void UnapplyBreakpoint(SBreakpoint* aBreakpoint); + void ClearBreakpoint(SBreakpoint* aBreakpoint, TBool aResumeAllBlocked=EFalse); + TInt SetProgramCounter(DThread* aThread, TLinAddr aAddress); + void ClearAllBreakpoints(); + void RemoveAllHardwareBreakpointsForThread(DThread* aThread); + void HandleRestoreCode(TLinAddr aAddress); + static void HandleCodesegRemoved(TAny* aPtr); + void DoHandleCodesegRemoved(); + TInt ReadInstructions(DThread* aThread, TLinAddr aAddress, TInt aLength, TDes8& aData); + TInt ApplyHardwareBreakpoint(SBreakpoint* aBreakpoint); + TInt DoApplyHardwareBreakpoint(SBreakpoint* aBreakpoint, TInt aContextReg); + static TUint32 GetArmContextIdForThread(DThread* aThread); + TInt MoveBreakpointToNextInstructionForThread(DThread* aThread, SBreakpoint* aBreakpoint); +#ifdef __EABI__ + void DoClearHardwareBreakpoint(SBreakpoint* aBreakpoint); + void SetDscr(TUint32 aVal); + void SetBreakpointPair(TInt aRegister, TUint aBvrValue, TUint aBcrValue); + TUint ReadBcr(TInt aRegister); + void SetContextIdBrp(TInt aRegister, TUint aContextId); + + // Ones from the-TLA-that-dare-not-speak-its-name + TInt ReadKernelRegisterValue(DThread* aThread, TInt aRegister, TUint32& aResult); + TInt DoReadMemory(DThread* aThread, TLinAddr aAddress, TInt aLength, TDes8& aResult); + TBool IsPreviousInstructionMovePCToLR(DThread *aThread); + TInt CurrentInstructionArm(DThread* aThread, TUint32& aInstruction); + TInt CurrentInstructionThumb(DThread* aThread, TUint32& aInstruction); + TUint32 PCAfterInstructionExecutes(DThread *aThread, TUint32 aCurrentPC, TUint32 /*aStatusRegister*/, TInt aInstSize, TUint32 &aNewRangeEnd, TBool &aChangingModes); + TUint32 ShiftedRegValue(DThread *aThread, TUint32 aInstruction, TUint32 aCurrentPC, TUint32 aStatusRegister); + TInt CurrentPC(DThread* aThread, TUint32& aPC); + TInt CurrentCPSR(DThread* aThread, TUint32& aCPSR); + TInt ReadMem32(DThread* aThread, const TUint32 aAddress, TUint32& aValue); + TInt ReadMem16(DThread* aThread, const TUint32 aAddress, TUint16& aValue); + TInt RegisterValue(DThread *aThread, const TUint32 aKernelRegisterId, TUint32 &aValue); +#endif + +#ifdef FSHELL_ARM_MEM_MAPPED_DEBUG + TUint32 ReadRegister(TInt aRegisterOffset); + void WriteRegister(TInt aRegisterOffset, TUint32 aValue); +#endif + +private: + enum TZombieMode + { + EDisabled = 0, + EAbnormalExit = 1, + EAllExits = 2, + }; + TZombieMode iZombieMode; + + struct SZombie + { + DThread* iThread; + SDblQueLink iLink; + DSemaphore* iBlocker; // Null if thread manually suspended via SuspendThread + TLinAddr iBreakpointAddress; // > 0 if the thread is blocked on a breakpoint + }; + SDblQue iZombies; + TInt iZombieCount; + NFastMutex iLock; // For iZombies and other non-breakpoint-related structures + + struct SBreakpoint + { + SBreakpoint(DThread* aThread, TInt aBreakpointId, TLinAddr aAddress, const RMemoryAccess::TPredicate& aCondition); + void SetThreadMatchPattern(HBuf* aMatch); + TBool MatchesThread(DThread* aThread) const; + ~SBreakpoint(); // Note this DOESNT deque from the breakpoint list - do that first! + + TBool HasModifiedCode() const; + TBool IsHardware() const; + + DThread* iThread; + TInt iBreakpointId; + TLinAddr iAddress; // If the breakpoint is pending, this is actually the codeseg offset + TBuf8<4> iOrigInstruction; + SDblQueLink iLink; + 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 + enum TFlags + { + EDisabledPendingCodesegLoad = 1, + EDisabledByUser = 2, + EDisabledDuringContinue = 4, + EDisabled = EDisabledPendingCodesegLoad|EDisabledByUser|EDisabledDuringContinue, + + EPersistant = 8, // Meaning the actual code has an invalid instruction, so hasn't been ModifyCoded, so we should resume to the next instruction. + EThumb = 16, + EHardware = 32, // Implies EThreadSpecific + ETempContinue = 64, + EThreadSpecific = 128, // Only match a single specified thread. + }; + TUint iFlags; + 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. + TInt iHardwareBreakpointId; // Only relevant if iFlags&EHardware + TInt iHardwareBreakpointContextReg; // Ditto. Value is either 4 or 5 + //TInt iContinueCount; + HBuf* iMatch; + RMemoryAccess::TPredicate iCondition; + + private: + SBreakpoint(); // No copying allowed + }; + TBool iCodeModifierInited; + SDblQue iBreakpoints; + TInt iNextBreakpointId; + MDebuggerEventClient* iBreakpointNotifyClient; + /* Rules for the breakpoint lock: Any manipulation of iBreakpoints, or of any breakpoint on the iBreakpoints list, must be protected by this lock. + * Ditto iFreeHwBreakpoints. SBreakpoint objects not on the list can be manipulated without needing the lock held + */ + DMutex* iBreakpointMutex; + TDfc iHandleCodesegRemovedDfc; + struct SRemovedCodeseg + { + DProcess* iProcess; + DCodeSeg* iCodeseg; + SDblQueLink iLink; + }; + SDblQue iRemovedCodesegs; // Protected by iLock + TUint32 iFreeHwBreakpoints; + DPlatChunkHw* iDebugRegistersChunk; + + class TCreatorInfo + { + public: + TCreatorInfo(TUint aThreadId, TUint aCreatorThreadId) + : iThreadId(aThreadId), iCreatorThreadId(aCreatorThreadId) + {} + + TUint iThreadId; + TUint iCreatorThreadId; + }; + RArray iCreatorInfo; + }; + +#endif // FDEBUGGERKERNEL_H