Commit graph

268 commits

Author SHA1 Message Date
Tom de Vries
6c85ef111b [gdb] Use using instead of typedef
After commit 1eed06ae51 ("[gdbsupport] Use using instead of typedef in
next_iterator") I wondered if I could do something similar using sed.

Result of:
...
$ find gdb* -type f -name "*.[ch]" -o -name "*.cc" \
    | egrep -v /testsuite/ \
    | xargs sed -i \
	    's/^\([ \t]*\)typedef \([a-zA-Z_0-9:<>,.() ]*\) \([\*&][\*&]*\)\([a-zA-Z_0-9]*\);/\1using \4 = \2 \3;/'

$ find gdb* -type f -name "*.[ch]" -o -name "*.cc" \
    | egrep -v /testsuite/ \
    | xargs sed -i \
	    's/^\([ \t]*\)typedef \([a-zA-Z_0-9:<>,.() ]*\) \([a-zA-Z_0-9]*\);/\1using \3 = \2;/'
...

Tested on x86_64-linux.
2026-06-11 08:54:34 +02:00
Matthieu Longo
dafd73bcda gdb/python: fix memory leak in gdb_py_tp_name
The current implementation of gdb_py_tp_name() leaks a reference to the
object returned by PyType_GetFullyQualifiedName() for Python >= 3.13, and
PyType_GetQualName() for Python >= 3.11.

Managing the strong reference on the returned PyObject* with a gdbpy_ref<>
fixes the reference count, but also causes the temporary object to be
deallocated on function exit. As a consequence, the 'const char *' returned
by PyUnicode_AsUTF8AndSize() becomes dangling and can no longer safely be
returned.

The proposed approach consists in changing gdb_py_tp_name() to return a
std::string, and forcing a copy of the 'const char *' value, statically
or dynamically allocated, stored in a temporary or non-temporary PyObject,
depending on the version of Python it was compiled with.
An unfortunate side effect of this fix is that every call sites where the
tp_name is printed, must now use `.c_str()' because PyErr_Format()
and its siblings cannot handle std::string.

Approved-By: Andrew Burgess <aburgess@redhat.com>
2026-06-04 15:09:54 +01:00
Tom de Vries
565074f17c [gdb/python] Boolify gdb_python_initialized
I noticed that while gdb_python_initialized is an int, there's also an
assignment using false:
...
  gdb_python_initialized = false;
...

Fix this by converting gdb_python_initialized to bool type.

Approved-by: Kevin Buettner <kevinb@redhat.com>
2026-05-25 08:47:40 +02:00
Andrew Burgess
60cd57ff6e gdb/python: add type traits check for all PyObject sub-classes
All of our custom Python types are created as structs, like this:

  struct some_new_type : public PyObject
  {
    ... various fields ...
  };

Then instances of this struct are created by calling PyObject_New,
either directly within GDB's C++ code, or within Python when a user's
Python script creates an instance of that class.

The problem is that Python is written in C, and PyObject_New doesn't
call any constructors for `some_new_type`, nor for any of the fields
within `some_new_type`.

If `some_new_type` is Plain Old Data (POD), then this is fine.  Or, to
be more C++ specific, if `some_new_type` is trivially default
constructable, then we're fine.

But if a field within `some_new_type` has a non-trivial constructor,
then we're in trouble as that constructor will never be run.

An example of a problematic field type is frame_info_ptr.  The
constructor for this type registers the new object with a central
management object, recording the `this` pointer, using this type within
`some_new_type` will not work as expected; frame invalidation will not
show up within the frame_info_ptr as you might expect.

And so, this type trait exists.  Whenever a struct is created to define
a new Python type we should add a line like:

  static_assert (gdb::is_python_allocatable_v<some_new_type>);

This will fail if any field of `some_new_type` are unsuitable for this
use.

We don't actually check is_trivially_default_constructible here.  Some
types, e.g. ui_file_style::color, have non-trivial (or no default)
constructors, but are still safe to use within `some_new_type` because
their constructors just initialise data fields; there's nothing
"special" that the constructor does that cannot be achieved by
assigning the fields after creation with PyObject_New.

What actually matters is that the type is trivially destructible
(Python won't call C++ destructors, so destructors with side effects,
like deregistering from a list, would be skipped) and trivially
copyable (Python may copy objects with memcpy).  Types like
frame_info_ptr, whose constructors and destructors have side effects
such as registering with a central management object, will be caught
because they are neither trivially destructible nor trivially copyable.
Simple POD types like ui_file_style are trivially destructible and
copyable, so pass this trait.

This commit adds the new type trait, and makes use of it in all cases
but one, pending_frame_object in python/py-unwind.c, has a field of
type frame_info_ptr, which is currently broken.  This will be fixed,
and the static_assert added, in the next commit.

Approved-By: Tom Tromey <tom@tromey.com>
2026-05-16 12:44:37 +01:00
Tom de Vries
e6a1fc06d7 [gdb/python] Undefine Py_RETURN_{NONE,TRUE,FALSE,NOTIMPLEMENTED}
Now that we've removed all uses of Py_RETURN_{NONE,TRUE,FALSE,NOTIMPLEMENTED},
undefine them to enforce using the refcount-safe wrappers instead.

Approved-By: Tom Tromey <tom@tromey.com>
2026-05-15 21:38:12 +02:00
Tom de Vries
b37f2bd246 [gdb/python] Introduce py_{none,true,false,notimplemented} functions
I came across this code:
...
   if (c)
     return v;
   else
     Py_RETURN_NONE;
...
and realized I couldn't easily rewrite it into "return c ? v : ...".

Probably something like this would work:
...
  return c ? v : ([] { Py_RETURN_NONE; } ());
...
but it made me wonder if we can get rid of Py_RETURN_NONE.

The only point of it seems to be to increase the reference count on the
Py_None object for older python versions.

Add a refcount-safe wrapper py_none (returning a gdbpy_ref), with the aim of
replacing all uses of Py_RETURN_NONE with "return py_none ().release ()".

Likewise for Py_RETURN_TRUE/Py_RETURN_FALSE/Py_RETURN_NOTIMPLEMENTED.

Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=34145
2026-05-15 21:38:12 +02:00
Matthieu Longo
58f83d8471 gdb/python: work around missing symbols not yet part of Python limited API
Most Python API usages in GDB can be migrated to the limited API, except
the following:

- PEP-741's configuration structures and functions, which use opaque
  types. They were originally intended to be part of the Python limited
  API, but some Python core maintainers opposed their inclusion at the
  time.
- PyOS_ReadlineFunctionPointer, a global variable storing a function
  used to override PyOS_StdioReadline(). The signature has remained
  unchanged for a long time.
- PyRun_InteractiveLoop, used to read and execute Python statements when
  embedding an interactive interpreter. Its signature has also remained
  stable for a long time.

Since no limited API alternatives exist for these, and given their long
history of ABI stability, one approach is to expose them in a GDB header
and rely on their continued stability. While this is not without risk,
it seems acceptable given the arguments above. This would remove the
remaining obstacles preventing GDB from being agnostic to the Python
version available at runtime.
That said, issues should be opened on CPython issue tracker to request
that these functions be included in the limited API in future versions.
Last but not least, GDB does not need to officially support the Python
limited API. The '--enable-py-limited-api' option can remain experimental,
with appropriate forewarnings about its limitations and guarantees.

This patch adds a new header, python-limited-api-missing.h, which
exposes symbols not yet part of the Python limited API.

Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=23830
Approved-By: Tom Tromey <tom@tromey.com>
2026-05-15 11:12:32 +01:00
Matthieu Longo
e3998113f9 gdb: add new helpers for retrieving a type's fully qualified name
Py_TYPE (self)->tp_name is the traditional idiomatic way to get a Python
type's fully qualified name. However, in the context of the Python
limited API, PyTypeObject is opaque, so the 'tp_name' attribute is no
longer accessible. Additionally, retrieving the type of a Python object
requires Py_TYPE, which is only available as part of the stable API
starting with Python 3.14.

This patch increases minimal Python limited API version from 3.11 to 3.14.
It also introduces two new helpers to retrieve a type's fully qualified
name: gdb_py_tp_name() and gdbpy_py_obj_tp_name(), which extract the fully
qualified name from a PyTypeObject and a PyObject, respectively. Ifdefery
allows these wrappers to select the appropriate API depending on the Python
version and whether the Python limited API is enabled. For any Python
version less than 3.13, gdb_py_tp_name() fallbacks using __qualname__
instead. However, the result may differ slightly in some cases, e.g. the
module name may be missing.

Finally, this patch adapts the existing code to use these wrappers, and
adjusts some test expectations to use the fully qualified name (or
__qualname__ for versions <= 3.13) where it was not previously used.
Note that the corner case where the module name would be missing does not
appear in the testsuite.

Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=23830

Approved-By: Tom Tromey <tom@tromey.com>
2026-04-08 11:49:30 +01:00
Tom Tromey
bbc133a308 Hold the GIL while clearing gdbpy_reggroup_object_map
Tom de Vries pointed out that a certain Python test left a core file.
Looking into this, I think the problem is that the GIL is not held
when gdbpy_reggroup_object_map is destroyed.

This patch changes the code to explicitly clear the global while
holding the GIL.  This fixed the crash for me.

This also adds a comment to gdbpy_initialize_file to explicitly
mention that the GIL is held while the finalizers are run.

Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=34013
Reviewed-By: Tom de Vries <tdevries@suse.de>
2026-03-25 11:12:14 -06:00
Andrew Burgess
030f56e0e8 gdb/python: introduce gdb.Symtab.source_lines method
This commit adds a new method gdb.Symtab.source_lines.  This method
can be used to read the lines from a symtab's source file.  This is
similar to GDB's internal source_cache::get_source_lines function.

Currently using the Python API, if a user wants to display source
lines then they need to use Symtab.fullname() to get the source file
name, then open this file and parse out the lines themselves.

This isn't too much effort, but the problem is that these lines will
not be styled.  The user could style the source content themselves,
but will this be styled exactly as GDB would style it?

The new Symtab.source_lines() method returns source lines with styling
included (as ANSI terminal escape sequences), assuming of course, that
styling is currently enabled.

Of course, in some cases, a user of the Python API might want source
code without styling.  That's supported too, the new method has an
'unstyled' argument.  If this is True then the output is forced to be
unstyled.  The argument is named 'unstyled' rather than 'styled'
because the API call cannot force styling on.  If 'set style enabled
off' is in effect then making the API call will never return styled
source lines.

The new API call allows for a range of lines to be requested if
desired.

As part of this commit I've updated the host_string_to_python_string
utility function to take a std::string_view.

Reviewed-By: Eli Zaretskii <eliz@gnu.org>
Approved-By: Tom Tromey <tom@tromey.com>
2026-03-05 10:17:08 +00:00
Tom Tromey
7fc4f93e28 Return gdbpy_ref<> from gdbpy_registry::lookup
This changes gdbpy_registry::lookup to return a gdbpy_ref<>, using the
type system to convey that a new reference is always returned.

Approved-By: Simon Marchi <simon.marchi@efficios.com>
2026-02-23 05:29:12 -07:00
Tom Tromey
a93acde059 Return gdbpy_ref<> from gdbarch_to_arch_object
This changes gdbarch_to_arch_object to return a gdbpy_ref<>,
using the type system to convey that a new reference is always
returned.

Approved-By: Simon Marchi <simon.marchi@efficios.com>
2026-02-23 05:29:12 -07:00
Tom Tromey
472748485e Return gdbpy_ref<> from symtab_to_linetable_object
This changes symtab_to_linetable_object to return a gdbpy_ref<>,
using the type system to convey that a new reference is always
returned.

Approved-By: Simon Marchi <simon.marchi@efficios.com>
2026-02-23 05:29:12 -07:00
Tom Tromey
3c21c86980 Return gdbpy_ref<> from frame_info_to_frame_object
This changes frame_info_to_frame_object to return a gdbpy_ref<>,
using the type system to convey that a new reference is always
returned.

Approved-By: Simon Marchi <simon.marchi@efficios.com>
2026-02-23 05:29:12 -07:00
Tom Tromey
fb81682fec Return gdbpy_ref<> from type_to_type_object
This changes type_to_type_object to return a gdbpy_ref<>,
using the type system to convey that a new reference is always
returned.

Approved-By: Simon Marchi <simon.marchi@efficios.com>
2026-02-23 05:29:12 -07:00
Tom Tromey
9a17597269 Return gdbpy_ref<> from value_to_value_object
This changes value_to_value_object to return a gdbpy_ref<>,
using the type system to convey that a new reference is always
returned.

Approved-By: Simon Marchi <simon.marchi@efficios.com>
2026-02-23 05:29:11 -07:00
Tom Tromey
702716deaf Return gdbpy_ref<> from block_to_block_object
This changes block_to_block_object to return a gdbpy_ref<>,
using the type system to convey that a new reference is always
returned.

Approved-By: Simon Marchi <simon.marchi@efficios.com>
2026-02-23 05:29:11 -07:00
Tom Tromey
9d71572cba Return gdbpy_ref<> from symtab_to_symtab_object
This changes symtab_to_symtab_object to return a gdbpy_ref<>,
using the type system to convey that a new reference is always
returned.

Approved-By: Simon Marchi <simon.marchi@efficios.com>
2026-02-23 05:29:11 -07:00
Tom Tromey
0ab23e2707 Return gdbpy_ref<> from symbol_to_symbol_object
This changes symbol_to_symbol_object to return a gdbpy_ref<>,
using the type system to convey that a new reference is always
returned.

Approved-By: Simon Marchi <simon.marchi@efficios.com>
2026-02-23 05:29:11 -07:00
Tom Tromey
800d967797 Return gdbpy_ref<> from symtab_and_line_to_sal_object
This changes symtab_and_line_to_sal_object to return a gdbpy_ref<>,
using the type system to convey that a new reference is always
returned.

Approved-By: Simon Marchi <simon.marchi@efficios.com>
2026-02-23 05:29:11 -07:00
Simon Marchi
f3965c2404 gdb/registry: add registry:🔑:try_emplace
We have many times the pattern:

    current_source_location *loc
      = current_source_key.get (pspace);
    if (loc == nullptr)
      loc = current_source_key.emplace (pspace);
    return loc;

I thought it would be nice to have it directly part of registry::key.
Add a try_emplace method, which is like emplace, except that it returns
the existing data, if any.  The try_emplace name comes from similar
methods in std::map or gdb::unordered_map
(ankerl::unordered_dense::map).

Replace as many callers as I could find to use it.

Change-Id: I21f922ca065a354f041caaf70484d6cfbcbb76ed
Approved-By: Tom Tromey <tom@tromey.com>
2026-02-09 12:48:36 -05:00
Matthieu Longo
1fe7c3b749 gdb: cast all Python extension objects passed to gdbpy_ref_policy to PyObject*
When enabling the Python limited API, pointers to Python C extension
objects can no longer be implicitly converted to 'PyObject *' by the
compiler.

gdbpy_ref_policy is a templated class that provides a generic interface
for incrementing and decrementing the reference counter on the given
object. It is used as a specialisation of the policy parameter in
gdb::ref_ptr, together with PyObject as the parameter type. As a result,
gdbpy_ref_policy always expects an argument derived from PyObject.

This patch fixes the resulting compilation issue by adding an explicit
static_cast to 'PyObject *' before passing the value to Py_INCREF and
Py_DECREF. As a side effect, these casts enforce, at compile time, that
the template type passed to gdbpy_ref_policy is a subclass of PyObject.
To provide a clearer diagnostic when an incorrect type is used, a
static_assert is added to gdbpy_ref_policy, avoiding obscure errors
originating from the static_cast. Finally, all C Python extension types
passed to gdbpy_ref_policy are updated to inherit from PyObject.

Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=23830
Approved-By: Tom Tromey <tom@tromey.com>
2026-01-29 16:46:14 +00:00
Matthieu Longo
9a84753aa7 gdb: new setters and getters for __dict__, and attributes
GDB is currently using the Python unlimited API. Migrating the codebase
to the Python limited API would have for benefit to make a GDB build
artifacts compatible with older and newer versions of Python that they
were built with.

This patch prepares the ground for migrating the existing C extension
types from static types to heap-allocated ones, by removing the
dependency on tp_dictoffset, which is unavailable when using the limited
API.

One of the most common incompatibilities in the current static type
declarations is the tp_dictoffset slot, which specifies the dictionary
offset within the instance structure. Historically, the unlimited
API has provided two approaches to supply a dictionary for __dict__:

 * A managed dictionary.
   Setting Py_TPFLAGS_MANAGED_DICT in tp_flags indicates that the
   instances of the type have a __dict__ attribute, and that the
   dictionary is managed by Python.
   According to the Python documentation, this is the recommended approach.
   However, this flag was introduced in 3.12, together with
   PyObject_VisitManagedDict() and PyObject_ClearManagedDict(), neither
   of which is part of the limited API (at least for now). As a result,
   this recommended approach is not viable in the context of the limited
   API.

 * An instance dictionary, for which the offset in the instance is
   provided via tp_dictoffset.
   According to the Python documentation, this "tp slot" is on the
   deprecation path, and Py_TPFLAGS_MANAGED_DICT should be used instead.
   Given the age of the GDB codebase and the requirement to support older
   Python versions (>= 3.4), no need to argue that today, the implementation
   of __dict__ relies on tp_dictoffset. However, in the context of the
   limited API, PyType_Slot does not provide a Py_tp_dictoffset member, so
   another approach is needed to provide __dict__ to instances of C extension
   types.

Given the constraints of the limited API, the proposed solution consists
in providing a dictionary through a common base class, gdbpy__dict__wrapper.
This helper class owns a dictionary member corresponding to __dict__, and
any C extension type requiring a __dict__ must inherit from it. Since
extension object must also be convertible to PyObject, this wrapper class
publicly inherits from PyObject as well.
Access to the dictionary is provided via a custom getter defined in a
PyGetSetDef, similarily to what was previously done with gdb_py_generic_dict().
Because __dict__ participates in attribute look-up, and since this dictionary
is neither managed by Python nor exposed via tp_dictoffset, custom
implementations of tp_getattro and tp_setattro are required to correctly
redirect attribute look-ups to the dictionary. These custom implementations
— equivalent to PyObject_GenericGetAttr() and PyObject_GenericSetAttr() —
must be installed via tp_getattro / tp_setattro for static types, or
Py_tp_getattro / Py_tp_setattro for heap-allocated types.

- gdbpy__dict__wrapper: a base class for C extension objects that own a
  __dict__.
- gdb_py_generic_dict_getter: a __dict__ getter for extension types
  derived from gdbpy__dict__wrapper.
- gdb_py_generic_getattro: equivalent of PyObject_GenericGetAttr, but
  fixes the look-up of __dict__.
- gdb_py_generic_setattro: equivalent of PyObject_GenericSetAttr, but
  fixes the look-up of __dict__.

Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=23830
Approved-By: Tom Tromey <tom@tromey.com>
2026-01-29 16:46:14 +00:00
Matthieu Longo
8b0f0d5fbf gdbpy_registry: cast C extension type object to PyObject * before Py_XINCREF
When enabling the Python limited API, pointers to Python C extension
objects can no longer be implicitly converted to 'PyObject *' by the
compiler.

The lookup() method of gbdpy_registry returns a new reference to the
type object of the looked-up entry. It does so by calling Py_XINCREF()
to increment the reference counter of the returned type object. The
template parameter obj_type corresponds to the type of C extension
object type. With the Python limited API enabled, obj_type can no longer
be implicitly converted to 'PyObject *' when passed to Py_XINCREF().

This patch fixes the resulting compilation issue by adding an explicit
static_cast to 'PyObject *' before passing the value to Py_XINCREF().
As a side effect, this cast enforces, at compile time, that the template
type 'Storage::obj_type' passed to gdbpy_registry is a subclass of
PyObject. To provide a clearer diagnostic when an incorrect type is used,
a static_assert is added to gdbpy_registry, avoiding obscure errors
originating from the static_cast. Finally, the relevant C extension types
passed to gdbpy_registry are updated to inherit publicly from PyObject.

Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=23830
Approved-By: Tom Tromey <tom@tromey.com>
2026-01-29 16:46:14 +00:00
Matthieu Longo
264a8a2236 Python limited API: migrate Py_CompileStringExFlags and PyRun_SimpleString
This patch replaces Py_CompileStringExFlags () with its limited C API
equivalent, Py_CompileString (). The eval_python_command () helper is
now exposed through the private GDB Python API as a utility function.
PyRun_SimpleString () is replaced with eval_python_command () to avoid
code duplication.

Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=23830
Approved-By: Tom Tromey <tom@tromey.com>
2026-01-28 09:41:25 +00:00
Tom Tromey
4abc1ce2cc Update copyright dates to include 2026
This updates the copyright headers to include 2026.  I did this by
running gdb/copyright.py and then manually modifying a few files as
noted by the script.
2026-01-05 13:16:46 -07:00
Tom Tromey
b056a39914 Don't use "module" name
In C++20, "module" is an "identifier with special meaning".  While it
can be used as a variable name, it highlights as a keyword in Emacs,
and I think it's nicer to just avoid it.

Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=32660
2025-12-18 11:50:08 -07:00
Simon Marchi
b15df2e027 gdb: fix some whitespace issues
Replace 8 spaces with a tab.

Change-Id: Ie8f942ce4b4ba4a83c2ee83cb904153b2e58cf8c
2025-11-26 15:12:03 -05:00
Tom Tromey
8eeb52e3c7 Remove Python API checker defines
The GCC plugin that implements the Python API checker does not appear
to really be maintained.  And, as far as I know, it never really
worked for C++ code anyway.  Considering those factors, and that no
one has tried to run it in years, I think it's time to remove the
macros from the gdb source.

Approved-By: Simon Marchi <simon.marchi@efficios.com>
2025-10-23 07:48:55 -06:00
Tom Tromey
f20c97f00d Remove Py_TPFLAGS_CHECKTYPES
According to 'git annotate', the Py_TPFLAGS_CHECKTYPES was added to
python-internal.h way back when gdb was first ported to Python 3.  It
was a compatibility fix for Python 2.

This is not needed any more, because Python 2 is no longer supported.
This patch removes the vestiges.

Approved-By: Simon Marchi <simon.marchi@efficios.com>
2025-10-23 07:43:00 -06:00
Simon Marchi
a5cbe67512 gdb, gdbserver, gdbsupport: trim trailing whitespaces
I noticed my IDE (VSCode) starting to automatically trim trailing
whitespaces on save, despite the setting for it being disabled.  I
realized that this is because the .editorconfig file now has

    trim_trailing_whitespace = true

for many file types.  If we have this EditorConfig setting forcing
editors to trim trailing whitespaces, I think it would make sense to
clean up trailing whitespaces from our files.  Otherwise, people will
always get spurious whitespace changes when editing these files.

I did a mass cleanup using this command:

$ find gdb gdbserver gdbsupport -type f \( \
    -name "*.c" -o \
    -name "*.h" -o \
    -name "*.cc" -o \
    -name "*.texi" -o \
    -name "*.exp" -o \
    -name "*.tcl" -o \
    -name "*.py" -o \
    -name "*.s" -o \
    -name "*.S" -o \
    -name "*.asm" -o \
    -name "*.awk" -o \
    -name "*.ac" -o \
    -name "Makefile*" -o \
    -name "*.sh" -o \
    -name "*.adb" -o \
    -name "*.ads" -o \
    -name "*.d" -o \
    -name "*.go" -o \
    -name "*.F90" -o \
    -name "*.f90" \
\) -exec sed -ri 's/[ \t]+$//' {} +

I then did an autotools regen, because we don't actually want to change
the Makefile and Makefile.in files that are generated.

Change-Id: I6f91b83e3b8c4dc7d5d51a2ebf60706120efe691
2025-10-20 15:44:08 -04:00
Andrew Burgess
7862554bcf gdb/python: introduce gdb.Corefile API
This commit starts adding some core file related features to the
Python API.

In this initial commit I've tried to keep the changes as small as
possible for easy review.

There's a new Python class gdb.Corefile, which represents a loaded
core file.  This API doesn't allow the user to create their own
gdb.Corefile objects, a core file must be loaded using the 'core-file'
command, then a gdb.Corefile object can be obtained by querying the
inferior in which the core file was loaded.

There's a new attribute gdb.Inferior.corefile, this is None when no
core file is loaded, or contains a gdb.Corefile object if a core file
has been loaded.

Currently, the gdb.Corefile object has one attribute, and one method,
these are:

  gdb.Corefile.filename -- the file name of the loaded core file.

  gdb.Corefile.is_valid() -- indicates if a gdb.Corefile object is
  valid or not.  See notes below.

A gdb.Corefile object is only valid while the corresponding core file
is loaded into an inferior.  Unloading the core file, or loading a
different one will cause a gdb.Corefile object to become invalid.  For
example:

  (gdb) core-file /tmp/core.54313
  ... snip ...
  (gdb) python core=gdb.selected_inferior().corefile
  (gdb) python print(core)
  <gdb.Corefile inferior=1 filename='/tmp/core.54313'>
  (gdb) python print(core.is_valid())
  True
  (gdb) core-file
  No core file now.
  (gdb) python print(core)
  <gdb.Corefile (invalid)>
  (gdb) python print(core.is_valid())
  False
  (gdb)

In order to track changes to the core file, there is a new observable
'core_file_changed', which accounts for the changes in corelow.c,
observable,c, and observable.h.  Currently, this observable is not
visible as a Python event.

I chose to access the core file via the inferior even though the core
file BFD object is actually stored within the program_space.  As such,
it might seem that the natural choice would be to add the attribute as
gdb.Progspace.corefile.

For background reading on my choice, please see:

  https://inbox.sourceware.org/gdb-patches/577f2c47793acb501c2611c0e6c7ea379f774830.1668789658.git.aburgess@redhat.com

This patch was never merged, it is still on my backlog, but the
observation in that work is that some targets are not really
shareable.  For example, the core_target (corelow.c) stores
information about the loaded core file within the target instance.  As
such, each target instance represents a single loaded core file.

Except that the BFD part of the core file is stored in the
program_space, which is a little weird.

During review, Tom made the observation, that maybe we should
investigate moving the core file BFD into the core_target.  I'm
inclined to agree with this as a direction of travel.

All this leaves us with two observations:

  1. Currently, loading a core file into an inferior, then using
     'add-inferior' will try to share the core_target between
     inferiors.  This is broken, and can trigger GDB crashes.  The
     obvious fix, without reworking core_target, is just to prevent
     this sharing, making core_target per-inferior.

  2. Having the core file information split between the core_target
     instance, and the BFD stored in the program_space is a little
     weird, and is really just historical.  Planning for a future
     where the BFD is also stored in the core_target might be wise.

So, if we imagine that the BFD is (one day) moved into the
core_target, and that the core_target really becomes non-shareable,
then it is, I think, clearer that the corefile attribute should live
on the gdb.Inferior object, not the gdb.Progspace object.

There's testing for all the functionality added in this commit.

Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=32844

Reviewed-By: Eli Zaretskii <eliz@gnu.org>
Approved-By: Tom Tromey <tom@tromey.com>
2025-10-06 16:56:55 +01:00
Andrew Burgess
3c72459681 gdb/python: extend gdb.write to support styled output
It is already possible to produce styled output from Python by
converting the gdb.Style to its escape code sequence, and writing that
to the output stream.

But this commit adds an alternative option to the mix by extending the
existing gdb.write() function to accept a 'style' argument.  The value
of this argument can be 'None' to indicate no style change should be
performed, this is the default, and matches the existing behaviour.

Or the new 'style' argument can be a gdb.Style object, in which case
the specified style is applied only for the string passed to
gdb.write, after which the default style is re-applied.

Using gdb.write with a style object more closely matches how GDB
handles styling internally, and has the benefit that the user doesn't
need to remember to restore the default style when they are done.

Reviewed-By: Eli Zaretskii <eliz@gnu.org>
Approved-By: Tom Tromey <tom@tromey.com>
2025-10-05 13:48:06 +01:00
Andrew Burgess
f5493d6c96 gdb/python: return gdbpy_ref<> from gdbpy_create_ptid_object
Update gdbpy_create_ptid_object (python/py-infthread.c) to return a
gdbpy_ref<> rather than a 'PyObject *'.  This reduces the chances that
a caller will leak an object, though no such memory leaks are fixed in
this commit, this is just a code improvement patch.

There should be no user visible changes after this commit.

Approved-By: Simon Marchi <simon.marchi@efficios.com>
2025-08-26 22:02:40 +01:00
Andrew Burgess
f84a4db958 gdb/python/guile: fix segfault from nested prefix command creation
A commit I recently pushed:

  commit 0b5023cc71
  Date:   Sat Apr 12 09:15:53 2025 +0100

      gdb/python/guile: user created prefix commands get help list

can trigger a segfault if a user tries to create nested prefix
commands.  For example, this will trigger a crash:

  (gdb) python gdb.ParameterPrefix("prefix-1", gdb.COMMAND_NONE)
  (gdb) python gdb.ParameterPrefix("prefix-1 prefix-2", gdb.COMMAND_NONE)

  Fatal signal: Segmentation fault
  ... etc ...

If the user adds an actual parameter under 'prefix-1' before creating
'prefix-2', then everything is fine:

  (gdb) python gdb.ParameterPrefix("prefix-1", gdb.COMMAND_NONE)
  (gdb) python gdb.Parameter('prefix-1 param-1', gdb.COMMAND_NONE, gdb.PARAM_BOOLEAN)
  (gdb) python gdb.ParameterPrefix("prefix-1 prefix-2", gdb.COMMAND_NONE)

The mistake in the above patch is in how gdbpy_parse_command_name is
used.  The BASE_LIST output argument from this function points to the
list of commands for the prefix, not to the prefix command itself.

So when gdbpy_parse_command_name is called for 'prefix-1 prefix-2',
BASE_LIST points to the list of commands associated with 'prefix-1',
not to the actual 'prefix-1' cmd_list_element.

Back in cmdpy_init, from where gdbpy_parse_command_name was called, I
was walking back from the first entry in BASE_LIST to figure out if
this was a "show" prefix command or not.  However, if BASE_LIST is
empty then there is no first item, and this would trigger the
segfault.

The solution it to extend gdbpy_parse_command_name to also return the
prefix cmd_list_element in addition to the existing values.  With this
done, and cmdpy_init updated, the segfault is now avoided.

There's a new test that would trigger the crash without the patch.

And, of course, the above commit also broke guile in the exact same
way.  And the fix is exactly the same.  And there's a guile test too.

NOTE: We should investigate possibly sharing some of this boiler plate
helper code between Python and Guile.  But not in this commit.

Approved-By: Tom Tromey <tom@tromey.com>
2025-06-04 09:39:33 +01:00
Tom Tromey
d61186d8f8 Require Python 3.4
I believe we previously agreed that the minimum supported Python
version should be 3.4.  This patch makes this change, harmonizing the
documentation (which was inconsistent about the minimum version) and
the code.

New in v2: rebased, and removed a pre-3.4 workaround from __init__.py.

Reviewed-By: Eli Zaretskii <eliz@gnu.org>
Approved-by: Kevin Buettner <kevinb@redhat.com>
Acked-By: Tom de Vries <tdevries@suse.de>
Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=31870
2025-05-30 07:09:53 -06:00
Tom Tromey
d01e823438 Update copyright dates to include 2025
This updates the copyright headers to include 2025.  I did this by
running gdb/copyright.py and then manually modifying a few files as
noted by the script.

Approved-By: Eli Zaretskii <eliz@gnu.org>
2025-04-08 10:54:39 -06:00
Tom de Vries
d3d4840e80 [gdb/build] Fix build with gcc 9
Since commit a691853148 ("gdb/python: introduce gdbpy_registry"), when
building gdb with gcc 9, I run into:
...
In file included from gdb/varobj.c:38:0:
gdb/python/python-internal.h:1211:47: error: expected ‘;’ before ‘<’ token
   using StorageKey = typename registry<O>::key<Storage>;
                                               ^
...
due to this code:
...
template <typename Storage>
class gdbpy_registry
{
  ...

  template<typename O>
  using StorageKey = typename registry<O>::key<Storage>;

  template<typename O>
  Storage *get_storage (O *owner, const StorageKey<O> &key) const
  { ... }

  ...
}
...

As an experiment, I tried out eliminating the type alias:
...
  template<typename O>
  Storage *get_storage (O *owner,
                        const typename registry<O>::key<Storage> &key) const
  { ... }
...
and got instead:
...
In file included from gdb/varobj.c:38:0:
gdb/python/python-internal.h:1211:63: error: non-template ‘key’ used as template
  Storage *get_storage (O *owner,
                        const typename registry<O>::key<Storage> &key) const
                                                     ^~~
gdb/python/python-internal.h:1211:63: note: use ‘registry<O>::template key’ \
  to indicate that it is a template
...

Following that suggestion, I tried:
...
  template<typename O>
  Storage *
  get_storage (O *owner,
               const typename registry<O>::template key<Storage> &key) const
  { ... }
...
which fixed the problem.

Likewise, adding the template keyword in the type alias fixes the original
problem, so fix it like that.

Tested on x86_64-linux.
2025-03-20 11:16:59 +01:00
Jan Vrany
a691853148 gdb/python: introduce gdbpy_registry
This commit introduces new template class gdbpy_registry to simplify
Python object lifecycle management. As of now, each of the Python
object implementations contain its own (copy of) lifecycle management
code that is largely very similar. The aim of gdbpy_registry is to
factor out this code into a common (template) class in order to simplify
the code.

Approved-By: Tom Tromey <tom@tromey.com>
2025-03-19 21:12:53 +00:00
Tom Tromey
cc70964032 Run check-include-guards.py
This patch is the result of running check-include-guards.py on the
current tree.  Running it a second time causes no changes.

Reviewed-By: Tom de Vries <tdevries@suse.de>
2024-12-18 10:00:44 -07:00
Simon Marchi
112f6d85fb Convert type copying to new hash table
This converts the type copying code to use the new hash map.

Change-Id: I35f0a4946dcc5c5eb84820126cf716b600f3302f
Co-Authored-By: Tom Tromey <tom@tromey.com>
Approved-By: Tom Tromey <tom@tromey.com>
2024-11-25 22:07:04 -05:00
Tom de Vries
fa61a48db2 [gdb/python] Eliminate GDB_PY_SET_HANDLE_EXCEPTION
Result of:
...
$ search="GDB_PY_SET_HANDLE_EXCEPTION ("
$ replace="return gdbpy_handle_gdb_exception (-1, "
$ sed -i \
    "s/$search/$replace/" \
    gdb/python/*.c
...

Also remove the now unused GDB_PY_SET_HANDLE_EXCEPTION.

No functional changes.

Tested on x86_64-linux.

Approved-By: Tom Tromey <tom@tromey.com>
2024-09-24 13:06:32 +02:00
Tom de Vries
1ccb6f106a [gdb/python] Eliminate GDB_PY_HANDLE_EXCEPTION
Result of:
...
$ search="GDB_PY_HANDLE_EXCEPTION ("
$ replace="return gdbpy_handle_gdb_exception (nullptr, "
$ sed -i \
    "s/$search/$replace/" \
    gdb/python/*.c
...

Also remove the now unused GDB_PY_HANDLE_EXCEPTION.

No functional changes.

Tested on x86_64-linux.

Approved-By: Tom Tromey <tom@tromey.com>
2024-09-24 13:06:32 +02:00
Tom de Vries
912bc231ab [gdb/python] Add gdbpy_handle_gdb_exception
I've recently committed two patches:
- commit 2f8cd40c37 ("[gdb/python] Use GDB_PY_HANDLE_EXCEPTION more often")
- commit fbf8e4c35c ("[gdb/python] Use GDB_PY_SET_HANDLE_EXCEPTION more often")
which use the macros GDB_PY_HANDLE_EXCEPTION and GDB_PY_SET_HANDLE_EXCEPTION
more often, with the goal of making things more consistent.

Having done that, I wondered if a better approach could be possible.

Consider GDB_PY_HANDLE_EXCEPTION:
...
 /* Use this in a 'catch' block to convert the exception to a Python
    exception and return nullptr.  */
 #define GDB_PY_HANDLE_EXCEPTION(Exception)	\
   do {						\
     gdbpy_convert_exception (Exception);	\
     return nullptr;				\
   } while (0)
...

The macro nicely codifies how python handles exceptions:
- setting an error condition using some PyErr_Set* variant, and
- returning a value implying that something went wrong
presumably with the goal that using the macro will mean not accidentally:
- forgetting to return on error, or
- returning the wrong value on error.

The problems are that:
- the macro hides control flow, specifically the return statement, and
- the macro hides the return value.

For example, when reading somewhere:
...
  catch (const gdb_exception &except)
    {
      GDB_PY_HANDLE_EXCEPTION (except);
    }
...
in order to understand what this does, you have to know that the macro
returns, and that it returns nullptr.

Add a template gdbpy_handle_gdb_exception:
...
template<typename T>
[[nodiscard]] T
gdbpy_handle_gdb_exception (T val, const gdb_exception &e)
{
  gdbpy_convert_exception (e);
  return val;
}
...
which can be used instead:
...
  catch (const gdb_exception &except)
    {
      return gdbpy_handle_gdb_exception (nullptr, except);
    }
...

[ Initially I tried this:
...
template<auto val>
[[nodiscard]] auto
gdbpy_handle_gdb_exception (const gdb_exception &e)
{
  gdbpy_convert_exception (e);
  return val;
}
...
with which the usage is slightly better looking:
...
  catch (const gdb_exception &except)
    {
      return gdbpy_handle_gdb_exception<nullptr> (except);
    }
...
but I ran into trouble with older gcc compilers. ]

While still a single statement, we now have it clear:
- that the statement returns,
- what value the statement returns.

[ FWIW, this could also be handled by say:
...
-      GDB_PY_HANDLE_EXCEPTION (except);
+      GDB_PY_HANDLE_EXCEPTION_AND_RETURN_VAL (except, nullptr);
...
but I still didn't find the fact that it returns easy to spot.

Alternatively, this is the simplest form we could use:
...
      return gdbpy_convert_exception (e), nullptr;
...
but the pairing would not necessarily survive a copy/paste/edit cycle. ]

Also note how making the value explicit makes it easier to check for
consistency:
...
  catch (const gdb_exception &except)
    {
      return gdbpy_handle_gdb_exception (-1, except);
    }

  if (PyErr_Occurred ())
    return -1;
...
given that we do use the explicit constants almost everywhere else.

Compared to using GDB_PY_HANDLE_EXCEPTION, there is the burden now to specify
the return value, but I assume that this will be generally copy-pasted and
therefore present no problem.

Also, there's no longer a guarantee that there's an immediate return, but I
assume that nodiscard making sure that the return value is not silently
ignored is sufficient mitigation.

For now, re-implement GDB_PY_HANDLE_EXCEPTION and GDB_PY_SET_HANDLE_EXCEPTION
in terms of gdbpy_handle_gdb_exception.

Follow-up patches will eliminate the macros.

No functional changes.

Tested on x86_64-linux.

Approved-By: Tom Tromey <tom@tromey.com>
2024-09-24 13:06:32 +02:00
Tom Tromey
336bb2a1c1 Automatically add types to Python modules
PR python/32163 points out that various types provided by gdb are not
added to the gdb module, so they aren't available for interactive
inspection.  I think this is just an oversight.

This patch fixes the problem by introducing a new helper function that
both readies the type and then adds it to the appropriate module.  The
patch also poisons PyType_Ready, the idea being to avoid this bug in
the future.

v2:
* Fixed a bug in original patch in gdb.Architecture registration
* Added regression test for the types mentioned in the bug

Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=32163
Reviewed-By: Alexandra Petlanova Hajkova <ahajkova@redhat.com>
2024-09-23 13:44:59 -06:00
Felix Willgerodt
6be9971c93 btrace, python: Enable ptwrite filter registration.
By default GDB will be printing the hex payload of the ptwrite package as
auxiliary information.  To customize this, the user can register a ptwrite
filter function in python, that takes the payload and the PC as arguments and
returns a string which will be printed instead.  Registering the filter
function is done using a factory pattern to make per-thread filtering easier.

Approved-By: Markus Metzger <markus.t.metzger@intel.com>
2024-08-14 11:20:57 +02:00
Simon Marchi
d9deb60b2e gdb, gdbserver, gdbsupport: use [[noreturn]] instead of ATTRIBUTE_NORETURN
C++ 11 has a built-in attribute for this, no need to use a compat macro.

Change-Id: I90e4220d26e8f3949d91761f8a13cd9c37da3875
Reviewed-by: Lancelot Six <lancelot.six@amd.com>
2024-07-16 18:30:45 -04:00
Tom de Vries
b820cd55a3 [gdb/build] Redo poisoning of PyObject_CallMethod
In commit 764af87825 ("[gdb/python] Add typesafe wrapper around
PyObject_CallMethod") I added poisoning of PyObject_CallMethod:
...
/* Poison PyObject_CallMethod.  The typesafe wrapper gdbpy_call_method should be
   used instead.  */
template<typename... Args>
PyObject *
PyObject_CallMethod (Args...);
...

The idea was that subsequent code would be forced to use gdbpy_call_method
instead of PyObject_CallMethod.

However, that caused build issues with gcc 14 and python 3.13:
...
/usr/bin/ld: python/py-disasm.o: in function `gdb::ref_ptr<_object, gdbpy_ref_policy<_object> > gdbpy_call_method<unsigned int, long long>(_object*, char const*, unsigned int, long long)':
/data/vries/gdb/src/gdb/python/python-internal.h:207:(.text+0x384f): undefined reference to `_object* PyObject_CallMethod<_object*, char*, char*, unsigned int, long long>(_object*, char*, char*, unsigned int, long long)'
/usr/bin/ld: python/py-tui.o: in function `gdb::ref_ptr<_object, gdbpy_ref_policy<_object> > gdbpy_call_method<int>(_object*, char const*, int)':
/data/vries/gdb/src/gdb/python/python-internal.h:207:(.text+0x1235): undefined reference to `_object* PyObject_CallMethod<_object*, char*, char*, int>(_object*, char*, char*, int)'
/usr/bin/ld: python/py-tui.o: in function `gdb::ref_ptr<_object, gdbpy_ref_policy<_object> > gdbpy_call_method<int, int, int>(_object*, char const*, int, int, int)':
/data/vries/gdb/src/gdb/python/python-internal.h:207:(.text+0x12b0): undefined reference to `_object* PyObject_CallMethod<_object*, char*, char*, int, int, int>(_object*, char*, char*, int, int, int)'
collect2: error: ld returned 1 exit status
...

Fix this by poisoning without using templates.

Tested on x86_64-linux.
2024-06-19 19:18:23 +02:00
Lancelot SIX
ea4e03c0a9 gdb/python/python-internal.h: avoid uninitialized constexpr
The following recent change introduced a regression when building using
clang++:

    commit 764af87825
    Date:   Wed Jun 12 18:58:49 2024 +0200

        [gdb/python] Add typesafe wrapper around PyObject_CallMethod

The error message is:

    ../../gdb/python/python-internal.h:151:16: error: default initialization of an object of const type 'const char'
    constexpr char gdbpy_method_format;
                   ^
                                       = '\0'
      CXX    python/py-block.o
    1 error generated.
    make[2]: *** [Makefile:1959: python/py-arch.o] Error 1
    make[2]: *** Waiting for unfinished jobs....
    In file included from ../../gdb/python/py-auto-load.c:25:
    ../../gdb/python/python-internal.h:151:16: error: default initialization of an object of const type 'const char'
    constexpr char gdbpy_method_format;
                   ^
                                       = '\0'
    1 error generated.
    make[2]: *** [Makefile:1959: python/py-auto-load.o] Error 1
    In file included from ../../gdb/python/py-block.c:23:
    ../../gdb/python/python-internal.h:151:16: error: default initialization of an object of const type 'const char'
    constexpr char gdbpy_method_format;
                   ^
                                       = '\0'
    1 error generated.

This patch fixes this by changing gdbpy_method_format to be a templated
struct, and only have its specializations define the static constexpr
member "format".  This way, we avoid having an uninitialized constexpr
expression, regardless of it being instantiated or not.

Reviewed-By: Tom de Vries <tdevries@suse.de>
Change-Id: I5bec241144f13500ef78daea30f00d01e373692d
2024-06-19 15:09:04 +01:00
Tom Tromey
c2d091ff5c Add gdbpy_call_method overloads for gdbpy_ref<>
This adds an overload of gdbpy_call_method that accepts a gdbpy_ref<>.
This is just a small convenience.

Reviewed-By: Tom de Vries <tdevries@suse.de>
2024-06-13 10:13:37 -06:00