11using EnvDTE ;
2+ using Microsoft . VisualStudio . Debugger . ComponentInterfaces ;
23using System ;
4+ using System . Windows . Forms ;
35using static GraphicalDebugging . MemoryReader ;
46
57namespace GraphicalDebugging
@@ -18,42 +20,30 @@ public Debugger(DTE dte)
1820 this . debugger = dte . Debugger ;
1921 }
2022
21- public int LoadSize ( string name )
23+ // TODO: return uint
24+ public bool TryLoadUInt ( string name , out int result )
2225 {
23- var expr = debugger . GetExpression ( name ) ;
24- return expr . IsValidValue
25- ? Math . Max ( Util . ParseInt ( expr . Value , debugger . HexDisplayMode ) , 0 )
26- : 0 ;
27- }
28- public int LoadInt ( string name , int defaultValue = 0 )
29- {
30- var expr = debugger . GetExpression ( name ) ;
31- return expr . IsValidValue
32- ? Util . ParseInt ( expr . Value , debugger . HexDisplayMode )
33- : defaultValue ;
26+ return TryLoadInt ( name , out result )
27+ && result >= 0 ;
3428 }
3529
3630 public bool TryLoadInt ( string name , out int result )
3731 {
3832 result = 0 ;
3933 var expr = debugger . GetExpression ( name ) ;
40- if ( ! expr . IsValidValue )
41- return false ;
42- result = Util . ParseInt ( expr . Value , debugger . HexDisplayMode ) ;
43- return true ;
34+ return expr . IsValidValue
35+ && Util . TryParseInt ( expr . Value , debugger . HexDisplayMode , out result ) ;
4436 }
4537
4638 public bool TryLoadDouble ( string name , out double result )
4739 {
4840 result = 0.0 ;
49- string castedName = "(double)" + name ;
50- if ( IsLanguageBasic )
51- castedName = "CType(" + name + ", Double)" ;
41+ string castedName = ! IsLanguageBasic
42+ ? "(double)" + name
43+ : "CType(" + name + ", Double)" ;
5244 var expr = debugger . GetExpression ( castedName ) ;
53- if ( ! expr . IsValidValue )
54- return false ;
55- result = Util . ParseDouble ( expr . Value ) ;
56- return true ;
45+ return expr . IsValidValue
46+ && Util . TryParseDouble ( expr . Value , out result ) ;
5747 }
5848
5949 public bool TryLoadBool ( string name , out bool result )
@@ -66,45 +56,39 @@ public bool TryLoadBool(string name, out bool result)
6656 return true ;
6757 }
6858
69- /*struct AddressDifference
70- {
71- long Value;
72- bool IsValid;
73- }*/
74-
75- // Valid difference of addresses of variables valName1 and valName2
76- // or long.MinValue
77- // detect invalid address difference with IsInvalidAddressDifference()
78- public long GetAddressDifference ( string valName1 , string valName2 )
79- {
80- ulong addr1 = GetValueAddress ( valName1 ) ;
81- ulong addr2 = GetValueAddress ( valName2 ) ;
82- if ( addr1 == 0 || addr2 == 0 )
83- return long . MinValue ;
84- return ( addr2 >= addr1 )
85- ? ( long ) ( addr2 - addr1 )
86- : - ( long ) ( addr1 - addr2 ) ;
87- }
88-
89- public long GetPointerDifference ( string pointerName1 , string pointerName2 )
59+ // TODO: take size to check against out of bounds
60+ // TODO: return ulong?
61+ // Difference of addresses of variables valName1 and valName2
62+ // Returns false if addresses cannot be loaded, parsed, any of them is equal to 0 or offset is < 0
63+ // In these cases result is negative
64+ public bool GetAddressOffset ( string valName1 , string valName2 , out long result )
9065 {
91- ulong addr1 = GetPointer ( pointerName1 ) ;
92- ulong addr2 = GetPointer ( pointerName2 ) ;
93- if ( addr1 == 0 || addr2 == 0 )
94- return long . MinValue ;
95- return ( addr2 >= addr1 )
96- ? ( long ) ( addr2 - addr1 )
97- : - ( long ) ( addr1 - addr2 ) ;
98- }
99-
100- public static long InvalidAddressDifference ( )
101- {
102- return long . MinValue ;
66+ result = long . MinValue ;
67+ if ( GetValueAddress ( valName1 , out ulong addr1 )
68+ && GetValueAddress ( valName2 , out ulong addr2 )
69+ && addr2 >= addr1 )
70+ {
71+ result = ( long ) ( addr2 - addr1 ) ;
72+ return true ;
73+ }
74+ return false ;
10375 }
10476
105- public static bool IsInvalidAddressDifference ( long diff )
77+ // TODO: take size to check against out of bounds
78+ // TODO: return ulong?
79+ // Returns false if addresses cannot be loaded, parsed, any of them is equal to 0 or offset is < 0
80+ // In these cases result is negative
81+ public bool GetPointerOffset ( string pointerName1 , string pointerName2 , out long result )
10682 {
107- return diff == long . MinValue ;
83+ result = long . MinValue ;
84+ if ( GetPointer ( pointerName1 , out ulong addr1 )
85+ && GetPointer ( pointerName2 , out ulong addr2 )
86+ && addr2 >= addr1 )
87+ {
88+ result = ( long ) ( addr2 - addr1 ) ;
89+ return true ;
90+ }
91+ return false ;
10892 }
10993
11094 // C++ and C# only!
@@ -122,62 +106,67 @@ public static bool IsInvalidAddressDifference(long diff)
122106 // - size: "System.Runtime.InteropServices.Marshal.ReadInt32(typeof(" + type + ").TypeHandle.Value, 4)"
123107 // - size: "*(((int*)(void*)typeof(" + type + ").TypeHandle.Value) + 1)"
124108
125- public ulong GetPointer ( string pointerName )
109+ // Value of pointer, aka address pointed to
110+ // Returns false if address cannot be loaded, parsed or if it is equal to 0
111+ public bool GetPointer ( string pointerName , out ulong result )
126112 {
113+ result = 0 ;
127114 var ptrExpr = debugger . GetExpression ( "(void*)(" + pointerName + ")" ) ;
128- if ( ! ptrExpr . IsValidValue )
129- return 0 ;
130- string addr = ptrExpr . Value ;
131-
132- // NOTE: Hexadecimal value is automatically detected, this is probably not needed.
133- // But automatically detect the format just in case of various versions
134- // of VS displayed it differently regardless of debugger mode.
135- return Util . ParseULong ( addr /*, true*/ ) ;
115+ return ptrExpr . IsValidValue
116+ // NOTE: Hexadecimal value is automatically detected, this is probably not needed.
117+ // But automatically detect the format just in case of various versions
118+ // of VS displayed it differently regardless of debugger mode.
119+ && Util . TryParseULong ( ptrExpr . Value /*, true*/ , out result )
120+ && result != 0 ;
136121 }
137122
138- // Valid address of variable valName or 0
139- public ulong GetValueAddress ( string valName )
123+ // Address of variable
124+ // Returns false if address cannot be loaded, parsed or if it is equal to 0
125+ public bool GetValueAddress ( string valName , out ulong result )
140126 {
141- return GetPointer ( "&(" + valName + ")" ) ;
127+ return GetPointer ( "&(" + valName + ")" , out result ) ;
142128 }
143129
144- // Valid size or 0
145130 // NOTE: In C++ the actual byte size depends on CHAR_BIT
146- public int GetValueSizeof ( string valName )
131+ // Returns false if size of variable cannot be loaded, parsed or if it is <= 0
132+ public bool GetValueSizeof ( string valName , out int result )
147133 {
134+ result = 0 ;
148135 string typeName = valName ; // In C++ value and type is interchangeable when passed into sizeof
149- //if (!IsLanguageCpp(debugger) )
136+ //if (!IsLanguageCpp)
150137 if ( IsLanguageCs ) // Change this when getting address in Basic works
151138 {
152139 var valExpr = debugger . GetExpression ( valName ) ;
153140 if ( ! valExpr . IsValidValue )
154- return 0 ;
141+ return false ;
155142 typeName = valExpr . Type ;
156143 }
157- return GetTypeSizeof ( typeName ) ;
144+ return GetTypeSizeof ( typeName , out result ) ;
158145 }
159146
160- // Valid size or 0
161- public int GetTypeSizeof ( string valType )
147+ // Returns false if size of type cannot be loaded, parsed or if it is <= 0
148+ public bool GetTypeSizeof ( string valType , out int result )
162149 {
150+ result = 0 ;
163151 if ( IsLanguageBasic ) // Change this when getting address in Basic works
164152 //sizeOfStr = "System.Runtime.InteropServices.Marshal.SizeOf(GetType(" + valType + "))";
165- return 0 ;
166-
153+ return false ;
167154 string sizeOfStr = "sizeof(" + valType + ")" ;
168155 var valSizeExpr = debugger . GetExpression ( sizeOfStr ) ;
169156 return valSizeExpr . IsValidValue
170- ? Util . ParseInt ( valSizeExpr . Value , debugger . HexDisplayMode )
171- : 0 ;
157+ && Util . TryParseInt ( valSizeExpr . Value , debugger . HexDisplayMode , out result )
158+ && result > 0 ;
172159 }
173160
174- public int GetCppSizeof ( string valNameOrType )
161+ // Returns false if size of type cannot be loaded, parsed or if it is <= 0
162+ public bool GetCppSizeof ( string valNameOrType , out int result )
175163 {
164+ result = 0 ;
176165 string sizeOfStr = "sizeof(" + valNameOrType + ")" ;
177166 var valSizeExpr = debugger . GetExpression ( sizeOfStr ) ;
178167 return valSizeExpr . IsValidValue
179- ? Util . ParseInt ( valSizeExpr . Value , debugger . HexDisplayMode )
180- : 0 ;
168+ && Util . TryParseInt ( valSizeExpr . Value , debugger . HexDisplayMode , out result )
169+ && result > 0 ;
181170 }
182171
183172 // Valid type name or null
@@ -227,21 +216,9 @@ public static bool IsInvalidType(string type1, string type2)
227216 return string . IsNullOrEmpty ( type1 ) || string . IsNullOrEmpty ( type2 ) ;
228217 }
229218
230- public static bool IsInvalidSize ( int size )
231- {
232- return size <= 0 ;
233- }
234-
235- public static bool IsInvalidSize ( int size1 , int size2 )
236- {
237- return size1 <= 0 || size2 <= 0 ;
238- }
239-
240219 public static bool IsInvalidOffset ( long size , long offset )
241220 {
242- return IsInvalidAddressDifference ( offset )
243- || offset < 0
244- || offset >= size ;
221+ return offset < 0 || offset >= size ;
245222 }
246223
247224 public static bool IsInvalidOffset ( long size , long offset1 , long offset2 )
0 commit comments