[0.1.x] + getWow64Context

git-svn-id: https://pykd.svn.codeplex.com/svn@77588 9b283d60-5439-405e-af05-b73fd8c4d996
This commit is contained in:
SND\EreTIk_cp 2012-06-26 12:43:18 +00:00 committed by Mikhail I. Izmestev
parent f225f3905e
commit 8ee1e65535
4 changed files with 137 additions and 32 deletions

View File

@ -10,7 +10,46 @@
///////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////
namespace pykd { namespace pykd {
////////////////////////////////////////////////////////////////////////////////
// Fill 32-bit register context
////////////////////////////////////////////////////////////////////////////////
template <typename TContext>
void FillRegistersFromContext32(
ThreadContext::RegValues &regValues,
const TContext &Context
)
{
regValues[CV_REG_DR0] = Context.Dr0;
regValues[CV_REG_DR1] = Context.Dr1;
regValues[CV_REG_DR2] = Context.Dr2;
regValues[CV_REG_DR3] = Context.Dr3;
regValues[CV_REG_DR6] = Context.Dr6;
regValues[CV_REG_DR7] = Context.Dr7;
regValues[CV_REG_GS] = Context.SegGs;
regValues[CV_REG_FS] = Context.SegFs;
regValues[CV_REG_ES] = Context.SegEs;
regValues[CV_REG_DS] = Context.SegDs;
regValues[CV_REG_EDI] = Context.Edi;
regValues[CV_REG_ESI] = Context.Esi;
regValues[CV_REG_EBX] = Context.Ebx;
regValues[CV_REG_EDX] = Context.Edx;
regValues[CV_REG_ECX] = Context.Ecx;
regValues[CV_REG_EAX] = Context.Eax;
regValues[CV_REG_EBP] = Context.Ebp;
regValues[CV_REG_ESP] = Context.Esp;
regValues[CV_REG_SS] = Context.SegSs;
regValues[CV_REG_EIP] = Context.Eip;
regValues[CV_REG_CS] = Context.SegCs;
regValues[CV_REG_EFLAGS] = Context.EFlags;
}
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
namespace I386 { namespace I386 {
@ -27,34 +66,7 @@ void ThreadContext::getI386Context()
if (S_OK != hres) if (S_OK != hres)
throw DbgException( "IDebugAdvanced2::GetThreadContext", hres ); throw DbgException( "IDebugAdvanced2::GetThreadContext", hres );
m_regValues[CV_REG_DR0] = Context.Dr0; FillRegistersFromContext32(m_regValues, Context);
m_regValues[CV_REG_DR1] = Context.Dr1;
m_regValues[CV_REG_DR2] = Context.Dr2;
m_regValues[CV_REG_DR3] = Context.Dr3;
m_regValues[CV_REG_DR6] = Context.Dr6;
m_regValues[CV_REG_DR7] = Context.Dr7;
m_regValues[CV_REG_GS] = Context.SegGs;
m_regValues[CV_REG_FS] = Context.SegFs;
m_regValues[CV_REG_ES] = Context.SegEs;
m_regValues[CV_REG_DS] = Context.SegDs;
m_regValues[CV_REG_EDI] = Context.Edi;
m_regValues[CV_REG_ESI] = Context.Esi;
m_regValues[CV_REG_EBX] = Context.Ebx;
m_regValues[CV_REG_EDX] = Context.Edx;
m_regValues[CV_REG_ECX] = Context.Ecx;
m_regValues[CV_REG_EAX] = Context.Eax;
m_regValues[CV_REG_EBP] = Context.Ebp;
m_regValues[CV_REG_ESP] = Context.Esp;
m_regValues[CV_REG_SS] = Context.SegSs;
m_regValues[CV_REG_EIP] = Context.Eip;
m_regValues[CV_REG_CS] = Context.SegCs;
m_regValues[CV_REG_EFLAGS] = Context.EFlags;
} }
///////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////
@ -136,6 +148,81 @@ ThreadContext::ThreadContext( IDebugClient4 *client ) :
///////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////
ThreadContext::ThreadContext(
IDebugClient4 *client,
ULONG processorType
) : pykd::DbgObject(client)
, m_processorType(processorType)
{
}
/////////////////////////////////////////////////////////////////////////////////
ContextPtr ThreadContext::getWow64Context( IDebugClient4 *client )
{
ContextPtr ptrContext( new ThreadContext(client, IMAGE_FILE_MACHINE_I386) );
ULONG processorType;
HRESULT hres = ptrContext->m_control->GetEffectiveProcessorType(&processorType);
if (S_OK != hres)
throw DbgException( "IDebugControl::GetEffectiveProcessorType", hres );
if (IMAGE_FILE_MACHINE_I386 != processorType)
throw DbgException( "Only for WOW64 processor mode" );
hres = ptrContext->m_control->GetActualProcessorType(&processorType);
if (S_OK != hres)
throw DbgException( "IDebugControl::GetActualProcessorType", hres );
if (IMAGE_FILE_MACHINE_AMD64 != processorType)
throw DbgException( "Only for WOW64 processor mode" );
//
// *** undoc ***
// !wow64exts.r
// http://www.woodmann.com/forum/archive/index.php/t-11162.html
// http://www.nynaeve.net/Code/GetThreadWow64Context.cpp
//
ULONG64 teb64Address;
hres = ptrContext->m_system->GetCurrentThreadTeb(&teb64Address);
if (S_OK != hres)
throw DbgException( "IDebugSystemObjects::GetCurrentThreadTeb", hres);
// ? @@C++(#FIELD_OFFSET(nt!_TEB64, TlsSlots))
// hardcoded in !wow64exts.r (6.2.8250.0)
static const ULONG teb64ToTlsOffset = 0x01480;
static const ULONG WOW64_TLS_CPURESERVED = 1;
ULONG64 cpuAreaAddress;
ULONG readedBytes;
hres =
ptrContext->m_dataSpaces->ReadVirtual(
teb64Address + teb64ToTlsOffset + (sizeof(ULONG64) * WOW64_TLS_CPURESERVED),
&cpuAreaAddress,
sizeof(cpuAreaAddress),
&readedBytes);
if (S_OK != hres || readedBytes != sizeof(cpuAreaAddress))
throw DbgException( "IDebugDataSpaces::ReadVirtual", hres);
// CPU Area is:
// +00 unknown ULONG
// +04 WOW64_CONTEXT struct
static const ULONG cpuAreaToWow64ContextOffset = sizeof(ULONG);
WOW64_CONTEXT Context = {0};
hres =
ptrContext->m_dataSpaces->ReadVirtual(
cpuAreaAddress + cpuAreaToWow64ContextOffset,
&Context,
sizeof(Context),
&readedBytes);
if (S_OK != hres || readedBytes != sizeof(Context))
throw DbgException( "IDebugDataSpaces::ReadVirtual", hres);
FillRegistersFromContext32(ptrContext->m_regValues, Context);
return ptrContext;
}
/////////////////////////////////////////////////////////////////////////////////
ULONG64 ThreadContext::getValue(ULONG cvRegId) const ULONG64 ThreadContext::getValue(ULONG cvRegId) const
{ {
ULONG64 val; ULONG64 val;

View File

@ -26,7 +26,10 @@ std::string processorToStr(ULONG processorMode);
class ThreadContext : private DbgObject class ThreadContext : private DbgObject
{ {
public: public:
typedef std::map<ULONG, ULONG64> RegValues;
ThreadContext( IDebugClient4 *client ); ThreadContext( IDebugClient4 *client );
static ContextPtr getWow64Context( IDebugClient4 *client );
// get register value by ID // get register value by ID
ULONG64 getValue(ULONG cvRegId) const; ULONG64 getValue(ULONG cvRegId) const;
@ -58,7 +61,11 @@ public:
std::string print() const; std::string print() const;
private: protected:
ThreadContext(
IDebugClient4 *client,
ULONG processorType
);
// query i386 registers // query i386 registers
void getI386Context(); void getI386Context();
@ -72,7 +79,6 @@ private:
void __declspec(noreturn) throwUnsupportedProcessor(PCSTR szFunction) const; void __declspec(noreturn) throwUnsupportedProcessor(PCSTR szFunction) const;
private: private:
typedef std::map<ULONG, ULONG64> RegValues;
RegValues m_regValues; RegValues m_regValues;
ULONG m_processorType; ULONG m_processorType;

View File

@ -254,6 +254,9 @@ public:
ContextPtr getThreadContext() { ContextPtr getThreadContext() {
return ContextPtr( new ThreadContext(m_client) ); return ContextPtr( new ThreadContext(m_client) );
} }
ContextPtr getThreadWow64Context() {
return ThreadContext::getWow64Context(m_client);
}
python::dict getLocals( python::dict getLocals(
ContextPtr ctx = ContextPtr( reinterpret_cast<ThreadContext*>(0) ) ContextPtr ctx = ContextPtr( reinterpret_cast<ThreadContext*>(0) )
@ -472,6 +475,10 @@ inline ContextPtr getThreadContext() {
return g_dbgClient->getThreadContext(); return g_dbgClient->getThreadContext();
} }
inline ContextPtr getThreadWow64Context() {
return g_dbgClient->getThreadWow64Context();
}
inline python::dict getLocals( inline python::dict getLocals(
ContextPtr ctx = ContextPtr() ContextPtr ctx = ContextPtr()
) )

View File

@ -322,6 +322,9 @@ BOOST_PYTHON_MODULE( pykd )
"Get the page size for the currently executing processor context" ) "Get the page size for the currently executing processor context" )
.def( "getContext", &DebugClient::getThreadContext, .def( "getContext", &DebugClient::getThreadContext,
"Get context of current thread (register values)" ) "Get context of current thread (register values)" )
.def( "getWow64Context", &DebugClient::getThreadWow64Context,
"Get WOW64-context of current thread (register values)\n"
"!wow64exts.r analog")
.def( "getLocals", &DebugClient::getLocals, DebugClient_getLocals( python::args( "ctx" ), .def( "getLocals", &DebugClient::getLocals, DebugClient_getLocals( python::args( "ctx" ),
"Get list of local variables" ) ) "Get list of local variables" ) )
.def( "setBp", &DebugClient::setSoftwareBp, DebugClient_setSoftwareBp( python::args( "offset", "callback" ), .def( "setBp", &DebugClient::setSoftwareBp, DebugClient_setSoftwareBp( python::args( "offset", "callback" ),
@ -523,6 +526,9 @@ BOOST_PYTHON_MODULE( pykd )
"Get the page size for the currently executing processor context" ); "Get the page size for the currently executing processor context" );
python::def( "getContext", &getThreadContext, python::def( "getContext", &getThreadContext,
"Get context of current thread (register values)" ); "Get context of current thread (register values)" );
python::def( "getWow64Context", &getThreadWow64Context,
"Get WOW64-context of current thread (register values)\n"
"!wow64exts.r analog" );
python::def( "getLocals", &getLocals, getLocals_( python::args( "ctx" ), python::def( "getLocals", &getLocals, getLocals_( python::args( "ctx" ),
"Get list of local variables" ) ); "Get list of local variables" ) );
python::def( "setBp", &setSoftwareBp, setSoftwareBp_( python::args( "offset", "callback" ), python::def( "setBp", &setSoftwareBp, setSoftwareBp_( python::args( "offset", "callback" ),
@ -719,7 +725,6 @@ BOOST_PYTHON_MODULE( pykd )
.def("__str__", &ThreadContext::print, .def("__str__", &ThreadContext::print,
"Return context as a string" ); "Return context as a string" );
python::class_<CpuReg, python::bases<intBase> >( python::class_<CpuReg, python::bases<intBase> >(
"cpuReg", "CPU regsiter class", boost::python::no_init ) "cpuReg", "CPU regsiter class", boost::python::no_init )
.def( "name", &CpuReg::name, "The name of the regsiter" ) .def( "name", &CpuReg::name, "The name of the regsiter" )