mirror of
https://github.com/ivellioscolin/pykd.git
synced 2025-04-20 03:23:23 +08:00
[0.2.x] + locals
git-svn-id: https://pykd.svn.codeplex.com/svn@79357 9b283d60-5439-405e-af05-b73fd8c4d996
This commit is contained in:
parent
71b3f0df9e
commit
77b1eee2f4
@ -59,8 +59,7 @@ struct STACK_FRAME_DESC {
|
|||||||
ULONG64 stackOffset;
|
ULONG64 stackOffset;
|
||||||
};
|
};
|
||||||
|
|
||||||
ULONG getStackTraceFrameCount();
|
void getStackTrace(std::vector<STACK_FRAME_DESC> &frames);
|
||||||
void getStackTrace( STACK_FRAME_DESC* frames, ULONG frameCount, ULONG* frameReturned = NULL );
|
|
||||||
|
|
||||||
//breakpoints
|
//breakpoints
|
||||||
ULONG breakPointSet( ULONG64 offset, bool hardware = false, ULONG size = 0, ULONG accessType = 0 );
|
ULONG breakPointSet( ULONG64 offset, bool hardware = false, ULONG size = 0, ULONG accessType = 0 );
|
||||||
|
@ -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: ");
|
const std::string DiaException::descPrefix("pyDia: ");
|
||||||
|
|
||||||
std::string DiaException::makeFullDesc(const std::string &desc, HRESULT hres)
|
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;
|
DWORD machineType;
|
||||||
m_symbol->get_machineType(&m_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;
|
ULONG celt;
|
||||||
while ( SUCCEEDED(symbols->Next(1, &child, &celt)) && (celt == 1) )
|
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;
|
child = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -220,7 +253,7 @@ SymbolPtr DiaSymbol::getChildByIndex(ULONG symTag, ULONG _index )
|
|||||||
if (S_OK != hres)
|
if (S_OK != hres)
|
||||||
throw DiaException("Call IDiaEnumSymbols::Item", 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)
|
if (S_OK != hres)
|
||||||
throw DiaException("Call IDiaEnumSymbols::Item", hres);
|
throw DiaException("Call IDiaEnumSymbols::Item", hres);
|
||||||
|
|
||||||
return SymbolPtr( new DiaSymbol(child) );
|
return SymbolPtr( new DiaSymbol(child, m_machineType) );
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string pattern = "*";
|
std::string pattern = "*";
|
||||||
@ -279,7 +312,7 @@ SymbolPtr DiaSymbol::getChildByName(const std::string &name )
|
|||||||
if (S_OK != hres)
|
if (S_OK != hres)
|
||||||
throw DiaException("Call IDiaEnumSymbols::Item", 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() )
|
if ( name == symPtr->getName() )
|
||||||
return symPtr;
|
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()
|
ULONG DiaSymbol::getIndexId()
|
||||||
{
|
{
|
||||||
return callSymbol(get_symIndexId);
|
return callSymbol(get_symIndexId);
|
||||||
@ -313,7 +373,8 @@ ULONG DiaSymbol::getIndexId()
|
|||||||
|
|
||||||
SymbolPtr DiaSymbol::getIndexType()
|
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()
|
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()
|
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);
|
throw DiaException("Call IDiaSession::findSymbolByRVAEx", hres);
|
||||||
if (!child)
|
if (!child)
|
||||||
throw DiaException("Call IDiaSession::findSymbolByRVAEx", E_UNEXPECTED);
|
throw DiaException("Call IDiaSession::findSymbolByRVAEx", E_UNEXPECTED);
|
||||||
if ( pdisplacement == NULL && displacement != 0 )
|
if ( !pdisplacement && displacement)
|
||||||
throw DiaException("Call IDiaSession::findSymbolByRVAEx failed to find suymbol" );
|
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() ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
@ -19,6 +19,8 @@ typedef CComPtr< IDiaEnumLineNumbers > DiaEnumLineNumbersPtr;
|
|||||||
typedef CComPtr< IDiaLineNumber> DiaLineNumberPtr;
|
typedef CComPtr< IDiaLineNumber> DiaLineNumberPtr;
|
||||||
typedef CComPtr< IDiaSourceFile > DiaSourceFilePtr;
|
typedef CComPtr< IDiaSourceFile > DiaSourceFilePtr;
|
||||||
|
|
||||||
|
typedef std::map<ULONG, ULONG> DiaRegToRegRelativeBase;
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
class DiaException : public SymbolException {
|
class DiaException : public SymbolException {
|
||||||
@ -51,10 +53,9 @@ private:
|
|||||||
|
|
||||||
class DiaSymbol : public Symbol {
|
class DiaSymbol : public Symbol {
|
||||||
public:
|
public:
|
||||||
|
DiaSymbol( DiaSymbolPtr &_symbol, DWORD machineType );
|
||||||
|
|
||||||
DiaSymbol( DiaSymbolPtr &_symbol );
|
static SymbolPtr fromGlobalScope( IDiaSymbol *_symbol );
|
||||||
|
|
||||||
DiaSymbol( IDiaSymbol *_symbol );
|
|
||||||
|
|
||||||
SymbolPtr getChildByName(const std::string &_name );
|
SymbolPtr getChildByName(const std::string &_name );
|
||||||
|
|
||||||
@ -105,6 +106,7 @@ public:
|
|||||||
ULONG getDataKind();
|
ULONG getDataKind();
|
||||||
|
|
||||||
//ULONG getRegisterId();
|
//ULONG getRegisterId();
|
||||||
|
virtual ULONG getRegRealativeId() override;
|
||||||
|
|
||||||
ULONG getMachineType() {
|
ULONG getMachineType() {
|
||||||
return m_machineType;
|
return m_machineType;
|
||||||
@ -195,6 +197,8 @@ protected:
|
|||||||
// const char *prefix = NULL
|
// const char *prefix = NULL
|
||||||
//);
|
//);
|
||||||
|
|
||||||
|
ULONG getRegRealativeIdImpl(const DiaRegToRegRelativeBase &DiaRegToRegRelative);
|
||||||
|
|
||||||
template <typename TRet>
|
template <typename TRet>
|
||||||
TRet callSymbolT(
|
TRet callSymbolT(
|
||||||
HRESULT(STDMETHODCALLTYPE IDiaSymbol::*method)(TRet *),
|
HRESULT(STDMETHODCALLTYPE IDiaSymbol::*method)(TRet *),
|
||||||
@ -222,8 +226,8 @@ public:
|
|||||||
|
|
||||||
DiaSession( IDiaSession* session, IDiaSymbol *globalScope ) :
|
DiaSession( IDiaSession* session, IDiaSymbol *globalScope ) :
|
||||||
m_globalScope( globalScope ),
|
m_globalScope( globalScope ),
|
||||||
m_session( session ),
|
m_globalSymbol( DiaSymbol::fromGlobalScope( globalScope ) ),
|
||||||
m_globalSymbol( new DiaSymbol( globalScope ) )
|
m_session( session )
|
||||||
{}
|
{}
|
||||||
|
|
||||||
SymbolPtr& getSymbolScope() {
|
SymbolPtr& getSymbolScope() {
|
||||||
|
@ -18,10 +18,189 @@ python::dict getLocals()
|
|||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
python::dict getLocalsByFrame( StackFrame &frame )
|
class BuildLocals
|
||||||
{
|
{
|
||||||
python::dict dct;
|
public:
|
||||||
return dct;
|
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();
|
||||||
}
|
}
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
@ -8,7 +8,7 @@ namespace pykd {
|
|||||||
|
|
||||||
python::dict getLocals();
|
python::dict getLocals();
|
||||||
|
|
||||||
python::dict getLocalsByFrame( StackFrame &frame );
|
python::dict getLocalsByFrame( const StackFrame &frame );
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
@ -220,10 +220,10 @@ std::string Module::getSymbolNameByVa( ULONG64 offset )
|
|||||||
|
|
||||||
sstr << sym->getName();
|
sstr << sym->getName();
|
||||||
|
|
||||||
if ( displacement > 0 )
|
if ( displacement > 0 && displacement )
|
||||||
sstr << '+' << std::hex << displacement;
|
sstr << '+' << std::hex << displacement;
|
||||||
else if ( displacement < 0 )
|
else if ( displacement < 0 )
|
||||||
sstr << '-' << std::hex << -displacement;
|
sstr << '-' << std::hex << -displacement;
|
||||||
|
|
||||||
return sstr.str();
|
return sstr.str();
|
||||||
}
|
}
|
||||||
|
@ -94,7 +94,7 @@ public:
|
|||||||
|
|
||||||
ULONG64 getSymbolSize( const std::string &symName );
|
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 );
|
std::string getSymbolNameByVa( ULONG64 offset );
|
||||||
|
|
||||||
|
@ -1,10 +1,14 @@
|
|||||||
<?xml version="1.0" encoding="windows-1251"?>
|
<?xml version="1.0" encoding="windows-1251"?>
|
||||||
<VisualStudioProject
|
<VisualStudioProject
|
||||||
ProjectType="Visual C++"
|
ProjectType="Visual C++"
|
||||||
Version="9,00"
|
Version="9.00"
|
||||||
Name="pykd"
|
Name="pykd"
|
||||||
ProjectGUID="{FE961905-666F-4908-A212-961465F46F13}"
|
ProjectGUID="{FE961905-666F-4908-A212-961465F46F13}"
|
||||||
RootNamespace="pykd"
|
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"
|
Keyword="Win32Proj"
|
||||||
TargetFrameworkVersion="0"
|
TargetFrameworkVersion="0"
|
||||||
>
|
>
|
||||||
|
@ -295,7 +295,7 @@ BOOST_PYTHON_MODULE( pykd )
|
|||||||
.def("offset", &Module::getSymbolOffset,
|
.def("offset", &Module::getSymbolOffset,
|
||||||
"Return offset of the symbol" )
|
"Return offset of the symbol" )
|
||||||
.def("findSymbol", &Module::getSymbolNameByVa,
|
.def("findSymbol", &Module::getSymbolNameByVa,
|
||||||
"Return symbol name by offset" )
|
"Return symbol name by virtual address" )
|
||||||
.def("rva", &Module::getSymbolRva,
|
.def("rva", &Module::getSymbolRva,
|
||||||
"Return rva of the symbol" )
|
"Return rva of the symbol" )
|
||||||
.def("sizeof", &Module::getSymbolSize,
|
.def("sizeof", &Module::getSymbolSize,
|
||||||
@ -382,8 +382,8 @@ BOOST_PYTHON_MODULE( pykd )
|
|||||||
"Return a frame's stack offset" )
|
"Return a frame's stack offset" )
|
||||||
.def_readonly( "frameNumber", &StackFrame::m_frameNumber,
|
.def_readonly( "frameNumber", &StackFrame::m_frameNumber,
|
||||||
"Return a frame's number" )
|
"Return a frame's number" )
|
||||||
//.def( "getLocals", &StackFrame::getLocals, StackFrame_getLocals( python::args( "ctx" ),
|
.def( "getLocals", &StackFrame::getLocals,
|
||||||
// "Get list of local variables for this stack frame" ) )
|
"Get list of local variables for this stack frame" )
|
||||||
.def( "__str__", &StackFrame::print,
|
.def( "__str__", &StackFrame::print,
|
||||||
"Return stacks frame as a string");
|
"Return stacks frame as a string");
|
||||||
|
|
||||||
|
@ -41,27 +41,38 @@ std::string StackFrame::print() const
|
|||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
python::dict StackFrame::getLocals()
|
python::dict StackFrame::getLocals() const
|
||||||
{
|
{
|
||||||
return getLocalsByFrame( *this );
|
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()
|
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 );
|
for ( ULONG i = 0; i < frames.size(); ++i )
|
||||||
|
|
||||||
python::list frameList;
|
|
||||||
|
|
||||||
for ( ULONG i = 0; i < frameCount; ++i )
|
|
||||||
{
|
{
|
||||||
python::object frameObj( StackFrame( frames.at(i) ) );
|
python::object frameObj( StackFrame( frames.at(i) ) );
|
||||||
|
|
||||||
frameList.append( frameObj );
|
frameList.append( frameObj );
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -72,12 +83,8 @@ python::list getCurrentStack()
|
|||||||
|
|
||||||
StackFrame getCurrentStackFrame()
|
StackFrame getCurrentStackFrame()
|
||||||
{
|
{
|
||||||
ULONG frameCount = getStackTraceFrameCount();
|
std::vector<STACK_FRAME_DESC> frames;
|
||||||
|
getStackTrace( frames );
|
||||||
std::vector<STACK_FRAME_DESC> frames(frameCount);
|
|
||||||
|
|
||||||
getStackTrace( &frames[0], frameCount );
|
|
||||||
|
|
||||||
return frames[0];
|
return frames[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6,6 +6,7 @@
|
|||||||
|
|
||||||
#include "dbgengine.h"
|
#include "dbgengine.h"
|
||||||
#include "context.h"
|
#include "context.h"
|
||||||
|
#include "symengine.h"
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
@ -18,10 +19,12 @@ class StackFrame
|
|||||||
public:
|
public:
|
||||||
StackFrame( const STACK_FRAME_DESC& desc );
|
StackFrame( const STACK_FRAME_DESC& desc );
|
||||||
|
|
||||||
python::dict getLocals();
|
python::dict getLocals() const;
|
||||||
|
|
||||||
std::string print() const;
|
std::string print() const;
|
||||||
|
|
||||||
|
ULONG64 getValue(RegRealativeId rri, LONG64 offset = 0) const;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
ULONG m_frameNumber;
|
ULONG m_frameNumber;
|
||||||
|
@ -111,6 +111,15 @@ enum BasicType
|
|||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
enum RegRealativeId
|
||||||
|
{
|
||||||
|
rriInstructionPointer,
|
||||||
|
rriStackFrame,
|
||||||
|
rriStackPointer
|
||||||
|
};
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
class Symbol {
|
class Symbol {
|
||||||
|
|
||||||
public:
|
public:
|
||||||
@ -144,7 +153,7 @@ public:
|
|||||||
virtual bool isConstant() = 0;
|
virtual bool isConstant() = 0;
|
||||||
virtual bool isIndirectVirtualBaseClass() = 0;
|
virtual bool isIndirectVirtualBaseClass() = 0;
|
||||||
virtual bool isVirtualBaseClass() = 0;
|
virtual bool isVirtualBaseClass() = 0;
|
||||||
|
virtual ULONG getRegRealativeId() = 0; // <- RegRealativeId
|
||||||
};
|
};
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
@ -673,46 +673,26 @@ ULONG64 getRegInstructionPointer()
|
|||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
ULONG getStackTraceFrameCount()
|
void getStackTrace(std::vector<STACK_FRAME_DESC> &frames)
|
||||||
{
|
{
|
||||||
PyThread_StateRestore pyThreadRestore( g_dbgEng->pystate );
|
PyThread_StateRestore pyThreadRestore( g_dbgEng->pystate );
|
||||||
|
|
||||||
HRESULT hres;
|
HRESULT hres;
|
||||||
ULONG filledFrames;
|
ULONG filledFrames = 1024;
|
||||||
|
std::vector<DEBUG_STACK_FRAME> dbgFrames(filledFrames);
|
||||||
hres = g_dbgEng->control->GetStackTrace( 0, 0, 0, NULL, 0, &filledFrames );
|
hres = g_dbgEng->control->GetStackTrace( 0, 0, 0, &dbgFrames[0], filledFrames, &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);
|
|
||||||
if ( FAILED( hres ) )
|
if ( FAILED( hres ) )
|
||||||
throw DbgException( "IDebugControl::GetStackTrace failed" );
|
throw DbgException( "IDebugControl::GetStackTrace failed" );
|
||||||
|
|
||||||
|
frames.resize(filledFrames);
|
||||||
for ( ULONG i = 0; i < filledFrames; ++i )
|
for ( ULONG i = 0; i < filledFrames; ++i )
|
||||||
{
|
{
|
||||||
frames[i].number = stack[i].FrameNumber;
|
frames[i].number = dbgFrames[i].FrameNumber;
|
||||||
frames[i].instructionOffset = stack[i].InstructionOffset;
|
frames[i].instructionOffset = dbgFrames[i].InstructionOffset;
|
||||||
frames[i].returnOffset = stack[i].ReturnOffset;
|
frames[i].returnOffset = dbgFrames[i].ReturnOffset;
|
||||||
frames[i].frameOffset = stack[i].FrameOffset;
|
frames[i].frameOffset = dbgFrames[i].FrameOffset;
|
||||||
frames[i].stackOffset = stack[i].StackOffset;
|
frames[i].stackOffset = dbgFrames[i].StackOffset;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( frameReturned )
|
|
||||||
*frameReturned = filledFrames;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
@ -3,47 +3,42 @@
|
|||||||
import unittest
|
import unittest
|
||||||
import target
|
import target
|
||||||
import pykd
|
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):
|
class LocalVarsTest(unittest.TestCase):
|
||||||
def testLocalVariable(self):
|
def testLocalVariable(self):
|
||||||
"""Start new process and test local variables"""
|
"""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()
|
testEnumWindowsProc1Locals(self, pykd.getLocals())
|
||||||
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 )
|
|
||||||
|
|
||||||
|
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 )
|
||||||
|
@ -61,6 +61,6 @@ class ModuleTest( unittest.TestCase ):
|
|||||||
self.assertTrue( re.search('targetapp\\.cpp', fileName ) )
|
self.assertTrue( re.search('targetapp\\.cpp', fileName ) )
|
||||||
self.assertEqual( 2, displacement )
|
self.assertEqual( 2, displacement )
|
||||||
fileName, lineNo, displacement = pykd.getSourceLine()
|
fileName, lineNo, displacement = pykd.getSourceLine()
|
||||||
self.assertEqual( 636, lineNo )
|
self.assertEqual( 616, lineNo )
|
||||||
|
|
||||||
|
|
||||||
|
@ -19,6 +19,7 @@ import moduletest
|
|||||||
import typeinfo
|
import typeinfo
|
||||||
import typedvar
|
import typedvar
|
||||||
import regtest
|
import regtest
|
||||||
|
import localstest
|
||||||
|
|
||||||
class StartProcessWithoutParamsTest(unittest.TestCase):
|
class StartProcessWithoutParamsTest(unittest.TestCase):
|
||||||
def testStart(self):
|
def testStart(self):
|
||||||
@ -30,13 +31,13 @@ class StartProcessWithoutParamsTest(unittest.TestCase):
|
|||||||
class TerminateProcessTest(unittest.TestCase):
|
class TerminateProcessTest(unittest.TestCase):
|
||||||
def testKill(self):
|
def testKill(self):
|
||||||
pykd.killProcess( target.processId )
|
pykd.killProcess( target.processId )
|
||||||
|
pykd.detachProcess( target.processId )
|
||||||
|
|
||||||
def getTestSuite( singleName = "" ):
|
def getTestSuite( singleName = "" ):
|
||||||
if singleName == "":
|
if singleName == "":
|
||||||
return unittest.TestSuite(
|
return unittest.TestSuite(
|
||||||
[
|
[
|
||||||
unittest.TestLoader().loadTestsFromTestCase( StartProcessWithoutParamsTest ),
|
unittest.TestLoader().loadTestsFromTestCase( StartProcessWithoutParamsTest ),
|
||||||
unittest.TestLoader().loadTestsFromTestCase( target.TargetTest ),
|
|
||||||
# *** Test without start/kill new processes
|
# *** Test without start/kill new processes
|
||||||
unittest.TestLoader().loadTestsFromTestCase( intbase.IntBaseTest ),
|
unittest.TestLoader().loadTestsFromTestCase( intbase.IntBaseTest ),
|
||||||
unittest.TestLoader().loadTestsFromTestCase( moduletest.ModuleTest ),
|
unittest.TestLoader().loadTestsFromTestCase( moduletest.ModuleTest ),
|
||||||
@ -44,8 +45,10 @@ def getTestSuite( singleName = "" ):
|
|||||||
unittest.TestLoader().loadTestsFromTestCase( typeinfo.TypeInfoTest ),
|
unittest.TestLoader().loadTestsFromTestCase( typeinfo.TypeInfoTest ),
|
||||||
unittest.TestLoader().loadTestsFromTestCase( typedvar.TypedVarTest ),
|
unittest.TestLoader().loadTestsFromTestCase( typedvar.TypedVarTest ),
|
||||||
unittest.TestLoader().loadTestsFromTestCase( regtest.CpuRegTest ),
|
unittest.TestLoader().loadTestsFromTestCase( regtest.CpuRegTest ),
|
||||||
# ***
|
# ^^^
|
||||||
unittest.TestLoader().loadTestsFromTestCase( TerminateProcessTest ),
|
unittest.TestLoader().loadTestsFromTestCase( TerminateProcessTest ),
|
||||||
|
|
||||||
|
unittest.TestLoader().loadTestsFromTestCase( localstest.LocalVarsTest ),
|
||||||
] )
|
] )
|
||||||
else:
|
else:
|
||||||
return unittest.TestSuite( unittest.TestLoader().loadTestsFromName( singleName ) )
|
return unittest.TestSuite( unittest.TestLoader().loadTestsFromName( singleName ) )
|
||||||
@ -53,7 +56,7 @@ def getTestSuite( singleName = "" ):
|
|||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
|
|
||||||
print "\nTesting PyKd ver. " + pykd.version
|
print "\nTesting PyKd ver. " + pykd.version
|
||||||
|
|
||||||
target.appPath = sys.argv[1]
|
target.appPath = sys.argv[1]
|
||||||
target.moduleName = os.path.splitext(os.path.basename(target.appPath))[0]
|
target.moduleName = os.path.splitext(os.path.basename(target.appPath))[0]
|
||||||
#print "Test module: %s" % target.appPath
|
#print "Test module: %s" % target.appPath
|
||||||
|
@ -10,13 +10,6 @@ module = None
|
|||||||
moduleName = None
|
moduleName = None
|
||||||
processId = None
|
processId = None
|
||||||
|
|
||||||
class TargetTest( unittest.TestCase ):
|
|
||||||
|
|
||||||
def testStartStop(self):
|
|
||||||
_locProcessId = pykd.startProcess( appPath )
|
|
||||||
pykd.killProcess( _locProcessId )
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#module = None
|
#module = None
|
||||||
#moduleName = None
|
#moduleName = None
|
||||||
|
@ -14,3 +14,12 @@ class ContextCallIt:
|
|||||||
try: self.callIt()
|
try: self.callIt()
|
||||||
except: pass
|
except: pass
|
||||||
|
|
||||||
|
class KillProcess:
|
||||||
|
"""Kill process"""
|
||||||
|
def __init__(self, processId):
|
||||||
|
self.processId = processId
|
||||||
|
|
||||||
|
def __call__(self):
|
||||||
|
pykd.killProcess( self.processId )
|
||||||
|
pykd.detachProcess( self.processId )
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user