diff options
-rw-r--r-- | gdb/NEWS | 4 | ||||
-rw-r--r-- | gdb/doc/python.texi | 23 | ||||
-rw-r--r-- | gdb/python/py-value.c | 77 | ||||
-rw-r--r-- | gdb/python/python-internal.h | 2 | ||||
-rw-r--r-- | gdb/python/python.c | 8 | ||||
-rw-r--r-- | gdb/testsuite/gdb.python/python.exp | 20 |
6 files changed, 132 insertions, 2 deletions
@@ -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" |