diff -r 883c830472cb -r 342b6dfe3a6f GDBFrame.st --- 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 " + "Modified: / 27-09-2018 / 11:17:01 / Jan Vrany " +! + thread ^ thread ! @@ -292,6 +332,38 @@ "Modified: / 27-02-2015 / 15:21:13 / Jan Vrany " ! ! +!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 " + "Modified: / 27-09-2018 / 10:18:46 / Jan Vrany " +! ! + !GDBFrame methodsFor:'testing'! isValid