mirror of
https://github.com/ivellioscolin/pykd.git
synced 2025-04-21 12:53:23 +08:00
[0.2.x] added : EventHandler class and breakpoints callback
git-svn-id: https://pykd.svn.codeplex.com/svn@79970 9b283d60-5439-405e-af05-b73fd8c4d996
This commit is contained in:
parent
4adda326f5
commit
642bb01c57
@ -5,25 +5,64 @@
|
|||||||
#include "stdafx.h"
|
#include "stdafx.h"
|
||||||
#include "bpoint.h"
|
#include "bpoint.h"
|
||||||
#include "dbgengine.h"
|
#include "dbgengine.h"
|
||||||
|
#include "eventhandler.h"
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
namespace pykd {
|
namespace pykd {
|
||||||
|
|
||||||
ULONG setSoftwareBp(ULONG64 offset, BpCallback &callback /*= BpCallback()*/)
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
ULONG setSoftwareBp(ULONG64 offset, python::object &callback/* = python::object() */)
|
||||||
{
|
{
|
||||||
offset = addr64( offset );
|
offset = addr64( offset );
|
||||||
|
|
||||||
return breakPointSet( offset );
|
ULONG id = breakPointSet( offset );
|
||||||
|
|
||||||
|
python::object main = boost::python::import("__main__");
|
||||||
|
python::dict main_namespace( main.attr("__dict__") );
|
||||||
|
EventHandlerPtr eventHandler = python::extract<EventHandlerPtr>( main_namespace["globalEventHandler"] );
|
||||||
|
EventHandlerImpl* handler = dynamic_cast<EventHandlerImpl*>( boost::get_pointer( eventHandler ) );
|
||||||
|
handler->addBpCallback( id, callback );
|
||||||
|
|
||||||
|
return id;
|
||||||
}
|
}
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
ULONG setHardwareBp(ULONG64 offset, ULONG size, ULONG accessType, BpCallback &callback /*= BpCallback()*/ )
|
ULONG setHardwareBp(ULONG64 offset, ULONG size, ULONG accessType, python::object &callback/* = python::object() */ )
|
||||||
{
|
{
|
||||||
offset = addr64( offset );
|
offset = addr64( offset );
|
||||||
|
|
||||||
return breakPointSet( offset, true, size, accessType );
|
ULONG id = breakPointSet( offset, true, size, accessType );
|
||||||
|
|
||||||
|
python::object main = boost::python::import("__main__");
|
||||||
|
python::dict main_namespace( main.attr("__dict__") );
|
||||||
|
EventHandlerPtr eventHandler = python::extract<EventHandlerPtr>( main_namespace["globalEventHandler"] );
|
||||||
|
EventHandlerImpl* handler = dynamic_cast<EventHandlerImpl*>( boost::get_pointer( eventHandler ) );
|
||||||
|
handler->addBpCallback( id, callback );
|
||||||
|
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
void removeBp( ULONG id )
|
||||||
|
{
|
||||||
|
breakPointRemove( id );
|
||||||
|
|
||||||
|
python::object main = boost::python::import("__main__");
|
||||||
|
python::dict main_namespace( main.attr("__dict__") );
|
||||||
|
EventHandlerPtr eventHandler = python::extract<EventHandlerPtr>( main_namespace["globalEventHandler"] );
|
||||||
|
EventHandlerImpl* handler = dynamic_cast<EventHandlerImpl*>( boost::get_pointer( eventHandler ) );
|
||||||
|
handler->removeBpCallback( id );
|
||||||
|
}
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
void removeAllBp()
|
||||||
|
{
|
||||||
|
// breakPointRemoveAll();
|
||||||
}
|
}
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
@ -6,47 +6,20 @@
|
|||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
#include "pyaux.h"
|
||||||
|
|
||||||
namespace pykd {
|
namespace pykd {
|
||||||
|
|
||||||
typedef python::object BpCallback;
|
ULONG setSoftwareBp(ULONG64 offset, python::object &callback = python::object() );
|
||||||
|
|
||||||
ULONG setSoftwareBp(ULONG64 offset, BpCallback &callback = BpCallback() );
|
ULONG setHardwareBp(ULONG64 offset, ULONG size, ULONG accessType, python::object &callback = python::object() );
|
||||||
|
|
||||||
ULONG setHardwareBp(ULONG64 offset, ULONG size, ULONG accessType, BpCallback &callback = BpCallback());
|
void removeBp( ULONG id );
|
||||||
|
|
||||||
|
void removeAllBp();
|
||||||
|
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
//////////////////////////////////////////////////////////////////////////////////
|
|
||||||
//
|
|
||||||
//inline BPOINT_ID setSoftwareBp(ULONG64 addr, BpCallback &callback = BpCallback()) {
|
|
||||||
// return g_dbgClient->setSoftwareBp(addr, callback);
|
|
||||||
//}
|
|
||||||
//
|
|
||||||
//////////////////////////////////////////////////////////////////////////////////
|
|
||||||
//
|
|
||||||
//inline BPOINT_ID setHardwareBp(ULONG64 addr, ULONG size, ULONG accessType, BpCallback &callback = BpCallback()) {
|
|
||||||
// return g_dbgClient->setHardwareBp(addr, size, accessType, callback);
|
|
||||||
//}
|
|
||||||
//
|
|
||||||
//////////////////////////////////////////////////////////////////////////////////
|
|
||||||
//
|
|
||||||
//inline python::list getAllBp() {
|
|
||||||
// return g_dbgClient->getAllBp();
|
|
||||||
//}
|
|
||||||
//
|
|
||||||
//////////////////////////////////////////////////////////////////////////////////
|
|
||||||
//
|
|
||||||
//inline void removeBp(BPOINT_ID Id) {
|
|
||||||
// return g_dbgClient->removeBp(Id);
|
|
||||||
//}
|
|
||||||
//
|
|
||||||
//////////////////////////////////////////////////////////////////////////////////
|
|
||||||
//
|
|
||||||
//inline void removeAllBp() {
|
|
||||||
// return g_dbgClient->removeAllBp();
|
|
||||||
//}
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
} // end pykd namespace
|
} // end pykd namespace
|
||||||
|
|
||||||
|
@ -66,9 +66,10 @@ void getStackTrace(std::vector<STACK_FRAME_DESC> &frames);
|
|||||||
#define DEBUG_CALLBACK_METHODTYPE __cdecl
|
#define DEBUG_CALLBACK_METHODTYPE __cdecl
|
||||||
|
|
||||||
enum DEBUG_CALLBACK_RESULT {
|
enum DEBUG_CALLBACK_RESULT {
|
||||||
DebugCallbackBreak,
|
DebugCallbackProceed = 0,
|
||||||
DebugCallbackProceed,
|
DebugCallbackNoChange = 1,
|
||||||
DebugCallbackNoChange
|
DebugCallbackBreak = 2,
|
||||||
|
DebugCallbackMax = 3
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -78,7 +79,7 @@ struct DEBUG_EVENT_CALLBACK {
|
|||||||
};
|
};
|
||||||
|
|
||||||
void eventRegisterCallbacks( const DEBUG_EVENT_CALLBACK *callbacks );
|
void eventRegisterCallbacks( const DEBUG_EVENT_CALLBACK *callbacks );
|
||||||
void eventRemoveCallbacks();
|
void eventRemoveCallbacks( const DEBUG_EVENT_CALLBACK *callbacks );
|
||||||
|
|
||||||
//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 );
|
||||||
|
@ -28,9 +28,11 @@ WindbgGlobalSession::WindbgGlobalSession()
|
|||||||
|
|
||||||
python::object main_namespace = main.attr("__dict__");
|
python::object main_namespace = main.attr("__dict__");
|
||||||
|
|
||||||
// äåëàåì àíàëîã from pykd import *
|
|
||||||
python::object pykd = boost::python::import( "pykd" );
|
python::object pykd = boost::python::import( "pykd" );
|
||||||
|
|
||||||
|
main_namespace["globalEventHandler"] = EventHandlerPtr( new EventHandlerImpl() );
|
||||||
|
|
||||||
|
// äåëàåì àíàëîã from pykd import *
|
||||||
python::dict pykd_namespace( pykd.attr("__dict__") );
|
python::dict pykd_namespace( pykd.attr("__dict__") );
|
||||||
|
|
||||||
python::list iterkeys( pykd_namespace.iterkeys() );
|
python::list iterkeys( pykd_namespace.iterkeys() );
|
||||||
@ -42,6 +44,13 @@ WindbgGlobalSession::WindbgGlobalSession()
|
|||||||
main_namespace[ key ] = pykd_namespace[ key ];
|
main_namespace[ key ] = pykd_namespace[ key ];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ïåðåíàïðàâëåíèå ñòàíäàðòíûõ ïîòîêîâ ÂÂ
|
||||||
|
python::object sys = python::import("sys");
|
||||||
|
|
||||||
|
sys.attr("stdout") = python::object( DbgOut() );
|
||||||
|
sys.attr("stderr") = python::object( DbgErr() );
|
||||||
|
sys.attr("stdin") = python::object( DbgIn() );
|
||||||
|
|
||||||
pyState = PyEval_SaveThread();
|
pyState = PyEval_SaveThread();
|
||||||
}
|
}
|
||||||
volatile LONG WindbgGlobalSession::sessionCount = 0;
|
volatile LONG WindbgGlobalSession::sessionCount = 0;
|
||||||
@ -100,7 +109,6 @@ HRESULT
|
|||||||
CALLBACK
|
CALLBACK
|
||||||
py( PDEBUG_CLIENT4 client, PCSTR args )
|
py( PDEBUG_CLIENT4 client, PCSTR args )
|
||||||
{
|
{
|
||||||
|
|
||||||
WindbgGlobalSession::RestorePyState();
|
WindbgGlobalSession::RestorePyState();
|
||||||
|
|
||||||
PyThreadState *globalInterpreter = PyThreadState_Swap( NULL );
|
PyThreadState *globalInterpreter = PyThreadState_Swap( NULL );
|
||||||
@ -121,6 +129,10 @@ py( PDEBUG_CLIENT4 client, PCSTR args )
|
|||||||
sys.attr("stderr") = python::object( DbgErr() );
|
sys.attr("stderr") = python::object( DbgErr() );
|
||||||
sys.attr("stdin") = python::object( DbgIn() );
|
sys.attr("stdin") = python::object( DbgIn() );
|
||||||
|
|
||||||
|
python::object pykd = python::import( "pykd" );
|
||||||
|
|
||||||
|
global["globalEventHandler"] = EventHandlerPtr( new EventHandlerImpl() );
|
||||||
|
|
||||||
// èìïîðòèðóåì ìîäóëü îáðàáîòêè èñêëþ÷åíèé ( íóæåí äëÿ âûâîäà traceback à )
|
// èìïîðòèðóåì ìîäóëü îáðàáîòêè èñêëþ÷åíèé ( íóæåí äëÿ âûâîäà traceback à )
|
||||||
python::object tracebackModule = python::import("traceback");
|
python::object tracebackModule = python::import("traceback");
|
||||||
|
|
||||||
@ -190,7 +202,6 @@ py( PDEBUG_CLIENT4 client, PCSTR args )
|
|||||||
|
|
||||||
eprintln( sstr.str() );
|
eprintln( sstr.str() );
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
catch(...)
|
catch(...)
|
||||||
{
|
{
|
||||||
@ -219,13 +230,6 @@ pycmd( PDEBUG_CLIENT4 client, PCSTR args )
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
|
|
||||||
// ïåðåíàïðàâëåíèå ñòàíäàðòíûõ ïîòîêîâ ÂÂ
|
|
||||||
python::object sys = python::import("sys");
|
|
||||||
|
|
||||||
sys.attr("stdout") = python::object( DbgOut() );
|
|
||||||
sys.attr("stderr") = python::object( DbgErr() );
|
|
||||||
sys.attr("stdin") = python::object( DbgIn() );
|
|
||||||
|
|
||||||
PyRun_String(
|
PyRun_String(
|
||||||
"__import__('code').InteractiveConsole(__import__('__main__').__dict__).interact()",
|
"__import__('code').InteractiveConsole(__import__('__main__').__dict__).interact()",
|
||||||
Py_file_input,
|
Py_file_input,
|
||||||
|
@ -16,10 +16,42 @@ EventHandler::EventHandler()
|
|||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
|
||||||
EventHandler::~EventHandler()
|
EventHandler::~EventHandler()
|
||||||
{
|
{
|
||||||
eventRemoveCallbacks();
|
eventRemoveCallbacks( this );
|
||||||
|
}
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
DEBUG_CALLBACK_RESULT DEBUG_CALLBACK_METHODTYPE EventHandlerImpl::OnBreakpoint( ULONG bpId )
|
||||||
|
{
|
||||||
|
BpMap::iterator foundIt = m_bpMap.find( bpId );
|
||||||
|
if ( foundIt == m_bpMap.end() )
|
||||||
|
return DebugCallbackNoChange;
|
||||||
|
|
||||||
|
python::object bpcallback = foundIt->second;
|
||||||
|
|
||||||
|
if ( bpcallback.is_none() )
|
||||||
|
return DebugCallbackBreak;
|
||||||
|
|
||||||
|
try {
|
||||||
|
|
||||||
|
python::object resObj = bpcallback( bpId );
|
||||||
|
|
||||||
|
if ( resObj.is_none() )
|
||||||
|
return DebugCallbackProceed;
|
||||||
|
|
||||||
|
ULONG retVal = python::extract<ULONG>( resObj );
|
||||||
|
|
||||||
|
if ( retVal >= DebugCallbackMax )
|
||||||
|
return DebugCallbackBreak;
|
||||||
|
|
||||||
|
return DEBUG_CALLBACK_RESULT(retVal);
|
||||||
|
}
|
||||||
|
catch (const python::error_already_set &) {
|
||||||
|
}
|
||||||
|
|
||||||
|
return DebugCallbackBreak;
|
||||||
}
|
}
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
@ -46,158 +78,4 @@ EventHandler::~EventHandler()
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
|
||||||
//
|
|
||||||
//InternalDbgEventHandler::InternalDbgEventHandler(
|
|
||||||
// IDebugClient4 *client,
|
|
||||||
// DebugClient *parentClient,
|
|
||||||
// SynSymbolsPtr synSymbols,
|
|
||||||
// BpCallbackMap &bpCallbacks
|
|
||||||
//) : m_parentClient(parentClient)
|
|
||||||
// , m_synSymbols(synSymbols)
|
|
||||||
// , m_bpCallbacks(bpCallbacks)
|
|
||||||
//{
|
|
||||||
// HRESULT hres = client->CreateClient(&m_client);
|
|
||||||
// if (FAILED(hres))
|
|
||||||
// throw DbgException("Call IDebugClient::CreateClient failed");
|
|
||||||
//
|
|
||||||
// hres = m_client->QueryInterface(__uuidof(IDebugControl), (void**)&m_control);
|
|
||||||
// if ( FAILED( hres ) )
|
|
||||||
// throw DbgException("QueryInterface IDebugControl failed");
|
|
||||||
//
|
|
||||||
// m_client->SetEventCallbacks(this);
|
|
||||||
//}
|
|
||||||
//
|
|
||||||
//////////////////////////////////////////////////////////////////////////////////
|
|
||||||
//
|
|
||||||
//InternalDbgEventHandler::~InternalDbgEventHandler()
|
|
||||||
//{
|
|
||||||
// m_control->Release();
|
|
||||||
// m_client->Release();
|
|
||||||
//}
|
|
||||||
//
|
|
||||||
//////////////////////////////////////////////////////////////////////////////////
|
|
||||||
//
|
|
||||||
//HRESULT InternalDbgEventHandler::GetInterestMask(
|
|
||||||
// __out PULONG Mask
|
|
||||||
//)
|
|
||||||
//{
|
|
||||||
// *Mask =
|
|
||||||
// DEBUG_EVENT_BREAKPOINT |
|
|
||||||
// DEBUG_EVENT_CHANGE_ENGINE_STATE |
|
|
||||||
// DEBUG_EVENT_CHANGE_SYMBOL_STATE;
|
|
||||||
//
|
|
||||||
// return S_OK;
|
|
||||||
//}
|
|
||||||
//
|
|
||||||
/////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
//
|
|
||||||
//HRESULT InternalDbgEventHandler::ChangeSymbolState(
|
|
||||||
// __in ULONG Flags,
|
|
||||||
// __in ULONG64 Argument
|
|
||||||
//)
|
|
||||||
//{
|
|
||||||
// HRESULT hres = S_OK;
|
|
||||||
//
|
|
||||||
// if (DEBUG_CSS_LOADS & Flags)
|
|
||||||
// hres = symLoaded(Argument);
|
|
||||||
//
|
|
||||||
// return hres;
|
|
||||||
//}
|
|
||||||
//
|
|
||||||
/////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
//
|
|
||||||
//HRESULT InternalDbgEventHandler::ChangeEngineState(
|
|
||||||
// __in ULONG Flags,
|
|
||||||
// __in ULONG64 Argument
|
|
||||||
//)
|
|
||||||
//{
|
|
||||||
// HRESULT hres = S_OK;
|
|
||||||
//
|
|
||||||
// if (DEBUG_CES_BREAKPOINTS & Flags)
|
|
||||||
// hres = bpChanged(static_cast<BPOINT_ID>(Argument));
|
|
||||||
//
|
|
||||||
// return hres;
|
|
||||||
//}
|
|
||||||
//
|
|
||||||
/////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
//
|
|
||||||
//HRESULT InternalDbgEventHandler::Breakpoint(IDebugBreakpoint *bp)
|
|
||||||
//{
|
|
||||||
// BPOINT_ID Id;
|
|
||||||
// HRESULT hres = bp->GetId(&Id);
|
|
||||||
// if (S_OK == hres)
|
|
||||||
// {
|
|
||||||
// boost::recursive_mutex::scoped_lock mapBpLock(*m_bpCallbacks.m_lock);
|
|
||||||
// BpCallbackMapIml::iterator it = m_bpCallbacks.m_map.find(Id);
|
|
||||||
// if (it != m_bpCallbacks.m_map.end())
|
|
||||||
// {
|
|
||||||
// PyThread_StateSave pyThreadSave( m_parentClient->getThreadState() );
|
|
||||||
//
|
|
||||||
// try {
|
|
||||||
//
|
|
||||||
// python::object resObj = it->second(Id);
|
|
||||||
//
|
|
||||||
// if (resObj.is_none())
|
|
||||||
// return DEBUG_STATUS_NO_CHANGE;
|
|
||||||
//
|
|
||||||
// python::extract<HRESULT> getRetCode( resObj );
|
|
||||||
// if (getRetCode.check())
|
|
||||||
// return getRetCode();
|
|
||||||
// }
|
|
||||||
// catch (const python::error_already_set &) {
|
|
||||||
// // TODO: some logging, alerting...
|
|
||||||
// return DEBUG_STATUS_BREAK;
|
|
||||||
// }
|
|
||||||
// // TODO: python code return invalid value
|
|
||||||
// // some logging, alerting...
|
|
||||||
// return DEBUG_STATUS_BREAK;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// return DEBUG_STATUS_NO_CHANGE;
|
|
||||||
//}
|
|
||||||
//
|
|
||||||
/////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
//
|
|
||||||
//HRESULT InternalDbgEventHandler::symLoaded(
|
|
||||||
// __in ULONG64 ModuleAddress
|
|
||||||
//)
|
|
||||||
//{
|
|
||||||
// if (!ModuleAddress)
|
|
||||||
// {
|
|
||||||
// // f.e. is case ".reload /f image.exe", if for image.exe no symbols
|
|
||||||
// m_synSymbols->restoreAll();
|
|
||||||
// return S_OK;
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// m_synSymbols->restoreForModule(ModuleAddress);
|
|
||||||
// return S_OK;
|
|
||||||
//}
|
|
||||||
//
|
|
||||||
//////////////////////////////////////////////////////////////////////////////////
|
|
||||||
//
|
|
||||||
//HRESULT InternalDbgEventHandler::bpChanged(BPOINT_ID Id)
|
|
||||||
//{
|
|
||||||
// if (DEBUG_ANY_ID == Id)
|
|
||||||
// return S_OK;
|
|
||||||
//
|
|
||||||
// IDebugBreakpoint *bp;
|
|
||||||
// HRESULT hres = m_control->GetBreakpointById(Id, &bp);
|
|
||||||
// if (E_NOINTERFACE == hres)
|
|
||||||
// {
|
|
||||||
// // breakpoint was removed
|
|
||||||
// boost::recursive_mutex::scoped_lock mapBpLock(*m_bpCallbacks.m_lock);
|
|
||||||
// m_bpCallbacks.m_map.erase(Id);
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// return S_OK;
|
|
||||||
//}
|
|
||||||
//
|
|
||||||
//////////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
|
@ -5,6 +5,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "dbgengine.h"
|
#include "dbgengine.h"
|
||||||
|
#include "bpoint.h"
|
||||||
|
|
||||||
namespace pykd {
|
namespace pykd {
|
||||||
|
|
||||||
@ -20,12 +21,93 @@ public:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
virtual DEBUG_CALLBACK_RESULT DEBUG_CALLBACK_METHODTYPE OnBreakpoint( ULONG bpId ) {
|
virtual DEBUG_CALLBACK_RESULT DEBUG_CALLBACK_METHODTYPE OnBreakpoint( ULONG bpId ) = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
|
||||||
|
class EventHandlerWrap : public python::wrapper<EventHandler>, public EventHandler
|
||||||
|
{
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
virtual DEBUG_CALLBACK_RESULT DEBUG_CALLBACK_METHODTYPE OnBreakpoint( ULONG Id ) {
|
||||||
|
return handler("onBreakpoint", Id);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
template<typename Arg1Type>
|
||||||
|
DEBUG_CALLBACK_RESULT handler( const char* handlerName, Arg1Type arg1 )
|
||||||
|
{
|
||||||
|
if (python::override pythonHandler = get_override( handlerName ))
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
return pythonHandler(arg1);
|
||||||
|
}
|
||||||
|
catch (const python::error_already_set &) {
|
||||||
|
//onHandlerException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return DebugCallbackNoChange;
|
||||||
|
}
|
||||||
|
|
||||||
|
DEBUG_CALLBACK_RESULT handler( const char* handlerName )
|
||||||
|
{
|
||||||
|
if (python::override pythonHandler = get_override( handlerName ))
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
return pythonHandler();
|
||||||
|
}
|
||||||
|
catch (const python::error_already_set &) {
|
||||||
|
//onHandlerException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return DebugCallbackNoChange;
|
return DebugCallbackNoChange;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
extern EventHandler *g_eventHandler;
|
typedef boost::shared_ptr<EventHandlerWrap> EventHandlerPtr;
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
class EventHandlerImpl : public EventHandlerWrap
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
void addBpCallback( ULONG id, python::object &callback )
|
||||||
|
{
|
||||||
|
m_bpMap.insert( std::make_pair( id, callback ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
void removeBpCallback( ULONG id )
|
||||||
|
{
|
||||||
|
BpMap::iterator foundIt = m_bpMap.find( id );
|
||||||
|
if ( foundIt != m_bpMap.end() )
|
||||||
|
m_bpMap.erase( foundIt );
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual ~EventHandlerImpl()
|
||||||
|
{
|
||||||
|
while( !m_bpMap.empty() )
|
||||||
|
{
|
||||||
|
BpMap::iterator it = m_bpMap.begin();
|
||||||
|
breakPointRemove( it->first );
|
||||||
|
m_bpMap.erase( it );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
virtual DEBUG_CALLBACK_RESULT DEBUG_CALLBACK_METHODTYPE OnBreakpoint( ULONG bpId );
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
typedef std::map<ULONG, python::object> BpMap;
|
||||||
|
|
||||||
|
BpMap m_bpMap;
|
||||||
|
};
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
22
pykd/pyaux.h
22
pykd/pyaux.h
@ -12,37 +12,27 @@ class PyThreadStateSaver {
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
PyThreadStateSaver() {
|
PyThreadStateSaver( PyThreadState* s = NULL) {
|
||||||
m_index = TlsAlloc();
|
|
||||||
|
state = s;
|
||||||
}
|
}
|
||||||
|
|
||||||
~PyThreadStateSaver() {
|
~PyThreadStateSaver() {
|
||||||
TlsFree( m_index );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void saveState() {
|
void saveState() {
|
||||||
//if ( !WindbgGlobalSession::isInit() )
|
state = PyEval_SaveThread();
|
||||||
TlsSetValue( m_index, PyEval_SaveThread() );
|
|
||||||
//else
|
|
||||||
// WindbgGlobalSession::SavePyState();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void restoreState() {
|
void restoreState() {
|
||||||
//if ( !WindbgGlobalSession::isInit() )
|
|
||||||
//{
|
|
||||||
PyThreadState* state = (PyThreadState*)TlsGetValue( m_index );
|
|
||||||
if ( state )
|
if ( state )
|
||||||
PyEval_RestoreThread( state );
|
PyEval_RestoreThread( state );
|
||||||
//}
|
|
||||||
//else
|
|
||||||
//{
|
|
||||||
// WindbgGlobalSession::RestorePyState();
|
|
||||||
//}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
DWORD m_index;
|
//DWORD m_index;
|
||||||
|
PyThreadState* state;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -117,7 +117,8 @@ BOOST_PYTHON_MODULE( pykd )
|
|||||||
"Get the page size for the currently executing processor context" );
|
"Get the page size for the currently executing processor context" );
|
||||||
|
|
||||||
// Manage target memory access
|
// Manage target memory access
|
||||||
|
python::def( "addr64", &addr64,
|
||||||
|
"Extend address to 64 bits formats" );
|
||||||
python::def( "isValid", &isVaValid,
|
python::def( "isValid", &isVaValid,
|
||||||
"Check if the virtual address is valid" );
|
"Check if the virtual address is valid" );
|
||||||
python::def( "compareMemory", &compareMemory, compareMemory_( python::args( "offset1", "offset2", "length", "phyAddr" ),
|
python::def( "compareMemory", &compareMemory, compareMemory_( python::args( "offset1", "offset2", "length", "phyAddr" ),
|
||||||
@ -229,9 +230,9 @@ BOOST_PYTHON_MODULE( pykd )
|
|||||||
"Set software breakpoint on executiont" ) );
|
"Set software breakpoint on executiont" ) );
|
||||||
python::def( "setBp", &setHardwareBp, setHardwareBp_( python::args( "offset", "size", "accsessType", "callback" ) ,
|
python::def( "setBp", &setHardwareBp, setHardwareBp_( python::args( "offset", "size", "accsessType", "callback" ) ,
|
||||||
"Set hardware breakpoint" ) );
|
"Set hardware breakpoint" ) );
|
||||||
python::def( "removeBp", &breakPointRemove,
|
python::def( "removeBp", &removeBp,
|
||||||
"Remove breapoint by IDs" );
|
"Remove breapoint by IDs" );
|
||||||
python::def( "removeAllBp", &breakPointRemoveAll,
|
python::def( "removeAllBp", &removeAllBp,
|
||||||
"Remove all breapoints" );
|
"Remove all breapoints" );
|
||||||
|
|
||||||
// custom types
|
// custom types
|
||||||
@ -439,6 +440,12 @@ BOOST_PYTHON_MODULE( pykd )
|
|||||||
.def( "ea", &Disasm::ea, "Return effective address for last disassembled instruction or 0" )
|
.def( "ea", &Disasm::ea, "Return effective address for last disassembled instruction or 0" )
|
||||||
.def( "reset", &Disasm::reset, "Reset current offset to begin" );
|
.def( "reset", &Disasm::reset, "Reset current offset to begin" );
|
||||||
|
|
||||||
|
python::class_<EventHandlerWrap, EventHandlerPtr, boost::noncopyable>(
|
||||||
|
"eventHandler", "Base class for overriding and handling debug notifications", python::no_init )
|
||||||
|
.def( "onBreakpoint", &EventHandlerWrap::OnBreakpoint,
|
||||||
|
"Triggered breakpoint event. Parameter is int: ID of breakpoint\n"
|
||||||
|
"For ignore event method must return DEBUG_STATUS_NO_CHANGE value" );
|
||||||
|
|
||||||
// wrapper for standart python exceptions
|
// wrapper for standart python exceptions
|
||||||
python::register_exception_translator<PyException>( &PyException::exceptionTranslate );
|
python::register_exception_translator<PyException>( &PyException::exceptionTranslate );
|
||||||
|
|
||||||
|
@ -60,3 +60,4 @@ namespace python = boost::python;
|
|||||||
#include <boost/regex.hpp>
|
#include <boost/regex.hpp>
|
||||||
#include <boost/variant.hpp>
|
#include <boost/variant.hpp>
|
||||||
#include <boost/tokenizer.hpp>
|
#include <boost/tokenizer.hpp>
|
||||||
|
#include <boost/thread/win32/recursive_mutex.hpp>
|
||||||
|
@ -244,7 +244,7 @@ void debugBreak()
|
|||||||
|
|
||||||
ULONG64 evaluate( const std::wstring &expression )
|
ULONG64 evaluate( const std::wstring &expression )
|
||||||
{
|
{
|
||||||
PyThreadState *pystate = PyEval_SaveThread();
|
PyThread_StateRestore pyThreadRestore( g_dbgEng->pystate );
|
||||||
|
|
||||||
HRESULT hres;
|
HRESULT hres;
|
||||||
ULONG64 value = 0;
|
ULONG64 value = 0;
|
||||||
@ -829,6 +829,8 @@ void breakPointRemove( ULONG id )
|
|||||||
|
|
||||||
void breakPointRemoveAll()
|
void breakPointRemoveAll()
|
||||||
{
|
{
|
||||||
|
PyThread_StateRestore pyThreadRestore( g_dbgEng->pystate );
|
||||||
|
|
||||||
ULONG numberOfBps;
|
ULONG numberOfBps;
|
||||||
do {
|
do {
|
||||||
HRESULT hres = g_dbgEng->control->GetNumberBreakpoints(&numberOfBps);
|
HRESULT hres = g_dbgEng->control->GetNumberBreakpoints(&numberOfBps);
|
||||||
@ -860,20 +862,32 @@ void eventRegisterCallbacks( const DEBUG_EVENT_CALLBACK *callbacks )
|
|||||||
|
|
||||||
void DebugEngine::registerCallbacks( const DEBUG_EVENT_CALLBACK *callbacks )
|
void DebugEngine::registerCallbacks( const DEBUG_EVENT_CALLBACK *callbacks )
|
||||||
{
|
{
|
||||||
HRESULT hres;
|
boost::recursive_mutex::scoped_lock l(m_handlerLock);
|
||||||
|
|
||||||
m_eventCallbacks = callbacks;
|
m_handlers.push_back( DebugEventContext( callbacks, PyThreadStateSaver( PyThreadState_Get() ) ) );
|
||||||
|
|
||||||
hres = operator->()->client->SetEventCallbacks( &m_callbacks );
|
|
||||||
|
|
||||||
if ( S_OK != hres)
|
|
||||||
throw DbgException("IDebugClient::SetEventCallbacks", hres );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
void eventRemoveCallbacks()
|
void eventRemoveCallbacks( const DEBUG_EVENT_CALLBACK *callback )
|
||||||
{
|
{
|
||||||
|
g_dbgEng.removeCallbacks( callback );
|
||||||
|
}
|
||||||
|
|
||||||
|
void DebugEngine::removeCallbacks( const DEBUG_EVENT_CALLBACK *callback )
|
||||||
|
{
|
||||||
|
boost::recursive_mutex::scoped_lock l(m_handlerLock);
|
||||||
|
|
||||||
|
HandlerList::iterator it = m_handlers.begin();
|
||||||
|
|
||||||
|
for ( ; it != m_handlers.end(); ++it )
|
||||||
|
{
|
||||||
|
if ( it->callback == callback )
|
||||||
|
{
|
||||||
|
m_handlers.erase( it );
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
@ -899,22 +913,29 @@ ULONG ConvertCallbackResult( DEBUG_CALLBACK_RESULT result )
|
|||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
HRESULT STDMETHODCALLTYPE DebugEngine::DbgEventCallbacks::Breakpoint(
|
HRESULT STDMETHODCALLTYPE DebugEngine::Breakpoint(
|
||||||
__in IDebugBreakpoint *bp
|
__in IDebugBreakpoint *bp
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
DEBUG_EVENT_CALLBACK* eventCallback = const_cast<DEBUG_EVENT_CALLBACK*>( g_dbgEng.getCallbacks() );
|
HRESULT hres;
|
||||||
|
ULONG id;
|
||||||
ULONG id;
|
|
||||||
HRESULT hres;
|
|
||||||
|
|
||||||
hres = bp->GetId( &id );
|
hres = bp->GetId( &id );
|
||||||
|
if ( FAILED( hres ) )
|
||||||
|
return DEBUG_STATUS_NO_CHANGE;
|
||||||
|
|
||||||
if ( hres == S_OK )
|
boost::recursive_mutex::scoped_lock l(m_handlerLock);
|
||||||
|
|
||||||
|
HandlerList::iterator it = m_handlers.begin();
|
||||||
|
|
||||||
|
for ( ; it != m_handlers.end(); ++it )
|
||||||
{
|
{
|
||||||
DEBUG_CALLBACK_RESULT result = eventCallback->OnBreakpoint( id );
|
PyThread_StateSave pyThreadSave( it->pystate );
|
||||||
|
|
||||||
return ConvertCallbackResult( result );
|
DEBUG_CALLBACK_RESULT result = it->callback->OnBreakpoint( id );
|
||||||
|
|
||||||
|
if ( DebugCallbackNoChange != result )
|
||||||
|
return ConvertCallbackResult( result );
|
||||||
}
|
}
|
||||||
|
|
||||||
return DEBUG_STATUS_NO_CHANGE;
|
return DEBUG_STATUS_NO_CHANGE;
|
||||||
@ -922,7 +943,6 @@ HRESULT STDMETHODCALLTYPE DebugEngine::DbgEventCallbacks::Breakpoint(
|
|||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
|
||||||
} // end pykd namespace
|
} // end pykd namespace
|
||||||
|
|
||||||
|
|
||||||
|
@ -12,8 +12,8 @@ namespace pykd {
|
|||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
class DebugEngine {
|
class DebugEngine : private DebugBaseEventCallbacks
|
||||||
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
struct DbgEngBind {
|
struct DbgEngBind {
|
||||||
@ -26,39 +26,38 @@ public:
|
|||||||
CComQIPtr<IDebugAdvanced2> advanced;
|
CComQIPtr<IDebugAdvanced2> advanced;
|
||||||
CComQIPtr<IDebugRegisters2> registers;
|
CComQIPtr<IDebugRegisters2> registers;
|
||||||
|
|
||||||
DbgEngBind( PDEBUG_CLIENT4 c )
|
DbgEngBind( PDEBUG_CLIENT4 client_, PDEBUG_EVENT_CALLBACKS callback )
|
||||||
{
|
{
|
||||||
client = c;
|
client = client_;
|
||||||
control = c;
|
control = client_;
|
||||||
system = c;
|
system = client_;
|
||||||
symbols = c;
|
symbols = client_;
|
||||||
dataspace = c;
|
dataspace = client_;
|
||||||
advanced = c;
|
advanced = client_;
|
||||||
registers = c;
|
registers = client_;
|
||||||
|
|
||||||
|
client->SetEventCallbacks( callback );
|
||||||
}
|
}
|
||||||
|
|
||||||
PyThreadStateSaver pystate;
|
PyThreadStateSaver pystate;
|
||||||
};
|
};
|
||||||
|
|
||||||
class DbgEventCallbacks : public DebugBaseEventCallbacks
|
// IUnknown impls
|
||||||
|
STDMETHOD_(ULONG, AddRef)() { return 1; }
|
||||||
|
STDMETHOD_(ULONG, Release)() { return 1; }
|
||||||
|
|
||||||
|
// IDebugEventCallbacks impls
|
||||||
|
STDMETHOD(GetInterestMask)(
|
||||||
|
__out PULONG Mask
|
||||||
|
)
|
||||||
{
|
{
|
||||||
// IUnknown impls
|
*Mask = DEBUG_EVENT_BREAKPOINT;
|
||||||
STDMETHOD_(ULONG, AddRef)() { return 1; }
|
return S_OK;
|
||||||
STDMETHOD_(ULONG, Release)() { return 1; }
|
}
|
||||||
|
|
||||||
// IDebugEventCallbacks impls
|
STDMETHOD(Breakpoint)(
|
||||||
STDMETHOD(GetInterestMask)(
|
__in IDebugBreakpoint *bp
|
||||||
__out PULONG Mask
|
);
|
||||||
)
|
|
||||||
{
|
|
||||||
*Mask = DEBUG_EVENT_BREAKPOINT;
|
|
||||||
return S_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
STDMETHOD(Breakpoint)(
|
|
||||||
__in IDebugBreakpoint *bp
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
DbgEngBind*
|
DbgEngBind*
|
||||||
operator->()
|
operator->()
|
||||||
@ -72,36 +71,33 @@ public:
|
|||||||
if ( FAILED( hres ) )
|
if ( FAILED( hres ) )
|
||||||
throw DbgException("DebugCreate failed");
|
throw DbgException("DebugCreate failed");
|
||||||
|
|
||||||
m_bind.reset(new DbgEngBind(client) );
|
m_bind.reset(new DbgEngBind(client, this) );
|
||||||
|
|
||||||
return m_bind.get();
|
return m_bind.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
void registerCallbacks( const DEBUG_EVENT_CALLBACK *callbacks );
|
void registerCallbacks( const DEBUG_EVENT_CALLBACK *callbacks );
|
||||||
void removeCallbacks();
|
void removeCallbacks( const DEBUG_EVENT_CALLBACK *callbacks );
|
||||||
const DEBUG_EVENT_CALLBACK* getCallbacks() const {
|
|
||||||
return m_eventCallbacks;
|
|
||||||
}
|
|
||||||
|
|
||||||
DebugEngine() :
|
|
||||||
m_callbacks()
|
|
||||||
{
|
|
||||||
g_eventHandler = new EventHandler();
|
|
||||||
}
|
|
||||||
|
|
||||||
~DebugEngine()
|
|
||||||
{
|
|
||||||
delete g_eventHandler;
|
|
||||||
g_eventHandler = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
std::auto_ptr<DbgEngBind> m_bind;
|
std::auto_ptr<DbgEngBind> m_bind;
|
||||||
|
|
||||||
DbgEventCallbacks m_callbacks;
|
struct DebugEventContext
|
||||||
|
{
|
||||||
|
DEBUG_EVENT_CALLBACK* callback;
|
||||||
|
PyThreadStateSaver pystate;
|
||||||
|
|
||||||
const DEBUG_EVENT_CALLBACK *m_eventCallbacks;
|
DebugEventContext( const DEBUG_EVENT_CALLBACK* callback_, PyThreadStateSaver &pystate_ ) :
|
||||||
|
callback( const_cast<DEBUG_EVENT_CALLBACK*>(callback_) ),
|
||||||
|
pystate(pystate_)
|
||||||
|
{}
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef std::list<DebugEventContext> HandlerList;
|
||||||
|
|
||||||
|
boost::recursive_mutex m_handlerLock;
|
||||||
|
HandlerList m_handlers;
|
||||||
};
|
};
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////
|
||||||
|
@ -9,25 +9,25 @@ from pykd import *
|
|||||||
|
|
||||||
def iat( moduleName, mask = "*" ):
|
def iat( moduleName, mask = "*" ):
|
||||||
|
|
||||||
module = loadModule( moduleName )
|
mod = module( moduleName )
|
||||||
dprintln( "Module: " + moduleName + " base: %x" % module.begin() + " end: %x" % module.end() )
|
dprintln( "Module: " + moduleName + " base: %x" % mod.begin() + " end: %x" % mod.end() )
|
||||||
|
|
||||||
if isKernelDebugging():
|
if isKernelDebugging():
|
||||||
systemModule = loadModule( "nt" )
|
systemModule = module( "nt" )
|
||||||
else:
|
else:
|
||||||
systemModule = loadModule( "ntdll" )
|
systemModule = module( "ntdll" )
|
||||||
|
|
||||||
|
|
||||||
if is64bitSystem():
|
if is64bitSystem():
|
||||||
ntHeader = systemModule.typedVar( "_IMAGE_NT_HEADERS64", module.begin() + ptrDWord( module.begin() + 0x3c ) )
|
ntHeader = systemModule.typedVar( "_IMAGE_NT_HEADERS64", mod.begin() + ptrDWord( mod.begin() + 0x3c ) )
|
||||||
if ntHeader.OptionalHeader.Magic == 0x10b:
|
if ntHeader.OptionalHeader.Magic == 0x10b:
|
||||||
systemModule = loadModule( "ntdll32" )
|
systemModule = loadModule( "ntdll32" )
|
||||||
ntHeader = systemModule.typedVar( "_IMAGE_NT_HEADERS", module.begin() + ptrDWord( module.begin() + 0x3c ) )
|
ntHeader = systemModule.typedVar( "_IMAGE_NT_HEADERS", mod.begin() + ptrDWord( mod.begin() + 0x3c ) )
|
||||||
pSize = 4
|
pSize = 4
|
||||||
else:
|
else:
|
||||||
pSize = 8
|
pSize = 8
|
||||||
else:
|
else:
|
||||||
ntHeader = systemModule.typedVar( "_IMAGE_NT_HEADERS", module.begin() + ptrDWord( module.begin() + 0x3c ) )
|
ntHeader = systemModule.typedVar( "_IMAGE_NT_HEADERS", mod.begin() + ptrDWord( mod.begin() + 0x3c ) )
|
||||||
pSize = 4
|
pSize = 4
|
||||||
|
|
||||||
|
|
||||||
@ -37,7 +37,7 @@ def iat( moduleName, mask = "*" ):
|
|||||||
if ntHeader.OptionalHeader.DataDirectory[12].Size == 0:
|
if ntHeader.OptionalHeader.DataDirectory[12].Size == 0:
|
||||||
return
|
return
|
||||||
|
|
||||||
iatAddr = module.begin() + ntHeader.OptionalHeader.DataDirectory[12].VirtualAddress;
|
iatAddr = mod.begin() + ntHeader.OptionalHeader.DataDirectory[12].VirtualAddress;
|
||||||
|
|
||||||
for i in range( 0, ntHeader.OptionalHeader.DataDirectory[12].Size / pSize ):
|
for i in range( 0, ntHeader.OptionalHeader.DataDirectory[12].Size / pSize ):
|
||||||
|
|
||||||
|
@ -26,7 +26,7 @@ Work with NT Object tree manager
|
|||||||
|
|
||||||
from pykd import *
|
from pykd import *
|
||||||
|
|
||||||
nt = loadModule("nt")
|
nt = module("nt")
|
||||||
|
|
||||||
def getTypeWin7(p):
|
def getTypeWin7(p):
|
||||||
"""
|
"""
|
||||||
|
Loading…
Reference in New Issue
Block a user