diff --git a/pykd/typedvar.cpp b/pykd/typedvar.cpp index a12fbb3..d4a77fb 100644 --- a/pykd/typedvar.cpp +++ b/pykd/typedvar.cpp @@ -432,23 +432,59 @@ BaseTypeVariant BitFieldVar::getValue() m_varData->read( &val, getSize() ); - val >>= m_typeInfo->getBitOffset(); - val &= ( 1 << m_typeInfo->getBitWidth() ) - 1; - - switch ( m_typeInfo->getSize() ) + if ( m_typeInfo->isSigned() ) { - case 1: - return (ULONG)*(PUCHAR)&val; + ULONG width = m_typeInfo->getBitWidth(); - case 2: - return (ULONG)*(PUSHORT)&val; + val >>= m_typeInfo->getBitOffset(); - case 4: - return *(PULONG)&val; + if ( ( val & ( 1ULL << ( width -1 ) ) ) != 0 ) + { + val |= ~( ( 1ULL << width ) - 1 ); + } + else + { + val &= ( 1ULL << width ) - 1; + } - case 8: - return *(PULONG64)&val; + LONG64 signedVal = (LONG64)val; + + switch ( m_typeInfo->getSize() ) + { + case 1: + return (LONG)signedVal; + + case 2: + return (LONG)signedVal; + + case 4: + return (LONG)signedVal; + + case 8: + return signedVal; + } } + else + { + val >>= m_typeInfo->getBitOffset(); + val &= ( 1 << m_typeInfo->getBitWidth() ) - 1; + + switch ( m_typeInfo->getSize() ) + { + case 1: + return (ULONG)*(PUCHAR)&val; + + case 2: + return (ULONG)*(PUSHORT)&val; + + case 4: + return *(PULONG)&val; + + case 8: + return *(PULONG64)&val; + } + } + throw DbgException( "failed get value " ); } diff --git a/pykd/typeinfo.cpp b/pykd/typeinfo.cpp index 222a4ee..3b387b6 100644 --- a/pykd/typeinfo.cpp +++ b/pykd/typeinfo.cpp @@ -351,6 +351,7 @@ BitFieldTypeInfo::BitFieldTypeInfo( SymbolPtr &symbol ) TypeInfoPtr typeInfo = TypeInfo::getBaseTypeInfo( symbol->getType() ); m_size = (ULONG)typeInfo->getSize(); + m_signed = typeInfo->isSigned(); std::stringstream sstr; diff --git a/pykd/typeinfo.h b/pykd/typeinfo.h index f1a958d..e8c594c 100644 --- a/pykd/typeinfo.h +++ b/pykd/typeinfo.h @@ -171,6 +171,10 @@ public: return false; } + virtual bool isSigned() { + throw TypeException( getName(), "type is not based" ); + } + virtual ULONG getCount() { throw TypeException( getName(), "type is not an array" ); } @@ -276,10 +280,19 @@ private: return true; } - std::string m_name; + virtual bool isSigned() { + T t = static_cast(-1); + return t < 0; + } + std::string m_name; }; +template<> +bool TypeInfoWrapper::isSigned() { + return false; +} + /////////////////////////////////////////////////////////////////////////////////// class BitFieldTypeInfo : public TypeInfo @@ -312,8 +325,13 @@ public: return m_size; } + virtual bool isSigned() { + return m_signed; + } + private: + bool m_signed; ULONG m_size; ULONG m_bitWidth; ULONG m_bitPos; diff --git a/test/scripts/typedvar.py b/test/scripts/typedvar.py index bcd65fb..640b046 100644 --- a/test/scripts/typedvar.py +++ b/test/scripts/typedvar.py @@ -140,11 +140,11 @@ class TypedVarTest( unittest.TestCase ): tv = target.module.typedVar("g_structWithBits") self.assertEqual( 4, tv.m_bit0_4 ) self.assertEqual( 1, tv.m_bit5 ) - self.assertEqual( 3, tv.m_bit6_7 ) + self.assertEqual( 5, tv.m_bit6_8 ) tv = target.module.typedVar("g_structWithSignBits") self.assertEqual( 4, tv.m_bit0_4 ) self.assertEqual( -1, tv.m_bit5 ) - self.assertEqual( -1, tv.m_bit6_7 ) + self.assertEqual( -3, tv.m_bit6_8 ) def testTypedVarList(self): tvl = target.module.typedVarList( target.module.g_listHead, "listStruct", "listEntry" ) diff --git a/test/targetapp/targetapp.cpp b/test/targetapp/targetapp.cpp index 1b78e62..043cbd2 100644 --- a/test/targetapp/targetapp.cpp +++ b/test/targetapp/targetapp.cpp @@ -44,13 +44,13 @@ std::string g_string; struct structWithBits { ULONG m_bit0_4 : 5; ULONG m_bit5 : 1; - ULONG m_bit6_7 : 2; + ULONG m_bit6_8 : 3; }; struct structWitSignBits { LONG m_bit0_4 : 5; LONG m_bit5 : 1; - LONG m_bit6_7 : 2; + LONG m_bit6_8 : 3; }; @@ -104,8 +104,8 @@ typedef struct structAbstract *pstructAbstract; pstructAbstract g_structAbstract = 0; -structWithBits g_structWithBits = { 4, 1, 3}; -structWitSignBits g_structWithSignBits = { 4, 1, 3 }; +structWithBits g_structWithBits = { 4, 1, 5}; +structWitSignBits g_structWithSignBits = { 4, 1, 5 }; structTest g_structTest = { 0, 500, true, 1, NULL }; structTest g_structTest1 = { 0, 500, true, 1, &g_structTest };