GDBFrame.st
changeset 144 342b6dfe3a6f
parent 132 70c17add3b24
child 146 50a8d9281fdc
--- a/GDBFrame.st	Wed Sep 26 13:25:40 2018 +0100
+++ b/GDBFrame.st	Wed Sep 26 11:16:56 2018 +0100
@@ -21,7 +21,8 @@
 "{ NameSpace: Smalltalk }"
 
 GDBDebuggerObject subclass:#GDBFrame
-	instanceVariableNames:'thread level addr func file fullname line arch from variables'
+	instanceVariableNames:'thread level addr func file fullname line arch from variables
+		registers registersChanges'
 	classVariableNames:''
 	poolDictionaries:''
 	category:'GDB-Core'
@@ -174,6 +175,45 @@
     ^ line
 !
 
+registers
+    "Return a list of mchine registers and their correcponsing
+     values in this frame (as list of GDBRegisterWithValue)"
+
+    registers isNil ifTrue:[
+        | registersSet result |
+
+        "/ First, retrieve a list of register available in this
+        "/ frame.
+        "/
+        "/ To reduce MI communication overhead, registers are cached
+        "/ in shared cache kept in process group (inferior). Caching is 
+        "/ based on an assumption that while each frame may have different 
+        "/ architecture, it is unlikely that  different frames with same 
+        "/ architecture would have different set of registers.
+        registersSet := self thread group registersMap at: self arch ifAbsentPut:[ 
+            result := debugger send: (GDBMI_data_list_register_names arguments: (Array with: '--thread' with: self thread id with: '--frame' with: self level)).
+            registersSet := Dictionary new.
+            (result propertyAt: 'register-names') withIndexDo:[ :name :number | 
+                name notEmpty ifTrue:[
+                    "/ Note, that GDB register indices starts with 0 (zero) like in C!!
+                    registersSet at: number - 1 put: (GDBRegister new setNumber: number - 1; setName: name)
+                ].
+            ].
+            registersSet
+        ].
+
+        "/ Second, fetch values and populate a collection of registers (as `GDBRegisterWithValue`). This is done
+        "/ onlt once, later on, the value of registers is updated automagically (see `GDBRegisterWithValue >> value`).
+        result := debugger send: (GDBMI_data_list_register_values new arguments: (Array with: '--thread' with: thread id with: '--frame' with: level with: 'r')).
+        registers := result propertyAt: #'register-values'.
+        registers do:[:value | value setFrame: self; setRegisterFrom: registersSet ].
+    ].
+    ^ registers value
+
+    "Created: / 26-09-2018 / 09:51:49 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+    "Modified: / 27-09-2018 / 11:17:01 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+!
+
 thread
     ^ thread
 !
@@ -292,6 +332,38 @@
     "Modified: / 27-02-2015 / 15:21:13 / Jan Vrany <jan.vrany@fit.cvut.cz>"
 ! !
 
+!GDBFrame methodsFor:'private'!
+
+registersChanges
+    registersChanges isNil ifTrue:[ 
+        self isValid ifTrue:[
+            registersChanges := GDBTransientDataHolder debugger: debugger factory: [ :old |
+                old isNil ifTrue:[ 
+                    #()
+                ] ifFalse:[
+                    | result changed |
+
+                    result := debugger send: (GDBMI_data_list_changed_registers new arguments: (Array with: '--thread' with: thread id with: '--frame' with: level)).
+                    changed := result propertyAt: #'changed-registers'.
+
+                    changed notEmptyOrNil ifTrue:[ 
+                        result := debugger send: (GDBMI_data_list_register_values new arguments: (Array with: '--thread' with: thread id with: '--frame' with: level with: 'r') , changed).
+                        (result propertyAt: #'register-values') asSet.
+                    ] ifFalse:[ 
+                        #()
+                    ].
+                ].
+            ].
+        ] ifFalse:[ 
+            registersChanges := #().
+        ].
+    ].
+    ^ registersChanges value
+
+    "Created: / 26-09-2018 / 22:35:52 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+    "Modified: / 27-09-2018 / 10:18:46 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+! !
+
 !GDBFrame methodsFor:'testing'!
 
 isValid