diff options
Diffstat (limited to 'gdb')
-rw-r--r-- | gdb/NEWS | 4 | ||||
-rw-r--r-- | gdb/doc/python.texi | 36 | ||||
-rw-r--r-- | gdb/python/py-inferior.c | 13 | ||||
-rw-r--r-- | gdb/testsuite/gdb.python/py-inferior.exp | 19 |
4 files changed, 71 insertions, 1 deletions
@@ -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]*} |