From: Tom Tromey <tromey@adacore.com>
To: gdb-patches@sourceware.org
Cc: Tom Tromey <tromey@adacore.com>
Subject: [PATCH RFC 2/6] Add py-iovec.c
Date: Thu, 22 Oct 2026 12:28:12 -0600 [thread overview]
Message-ID: <20261022-android-apk-file-v1-2-8444bb5f832a@adacore.com> (raw)
In-Reply-To: <20261022-android-apk-file-v1-0-8444bb5f832a@adacore.com>
This patch adds py-iovec.c, which provides a way to construct a new
BFD that can access Python objects to get the underlying data. Due to
how subsequent patches are written, Python file-like objects aren't
used directly, but instead a wrapper will be provided.
---
gdb/Makefile.in | 1 +
gdb/python/py-iovec.c | 130 +++++++++++++++++++++++++++++++++++++++++++
gdb/python/python-internal.h | 2 +
3 files changed, 133 insertions(+)
diff --git a/gdb/Makefile.in b/gdb/Makefile.in
index 4260c90d425..e6c99924451 100644
--- a/gdb/Makefile.in
+++ b/gdb/Makefile.in
@@ -413,6 +413,7 @@ SUBDIR_PYTHON_SRCS = \
python/py-infevents.c \
python/py-infthread.c \
python/py-instruction.c \
+ python/py-iovec.c \
python/py-lazy-string.c \
python/py-linetable.c \
python/py-membuf.c \
diff --git a/gdb/python/py-iovec.c b/gdb/python/py-iovec.c
new file mode 100644
index 00000000000..4bcea6d8a3b
--- /dev/null
+++ b/gdb/python/py-iovec.c
@@ -0,0 +1,130 @@
+/* Python interface to BFD iovec
+
+ Copyright (C) 2026 Free Software Foundation, Inc.
+
+ This file is part of GDB.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>. */
+
+#include "gdb_bfd.h"
+#include "gdbcore.h"
+#include "python-internal.h"
+
+struct py_iovec : public gdb_bfd_iovec_base
+{
+ py_iovec (gdbpy_ref<> &&file_obj, ULONGEST file_size)
+ : m_file (std::move (file_obj)),
+ m_size (file_size)
+ {
+ }
+
+ ~py_iovec ();
+
+ file_ptr read (bfd *abfd, void *buffer, file_ptr nbytes,
+ file_ptr offset) override;
+
+ int stat (struct bfd *abfd, struct stat *sb) override
+ {
+ /* We only support the size here. */
+ memset (sb, 0, sizeof (*sb));
+ sb->st_size = m_size;
+ return 0;
+ }
+
+ gdbpy_ref<> m_file;
+ ULONGEST m_size;
+};
+
+py_iovec::~py_iovec ()
+{
+ /* Make sure the GIL is held before destruction. */
+ gdbpy_enter enter_py;
+
+ gdbpy_ref<> result = gdbpy_call_method (m_file.get (), "close");
+ if (result == nullptr)
+ gdbpy_print_stack ();
+
+ m_file.reset (nullptr);
+}
+
+file_ptr
+py_iovec::read (bfd *abfd, void *buffer, file_ptr nbytes, file_ptr offset)
+{
+ /* If this read will read all of the file, limit it to just the rest. */
+ if (offset + nbytes > m_size)
+ nbytes = m_size - offset;
+
+ /* If there are no more bytes left, we've reached EOF. */
+ if (nbytes == 0)
+ return 0;
+
+ gdbpy_enter enter_py;
+
+ char *data;
+ Py_ssize_t len;
+ gdbpy_ref<> bytes = gdbpy_call_method (m_file.get (), "read",
+ (gdb_py_ulongest) offset,
+ (gdb_py_ulongest) nbytes);
+ if (bytes == nullptr
+ || PyBytes_AsStringAndSize (bytes.get (), &data, &len) == -1)
+ {
+ gdbpy_print_stack ();
+ bfd_set_error (bfd_error_bad_value);
+ return -1;
+ }
+
+ memcpy (buffer, data, len);
+ return len;
+}
+
+gdb_bfd_ref_ptr
+open_bfd_from_python (gdbpy_ref<> &&file_obj)
+{
+ int has_attr = PyObject_HasAttrString (file_obj.get (), "read");
+ if (has_attr != 1)
+ {
+ /* This may return without the error set, but this scenario is
+ handled by the caller. */
+ return nullptr;
+ }
+
+ gdbpy_ref<> size_obj = gdbpy_call_method (file_obj.get (), "size");
+ if (size_obj == nullptr)
+ return nullptr;
+ gdb_py_ulongest size = gdb_py_long_as_ulongest (size_obj.get ());
+ if (PyErr_Occurred ())
+ return nullptr;
+
+ gdbpy_ref<> name_obj = gdbpy_call_method (file_obj.get (), "filename");
+ if (name_obj == nullptr)
+ return nullptr;
+ gdb::unique_xmalloc_ptr<char> filename
+ = python_string_to_host_string (name_obj.get ());
+ if (filename == nullptr)
+ return nullptr;
+
+ auto iovec = std::make_unique<py_iovec> (std::move (file_obj), size);
+
+ auto open = [&] (bfd *nbfd) -> py_iovec *
+ {
+ return iovec.release ();
+ };
+
+ gdb_bfd_ref_ptr result = gdb_bfd_openr_iovec (filename.get (),
+ gnutarget, open);
+ if (result == nullptr)
+ PyErr_Format (PyExc_OSError, "could not open %s: %s",
+ filename.get (), bfd_errmsg (bfd_get_error ()));
+ return result;
+}
diff --git a/gdb/python/python-internal.h b/gdb/python/python-internal.h
index 2e064107cbc..bf7eb795061 100644
--- a/gdb/python/python-internal.h
+++ b/gdb/python/python-internal.h
@@ -1416,6 +1416,8 @@ class gdbpy_memoizing_registry_storage
extern gdbpy_ref<> eval_python_command
(const char *command, int start_symbol, const char *filename = nullptr);
+extern gdb_bfd_ref_ptr open_bfd_from_python (gdbpy_ref<> &&file_obj);
+
/* The following four functions are refcount-safe wrappers around
Py_RETURN_{NONE,TRUE,FALSE,NOTIMPLEMENTED}. */
--
2.56.0
next prev parent reply other threads:[~2026-10-22 18:29 UTC|newest]
Thread overview: 7+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-10-22 18:28 [PATCH RFC 0/6] Handle Android APK files Tom Tromey
2026-10-22 18:28 ` [PATCH RFC 1/6] Add py-file.c Tom Tromey
2026-10-22 18:28 ` Tom Tromey [this message]
2026-10-22 18:28 ` [PATCH RFC 3/6] Allow missing build-id when finding an objfile Tom Tromey
2026-10-22 18:28 ` [PATCH RFC 4/6] Allow missing objfile handler to return a file Tom Tromey
2026-10-22 18:28 ` [PATCH RFC 5/6] Call ext_lang_find_objfile_from_buildid from solib_bfd_fopen Tom Tromey
2026-10-22 18:28 ` [PATCH RFC 6/6] Add gdb.handler.android module 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=20261022-android-apk-file-v1-2-8444bb5f832a@adacore.com \
--to=tromey@adacore.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