aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gdb/NEWS4
-rw-r--r--gdb/doc/python.texi23
-rw-r--r--gdb/python/py-value.c77
-rw-r--r--gdb/python/python-internal.h2
-rw-r--r--gdb/python/python.c8
-rw-r--r--gdb/testsuite/gdb.python/python.exp20
6 files changed, 132 insertions, 2 deletions
diff --git a/gdb/NEWS b/gdb/NEWS
index 392e299..5b5c467 100644
--- a/gdb/NEWS
+++ b/gdb/NEWS
@@ -42,6 +42,10 @@ set|show record btrace cpu
** gdb.execute can now execute multi-line gdb commands.
+ ** The new functions gdb.convenience_variable and
+ gdb.set_convenience_variable can be used to get and set the value
+ of convenience variables.
+
* New targets
RiscV ELF riscv*-*-elf
diff --git a/gdb/doc/python.texi b/gdb/doc/python.texi
index 4182b60..60e016a 100644
--- a/gdb/doc/python.texi
+++ b/gdb/doc/python.texi
@@ -288,6 +288,26 @@ If no exception is raised, the return value is always an instance of
@code{gdb.Value} (@pxref{Values From Inferior}).
@end defun
+@findex gdb.convenience_variable
+@defun gdb.convenience_variable (name)
+Return the value of the convenience variable (@pxref{Convenience
+Vars}) named @var{name}. @var{name} must be a string. The name
+should not include the @samp{$} that is used to mark a convenience
+variable in an expression. If the convenience variable does not
+exist, then @code{None} is returned.
+@end defun
+
+@findex gdb.set_convenience_variable
+@defun gdb.set_convenience_variable (name, value)
+Set the value of the convenience variable (@pxref{Convenience Vars})
+named @var{name}. @var{name} must be a string. The name should not
+include the @samp{$} that is used to mark a convenience variable in an
+expression. If @var{value} is @code{None}, then the convenience
+variable is removed. Otherwise, if @var{value} is not a
+@code{gdb.Value} (@pxref{Values From Inferior}), it is is converted
+using the @code{gdb.Value} constructor.
+@end defun
+
@findex gdb.parse_and_eval
@defun gdb.parse_and_eval (expression)
Parse @var{expression}, which must be a string, as an expression in
@@ -297,8 +317,7 @@ the current language, evaluate it, and return the result as a
This function can be useful when implementing a new command
(@pxref{Commands In Python}), as it provides a way to parse the
command's argument as an expression. It is also useful simply to
-compute values, for example, it is the only way to get the value of a
-convenience variable (@pxref{Convenience Vars}) as a @code{gdb.Value}.
+compute values.
@end defun
@findex gdb.find_pc_line
diff --git a/gdb/python/py-value.c b/gdb/python/py-value.c
index bba6d0b..30a0082 100644
--- a/gdb/python/py-value.c
+++ b/gdb/python/py-value.c
@@ -1746,6 +1746,83 @@ gdbpy_history (PyObject *self, PyObject *args)
return value_to_value_object (res_val);
}
+/* Return the value of a convenience variable. */
+PyObject *
+gdbpy_convenience_variable (PyObject *self, PyObject *args)
+{
+ const char *varname;
+ struct value *res_val = NULL;
+
+ if (!PyArg_ParseTuple (args, "s", &varname))
+ return NULL;
+
+ TRY
+ {
+ struct internalvar *var = lookup_only_internalvar (varname);
+
+ if (var != NULL)
+ {
+ res_val = value_of_internalvar (python_gdbarch, var);
+ if (TYPE_CODE (value_type (res_val)) == TYPE_CODE_VOID)
+ res_val = NULL;
+ }
+ }
+ CATCH (except, RETURN_MASK_ALL)
+ {
+ GDB_PY_HANDLE_EXCEPTION (except);
+ }
+ END_CATCH
+
+ if (res_val == NULL)
+ Py_RETURN_NONE;
+
+ return value_to_value_object (res_val);
+}
+
+/* Set the value of a convenience variable. */
+PyObject *
+gdbpy_set_convenience_variable (PyObject *self, PyObject *args)
+{
+ const char *varname;
+ PyObject *value_obj;
+ struct value *value = NULL;
+
+ if (!PyArg_ParseTuple (args, "sO", &varname, &value_obj))
+ return NULL;
+
+ /* None means to clear the variable. */
+ if (value_obj != Py_None)
+ {
+ value = convert_value_from_python (value_obj);
+ if (value == NULL)
+ return NULL;
+ }
+
+ TRY
+ {
+ if (value == NULL)
+ {
+ struct internalvar *var = lookup_only_internalvar (varname);
+
+ if (var != NULL)
+ clear_internalvar (var);
+ }
+ else
+ {
+ struct internalvar *var = lookup_internalvar (varname);
+
+ set_internalvar (var, value);
+ }
+ }
+ CATCH (except, RETURN_MASK_ALL)
+ {
+ GDB_PY_HANDLE_EXCEPTION (except);
+ }
+ END_CATCH
+
+ Py_RETURN_NONE;
+}
+
/* Returns 1 in OBJ is a gdb.Value object, 0 otherwise. */
int
diff --git a/gdb/python/python-internal.h b/gdb/python/python-internal.h
index 26400f4..495655e 100644
--- a/gdb/python/python-internal.h
+++ b/gdb/python/python-internal.h
@@ -477,6 +477,8 @@ extern enum ext_lang_rc gdbpy_get_matching_xmethod_workers
PyObject *gdbpy_history (PyObject *self, PyObject *args);
+PyObject *gdbpy_convenience_variable (PyObject *self, PyObject *args);
+PyObject *gdbpy_set_convenience_variable (PyObject *self, PyObject *args);
PyObject *gdbpy_breakpoints (PyObject *, PyObject *);
PyObject *gdbpy_frame_stop_reason_string (PyObject *, PyObject *);
PyObject *gdbpy_lookup_symbol (PyObject *self, PyObject *args, PyObject *kw);
diff --git a/gdb/python/python.c b/gdb/python/python.c
index c29e7d7..1805c90 100644
--- a/gdb/python/python.c
+++ b/gdb/python/python.c
@@ -2132,6 +2132,14 @@ Return a tuple containing all inferiors." },
Invalidate any cached frame objects in gdb.\n\
Intended for internal use only." },
+ { "convenience_variable", gdbpy_convenience_variable, METH_VARARGS,
+ "convenience_variable (NAME) -> value.\n\
+Return the value of the convenience variable $NAME,\n\
+or None if not set." },
+ { "set_convenience_variable", gdbpy_set_convenience_variable, METH_VARARGS,
+ "convenience_variable (NAME, VALUE) -> None.\n\
+Set the value of the convenience variable $NAME." },
+
{NULL, NULL, 0, NULL}
};
diff --git a/gdb/testsuite/gdb.python/python.exp b/gdb/testsuite/gdb.python/python.exp
index f6bf93a..2780b78 100644
--- a/gdb/testsuite/gdb.python/python.exp
+++ b/gdb/testsuite/gdb.python/python.exp
@@ -477,3 +477,23 @@ gdb_py_test_silent_cmd "step" "Step into func2" 1
gdb_py_test_silent_cmd "up" "Step out of func2" 1
gdb_test "python print (gdb.find_pc_line(gdb.selected_frame().pc()).line > line)" "True" "test find_pc_line with resume address"
+
+gdb_test_no_output "set variable \$cvar1 = 23" "set convenience variable"
+gdb_test "python print(gdb.convenience_variable('cvar1'))" "23"
+gdb_test "python print(gdb.convenience_variable('cvar2'))" "None"
+gdb_test_no_output "python gdb.set_convenience_variable('cvar1', 89)" \
+ "change convenience variable from python"
+gdb_test "python print(gdb.convenience_variable('cvar1'))" "89" \
+ "print new value of convenience variable from python"
+gdb_test "print \$cvar1" " = 89" \
+ "print new value of convenience variable from CLI"
+gdb_test_no_output "python gdb.set_convenience_variable('cvar3', -5)" \
+ "make convenience variable from python"
+gdb_test "python print(gdb.convenience_variable('cvar3'))" "-5" \
+ "print value of new convenience variable from python"
+gdb_test_no_output "python gdb.set_convenience_variable('cvar3', None)" \
+ "reset convenience variable from python"
+gdb_test "python print(gdb.convenience_variable('cvar3'))" "None" \
+ "print reset convenience variable from python"
+gdb_test "print \$cvar3" "= void" \
+ "print reset convenience variable from CLI"