aboutsummaryrefslogtreecommitdiff
path: root/gdb
diff options
context:
space:
mode:
Diffstat (limited to 'gdb')
-rw-r--r--gdb/NEWS4
-rw-r--r--gdb/doc/python.texi36
-rw-r--r--gdb/python/py-inferior.c13
-rw-r--r--gdb/testsuite/gdb.python/py-inferior.exp19
4 files changed, 71 insertions, 1 deletions
diff --git a/gdb/NEWS b/gdb/NEWS
index 7254973..92e7f32 100644
--- a/gdb/NEWS
+++ b/gdb/NEWS
@@ -100,6 +100,10 @@ show remote thread-options-packet
objects can still be obtained through calling other API
functions, for example 'gdb.current_progspace()'.
+ ** User defined attributes can be added to a gdb.Inferior object,
+ these will be stored in the object's new Inferior.__dict__
+ attribute.
+
* Debugger Adapter Protocol changes
** GDB now emits the "process" event.
diff --git a/gdb/doc/python.texi b/gdb/doc/python.texi
index da37348..2fd8a9b 100644
--- a/gdb/doc/python.texi
+++ b/gdb/doc/python.texi
@@ -3667,6 +3667,42 @@ Unset the environment variable @var{name}. @var{name} must be a
string.
@end defun
+One may add arbitrary attributes to @code{gdb.Inferior} objects in the
+usual Python way. This is useful if, for example, one needs to do
+some extra record keeping associated with the inferior.
+
+In this contrived example we record the time when an inferior last
+stopped:
+
+@smallexample
+@group
+(@value{GDBP}) python
+import datetime
+
+def thread_stopped(event):
+ if event.inferior_thread is not None:
+ thread = event.inferior_thread
+ else:
+ thread = gdb.selected_thread()
+ inferior = thread.inferior
+ inferior._last_stop_time = datetime.datetime.today()
+
+gdb.events.stop.connect(thread_stopped)
+@end group
+@group
+(@value{GDBP}) file /tmp/hello
+Reading symbols from /tmp/hello...
+(@value{GDBP}) start
+Temporary breakpoint 1 at 0x401198: file /tmp/hello.c, line 18.
+Starting program: /tmp/hello
+
+Temporary breakpoint 1, main () at /tmp/hello.c:18
+18 printf ("Hello World\n");
+(@value{GDBP}) python print(gdb.selected_inferior()._last_stop_time)
+2024-01-04 14:48:41.347036
+@end group
+@end smallexample
+
@node Events In Python
@subsubsection Events In Python
@cindex inferior events in Python
diff --git a/gdb/python/py-inferior.c b/gdb/python/py-inferior.c
index 929d8bd..3f14bc3 100644
--- a/gdb/python/py-inferior.c
+++ b/gdb/python/py-inferior.c
@@ -46,6 +46,10 @@ struct inferior_object
/* thread_object instances under this inferior. This owns a
reference to each object it contains. */
thread_map_t *threads;
+
+ /* Dictionary holding user-added attributes.
+ This is the __dict__ attribute of the object. */
+ PyObject *dict;
};
extern PyTypeObject inferior_object_type
@@ -241,6 +245,9 @@ inferior_to_inferior_object (struct inferior *inferior)
inf_obj->inferior = inferior;
inf_obj->threads = new thread_map_t ();
+ inf_obj->dict = PyDict_New ();
+ if (inf_obj->dict == nullptr)
+ return nullptr;
/* PyObject_New initializes the new object with a refcount of 1. This
counts for the reference we are keeping in the inferior data. */
@@ -981,6 +988,8 @@ infpy_dealloc (PyObject *obj)
function is called. */
gdb_assert (inf_obj->inferior == nullptr);
+ Py_XDECREF (inf_obj->dict);
+
Py_TYPE (obj)->tp_free (obj);
}
@@ -1038,6 +1047,8 @@ GDBPY_INITIALIZE_FILE (gdbpy_initialize_inferior);
static gdb_PyGetSetDef inferior_object_getset[] =
{
+ { "__dict__", gdb_py_generic_dict, nullptr,
+ "The __dict__ for this inferior.", &inferior_object_type },
{ "arguments", infpy_get_args, infpy_set_args,
"Arguments to this program.", nullptr },
{ "num", infpy_get_num, NULL, "ID of inferior, as assigned by GDB.", NULL },
@@ -1135,7 +1146,7 @@ PyTypeObject inferior_object_type =
0, /* tp_dict */
0, /* tp_descr_get */
0, /* tp_descr_set */
- 0, /* tp_dictoffset */
+ offsetof (inferior_object, dict), /* tp_dictoffset */
0, /* tp_init */
0 /* tp_alloc */
};
diff --git a/gdb/testsuite/gdb.python/py-inferior.exp b/gdb/testsuite/gdb.python/py-inferior.exp
index 5a221f8..0e00636 100644
--- a/gdb/testsuite/gdb.python/py-inferior.exp
+++ b/gdb/testsuite/gdb.python/py-inferior.exp
@@ -85,6 +85,15 @@ gdb_test "python print (i0.threads ())" \
gdb_test "python print (i0.progspace)" "<gdb.Progspace object at $hex>"
gdb_test "python print (i0.progspace == gdb.progspaces()\[0\])" "True"
+# Add a user defined attribute to the inferior, and check the
+# attribute can be read back.
+gdb_test_no_output "python i0._user_attr = 123" \
+ "add a user defined attribute to the inferior object"
+gdb_test "python print(i0._user_attr)" \
+ "123" "read back user defined attribute from i0"
+gdb_test "python print(gdb.inferiors()\[0\]._user_attr)" \
+ "123" "read back user defined attribute from gdb.inferiors"
+
# Test the number of inferior threads.
gdb_breakpoint check_threads
@@ -127,6 +136,16 @@ gdb_test "print str" " = \"hallo, testsuite\"" \
# correct inferior.
set num [add_inferior]
+# Confirm the new inferior doesn't have the user defined attribute,
+# but that the first inferior does still have the attribute.
+gdb_test "python print(gdb.inferiors()\[1\]._user_attr)" \
+ [multi_line \
+ "AttributeError: 'gdb\\.Inferior' object has no attribute '_user_attr'" \
+ "Error while executing Python code\\."] \
+ "check new inferior doesn't have user defined attribute"
+gdb_test "python print(gdb.inferiors()\[0\]._user_attr)" \
+ "123" "read back user defined attribute again"
+
# Test memory search.
set hex_number {0x[0-9a-fA-F][0-9a-fA-F]*}