[~] python thread state moved from dbgExt to TLS

[+] bp without callback - always break when triggered, goLib - demo for this case
[+]  python thread restore for dbgCommand
[~] remove trailing blanks

git-svn-id: https://pykd.svn.codeplex.com/svn@69510 9b283d60-5439-405e-af05-b73fd8c4d996
This commit is contained in:
SND\EreTIk_cp 2011-09-02 07:48:53 +00:00
parent 105ba17ade
commit 5ac233a473
10 changed files with 205 additions and 173 deletions

View File

@ -14,34 +14,50 @@ dbgBreakpointClass::breakpointMap dbgBreakpointClass::m_breakMap;
HRESULT dbgBreakpointClass::onBreakpointEvnet( IDebugBreakpoint* bp )
{
PyThread_StateSave pyThrdState( dbgExt->getThreadState() );
PyThread_StateSave pyThreadSave;
try {
breakpointMap::iterator it = m_breakMap.find( bp );
if ( it != m_breakMap.end() )
return boost::python::extract<HRESULT>( it->second->m_callback() );
breakpointMap::iterator it = m_breakMap.find( bp );
if ( it != m_breakMap.end() )
{
boost::python::object &callback = it->second->m_callback;
if (!callback.is_none())
return boost::python::extract<HRESULT>( callback() );
return DEBUG_STATUS_BREAK;
}
}
catch(...)
{}
return DEBUG_STATUS_NO_CHANGE;
{
}
return DEBUG_STATUS_NO_CHANGE;
}
///////////////////////////////////////////////////////////////////////////////
dbgBreakpointClass::dbgBreakpointClass( ULONG64 offset, boost::python::object &callback )
: m_offset(offset)
, m_callback(callback)
, m_breakpoint(NULL)
{
m_offset = offset;
m_breakpoint = NULL;
m_callback = callback;
set();
set();
}
///////////////////////////////////////////////////////////////////////////////
dbgBreakpointClass::dbgBreakpointClass( ULONG64 offset)
: m_offset(offset)
, m_breakpoint(NULL)
{
// m_callback is None, see dbgBreakpointClass::onBreakpointEvnet
set();
}
///////////////////////////////////////////////////////////////////////////////
dbgBreakpointClass::~dbgBreakpointClass()
{
remove();
@ -53,44 +69,44 @@ bool
dbgBreakpointClass::set()
{
HRESULT hres;
try {
if ( m_breakpoint )
return true;
return true;
hres = dbgExt->control->AddBreakpoint( DEBUG_BREAKPOINT_CODE, DEBUG_ANY_ID, &m_breakpoint );
if ( FAILED( hres ) )
throw DbgException( "IDebugControl::AddBreakpoint failed" );
hres = m_breakpoint->SetOffset( m_offset );
if ( FAILED( hres ) )
throw DbgException( "IDebugBreakpoint::SetOffset failed" );
hres = m_breakpoint->SetFlags( DEBUG_BREAKPOINT_ENABLED );
if ( FAILED( hres ) )
throw DbgException( "IDebugBreakpoint::SetFlags failed" );
m_breakMap.insert( std::make_pair( m_breakpoint, this ) );
return true;
return true;
}
catch( std::exception &e )
{
dbgExt->control->Output( DEBUG_OUTPUT_ERROR, "pykd error: %s\n", e.what() );
}
catch(...)
{
dbgExt->control->Output( DEBUG_OUTPUT_ERROR, "pykd unexpected error\n" );
}
remove();
return false;
catch( std::exception &e )
{
dbgExt->control->Output( DEBUG_OUTPUT_ERROR, "pykd error: %s\n", e.what() );
}
catch(...)
{
dbgExt->control->Output( DEBUG_OUTPUT_ERROR, "pykd unexpected error\n" );
}
remove();
return false;
}
///////////////////////////////////////////////////////////////////////////////
void
dbgBreakpointClass::remove()
{
@ -111,36 +127,36 @@ dbgBreakpointClass::remove()
std::string
dbgBreakpointClass::print() const
{
HRESULT status = S_OK;
HRESULT status = S_OK;
try
{
if (!m_breakpoint)
return "not set";
try
{
if (!m_breakpoint)
return "not set";
DEBUG_BREAKPOINT_PARAMETERS params;
status = m_breakpoint->GetParameters(&params);
if (FAILED(status))
throw DbgException("IDebugBreakpoint::GetParameters failed");
DEBUG_BREAKPOINT_PARAMETERS params;
status = m_breakpoint->GetParameters(&params);
if (FAILED(status))
throw DbgException("IDebugBreakpoint::GetParameters failed");
boost::format fmt("%1$2d %2%%3% %4%:*** ");
fmt % params.Id
% (params.Flags & DEBUG_BREAKPOINT_ENABLED ? 'e' : 'd')
% 'u'
% params.CurrentPassCount;
boost::format fmt("%1$2d %2%%3% %4%:*** ");
fmt % params.Id
% (params.Flags & DEBUG_BREAKPOINT_ENABLED ? 'e' : 'd')
% 'u'
% params.CurrentPassCount;
return fmt.str();
}
catch (std::exception & e)
{
dbgExt->control->Output( DEBUG_OUTPUT_ERROR, "pykd error: %s\n", e.what() );
}
catch (...)
{
dbgExt->control->Output( DEBUG_OUTPUT_ERROR, "pykd unexpected error\n" );
}
return fmt.str();
}
catch (std::exception & e)
{
dbgExt->control->Output( DEBUG_OUTPUT_ERROR, "pykd error: %s\n", e.what() );
}
catch (...)
{
dbgExt->control->Output( DEBUG_OUTPUT_ERROR, "pykd unexpected error\n" );
}
return "";
return "";
}
///////////////////////////////////////////////////////////////////////////////

View File

@ -10,12 +10,13 @@ class dbgBreakpointClass {
public:
dbgBreakpointClass( ULONG64 offset, boost::python::object &callback );
dbgBreakpointClass( ULONG64 offset );
~dbgBreakpointClass();
bool
set();
void
remove();

View File

@ -16,13 +16,16 @@ dbgCommand( const std::string &command )
HRESULT hres;
OutputReader outReader( dbgExt->client );
hres = dbgExt->control->Execute( DEBUG_OUTCTL_THIS_CLIENT, command.c_str(), 0 );
{
PyThread_StateRestore pyThreadRestore;
hres = dbgExt->control->Execute( DEBUG_OUTCTL_THIS_CLIENT, command.c_str(), 0 );
}
if ( FAILED( hres ) )
throw DbgException( "IDebugControl::Execute failed" );
return std::string( outReader.Line() );
}
}
///////////////////////////////////////////////////////////////////////////////
@ -87,7 +90,7 @@ evaluate( const std::string &expression )
&remainderIndex );
if ( FAILED( hres ) )
throw DbgException( "IDebugControl::Evaluate failed" );
throw DbgException( "IDebugControl::Evaluate failed" );
if ( remainderIndex == expression.length() )
value = debugValue.I64;
@ -101,7 +104,7 @@ evaluate( const std::string &expression )
&remainderIndex );
if ( FAILED( hres ) )
throw DbgException( "IDebugControl::Evaluate failed" );
throw DbgException( "IDebugControl::Evaluate failed" );
if ( remainderIndex == expression.length() )
value = debugValue.I32;
@ -118,12 +121,12 @@ breakin()
HRESULT hres;
{
PyThread_StateRestore state;
PyThread_StateRestore pyThreadRestore;
hres = dbgExt->control->SetInterrupt( DEBUG_INTERRUPT_ACTIVE );
}
if ( FAILED( hres ) )
throw DbgException( "IDebugControl::SetInterrupt" );
throw DbgException( "IDebugControl::SetInterrupt" );
}
///////////////////////////////////////////////////////////////////////////////

View File

@ -16,29 +16,27 @@ setExecutionStatus()
HRESULT hres;
hres = dbgExt->control->SetExecutionStatus( status );
if ( FAILED( hres ) )
throw DbgException( "IDebugControl::SetExecutionStatus failed" );
ULONG currentStatus;
ULONG currentStatus;
do {
{
PyThread_StateRestore state(dbgExt->getThreadState());
PyThread_StateRestore pyThreadRestore;
hres = dbgExt->control->WaitForEvent( 0, INFINITE );
}
if ( FAILED( hres ) )
throw DbgException( "IDebugControl::WaitForEvent failed" );
hres = dbgExt->control->GetExecutionStatus( &currentStatus );
if ( FAILED( hres ) )
throw DbgException( "IDebugControl::GetExecutionStatus failed" );
} while( currentStatus != DEBUG_STATUS_BREAK && currentStatus != DEBUG_STATUS_NO_DEBUGGEE );
}

View File

@ -41,10 +41,10 @@ HRESULT debugEvent::GetInterestMask(
*Mask = 0;
*Mask |= DEBUG_EVENT_LOAD_MODULE;
*Mask |= DEBUG_EVENT_UNLOAD_MODULE;
*Mask |= DEBUG_EVENT_UNLOAD_MODULE;
*Mask |= DEBUG_EVENT_SESSION_STATUS;
return S_OK;
return S_OK;
}
///////////////////////////////////////////////////////////////////////////////////
@ -69,8 +69,7 @@ HRESULT debugEvent::LoadModule(
dbgModuleClass module(moduleName, moduleBase, moduleSize);
silentMode.reset();
PyThread_StateSave pyThrdState( dbgExt->getThreadState() );
PyThread_StateSave pyThreadSave;
return onLoadModule( module );
}
@ -91,8 +90,7 @@ HRESULT debugEvent::UnloadModule(
dbgModuleClass module(moduleName, moduleBase, moduleSize);
silentMode.reset();
PyThread_StateSave pyThrdState( dbgExt->getThreadState() );
PyThread_StateSave pyThreadSave;
return onUnloadModule( module );
}
@ -102,8 +100,7 @@ HRESULT debugEvent::SessionStatus(
__in ULONG Status
)
{
PyThread_StateSave pyThrdState( dbgExt->getThreadState() );
PyThread_StateSave pyThreadSave;
return onChangeSessionStatus( Status );
}
@ -114,8 +111,7 @@ HRESULT debugEvent::ChangeDebuggeeState(
__in ULONG64 Argument
)
{
PyThread_StateSave pyThrdState( dbgExt->getThreadState() );
PyThread_StateSave pyThreadSave;
return onChangeDebugeeState();
}

View File

@ -4,15 +4,16 @@
#include "dbgeventcb.h"
#include "dbgmodule.h"
#include "pyaux.h"
/////////////////////////////////////////////////////////////////////////////////
class debugEvent : public DebugBaseEventCallbacks
{
public:
debugEvent();
virtual ~debugEvent();
virtual ULONG onLoadModule(const dbgModuleClass &/* module */) = 0;
@ -30,8 +31,8 @@ private:
STDMETHOD(GetInterestMask)(
__out PULONG Mask
);
);
STDMETHOD(LoadModule)(
__in ULONG64 ImageFileHandle,
__in ULONG64 BaseOffset,
@ -46,18 +47,18 @@ private:
__in PCSTR ImageBaseName,
__in ULONG64 BaseOffset
);
STDMETHOD(SessionStatus)(
__in ULONG Status
);
STDMETHOD(ChangeDebuggeeState)(
__in ULONG Flags,
__in ULONG64 Argument );
private:
IDebugClient *m_debugClient;
IDebugClient *m_debugClient;
};
/////////////////////////////////////////////////////////////////////////////////
@ -65,9 +66,9 @@ private:
class debugEventWrap : public boost::python::wrapper<debugEvent>, public debugEvent
{
public:
public:
ULONG onLoadModule(const dbgModuleClass &module) {
return handler<const dbgModuleClass &>("onLoadModule", module );
}
@ -75,33 +76,33 @@ public:
ULONG onUnloadModule(const dbgModuleClass &module) {
return handler<const dbgModuleClass &>("onUnloadModule", module );
}
ULONG onChangeSessionStatus( ULONG status ) {
return handler( "onChangeSessionStatus", status );
}
}
ULONG onChangeDebugeeState() {
return handler( "onChangeDebugeeState" );
}
private:
return handler( "onChangeDebugeeState" );
}
private:
template<typename Arg1Type>
ULONG handler( const char* handlerName, Arg1Type arg1 )
{
if (boost::python::override pythonHandler = get_override( handlerName ))
if (boost::python::override pythonHandler = get_override( handlerName ))
return pythonHandler(arg1);
return DEBUG_STATUS_NO_CHANGE;
}
}
ULONG handler( const char* handlerName )
{
if (boost::python::override pythonHandler = get_override( handlerName ))
if (boost::python::override pythonHandler = get_override( handlerName ))
return pythonHandler();
return DEBUG_STATUS_NO_CHANGE;
}
}
};
/////////////////////////////////////////////////////////////////////////////////

View File

@ -38,6 +38,9 @@ DbgExt *dbgExt = NULL;
// ãëîáàëüíûé êëèåíò
dbgClient g_dbgClient;
// êîíòåñêò èñïîëíåíèÿ íèòè ïèòîíà
__declspec( thread ) PyThreadStatePtr ptrPyThreadState = NULL;
//////////////////////////////////////////////////////////////////////////////
BOOST_PYTHON_FUNCTION_OVERLOADS( dprint, dbgPrint::dprint, 1, 2 )
@ -340,7 +343,9 @@ BOOST_PYTHON_MODULE( pykd )
boost::python::class_<dbgBreakpointClass>( "bp",
"Class representing breakpoint",
boost::python::init<ULONG64,boost::python::object&>( boost::python::args("offset", "callback"),
"dbgBreakpointClass constructor" ) )
"Break point: user callback" ) )
.def( boost::python::init< ULONG64 >( boost::python::args("offset"),
"Break point constructor: always break" ) )
.def( "set", &dbgBreakpointClass::set,
"Set a breakpoint at the specified address" )
.def( "remove", &dbgBreakpointClass::remove,
@ -703,7 +708,6 @@ DebugExtensionUninitialize()
}
DbgExt::DbgExt( IDebugClient4 *masterClient )
: m_threadState(NULL)
{
client = NULL;
masterClient->QueryInterface( __uuidof(IDebugClient), (void **)&client );
@ -753,21 +757,24 @@ DbgExt::DbgExt( IDebugClient4 *masterClient )
DbgExt::~DbgExt()
{
BOOST_ASSERT(dbgExt == this);
dbgExt = m_previosExt;
if ( client )
client->Release();
if ( client4 )
client4->Release();
if ( client5 )
client5->Release();
if ( control )
control->Release();
if ( control4 )
control4->Release();
if ( registers )
registers->Release();
@ -776,26 +783,24 @@ DbgExt::~DbgExt()
if ( symbols2 )
symbols2->Release();
if ( symbols3 )
symbols3->Release();
if ( dataSpaces )
dataSpaces->Release();
if ( dataSpaces4 )
dataSpaces4->Release();
if ( advanced2 )
advanced2->Release();
if ( system )
system->Release();
if ( system2 )
system2->Release();
dbgExt = m_previosExt;
}
/////////////////////////////////////////////////////////////////////////////////

View File

@ -32,16 +32,9 @@ public:
~DbgExt();
PyThreadState**
getThreadState() {
return &m_threadState;
}
private:
private:
DbgExt *m_previosExt;
PyThreadState *m_threadState;
};
extern DbgExt *dbgExt;

View File

@ -2,6 +2,9 @@
///////////////////////////////////////////////////////////////////////////////
typedef PyThreadState *PyThreadStatePtr;
extern __declspec( thread ) PyThreadStatePtr ptrPyThreadState;
// --> call back
// { PyThread_StateSave state( winext->getThreadState() );
// do_callback();
@ -15,58 +18,40 @@ class PyThread_StateSave {
public:
PyThread_StateSave( PyThreadState **state )
: m_state(NULL)
PyThread_StateSave()
: m_bRestored(false)
{
if ( *state )
if (ptrPyThreadState)
{
m_state = state;
PyEval_RestoreThread( *m_state );
PyEval_RestoreThread( ptrPyThreadState );
m_bRestored = true;
}
}
~PyThread_StateSave() {
if ( m_state )
*m_state =PyEval_SaveThread();
if ( m_bRestored )
ptrPyThreadState = PyEval_SaveThread();
}
private:
PyThreadState **m_state;
bool m_bRestored;
};
// { PyThread_StateRestore state;
// long_or_block_opreration();
// }
class PyThread_StateRestore {
class PyThread_StateRestore
{
public:
explicit PyThread_StateRestore() {
m_state = &m_ownState;
*m_state =PyEval_SaveThread();
}
PyThread_StateRestore( PyThreadState **state ) {
if ( *state )
{
m_state = state;
*m_state =PyEval_SaveThread();
}
PyThread_StateRestore() {
ptrPyThreadState = PyEval_SaveThread();
}
~PyThread_StateRestore() {
if (*m_state)
PyEval_RestoreThread( *m_state );
PyEval_RestoreThread( ptrPyThreadState );
}
private:
PyThreadState **m_state;
PyThreadState *m_ownState;
};
///////////////////////////////////////////////////////////////////////////////

34
samples/goLib.py Normal file
View File

@ -0,0 +1,34 @@
"""
Using bp class without callback
"""
from pykd import *
if __name__ == "__main__":
if not isKernelDebugging():
if not isWindbgExt():
startProcess("calc.exe")
kernel32 = loadModule("kernel32")
bpA = bp( kernel32.LoadLibraryA )
bpW = bp( kernel32.LoadLibraryW )
go()
dbgCommand("gu")
dprintln( dbgCommand("!dlls @$retreg") )
else:
dprintln("Script for user mode only")