From 0768ce3fe3bd3bb21c1e039f8b3f1c5bf53089c8 Mon Sep 17 00:00:00 2001
From: "SND\\kernelnet_cp"
 <SND\kernelnet_cp@9b283d60-5439-405e-af05-b73fd8c4d996>
Date: Mon, 23 Jan 2012 07:50:36 +0000
Subject: [PATCH] [0.1.x] added : cpuReg class [0.1.x] refactored :
 context.cpp/h

git-svn-id: https://pykd.svn.codeplex.com/svn@73463 9b283d60-5439-405e-af05-b73fd8c4d996
---
 pykd/context.cpp | 287 +++++++++++++++++++++--------------------------
 pykd/context.h   |  40 +++----
 pykd/cpureg.cpp  | 140 ++++++++++++++++-------
 pykd/cpureg.h    |  32 +++++-
 pykd/dbgclient.h |  16 ++-
 pykd/dbgext.cpp  |  32 +++---
 pykd/intbase.h   |   5 +
 pykd/livevar.cpp |   4 +-
 pykd/pykdver.h   |  11 +-
 9 files changed, 311 insertions(+), 256 deletions(-)

diff --git a/pykd/context.cpp b/pykd/context.cpp
index 2c2cfab..c39550a 100644
--- a/pykd/context.cpp
+++ b/pykd/context.cpp
@@ -7,9 +7,9 @@
 
 /////////////////////////////////////////////////////////////////////////////////
 
-namespace Ctx {
-
-/////////////////////////////////////////////////////////////////////////////////
+namespace pykd {
+    
+////////////////////////////////////////////////////////////////////////////////
 
 namespace I386 {
 #include "defctxi386.h"
@@ -17,15 +17,13 @@ namespace I386 {
 
 /////////////////////////////////////////////////////////////////////////////////
 
-void Registers::getI386Context(
-    IDebugAdvanced2 *advanced
-)
+void ThreadContext::getI386Context()
 {
     I386::CONTEXT Context = {0};
 
-    HRESULT hres = advanced->GetThreadContext(&Context, sizeof(Context));
+    HRESULT hres = m_advanced->GetThreadContext(&Context, sizeof(Context));
     if (S_OK != hres)
-        throw Exception( "IDebugAdvanced2::GetThreadContext", hres );
+        throw DbgException( "IDebugAdvanced2::GetThreadContext", hres );
 
     m_regValues[CV_REG_DR0] = Context.Dr0;
     m_regValues[CV_REG_DR1] = Context.Dr1;
@@ -65,15 +63,13 @@ namespace AMD64 {
 
 /////////////////////////////////////////////////////////////////////////////////
 
-void Registers::getAmd64Context(
-    IDebugAdvanced2 *advanced
-)
+void ThreadContext::getAmd64Context()
 {
     AMD64::CONTEXT Context = {0};
 
-    HRESULT hres = advanced->GetThreadContext(&Context, sizeof(Context));
+    HRESULT hres = m_advanced->GetThreadContext(&Context, sizeof(Context));
     if (S_OK != hres)
-        throw Exception( "IDebugAdvanced2::GetThreadContext", hres);
+        throw DbgException( "IDebugAdvanced2::GetThreadContext", hres);
 
     m_regValues[CV_AMD64_MXCSR] = Context.MxCsr;
 
@@ -115,66 +111,48 @@ void Registers::getAmd64Context(
 
 /////////////////////////////////////////////////////////////////////////////////
 
-Registers::Registers(
-    IDebugControl4 *control,
-    IDebugAdvanced2 *advanced
-)
+ThreadContext::ThreadContext( IDebugClient4 *client ) :
+    pykd::DbgObject( client )
 {
-    HRESULT hres = control->GetExecutingProcessorType(&m_processorType);
+    HRESULT hres = m_control->GetExecutingProcessorType(&m_processorType);
     if (S_OK != hres)
-        throw Exception( "IDebugControl::GetExecutingProcessorType", hres );
+        throw DbgException( "IDebugControl::GetExecutingProcessorType", hres );
 
     switch (m_processorType)
     {
     case IMAGE_FILE_MACHINE_I386:
-        getI386Context(advanced);
+        getI386Context();
         return;
 
     case IMAGE_FILE_MACHINE_AMD64:
-        getAmd64Context(advanced);
+        getAmd64Context();
         return;
     }
 
     std::stringstream sstream;
     sstream << __FUNCTION__ << ":\n";
     sstream << "Unsupported processor type: 0x" << std::hex << m_processorType;
-    throw Exception( sstream.str() );
+    throw DbgException( sstream.str() );
 }
 
 /////////////////////////////////////////////////////////////////////////////////
 
-ULONG64 Registers::getValue(ULONG cvRegId) const
+ULONG64 ThreadContext::getValue(ULONG cvRegId) const
 {
-    try
-    {
-        return getSubValue(cvRegId);
-    }
-    catch (const IsNotSubRegister &)
-    {
-    }
+    ULONG64  val;
 
-    RegValues::const_iterator it = m_regValues.find(cvRegId);
-    if (it == m_regValues.end())
-        throw Exception(__FUNCTION__ ": Register missing");
-    return it->second;
+    if ( getValueNoThrow( cvRegId, val ) )
+        return val;
+
+    throw DbgException(__FUNCTION__ ": Register missing");
 }
 
-/////////////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////////
 
-bool Registers::getValueNoThrow(ULONG cvRegId, ULONG64 &val) const
+bool ThreadContext::getValueNoThrow(ULONG cvRegId, ULONG64 &val) const
 {
-    try
-    {
-        val = getSubValue(cvRegId);
+    if ( getSubValue(cvRegId, val ) )
         return true;
-    }
-    catch (const IsNotSubRegister &)
-    {
-    }
-    catch (const Exception &)
-    {
-        return false;
-    }
 
     RegValues::const_iterator it = m_regValues.find(cvRegId);
     if (it == m_regValues.end())
@@ -184,9 +162,9 @@ bool Registers::getValueNoThrow(ULONG cvRegId, ULONG64 &val) const
     return true;
 }
 
-/////////////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////////
 
-ULONG64 Registers::getIp() const
+ULONG64 ThreadContext::getIp() const
 {
     return getValue(
         IMAGE_FILE_MACHINE_I386 == m_processorType ? CV_REG_EIP : CV_AMD64_RIP
@@ -195,7 +173,7 @@ ULONG64 Registers::getIp() const
 
 /////////////////////////////////////////////////////////////////////////////////
 
-ULONG64 Registers::getRetReg() const
+ULONG64 ThreadContext::getRetReg() const
 {
     return getValue(
         IMAGE_FILE_MACHINE_I386 == m_processorType ? CV_REG_EAX : CV_AMD64_RAX
@@ -204,7 +182,7 @@ ULONG64 Registers::getRetReg() const
 
 /////////////////////////////////////////////////////////////////////////////////
 
-ULONG64 Registers::getSp() const
+ULONG64 ThreadContext::getSp() const
 {
     return getValue(
         IMAGE_FILE_MACHINE_I386 == m_processorType ? CV_REG_ESP : CV_AMD64_RSP
@@ -213,7 +191,7 @@ ULONG64 Registers::getSp() const
 
 /////////////////////////////////////////////////////////////////////////////////
 
-python::object Registers::getByIndex(ULONG ind) const
+python::object ThreadContext::getByIndex(ULONG ind) const
 {
     RegValues::const_iterator it = m_regValues.begin();
     for (ULONG i = 0; it != m_regValues.end(); ++i, ++it )
@@ -222,10 +200,7 @@ python::object Registers::getByIndex(ULONG ind) const
             return python::make_tuple(it->first, it->second);
     }
 
-    PyErr_SetString(PyExc_IndexError, "Index out of range");
-    python::throw_error_already_set();
-
-    return python::object();
+    throw PyException( PyExc_IndexError, "Index out of range");
 }
 
 /////////////////////////////////////////////////////////////////////////////////
@@ -243,109 +218,110 @@ struct SubRegister {
 
 /////////////////////////////////////////////////////////////////////////////////
 
-static const class SubRegisterMapI386 : public std::map<ULONG, SubRegister> {
-public:
-    SubRegisterMapI386();
-} g_SubRegistersI386;
+
+struct SubRegisterMapI386 {
+
+    std::map<ULONG, SubRegister>        subRegs;
+
+    SubRegisterMapI386()
+    {
+        subRegs[CV_REG_AL].set(CV_REG_EAX, 0x00, 0xff);
+        subRegs[CV_REG_CL].set(CV_REG_ECX, 0x00, 0xff);
+        subRegs[CV_REG_DL].set(CV_REG_EDX, 0x00, 0xff);
+        subRegs[CV_REG_BL].set(CV_REG_EBX, 0x00, 0xff);
+
+        subRegs[CV_REG_AH].set(CV_REG_EAX, 0x08, 0xff);
+        subRegs[CV_REG_CH].set(CV_REG_ECX, 0x08, 0xff);
+        subRegs[CV_REG_DH].set(CV_REG_EDX, 0x08, 0xff);
+        subRegs[CV_REG_BH].set(CV_REG_EBX, 0x08, 0xff);
+
+        subRegs[CV_REG_AX].set(CV_REG_EAX, 0x00, 0xffff);
+        subRegs[CV_REG_CX].set(CV_REG_ECX, 0x00, 0xffff);
+        subRegs[CV_REG_DX].set(CV_REG_EDX, 0x00, 0xffff);
+        subRegs[CV_REG_BX].set(CV_REG_EBX, 0x00, 0xffff);
+
+        subRegs[CV_REG_SP].set(CV_REG_ESP, 0x00, 0xffff);
+        subRegs[CV_REG_BP].set(CV_REG_EBP, 0x00, 0xffff);
+        subRegs[CV_REG_SI].set(CV_REG_ESI, 0x00, 0xffff);
+        subRegs[CV_REG_DI].set(CV_REG_EDI, 0x00, 0xffff);
+    }
+
+};
+
+static const std::map<ULONG, SubRegister>  g_SubRegistersI386 = SubRegisterMapI386().subRegs;
 
 /////////////////////////////////////////////////////////////////////////////////
 
-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);
+struct SubRegisterMapAmd64 {
 
-    (*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);
+    std::map<ULONG, SubRegister>        subRegs; 
 
-    (*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);
+    SubRegisterMapAmd64()
+    {
+        subRegs[CV_AMD64_AL].set(CV_AMD64_RAX, 0x00, 0xff);
+        subRegs[CV_AMD64_CL].set(CV_AMD64_RCX, 0x00, 0xff);
+        subRegs[CV_AMD64_DL].set(CV_AMD64_RDX, 0x00, 0xff);
+        subRegs[CV_AMD64_BL].set(CV_AMD64_RBX, 0x00, 0xff);
 
-    (*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);
+        subRegs[CV_AMD64_AH].set(CV_AMD64_RAX, 0x08, 0xff);
+        subRegs[CV_AMD64_CH].set(CV_AMD64_RCX, 0x08, 0xff);
+        subRegs[CV_AMD64_DH].set(CV_AMD64_RDX, 0x08, 0xff);
+        subRegs[CV_AMD64_BH].set(CV_AMD64_RBX, 0x08, 0xff);
 
-}
+        subRegs[CV_AMD64_AX].set(CV_AMD64_RAX, 0x00, 0xffff);
+        subRegs[CV_AMD64_CX].set(CV_AMD64_RCX, 0x00, 0xffff);
+        subRegs[CV_AMD64_DX].set(CV_AMD64_RDX, 0x00, 0xffff);
+        subRegs[CV_AMD64_BX].set(CV_AMD64_RBX, 0x00, 0xffff);
+
+        subRegs[CV_AMD64_SP].set(CV_AMD64_RSP, 0x00, 0xffff);
+        subRegs[CV_AMD64_BP].set(CV_AMD64_RBP, 0x00, 0xffff);
+        subRegs[CV_AMD64_SI].set(CV_AMD64_RSI, 0x00, 0xffff);
+        subRegs[CV_AMD64_DI].set(CV_AMD64_RDI, 0x00, 0xffff);
+
+        subRegs[CV_AMD64_EAX].set(CV_AMD64_RAX, 0x00, 0xffffffff);
+        subRegs[CV_AMD64_ECX].set(CV_AMD64_RCX, 0x00, 0xffffffff);
+        subRegs[CV_AMD64_EDX].set(CV_AMD64_RDX, 0x00, 0xffffffff);
+        subRegs[CV_AMD64_EBX].set(CV_AMD64_RBX, 0x00, 0xffffffff);
+
+        subRegs[CV_AMD64_ESP].set(CV_AMD64_RSP, 0x00, 0xffffffff);
+        subRegs[CV_AMD64_EBP].set(CV_AMD64_RBP, 0x00, 0xffffffff);
+        subRegs[CV_AMD64_ESI].set(CV_AMD64_RSI, 0x00, 0xffffffff);
+        subRegs[CV_AMD64_EDI].set(CV_AMD64_RDI, 0x00, 0xffffffff);
+
+        subRegs[CV_AMD64_R8B].set(CV_AMD64_R8, 0x00, 0xff);
+        subRegs[CV_AMD64_R9B].set(CV_AMD64_R9, 0x00, 0xff);
+        subRegs[CV_AMD64_R10B].set(CV_AMD64_R10, 0x00, 0xff);
+        subRegs[CV_AMD64_R11B].set(CV_AMD64_R11, 0x00, 0xff);
+        subRegs[CV_AMD64_R12B].set(CV_AMD64_R12, 0x00, 0xff);
+        subRegs[CV_AMD64_R13B].set(CV_AMD64_R13, 0x00, 0xff);
+        subRegs[CV_AMD64_R14B].set(CV_AMD64_R14, 0x00, 0xff);
+        subRegs[CV_AMD64_R15B].set(CV_AMD64_R15, 0x00, 0xff);
+
+        subRegs[CV_AMD64_R8W].set(CV_AMD64_R8, 0x00, 0xffff);
+        subRegs[CV_AMD64_R9W].set(CV_AMD64_R9, 0x00, 0xffff);
+        subRegs[CV_AMD64_R10W].set(CV_AMD64_R10, 0x00, 0xffff);
+        subRegs[CV_AMD64_R11W].set(CV_AMD64_R11, 0x00, 0xffff);
+        subRegs[CV_AMD64_R12W].set(CV_AMD64_R12, 0x00, 0xffff);
+        subRegs[CV_AMD64_R13W].set(CV_AMD64_R13, 0x00, 0xffff);
+        subRegs[CV_AMD64_R14W].set(CV_AMD64_R14, 0x00, 0xffff);
+        subRegs[CV_AMD64_R15W].set(CV_AMD64_R15, 0x00, 0xffff);
+
+        subRegs[CV_AMD64_R8D].set(CV_AMD64_R8, 0x00, 0xffffffff);
+        subRegs[CV_AMD64_R9D].set(CV_AMD64_R9, 0x00, 0xffffffff);
+        subRegs[CV_AMD64_R10D].set(CV_AMD64_R10, 0x00, 0xffffffff);
+        subRegs[CV_AMD64_R11D].set(CV_AMD64_R11, 0x00, 0xffffffff);
+        subRegs[CV_AMD64_R12D].set(CV_AMD64_R12, 0x00, 0xffffffff);
+        subRegs[CV_AMD64_R13D].set(CV_AMD64_R13, 0x00, 0xffffffff);
+        subRegs[CV_AMD64_R14D].set(CV_AMD64_R14, 0x00, 0xffffffff);
+        subRegs[CV_AMD64_R15D].set(CV_AMD64_R15, 0x00, 0xffffffff);
+    }
+};
+
+static const  std::map<ULONG, SubRegister>   g_SubRegistersAmd64 = SubRegisterMapAmd64().subRegs;
 
 /////////////////////////////////////////////////////////////////////////////////
 
-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
+bool ThreadContext::getSubValue(ULONG cvRegId, ULONG64 &val) const
 {
     const std::map<ULONG, SubRegister> *subRegs = NULL;
     if (IMAGE_FILE_MACHINE_I386 == m_processorType)
@@ -356,18 +332,17 @@ ULONG64 Registers::getSubValue(ULONG cvRegId) const
     std::map<ULONG, SubRegister>::const_iterator itSubReg = 
         subRegs->find(cvRegId);
     if (itSubReg == subRegs->end())
-        throw IsNotSubRegister();
+       return false;
 
     RegValues::const_iterator itFullReg = m_regValues.find(itSubReg->second.m_fromReg);
     if (itFullReg == m_regValues.end())
-        throw Exception(__FUNCTION__ ": Register missing");
+        return false;
 
-    return 
-        (itFullReg->second >> itSubReg->second.m_bitsShift) & itSubReg->second.m_bitsMask;
-}
-
-// ----------------------------------------------------------------------------
+    val = (itFullReg->second >> itSubReg->second.m_bitsShift) & itSubReg->second.m_bitsMask;
 
+    return true;
 }
 
 /////////////////////////////////////////////////////////////////////////////////
+
+}
diff --git a/pykd/context.h b/pykd/context.h
index 7753fd2..32e7c32 100644
--- a/pykd/context.h
+++ b/pykd/context.h
@@ -1,31 +1,24 @@
+#pragma once
 
 #include <map>
 #include <DbgEng.h>
 #include <CvConst.h>
 
+#include "context.h"
+#include "dbgobj.h"
 #include "dbgexcept.h"
 
-#pragma once
+namespace pykd {
 
-namespace pykd{
-    std::string processorToStr(ULONG processorMode);
-}
-
-namespace Ctx {
+std::string processorToStr(ULONG processorMode);
 
 ////////////////////////////////////////////////////////////////////////////////
 
-typedef pykd::DbgException Exception;
-
-////////////////////////////////////////////////////////////////////////////////
-
-class Registers
+class ThreadContext : private DbgObject
 {
 public:
-    Registers(
-        IDebugControl4 *control,
-        IDebugAdvanced2 *advanced
-    );
+
+    ThreadContext( IDebugClient4 *client );
 
     // get register value by ID
     ULONG64 getValue(ULONG cvRegId) const;
@@ -44,6 +37,7 @@ public:
     ULONG getCount() const {
         return static_cast<ULONG>( m_regValues.size() );
     }
+
     python::object getByIndex(ULONG ind) const;
 
     // get processor type
@@ -53,22 +47,14 @@ public:
 
 private:
 
-    struct IsNotSubRegister : public std::exception {
-        IsNotSubRegister() : std::exception("is not sub-register") { }
-    };
-
     // query i386 registers
-    void getI386Context(
-        IDebugAdvanced2 *advanced
-    );
+    void getI386Context();
 
     // query AMD64 registers
-    void getAmd64Context(
-        IDebugAdvanced2 *advanced
-    );
+    void getAmd64Context();
 
     // try query as "sub-register"
-    ULONG64 getSubValue(ULONG cvRegId) const;
+    bool getSubValue(ULONG cvRegId, ULONG64 &val) const;
 
 private:
     typedef std::map<ULONG, ULONG64> RegValues;
@@ -79,7 +65,7 @@ private:
 
 ////////////////////////////////////////////////////////////////////////////////
 
-typedef boost::shared_ptr< Registers > ContextPtr;
+typedef boost::shared_ptr< ThreadContext > ContextPtr;
 
 ////////////////////////////////////////////////////////////////////////////////
 
diff --git a/pykd/cpureg.cpp b/pykd/cpureg.cpp
index ee61890..0e22591 100644
--- a/pykd/cpureg.cpp
+++ b/pykd/cpureg.cpp
@@ -7,60 +7,114 @@ namespace pykd {
 
 ///////////////////////////////////////////////////////////////////////////////////
 
-python::object DebugClient::getRegByIndex( ULONG index )
+CpuReg::CpuReg( IDebugClient4 *client, const std::string &regName ) :
+    DbgObject( client )  
 {
-    HRESULT         hres;
+    HRESULT         hres;  
 
-    DEBUG_VALUE    debugValue;            
-    hres = m_registers->GetValue( index, &debugValue );
+    m_name = regName;
+
+    hres = m_registers->GetIndexByName( m_name.c_str(), &m_index );
     if ( FAILED( hres ) )
-        throw DbgException( "IDebugRegister::GetValue  failed" );
-        
-    switch( debugValue.Type )
-    {
-    case DEBUG_VALUE_INT8:
-        return boost::python::long_( debugValue.I8 );
-        break;
-        
-    case DEBUG_VALUE_INT16:
-        return boost::python::long_( debugValue.I16 );
-        break;
-        
-    case DEBUG_VALUE_INT32:
-        return boost::python::long_( debugValue.I32 );
-        break;
-        
-    case DEBUG_VALUE_INT64:
-        return boost::python::long_(debugValue.I64 );
-        break;
-   }
-
-   throw DbgException( "Invalid register value" );  
-}
-
-python::object getRegByIndex( ULONG index )
-{
-    return g_dbgClient->getRegByIndex( index );  
+        throw DbgException( "IDebugRegister::GetIndexByName", hres );    
 }
 
 ///////////////////////////////////////////////////////////////////////////////////
 
-
-python::object DebugClient::getRegByName( const std::wstring &regName )
+CpuReg::CpuReg( IDebugClient4 *client, ULONG index ) :
+    DbgObject( client )  
 {
-    ULONG       registerIndex = 0;
-    HRESULT     hres;
+    HRESULT         hres;  
+
+    m_index = index;
+
+    ULONG       nameSize = 0;
+
+    hres = 
+       m_registers->GetDescription( 
+            m_index,
+            NULL,
+            0,
+            &nameSize,
+            NULL );
 
-    hres = m_registers->GetIndexByNameWide( regName.c_str(), &registerIndex );
     if ( FAILED( hres ) )
-        throw DbgException( "IDebugRegister2::GetIndexByNameWide  failed" );
+        throw DbgException( "IDebugRegister::GetDescription", hres );
 
-    return getRegByIndex( registerIndex );
-}        
+    std::vector<char>   nameBuffer(nameSize);
 
-python::object getRegByName( const std::wstring &regName )
+    hres = 
+        m_registers->GetDescription( 
+            m_index,
+            &nameBuffer[0],
+            nameSize,
+            NULL,
+            NULL );
+
+    if ( FAILED( hres ) )
+        throw DbgException( "IDebugRegister::GetDescription", hres );
+
+    m_name = std::string( &nameBuffer[0] );
+    
+}
+
+///////////////////////////////////////////////////////////////////////////////////
+
+BaseTypeVariant CpuReg::getValue()
 {
-    return g_dbgClient->getRegByName( regName );
+    HRESULT         hres;   
+        
+    DEBUG_VALUE    debugValue;            
+    hres = m_registers->GetValue( m_index, &debugValue );
+    if ( FAILED( hres ) )
+        throw DbgException( "IDebugRegister::GetValue", hres );
+        
+    switch( debugValue.Type )
+    {
+    case DEBUG_VALUE_INT8:
+        return BaseTypeVariant( (LONG)debugValue.I8 );
+        break;
+        
+    case DEBUG_VALUE_INT16:
+        return BaseTypeVariant( (LONG)debugValue.I16 );
+        break;
+        
+    case DEBUG_VALUE_INT32:
+        return BaseTypeVariant( debugValue.I32 );
+        break;
+        
+    case DEBUG_VALUE_INT64:
+        return BaseTypeVariant( debugValue.I64 );
+        break;
+    } 
+
+    throw DbgException( "Failed to convert register value" );
+}
+
+///////////////////////////////////////////////////////////////////////////////////
+
+CpuReg DebugClient::getRegByName( const std::string &regName )
+{
+     return CpuReg( m_client, regName );  
+}
+
+
+CpuReg getRegByName( const std::string &regName )
+{
+     return g_dbgClient->getRegByName( regName );
+}
+
+///////////////////////////////////////////////////////////////////////////////////
+
+CpuReg DebugClient::getRegByIndex( ULONG index )
+{
+    return CpuReg( m_client, index );
+}
+
+
+CpuReg getRegByIndex( ULONG index )
+{
+    return g_dbgClient->getRegByIndex( index );
 }
 
 ///////////////////////////////////////////////////////////////////////////////////
@@ -72,7 +126,7 @@ ULONG64 DebugClient::loadMSR( ULONG  msr )
 
     hres = m_dataSpaces->ReadMsr( msr, &value );
     if ( FAILED( hres ) )
-         throw DbgException( "IDebugDataSpaces::ReadMsr  failed" );
+         throw DbgException( "IDebugDataSpaces::ReadMsr", hres );
 
     return value;
 }
@@ -90,7 +144,7 @@ void DebugClient::setMSR( ULONG msr, ULONG64 value)
 
     hres = m_dataSpaces->WriteMsr(msr, value);
     if ( FAILED( hres ) )
-         throw DbgException( "IDebugDataSpaces::WriteMsr  failed" );
+         throw DbgException( "IDebugDataSpaces::WriteMsr", hres );
 }
 
 void setMSR( ULONG msr, ULONG64 value)
diff --git a/pykd/cpureg.h b/pykd/cpureg.h
index 05b445d..d8bd3d4 100644
--- a/pykd/cpureg.h
+++ b/pykd/cpureg.h
@@ -7,9 +7,37 @@ namespace pykd {
 
 ///////////////////////////////////////////////////////////////////////////////////
 
-python::object getRegByName( const std::wstring &regName );
+class CpuReg : public intBase, protected DbgObject {
 
-python::object getRegByIndex( ULONG index );
+public:
+
+    CpuReg( IDebugClient4 *client, const std::string &regName );
+
+    CpuReg( IDebugClient4 *client, ULONG index );
+
+    std::string
+    name() const {
+        return m_name;
+    }
+
+    ULONG index() const {
+        return m_index;
+    }
+
+    virtual BaseTypeVariant getValue();
+
+private:
+
+    std::string     m_name;
+
+    ULONG           m_index;
+};
+
+///////////////////////////////////////////////////////////////////////////////////
+
+CpuReg getRegByName( const std::string &regName );
+
+CpuReg getRegByIndex( ULONG index );
 
 ULONG64 loadMSR( ULONG  msr );
 
diff --git a/pykd/dbgclient.h b/pykd/dbgclient.h
index 1661cbc..9282556 100644
--- a/pykd/dbgclient.h
+++ b/pykd/dbgclient.h
@@ -210,9 +210,9 @@ public:
 
     void setMSR( ULONG msr, ULONG64 value);
     
-    python::object getRegByName( const std::wstring &regName );
+    CpuReg getRegByName( const std::string &regName );
 
-    python::object getRegByIndex( ULONG index );
+    CpuReg getRegByIndex( ULONG index );
 
     void setCurrentProcess( ULONG64 addr );
 
@@ -234,14 +234,12 @@ public:
         return getDbgControl(GetPageSize);
     }
 
-    Ctx::ContextPtr getThreadContext() {
-        return Ctx::ContextPtr(
-            new Ctx::Registers(m_control, m_advanced)
-        );
+    ContextPtr getThreadContext() {
+        return ContextPtr( new ThreadContext(m_client) );
     }
 
     python::dict getLocals(
-        Ctx::ContextPtr ctx = Ctx::ContextPtr( reinterpret_cast<Ctx::Registers *>(0) ) 
+        ContextPtr ctx = ContextPtr( reinterpret_cast<ThreadContext*>(0) ) 
     );
 public:
 
@@ -397,12 +395,12 @@ inline ULONG getPageSize() {
     return g_dbgClient->getPageSize();
 }
 
-inline Ctx::ContextPtr getThreadContext() {
+inline ContextPtr getThreadContext() {
     return g_dbgClient->getThreadContext();
 }
 
 inline python::dict getLocals(
-    Ctx::ContextPtr ctx = Ctx::ContextPtr( reinterpret_cast<Ctx::Registers *>(0) )
+    ContextPtr ctx = ContextPtr()
 )
 {
     return g_dbgClient->getLocals(ctx);
diff --git a/pykd/dbgext.cpp b/pykd/dbgext.cpp
index 41213dd..d47a17b 100644
--- a/pykd/dbgext.cpp
+++ b/pykd/dbgext.cpp
@@ -143,7 +143,8 @@ BOOST_PYTHON_MODULE( pykd )
         .def( "__long__", &intBase::long_ )
         .def( "__int__", &intBase::int_ )
         .def( "__index__", &intBase::long_ )
-        .def( "__hash__", &intBase::long_ );
+        .def( "__hash__", &intBase::long_ )
+        .def( "__coerce__", &intBase::coerce );
 
     python::class_<DebugClient, DebugClientPtr>("dbgClient", "Class representing a debugging session", python::no_init  )
         .def( "addr64", &DebugClient::addr64,
@@ -442,11 +443,11 @@ BOOST_PYTHON_MODULE( pykd )
     python::def( "ptrSize", &ptrSize,
         "Return effective pointer size" );
     python::def ( "rdmsr", &DebugClient::loadMSR,
-            "Return MSR value" );
+        "Return MSR value" );
     python::def( "reg", &getRegByName,
         "Return a CPU regsiter value by the register's name" );
     python::def( "reg", &getRegByIndex,
-         "Return a CPU regsiter value by the register's value" );
+        "Return a CPU regsiter value by the register's value" );
     python::def( "setExecutionStatus",  &setExecutionStatus,
         "Requests that the debugger engine enter an executable state" );
     python::def( "setCurrentProcess", &setCurrentProcess, 
@@ -599,7 +600,7 @@ BOOST_PYTHON_MODULE( pykd )
         .def( "ea", &Disasm::ea, "Return effective address for last disassembled instruction or 0" )
         .def( "reset", &Disasm::reset, "Reset current offset to begin" );
 
-   python::class_<DEBUG_STACK_FRAME>( "stackFrame", 
+    python::class_<DEBUG_STACK_FRAME>( "stackFrame", 
          "Class representing a frame of the call satck", python::no_init )
         .def_readonly( "instructionOffset", &DEBUG_STACK_FRAME::InstructionOffset,
             "Return a frame's instruction offset" )
@@ -612,23 +613,28 @@ BOOST_PYTHON_MODULE( pykd )
         .def_readonly( "frameNumber", &DEBUG_STACK_FRAME::FrameNumber,
             "Return a frame's number" );
 
-   python::class_<Ctx::Registers, Ctx::ContextPtr>(
+    python::class_<ThreadContext, ContextPtr>(
         "Context", "Context of thread (register values)", python::no_init )
-        .def( "ip", &Ctx::Registers::getIp, 
+        .def( "ip", &ThreadContext::getIp, 
             "Get instruction pointer register" )
-        .def( "retreg", &Ctx::Registers::getIp, 
+        .def( "retreg", &ThreadContext::getIp, 
             "Get primary return value register" )
-        .def( "csp", &Ctx::Registers::getSp, 
+        .def( "csp", &ThreadContext::getSp, 
             "Get current stack pointer" )
-        .def( "get", &Ctx::Registers::getValue, 
+        .def( "get", &ThreadContext::getValue, 
             "Get register value by ID (CV_REG_XXX)" )
-        .def( "processorType", &Ctx::Registers::getProcessorType,
-            "Get processor type as string")
-        .def("__len__", &Ctx::Registers::getCount,
+        .def( "processorType", &ThreadContext::getProcessorType,
+            "Get processor ThreadContext as string")
+        .def("__len__", &ThreadContext::getCount,
             "Return count of registers")
-        .def("__getitem__", &Ctx::Registers::getByIndex,
+        .def("__getitem__", &ThreadContext::getByIndex,
             "Return tuple<ID, VALUE> by index");
 
+    python::class_<CpuReg, python::bases<intBase> >( 
+        "cpuReg", "CPU regsiter class", boost::python::no_init )
+            .def( "name", &CpuReg::name, "The name of the regsiter" )
+            .def( "index", &CpuReg::index, "The index of thr register" );
+
     python::def( "diaLoadPdb", &pyDia::GlobalScope::loadPdb, 
         "Open pdb file for querying debug symbols. Return DiaSymbol of global scope");
 
diff --git a/pykd/intbase.h b/pykd/intbase.h
index 4fb81ea..302880e 100644
--- a/pykd/intbase.h
+++ b/pykd/intbase.h
@@ -185,6 +185,11 @@ public:
         return boost::apply_visitor( VariantToPyobj(), getValue() ) != 0;
     }
 
+    python::object coerce() {
+        __debugbreak();
+        return python::object();
+    }
+
 private:
 
     virtual BaseTypeVariant getValue() {
diff --git a/pykd/livevar.cpp b/pykd/livevar.cpp
index 3996b80..3b44d3d 100644
--- a/pykd/livevar.cpp
+++ b/pykd/livevar.cpp
@@ -19,7 +19,7 @@ struct addLocals {
     python::dict &m_locals;
     const Module &m_module;
     ULONG m_rva;
-    Ctx::ContextPtr m_ctx;
+    ContextPtr m_ctx;
     IDebugClient4 *m_client;
     ULONG m_formalNameCounter;
 
@@ -181,7 +181,7 @@ static bool isOutOfDebugRange(
 
 ////////////////////////////////////////////////////////////////////////////////
 
-python::dict DebugClient::getLocals(Ctx::ContextPtr ctx OPTIONAL)
+python::dict DebugClient::getLocals(ContextPtr ctx OPTIONAL)
 {
     if (!ctx)
         ctx = getThreadContext();
diff --git a/pykd/pykdver.h b/pykd/pykdver.h
index 47fef54..595c7d0 100644
--- a/pykd/pykdver.h
+++ b/pykd/pykdver.h
@@ -1,11 +1,14 @@
 
+#define PYKD_VERSION_MAJOR      0
+#define PYKD_VERSION_MINOR      1
+#define PYKD_VERSION_SUBVERSION 0
+#define PYKD_VERSION_BUILDNO    6
+
+
 #define __VER_STR2__(x) #x
 #define __VER_STR1__(x) __VER_STR2__(x)
 
-#define PYKD_VERSION_MAJOR      1
-#define PYKD_VERSION_MINOR      6
-
-#define PYKD_VERSION_BUILD      0,PYKD_VERSION_MAJOR,0,PYKD_VERSION_MINOR
+#define PYKD_VERSION_BUILD      PYKD_VERSION_MAJOR, PYKD_VERSION_MINOR, PYKD_VERSION_SUBVERSION, PYKD_VERSION_BUILDNO
 
 #define PYKD_VERSION_BUILD_STR  __VER_STR1__(PYKD_VERSION_BUILD)