public inbox for gdb-patches@sourceware.org
 help / color / mirror / Atom feed
From: Andrew Burgess <aburgess@redhat.com>
To: gdb-patches@sourceware.org
Cc: Andrew Burgess <aburgess@redhat.com>
Subject: [PATCH 5/6] gdb/python: Add gdb.Inferior.__dict__ attribute
Date: Fri,  5 Jan 2024 11:48:34 +0000	[thread overview]
Message-ID: <6eb215cd5252a70326d1ec5bd9c7d96e9a6d20e5.1704455158.git.aburgess@redhat.com> (raw)
In-Reply-To: <cover.1704455158.git.aburgess@redhat.com>

The gdb.Objfile, gdb.Progspace, and gdb.Type Python types already have
a __dict__ attribute, which allows users to create user defined
attributes within the objects.  This is useful if the user wants to
cache information within an object.

This commit adds the same functionality to the gdb.Inferior type.

After this commit there is a new gdb.Inferior.__dict__ attribute,
which is a dictionary.  A user can, for example, do this:

  (gdb) pi
  >>> i = gdb.selected_inferior()
  >>> i._user_attribute = 123
  >>> i._user_attribute
  123
  >>>

There's a new test included.
---
 gdb/NEWS                                 |  4 +++
 gdb/doc/python.texi                      | 32 ++++++++++++++++++++++++
 gdb/python/py-inferior.c                 | 13 +++++++++-
 gdb/testsuite/gdb.python/py-inferior.exp | 19 ++++++++++++++
 4 files changed, 67 insertions(+), 1 deletion(-)

diff --git a/gdb/NEWS b/gdb/NEWS
index 36443c38aca..500d5ab7160 100644
--- a/gdb/NEWS
+++ b/gdb/NEWS
@@ -92,6 +92,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 d74defeec0c..721f0100178 100644
--- a/gdb/doc/python.texi
+++ b/gdb/doc/python.texi
@@ -3667,6 +3667,38 @@
 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
+(gdb) 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)
+(gdb) file /tmp/hello
+Reading symbols from /tmp/hello...
+(gdb) 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");
+(gdb) python print(gdb.selected_inferior()._last_stop_time)
+2024-01-04 14:48:41.347036
+@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 929d8bd17b5..3f14bc31459 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 5a221f800c3..0e00636fa1c 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]*}
-- 
2.25.4


  parent reply	other threads:[~2024-01-05 11:48 UTC|newest]

Thread overview: 36+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2024-01-05 11:48 [PATCH 0/6] Python __repr__() methods and new __dict__ attributes Andrew Burgess
2024-01-05 11:48 ` [PATCH 1/6] gdb/python: hoist common invalid object repr code into py-utils.c Andrew Burgess
2024-01-09 19:19   ` Tom Tromey
2024-01-05 11:48 ` [PATCH 2/6] gdb/python: add gdb.InferiorThread.__repr__() method Andrew Burgess
2024-01-05 11:48 ` [PATCH 3/6] gdb/python: add gdb.Frame.__repr__() method Andrew Burgess
2024-01-05 11:48 ` [PATCH 4/6] gdb/python: remove users ability to create gdb.Progspace objects Andrew Burgess
2024-01-05 13:27   ` Eli Zaretskii
2024-01-05 11:48 ` Andrew Burgess [this message]
2024-01-05 13:33   ` [PATCH 5/6] gdb/python: Add gdb.Inferior.__dict__ attribute Eli Zaretskii
2024-01-09 20:05   ` Tom Tromey
2024-01-05 11:48 ` [PATCH 6/6] gdb/python: Add gdb.InferiorThread.__dict__ attribute Andrew Burgess
2024-01-05 13:31   ` Eli Zaretskii
2024-01-09 20:11   ` Tom Tromey
2024-01-10 10:38     ` Andrew Burgess
2024-01-10 15:54 ` [PATCHv2 0/8] Python __repr__() methods and new __dict__ attributes Andrew Burgess
2024-01-09 17:32   ` [PATCH] gdb/python: New InferiorThread.ptid_string attribute Andrew Burgess
2024-01-09 18:50     ` Eli Zaretskii
2024-01-09 19:10     ` Tom Tromey
2024-01-12  9:39       ` [PUSHED] " Andrew Burgess
2024-01-10 15:54     ` [PATCH] " Andrew Burgess
2024-01-10 15:54   ` [PATCHv2 1/8] gdb/python: hoist common invalid object repr code into py-utils.c Andrew Burgess
2024-01-10 15:54   ` [PATCHv2 2/8] gdb/python: add gdb.InferiorThread.__repr__() method Andrew Burgess
2024-01-10 15:54   ` [PATCHv2 3/8] gdb/python: add gdb.Frame.__repr__() method Andrew Burgess
2024-01-10 15:54   ` [PATCHv2 4/8] gdb/python: remove users ability to create gdb.Progspace objects Andrew Burgess
2024-01-10 15:54   ` [PATCHv2 5/8] gdb/python: Add gdb.Inferior.__dict__ attribute Andrew Burgess
2024-01-10 15:54   ` [PATCHv2 6/8] gdb/python: Add gdb.InferiorThread.__dict__ attribute Andrew Burgess
2024-01-10 15:54   ` [PATCHv2 7/8] gdb/doc: add some notes on selecting suitable attribute names Andrew Burgess
2024-01-10 16:35     ` Eli Zaretskii
2024-01-11 10:48       ` Andrew Burgess
2024-01-11 10:56         ` Eli Zaretskii
2024-01-10 15:54   ` [PATCHv2 8/8] gdb/doc: update examples in gdb.Progspace and gdb.Objfile docs Andrew Burgess
2024-01-10 16:36     ` Eli Zaretskii
2024-01-10 18:08   ` [PATCHv2 0/8] Python __repr__() methods and new __dict__ attributes Tom Tromey
2024-01-12 13:44     ` Andrew Burgess
2024-01-12 14:57       ` Tom de Vries
2024-01-12 16:20         ` Andrew Burgess

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=6eb215cd5252a70326d1ec5bd9c7d96e9a6d20e5.1704455158.git.aburgess@redhat.com \
    --to=aburgess@redhat.com \
    --cc=gdb-patches@sourceware.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).