--- a/GDBMI_break_enable.st Mon May 28 23:18:45 2018 +0100
+++ b/GDBMI_break_enable.st Mon Jun 04 14:34:44 2018 +0100
@@ -97,3 +97,10 @@
^ 'break-enable'
! !
+!GDBMI_break_enable class methodsFor:'documentation'!
+
+version_HG
+
+ ^ '$Changeset: <not expanded> $'
+! !
+
--- a/GDBVariableObject.st Mon May 28 23:18:45 2018 +0100
+++ b/GDBVariableObject.st Mon Jun 04 14:34:44 2018 +0100
@@ -24,7 +24,7 @@
GDBDebuggerObject subclass:#GDBVariableObject
instanceVariableNames:'parent name exp path thread frame value type numchild has_more
- children changed inScope visualizer'
+ children changed inScope visualizer dynamic'
classVariableNames:''
poolDictionaries:''
category:'GDB-Core'
@@ -84,11 +84,11 @@
children
self isValid ifFalse:[ ^ #() ].
children isNil ifTrue:[
- (self isValid and:[numchild isNil or:[numchild > 0]]) ifTrue:[
+ (self isValid and:[has_more or:[ numchild isNil or:[numchild > 0]]]) ifTrue:[
| result |
result := debugger send: (GDBMI_var_list_children arguments: (Array with: '--all-values' with: name)).
- children := result propertyAt: #children.
+ children := (result propertyAt: #children) ? #().
children do:[:each | each setDebugger: debugger; setParent: self ].
numchild := children size.
] ifFalse:[
@@ -98,7 +98,7 @@
^ children
"Created: / 27-01-2018 / 22:53:15 / Jan Vrany <jan.vrany@fit.cvut.cz>"
- "Modified: / 19-02-2018 / 15:49:09 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+ "Modified: / 04-06-2018 / 10:57:02 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!
expression
@@ -180,6 +180,23 @@
p expression '/ -> 'y'
"
+
+ "/ Raise an error early when #path is requested for a child of dynamic
+ "/ varobj. Thie is not supported by GDB.
+ "/
+ "/ Although GDB should report an error [1], dur to a bug it report
+ "/ either wrong (nonsense) value or crashes. A patch has been send
+ "/ to the upstream [2], but meanwhile, check here as well in case someone
+ "/ uses this with older / not yet patches version of GDB.
+ "/
+ "/ [1]: https://sourceware.org/gdb/onlinedocs/gdb/GDB_002fMI-Variable-Objects.html
+ "/ [2]: https://sourceware.org/ml/gdb-patches/2018-06/msg00058.html
+ "/
+ (parent notNil and:[parent isDynamic]) ifTrue:[
+ GDBError raiseErrorString: 'Invalid varobj, #path is not supported for children of a dynamic varobjs'.
+ ^ self
+ ].
+
path isNil ifTrue:[
| result |
@@ -189,6 +206,8 @@
^ path
"Created: / 05-02-2018 / 21:16:30 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+ "Modified: / 01-06-2018 / 16:31:56 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+ "Modified (comment): / 04-06-2018 / 14:19:57 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!
thread
@@ -323,11 +342,13 @@
duplicate
"Create and returns a duplicate of the receiver, representing
- the same value. Other than thatm the eturned duplicate is completely
+ the same value. Other than that the returned duplicate is completely
independent"
+
^ debugger evaluate: self path in: self frame
"Created: / 13-02-2018 / 22:17:36 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+ "Modified (format): / 04-06-2018 / 14:23:16 / Jan Vrany <jan.vrany@fit.cvut.cz>"
! !
!GDBVariableObject methodsFor:'displaying'!
@@ -380,8 +401,10 @@
super initialize.
inScope := true.
+ dynamic := false.
+ has_more := true.
- "Modified: / 13-02-2018 / 23:51:07 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+ "Modified: / 04-06-2018 / 10:55:17 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!
release
@@ -514,6 +537,14 @@
"Created: / 12-02-2018 / 21:56:38 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!
+isDynamic
+ "Return true, if this varobj is a dynamic varobj, false otherwise"
+
+ ^ dynamic
+
+ "Created: / 01-06-2018 / 16:29:56 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+!
+
isValid
changed value. "/ to force update if necessary
^ debugger notNil
--- a/tests/GDBDebuggeesResource.st Mon May 28 23:18:45 2018 +0100
+++ b/tests/GDBDebuggeesResource.st Mon Jun 04 14:34:44 2018 +0100
@@ -91,6 +91,12 @@
"Modified: / 12-01-2018 / 12:43:55 / jv"
!
+binaryPyVarobj
+ ^ self binary: 'py-varobj'
+
+ "Created: / 01-06-2018 / 16:25:22 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+!
+
binaryVariables1
^ self binary: 'variables1'
--- a/tests/GDBDebuggerTestsR.st Mon May 28 23:18:45 2018 +0100
+++ b/tests/GDBDebuggerTestsR.st Mon Jun 04 14:34:44 2018 +0100
@@ -808,6 +808,47 @@
debugger send: 'quit' andWait: false.
"Created: / 20-03-2018 / 22:32:00 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+!
+
+test_variables_08
+ "
+ This tests -var-info-path-expression on dynamic varobjs.
+ "
+
+ | c1 c1_cdr c1_cdr_cdr |
+
+ debugger := GDBDebugger new.
+ self assert: debugger isConnected.
+
+ debugger executable: GDBDebuggeesResource current binaryPyVarobj.
+ self assert: debugger breakpoints isEmpty.
+
+ debugger send: 'source ', ((Smalltalk getPackageDirectoryForPackage:self class package)
+ / 'c' / 'py-varobj.py') pathName.
+ debugger enablePrettyPrinting.
+ debugger send: 'b py-varobj.c:22'.
+ debugger send: 'r'.
+
+ c1 := debugger evaluate: '&c1'.
+ self assert: c1 isDynamic.
+ self assert: c1 path = '&c1'.
+
+ c1_cdr := c1 children second.
+ self assert: c1_cdr expression = 'cdr'.
+ self assert: c1_cdr isDynamic.
+ self assert: c1_cdr parent == c1.
+ self should: [ c1_cdr path ] raise: GDBError.
+
+ c1_cdr_cdr := c1_cdr children second.
+ self assert: c1_cdr_cdr expression = 'cdr'.
+ self assert: c1_cdr_cdr isDynamic.
+ self assert: c1_cdr_cdr parent == c1_cdr.
+ self should: [ c1_cdr_cdr path ] raise: GDBError.
+
+ debugger send: 'quit' andWait: false.
+
+ "Created: / 01-06-2018 / 16:27:29 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+ "Modified (comment): / 04-06-2018 / 11:02:19 / Jan Vrany <jan.vrany@fit.cvut.cz>"
! !
!GDBDebuggerTestsR class methodsFor:'documentation'!
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/c/py-varobj.c Mon Jun 04 14:34:44 2018 +0100
@@ -0,0 +1,23 @@
+struct _cons
+{
+ struct _cons *slots[2];
+};
+
+#define nil ((struct _cons*)0);
+
+int
+main (int argc, char **argv)
+{
+ struct _cons c1, c2, c3;
+
+ c1.slots[0] = nil;
+ c1.slots[1] = &c2;
+
+ c2.slots[0] = nil;
+ c2.slots[1] = &c3;
+
+ c3.slots[0] = nil;
+ c3.slots[1] = nil;
+
+ return 0; /* next line */
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/c/py-varobj.py Mon Jun 04 14:34:44 2018 +0100
@@ -0,0 +1,35 @@
+import gdb
+import gdb.types
+import sys
+
+if sys.version_info[0] > 2:
+ long = int
+ imap = map
+
+class cons_pp(object):
+ def __init__(self, val):
+ self._val = val
+
+ def to_string(self):
+ if long(self._val) == 0:
+ return "nil"
+ else:
+ return "(...)"
+
+ def children(self):
+ if long(self._val) == 0:
+ return []
+ else:
+ return [
+ ('car' , self._val["slots"][0]),
+ ('cdr' , self._val["slots"][1])
+ ]
+
+def cons_pp_lookup(val):
+ if str(val.type) == 'struct _cons *':
+ return cons_pp(val)
+ else:
+ return None
+
+del gdb.pretty_printers[1:]
+gdb.pretty_printers.append(cons_pp_lookup)
\ No newline at end of file