diff --git a/pykd/context.h b/pykd/context.h index 2196bd1..53db942 100644 --- a/pykd/context.h +++ b/pykd/context.h @@ -1,7 +1,6 @@ #pragma once #include <map> -#include <DbgEng.h> #include <CvConst.h> #include "context.h" diff --git a/pykd/dbgclient.h b/pykd/dbgclient.h index b0fab1e..e9c5f88 100644 --- a/pykd/dbgclient.h +++ b/pykd/dbgclient.h @@ -1,7 +1,6 @@ #pragma once #include <string> -#include <dbgeng.h> #include <dbghelp.h> #include <boost\smart_ptr\scoped_ptr.hpp> diff --git a/pykd/dbgevent.h b/pykd/dbgevent.h index b8d1a18..893c7a6 100644 --- a/pykd/dbgevent.h +++ b/pykd/dbgevent.h @@ -6,7 +6,6 @@ #include "stdafx.h" -#include <dbgeng.h> #include "dbgobj.h" #include "module.h" #include "dbgclient.h" diff --git a/pykd/dbgext.cpp b/pykd/dbgext.cpp index 9e962ac..e00dae1 100644 --- a/pykd/dbgext.cpp +++ b/pykd/dbgext.cpp @@ -1,6 +1,5 @@ #include "stdafx.h" -#include <dbgeng.h> #include <dia2.h> #include <boost/tokenizer.hpp> diff --git a/pykd/dbgmem.h b/pykd/dbgmem.h index 413d416..a1b5070 100644 --- a/pykd/dbgmem.h +++ b/pykd/dbgmem.h @@ -1,7 +1,5 @@ #pragma once -#include <dbgeng.h> - namespace pykd { /////////////////////////////////////////////////////////////////////////////////// diff --git a/pykd/dbgobj.h b/pykd/dbgobj.h index 93f2832..9b3211f 100644 --- a/pykd/dbgobj.h +++ b/pykd/dbgobj.h @@ -1,6 +1,5 @@ #pragma once -#include <dbgeng.h> #include "dbgexcept.h" #include "synsymbol.h" @@ -49,8 +48,8 @@ protected: virtual ~DbgObject() {}; - CComPtr<IDebugClient5> m_client5; - CComPtr<IDebugClient4> m_client; + CComPtr<IDebugClient5> m_client5; + CComPtr<IDebugClient4> m_client; CComPtr<IDebugControl4> m_control; CComPtr<IDebugSymbols3> m_symbols; CComPtr<IDebugAdvanced2> m_advanced; diff --git a/pykd/diawrapper.cpp b/pykd/diawrapper.cpp index 09709af..c04bd26 100644 --- a/pykd/diawrapper.cpp +++ b/pykd/diawrapper.cpp @@ -207,7 +207,7 @@ python::object Symbol::getValue() case VT_I8: case VT_UI8: - return python::object( float(vtValue.llVal) ); + return python::object( vtValue.llVal ); case VT_R4: return python::object( double(vtValue.fltVal) ); diff --git a/pykd/inteventhandler.h b/pykd/inteventhandler.h index d52d13e..b9dfcb7 100644 --- a/pykd/inteventhandler.h +++ b/pykd/inteventhandler.h @@ -4,7 +4,6 @@ #pragma once -#include <DbgEng.h> #include "synsymbol.h" //////////////////////////////////////////////////////////////////////////////// diff --git a/pykd/livevar.cpp b/pykd/livevar.cpp index 3b44d3d..435320f 100644 --- a/pykd/livevar.cpp +++ b/pykd/livevar.cpp @@ -22,6 +22,7 @@ struct addLocals { ContextPtr m_ctx; IDebugClient4 *m_client; ULONG m_formalNameCounter; + CComPtr< IDebugDataSpaces4 > m_dataSpaces; void append(pyDia::SymbolPtr symParent); @@ -139,7 +140,7 @@ TypedVarPtr addLocals::getTypeVarByOffset( TypeInfoPtr typeInfo = TypeInfo::getTypeInfo( symType ); - return TypedVar::getTypedVar( m_client, typeInfo, varOffset ); + return TypedVar::getTypedVar( m_client, typeInfo, VarDataMemory::factory(m_dataSpaces, varOffset) ); } //////////////////////////////////////////////////////////////////////////////// @@ -199,7 +200,7 @@ python::dict DebugClient::getLocals(ContextPtr ctx OPTIONAL) return python::dict(); // out of function debug range python::dict locals; - impl::addLocals Locals = { locals, mod, rva, ctx, m_client, 0 }; + impl::addLocals Locals = { locals, mod, rva, ctx, m_client, 0, m_dataSpaces }; Locals.append(symFunc); diff --git a/pykd/module.cpp b/pykd/module.cpp index af1f331..d80d50d 100644 --- a/pykd/module.cpp +++ b/pykd/module.cpp @@ -192,7 +192,7 @@ Module::reloadSymbols() TypedVarPtr Module::getTypedVarByTypeName( const std::string &typeName, ULONG64 addr ) { - return TypedVar::getTypedVar( m_client, getTypeByName(typeName), addr ); + return TypedVar::getTypedVar( m_client, getTypeByName(typeName), VarDataMemory::factory(m_dataSpaces, addr) ); } /////////////////////////////////////////////////////////////////////////////////// @@ -200,7 +200,7 @@ Module::getTypedVarByTypeName( const std::string &typeName, ULONG64 addr ) TypedVarPtr Module::getTypedVarByType( const TypeInfoPtr &typeInfo, ULONG64 addr ) { - return TypedVar::getTypedVar( m_client, typeInfo, addr ); + return TypedVar::getTypedVar( m_client, typeInfo, VarDataMemory::factory(m_dataSpaces, addr) ); } /////////////////////////////////////////////////////////////////////////////////// @@ -210,7 +210,7 @@ Module::getTypedVarByName( const std::string &symName ) { HRESULT hres; - pyDia::SymbolPtr typeSym = getDia()->getChildByName( symName ); + pyDia::SymbolPtr symVar = getDia()->getChildByName( symName ); std::string fullName = m_name; fullName += '!'; @@ -220,10 +220,16 @@ Module::getTypedVarByName( const std::string &symName ) hres = m_symbols->GetOffsetByName( fullName.c_str(), &offset ); - if ( FAILED( hres ) ) - throw DbgException("IDebugSymbols::GetOffsetByName failed" ); + TypeInfoPtr typeInfo = TypeInfo::getTypeInfo( symVar->getType() ); - return TypedVar::getTypedVar( m_client, TypeInfo::getTypeInfo( typeSym->getType() ), offset ); + if ( FAILED( hres ) ) + { + if ( LocIsConstant == symVar->getLocType() ) + return TypedVar::getTypedVar( m_client, typeInfo, VarDataConst::factory(m_control, symVar) ); + throw DbgException("IDebugSymbols::GetOffsetByName failed" ); + } + + return TypedVar::getTypedVar( m_client, typeInfo, VarDataMemory::factory(m_dataSpaces, offset) ); } /////////////////////////////////////////////////////////////////////////////////// @@ -301,7 +307,9 @@ TypedVarPtr Module::containingRecordByName( ULONG64 address, const std::string & TypeInfoPtr fieldTypeInfo = typeInfo->getField( fieldName ); - return TypedVar::getTypedVar( m_client, typeInfo, address - fieldTypeInfo->getOffset() ); + VarDataPtr varData = VarDataMemory::factory( m_dataSpaces, address - fieldTypeInfo->getOffset() ); + + return TypedVar::getTypedVar( m_client, typeInfo, varData ); } /////////////////////////////////////////////////////////////////////////////////// @@ -312,7 +320,9 @@ TypedVarPtr Module::containingRecordByType( ULONG64 address, const TypeInfoPtr & TypeInfoPtr fieldTypeInfo = typeInfo->getField( fieldName ); - return TypedVar::getTypedVar( m_client, typeInfo, address - fieldTypeInfo->getOffset() ); + VarDataPtr varData = VarDataMemory::factory( m_dataSpaces, address - fieldTypeInfo->getOffset() ); + + return TypedVar::getTypedVar( m_client, typeInfo, varData ); } diff --git a/pykd/pykd_2008.vcproj b/pykd/pykd_2008.vcproj index d4f0bac..604aa19 100644 --- a/pykd/pykd_2008.vcproj +++ b/pykd/pykd_2008.vcproj @@ -485,6 +485,10 @@ RelativePath=".\typeinfo.cpp" > </File> + <File + RelativePath=".\vardata.cpp" + > + </File> </Filter> <Filter Name="Header Files" @@ -615,6 +619,10 @@ RelativePath=".\utils.h" > </File> + <File + RelativePath=".\vardata.h" + > + </File> <File RelativePath=".\windbg.h" > diff --git a/pykd/stdafx.h b/pykd/stdafx.h index fe14b03..14bcf9c 100644 --- a/pykd/stdafx.h +++ b/pykd/stdafx.h @@ -33,6 +33,8 @@ #include <dia2.h> +#include <DbgEng.h> + // //#ifndef __field_ecount_opt //#define __field_ecount_opt(x) diff --git a/pykd/synsymbol.h b/pykd/synsymbol.h index 7742977..866dc98 100644 --- a/pykd/synsymbol.h +++ b/pykd/synsymbol.h @@ -5,7 +5,6 @@ #pragma once #include "dbgexcept.h" -#include <DbgEng.h> #include <map> namespace pykd { diff --git a/pykd/typedvar.cpp b/pykd/typedvar.cpp index 15e4d59..7e268db 100644 --- a/pykd/typedvar.cpp +++ b/pykd/typedvar.cpp @@ -1,4 +1,4 @@ -#include "stdafx.h" +#include "stdafx.h" #include <iomanip> @@ -10,43 +10,43 @@ namespace pykd { /////////////////////////////////////////////////////////////////////////////////// -TypedVarPtr TypedVar::getTypedVar( IDebugClient4 *client, const TypeInfoPtr& typeInfo, ULONG64 offset ) +TypedVarPtr TypedVar::getTypedVar( IDebugClient4 *client, const TypeInfoPtr& typeInfo, VarDataPtr varData ) { TypedVarPtr tv; if ( typeInfo->isBasicType() ) { - tv.reset( new BasicTypedVar( client, typeInfo, offset) ); + tv.reset( new BasicTypedVar( client, typeInfo, varData) ); return tv; } if ( typeInfo->isPointer() ) { - tv.reset( new PtrTypedVar( client, typeInfo, offset ) ); + tv.reset( new PtrTypedVar( client, typeInfo, varData ) ); return tv; } if ( typeInfo->isArray() ) { - tv.reset( new ArrayTypedVar( client, typeInfo, offset ) ); + tv.reset( new ArrayTypedVar( client, typeInfo, varData ) ); return tv; } if ( typeInfo->isUserDefined() ) { - tv.reset( new UdtTypedVar( client, typeInfo, offset ) ); + tv.reset( new UdtTypedVar( client, typeInfo, varData ) ); return tv; } if ( typeInfo->isBitField() ) { - tv.reset( new BitFieldVar( client, typeInfo, offset ) ); + tv.reset( new BitFieldVar( client, typeInfo, varData ) ); return tv; } if ( typeInfo->isEnum() ) { - tv.reset( new EnumTypedVar( client, typeInfo, offset ) ); + tv.reset( new EnumTypedVar( client, typeInfo, varData ) ); return tv; } @@ -57,10 +57,10 @@ TypedVarPtr TypedVar::getTypedVar( IDebugClient4 *client, const TypeInfoPtr& t /////////////////////////////////////////////////////////////////////////////////// -TypedVar::TypedVar ( IDebugClient4 *client, const TypeInfoPtr& typeInfo, ULONG64 offset ) : +TypedVar::TypedVar ( IDebugClient4 *client, const TypeInfoPtr& typeInfo, VarDataPtr varData ) : DbgObject( client ), m_typeInfo( typeInfo ), - m_offset( offset ), + m_varData( varData ), m_dataKind( DataIsGlobal ) { m_size = m_typeInfo->getSize(); @@ -69,9 +69,8 @@ TypedVar::TypedVar ( IDebugClient4 *client, const TypeInfoPtr& typeInfo, ULONG64 BaseTypeVariant BasicTypedVar::getValue() { - ULONG64 val = 0; - - readMemory( m_dataSpaces, m_offset, &val, getSize(), false ); + ULONG64 val = 0; + m_varData->read(&val, getSize()); if ( m_typeInfo->getName() == "Char" ) return (LONG)*(PCHAR)&val; @@ -121,7 +120,7 @@ std::string BasicTypedVar::print() { std::stringstream sstr; - sstr << m_typeInfo->getName() << " at " << std::hex << m_offset; + sstr << m_typeInfo->getName() << " " << m_varData->asString(); sstr << " Value: " << printValue(); return sstr.str(); @@ -143,22 +142,15 @@ std::string BasicTypedVar::printValue() BaseTypeVariant PtrTypedVar::getValue() { - ULONG64 val = 0; - - readMemoryPtr( m_dataSpaces, m_offset, &val ); - - return val; + return m_varData->readPtr(); } /////////////////////////////////////////////////////////////////////////////////// TypedVarPtr PtrTypedVar::deref() { - ULONG64 val = 0; - - readMemoryPtr( m_dataSpaces, m_offset, &val ); - - return TypedVar::getTypedVar( m_client, m_typeInfo->deref(), val ); + VarDataPtr varData = VarDataMemory::factory( m_dataSpaces, m_varData->readPtr() ); + return TypedVar::getTypedVar( m_client, m_typeInfo->deref(), varData ); } /////////////////////////////////////////////////////////////////////////////////// @@ -167,7 +159,7 @@ std::string PtrTypedVar::print() { std::stringstream sstr; - sstr << m_typeInfo->getName() << " at 0x" << std::hex << m_offset; + sstr << m_typeInfo->getName() << " " << m_varData->asString(); sstr << " Value: " << printValue(); return sstr.str(); @@ -179,7 +171,7 @@ std::string PtrTypedVar::printValue() { std::stringstream sstr; - sstr << "0x" << boost::apply_visitor( VariantToHex(), getValue() ); + sstr << "0x" << boost::apply_visitor( VariantToHex(), getValue() ); return sstr.str(); } @@ -190,7 +182,7 @@ std::string ArrayTypedVar::print() { std::stringstream sstr; - sstr << m_typeInfo->getName() << " at 0x" << std::hex << m_offset; + sstr << m_typeInfo->getName() << " " << m_varData->asString(); return sstr.str(); } @@ -211,7 +203,7 @@ TypedVarPtr ArrayTypedVar::getElementByIndex( ULONG index ) TypeInfoPtr elementType = m_typeInfo->getElementType(); - return TypedVar::getTypedVar( m_client, elementType, m_offset + elementType->getSize()*index ); + return TypedVar::getTypedVar( m_client, elementType, m_varData->fork(elementType->getSize()*index) ); } /////////////////////////////////////////////////////////////////////////////////// @@ -221,7 +213,7 @@ UdtTypedVar::getField( const std::string &fieldName ) { TypeInfoPtr fieldType = m_typeInfo->getField( fieldName ); - return TypedVar::getTypedVar( m_client, fieldType, m_offset + fieldType->getOffset() ); + return TypedVar::getTypedVar( m_client, fieldType, m_varData->fork(fieldType->getOffset()) ); } /////////////////////////////////////////////////////////////////////////////////// @@ -230,12 +222,12 @@ std::string UdtTypedVar::print() { std::stringstream sstr; - sstr << "struct/class: " << m_typeInfo->getName() << " at 0x" << std::hex << m_offset << std::endl; + sstr << "struct/class: " << m_typeInfo->getName() << " " << m_varData->asString(); for ( ULONG i = 0; i < m_typeInfo->getFieldCount(); ++i ) { TypeInfoPtr fieldType = m_typeInfo->getFieldByIndex(i); - TypedVarPtr fieldVar = TypedVar::getTypedVar( m_client, fieldType, m_offset + fieldType->getOffset() ); + TypedVarPtr fieldVar = TypedVar::getTypedVar( m_client, fieldType, m_varData->fork(fieldType->getOffset()) ); sstr << " +" << std::right << std::setw(4) << std::setfill('0') << std::hex << fieldType->getOffset(); sstr << " " << std::left << std::setw( 20 ) << std::setfill(' ') << m_typeInfo->getFieldNameByIndex(i) << ':'; @@ -261,7 +253,7 @@ BaseTypeVariant BitFieldVar::getValue() { ULONG64 val = 0; - readMemory( m_dataSpaces, m_offset, &val, getSize(), false ); + m_varData->read( &val, getSize() ); val >>= m_typeInfo->getBitOffset(); val &= m_typeInfo->getBitWidth(); @@ -303,7 +295,7 @@ BaseTypeVariant EnumTypedVar::getValue() { ULONG val = 0; - readMemory( m_dataSpaces, m_offset, &val, getSize(), false ); + m_varData->read( &val, getSize() ); return val; }; @@ -314,7 +306,7 @@ std::string EnumTypedVar::print() { std::stringstream sstr; - sstr << "enum: " << m_typeInfo->getName() << " at 0x" << std::hex << m_offset; + sstr << "enum: " << m_typeInfo->getName() << " " << m_varData->asString(); sstr << " Value: " << printValue(); return sstr.str(); diff --git a/pykd/typedvar.h b/pykd/typedvar.h index 1964fc3..6b06c9a 100644 --- a/pykd/typedvar.h +++ b/pykd/typedvar.h @@ -4,6 +4,7 @@ #include "intbase.h" #include "dbgobj.h" #include "dbgexcept.h" +#include "vardata.h" namespace pykd { @@ -18,10 +19,10 @@ class TypedVar : public intBase, protected DbgObject { public: - static TypedVarPtr getTypedVar( IDebugClient4 *client, const TypeInfoPtr& typeInfo, ULONG64 offset ); + static TypedVarPtr getTypedVar( IDebugClient4 *client, const TypeInfoPtr& typeInfo, VarDataPtr varData ); ULONG64 getAddress() const { - return m_offset; + return m_varData->getAddr(); } ULONG getSize() const { @@ -66,7 +67,7 @@ public: } virtual BaseTypeVariant getValue() { - return m_offset; + return m_varData->getAddr(); } ULONG getDataKind() const { @@ -79,11 +80,11 @@ public: protected: - TypedVar ( IDebugClient4 *client, const TypeInfoPtr& typeInfo, ULONG64 offset ); + TypedVar ( IDebugClient4 *client, const TypeInfoPtr& typeInfo, VarDataPtr varData ); TypeInfoPtr m_typeInfo; - ULONG64 m_offset; + VarDataPtr m_varData; ULONG m_size; @@ -97,7 +98,10 @@ class BasicTypedVar : public TypedVar { public: - BasicTypedVar ( IDebugClient4 *client, const TypeInfoPtr& typeInfo, ULONG64 offset ) : TypedVar(client, typeInfo, offset){} + BasicTypedVar ( IDebugClient4 *client, const TypeInfoPtr& typeInfo, VarDataPtr varData ) + : TypedVar(client, typeInfo, varData) + { + } virtual std::string print(); @@ -114,7 +118,10 @@ class PtrTypedVar : public TypedVar { public: - PtrTypedVar ( IDebugClient4 *client, const TypeInfoPtr& typeInfo, ULONG64 offset ) : TypedVar(client, typeInfo, offset){} + PtrTypedVar ( IDebugClient4 *client, const TypeInfoPtr& typeInfo, VarDataPtr varData ) + : TypedVar(client, typeInfo, varData) + { + } virtual std::string print(); @@ -132,7 +139,10 @@ class ArrayTypedVar: public TypedVar { public: - ArrayTypedVar ( IDebugClient4 *client, const TypeInfoPtr& typeInfo, ULONG64 offset ) : TypedVar(client, typeInfo, offset){} + ArrayTypedVar ( IDebugClient4 *client, const TypeInfoPtr& typeInfo, VarDataPtr varData ) + : TypedVar(client, typeInfo, varData) + { + } virtual ULONG getElementCount() { return m_typeInfo->getCount(); @@ -151,7 +161,10 @@ class UdtTypedVar : public TypedVar { public: - UdtTypedVar( IDebugClient4 *client, const TypeInfoPtr& typeInfo, ULONG64 offset ) : TypedVar(client, typeInfo, offset){} + UdtTypedVar( IDebugClient4 *client, const TypeInfoPtr& typeInfo, VarDataPtr varData ) + : TypedVar(client, typeInfo, varData) + { + } virtual std::string print(); @@ -166,7 +179,10 @@ class BitFieldVar: public TypedVar { public: - BitFieldVar( IDebugClient4 *client, const TypeInfoPtr& typeInfo, ULONG64 offset ) : TypedVar(client, typeInfo, offset){} + BitFieldVar( IDebugClient4 *client, const TypeInfoPtr& typeInfo, VarDataPtr varData ) + : TypedVar(client, typeInfo, varData) + { + } virtual std::string printValue(); @@ -178,7 +194,10 @@ public: class EnumTypedVar : public TypedVar { public: - EnumTypedVar( IDebugClient4 *client, const TypeInfoPtr& typeInfo, ULONG64 offset ) : TypedVar(client, typeInfo, offset){} + EnumTypedVar( IDebugClient4 *client, const TypeInfoPtr& typeInfo, VarDataPtr varData ) + : TypedVar(client, typeInfo, varData) + { + } virtual std::string print(); diff --git a/pykd/vardata.cpp b/pykd/vardata.cpp new file mode 100644 index 0000000..2feb02c --- /dev/null +++ b/pykd/vardata.cpp @@ -0,0 +1,171 @@ +// +// Access to variable data +// + +#include "stdafx.h" + +#include "vardata.h" +#include "dbgmem.h" +#include "dbgexcept.h" + +//////////////////////////////////////////////////////////////////////////////// + +namespace pykd { + +//////////////////////////////////////////////////////////////////////////////// + +VarDataMemory::VarDataMemory(CComPtr< IDebugDataSpaces4 > dataSpaces, ULONG64 addr) + : m_dataSpaces(dataSpaces) + , m_addr(addr) +{ +} + +//////////////////////////////////////////////////////////////////////////////// + +std::string VarDataMemory::asString() const +{ + std::stringstream sstr; + sstr << "at 0x" << std::hex << m_addr; + return sstr.str(); +} + +//////////////////////////////////////////////////////////////////////////////// + +ULONG64 VarDataMemory::getAddr() const +{ + return m_addr; +} + +//////////////////////////////////////////////////////////////////////////////// + +VarDataPtr VarDataMemory::fork(ULONG offset) const +{ + return VarDataPtr( new VarDataMemory(m_dataSpaces, m_addr + offset) ); +} + +//////////////////////////////////////////////////////////////////////////////// + +void VarDataMemory::read(PVOID buffer, ULONG length, ULONG offset /*= 0*/) const +{ + readMemory(m_dataSpaces, m_addr + offset, buffer, length); +} + +//////////////////////////////////////////////////////////////////////////////// + +ULONG64 VarDataMemory::readPtr() const +{ + ULONG64 ptrValue = 0; + readMemoryPtr(m_dataSpaces, m_addr, &ptrValue); + return ptrValue; +} + +//////////////////////////////////////////////////////////////////////////////// + +VarDataConst::VarDataConst(CComPtr< IDebugControl4 > control, pyDia::SymbolPtr symData) + : m_control(control) + , m_fieldOffset(0) + , m_dataBuff( new std::vector< UCHAR >((size_t)symData->getType()->getSize(), 0) ) +{ + VARIANT vtValue = {0}; + symData->getValue(vtValue); + + switch (vtValue.vt) + { + case VT_I1: + case VT_UI1: + fillDataBuff(vtValue.bVal); + break; + + case VT_BOOL: + fillDataBuff(!!vtValue.iVal); + break; + + case VT_I2: + case VT_UI2: + fillDataBuff(vtValue.iVal); + break; + + case VT_I4: + case VT_UI4: + case VT_INT: + case VT_UINT: + case VT_ERROR: + case VT_HRESULT: + fillDataBuff(vtValue.lVal); + break; + + case VT_I8: + case VT_UI8: + fillDataBuff(vtValue.llVal); + break; + + case VT_R4: + fillDataBuff(vtValue.fltVal); + break; + + case VT_R8: + fillDataBuff(vtValue.dblVal); + break; + + default: + throw DbgException( "Unsupported const value" ); + } +} + +//////////////////////////////////////////////////////////////////////////////// + +std::string VarDataConst::asString() const +{ + return "<constant>"; +} + +//////////////////////////////////////////////////////////////////////////////// + +ULONG64 VarDataConst::getAddr() const +{ + throw DbgException("Constant does not have address"); +} + +//////////////////////////////////////////////////////////////////////////////// + +VarDataPtr VarDataConst::fork(ULONG offset) const +{ + return VarDataPtr(new VarDataConst(*this, offset)); +} + +//////////////////////////////////////////////////////////////////////////////// + +void VarDataConst::read(PVOID buffer, ULONG length, ULONG offset /*= 0*/) const +{ + if (offset + length > m_dataBuff->size()) + throw DbgException("Internal error in " __FUNCTION__); + RtlCopyMemory(buffer, &m_dataBuff->at(offset), length); +} + +////////////////////////////////////////////////////////////////////////////////' + +ULONG64 VarDataConst::readPtr() const +{ + ULONG64 val = 0; + const ULONG length = (S_OK == m_control->IsPointer64Bit()) ? 8 : 4; + if (length > m_dataBuff->size()) + throw DbgException("Internal error in " __FUNCTION__); + RtlCopyMemory(&val, &m_dataBuff->at(0), length); + return val; +} + +//////////////////////////////////////////////////////////////////////////////// + +VarDataConst::VarDataConst(const VarDataConst &from, ULONG fieldOffset) + : m_control(from.m_control) + , m_fieldOffset(from.m_fieldOffset + fieldOffset) + , m_dataBuff(from.m_dataBuff) +{ +} + +//////////////////////////////////////////////////////////////////////////////// + +} + +//////////////////////////////////////////////////////////////////////////////// + diff --git a/pykd/vardata.h b/pykd/vardata.h new file mode 100644 index 0000000..b1f27bf --- /dev/null +++ b/pykd/vardata.h @@ -0,0 +1,95 @@ +// +// Access to variable data +// + +#pragma once + +//////////////////////////////////////////////////////////////////////////////// + +#include <array> +#include <boost\smart_ptr\shared_ptr.hpp> + +#include "diawrapper.h" + +//////////////////////////////////////////////////////////////////////////////// + +namespace pykd { + +// pointer to variable data access interface +interface IVarData; +typedef boost::shared_ptr< IVarData > VarDataPtr; + +// access to variable data interface +interface IVarData +{ + virtual ~IVarData() {} + + virtual std::string asString() const = 0; + virtual ULONG64 getAddr() const = 0; + virtual VarDataPtr fork(ULONG offset) const = 0; + + virtual void read(PVOID buffer, ULONG length, ULONG offset = 0) const = 0; + virtual ULONG64 readPtr() const = 0; +}; + +// variable in memory +class VarDataMemory : public IVarData +{ +public: + + // IVarData implementation + virtual std::string asString() const override; + virtual ULONG64 getAddr() const override; + virtual VarDataPtr fork(ULONG offset) const override; + + virtual void read(PVOID buffer, ULONG length, ULONG offset = 0) const override; + virtual ULONG64 readPtr() const override; + + static VarDataPtr factory(CComPtr< IDebugDataSpaces4 > dataSpaces, ULONG64 addr) { + return VarDataPtr( new VarDataMemory(dataSpaces, addr) ); + } + +protected: + VarDataMemory(CComPtr< IDebugDataSpaces4 > dataSpaces, ULONG64 addr); + +private: + CComPtr< IDebugDataSpaces4 > m_dataSpaces; + ULONG64 m_addr; +}; + +// constant variable +class VarDataConst : public IVarData +{ +public: + // IVarData implementation + virtual std::string asString() const override; + virtual ULONG64 getAddr() const override; + virtual VarDataPtr fork(ULONG offset) const override; + + virtual void read(PVOID buffer, ULONG length, ULONG offset = 0) const override; + virtual ULONG64 readPtr() const override; + + static VarDataPtr factory(CComPtr< IDebugControl4 > control, pyDia::SymbolPtr symData) { + return VarDataPtr( new VarDataConst(control, symData) ); + } + +protected: + VarDataConst(CComPtr< IDebugControl4 > control, pyDia::SymbolPtr symData); + VarDataConst(const VarDataConst &from, ULONG fieldOffset); + + template<typename T> + void fillDataBuff(const T &data) + { + RtlCopyMemory( &m_dataBuff->at(0), &data, min(sizeof(T), m_dataBuff->size()) ); + } + +private: + CComPtr< IDebugControl4 > m_control; + + ULONG m_fieldOffset; + boost::shared_ptr< std::vector<UCHAR> > m_dataBuff; +}; + +} + +////////////////////////////////////////////////////////////////////////// diff --git a/test/scripts/typedvar.py b/test/scripts/typedvar.py index e1b122d..1e0493b 100644 --- a/test/scripts/typedvar.py +++ b/test/scripts/typedvar.py @@ -23,10 +23,8 @@ class TypedVarTest( unittest.TestCase ): self.assertEqual( -8, target.module.typedVar( "g_longlongValue" ) ) def testConst(self): - try: - self.assertEqual( True, target.module.typedVar( "g_constBoolValue" ) ) - except pykd.BaseException: - self.assertFalse( "FIXME: constants without RVA is not supported" ) + self.assertEqual( True, target.module.typedVar( "g_constBoolValue" ) ) + self.assertEqual( 0x5555, target.module.typedVar( "g_constNumValue" ) ) def testGetAddress( self ): tv = target.module.typedVar( "structTest", target.module.g_structTest )