Add model for machine registers
To access machine registers and their values, a new API method
`GDBFrame >> registersWithValues` is intruced in this commit.
--- a/GDBDebugger.st Wed Sep 26 13:25:40 2018 +0100
+++ b/GDBDebugger.st Wed Sep 26 11:16:56 2018 +0100
@@ -906,12 +906,13 @@
| inferior |
inferior := self inferiorForId:aGDBThreadGroupStartedEvent threadGroupId.
+ inferior reset.
inferior setPid:aGDBThreadGroupStartedEvent pid.
aGDBThreadGroupStartedEvent setThreadGroup:inferior.
"Created: / 06-09-2014 / 02:37:31 / Jan Vrany <jan.vrany@fit.cvut.cz>"
- "Modified (comment): / 07-02-2018 / 12:50:43 / Jan Vrany <jan.vrany@fit.cvut.cz>"
"Modified: / 26-03-2018 / 21:33:11 / jv"
+ "Modified: / 26-09-2018 / 10:57:05 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!
onThreadSelectedEvent: aGDBThreadSelectedEvent
--- a/GDBEventSetProcessingStarted.st Wed Sep 26 13:25:40 2018 +0100
+++ b/GDBEventSetProcessingStarted.st Wed Sep 26 11:16:56 2018 +0100
@@ -50,3 +50,10 @@
"
! !
+!GDBEventSetProcessingStarted class methodsFor:'documentation'!
+
+version_HG
+
+ ^ '$Changeset: <not expanded> $'
+! !
+
--- 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
--- a/GDBMI_data_list_changed_registers.st Wed Sep 26 13:25:40 2018 +0100
+++ b/GDBMI_data_list_changed_registers.st Wed Sep 26 11:16:56 2018 +0100
@@ -98,6 +98,17 @@
^ 'data-list-changed-registers'
! !
+!GDBMI_data_list_changed_registers methodsFor:'accessing-descriptors'!
+
+resultDescription
+ ^ (super resultDescription)
+ define:#'changed-registers' as:Array of: Integer;
+ yourself
+
+ "Created: / 26-09-2018 / 10:37:25 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+ "Modified: / 26-09-2018 / 22:34:09 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+! !
+
!GDBMI_data_list_changed_registers class methodsFor:'documentation'!
version_HG
--- a/GDBMI_data_list_register_values.st Wed Sep 26 13:25:40 2018 +0100
+++ b/GDBMI_data_list_register_values.st Wed Sep 26 11:16:56 2018 +0100
@@ -154,6 +154,16 @@
^ 'data-list-register-values'
! !
+!GDBMI_data_list_register_values methodsFor:'accessing-descriptors'!
+
+resultDescription
+ ^ (super resultDescription)
+ define:#'register-values' as:Array of:GDBRegisterWithValue;
+ yourself
+
+ "Created: / 26-09-2018 / 10:37:25 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+! !
+
!GDBMI_data_list_register_values class methodsFor:'documentation'!
version_HG
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/GDBRegister.st Wed Sep 26 11:16:56 2018 +0100
@@ -0,0 +1,112 @@
+"
+jv:libgdbs - GNU Debugger Interface Library
+Copyright (C) 2015-now Jan Vrany
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+"
+"{ Package: 'jv:libgdbs' }"
+
+"{ NameSpace: Smalltalk }"
+
+GDBObject subclass:#GDBRegister
+ instanceVariableNames:'number name'
+ classVariableNames:''
+ poolDictionaries:''
+ category:'GDB-Core'
+!
+
+!GDBRegister class methodsFor:'documentation'!
+
+copyright
+"
+jv:libgdbs - GNU Debugger Interface Library
+Copyright (C) 2015-now Jan Vrany
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+"
+!
+
+documentation
+"
+ a `GDBRegister` instance represent a single machine
+ register.
+
+ It does not hold a value - value is held in
+ `GDBRegisterWithValue`
+
+
+ [author:]
+ Jan Vrany <jan.vrany@fit.cvut.cz>
+
+ [instance variables:]
+
+ [class variables:]
+
+ [see also:]
+ GDNRegisterWithValue
+ GDBFrame >> registers
+
+"
+! !
+
+!GDBRegister methodsFor:'accessing'!
+
+name
+ ^ name
+!
+
+number
+ ^ number
+! !
+
+!GDBRegister methodsFor:'initialization'!
+
+setName: aString
+ name := aString
+
+ "Created: / 26-09-2018 / 10:06:36 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+!
+
+setNumber: aNumber
+ number := aNumber
+
+ "Created: / 26-09-2018 / 10:06:45 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+! !
+
+!GDBRegister methodsFor:'printing & storing'!
+
+printOn:aStream
+ "append a printed representation of the receiver to the argument, aStream"
+
+ super printOn:aStream.
+ aStream nextPut:$(.
+ name printOn:aStream.
+ aStream nextPut:$).
+
+ "Modified: / 26-09-2018 / 10:10:35 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+! !
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/GDBRegisterWithValue.st Wed Sep 26 11:16:56 2018 +0100
@@ -0,0 +1,174 @@
+"
+jv:libgdbs - GNU Debugger Interface Library
+Copyright (C) 2015-now Jan Vrany
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+"
+"{ Package: 'jv:libgdbs' }"
+
+"{ NameSpace: Smalltalk }"
+
+GDBDebuggerObject subclass:#GDBRegisterWithValue
+ instanceVariableNames:'register frame value changed'
+ classVariableNames:''
+ poolDictionaries:''
+ category:'GDB-Core'
+!
+
+!GDBRegisterWithValue class methodsFor:'documentation'!
+
+copyright
+"
+jv:libgdbs - GNU Debugger Interface Library
+Copyright (C) 2015-now Jan Vrany
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+"
+! !
+
+!GDBRegisterWithValue class methodsFor:'accessing-magritte'!
+
+descriptionContainer
+ ^ super descriptionContainer
+ define: #number as: Integer;
+ define: #value as: String;
+ yourself
+
+ "Created: / 26-09-2018 / 10:38:29 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+! !
+
+!GDBRegisterWithValue methodsFor:'accessing'!
+
+name
+ ^ register name
+
+ "Created: / 27-09-2018 / 10:06:32 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+!
+
+number
+ ^ register isInteger ifTrue:[
+ register
+ ] ifFalse:[
+ register number
+ ]
+
+ "Created: / 27-09-2018 / 09:56:09 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+!
+
+value
+ changed value.
+ ^ value
+
+ "Modified: / 27-09-2018 / 15:26:50 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+! !
+
+!GDBRegisterWithValue methodsFor:'initialization'!
+
+setDebugger: aGDBDebugger
+ super setDebugger: aGDBDebugger.
+ changed := GDBTransientDataHolder debugger: debugger factory: [
+ (frame notNil and:[frame isValid]) ifTrue:[
+ | changes change |
+
+ changes := frame registersChanges.
+ change := changes detect:[:each | each number = self number ] ifNone:[ nil ].
+ (change notNil and:[change value ~= value]) ifTrue:[
+ value := change value.
+ true
+ ] ifFalse:[
+ false
+ ].
+ ] ifFalse:[
+ false
+ ].
+ ].
+
+ "Created: / 27-09-2018 / 15:11:35 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+!
+
+setFrame: aGDBFrame
+ self setDebugger: aGDBFrame debugger.
+ frame := aGDBFrame.
+
+ "Created: / 26-09-2018 / 22:25:39 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+ "Modified: / 27-09-2018 / 15:31:36 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+!
+
+setRegisterFrom: aDictionary
+ self assert: register isInteger.
+ self assert: (aDictionary includesKey: register).
+
+ register := aDictionary at: register.
+
+ "Created: / 26-09-2018 / 10:41:47 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+! !
+
+!GDBRegisterWithValue methodsFor:'printing & storing'!
+
+printOn:aStream
+ "append a printed representation of the receiver to the argument, aStream"
+
+ super printOn:aStream.
+ aStream nextPut:$(.
+ register isInteger ifTrue:[
+ register printOn:aStream.
+ ] ifFalse:[
+ register name printOn:aStream.
+ ].
+ aStream nextPutAll: ': '.
+ value printOn: aStream.
+ aStream nextPut:$).
+
+ "Modified: / 26-09-2018 / 10:48:31 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+! !
+
+!GDBRegisterWithValue methodsFor:'private'!
+
+_number: anInteger
+ register := anInteger
+
+ "Created: / 26-09-2018 / 10:39:14 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+! !
+
+!GDBRegisterWithValue methodsFor:'queries'!
+
+hasChanged
+ "Return true, if the value of this register has changed since last
+ 'stop', false otherwise (i.e., when unchanged)"
+
+ ^ changed value
+
+ "Created: / 27-09-2018 / 16:01:16 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+! !
+
+!GDBRegisterWithValue class methodsFor:'documentation'!
+
+version_HG
+
+ ^ '$Changeset: <not expanded> $'
+! !
+
--- a/GDBThreadGroup.st Wed Sep 26 13:25:40 2018 +0100
+++ b/GDBThreadGroup.st Wed Sep 26 11:16:56 2018 +0100
@@ -23,7 +23,7 @@
"{ NameSpace: Smalltalk }"
GDBDebuggerObject subclass:#GDBThreadGroup
- instanceVariableNames:'id type executable running pid exit_code threads'
+ instanceVariableNames:'id type executable running pid exit_code threads registersMap'
classVariableNames:'ExecutableSentinel'
poolDictionaries:'GDBCommandStatus'
category:'GDB-Core'
@@ -227,8 +227,19 @@
"Invoked when a new instance is created."
running := false.
+ registersMap := Dictionary new.
- "Modified: / 06-06-2017 / 00:25:13 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+ "Modified: / 26-09-2018 / 09:53:17 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+!
+
+reset
+ "Reset all internal caches. Invoked bu debugger when an inferior
+ starts. This is necessary since GDB recycles inferors and so we
+ do."
+
+ registersMap := Dictionary new.
+
+ "Created: / 26-09-2018 / 10:58:11 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!
setExitCode: anInteger
@@ -273,6 +284,12 @@
!GDBThreadGroup methodsFor:'private'!
+registersMap
+ ^ registersMap
+
+ "Created: / 26-09-2018 / 10:01:03 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+!
+
threadAdd: aGDBThread
self threads add: aGDBThread
--- a/Make.proto Wed Sep 26 13:25:40 2018 +0100
+++ b/Make.proto Wed Sep 26 11:16:56 2018 +0100
@@ -172,6 +172,7 @@
$(OUTDIR)GDBMITracer.$(O) GDBMITracer.$(C) GDBMITracer.$(H): GDBMITracer.st $(INCLUDE_TOP)/jv/libgdbs/GDBDebugFlags.$(H) $(INCLUDE_TOP)/stx/libbasic/Object.$(H) $(STCHDR)
$(OUTDIR)GDBMemoryDump.$(O) GDBMemoryDump.$(C) GDBMemoryDump.$(H): GDBMemoryDump.st $(INCLUDE_TOP)/jv/libgdbs/GDBObject.$(H) $(INCLUDE_TOP)/stx/libbasic/Object.$(H) $(STCHDR)
$(OUTDIR)GDBMemoryDumpRow.$(O) GDBMemoryDumpRow.$(C) GDBMemoryDumpRow.$(H): GDBMemoryDumpRow.st $(INCLUDE_TOP)/jv/libgdbs/GDBObject.$(H) $(INCLUDE_TOP)/stx/libbasic/Object.$(H) $(STCHDR)
+$(OUTDIR)GDBRegister.$(O) GDBRegister.$(C) GDBRegister.$(H): GDBRegister.st $(INCLUDE_TOP)/jv/libgdbs/GDBObject.$(H) $(INCLUDE_TOP)/stx/libbasic/Object.$(H) $(STCHDR)
$(OUTDIR)GDBStreamOutputEvent.$(O) GDBStreamOutputEvent.$(C) GDBStreamOutputEvent.$(H): GDBStreamOutputEvent.st $(INCLUDE_TOP)/jv/libgdbs/GDBEvent.$(H) $(INCLUDE_TOP)/stx/goodies/announcements/Announcement.$(H) $(INCLUDE_TOP)/stx/libbasic/Object.$(H) $(STCHDR)
$(OUTDIR)GDBThreadGroupTypeProcess.$(O) GDBThreadGroupTypeProcess.$(C) GDBThreadGroupTypeProcess.$(H): GDBThreadGroupTypeProcess.st $(INCLUDE_TOP)/jv/libgdbs/GDBThreadGroupType.$(H) $(INCLUDE_TOP)/stx/libbasic/Object.$(H) $(STCHDR)
$(OUTDIR)GDBThreadInfo.$(O) GDBThreadInfo.$(C) GDBThreadInfo.$(H): GDBThreadInfo.st $(INCLUDE_TOP)/jv/libgdbs/GDBObject.$(H) $(INCLUDE_TOP)/stx/libbasic/Object.$(H) $(STCHDR)
@@ -301,6 +302,7 @@
$(OUTDIR)GDBMI_var_show_format.$(O) GDBMI_var_show_format.$(C) GDBMI_var_show_format.$(H): GDBMI_var_show_format.st $(INCLUDE_TOP)/jv/libgdbs/GDBCommand.$(H) $(INCLUDE_TOP)/jv/libgdbs/GDBMICommand.$(H) $(INCLUDE_TOP)/stx/libbasic/Object.$(H) $(STCHDR)
$(OUTDIR)GDBMI_var_update.$(O) GDBMI_var_update.$(C) GDBMI_var_update.$(H): GDBMI_var_update.st $(INCLUDE_TOP)/jv/libgdbs/GDBCommand.$(H) $(INCLUDE_TOP)/jv/libgdbs/GDBMICommand.$(H) $(INCLUDE_TOP)/stx/libbasic/Object.$(H) $(STCHDR)
$(OUTDIR)GDBNotificationEvent.$(O) GDBNotificationEvent.$(C) GDBNotificationEvent.$(H): GDBNotificationEvent.st $(INCLUDE_TOP)/jv/libgdbs/GDBAsyncEvent.$(H) $(INCLUDE_TOP)/jv/libgdbs/GDBEvent.$(H) $(INCLUDE_TOP)/stx/goodies/announcements/Announcement.$(H) $(INCLUDE_TOP)/stx/libbasic/Object.$(H) $(STCHDR)
+$(OUTDIR)GDBRegisterWithValue.$(O) GDBRegisterWithValue.$(C) GDBRegisterWithValue.$(H): GDBRegisterWithValue.st $(INCLUDE_TOP)/jv/libgdbs/GDBDebuggerObject.$(H) $(INCLUDE_TOP)/jv/libgdbs/GDBObject.$(H) $(INCLUDE_TOP)/stx/libbasic/Object.$(H) $(STCHDR)
$(OUTDIR)GDBSelectedFrameChangedEvent.$(O) GDBSelectedFrameChangedEvent.$(C) GDBSelectedFrameChangedEvent.$(H): GDBSelectedFrameChangedEvent.st $(INCLUDE_TOP)/jv/libgdbs/GDBEvent.$(H) $(INCLUDE_TOP)/jv/libgdbs/GDBInternalEvent.$(H) $(INCLUDE_TOP)/stx/goodies/announcements/Announcement.$(H) $(INCLUDE_TOP)/stx/libbasic/Object.$(H) $(STCHDR)
$(OUTDIR)GDBStatusEvent.$(O) GDBStatusEvent.$(C) GDBStatusEvent.$(H): GDBStatusEvent.st $(INCLUDE_TOP)/jv/libgdbs/GDBAsyncEvent.$(H) $(INCLUDE_TOP)/jv/libgdbs/GDBEvent.$(H) $(INCLUDE_TOP)/stx/goodies/announcements/Announcement.$(H) $(INCLUDE_TOP)/stx/libbasic/Object.$(H) $(STCHDR)
$(OUTDIR)GDBTargetOutputEvent.$(O) GDBTargetOutputEvent.$(C) GDBTargetOutputEvent.$(H): GDBTargetOutputEvent.st $(INCLUDE_TOP)/jv/libgdbs/GDBEvent.$(H) $(INCLUDE_TOP)/jv/libgdbs/GDBStreamOutputEvent.$(H) $(INCLUDE_TOP)/stx/goodies/announcements/Announcement.$(H) $(INCLUDE_TOP)/stx/libbasic/Object.$(H) $(STCHDR)
--- a/Make.spec Wed Sep 26 13:25:40 2018 +0100
+++ b/Make.spec Wed Sep 26 11:16:56 2018 +0100
@@ -96,6 +96,7 @@
GDBMITracer \
GDBMemoryDump \
GDBMemoryDumpRow \
+ GDBRegister \
GDBStreamOutputEvent \
GDBThreadGroupTypeProcess \
GDBThreadInfo \
@@ -225,6 +226,7 @@
GDBMI_var_show_format \
GDBMI_var_update \
GDBNotificationEvent \
+ GDBRegisterWithValue \
GDBSelectedFrameChangedEvent \
GDBStatusEvent \
GDBTargetOutputEvent \
@@ -304,6 +306,7 @@
$(OUTDIR)GDBMITracer.$(O) \
$(OUTDIR)GDBMemoryDump.$(O) \
$(OUTDIR)GDBMemoryDumpRow.$(O) \
+ $(OUTDIR)GDBRegister.$(O) \
$(OUTDIR)GDBStreamOutputEvent.$(O) \
$(OUTDIR)GDBThreadGroupTypeProcess.$(O) \
$(OUTDIR)GDBThreadInfo.$(O) \
@@ -433,6 +436,7 @@
$(OUTDIR)GDBMI_var_show_format.$(O) \
$(OUTDIR)GDBMI_var_update.$(O) \
$(OUTDIR)GDBNotificationEvent.$(O) \
+ $(OUTDIR)GDBRegisterWithValue.$(O) \
$(OUTDIR)GDBSelectedFrameChangedEvent.$(O) \
$(OUTDIR)GDBStatusEvent.$(O) \
$(OUTDIR)GDBTargetOutputEvent.$(O) \
--- a/abbrev.stc Wed Sep 26 13:25:40 2018 +0100
+++ b/abbrev.stc Wed Sep 26 11:16:56 2018 +0100
@@ -46,6 +46,8 @@
GDBMITracer GDBMITracer jv:libgdbs 'GDB-Private-MI Trace' 0
GDBMemoryDump GDBMemoryDump jv:libgdbs 'GDB-Core' 0
GDBMemoryDumpRow GDBMemoryDumpRow jv:libgdbs 'GDB-Core' 0
+GDBRegister GDBRegister jv:libgdbs 'GDB-Core' 0
+GDBRegisterWithValue GDBRegisterWithValue jv:libgdbs 'GDB-Core' 0
GDBStreamOutputEvent GDBStreamOutputEvent jv:libgdbs 'GDB-Core-Events' 0
GDBThreadGroupTypeProcess GDBThreadGroupTypeProcess jv:libgdbs 'GDB-Core' 1
GDBThreadInfo GDBThreadInfo jv:libgdbs 'GDB-Private' 0
--- a/bc.mak Wed Sep 26 13:25:40 2018 +0100
+++ b/bc.mak Wed Sep 26 11:16:56 2018 +0100
@@ -119,6 +119,7 @@
$(OUTDIR)GDBMITracer.$(O) GDBMITracer.$(C) GDBMITracer.$(H): GDBMITracer.st $(INCLUDE_TOP)\jv\libgdbs\GDBDebugFlags.$(H) $(INCLUDE_TOP)\stx\libbasic\Object.$(H) $(STCHDR)
$(OUTDIR)GDBMemoryDump.$(O) GDBMemoryDump.$(C) GDBMemoryDump.$(H): GDBMemoryDump.st $(INCLUDE_TOP)\jv\libgdbs\GDBObject.$(H) $(INCLUDE_TOP)\stx\libbasic\Object.$(H) $(STCHDR)
$(OUTDIR)GDBMemoryDumpRow.$(O) GDBMemoryDumpRow.$(C) GDBMemoryDumpRow.$(H): GDBMemoryDumpRow.st $(INCLUDE_TOP)\jv\libgdbs\GDBObject.$(H) $(INCLUDE_TOP)\stx\libbasic\Object.$(H) $(STCHDR)
+$(OUTDIR)GDBRegister.$(O) GDBRegister.$(C) GDBRegister.$(H): GDBRegister.st $(INCLUDE_TOP)\jv\libgdbs\GDBObject.$(H) $(INCLUDE_TOP)\stx\libbasic\Object.$(H) $(STCHDR)
$(OUTDIR)GDBStreamOutputEvent.$(O) GDBStreamOutputEvent.$(C) GDBStreamOutputEvent.$(H): GDBStreamOutputEvent.st $(INCLUDE_TOP)\jv\libgdbs\GDBEvent.$(H) $(INCLUDE_TOP)\stx\goodies\announcements\Announcement.$(H) $(INCLUDE_TOP)\stx\libbasic\Object.$(H) $(STCHDR)
$(OUTDIR)GDBThreadGroupTypeProcess.$(O) GDBThreadGroupTypeProcess.$(C) GDBThreadGroupTypeProcess.$(H): GDBThreadGroupTypeProcess.st $(INCLUDE_TOP)\jv\libgdbs\GDBThreadGroupType.$(H) $(INCLUDE_TOP)\stx\libbasic\Object.$(H) $(STCHDR)
$(OUTDIR)GDBThreadInfo.$(O) GDBThreadInfo.$(C) GDBThreadInfo.$(H): GDBThreadInfo.st $(INCLUDE_TOP)\jv\libgdbs\GDBObject.$(H) $(INCLUDE_TOP)\stx\libbasic\Object.$(H) $(STCHDR)
@@ -248,6 +249,7 @@
$(OUTDIR)GDBMI_var_show_format.$(O) GDBMI_var_show_format.$(C) GDBMI_var_show_format.$(H): GDBMI_var_show_format.st $(INCLUDE_TOP)\jv\libgdbs\GDBCommand.$(H) $(INCLUDE_TOP)\jv\libgdbs\GDBMICommand.$(H) $(INCLUDE_TOP)\stx\libbasic\Object.$(H) $(STCHDR)
$(OUTDIR)GDBMI_var_update.$(O) GDBMI_var_update.$(C) GDBMI_var_update.$(H): GDBMI_var_update.st $(INCLUDE_TOP)\jv\libgdbs\GDBCommand.$(H) $(INCLUDE_TOP)\jv\libgdbs\GDBMICommand.$(H) $(INCLUDE_TOP)\stx\libbasic\Object.$(H) $(STCHDR)
$(OUTDIR)GDBNotificationEvent.$(O) GDBNotificationEvent.$(C) GDBNotificationEvent.$(H): GDBNotificationEvent.st $(INCLUDE_TOP)\jv\libgdbs\GDBAsyncEvent.$(H) $(INCLUDE_TOP)\jv\libgdbs\GDBEvent.$(H) $(INCLUDE_TOP)\stx\goodies\announcements\Announcement.$(H) $(INCLUDE_TOP)\stx\libbasic\Object.$(H) $(STCHDR)
+$(OUTDIR)GDBRegisterWithValue.$(O) GDBRegisterWithValue.$(C) GDBRegisterWithValue.$(H): GDBRegisterWithValue.st $(INCLUDE_TOP)\jv\libgdbs\GDBDebuggerObject.$(H) $(INCLUDE_TOP)\jv\libgdbs\GDBObject.$(H) $(INCLUDE_TOP)\stx\libbasic\Object.$(H) $(STCHDR)
$(OUTDIR)GDBSelectedFrameChangedEvent.$(O) GDBSelectedFrameChangedEvent.$(C) GDBSelectedFrameChangedEvent.$(H): GDBSelectedFrameChangedEvent.st $(INCLUDE_TOP)\jv\libgdbs\GDBEvent.$(H) $(INCLUDE_TOP)\jv\libgdbs\GDBInternalEvent.$(H) $(INCLUDE_TOP)\stx\goodies\announcements\Announcement.$(H) $(INCLUDE_TOP)\stx\libbasic\Object.$(H) $(STCHDR)
$(OUTDIR)GDBStatusEvent.$(O) GDBStatusEvent.$(C) GDBStatusEvent.$(H): GDBStatusEvent.st $(INCLUDE_TOP)\jv\libgdbs\GDBAsyncEvent.$(H) $(INCLUDE_TOP)\jv\libgdbs\GDBEvent.$(H) $(INCLUDE_TOP)\stx\goodies\announcements\Announcement.$(H) $(INCLUDE_TOP)\stx\libbasic\Object.$(H) $(STCHDR)
$(OUTDIR)GDBTargetOutputEvent.$(O) GDBTargetOutputEvent.$(C) GDBTargetOutputEvent.$(H): GDBTargetOutputEvent.st $(INCLUDE_TOP)\jv\libgdbs\GDBEvent.$(H) $(INCLUDE_TOP)\jv\libgdbs\GDBStreamOutputEvent.$(H) $(INCLUDE_TOP)\stx\goodies\announcements\Announcement.$(H) $(INCLUDE_TOP)\stx\libbasic\Object.$(H) $(STCHDR)
--- a/jv_libgdbs.st Wed Sep 26 13:25:40 2018 +0100
+++ b/jv_libgdbs.st Wed Sep 26 11:16:56 2018 +0100
@@ -161,6 +161,8 @@
GDBMITracer
GDBMemoryDump
GDBMemoryDumpRow
+ GDBRegister
+ GDBRegisterWithValue
GDBStreamOutputEvent
GDBThreadGroupTypeProcess
GDBThreadInfo
--- a/libInit.cc Wed Sep 26 13:25:40 2018 +0100
+++ b/libInit.cc Wed Sep 26 11:16:56 2018 +0100
@@ -61,6 +61,7 @@
extern void _GDBMITracer_Init(int pass, struct __vmData__ *__pRT__, OBJ snd);
extern void _GDBMemoryDump_Init(int pass, struct __vmData__ *__pRT__, OBJ snd);
extern void _GDBMemoryDumpRow_Init(int pass, struct __vmData__ *__pRT__, OBJ snd);
+extern void _GDBRegister_Init(int pass, struct __vmData__ *__pRT__, OBJ snd);
extern void _GDBStreamOutputEvent_Init(int pass, struct __vmData__ *__pRT__, OBJ snd);
extern void _GDBThreadGroupTypeProcess_Init(int pass, struct __vmData__ *__pRT__, OBJ snd);
extern void _GDBThreadInfo_Init(int pass, struct __vmData__ *__pRT__, OBJ snd);
@@ -190,6 +191,7 @@
extern void _GDBMI_137var_137show_137format_Init(int pass, struct __vmData__ *__pRT__, OBJ snd);
extern void _GDBMI_137var_137update_Init(int pass, struct __vmData__ *__pRT__, OBJ snd);
extern void _GDBNotificationEvent_Init(int pass, struct __vmData__ *__pRT__, OBJ snd);
+extern void _GDBRegisterWithValue_Init(int pass, struct __vmData__ *__pRT__, OBJ snd);
extern void _GDBSelectedFrameChangedEvent_Init(int pass, struct __vmData__ *__pRT__, OBJ snd);
extern void _GDBStatusEvent_Init(int pass, struct __vmData__ *__pRT__, OBJ snd);
extern void _GDBTargetOutputEvent_Init(int pass, struct __vmData__ *__pRT__, OBJ snd);
@@ -278,6 +280,7 @@
_GDBMITracer_Init(pass,__pRT__,snd);
_GDBMemoryDump_Init(pass,__pRT__,snd);
_GDBMemoryDumpRow_Init(pass,__pRT__,snd);
+ _GDBRegister_Init(pass,__pRT__,snd);
_GDBStreamOutputEvent_Init(pass,__pRT__,snd);
_GDBThreadGroupTypeProcess_Init(pass,__pRT__,snd);
_GDBThreadInfo_Init(pass,__pRT__,snd);
@@ -407,6 +410,7 @@
_GDBMI_137var_137show_137format_Init(pass,__pRT__,snd);
_GDBMI_137var_137update_Init(pass,__pRT__,snd);
_GDBNotificationEvent_Init(pass,__pRT__,snd);
+ _GDBRegisterWithValue_Init(pass,__pRT__,snd);
_GDBSelectedFrameChangedEvent_Init(pass,__pRT__,snd);
_GDBStatusEvent_Init(pass,__pRT__,snd);
_GDBTargetOutputEvent_Init(pass,__pRT__,snd);
--- a/tests/GDBDebuggerTestsR.st Wed Sep 26 13:25:40 2018 +0100
+++ b/tests/GDBDebuggerTestsR.st Wed Sep 26 11:16:56 2018 +0100
@@ -450,6 +450,59 @@
"Created: / 07-02-2018 / 10:56:59 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!
+test_registers_01a
+ | stack rax rip rsp raxValue1 ripValue1 rspValue1 raxValue2 ripValue2 rspValue2 |
+
+ debugger := GDBDebugger new.
+ self assert: debugger isConnected.
+ debugger executable: GDBDebuggeesResource current binaryFactorial1.
+ debugger send: 'b factorial'.
+ debugger send: 'r' andWaitFor: GDBStoppedEvent.
+ debugger send: 'c' andWaitFor: GDBStoppedEvent.
+
+ stack := debugger selectedInferior threads first stack.
+ self assert: stack size == 3.
+
+ self skipIf: (stack first arch name ~= 'x86_64') description: 'not supported on this architecture'.
+
+ rax := stack first registers detect:[:reg | reg name = 'rax' ].
+ rip := stack first registers detect:[:reg | reg name = 'rip' ].
+ rsp := stack first registers detect:[:reg | reg name = 'rsp' ].
+
+ self assert: rax hasChanged not.
+ self assert: rip hasChanged not.
+ self assert: rsp hasChanged not.
+
+ raxValue1 := rax value.
+ ripValue1 := rip value.
+ rspValue1 := rsp value.
+
+ debugger send: 'stepi' andWaitFor: GDBStoppedEvent.
+ debugger send: 'stepi' andWaitFor: GDBStoppedEvent.
+ debugger send: 'stepi' andWaitFor: GDBStoppedEvent.
+ debugger send: 'stepi' andWaitFor: GDBStoppedEvent.
+
+ raxValue2 := rax value.
+ ripValue2 := rip value.
+ rspValue2 := rsp value.
+
+ self assert: raxValue1 ~= raxValue2.
+ self assert: ripValue1 ~= ripValue2.
+ self assert: rspValue1 = rspValue2.
+
+ self assert: rax hasChanged.
+ self assert: rip hasChanged.
+ self assert: rsp hasChanged not.
+
+
+ debugger send: 'd'.
+ debugger send: 'c' andWaitFor: GDBThreadGroupExitedEvent.
+ debugger send: 'quit' andWait: false.
+
+ "Created: / 27-09-2018 / 10:45:20 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+ "Modified: / 27-09-2018 / 16:02:31 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+!
+
test_stack_01a
"Tests that stack frames object are preserved amonh run/stop cycles
if they 're still valid"