Fix register-setting response from DAP
authorTom Tromey <tromey@adacore.com>
Wed, 4 Oct 2023 18:58:32 +0000 (12:58 -0600)
committerTom Tromey <tromey@adacore.com>
Mon, 16 Oct 2023 15:27:28 +0000 (09:27 -0600)
Andry noticed that given a DAP setExpression request, where the
expression to set is a register, DAP will return the wrong value -- it
will return the old value, not the updated one.

This happens because gdb.Value.assign (which was recently added for
DAP) does not update the value.

In this patch, I chose to have the assign method update the Value
in-place.  It's also possible to have it return a new value, but this
didn't seem very useful to me.

gdb/python/py-value.c
gdb/testsuite/gdb.dap/scopes.exp

index 245de68e0b9fb26c68ac5d8c9b93491c6a0de5f5..0bf1d6e0daeb27aec2e78294254fe2496cf21c55 100644 (file)
@@ -905,7 +905,13 @@ valpy_assign (PyObject *self_obj, PyObject *args)
   try
     {
       value_object *self = (value_object *) self_obj;
-      value_assign (self->value, val);
+      value *new_value = value_assign (self->value, val);
+      /* value_as_address returns a new value with the same location
+        as the old one.  Ensure that this gdb.Value is updated to
+        reflect the new value.  */
+      new_value->incref ();
+      self->value->decref ();
+      self->value = new_value;
     }
   catch (const gdb_exception &except)
     {
index 003557cf3238ccf66ab275632605de7ff5bf6bb5..db815d2d5aaf026dc0618321bb639f548a2f8336 100644 (file)
@@ -125,8 +125,27 @@ gdb_assert {[llength $deivals] == 2} "dei has two members"
 
 set num [dict get $reg_scope variablesReference]
 # The request succeeding is sufficient.
-dap_check_request_and_response "fetch first register" \
-    "variables" \
-    [format {o variablesReference [i %d] count [i 1]} $num]
+set val [dap_check_request_and_response "fetch first register" \
+            "variables" \
+            [format {o variablesReference [i %d] count [i 1]} $num]]
+
+# Try setting the value to something else.
+set val [dict get [lindex $val 0] body variables]
+set name [dict get [lindex $val 0] name]
+set val [dict get [lindex $val 0] value]
+# Just make sure it is different from the original value.
+set val [expr {$val ^ 7}]
+
+# setVariable isn't implemented yet, so use the register name.  Note
+# that we sneak the "$" into the name, written in a slightly funny way
+# to work around apparent TON limitations.
+set response [dap_check_request_and_response "set first register" \
+                 setExpression \
+                 [format {o expression [s \$%s] value [s %d] frameId [i %d]} \
+                      $name $val $frame_id]]
+set response [lindex $response 0]
+
+gdb_assert {[dict get $response body value] == $val} \
+    "setting register yields updated value"
 
 dap_shutdown