Mirror of the gdb-patches mailing list
 help / color / mirror / Atom feed
From: Tom Tromey <tom@tromey.com>
To: gdb-patches@sourceware.org
Cc: Tom Tromey <tom@tromey.com>
Subject: [PATCH 4/5] Rewrite breakpoint location getter methods
Date: Wed, 14 Oct 2026 08:08:52 -0600	[thread overview]
Message-ID: <20261014-python-safety-breakpoint-v1-4-c8e72d58f3cd@tromey.com> (raw)
In-Reply-To: <20261014-python-safety-breakpoint-v1-0-c8e72d58f3cd@tromey.com>

This rewrites the breakpoint location getter methods to use the Python
safety API.
---
 gdb/python/py-breakpoint.c | 231 +++++++++++++++++++++------------------------
 1 file changed, 110 insertions(+), 121 deletions(-)

diff --git a/gdb/python/py-breakpoint.c b/gdb/python/py-breakpoint.c
index 40d1244abcf..b39093ebd81 100644
--- a/gdb/python/py-breakpoint.c
+++ b/gdb/python/py-breakpoint.c
@@ -67,6 +67,52 @@ struct gdbpy_breakpoint_location_object : public PyObject
   /* An owning reference to the location's breakpoint owner.  */
   gdbpy_breakpoint_object *owner;
 
+  /* Python function to test whether or not the breakpoint location is
+     enabled.  */
+  bool get_enabled () const
+  {
+    require_valid ();
+    return bp_loc->enabled;
+  }
+
+  /* Python function to get owner of breakpoint location, which is of
+     type gdb.Breakpoint.  */
+  gdbpy_ref<> get_owner () const
+  {
+    require_valid ();
+    return gdbpy_ref<>::new_reference (owner);
+  }
+
+  /* Python function to get address of breakpoint location.  */
+  CORE_ADDR get_address () const
+  {
+    require_valid ();
+    return bp_loc->address;
+  }
+
+  /* Python function to get the function name of where this location
+     was set.  */
+  const char *get_function () const
+  {
+    require_valid ();
+    return bp_loc->function_name.get ();
+  }
+
+  /* Return the full filename of the location.  */
+  const char *get_fullname () const
+  {
+    require_valid ();
+    if (bp_loc->symtab == nullptr)
+      return nullptr;
+    return bp_loc->symtab->fullname ();
+  }
+
+  /* Accessor to get the source location.  */
+  gdbpy_ref<> get_source_location () const;
+
+  /* Accessor to get the thread groups.  */
+  gdbpy_ref<> get_thread_groups () const;
+
   /* Implementation of 'repr'.  */
   gdbpy_ref<> repr ();
 
@@ -82,15 +128,6 @@ struct gdbpy_breakpoint_location_object : public PyObject
 
 static_assert (gdb::is_python_allocatable_v<gdbpy_breakpoint_location_object>);
 
-/* Require that BREAKPOINT and LOCATION->OWNER are the same; throw a Python
-   exception if they are not.  */
-#define BPLOCPY_REQUIRE_VALID(Breakpoint, Location)                         \
-    do {                                                                    \
-      if ((Breakpoint)->bp != (Location)->bp_loc->owner)                    \
-	return PyErr_Format (PyExc_RuntimeError,                            \
-			     _("Breakpoint location is invalid."));	    \
-    } while (0)
-
 /* Require that BREAKPOINT and LOCATION->OWNER are the same; throw a Python
    exception if they are not.  This macro is for use in setter functions.  */
 #define BPLOCPY_SET_REQUIRE_VALID(Breakpoint, Location)                     \
@@ -1604,45 +1641,6 @@ bplocpy_set_enabled (PyObject *py_self, PyObject *newvalue, void *closure)
   return 0;
 }
 
-/* Python function to test whether or not the breakpoint location is enabled.  */
-
-static PyObject *
-bplocpy_get_enabled (PyObject *py_self, void *closure)
-{
-  auto *self = (gdbpy_breakpoint_location_object *) py_self;
-  BPPY_REQUIRE_VALID (self->owner);
-  BPLOCPY_REQUIRE_VALID (self->owner, self);
-
-  if (self->bp_loc->enabled)
-    return py_true ().release ();
-  else
-    return py_false ().release ();
-}
-
-/* Python function to get address of breakpoint location.  */
-
-static PyObject *
-bplocpy_get_address (PyObject *py_self, void *closure)
-{
-  auto *self = (gdbpy_breakpoint_location_object *) py_self;
-  BPPY_REQUIRE_VALID (self->owner);
-  BPLOCPY_REQUIRE_VALID (self->owner, self);
-  return gdb_py_object_from_ulongest (self->bp_loc->address).release ();
-}
-
-/* Python function to get owner of breakpoint location, which
-   is of type gdb.Breakpoint.  */
-
-static PyObject *
-bplocpy_get_owner (PyObject *py_self, void *closure)
-{
-  auto *self = (gdbpy_breakpoint_location_object *) py_self;
-  BPPY_REQUIRE_VALID (self->owner);
-  BPLOCPY_REQUIRE_VALID (self->owner, self);
-  Py_INCREF (self->owner);
-  return self->owner;
-}
-
 /* Attempt to get fully resolved file path for symtab.  */
 
 static gdbpy_ref<>
@@ -1650,99 +1648,69 @@ bploc_filepath (struct symtab *bploc_symtab)
 {
   /* The exception is not ours to handle.  We should always
      return some string value and filename is never null.  */
+  const char *filename = nullptr;
   try
     {
-      const char *full = symtab_to_fullname (bploc_symtab);
-      if (full)
-	return host_string_to_python_string (full);
+      filename = symtab_to_fullname (bploc_symtab);
     }
   catch (const gdb_exception &except)
     {
     }
 
-  return host_string_to_python_string (bploc_symtab->filename ());
+  if (filename == nullptr)
+    filename = bploc_symtab->filename ();
+  gdb_assert (filename != nullptr);
+
+  gdbpy_ref<> result = host_string_to_python_string (filename);
+  /* FIXME: Python safety: host_string_to_python_string should
+     throw.  */
+  if (result == nullptr)
+    throw gdb_python_exception ();
+  return result;
 }
 
 /* Python function to get the source file name path and line number
    where this breakpoint location was set.  */
 
-static PyObject *
-bplocpy_get_source_location (PyObject *py_self, void *closure)
+gdbpy_ref<>
+gdbpy_breakpoint_location_object::get_source_location () const
 {
-  auto *self = (gdbpy_breakpoint_location_object *) py_self;
-  BPPY_REQUIRE_VALID (self->owner);
-  BPLOCPY_REQUIRE_VALID (self->owner, self);
-  if (self->bp_loc->symtab)
+  require_valid ();
+  if (bp_loc->symtab != nullptr)
     {
-      gdbpy_ref<> tup (PyTuple_New (2));
-      if (tup == nullptr)
-	return nullptr;
-      gdbpy_ref<> filename = bploc_filepath (self->bp_loc->symtab);
-      if (filename == nullptr)
-	return nullptr;
-      auto line = gdb_py_object_from_ulongest (self->bp_loc->line_number);
+      gdbpy_ref<> tup = gdbpy_tuple_new (2);
+      gdbpy_ref<> filename = bploc_filepath (bp_loc->symtab);
+      auto line = gdb_py_object_from_ulongest (bp_loc->line_number);
+      /* FIXME: Python safety: gdb_py_object_from_ulongest should
+	 throw.  */
       if (line == nullptr)
-	return nullptr;
-      if (PyTuple_SetItem (tup.get (), 0, filename.release ()) == -1
-	  || PyTuple_SetItem (tup.get (), 1, line.release ()) == -1)
-	return nullptr;
-      return tup.release ();
+	throw gdb_python_exception ();
+      gdbpy_tuple_set_item (tup, 0, std::move (filename));
+      gdbpy_tuple_set_item (tup, 1, std::move (line));
+      return tup;
     }
-  else
-    return py_none ().release ();
-}
 
-/* Python function to get the function name of where this location was set.  */
-
-static PyObject *
-bplocpy_get_function (PyObject *py_self, void *closure)
-{
-  auto *self = (gdbpy_breakpoint_location_object *) py_self;
-  BPPY_REQUIRE_VALID (self->owner);
-  BPLOCPY_REQUIRE_VALID (self->owner, self);
-  const auto fn_name = self->bp_loc->function_name.get ();
-  if (fn_name != nullptr)
-    return host_string_to_python_string (fn_name).release ();
-  return py_none ().release ();
+  return py_none ();
 }
 
-static PyObject *
-bplocpy_get_thread_groups (PyObject *py_self, void *closure)
+gdbpy_ref<>
+gdbpy_breakpoint_location_object::get_thread_groups () const
 {
-  auto *self = (gdbpy_breakpoint_location_object *) py_self;
-  BPPY_REQUIRE_VALID (self->owner);
-  BPLOCPY_REQUIRE_VALID (self->owner, self);
-  gdbpy_ref<> list (PyList_New (0));
-  if (list == nullptr)
-    return nullptr;
+  require_valid ();
+  gdbpy_ref<> list = gdbpy_list_new (0);
   for (inferior *inf : all_inferiors ())
     {
-      if (inf->pspace == self->bp_loc->pspace)
+      if (inf->pspace == bp_loc->pspace)
 	{
 	  gdbpy_ref<> num = gdb_py_object_from_ulongest (inf->num);
+	  /* FIXME: Python safety: gdb_py_object_from_ulongest should
+	     throw.  */
 	  if (num == nullptr)
-	    return nullptr;
-	  if (PyList_Append (list.get (), num.get ()) != 0)
-	    return nullptr;
+	    throw gdb_python_exception ();
+	  gdbpy_list_append (list, num);
 	}
     }
-  return list.release ();
-}
-
-static PyObject *
-bplocpy_get_fullname (PyObject *py_self, void *closure)
-{
-  auto *self = (gdbpy_breakpoint_location_object *) py_self;
-  BPPY_REQUIRE_VALID (self->owner);
-  BPLOCPY_REQUIRE_VALID (self->owner, self);
-  const auto symtab = self->bp_loc->symtab;
-  if (symtab != nullptr && symtab->fullname () != nullptr)
-    {
-      gdbpy_ref<> fullname
-	= host_string_to_python_string (symtab->fullname ());
-      return fullname.release ();
-    }
-  return py_none ().release ();
+  return list;
 }
 
 /* De-allocation function to be called for the Python object.  */
@@ -1798,19 +1766,40 @@ gdbpy_breakpoint_location_object::repr ()
 /* Attribute get/set Python definitions. */
 
 static gdb_PyGetSetDef bp_location_object_getset[] = {
-  { "enabled", bplocpy_get_enabled, bplocpy_set_enabled,
+  { "enabled",
+    wrap_getter<gdbpy_breakpoint_location_object,
+		&gdbpy_breakpoint_location_object::get_enabled>,
+    bplocpy_set_enabled,
     "Boolean telling whether the breakpoint is enabled.", NULL },
-  { "owner", bplocpy_get_owner, NULL,
+  { "owner",
+    wrap_getter<gdbpy_breakpoint_location_object,
+		&gdbpy_breakpoint_location_object::get_owner>,
+    nullptr,
     "Get the breakpoint owner object", NULL },
-  { "address", bplocpy_get_address, NULL,
+  { "address",
+    wrap_getter<gdbpy_breakpoint_location_object,
+		&gdbpy_breakpoint_location_object::get_address>,
+    nullptr,
     "Get address of where this location was set", NULL},
-  { "source", bplocpy_get_source_location, NULL,
+  { "source",
+    wrap_getter<gdbpy_breakpoint_location_object,
+		&gdbpy_breakpoint_location_object::get_source_location>,
+    nullptr,
     "Get file and line number of where this location was set", NULL},
-  { "function", bplocpy_get_function, NULL,
+  { "function",
+    wrap_getter<gdbpy_breakpoint_location_object,
+		&gdbpy_breakpoint_location_object::get_function>,
+    nullptr,
     "Get function of where this location was set", NULL },
-  { "fullname", bplocpy_get_fullname, NULL,
+  { "fullname",
+    wrap_getter<gdbpy_breakpoint_location_object,
+		&gdbpy_breakpoint_location_object::get_fullname>,
+    nullptr,
     "Get fullname of where this location was set", NULL },
-  { "thread_groups", bplocpy_get_thread_groups, NULL,
+  { "thread_groups",
+    wrap_getter<gdbpy_breakpoint_location_object,
+		&gdbpy_breakpoint_location_object::get_thread_groups>,
+    nullptr,
     "Get thread groups where this location is in", NULL },
   { NULL }  /* Sentinel.  */
 };

-- 
2.49.0


  parent reply	other threads:[~2026-10-14 14:09 UTC|newest]

Thread overview: 6+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-10-14 14:08 [PATCH 0/5] Use Python safety API for breakpoint locations Tom Tromey
2026-10-14 14:08 ` [PATCH 1/5] Rewrite gdb.BreakpointLocation repr method Tom Tromey
2026-10-14 14:08 ` [PATCH 2/5] Move two macros from python-internal.h to py-breakpoint.c Tom Tromey
2026-10-14 14:08 ` [PATCH 3/5] Add require_valid to Python breakpoint and breakpoint location Tom Tromey
2026-10-14 14:08 ` Tom Tromey [this message]
2026-10-14 14:08 ` [PATCH 5/5] Rewrite gdb.BreakpointLocation setter Tom Tromey

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=20261014-python-safety-breakpoint-v1-4-c8e72d58f3cd@tromey.com \
    --to=tom@tromey.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