API: add `GDBDebugger >> getParameter:` and `setParameter:to:`
...to get / set GDB internal parameters such as prompt. The only
complication here is that when a parameter is set by MI `-gdb-set`
command, the `=cmd-param-changed' notification is not sent. This
may or may not be a GDB bug.
To make this transparent to `libgdbs` clients, intercept all `-gdb-set`
commands and when sucessful, emit the event manually. This way, client
may rely on value change notification (`GDBCmdParamChangedEvent`) to
detect changes.
--- a/GDBCmdParamChangedEvent.st Wed Jan 16 23:42:24 2019 +0000
+++ b/GDBCmdParamChangedEvent.st Sat Jan 19 23:25:55 2019 +0000
@@ -50,6 +50,21 @@
"
! !
+!GDBCmdParamChangedEvent class methodsFor:'instance creation'!
+
+name: name value: value
+ ^ self new
+ propertyAt: #param put: name;
+ propertyAt: #value put: value;
+ yourself.
+
+ "
+ GDBCmdParamChangedEvent name: 'prompt' value: '> '
+ "
+
+ "Created: / 19-01-2019 / 22:33:39 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+! !
+
!GDBCmdParamChangedEvent methodsFor:'accessing'!
name
--- a/GDBCommandResult.st Wed Jan 16 23:42:24 2019 +0000
+++ b/GDBCommandResult.st Sat Jan 19 23:25:55 2019 +0000
@@ -117,6 +117,22 @@
"Modified: / 30-12-2018 / 20:01:33 / Jan Vrany <jan.vrany@fit.cvut.cz>"
! !
+!GDBCommandResult methodsFor:'printing & storing'!
+
+printOn:aStream
+ "append a printed representation of the receiver to the argument, aStream"
+
+ super printOn:aStream.
+ aStream
+ nextPut:$(;
+ nextPutAll: status;
+ nextPutAll:': ';
+ nextPutAll: command asString;
+ nextPut:$).
+
+ "Modified: / 19-01-2019 / 22:58:12 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+! !
+
!GDBCommandResult methodsFor:'testing'!
isDone
--- a/GDBCommandResultEvent.st Wed Jan 16 23:42:24 2019 +0000
+++ b/GDBCommandResultEvent.st Sat Jan 19 23:25:55 2019 +0000
@@ -56,8 +56,8 @@
^ result
!
-result:something
- result := something.
+result:aGDBCommandResult
+ result := aGDBCommandResult.
!
status
@@ -74,6 +74,22 @@
"Created: / 01-03-2015 / 08:56:04 / Jan Vrany <jan.vrany@fit.cvut.cz>"
! !
+!GDBCommandResultEvent methodsFor:'printing & storing'!
+
+printOn:aStream
+ "append a printed representation of the receiver to the argument, aStream"
+
+ super printOn:aStream.
+ aStream
+ nextPut:$(;
+ nextPutAll: result status;
+ nextPutAll:': ';
+ nextPutAll: result command asString;
+ nextPut:$).
+
+ "Created: / 19-01-2019 / 22:59:13 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+! !
+
!GDBCommandResultEvent methodsFor:'testing'!
isCommandResultEvent
--- a/GDBDebugger.st Wed Jan 16 23:42:24 2019 +0000
+++ b/GDBDebugger.st Sat Jan 19 23:25:55 2019 +0000
@@ -354,7 +354,7 @@
self assert: self isConnected.
command isString ifTrue:[
- commandObject := (GDBMIParser on:command) parseCommand.
+ commandObject := GDBCommand parse: command.
commandObject token:self nextCommandSequnceNumber.
] ifFalse:[
commandObject := command.
@@ -368,7 +368,7 @@
withTimeoutMs: timeout
"Created: / 07-03-2015 / 11:38:45 / Jan Vrany <jan.vrany@fit.cvut.cz>"
- "Modified (format): / 04-02-2018 / 00:20:53 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+ "Modified: / 19-01-2019 / 23:05:35 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!
send:command andWithResultDo: block
@@ -397,7 +397,7 @@
self assert: self isConnected.
cmd := command.
cmd isString ifTrue:[
- cmd := GDBCLICommand new value:cmd.
+ cmd := GDBCommand parse:cmd.
].
token := self nextCommandSequnceNumber.
cmd token:token.
@@ -419,7 +419,7 @@
"Created: / 26-01-2018 / 21:47:34 / Jan Vrany <jan.vrany@fit.cvut.cz>"
"Modified: / 26-03-2018 / 21:48:02 / jv"
- "Modified (comment): / 01-01-2019 / 11:31:17 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+ "Modified: / 19-01-2019 / 23:06:26 / Jan Vrany <jan.vrany@fit.cvut.cz>"
! !
!GDBDebugger methodsFor:'commands - API'!
@@ -594,6 +594,22 @@
"Modified: / 09-02-2018 / 09:44:54 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!
+getParameter:name
+ "Teturn the current value of a GDB parameter.
+ See `show` GDB command.
+
+ Subscribe to `GDBCmdParamChangedEvent` to get notified
+ when parameter value changes.
+ "
+
+ | result |
+
+ result := self send:(GDBMI_gdb_show arguments:(Array with:name)).
+ ^ result propertyAt:#value.
+
+ "Created: / 19-01-2019 / 21:55:09 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+!
+
selectFrame: aGDBFrame
"
Set the context frame to given frame. This frame is then
@@ -616,6 +632,20 @@
"Created: / 01-02-2018 / 22:25:32 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!
+setParameter:name to:value
+ "Set an internal GDB parameter named `name` to `value`.
+ See `set` GDB command.
+
+ Subscribe to `GDBCmdParamChangedEvent` to get notified
+ when parameter value changes.
+ "
+
+ self assert:value isString.
+ self send:(GDBMI_gdb_set arguments:(Array with:name with:value)).
+
+ "Created: / 19-01-2019 / 21:56:47 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+!
+
targetConnect: type parameters: parameters
"Connect to the remote target. `type` is the type of target,
for instance ‘extended-remote=’. `parameters` are device names,
@@ -795,6 +825,29 @@
"Modified: / 20-06-2014 / 22:09:57 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!
+onCommandResultEvent:aGDBCommandResultEvent
+ | result |
+
+ result := aGDBCommandResultEvent result.
+
+ "/ For some reason, -gdb-set MI command does not cause
+ "/ =cmd-param-changed notification. To make this transparent
+ "/ for users, catch successful -gdb-set here and send
+ "/ GDBCmdParamChangedEvent manually. Sigh, what a hack!!
+ (result isDone
+ and:[ result command notNil
+ and:[ result command isMICommand
+ and:[ result command operation = 'gdb-set' ]]]) ifTrue:[
+ | event |
+
+ event := GDBCmdParamChangedEvent name: result command arguments first value: result command arguments second.
+ connection pushEvent: event.
+ ].
+
+ "Created: / 19-01-2019 / 22:35:45 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+ "Modified: / 21-01-2019 / 17:53:03 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+!
+
onExitEvent:aGDBExitEvent
self release.
@@ -988,6 +1041,7 @@
subscribe
connection eventAnnouncerInternal
when: GDBCommandEvent send: #onCommandEvent: to: self;
+ when: GDBCommandResultEvent send: #onCommandResultEvent: to: self;
when: GDBExitEvent send: #onExitEvent: to: self;
when: GDBThreadGroupAddedEvent send: #onThreadGroupAddedEvent: to: self;
@@ -1009,7 +1063,7 @@
when: GDBCmdParamChangedEvent send: #onCmdParamChangedEvent: to: self.
"Created: / 20-06-2014 / 22:07:04 / Jan Vrany <jan.vrany@fit.cvut.cz>"
- "Modified: / 29-07-2018 / 22:18:44 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+ "Modified: / 19-01-2019 / 22:20:56 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!
unsubscribe
--- a/tests/GDBDebuggerTestsR.st Wed Jan 16 23:42:24 2019 +0000
+++ b/tests/GDBDebuggerTestsR.st Sat Jan 19 23:25:55 2019 +0000
@@ -475,6 +475,37 @@
"Modified: / 18-10-2018 / 10:56:28 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!
+test_parameters_01
+ | event |
+
+ debugger announcer when: GDBCmdParamChangedEvent do:[:ev | event := ev ].
+
+ debugger send: 'set prompt > '.
+ self assert: (debugger getParameter: 'prompt') = '> '.
+ self assert: event notNil.
+ self assert: event name = 'prompt'.
+ self assert: event value = '> '.
+
+ event := nil.
+ debugger setParameter: 'prompt' to: '$'.
+ self assert: (debugger getParameter: 'prompt') = '$'.
+ self assert: event notNil.
+ self assert: event name = 'prompt'.
+ self assert: event value = '$'.
+
+ event := nil.
+ debugger send: '-gdb-set prompt X'.
+ self assert: (debugger getParameter: 'prompt') = 'X'.
+ self assert: event notNil.
+ self assert: event name = 'prompt'.
+ self assert: event value = 'X'.
+
+
+ debugger send: 'quit' andWait: false.
+
+ "Created: / 19-01-2019 / 22:51:54 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+!
+
test_registers_01a
| stack rax rip rsp raxValue1 ripValue1 rspValue1 raxValue2 ripValue2 rspValue2 |