diff --git a/pykd/context.cpp b/pykd/context.cpp index 120ca46..08a77d1 100644 --- a/pykd/context.cpp +++ b/pykd/context.cpp @@ -145,6 +145,14 @@ Registers::Registers( ULONG64 Registers::getValue(ULONG cvRegId) const { + try + { + return getSubValue(cvRegId); + } + catch (const IsNotSubRegister &) + { + } + RegValues::const_iterator it = m_regValues.find(cvRegId); if (it == m_regValues.end()) throw Exception(__FUNCTION__ ": Register missing"); @@ -155,6 +163,19 @@ ULONG64 Registers::getValue(ULONG cvRegId) 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); if (it == m_regValues.end()) 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 { +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 { +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 *subRegs = NULL; + if (IMAGE_FILE_MACHINE_I386 == m_processorType) + subRegs = &g_SubRegistersI386; + else + subRegs = &g_SubRegistersAmd64; + + std::map::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; +} + +// ---------------------------------------------------------------------------- + } ///////////////////////////////////////////////////////////////////////////////// diff --git a/pykd/context.h b/pykd/context.h index f9f9269..7753fd2 100644 --- a/pykd/context.h +++ b/pykd/context.h @@ -7,6 +7,10 @@ #pragma once +namespace pykd{ + std::string processorToStr(ULONG processorMode); +} + namespace Ctx { //////////////////////////////////////////////////////////////////////////////// @@ -42,8 +46,17 @@ public: } python::object getByIndex(ULONG ind) const; + // get processor type + std::string getProcessorType() const { + return pykd::processorToStr(m_processorType); + } + private: + struct IsNotSubRegister : public std::exception { + IsNotSubRegister() : std::exception("is not sub-register") { } + }; + // query i386 registers void getI386Context( IDebugAdvanced2 *advanced @@ -54,6 +67,9 @@ private: IDebugAdvanced2 *advanced ); + // try query as "sub-register" + ULONG64 getSubValue(ULONG cvRegId) const; + private: typedef std::map RegValues; RegValues m_regValues; diff --git a/pykd/dbgext.cpp b/pykd/dbgext.cpp index 95f1505..22b8aaf 100644 --- a/pykd/dbgext.cpp +++ b/pykd/dbgext.cpp @@ -604,6 +604,8 @@ BOOST_PYTHON_MODULE( pykd ) "Get current stack pointer" ) .def( "get", &Ctx::Registers::getValue, "Get register value by ID (CV_REG_XXX)" ) + .def( "processorType", &Ctx::Registers::getProcessorType, + "Get processor type as string") .def("__len__", &Ctx::Registers::getCount, "Return count of registers") .def("__getitem__", &Ctx::Registers::getByIndex, diff --git a/pykd/process.cpp b/pykd/process.cpp index 1f58d5e..ac6a817 100644 --- a/pykd/process.cpp +++ b/pykd/process.cpp @@ -78,7 +78,7 @@ getCurrentStack() /////////////////////////////////////////////////////////////////////////////////// -static std::string processorToStr(ULONG processorMode) +std::string processorToStr(ULONG processorMode) { switch( processorMode ) { diff --git a/test/scripts/clienttest.py b/test/scripts/clienttest.py index a004fc9..29cfdee 100644 --- a/test/scripts/clienttest.py +++ b/test/scripts/clienttest.py @@ -26,15 +26,25 @@ class DbgClientTest( unittest.TestCase ): ctx = pykd.getContext() # for reg in ctx: # regName = "" -# try: +# if ctx.processorType() == "X86": # regName = pykd.diaI386Regs[ reg[0] ] -# except KeyError: +# else: # 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() ) + 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 ): self.assertFalse( pykd.isDumpAnalyzing() )