[0.3.x] updated : test

git-svn-id: https://pykd.svn.codeplex.com/svn@84081 9b283d60-5439-405e-af05-b73fd8c4d996
This commit is contained in:
SND\kernelnet_cp 2013-06-17 14:21:11 +00:00 committed by Mikhail I. Izmestev
parent d68acf97ea
commit 5dc822ab1b
10 changed files with 219 additions and 210 deletions

122
pykd/breakpoint.cpp Normal file
View File

@ -0,0 +1,122 @@
#include "stdafx.h"
#include "kdlib\eventhandler.h"
#include "breakpoint.h"
#include "dbgexcept.h"
namespace pykd {
///////////////////////////////////////////////////////////////////////////////
class SoftwareBreakpoint : public Breakpoint
{
public:
SoftwareBreakpoint( kdlib::MEMOFFSET_64 offset ) {
m_id = kdlib::softwareBreakPointSet( offset );
}
~SoftwareBreakpoint() {
kdlib::breakPointRemove( m_id );
}
private:
kdlib::BREAKPOINT_ID m_id;
};
///////////////////////////////////////////////////////////////////////////////
class SoftwareBreakpointWithCallback : public Breakpoint, private kdlib::EventHandler
{
public:
SoftwareBreakpointWithCallback( kdlib::MEMOFFSET_64 offset, python::object &callback )
{
m_pystate = PyThreadState_Get();
m_callback = callback;
m_id = kdlib::softwareBreakPointSet( offset );
}
~SoftwareBreakpointWithCallback()
{
try {
kdlib::breakPointRemove( m_id );
} catch( kdlib::DbgException& )
{ }
}
private:
virtual kdlib::DebugCallbackResult onBreakpoint( kdlib::BREAKPOINT_ID bpId )
{
kdlib::DebugCallbackResult result;
if ( bpId != m_id )
return kdlib::DebugCallbackNoChange;
PyEval_RestoreThread( m_pystate );
try {
do {
python::object resObj = m_callback( bpId );
if ( resObj.is_none() )
{
result = kdlib::DebugCallbackNoChange;
break;
}
int retVal = python::extract<int>( resObj );
if ( retVal >= kdlib::DebugCallbackMax )
{
result = kdlib::DebugCallbackBreak;
break;
}
result = kdlib::DebugCallbackResult(retVal);
} while( FALSE );
}
catch (const python::error_already_set &)
{
printException();
result = kdlib::DebugCallbackBreak;
}
m_pystate = PyEval_SaveThread();
return result;
}
kdlib::BREAKPOINT_ID m_id;
python::object m_callback;
PyThreadState* m_pystate;
};
///////////////////////////////////////////////////////////////////////////////
BreakpointPtr Breakpoint::setSoftwareBreakpoint( kdlib::MEMOFFSET_64 offset, python::object &callback )
{
if ( callback )
{
return BreakpointPtr( new SoftwareBreakpointWithCallback( offset, callback ) );
}
else
{
return BreakpointPtr( new SoftwareBreakpoint(offset) );
}
}
///////////////////////////////////////////////////////////////////////////////
} // end namespace pykd

33
pykd/breakpoint.h Normal file
View File

@ -0,0 +1,33 @@
#pragma once
#include "kdlib/dbgengine.h"
#include "boost/shared_ptr.hpp"
#include "boost/noncopyable.hpp"
#include "boost/python/object.hpp"
namespace python = boost::python;
namespace pykd {
///////////////////////////////////////////////////////////////////////////////
class Breakpoint;
typedef boost::shared_ptr<Breakpoint> BreakpointPtr;
class Breakpoint : public boost::noncopyable
{
public:
static
BreakpointPtr setSoftwareBreakpoint( kdlib::MEMOFFSET_64 offset, python::object &callback = python::object() );
protected:
virtual ~Breakpoint() {}
};
///////////////////////////////////////////////////////////////////////////////
} // end namespace pykd

View File

@ -8,13 +8,17 @@ namespace pykd {
///////////////////////////////////////////////////////////////////////////////
void targetGo()
kdlib::ExecutionStatus targetGo()
{
kdlib::ExecutionStatus status;
PyThreadState* state = PyEval_SaveThread();
kdlib::targetGo();
status = kdlib::targetGo();
PyEval_RestoreThread( state );
return status;
}
///////////////////////////////////////////////////////////////////////////////
@ -30,24 +34,32 @@ void targetBreak()
///////////////////////////////////////////////////////////////////////////////
void targetStep()
kdlib::ExecutionStatus targetStep()
{
kdlib::ExecutionStatus status;
PyThreadState* state = PyEval_SaveThread();
kdlib::targetStep();
status = kdlib::targetStep();
PyEval_RestoreThread( state );
return status;
}
///////////////////////////////////////////////////////////////////////////////
void targetStepIn()
kdlib::ExecutionStatus targetStepIn()
{
kdlib::ExecutionStatus status;
PyThreadState* state = PyEval_SaveThread();
kdlib::targetStepIn();
status = kdlib::targetStepIn();
PyEval_RestoreThread( state );
return status;
}
///////////////////////////////////////////////////////////////////////////////

View File

@ -9,10 +9,10 @@ namespace pykd {
///////////////////////////////////////////////////////////////////////////////
void targetGo();
kdlib::ExecutionStatus targetGo();
void targetBreak();
void targetStep();
void targetStepIn();
kdlib::ExecutionStatus targetStep();
kdlib::ExecutionStatus targetStepIn();
python::tuple getSourceLine( kdlib::MEMOFFSET_64 offset = 0 );

View File

@ -123,6 +123,7 @@
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClInclude Include="breakpoint.h" />
<ClInclude Include="dbgengine.h" />
<ClInclude Include="dbgexcept.h" />
<ClInclude Include="memaccess.h" />
@ -136,6 +137,7 @@
<ClInclude Include="windbgext.h" />
</ItemGroup>
<ItemGroup>
<ClCompile Include="breakpoint.cpp" />
<ClCompile Include="dbgengine.cpp" />
<ClCompile Include="dbgexcept.cpp" />
<ClCompile Include="dllmain.cpp">

View File

@ -48,6 +48,9 @@
<ClInclude Include="dbgengine.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="breakpoint.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="stdafx.cpp">
@ -68,6 +71,9 @@
<ClCompile Include="dbgengine.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="breakpoint.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<None Include="pykd.def">

View File

@ -12,6 +12,7 @@
#include "typeinfo.h"
#include "typedvar.h"
#include "windbgext.h"
#include "breakpoint.h"
using namespace pykd;
@ -50,8 +51,7 @@ BOOST_PYTHON_FUNCTION_OVERLOADS( compareMemory_, kdlib::compareMemory, 3, 4 );
BOOST_PYTHON_FUNCTION_OVERLOADS( getSourceLine_, getSourceLine, 0, 1 );
BOOST_PYTHON_FUNCTION_OVERLOADS( getSourceFile_, kdlib::getSourceFile, 0, 1 );
//
//BOOST_PYTHON_FUNCTION_OVERLOADS( setSoftwareBp_, setSoftwareBp, 1, 2 );
//BOOST_PYTHON_FUNCTION_OVERLOADS( setHardwareBp_, setHardwareBp, 3, 4 );
//
//BOOST_PYTHON_FUNCTION_OVERLOADS( findSymbol_, TypeInfo::findSymbol, 1, 2 );
@ -272,13 +272,14 @@ BOOST_PYTHON_MODULE( pykd )
// python::def( "getParams", &getParams,
// "Get list of function arguments" );
// // breakpoints
// python::def( "setBp", &setSoftwareBp, setSoftwareBp_( python::args( "offset", "callback" ),
// "Set software breakpoint on executiont" ) );
// python::def( "setBp", &setHardwareBp, setHardwareBp_( python::args( "offset", "size", "accsessType", "callback" ) ,
// "Set hardware breakpoint" ) );
// python::def( "removeBp", &removeBp,
// "Remove breapoint by IDs" );
// breakpoints
python::def( "setBp", &kdlib::softwareBreakPointSet,
"Set software breakpoint on executiont" );
python::def( "removeBp", &kdlib::breakPointRemove,
"Remove breapoint by IDs" );
//python::def( "setBp", &setHardwareBp, setHardwareBp_( python::args( "offset", "size", "accsessType", "callback" ) ,
// "Set hardware breakpoint" ) );
// //python::def( "removeAllBp", &removeAllBp,
// // "Remove all breapoints" );
@ -503,6 +504,13 @@ BOOST_PYTHON_MODULE( pykd )
// .def( "createUnion", &TypeBuilder::createUnion,
// "Create custom union" );
python::class_<Breakpoint, BreakpointPtr, boost::noncopyable>( "breakpoint",
"class for breakpoint representation", python::no_init )
.def("__init__", python::make_constructor(Breakpoint::setSoftwareBreakpoint) )
;
// python::class_<CpuReg, python::bases<intBase> >(
// "cpuReg", "CPU regsiter class", boost::python::no_init )
// .def( "name", &CpuReg::name, "The name of the regsiter" )
@ -613,18 +621,18 @@ BOOST_PYTHON_MODULE( pykd )
// .def( "jumprel", &Disasm::jumprel, "Change the current instruction" );
// python::enum_<DEBUG_CALLBACK_RESULT>("eventResult", "Return value of event handler")
// .value("Proceed", DebugCallbackProceed)
// .value("NoChange", DebugCallbackNoChange)
// .value("Break", DebugCallbackBreak)
// .export_values();
python::enum_<kdlib::DebugCallbackResult>("eventResult", "Return value of event handler")
.value("Proceed", kdlib::DebugCallbackProceed)
.value("NoChange", kdlib::DebugCallbackNoChange)
.value("Break", kdlib::DebugCallbackBreak)
.export_values();
// python::enum_<EXECUTION_STATUS>("executionStatus", "Execution Status")
// .value("NoChange", DebugStatusNoChange )
// .value("Go", DebugStatusGo )
// .value("Break", DebugStatusBreak )
// .value("NoDebuggee", DebugStatusNoDebuggee )
// .export_values();
python::enum_<kdlib::ExecutionStatus>("executionStatus", "Execution Status")
.value("NoChange", kdlib::DebugStatusNoChange )
.value("Go", kdlib::DebugStatusGo )
.value("Break", kdlib::DebugStatusBreak )
.value("NoDebuggee", kdlib::DebugStatusNoDebuggee )
.export_values();
// python::class_<EventHandlerWrap, EventHandlerPtr, boost::noncopyable>(
// "eventHandler", "Base class for overriding and handling debug notifications" )

View File

@ -1,179 +0,0 @@
"""
Tests for pyDia
"""
import unittest
import target
import pykd
from sets import Set
class DiaTest( unittest.TestCase ):
def testCtor(self):
""" DiaSymbol can not be created direct """
try: pykd.DiaSymbol()
except RuntimeError: pass
def testFind(self):
gScope = pykd.diaLoadPdb( str(target.module.pdb()) )
self.assertNotEqual(0, len(gScope))
symFunction = gScope.find("FuncWithName0")
self.assertTrue(1 == len( symFunction ))
symFunction = gScope.findEx(pykd.SymTagNull,
"FuNc*Name?",
pykd.nsCaseInRegularExpression)
self.assertTrue(len(symFunction) > 1)
def testSize(self):
gScope = pykd.diaLoadPdb( str(target.module.pdb()) )
self.assertEqual(1, gScope["g_ucharValue"].type().size())
self.assertEqual(2, gScope["g_ushortValue"].type().size())
self.assertEqual(4, gScope["g_ulongValue"].type().size())
self.assertEqual(8, gScope["g_ulonglongValue"].type().size())
def testValue(self):
gScope = pykd.diaLoadPdb( str(target.module.pdb()) )
self.assertEqual(0x5555, gScope["g_constNumValue"].value())
self.assertEqual(True, gScope["g_constBoolValue"].value())
def testName(self):
gScope = pykd.diaLoadPdb( str(target.module.pdb()) )
self.assertEqual( "g_constNumValue",
gScope["g_constNumValue"].name() )
self.assertEqual( "FuncWithName0",
gScope["FuncWithName0"].name() )
def testRva(self):
gScope = pykd.diaLoadPdb( str(target.module.pdb()) )
_rva = gScope["FuncWithName0"].rva()
self.assertNotEqual(0, _rva)
modLen = target.module.end() - target.module.begin()
self.assertTrue( _rva < modLen )
_rva = gScope["g_string"].rva()
self.assertNotEqual(0, _rva)
self.assertTrue( _rva < modLen )
def testSymTag(self):
gScope = pykd.diaLoadPdb( str(target.module.pdb()) )
self.assertEqual( pykd.SymTagFunction,
gScope["FuncWithName0"].symTag() )
self.assertEqual( pykd.SymTagData,
gScope["g_string"].symTag() )
def testLocType(self):
gScope = pykd.diaLoadPdb( str(target.module.pdb()) )
self.assertEqual( pykd.LocIsConstant,
gScope["g_constNumValue"].locType() )
self.assertEqual( pykd.LocIsStatic,
gScope["FuncWithName1"].locType() )
def testBasicType(self):
gScope = pykd.diaLoadPdb( str(target.module.pdb()) )
self.assertFalse(gScope["g_string"].type().isBasic())
self.assertEqual( pykd.btBool,
gScope["g_constBoolValue"].type().baseType() )
self.assertEqual( pykd.btULong,
gScope["g_ulongValue"].type().baseType() )
def testBasicName(self):
self.assertEqual( "NoType", pykd.diaBasicType[ pykd.btNoType ] )
self.assertEqual( "Void", pykd.diaBasicType[ pykd.btVoid ] )
self.assertEqual( "Char", pykd.diaBasicType[ pykd.btChar ] )
self.assertEqual( "WChar", pykd.diaBasicType[ pykd.btWChar ] )
self.assertEqual( "Int", pykd.diaBasicType[ pykd.btInt ] )
self.assertEqual( "UInt", pykd.diaBasicType[ pykd.btUInt ] )
self.assertEqual( "Float", pykd.diaBasicType[ pykd.btFloat ] )
self.assertEqual( "BCD", pykd.diaBasicType[ pykd.btBCD ] )
self.assertEqual( "Bool", pykd.diaBasicType[ pykd.btBool ] )
self.assertEqual( "Long", pykd.diaBasicType[ pykd.btLong ] )
self.assertEqual( "ULong", pykd.diaBasicType[ pykd.btULong ] )
self.assertEqual( "Currency", pykd.diaBasicType[ pykd.btCurrency ] )
self.assertEqual( "Date", pykd.diaBasicType[ pykd.btDate ] )
self.assertEqual( "Variant", pykd.diaBasicType[ pykd.btVariant ] )
self.assertEqual( "Complex", pykd.diaBasicType[ pykd.btComplex ] )
self.assertEqual( "Bit", pykd.diaBasicType[ pykd.btBit ] )
self.assertEqual( "BSTR", pykd.diaBasicType[ pykd.btBSTR ] )
self.assertEqual( "Hresult", pykd.diaBasicType[ pykd.btHresult ] )
def testBits(self):
gScope = pykd.diaLoadPdb( str(target.module.pdb()) )
structWithBits = gScope["structWithBits"]
bitField = structWithBits["m_bit0_4"]
self.assertEqual(pykd.LocIsBitField, bitField.locType())
self.assertEqual(0, bitField.bitPos())
self.assertEqual(5, bitField.size())
bitField = structWithBits["m_bit5"]
self.assertEqual(pykd.LocIsBitField, bitField.locType())
self.assertEqual(5, bitField.bitPos())
self.assertEqual(1, bitField.size())
bitField = structWithBits["m_bit6_7"]
self.assertEqual(pykd.LocIsBitField, bitField.locType())
self.assertEqual(6, bitField.bitPos())
self.assertEqual(2, bitField.size())
def testIndexId(self):
gScope = pykd.diaLoadPdb( str(target.module.pdb()) )
self.assertNotEqual( gScope["classChild"].indexId(),
gScope["classBase"].indexId() )
self.assertNotEqual( gScope["FuncWithName0"].indexId(),
gScope["FuncWithName1"].indexId() )
def testUdtKind(self):
gScope = pykd.diaLoadPdb( str(target.module.pdb()) )
self.assertEqual(pykd.UdtStruct, gScope["structTest"].udtKind())
self.assertEqual(pykd.UdtUnion, gScope["unionTest"].udtKind())
self.assertEqual(pykd.UdtClass, gScope["classBase"].udtKind())
def testOffset(self):
gScope = pykd.diaLoadPdb( str(target.module.pdb()) )
structTest = gScope["structTest"]
self.assertEqual( 0, structTest["m_field0"].offset() )
self.assertTrue( structTest["m_field0"].offset() <
structTest["m_field1"].offset() )
self.assertTrue( structTest["m_field1"].offset() <
structTest["m_field2"].offset() )
self.assertTrue( structTest["m_field2"].offset() <
structTest["m_field3"].offset() )
self.assertTrue( structTest["m_field3"].offset() <
structTest.size() )
def testMachine(self):
gScope = pykd.diaLoadPdb( str(target.module.pdb()) )
machine = gScope.machineType()
self.assertTrue( (machine == pykd.IMAGE_FILE_MACHINE_I386) or
(machine == pykd.IMAGE_FILE_MACHINE_AMD64) )
def testFindByRva(self):
gScope = pykd.diaLoadPdb( str(target.module.pdb()) )
func = gScope["FuncWithName0"]
tplSymOffset = gScope.findByRva(func.rva(), pykd.SymTagFunction)
self.assertEqual(tplSymOffset[0].indexId(), func.indexId())
self.assertEqual(tplSymOffset[1], 0)
tplSymOffset = gScope.findByRva(func.rva()+2, pykd.SymTagFunction)
self.assertEqual(tplSymOffset[0].indexId(), func.indexId())
self.assertEqual(tplSymOffset[1], 2)
def testSymbolById(self):
gScope = pykd.diaLoadPdb( str(target.module.pdb()) )
func = gScope["FuncWithName0"]
self.assertEqual( gScope.symbolById(func.indexId()).indexId(),
func.indexId())
def testCount(self):
gScope = pykd.diaLoadPdb( str(target.module.pdb()) )
var = gScope["FuncWithName1"]["_unionTest"]
self.assertEqual( 2, var.type().count() )
def testDataKind(self):
gScope = pykd.diaLoadPdb( str(target.module.pdb()) )
self.assertEqual( pykd.DataIsGlobal, gScope["g_structTest"].dataKind() )
self.assertEqual( pykd.DataIsParam, gScope["EnumWindowsProc1"]["hWindow"].dataKind() )
def testSymbolHash(self):
"""Test set of DIA symbols"""
gScope = pykd.diaLoadPdb( str(target.module.pdb()) )
symSet = set([ gScope["g_structTest"], gScope["EnumWindowsProc1"], gScope["g_structTest"] ])
self.assertEqual( 2, len(symSet) )
self.assertTrue( gScope["g_structTest"] in symSet )
self.assertFalse( gScope["EnumWindowsProc2"] in symSet )

View File

@ -18,6 +18,9 @@ import memtest
import moduletest
import typeinfo
import typedvar
import breakpoint
#import regtest
#import mspdbtest
#import localstest
@ -56,6 +59,8 @@ def getTestSuite( singleName = "" ):
# ^^^
unittest.TestLoader().loadTestsFromTestCase( TerminateProcessTest ),
unittest.TestLoader().loadTestsFromTestCase( breakpoint.BreakpointTest ),
#unittest.TestLoader().loadTestsFromTestCase( mspdbtest.MsPdbTest ),
#unittest.TestLoader().loadTestsFromTestCase( localstest.LocalVarsTest ),
#unittest.TestLoader().loadTestsFromTestCase( ehexcepttest.EhExceptionTest ),
@ -77,4 +82,4 @@ if __name__ == "__main__":
target.appPath = sys.argv[1]
target.moduleName = os.path.splitext(os.path.basename(target.appPath))[0]
unittest.TextTestRunner(stream=sys.stdout, verbosity=2).run( getTestSuite() )\
unittest.TextTestRunner(stream=sys.stdout, verbosity=2).run( getTestSuite() )

View File

@ -237,7 +237,7 @@ class TypedVarTest( unittest.TestCase ):
def testPointerToFunction(self):
funcptr = target.module.typedVar( "CdeclFuncPtr" )
self.assertEqual( funcptr, target.module.CdeclFunc )
self.assertEqual( funcptr.deref(), target.module.CdeclFunc )
#tv1 = target.module.typedVar( "g_unTypedPtrToFunction" )