From 63e824d50a657a42444f64d136bd33f3238f943c Mon Sep 17 00:00:00 2001 From: "SND\\kernelnet_cp" Date: Wed, 21 Oct 2015 11:03:41 +0000 Subject: [PATCH] [0.3.x] reworked : setBp returns now strong reference git-svn-id: https://pykd.svn.codeplex.com/svn@90851 9b283d60-5439-405e-af05-b73fd8c4d996 --- pykd/pyeventhandler.cpp | 79 +++++++++---- pykd/pyeventhandler.h | 12 +- test/scripts/breakpoint.py | 231 +++++++++++++------------------------ 3 files changed, 142 insertions(+), 180 deletions(-) diff --git a/pykd/pyeventhandler.cpp b/pykd/pyeventhandler.cpp index 4ddf213..67ac4ac 100644 --- a/pykd/pyeventhandler.cpp +++ b/pykd/pyeventhandler.cpp @@ -511,42 +511,51 @@ void EventHandler::onStopInput() ///////////////////////////////////////////////////////////////////////////////// -Breakpoint::Breakpoint(kdlib::BreakpointPtr bp) +Breakpoint::Breakpoint(kdlib::BreakpointPtr bp, bool weakbp) { - m_pystate = PyThreadState_Get(); m_breakpoint = bp; + m_weakBp = weakbp; } Breakpoint::Breakpoint(kdlib::MEMOFFSET_64 offset) { AutoRestorePyState pystate(&m_pystate); - m_breakpoint = kdlib::softwareBreakPointSet(offset, this); + m_weakBp = false; } Breakpoint::Breakpoint(kdlib::MEMOFFSET_64 offset, python::object &callback) { m_callback = callback; - AutoRestorePyState pystate(&m_pystate); - m_breakpoint = kdlib::softwareBreakPointSet(offset, this); + m_weakBp = false; } Breakpoint::Breakpoint(kdlib::MEMOFFSET_64 offset, size_t size, kdlib::ACCESS_TYPE accessType) { AutoRestorePyState pystate(&m_pystate); - m_breakpoint = kdlib::hardwareBreakPointSet(offset, size, accessType, this); + m_weakBp = false; } Breakpoint::Breakpoint(kdlib::MEMOFFSET_64 offset, size_t size, kdlib::ACCESS_TYPE accessType, python::object &callback) { m_callback = callback; - AutoRestorePyState pystate(&m_pystate); - m_breakpoint = kdlib::hardwareBreakPointSet(offset, size, accessType, this); + m_weakBp = false; +} + +///////////////////////////////////////////////////////////////////////////////// + +Breakpoint::~Breakpoint() +{ + AutoRestorePyState pystate; + if (!m_weakBp && m_breakpoint ) + { + m_breakpoint->remove(); + } } ///////////////////////////////////////////////////////////////////////////////// @@ -615,18 +624,54 @@ kdlib::DebugCallbackResult Breakpoint::onHit() ///////////////////////////////////////////////////////////////////////////////// +void Breakpoint::remove() +{ + AutoRestorePyState pystate; + if (m_breakpoint) + { + m_breakpoint->remove(); + m_breakpoint = 0; + } +} + +///////////////////////////////////////////////////////////////////////////////// + Breakpoint* Breakpoint::setSoftwareBreakpoint( kdlib::MEMOFFSET_64 offset, python::object &callback ) { - Breakpoint *internalBp = new Breakpoint(offset, callback); - return new Breakpoint(internalBp->m_breakpoint); + if (!callback) + { + AutoRestorePyState pystate; + kdlib::BreakpointPtr bp = kdlib::softwareBreakPointSet(offset, 0); + return new Breakpoint(bp, false); + } + else + { + return new Breakpoint(offset, callback); + } } ///////////////////////////////////////////////////////////////////////////////// Breakpoint* Breakpoint::setHardwareBreakpoint( kdlib::MEMOFFSET_64 offset, size_t size, kdlib::ACCESS_TYPE accessType, python::object &callback ) { - Breakpoint *internalBp = new Breakpoint(offset, size, accessType, callback); - return new Breakpoint(internalBp->m_breakpoint); + if (!callback) + { + AutoRestorePyState pystate; + kdlib::BreakpointPtr bp = kdlib::hardwareBreakPointSet(offset, size, accessType, 0); + return new Breakpoint(bp, false); + } + else + { + return new Breakpoint(offset, size, accessType, callback); + } +} + +///////////////////////////////////////////////////////////////////////////////// + +unsigned long Breakpoint::getNumberBreakpoints() +{ + AutoRestorePyState pystate; + return kdlib::getNumberBreakpoints(); } ///////////////////////////////////////////////////////////////////////////////// @@ -645,16 +690,6 @@ Breakpoint* Breakpoint::getBreakpointByIndex(unsigned long index) ///////////////////////////////////////////////////////////////////////////////// -void Breakpoint::remove() -{ - AutoRestorePyState pystate; - if (m_breakpoint) - { - m_breakpoint->remove(); - m_breakpoint = 0; - } -} -///////////////////////////////////////////////////////////////////////////////// } // end namespace pykd diff --git a/pykd/pyeventhandler.h b/pykd/pyeventhandler.h index 10ce0e2..692b6e9 100644 --- a/pykd/pyeventhandler.h +++ b/pykd/pyeventhandler.h @@ -60,16 +60,13 @@ public: static Breakpoint* setHardwareBreakpoint( kdlib::MEMOFFSET_64 offset, size_t size, kdlib::ACCESS_TYPE accessType, python::object &callback= python::object() ); - static unsigned long getNumberBreakpoints() { - AutoRestorePyState pystate; - return kdlib::getNumberBreakpoints(); - } + static unsigned long getNumberBreakpoints(); static Breakpoint* getBreakpointByIndex(unsigned long index); public: - explicit Breakpoint(kdlib::BreakpointPtr bp); + explicit Breakpoint(kdlib::BreakpointPtr bp, bool weakbp = true); explicit Breakpoint(kdlib::MEMOFFSET_64 offset); @@ -79,8 +76,7 @@ public: Breakpoint(kdlib::MEMOFFSET_64 offset, size_t size, kdlib::ACCESS_TYPE accessType, python::object &callback); - ~Breakpoint() - {} + ~Breakpoint(); virtual kdlib::DebugCallbackResult onHit(); @@ -111,6 +107,8 @@ private: kdlib::BreakpointPtr m_breakpoint; python::object m_callback; + + bool m_weakBp; }; diff --git a/test/scripts/breakpoint.py b/test/scripts/breakpoint.py index f31b7cf..afbef83 100644 --- a/test/scripts/breakpoint.py +++ b/test/scripts/breakpoint.py @@ -22,81 +22,45 @@ def continueOnBreak(): class BreakpointTest( unittest.TestCase ): + def setUp(self): + pykd.startProcess( target.appPath + " breakhandlertest" ) + self.targetModule = pykd.module( target.moduleName ) + self.targetModule.reload() + pykd.go() + + def tearDown(self): + self.taregtModule = None + pykd.killAllProcesses() + def testNoBreakpoint(self): - processId = pykd.startProcess( target.appPath + " breakhandlertest" ) - with testutils.ContextCallIt( testutils.KillProcess(processId) ) as killStartedProcess : - pykd.go() - self.assertEqual( pykd.executionStatus.NoDebuggee, pykd.go() ) + self.assertEqual( pykd.executionStatus.NoDebuggee, pykd.go() ) def testSetBp(self): - processId = pykd.startProcess( target.appPath + " breakhandlertest" ) - targetModule = pykd.module( target.moduleName ) - targetModule.reload() - with testutils.ContextCallIt( testutils.KillProcess(processId) ) as killStartedProcess : - pykd.go() - pykd.setBp( targetModule.CdeclFunc ) - self.assertEqual( pykd.executionStatus.Break, pykd.go() ) + bp = pykd.setBp( self.targetModule.CdeclFunc ) + self.assertEqual( pykd.executionStatus.Break, pykd.go() ) def testRemoveBp(self): - processId = pykd.startProcess( target.appPath + " breakhandlertest" ) - targetModule = pykd.module( target.moduleName ) - targetModule.reload() - with testutils.ContextCallIt( testutils.KillProcess(processId) ) as killStartedProcess : - pykd.go() - bp = pykd.setBp( targetModule.CdeclFunc ) - bp.remove() - self.assertEqual( pykd.executionStatus.NoDebuggee, pykd.go() ) + bp = pykd.setBp( self.targetModule.CdeclFunc ) + bp.remove() + self.assertEqual( pykd.executionStatus.NoDebuggee, pykd.go() ) def disable_testDeleteBp(self): - processId = pykd.startProcess( target.appPath + " breakhandlertest" ) - targetModule = pykd.module( target.moduleName ) - targetModule.reload() - with testutils.ContextCallIt( testutils.KillProcess(processId) ) as killStartedProcess : - pykd.go() - bp = pykd.setBp( targetModule.CdeclFunc ) - del bp - self.assertEqual( pykd.executionStatus.NoDebuggee, pykd.go() ) + bp = pykd.setBp( self.targetModule.CdeclFunc ) + del bp + self.assertEqual( pykd.executionStatus.NoDebuggee, pykd.go() ) def testBreakCallback(self): - processId = pykd.startProcess( target.appPath + " breakhandlertest" ) - targetModule = pykd.module( target.moduleName ) - targetModule.reload() - with testutils.ContextCallIt( testutils.KillProcess(processId) ) as killStartedProcess : - pykd.go() - breakCount = callCounter(stopOnBreak) - pykd.setBp( targetModule.CdeclFunc, breakCount ) - self.assertEqual( pykd.executionStatus.Break, pykd.go() ) - self.assertEqual( 1, breakCount.count ) - - def testBpScope(self): - - def setBpFunc(): - #breakpoint must be set until remove method will be called explicitly - pykd.setBp(targetModule.CdeclFunc) - - processId = pykd.startProcess( target.appPath + " breakhandlertest" ) - targetModule = pykd.module( target.moduleName ) - targetModule.reload() - with testutils.ContextCallIt( testutils.KillProcess(processId) ) as killStartedProcess : - pykd.go() - setBpFunc() - self.assertEqual( pykd.executionStatus.Break, pykd.go() ) - + breakCount = callCounter(stopOnBreak) + bp = pykd.setBp( self.targetModule.CdeclFunc, breakCount ) + self.assertEqual( pykd.executionStatus.Break, pykd.go() ) + self.assertEqual( 1, breakCount.count ) def testNoBreakCallback(self): - processId = pykd.startProcess( target.appPath + " breakhandlertest" ) - targetModule = pykd.module( target.moduleName ) - targetModule.reload() - with testutils.ContextCallIt( testutils.KillProcess(processId) ) as killStartedProcess : - pykd.go() - breakCount = callCounter(continueOnBreak) - - pykd.setBp( targetModule.CdeclFunc, breakCount ) - - self.assertEqual( pykd.executionStatus.NoDebuggee, pykd.go() ) - - self.assertEqual( 1, breakCount.count ) + breakCount = callCounter(continueOnBreak) + bp = pykd.setBp( self.targetModule.CdeclFunc, breakCount ) + self.assertEqual( pykd.executionStatus.NoDebuggee, pykd.go() ) + self.assertEqual( 1, breakCount.count ) def testBreakpointHandler(self): @@ -110,21 +74,10 @@ class BreakpointTest( unittest.TestCase ): self.count = self.count + 1 return True - processId = pykd.startProcess( target.appPath + " breakhandlertest" ) - targetModule = pykd.module( target.moduleName ) - targetModule.reload() - with testutils.ContextCallIt( testutils.KillProcess(processId) ) as killStartedProcess : - - pykd.go() - - handler = BreakpointHandler() - - pykd.setBp( targetModule.CdeclFunc ) - - self.assertEqual( pykd.executionStatus.Break, pykd.go() ) - - self.assertEqual( 1, handler.count ) - + handler = BreakpointHandler() + bp = pykd.setBp( self.targetModule.CdeclFunc ) + self.assertEqual( pykd.executionStatus.Break, pykd.go() ) + self.assertEqual( 1, handler.count ) def testBreakpointClass(self): @@ -137,21 +90,12 @@ class BreakpointTest( unittest.TestCase ): self.count = self.count + 1 return True - processId = pykd.startProcess( target.appPath + " breakhandlertest" ) - targetModule = pykd.module( target.moduleName ) - targetModule.reload() - with testutils.ContextCallIt( testutils.KillProcess(processId) ) as killStartedProcess : - - pykd.go() - - bp = MyBreakpoint( targetModule.typedVar("CdeclFunc").getDebugStart() ) - - self.assertEqual( pykd.executionStatus.Break, pykd.go() ) - - self.assertEqual( 1, bp.count ) + bp = MyBreakpoint( self.targetModule.typedVar("CdeclFunc").getDebugStart() ) + self.assertEqual( pykd.executionStatus.Break, pykd.go() ) + self.assertEqual( 1, bp.count ) - def testBreakpointCondition(self): + def testBreakpointCondition1(self): def makebpcallback(n): @@ -161,81 +105,66 @@ class BreakpointTest( unittest.TestCase ): return pykd.eventResult.Proceed return bpcallback - processId = pykd.startProcess( target.appPath + " breakhandlertest" ) - targetModule = pykd.module( target.moduleName ) - targetModule.reload() - with testutils.ContextCallIt( testutils.KillProcess(processId) ) as killStartedProcess : - pykd.go() - bp = pykd.setBp( targetModule.typedVar("CdeclFunc").getDebugStart(), makebpcallback(1) ) - self.assertEqual( pykd.executionStatus.Break, pykd.go() ) + bp = pykd.setBp( self.targetModule.typedVar("CdeclFunc").getDebugStart(), makebpcallback(1) ) + self.assertEqual( pykd.executionStatus.Break, pykd.go() ) - processId = pykd.startProcess( target.appPath + " breakhandlertest" ) - targetModule = pykd.module( target.moduleName ) - targetModule.reload() - with testutils.ContextCallIt( testutils.KillProcess(processId) ) as killStartedProcess : - pykd.go() - bp = pykd.setBp(targetModule.typedVar("CdeclFunc").getDebugStart(), makebpcallback(100) ) - self.assertEqual( pykd.executionStatus.NoDebuggee, pykd.go() ) + def testBreakpointCondition2(self): + + def makebpcallback(n): + + def bpcallback(): + if pykd.getParam("b") > n: + return pykd.eventResult.Break + return pykd.eventResult.Proceed + return bpcallback + + bp = pykd.setBp(self.targetModule.typedVar("CdeclFunc").getDebugStart(), makebpcallback(100) ) + self.assertEqual( pykd.executionStatus.NoDebuggee, pykd.go() ) + def testBreakpointEnum(self): - processId = pykd.startProcess( target.appPath + " breakhandlertest" ) - targetModule = pykd.module( target.moduleName ) - targetModule.reload() - with testutils.ContextCallIt( testutils.KillProcess(processId) ) as killStartedProcess : - pykd.go() - - pykd.setBp( targetModule.CdeclFunc) - pykd.setBp( targetModule.CdeclFunc + 1) - pykd.setBp( targetModule.CdeclFunc + 2) - self.assertEqual(3, pykd.getNumberBreakpoints()); - bpLst = [pykd.getBp(i) for i in xrange(3)] - self.assertEqual(3, len(bpLst)) - map( lambda bp: bp.remove(), bpLst) - self.assertEqual(0, pykd.getNumberBreakpoints()); + b1 = pykd.setBp( self.targetModule.CdeclFunc) + b2 = pykd.setBp( self.targetModule.CdeclFunc + 1) + b3 = pykd.setBp( self.targetModule.CdeclFunc + 2) + + self.assertEqual(3, pykd.getNumberBreakpoints()); + bpLst = [pykd.getBp(i) for i in xrange(3)] + self.assertEqual(3, len(bpLst)) + map( lambda bp: bp.remove(), bpLst) + self.assertEqual(0, pykd.getNumberBreakpoints()); def testBreakpointChangeHandler(self): class BreakpointChangeHandler( pykd.eventHandler ): + + def __init__(self): + pykd.eventHandler.__init__(self) + self.count = 0 def onChangeBreakpoints(self): - pass + self.count += 1 - processId = pykd.startProcess( target.appPath + " breakhandlertest" ) - targetModule = pykd.module( target.moduleName ) - targetModule.reload() - with testutils.ContextCallIt( testutils.KillProcess(processId) ) as killStartedProcess : - pykd.go() - handler = BreakpointChangeHandler() - bp = pykd.setBp( targetModule.CdeclFunc) - bp.remove() - self.assertEqual(0, pykd.getNumberBreakpoints()) + handler = BreakpointChangeHandler() + bp = pykd.setBp(self.targetModule.CdeclFunc) + bp.remove() + self.assertEqual(0, pykd.getNumberBreakpoints()) + self.assertEqual(4, handler.count) def testLambdaBpContinue(self): - - processId = pykd.startProcess( target.appPath + " breakhandlertest" ) - targetModule = pykd.module( target.moduleName ) - targetModule.reload() - with testutils.ContextCallIt( testutils.KillProcess(processId) ) as killStartedProcess : - pykd.go() - bp1 = pykd.setBp(targetModule.CdeclFunc, lambda : None ) - bp2 = pykd.setBp(targetModule.CdeclFunc, lambda : False ) - bp3 = pykd.setBp(targetModule.CdeclFunc, lambda : 0 ) - self.assertEqual( pykd.executionStatus.NoDebuggee, pykd.go() ) - + bp1 = pykd.setBp(self.targetModule.CdeclFunc, lambda : None ) + bp2 = pykd.setBp(self.targetModule.CdeclFunc, lambda : False ) + bp3 = pykd.setBp(self.targetModule.CdeclFunc, lambda : 0 ) + self.assertEqual( pykd.executionStatus.NoDebuggee, pykd.go() ) def testLambdaBpBreak(self): + bp2 = pykd.setBp(self.targetModule.CdeclFunc, lambda : True ) + self.assertEqual( pykd.executionStatus.Break, pykd.go() ) - processId = pykd.startProcess( target.appPath + " breakhandlertest" ) - targetModule = pykd.module( target.moduleName ) - targetModule.reload() - with testutils.ContextCallIt( testutils.KillProcess(processId) ) as killStartedProcess : - pykd.go() - bp2 = pykd.setBp(targetModule.CdeclFunc, lambda : True ) - self.assertEqual( pykd.executionStatus.Break, pykd.go() ) - - - - + def testBpCommand(self): + pykd.dbgCommand("bp 0x100") + self.assertEqual(1, pykd.getNumberBreakpoints()) + bp = pykd.getBp(0) + self.assertEqual(0x100, bp.getOffset())