[0.1.x] +sub-registers in thread context

git-svn-id: https://pykd.svn.codeplex.com/svn@72770 9b283d60-5439-405e-af05-b73fd8c4d996
This commit is contained in:
SND\EreTIk_cp 2011-12-29 19:56:00 +00:00 committed by Mikhail I. Izmestev
parent c465d4c110
commit df1c3afb65
5 changed files with 190 additions and 3 deletions

View File

@ -145,6 +145,14 @@ Registers::Registers(
ULONG64 Registers::getValue(ULONG cvRegId) const ULONG64 Registers::getValue(ULONG cvRegId) const
{ {
try
{
return getSubValue(cvRegId);
}
catch (const IsNotSubRegister &)
{
}
RegValues::const_iterator it = m_regValues.find(cvRegId); RegValues::const_iterator it = m_regValues.find(cvRegId);
if (it == m_regValues.end()) if (it == m_regValues.end())
throw Exception(__FUNCTION__ ": Register missing"); throw Exception(__FUNCTION__ ": Register missing");
@ -155,6 +163,19 @@ ULONG64 Registers::getValue(ULONG cvRegId) const
bool Registers::getValueNoThrow(ULONG cvRegId, ULONG64 &val) const bool Registers::getValueNoThrow(ULONG cvRegId, ULONG64 &val) const
{ {
try
{
val = getSubValue(cvRegId);
return true;
}
catch (const IsNotSubRegister &)
{
}
catch (const Exception &)
{
return false;
}
RegValues::const_iterator it = m_regValues.find(cvRegId); RegValues::const_iterator it = m_regValues.find(cvRegId);
if (it == m_regValues.end()) if (it == m_regValues.end())
return false; return false;
@ -209,6 +230,144 @@ python::object Registers::getByIndex(ULONG ind) const
///////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////
struct SubRegister {
ULONG m_fromReg;
ULONG m_bitsShift;
ULONG m_bitsMask;
void set(ULONG fromReg, ULONG bitsShift, ULONG bitsMask)
{
m_fromReg = fromReg; m_bitsShift = bitsShift; m_bitsMask = bitsMask;
}
};
/////////////////////////////////////////////////////////////////////////////////
static const class SubRegisterMapI386 : public std::map<ULONG, SubRegister> {
public:
SubRegisterMapI386();
} g_SubRegistersI386;
/////////////////////////////////////////////////////////////////////////////////
SubRegisterMapI386::SubRegisterMapI386()
{
(*this)[CV_REG_AL].set(CV_REG_EAX, 0x00, 0xff);
(*this)[CV_REG_CL].set(CV_REG_ECX, 0x00, 0xff);
(*this)[CV_REG_DL].set(CV_REG_EDX, 0x00, 0xff);
(*this)[CV_REG_BL].set(CV_REG_EBX, 0x00, 0xff);
(*this)[CV_REG_AH].set(CV_REG_EAX, 0x08, 0xff);
(*this)[CV_REG_CH].set(CV_REG_ECX, 0x08, 0xff);
(*this)[CV_REG_DH].set(CV_REG_EDX, 0x08, 0xff);
(*this)[CV_REG_BH].set(CV_REG_EBX, 0x08, 0xff);
(*this)[CV_REG_AX].set(CV_REG_EAX, 0x00, 0xffff);
(*this)[CV_REG_CX].set(CV_REG_ECX, 0x00, 0xffff);
(*this)[CV_REG_DX].set(CV_REG_EDX, 0x00, 0xffff);
(*this)[CV_REG_BX].set(CV_REG_EBX, 0x00, 0xffff);
(*this)[CV_REG_SP].set(CV_REG_ESP, 0x00, 0xffff);
(*this)[CV_REG_BP].set(CV_REG_EBP, 0x00, 0xffff);
(*this)[CV_REG_SI].set(CV_REG_ESI, 0x00, 0xffff);
(*this)[CV_REG_DI].set(CV_REG_EDI, 0x00, 0xffff);
}
/////////////////////////////////////////////////////////////////////////////////
static const class SubRegisterMapAmd64 : public std::map<ULONG, SubRegister> {
public:
SubRegisterMapAmd64();
} g_SubRegistersAmd64;
/////////////////////////////////////////////////////////////////////////////////
SubRegisterMapAmd64::SubRegisterMapAmd64()
{
(*this)[CV_AMD64_AL].set(CV_AMD64_RAX, 0x00, 0xff);
(*this)[CV_AMD64_CL].set(CV_AMD64_RCX, 0x00, 0xff);
(*this)[CV_AMD64_DL].set(CV_AMD64_RDX, 0x00, 0xff);
(*this)[CV_AMD64_BL].set(CV_AMD64_RBX, 0x00, 0xff);
(*this)[CV_AMD64_AH].set(CV_AMD64_RAX, 0x08, 0xff);
(*this)[CV_AMD64_CH].set(CV_AMD64_RCX, 0x08, 0xff);
(*this)[CV_AMD64_DH].set(CV_AMD64_RDX, 0x08, 0xff);
(*this)[CV_AMD64_BH].set(CV_AMD64_RBX, 0x08, 0xff);
(*this)[CV_AMD64_AX].set(CV_AMD64_RAX, 0x00, 0xffff);
(*this)[CV_AMD64_CX].set(CV_AMD64_RCX, 0x00, 0xffff);
(*this)[CV_AMD64_DX].set(CV_AMD64_RDX, 0x00, 0xffff);
(*this)[CV_AMD64_BX].set(CV_AMD64_RBX, 0x00, 0xffff);
(*this)[CV_AMD64_SP].set(CV_AMD64_RSP, 0x00, 0xffff);
(*this)[CV_AMD64_BP].set(CV_AMD64_RBP, 0x00, 0xffff);
(*this)[CV_AMD64_SI].set(CV_AMD64_RSI, 0x00, 0xffff);
(*this)[CV_AMD64_DI].set(CV_AMD64_RDI, 0x00, 0xffff);
(*this)[CV_AMD64_EAX].set(CV_AMD64_RAX, 0x00, 0xffffffff);
(*this)[CV_AMD64_ECX].set(CV_AMD64_RCX, 0x00, 0xffffffff);
(*this)[CV_AMD64_EDX].set(CV_AMD64_RDX, 0x00, 0xffffffff);
(*this)[CV_AMD64_EBX].set(CV_AMD64_RBX, 0x00, 0xffffffff);
(*this)[CV_AMD64_ESP].set(CV_AMD64_RSP, 0x00, 0xffffffff);
(*this)[CV_AMD64_EBP].set(CV_AMD64_RBP, 0x00, 0xffffffff);
(*this)[CV_AMD64_ESI].set(CV_AMD64_RSI, 0x00, 0xffffffff);
(*this)[CV_AMD64_EDI].set(CV_AMD64_RDI, 0x00, 0xffffffff);
(*this)[CV_AMD64_R8B].set(CV_AMD64_R8, 0x00, 0xff);
(*this)[CV_AMD64_R9B].set(CV_AMD64_R9, 0x00, 0xff);
(*this)[CV_AMD64_R10B].set(CV_AMD64_R10, 0x00, 0xff);
(*this)[CV_AMD64_R11B].set(CV_AMD64_R11, 0x00, 0xff);
(*this)[CV_AMD64_R12B].set(CV_AMD64_R12, 0x00, 0xff);
(*this)[CV_AMD64_R13B].set(CV_AMD64_R13, 0x00, 0xff);
(*this)[CV_AMD64_R14B].set(CV_AMD64_R14, 0x00, 0xff);
(*this)[CV_AMD64_R15B].set(CV_AMD64_R15, 0x00, 0xff);
(*this)[CV_AMD64_R8W].set(CV_AMD64_R8, 0x00, 0xffff);
(*this)[CV_AMD64_R9W].set(CV_AMD64_R9, 0x00, 0xffff);
(*this)[CV_AMD64_R10W].set(CV_AMD64_R10, 0x00, 0xffff);
(*this)[CV_AMD64_R11W].set(CV_AMD64_R11, 0x00, 0xffff);
(*this)[CV_AMD64_R12W].set(CV_AMD64_R12, 0x00, 0xffff);
(*this)[CV_AMD64_R13W].set(CV_AMD64_R13, 0x00, 0xffff);
(*this)[CV_AMD64_R14W].set(CV_AMD64_R14, 0x00, 0xffff);
(*this)[CV_AMD64_R15W].set(CV_AMD64_R15, 0x00, 0xffff);
(*this)[CV_AMD64_R8D].set(CV_AMD64_R8, 0x00, 0xffffffff);
(*this)[CV_AMD64_R9D].set(CV_AMD64_R9, 0x00, 0xffffffff);
(*this)[CV_AMD64_R10D].set(CV_AMD64_R10, 0x00, 0xffffffff);
(*this)[CV_AMD64_R11D].set(CV_AMD64_R11, 0x00, 0xffffffff);
(*this)[CV_AMD64_R12D].set(CV_AMD64_R12, 0x00, 0xffffffff);
(*this)[CV_AMD64_R13D].set(CV_AMD64_R13, 0x00, 0xffffffff);
(*this)[CV_AMD64_R14D].set(CV_AMD64_R14, 0x00, 0xffffffff);
(*this)[CV_AMD64_R15D].set(CV_AMD64_R15, 0x00, 0xffffffff);
}
/////////////////////////////////////////////////////////////////////////////////
ULONG64 Registers::getSubValue(ULONG cvRegId) const
{
const std::map<ULONG, SubRegister> *subRegs = NULL;
if (IMAGE_FILE_MACHINE_I386 == m_processorType)
subRegs = &g_SubRegistersI386;
else
subRegs = &g_SubRegistersAmd64;
std::map<ULONG, SubRegister>::const_iterator itSubReg =
subRegs->find(cvRegId);
if (itSubReg == subRegs->end())
throw IsNotSubRegister();
RegValues::const_iterator itFullReg = m_regValues.find(itSubReg->second.m_fromReg);
if (itFullReg == m_regValues.end())
throw Exception(__FUNCTION__ ": Register missing");
return
(itFullReg->second >> itSubReg->second.m_bitsShift) & itSubReg->second.m_bitsMask;
}
// ----------------------------------------------------------------------------
} }
///////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////

View File

@ -7,6 +7,10 @@
#pragma once #pragma once
namespace pykd{
std::string processorToStr(ULONG processorMode);
}
namespace Ctx { namespace Ctx {
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
@ -42,8 +46,17 @@ public:
} }
python::object getByIndex(ULONG ind) const; python::object getByIndex(ULONG ind) const;
// get processor type
std::string getProcessorType() const {
return pykd::processorToStr(m_processorType);
}
private: private:
struct IsNotSubRegister : public std::exception {
IsNotSubRegister() : std::exception("is not sub-register") { }
};
// query i386 registers // query i386 registers
void getI386Context( void getI386Context(
IDebugAdvanced2 *advanced IDebugAdvanced2 *advanced
@ -54,6 +67,9 @@ private:
IDebugAdvanced2 *advanced IDebugAdvanced2 *advanced
); );
// try query as "sub-register"
ULONG64 getSubValue(ULONG cvRegId) const;
private: private:
typedef std::map<ULONG, ULONG64> RegValues; typedef std::map<ULONG, ULONG64> RegValues;
RegValues m_regValues; RegValues m_regValues;

View File

@ -604,6 +604,8 @@ BOOST_PYTHON_MODULE( pykd )
"Get current stack pointer" ) "Get current stack pointer" )
.def( "get", &Ctx::Registers::getValue, .def( "get", &Ctx::Registers::getValue,
"Get register value by ID (CV_REG_XXX)" ) "Get register value by ID (CV_REG_XXX)" )
.def( "processorType", &Ctx::Registers::getProcessorType,
"Get processor type as string")
.def("__len__", &Ctx::Registers::getCount, .def("__len__", &Ctx::Registers::getCount,
"Return count of registers") "Return count of registers")
.def("__getitem__", &Ctx::Registers::getByIndex, .def("__getitem__", &Ctx::Registers::getByIndex,

View File

@ -78,7 +78,7 @@ getCurrentStack()
/////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////
static std::string processorToStr(ULONG processorMode) std::string processorToStr(ULONG processorMode)
{ {
switch( processorMode ) switch( processorMode )
{ {

View File

@ -26,15 +26,25 @@ class DbgClientTest( unittest.TestCase ):
ctx = pykd.getContext() ctx = pykd.getContext()
# for reg in ctx: # for reg in ctx:
# regName = "" # regName = ""
# try: # if ctx.processorType() == "X86":
# regName = pykd.diaI386Regs[ reg[0] ] # regName = pykd.diaI386Regs[ reg[0] ]
# except KeyError: # else:
# regName = pykd.diaAmd64Regs[ reg[0] ] # regName = pykd.diaAmd64Regs[ reg[0] ]
# pykd.dprint( "\n" + regName + ": 0x%x " % reg[1]) # pykd.dprint( "\n" + regName + ": 0x%x " % reg[1])
self.assertNotEqual( 0, len(ctx) ) self.assertNotEqual( 0, len(ctx) )
self.assertNotEqual( 0, ctx.ip() ) self.assertNotEqual( 0, ctx.ip() )
self.assertNotEqual( 0, ctx.csp() ) self.assertNotEqual( 0, ctx.csp() )
self.assertEqual( (ctx.get(pykd.CV_REG_AH) << 8) | ctx.get(pykd.CV_REG_AL), ctx.get(pykd.CV_REG_AX) )
self.assertEqual( ctx.get(pykd.CV_REG_AX), ctx.get(pykd.CV_REG_EAX) & 0xffff )
if ctx.processorType() == "X64":
self.assertEqual( ctx.get(pykd.CV_REG_EAX), ctx.get(pykd.CV_AMD64_RAX) & 0xffffffff )
self.assertEqual( (ctx.get(pykd.CV_REG_DH) << 8) | ctx.get(pykd.CV_REG_DL), ctx.get(pykd.CV_REG_DX) )
self.assertEqual( ctx.get(pykd.CV_REG_DX), ctx.get(pykd.CV_REG_EDX) & 0xffff )
if ctx.processorType() == "X64":
self.assertEqual( ctx.get(pykd.CV_REG_EDX), ctx.get(pykd.CV_AMD64_RDX) & 0xffffffff )
def testIsDumpAnalyzing( self ): def testIsDumpAnalyzing( self ):
self.assertFalse( pykd.isDumpAnalyzing() ) self.assertFalse( pykd.isDumpAnalyzing() )