[0.2.x] + locals

git-svn-id: https://pykd.svn.codeplex.com/svn@79357 9b283d60-5439-405e-af05-b73fd8c4d996
This commit is contained in:
SND\EreTIk_cp 2012-09-04 14:58:50 +00:00 committed by Mikhail I. Izmestev
parent 71b3f0df9e
commit 77b1eee2f4
18 changed files with 381 additions and 130 deletions

View File

@ -59,8 +59,7 @@ struct STACK_FRAME_DESC {
ULONG64 stackOffset;
};
ULONG getStackTraceFrameCount();
void getStackTrace( STACK_FRAME_DESC* frames, ULONG frameCount, ULONG* frameReturned = NULL );
void getStackTrace(std::vector<STACK_FRAME_DESC> &frames);
//breakpoints
ULONG breakPointSet( ULONG64 offset, bool hardware = false, ULONG size = 0, ULONG accessType = 0 );

View File

@ -8,6 +8,36 @@ namespace pykd {
///////////////////////////////////////////////////////////////////////////////
static const struct DiaRegToRegRelativeAmd64 : DiaRegToRegRelativeBase
{
typedef std::map<ULONG, ULONG> Base;
DiaRegToRegRelativeAmd64();
} g_DiaRegToRegRelativeAmd64;
DiaRegToRegRelativeAmd64::DiaRegToRegRelativeAmd64()
{
(*this)[CV_AMD64_RIP] = rriInstructionPointer;
(*this)[CV_AMD64_RBP] = rriStackFrame;
(*this)[CV_AMD64_RSP] = rriStackPointer;
}
///////////////////////////////////////////////////////////////////////////////
static const struct DiaRegToRegRelativeI386 : DiaRegToRegRelativeBase
{
typedef std::map<ULONG, ULONG> Base;
DiaRegToRegRelativeI386();
} g_DiaRegToRegRelativeI386;
DiaRegToRegRelativeI386::DiaRegToRegRelativeI386()
{
(*this)[CV_REG_EIP] = rriInstructionPointer;
(*this)[CV_REG_EBP] = rriStackFrame;
(*this)[CV_REG_ESP] = rriStackPointer;
}
///////////////////////////////////////////////////////////////////////////////
const std::string DiaException::descPrefix("pyDia: ");
std::string DiaException::makeFullDesc(const std::string &desc, HRESULT hres)
@ -96,18 +126,21 @@ std::string getBasicTypeName( ULONG basicType )
////////////////////////////////////////////////////////////////////////////////
DiaSymbol::DiaSymbol(__inout DiaSymbolPtr &_symbol )
DiaSymbol::DiaSymbol(__inout DiaSymbolPtr &_symbol, DWORD machineType )
: m_symbol(_symbol), m_machineType(machineType)
{
m_symbol = _symbol;
m_symbol->get_machineType(&m_machineType);
}
//////////////////////////////////////////////////////////////////////////////////
DiaSymbol::DiaSymbol( IDiaSymbol *_symbol )
SymbolPtr DiaSymbol::fromGlobalScope( IDiaSymbol *_symbol )
{
m_symbol = _symbol;
m_symbol->get_machineType(&m_machineType);
DWORD machineType;
HRESULT hres = _symbol->get_machineType(&machineType);
if (S_OK != hres)
throw DiaException("IDiaSymbol::get_machineType", hres);
return SymbolPtr( new DiaSymbol(DiaSymbolPtr(_symbol), machineType) );
}
//////////////////////////////////////////////////////////////////////////////////
@ -148,7 +181,7 @@ SymbolPtrList DiaSymbol::findChildren(
ULONG celt;
while ( SUCCEEDED(symbols->Next(1, &child, &celt)) && (celt == 1) )
{
childList.push_back( SymbolPtr( new DiaSymbol(child) ) );
childList.push_back( SymbolPtr( new DiaSymbol(child, m_machineType) ) );
child = NULL;
}
@ -220,7 +253,7 @@ SymbolPtr DiaSymbol::getChildByIndex(ULONG symTag, ULONG _index )
if (S_OK != hres)
throw DiaException("Call IDiaEnumSymbols::Item", hres);
return SymbolPtr( new DiaSymbol(child) );
return SymbolPtr( new DiaSymbol(child, m_machineType) );
}
////////////////////////////////////////////////////////////////////////////////
@ -247,7 +280,7 @@ SymbolPtr DiaSymbol::getChildByName(const std::string &name )
if (S_OK != hres)
throw DiaException("Call IDiaEnumSymbols::Item", hres);
return SymbolPtr( new DiaSymbol(child) );
return SymbolPtr( new DiaSymbol(child, m_machineType) );
}
std::string pattern = "*";
@ -279,7 +312,7 @@ SymbolPtr DiaSymbol::getChildByName(const std::string &name )
if (S_OK != hres)
throw DiaException("Call IDiaEnumSymbols::Item", hres);
SymbolPtr symPtr = SymbolPtr( new DiaSymbol(child) );
SymbolPtr symPtr = SymbolPtr( new DiaSymbol(child, m_machineType) );
if ( name == symPtr->getName() )
return symPtr;
@ -304,6 +337,33 @@ ULONG DiaSymbol::getDataKind()
////////////////////////////////////////////////////////////////////////////////
ULONG DiaSymbol::getRegRealativeId()
{
switch (m_machineType)
{
case IMAGE_FILE_MACHINE_AMD64:
return getRegRealativeIdImpl(g_DiaRegToRegRelativeAmd64);
case IMAGE_FILE_MACHINE_I386:
return getRegRealativeIdImpl(g_DiaRegToRegRelativeI386);
}
throw DiaException("Unsupported machine type");
}
////////////////////////////////////////////////////////////////////////////////
ULONG DiaSymbol::getRegRealativeIdImpl(const DiaRegToRegRelativeBase &DiaRegToRegRelative)
{
DiaRegToRegRelativeBase::const_iterator it =
DiaRegToRegRelative.find(callSymbol(get_registerId));
if (it == DiaRegToRegRelative.end())
throw DiaException("Cannot convert DAI register ID to relative register ID");
return it->second;
}
////////////////////////////////////////////////////////////////////////////////
ULONG DiaSymbol::getIndexId()
{
return callSymbol(get_symIndexId);
@ -313,7 +373,8 @@ ULONG DiaSymbol::getIndexId()
SymbolPtr DiaSymbol::getIndexType()
{
return SymbolPtr( new DiaSymbol(callSymbol(get_arrayIndexType) ) );
DiaSymbolPtr diaSymbol(callSymbol(get_arrayIndexType));
return SymbolPtr( new DiaSymbol(diaSymbol, m_machineType) );
}
////////////////////////////////////////////////////////////////////////////////
@ -381,7 +442,8 @@ ULONG DiaSymbol::getSymTag()
SymbolPtr DiaSymbol::getType()
{
return SymbolPtr( new DiaSymbol( callSymbol(get_type) ) );
DiaSymbolPtr diaSymbol(callSymbol(get_type));
return SymbolPtr( new DiaSymbol( diaSymbol, m_machineType ) );
}
////////////////////////////////////////////////////////////////////////////////
@ -480,9 +542,10 @@ ULONG DiaSymbol::getVirtualBaseDispIndex()
ULONG DiaSymbol::getVirtualBaseDispSize()
{
SymbolPtr baseTableType = SymbolPtr( new DiaSymbol( callSymbol(get_virtualBaseTableType) ) );
DiaSymbolPtr diaSymbol(callSymbol(get_virtualBaseTableType));
SymbolPtr baseTableType = SymbolPtr( new DiaSymbol( diaSymbol, m_machineType ) );
return (ULONG)baseTableType->getType()->getSize();
return (ULONG)baseTableType->getType()->getSize();
}
//////////////////////////////////////////////////////////////////////////////
@ -534,10 +597,13 @@ SymbolPtr DiaSession::findByRva( ULONG rva, ULONG symTag, LONG* pdisplacement )
throw DiaException("Call IDiaSession::findSymbolByRVAEx", hres);
if (!child)
throw DiaException("Call IDiaSession::findSymbolByRVAEx", E_UNEXPECTED);
if ( pdisplacement == NULL && displacement != 0 )
if ( !pdisplacement && displacement)
throw DiaException("Call IDiaSession::findSymbolByRVAEx failed to find suymbol" );
return SymbolPtr( new DiaSymbol(child) );
if (pdisplacement)
*pdisplacement = displacement;
return SymbolPtr( new DiaSymbol(child, m_globalSymbol->getMachineType() ) );
}
///////////////////////////////////////////////////////////////////////////////

View File

@ -19,6 +19,8 @@ typedef CComPtr< IDiaEnumLineNumbers > DiaEnumLineNumbersPtr;
typedef CComPtr< IDiaLineNumber> DiaLineNumberPtr;
typedef CComPtr< IDiaSourceFile > DiaSourceFilePtr;
typedef std::map<ULONG, ULONG> DiaRegToRegRelativeBase;
//////////////////////////////////////////////////////////////////////////////
class DiaException : public SymbolException {
@ -51,10 +53,9 @@ private:
class DiaSymbol : public Symbol {
public:
DiaSymbol( DiaSymbolPtr &_symbol, DWORD machineType );
DiaSymbol( DiaSymbolPtr &_symbol );
DiaSymbol( IDiaSymbol *_symbol );
static SymbolPtr fromGlobalScope( IDiaSymbol *_symbol );
SymbolPtr getChildByName(const std::string &_name );
@ -105,6 +106,7 @@ public:
ULONG getDataKind();
//ULONG getRegisterId();
virtual ULONG getRegRealativeId() override;
ULONG getMachineType() {
return m_machineType;
@ -195,6 +197,8 @@ protected:
// const char *prefix = NULL
//);
ULONG getRegRealativeIdImpl(const DiaRegToRegRelativeBase &DiaRegToRegRelative);
template <typename TRet>
TRet callSymbolT(
HRESULT(STDMETHODCALLTYPE IDiaSymbol::*method)(TRet *),
@ -222,8 +226,8 @@ public:
DiaSession( IDiaSession* session, IDiaSymbol *globalScope ) :
m_globalScope( globalScope ),
m_session( session ),
m_globalSymbol( new DiaSymbol( globalScope ) )
m_globalSymbol( DiaSymbol::fromGlobalScope( globalScope ) ),
m_session( session )
{}
SymbolPtr& getSymbolScope() {

View File

@ -18,10 +18,189 @@ python::dict getLocals()
///////////////////////////////////////////////////////////////////////////////
python::dict getLocalsByFrame( StackFrame &frame )
class BuildLocals
{
python::dict dct;
return dct;
public:
BuildLocals( ModulePtr mod, const StackFrame &frame )
: m_mod(mod), m_frame(frame), m_formalGen(0)
{
m_ipRva = static_cast<ULONG>(m_frame.m_instructionOffset - m_mod->getBase());
}
void process( SymbolPtr symParent );
python::dict &getResult() {
return m_dct;
}
protected:
void addVar(SymbolPtr symVar);
private:
ModulePtr m_mod;
const StackFrame &m_frame;
python::dict m_dct;
size_t m_formalGen;
ULONG m_ipRva;
};
///////////////////////////////////////////////////////////////////////////////
void BuildLocals::process(
SymbolPtr symParent
)
{
// add vars from current scope
SymbolPtrList symList = symParent->findChildren(SymTagData);
SymbolPtrList::iterator itVar = symList.begin();
for (; itVar != symList.end(); ++itVar)
addVar(*itVar);
// find inners scopes
symList = symParent->findChildren(SymTagBlock);
SymbolPtrList::iterator itScope = symList.begin();
for (; itScope != symList.end(); ++itScope)
{
SymbolPtr scope = *itScope;
ULONG scopeRva = scope->getRva();
if (scopeRva <= m_ipRva && (scopeRva + scope->getSize()) > m_ipRva)
process(scope);
}
}
///////////////////////////////////////////////////////////////////////////////
void BuildLocals::addVar(SymbolPtr symVar)
{
std::string name;
try
{
name = symVar->getName();
if (name.empty())
return;
}
catch (const SymbolException &except)
{
DBG_UNREFERENCED_PARAMETER(except);
return;
}
if (m_dct.has_key(name))
{
std::stringstream sstream;
sstream << name << "#" << std::dec << ++m_formalGen;
name = sstream.str();
}
BOOST_ASSERT(!m_dct.has_key(name));
if (m_dct.has_key(name))
return;
ULONG64 varAddr;
const LocationType locType = static_cast<LocationType>(symVar->getLocType());
switch (locType)
{
case LocIsStatic:
varAddr = m_mod->getBase() + symVar->getRva();
break;
case LocIsRegRel:
{
RegRealativeId rri;
try
{
rri = static_cast<RegRealativeId>(symVar->getRegRealativeId());
}
catch (const DbgException &except)
{
DBG_UNREFERENCED_PARAMETER(except);
return;
}
varAddr = m_frame.getValue(rri, symVar->getOffset());
}
break;
default:
BOOST_ASSERT(LocIsEnregistered == locType);
return;
}
TypeInfoPtr typeInfo = TypeInfo::getTypeInfo(symVar);
TypedVarPtr typedVar = TypedVar::getTypedVarByTypeInfo(typeInfo, varAddr);
typedVar->setDataKind( symVar->getDataKind() );
m_dct[name] = typedVar;
}
///////////////////////////////////////////////////////////////////////////////
static bool IsInDebugRange(
SymbolPtr func,
ULONG ipRva
)
{
SymbolPtrList lstFuncDebugStart;
SymbolPtrList lstFuncDebugEnd;
try
{
lstFuncDebugStart = func->findChildren(SymTagFuncDebugStart);
if (1 != lstFuncDebugStart.size())
{
BOOST_ASSERT(lstFuncDebugStart.empty());
return true;
}
lstFuncDebugEnd = func->findChildren(SymTagFuncDebugEnd);
if (1 != lstFuncDebugEnd.size())
{
BOOST_ASSERT(lstFuncDebugEnd.empty());
return true;
}
}
catch (const SymbolException &except)
{
DBG_UNREFERENCED_PARAMETER(except);
return true;
}
return
((*lstFuncDebugStart.begin())->getRva() <= ipRva) &&
((*lstFuncDebugEnd.begin())->getRva() >= ipRva);
}
///////////////////////////////////////////////////////////////////////////////
python::dict getLocalsByFrame( const StackFrame &frame )
{
// query target fuction by $ip register
ModulePtr mod;
SymbolPtr func;
try
{
mod = Module::loadModuleByOffset(frame.m_instructionOffset);
LONG displacemnt;
func = mod->getSymbolByVa(frame.m_instructionOffset, SymTagFunction, &displacemnt );
}
catch (const DbgException &except)
{
DBG_UNREFERENCED_PARAMETER(except);
return python::dict();
}
#ifdef _DEBUG
std::string funcName;
funcName = func->getName();
#endif // _DEBUG
if (!IsInDebugRange(func, static_cast<ULONG>(frame.m_instructionOffset - mod->getBase())))
{
// not in debug range
return python::dict();
}
BuildLocals buildLocals(mod, frame);
buildLocals.process(func);
return buildLocals.getResult();
}
///////////////////////////////////////////////////////////////////////////////

View File

@ -8,7 +8,7 @@ namespace pykd {
python::dict getLocals();
python::dict getLocalsByFrame( StackFrame &frame );
python::dict getLocalsByFrame( const StackFrame &frame );
///////////////////////////////////////////////////////////////////////////////

View File

@ -220,7 +220,7 @@ std::string Module::getSymbolNameByVa( ULONG64 offset )
sstr << sym->getName();
if ( displacement > 0 )
if ( displacement > 0 && displacement )
sstr << '+' << std::hex << displacement;
else if ( displacement < 0 )
sstr << '-' << std::hex << -displacement;

View File

@ -94,7 +94,7 @@ public:
ULONG64 getSymbolSize( const std::string &symName );
SymbolPtr getSymbolByVa( ULONG64 offset, ULONG symTag, LONG* displacemnt );
SymbolPtr getSymbolByVa( ULONG64 offset, ULONG symTag, LONG* displacemnt = NULL );
std::string getSymbolNameByVa( ULONG64 offset );

View File

@ -1,10 +1,14 @@
<?xml version="1.0" encoding="windows-1251"?>
<VisualStudioProject
ProjectType="Visual C++"
Version="9,00"
Version="9.00"
Name="pykd"
ProjectGUID="{FE961905-666F-4908-A212-961465F46F13}"
RootNamespace="pykd"
SccProjectName="$/pykd/branch/0.2.x/pykd"
SccAuxPath="https://tfs.codeplex.com/tfs/TFS08"
SccLocalPath="."
SccProvider="{4CA58AB2-18FA-4F8D-95D4-32DDF27D184C}"
Keyword="Win32Proj"
TargetFrameworkVersion="0"
>

View File

@ -295,7 +295,7 @@ BOOST_PYTHON_MODULE( pykd )
.def("offset", &Module::getSymbolOffset,
"Return offset of the symbol" )
.def("findSymbol", &Module::getSymbolNameByVa,
"Return symbol name by offset" )
"Return symbol name by virtual address" )
.def("rva", &Module::getSymbolRva,
"Return rva of the symbol" )
.def("sizeof", &Module::getSymbolSize,
@ -382,8 +382,8 @@ BOOST_PYTHON_MODULE( pykd )
"Return a frame's stack offset" )
.def_readonly( "frameNumber", &StackFrame::m_frameNumber,
"Return a frame's number" )
//.def( "getLocals", &StackFrame::getLocals, StackFrame_getLocals( python::args( "ctx" ),
// "Get list of local variables for this stack frame" ) )
.def( "getLocals", &StackFrame::getLocals,
"Get list of local variables for this stack frame" )
.def( "__str__", &StackFrame::print,
"Return stacks frame as a string");

View File

@ -41,27 +41,38 @@ std::string StackFrame::print() const
////////////////////////////////////////////////////////////////////////////////
python::dict StackFrame::getLocals()
python::dict StackFrame::getLocals() const
{
return getLocalsByFrame( *this );
}
///////////////////////////////////////////////////////////////////////////////
ULONG64 StackFrame::getValue(RegRealativeId rri, LONG64 offset /*= 0*/) const
{
switch (rri)
{
case rriInstructionPointer: return m_instructionOffset + offset;
case rriStackFrame: return m_frameOffset + offset;
case rriStackPointer: return m_stackOffset + offset;
}
BOOST_ASSERT(!"Unexcepted error");
throw DbgException(__FUNCTION__ " Unexcepted error" );
}
////////////////////////////////////////////////////////////////////////////////
python::list getCurrentStack()
{
ULONG frameCount = getStackTraceFrameCount();
std::vector<STACK_FRAME_DESC> frames;
getStackTrace( frames );
std::vector<STACK_FRAME_DESC> frames(frameCount);
python::list frameList;
getStackTrace( &frames[0], frameCount );
python::list frameList;
for ( ULONG i = 0; i < frameCount; ++i )
for ( ULONG i = 0; i < frames.size(); ++i )
{
python::object frameObj( StackFrame( frames.at(i) ) );
frameList.append( frameObj );
}
@ -72,12 +83,8 @@ python::list getCurrentStack()
StackFrame getCurrentStackFrame()
{
ULONG frameCount = getStackTraceFrameCount();
std::vector<STACK_FRAME_DESC> frames(frameCount);
getStackTrace( &frames[0], frameCount );
std::vector<STACK_FRAME_DESC> frames;
getStackTrace( frames );
return frames[0];
}

View File

@ -6,6 +6,7 @@
#include "dbgengine.h"
#include "context.h"
#include "symengine.h"
////////////////////////////////////////////////////////////////////////////////
@ -18,10 +19,12 @@ class StackFrame
public:
StackFrame( const STACK_FRAME_DESC& desc );
python::dict getLocals();
python::dict getLocals() const;
std::string print() const;
ULONG64 getValue(RegRealativeId rri, LONG64 offset = 0) const;
public:
ULONG m_frameNumber;

View File

@ -111,6 +111,15 @@ enum BasicType
////////////////////////////////////////////////////////////////////////////////
enum RegRealativeId
{
rriInstructionPointer,
rriStackFrame,
rriStackPointer
};
////////////////////////////////////////////////////////////////////////////////
class Symbol {
public:
@ -144,7 +153,7 @@ public:
virtual bool isConstant() = 0;
virtual bool isIndirectVirtualBaseClass() = 0;
virtual bool isVirtualBaseClass() = 0;
virtual ULONG getRegRealativeId() = 0; // <- RegRealativeId
};
///////////////////////////////////////////////////////////////////////////////

View File

@ -673,46 +673,26 @@ ULONG64 getRegInstructionPointer()
///////////////////////////////////////////////////////////////////////////////
ULONG getStackTraceFrameCount()
void getStackTrace(std::vector<STACK_FRAME_DESC> &frames)
{
PyThread_StateRestore pyThreadRestore( g_dbgEng->pystate );
HRESULT hres;
ULONG filledFrames;
hres = g_dbgEng->control->GetStackTrace( 0, 0, 0, NULL, 0, &filledFrames );
if ( FAILED( hres ) )
throw DbgException( "IDebugControl::GetStackTrace failed" );
return filledFrames;
}
///////////////////////////////////////////////////////////////////////////////
void getStackTrace( STACK_FRAME_DESC* frames, ULONG frameCount, ULONG* frameReturned )
{
PyThread_StateRestore pyThreadRestore( g_dbgEng->pystate );
HRESULT hres;
ULONG filledFrames;
std::vector<DEBUG_STACK_FRAME> stack(frameCount);
hres = g_dbgEng->control->GetStackTrace( 0, 0, 0, &stack[0], frameCount, &filledFrames);
HRESULT hres;
ULONG filledFrames = 1024;
std::vector<DEBUG_STACK_FRAME> dbgFrames(filledFrames);
hres = g_dbgEng->control->GetStackTrace( 0, 0, 0, &dbgFrames[0], filledFrames, &filledFrames);
if ( FAILED( hres ) )
throw DbgException( "IDebugControl::GetStackTrace failed" );
frames.resize(filledFrames);
for ( ULONG i = 0; i < filledFrames; ++i )
{
frames[i].number = stack[i].FrameNumber;
frames[i].instructionOffset = stack[i].InstructionOffset;
frames[i].returnOffset = stack[i].ReturnOffset;
frames[i].frameOffset = stack[i].FrameOffset;
frames[i].stackOffset = stack[i].StackOffset;
frames[i].number = dbgFrames[i].FrameNumber;
frames[i].instructionOffset = dbgFrames[i].InstructionOffset;
frames[i].returnOffset = dbgFrames[i].ReturnOffset;
frames[i].frameOffset = dbgFrames[i].FrameOffset;
frames[i].stackOffset = dbgFrames[i].StackOffset;
}
if ( frameReturned )
*frameReturned = filledFrames;
}
///////////////////////////////////////////////////////////////////////////////

View File

@ -3,47 +3,42 @@
import unittest
import target
import pykd
import testutils
def testEnumWindowsProc1Locals(testCase, locals):
testCase.assertNotEqual( 0, locals["hWindow"] )
DataIsParam = 3
testCase.assertEqual( DataIsParam, locals["hWindow"].dataKind() )
testCase.assertEqual( 6, locals["lParam"] )
testCase.assertEqual( DataIsParam, locals["lParam"].dataKind() )
DataIsLocal = 1
testCase.assertNotEqual( 0, locals["dwProccessId"] )
testCase.assertEqual( DataIsLocal, locals["dwProccessId"].dataKind() )
DataIsStaticLocal = 2
testCase.assertNotEqual( 0, locals["staticVar"] )
testCase.assertEqual( DataIsStaticLocal, locals["staticVar"].dataKind() )
testCase.assertEqual( locals["dwProccessId"] + 1, locals["staticVar"] )
class LocalVarsTest(unittest.TestCase):
def testLocalVariable(self):
"""Start new process and test local variables"""
_locProcessId = pykd.startProcess( target.appPath + " -testEnumWindows" )
with testutils.ContextCallIt( testutils.KillProcess(_locProcessId) ) as killStartedProcess :
pykd.go() # initial breakpoint -> wmain
pykd.go() # wmain -> targetapp!EnumWindowsProc1
newClnt = pykd.createDbgClient()
newClnt.startProcess( target.appPath + " -testEnumWindows" )
newClnt.go() # initial breakpoint -> wmain
newClnt.go() # wmain -> targetapp!EnumWindowsProc1
# pykd.dprint( "\n" + newClnt.dbgCommand("u") )
locals = newClnt.getLocals()
self.assertNotEqual( 0, locals["hWindow"] )
self.assertEqual( pykd.DataIsParam, locals["hWindow"].dataKind() )
self.assertEqual( 6, locals["lParam"] )
self.assertEqual( pykd.DataIsParam, locals["lParam"].dataKind() )
self.assertNotEqual( 0, locals["dwProccessId"] )
self.assertEqual( pykd.DataIsLocal, locals["dwProccessId"].dataKind() )
self.assertNotEqual( 0, locals["staticVar"] )
self.assertEqual( pykd.DataIsStaticLocal, locals["staticVar"].dataKind() )
self.assertEqual( locals["dwProccessId"] + 1, locals["staticVar"] )
newClnt.go() # targetapp!EnumWindowsProc1 -> targetapp!functionCalledFromEnumWindowsProc1
# get local variables from previous stack frame
prevLocals = newClnt.getCurrentStack()[1].getLocals()
self.assertEqual( len(prevLocals), len(locals) )
for varName in locals.iterkeys():
self.assertEqual( prevLocals[varName], locals[varName] )
newClnt.go() # targetapp!EnumWindowsProc1 -> targetapp!EnumWindowsProc2
locals = newClnt.getLocals()
self.assertEqual( len(locals), 2 )
locValues = locals.values()
self.assertTrue( locValues[0] == 7 or locValues[1] == 7 )
testEnumWindowsProc1Locals(self, pykd.getLocals())
pykd.go() # targetapp!EnumWindowsProc1 -> targetapp!functionCalledFromEnumWindowsProc1
testEnumWindowsProc1Locals(self, pykd.getCurrentStack()[1].getLocals())
pykd.go() # targetapp!EnumWindowsProc1 -> targetapp!EnumWindowsProc2
locals = pykd.getLocals()
self.assertEqual( len(locals), 2 )
locValues = locals.values()
self.assertTrue( locValues[0] == 7 or locValues[1] == 7 )

View File

@ -61,6 +61,6 @@ class ModuleTest( unittest.TestCase ):
self.assertTrue( re.search('targetapp\\.cpp', fileName ) )
self.assertEqual( 2, displacement )
fileName, lineNo, displacement = pykd.getSourceLine()
self.assertEqual( 636, lineNo )
self.assertEqual( 616, lineNo )

View File

@ -19,6 +19,7 @@ import moduletest
import typeinfo
import typedvar
import regtest
import localstest
class StartProcessWithoutParamsTest(unittest.TestCase):
def testStart(self):
@ -30,13 +31,13 @@ class StartProcessWithoutParamsTest(unittest.TestCase):
class TerminateProcessTest(unittest.TestCase):
def testKill(self):
pykd.killProcess( target.processId )
pykd.detachProcess( target.processId )
def getTestSuite( singleName = "" ):
if singleName == "":
return unittest.TestSuite(
[
unittest.TestLoader().loadTestsFromTestCase( StartProcessWithoutParamsTest ),
unittest.TestLoader().loadTestsFromTestCase( target.TargetTest ),
# *** Test without start/kill new processes
unittest.TestLoader().loadTestsFromTestCase( intbase.IntBaseTest ),
unittest.TestLoader().loadTestsFromTestCase( moduletest.ModuleTest ),
@ -44,8 +45,10 @@ def getTestSuite( singleName = "" ):
unittest.TestLoader().loadTestsFromTestCase( typeinfo.TypeInfoTest ),
unittest.TestLoader().loadTestsFromTestCase( typedvar.TypedVarTest ),
unittest.TestLoader().loadTestsFromTestCase( regtest.CpuRegTest ),
# ***
# ^^^
unittest.TestLoader().loadTestsFromTestCase( TerminateProcessTest ),
unittest.TestLoader().loadTestsFromTestCase( localstest.LocalVarsTest ),
] )
else:
return unittest.TestSuite( unittest.TestLoader().loadTestsFromName( singleName ) )

View File

@ -10,13 +10,6 @@ module = None
moduleName = None
processId = None
class TargetTest( unittest.TestCase ):
def testStartStop(self):
_locProcessId = pykd.startProcess( appPath )
pykd.killProcess( _locProcessId )
#module = None
#moduleName = None

View File

@ -14,3 +14,12 @@ class ContextCallIt:
try: self.callIt()
except: pass
class KillProcess:
"""Kill process"""
def __init__(self, processId):
self.processId = processId
def __call__(self):
pykd.killProcess( self.processId )
pykd.detachProcess( self.processId )