[0.1.x] + context of current thread

git-svn-id: https://pykd.svn.codeplex.com/svn@72757 9b283d60-5439-405e-af05-b73fd8c4d996
This commit is contained in:
SND\EreTIk_cp 2011-12-29 12:45:16 +00:00 committed by Mikhail I. Izmestev
parent 932fc93926
commit 380410a521
9 changed files with 513 additions and 34 deletions

214
pykd/context.cpp Normal file
View File

@ -0,0 +1,214 @@
#include "stdafx.h"
#include <boost\python\tuple.hpp>
#include "context.h"
/////////////////////////////////////////////////////////////////////////////////
namespace Ctx {
/////////////////////////////////////////////////////////////////////////////////
namespace I386 {
#include "defctxi386.h"
}
/////////////////////////////////////////////////////////////////////////////////
void Registers::getI386Context(
IDebugAdvanced2 *advanced
)
{
I386::CONTEXT Context = {0};
HRESULT hres = advanced->GetThreadContext(&Context, sizeof(Context));
if (S_OK != hres)
throw Exception( pykd::buildExceptDesc("IDebugAdvanced2::GetThreadContext", hres) );
m_regValues[CV_REG_DR0] = Context.Dr0;
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;
}
/////////////////////////////////////////////////////////////////////////////////
namespace AMD64 {
#include "defctxamd64.h"
}
/////////////////////////////////////////////////////////////////////////////////
void Registers::getAmd64Context(
IDebugAdvanced2 *advanced
)
{
AMD64::CONTEXT Context = {0};
HRESULT hres = advanced->GetThreadContext(&Context, sizeof(Context));
if (S_OK != hres)
throw Exception( pykd::buildExceptDesc("IDebugAdvanced2::GetThreadContext", hres) );
m_regValues[CV_AMD64_MXCSR] = Context.MxCsr;
m_regValues[CV_AMD64_CS] = Context.SegCs;
m_regValues[CV_AMD64_DS] = Context.SegDs;
m_regValues[CV_AMD64_ES] = Context.SegEs;
m_regValues[CV_AMD64_FS] = Context.SegFs;
m_regValues[CV_AMD64_GS] = Context.SegGs;
m_regValues[CV_AMD64_SS] = Context.SegSs;
m_regValues[CV_AMD64_EFLAGS] = Context.EFlags;
m_regValues[CV_AMD64_DR0] = Context.Dr0;
m_regValues[CV_AMD64_DR1] = Context.Dr1;
m_regValues[CV_AMD64_DR2] = Context.Dr2;
m_regValues[CV_AMD64_DR3] = Context.Dr3;
m_regValues[CV_AMD64_DR6] = Context.Dr6;
m_regValues[CV_AMD64_DR7] = Context.Dr7;
m_regValues[CV_AMD64_RAX] = Context.Rax;
m_regValues[CV_AMD64_RCX] = Context.Rcx;
m_regValues[CV_AMD64_RDX] = Context.Rdx;
m_regValues[CV_AMD64_RBX] = Context.Rbx;
m_regValues[CV_AMD64_RSP] = Context.Rsp;
m_regValues[CV_AMD64_RBP] = Context.Rbp;
m_regValues[CV_AMD64_RSI] = Context.Rdi;
m_regValues[CV_AMD64_RDI] = Context.Rdi;
m_regValues[CV_AMD64_R8] = Context.R8;
m_regValues[CV_AMD64_R9] = Context.R9;
m_regValues[CV_AMD64_R10] = Context.R10;
m_regValues[CV_AMD64_R11] = Context.R11;
m_regValues[CV_AMD64_R12] = Context.R12;
m_regValues[CV_AMD64_R13] = Context.R13;
m_regValues[CV_AMD64_R14] = Context.R14;
m_regValues[CV_AMD64_R15] = Context.R15;
m_regValues[CV_AMD64_RIP] = Context.Rip;
}
/////////////////////////////////////////////////////////////////////////////////
Registers::Registers(
IDebugControl4 *control,
IDebugAdvanced2 *advanced
)
{
HRESULT hres = control->GetExecutingProcessorType(&m_processorType);
if (S_OK != hres)
throw Exception( pykd::buildExceptDesc("IDebugControl::GetExecutingProcessorType", hres) );
switch (m_processorType)
{
case IMAGE_FILE_MACHINE_I386:
getI386Context(advanced);
return;
case IMAGE_FILE_MACHINE_AMD64:
getAmd64Context(advanced);
return;
}
std::stringstream sstream;
sstream << __FUNCTION__ << ":\n";
sstream << "Unsupported processor type: 0x" << std::hex << m_processorType;
throw Exception( sstream.str() );
}
/////////////////////////////////////////////////////////////////////////////////
ULONG64 Registers::getValue(ULONG cvRegId) const
{
RegValues::const_iterator it = m_regValues.find(cvRegId);
if (it == m_regValues.end())
throw Exception(__FUNCTION__ ": Register missing");
return it->second;
}
/////////////////////////////////////////////////////////////////////////////////
bool Registers::getValueNoThrow(ULONG cvRegId, ULONG64 &val) const
{
RegValues::const_iterator it = m_regValues.find(cvRegId);
if (it == m_regValues.end())
return false;
val = it->second;
return true;
}
/////////////////////////////////////////////////////////////////////////////////
ULONG64 Registers::getIp() const
{
return getValue(
IMAGE_FILE_MACHINE_I386 == m_processorType ? CV_REG_EIP : CV_AMD64_RIP
);
}
/////////////////////////////////////////////////////////////////////////////////
ULONG64 Registers::getRetReg() const
{
return getValue(
IMAGE_FILE_MACHINE_I386 == m_processorType ? CV_REG_EAX : CV_AMD64_RAX
);
}
/////////////////////////////////////////////////////////////////////////////////
ULONG64 Registers::getSp() const
{
return getValue(
IMAGE_FILE_MACHINE_I386 == m_processorType ? CV_REG_ESP : CV_AMD64_RSP
);
}
/////////////////////////////////////////////////////////////////////////////////
python::object Registers::getByIndex(ULONG ind) const
{
RegValues::const_iterator it = m_regValues.begin();
for (ULONG i = 0; it != m_regValues.end(); ++i, ++it )
{
if (i == ind)
return python::make_tuple(it->first, it->second);
}
PyErr_SetString(PyExc_IndexError, "Index out of range");
python::throw_error_already_set();
return python::object();
}
/////////////////////////////////////////////////////////////////////////////////
}
/////////////////////////////////////////////////////////////////////////////////

71
pykd/context.h Normal file
View File

@ -0,0 +1,71 @@
#include <map>
#include <DbgEng.h>
#include <CvConst.h>
#include "dbgexcept.h"
#pragma once
namespace Ctx {
////////////////////////////////////////////////////////////////////////////////
typedef pykd::DbgException Exception;
////////////////////////////////////////////////////////////////////////////////
class Registers
{
public:
Registers(
IDebugControl4 *control,
IDebugAdvanced2 *advanced
);
// get register value by ID
ULONG64 getValue(ULONG cvRegId) const;
bool getValueNoThrow(ULONG cvRegId, ULONG64 &val) const;
// get @$ip pseudo register
ULONG64 getIp() const;
// get @$retreg pseudo register
ULONG64 getRetReg() const;
// get @$csp pseudo register
ULONG64 getSp() const;
// enumerate register values: tuple<CV_REG_ID, VALUE>
ULONG getCount() const {
return static_cast<ULONG>( m_regValues.size() );
}
python::object getByIndex(ULONG ind) const;
private:
// query i386 registers
void getI386Context(
IDebugAdvanced2 *advanced
);
// query AMD64 registers
void getAmd64Context(
IDebugAdvanced2 *advanced
);
private:
typedef std::map<ULONG, ULONG64> RegValues;
RegValues m_regValues;
ULONG m_processorType;
};
////////////////////////////////////////////////////////////////////////////////
typedef boost::shared_ptr< Registers > ContextPtr;
////////////////////////////////////////////////////////////////////////////////
}

View File

@ -16,6 +16,7 @@
#include "cpureg.h"
#include "inteventhandler.h"
#include "synsymbol.h"
#include "context.h"
/////////////////////////////////////////////////////////////////////////////////
@ -233,6 +234,12 @@ public:
return getDbgControl(GetPageSize);
}
Ctx::ContextPtr getThreadContext() {
return Ctx::ContextPtr(
new Ctx::Registers(m_control, m_advanced)
);
}
public:
CComPtr<IDebugClient4>&
@ -387,6 +394,10 @@ inline ULONG getPageSize() {
return g_dbgClient->getPageSize();
}
inline Ctx::ContextPtr getThreadContext() {
return g_dbgClient->getThreadContext();
}
/////////////////////////////////////////////////////////////////////////////////
template<ULONG status>

View File

@ -283,6 +283,8 @@ BOOST_PYTHON_MODULE( pykd )
"Get the number of actual processors in the machine" )
.def( "getPageSize", &DebugClient::getPageSize,
"Get the page size for the currently executing processor context" )
.def( "getContext", &DebugClient::getThreadContext,
"Get context of current thread (register values)" )
.def( "addSynSymbol", &DebugClient::addSyntheticSymbol,
"Add new synthetic symbol for virtual address" )
.def( "delAllSynSymbols", &DebugClient::delAllSyntheticSymbols,
@ -454,6 +456,8 @@ BOOST_PYTHON_MODULE( pykd )
"Get the number of actual processors in the machine" );
python::def( "getPageSize", &getPageSize,
"Get the page size for the currently executing processor context" );
python::def( "getContext", &getThreadContext,
"Get context of current thread (register values)" );
python::class_<TypeInfo, TypeInfoPtr, python::bases<intBase>, boost::noncopyable >("typeInfo", "Class representing typeInfo", python::no_init )
.def( "name", &TypeInfo::getName )
@ -585,7 +589,22 @@ BOOST_PYTHON_MODULE( pykd )
"Return a frame's stack offset" )
.def_readonly( "frameNumber", &DEBUG_STACK_FRAME::FrameNumber,
"Return a frame's number" );
python::class_<Ctx::Registers, Ctx::ContextPtr>(
"Context", "Context of thread (register values)", python::no_init )
.def( "ip", &Ctx::Registers::getIp,
"Get instruction pointer register" )
.def( "retreg", &Ctx::Registers::getIp,
"Get primary return value register" )
.def( "csp", &Ctx::Registers::getSp,
"Get current stack pointer" )
.def( "get", &Ctx::Registers::getValue,
"Get register value by ID (CV_REG_XXX)" )
.def("__len__", &Ctx::Registers::getCount,
"Return count of registers")
.def("__getitem__", &Ctx::Registers::getByIndex,
"Return tuple<ID, VALUE> by index");
python::def( "diaLoadPdb", &pyDia::GlobalScope::loadPdb,
"Open pdb file for quering debug symbols. Return DiaSymbol of global scope");

95
pykd/defctxamd64.h Normal file
View File

@ -0,0 +1,95 @@
struct DECLSPEC_ALIGN(16) M128A {
ULONGLONG Low;
LONGLONG High;
};
struct XMM_SAVE_AREA32 {
USHORT ControlWord;
USHORT StatusWord;
UCHAR TagWord;
UCHAR Reserved1;
USHORT ErrorOpcode;
ULONG ErrorOffset;
USHORT ErrorSelector;
USHORT Reserved2;
ULONG DataOffset;
USHORT DataSelector;
USHORT Reserved3;
ULONG MxCsr;
ULONG MxCsr_Mask;
M128A FloatRegisters[8];
M128A XmmRegisters[16];
UCHAR Reserved4[96];
};
struct DECLSPEC_ALIGN(16) CONTEXT {
ULONG64 P1Home;
ULONG64 P2Home;
ULONG64 P3Home;
ULONG64 P4Home;
ULONG64 P5Home;
ULONG64 P6Home;
ULONG ContextFlags;
ULONG MxCsr;
USHORT SegCs;
USHORT SegDs;
USHORT SegEs;
USHORT SegFs;
USHORT SegGs;
USHORT SegSs;
ULONG EFlags;
ULONG64 Dr0;
ULONG64 Dr1;
ULONG64 Dr2;
ULONG64 Dr3;
ULONG64 Dr6;
ULONG64 Dr7;
ULONG64 Rax;
ULONG64 Rcx;
ULONG64 Rdx;
ULONG64 Rbx;
ULONG64 Rsp;
ULONG64 Rbp;
ULONG64 Rsi;
ULONG64 Rdi;
ULONG64 R8;
ULONG64 R9;
ULONG64 R10;
ULONG64 R11;
ULONG64 R12;
ULONG64 R13;
ULONG64 R14;
ULONG64 R15;
ULONG64 Rip;
union {
XMM_SAVE_AREA32 FltSave;
struct {
M128A Header[2];
M128A Legacy[8];
M128A Xmm0;
M128A Xmm1;
M128A Xmm2;
M128A Xmm3;
M128A Xmm4;
M128A Xmm5;
M128A Xmm6;
M128A Xmm7;
M128A Xmm8;
M128A Xmm9;
M128A Xmm10;
M128A Xmm11;
M128A Xmm12;
M128A Xmm13;
M128A Xmm14;
M128A Xmm15;
};
};
M128A VectorRegister[26];
ULONG64 VectorControl;
ULONG64 DebugControl;
ULONG64 LastBranchToRip;
ULONG64 LastBranchFromRip;
ULONG64 LastExceptionToRip;
ULONG64 LastExceptionFromRip;
};

54
pykd/defctxi386.h Normal file
View File

@ -0,0 +1,54 @@
#define MAXIMUM_SUPPORTED_EXTENSION 512
#define SIZE_OF_80387_REGISTERS 80
struct FLOATING_SAVE_AREA {
ULONG ControlWord;
ULONG StatusWord;
ULONG TagWord;
ULONG ErrorOffset;
ULONG ErrorSelector;
ULONG DataOffset;
ULONG DataSelector;
UCHAR RegisterArea[SIZE_OF_80387_REGISTERS];
ULONG Cr0NpxState;
};
struct CONTEXT {
ULONG ContextFlags;
ULONG Dr0;
ULONG Dr1;
ULONG Dr2;
ULONG Dr3;
ULONG Dr6;
ULONG Dr7;
FLOATING_SAVE_AREA FloatSave;
ULONG SegGs;
ULONG SegFs;
ULONG SegEs;
ULONG SegDs;
ULONG Edi;
ULONG Esi;
ULONG Ebx;
ULONG Edx;
ULONG Ecx;
ULONG Eax;
ULONG Ebp;
ULONG Eip;
ULONG SegCs;
ULONG EFlags;
ULONG Esp;
ULONG SegSs;
UCHAR ExtendedRegisters[MAXIMUM_SUPPORTED_EXTENSION];
};

View File

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="windows-1251"?>
<VisualStudioProject
ProjectType="Visual C++"
Version="9,00"
Version="9.00"
Name="pykd"
ProjectGUID="{FE961905-666F-4908-A212-961465F46F13}"
RootNamespace="pykd"
@ -349,6 +349,10 @@
Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
>
<File
RelativePath=".\context.cpp"
>
</File>
<File
RelativePath=".\cpureg.cpp"
>
@ -475,6 +479,10 @@
Filter="h;hpp;hxx;hm;inl;inc;xsd"
UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
>
<File
RelativePath=".\context.h"
>
</File>
<File
RelativePath=".\cpureg.h"
>
@ -511,6 +519,14 @@
RelativePath=".\dbgpath.h"
>
</File>
<File
RelativePath=".\defctxamd64.h"
>
</File>
<File
RelativePath=".\defctxi386.h"
>
</File>
<File
RelativePath=".\diaregs.h"
>

View File

@ -21,6 +21,20 @@ class DbgClientTest( unittest.TestCase ):
"""Size of memory page must be >= 4kb"""
self.assertTrue( pykd.getPageSize() >= 4*1024 )
def testCurrentThreadContext( self ):
"""Some check of current thread context content"""
ctx = pykd.getContext()
# for reg in ctx:
# regName = ""
# try:
# regName = pykd.diaI386Regs[ reg[0] ]
# except KeyError:
# regName = pykd.diaAmd64Regs[ reg[0] ]
# pykd.dprint( "\n" + regName + ": 0x%x " % reg[1])
self.assertNotEqual( 0, len(ctx) )
self.assertNotEqual( 0, ctx.ip() )
self.assertNotEqual( 0, ctx.csp() )
def testIsDumpAnalyzing( self ):
self.assertFalse( pykd.isDumpAnalyzing() )
@ -29,7 +43,7 @@ class DbgClientTest( unittest.TestCase ):
pykd.setExecutionStatus( pykd.DEBUG_STATUS_GO )
pykd.waitForEvent()
self.assertEqual( pykd.DEBUG_STATUS_BREAK, pykd.getExecutionStatus() )
def testPdbFile( self ):
self.assertNotEqual( '', pykd.getPdbFile( target.module.begin() ) )
@ -39,6 +53,6 @@ class DbgClientTest( unittest.TestCase ):
def testThreadList( self ):
self.assertNotEqual( 0, len(pykd.getThreadList()) )
def testSymbolsPath( self ):
self.assertNotEqual( '', pykd.symbolsPath() )

View File

@ -7,6 +7,8 @@
#include "utils.h"
////////////////////////////////////////////////////////////////////////////////
#pragma pack( push, 4 )
const ULONG g_constNumValue = 0x5555;
@ -160,6 +162,10 @@ listStruct1 g_listItem11 = { 100 };
listStruct1 g_listItem12 = { 200 };
listStruct1 g_listItem13 = { 300 };
#pragma pack( pop )
////////////////////////////////////////////////////////////////////////////////
#define InitializeListHead(ListHead) (\
(ListHead)->Flink = (ListHead)->Blink = (ListHead))
@ -174,6 +180,8 @@ listStruct1 g_listItem13 = { 300 };
_EX_ListHead->Blink = (Entry);\
}
////////////////////////////////////////////////////////////////////////////////
void FuncWithName0()
{
classChild _classChild;
@ -212,6 +220,8 @@ void FuncWithName0()
std::cout << g_classChild.m_enumField;
}
////////////////////////////////////////////////////////////////////////////////
void FuncWithName1(int a)
{
unionTest _unionTest[2] = {0};
@ -227,49 +237,23 @@ void FuncWithName1(int a)
std::cout << g_string;
}
void FuncWithVolatileArg(volatile long *arg1)
{
InterlockedIncrement(arg1);
}
////////////////////////////////////////////////////////////////////////////////
BOOL CALLBACK EnumWindowsProc(
HWND hWindow,
LPARAM lParam
)
{
DWORD dwProccessId = 0;
if (hWindow)
std::cout << lParam;
switch(lParam)
{
case 1:
std::cout << "case 1";
break;
case 2:
std::cout << "case 2";
break;
case 3:
std::cout << "case 2";
break;
default:
{
DWORD dwProccessId = 0;
DWORD dwThreadId = ::GetWindowThreadProcessId(hWindow, &dwProccessId);
std::cout << dwProccessId << dwThreadId;
classWithDestructor classInstance(dwProccessId);
std::cout << GetWindowLong(hWindow, GWL_STYLE);
}
DWORD dwThreadId = ::GetWindowThreadProcessId(hWindow, &dwProccessId);
std::cout << dwProccessId << dwThreadId;
}
return FALSE;
}
#pragma pack( pop )
////////////////////////////////////////////////////////////////////////////////
int doLoadUnload()
@ -328,3 +312,4 @@ int _tmain(int argc, _TCHAR* argv[])
return 0;
}
////////////////////////////////////////////////////////////////////////////////