--- 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