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-08-21 09:45:18 +01:00
|
|
|
|
/* Python interface to core files.
|
|
|
|
|
|
|
2026-01-05 08:13:29 -07:00
|
|
|
|
Copyright (C) 2025-2026 Free Software Foundation, Inc.
|
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-08-21 09:45:18 +01:00
|
|
|
|
|
|
|
|
|
|
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 "python-internal.h"
|
|
|
|
|
|
#include "progspace.h"
|
|
|
|
|
|
#include "observable.h"
|
|
|
|
|
|
#include "inferior.h"
|
2025-08-25 16:48:22 +01:00
|
|
|
|
#include "gdbcore.h"
|
|
|
|
|
|
#include "gdbsupport/rsp-low.h"
|
2026-03-27 09:52:55 +00:00
|
|
|
|
#include "py-event.h"
|
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-08-21 09:45:18 +01:00
|
|
|
|
|
|
|
|
|
|
/* A gdb.Corefile object. */
|
|
|
|
|
|
|
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>
2025-07-17 18:36:41 +01:00
|
|
|
|
struct corefile_object : public gdbpy_dict_wrapper
|
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-08-21 09:45:18 +01:00
|
|
|
|
{
|
|
|
|
|
|
/* The inferior this core file is attached to. This will be set to NULL
|
|
|
|
|
|
when the inferior is deleted, or if a different core file is loaded
|
|
|
|
|
|
for the inferior. When this is NULL the gdb.Corefile object is
|
|
|
|
|
|
considered invalid.*/
|
|
|
|
|
|
struct inferior *inferior;
|
|
|
|
|
|
|
2025-08-25 16:48:22 +01:00
|
|
|
|
/* A Tuple of gdb.CorefileMappedFile objects. This tuple is only created
|
|
|
|
|
|
the first time the user calls gdb.Corefile.mapped_files(), the result
|
|
|
|
|
|
is cached here. If this pointer is not NULL then this is an owning
|
|
|
|
|
|
pointer (i.e. this owns a reference to the Tuple). */
|
|
|
|
|
|
PyObject *mapped_files;
|
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-08-21 09:45:18 +01:00
|
|
|
|
};
|
|
|
|
|
|
|
2025-10-21 10:00:20 -06:00
|
|
|
|
extern PyTypeObject corefile_object_type;
|
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-08-21 09:45:18 +01:00
|
|
|
|
|
2025-08-25 16:48:22 +01:00
|
|
|
|
/* A gdb.CorefileMapped object. */
|
|
|
|
|
|
|
2025-10-25 23:55:29 +01:00
|
|
|
|
struct corefile_mapped_file_object : public PyObject
|
2025-08-25 16:48:22 +01:00
|
|
|
|
{
|
|
|
|
|
|
/* The name of a file that was mapped when the core file was created.
|
|
|
|
|
|
This is a 'str' object. */
|
|
|
|
|
|
PyObject *filename;
|
|
|
|
|
|
|
|
|
|
|
|
/* The build-id of a file that was mapped when the core file was
|
|
|
|
|
|
created. This is either a 'str' if the file had a build-id, or
|
|
|
|
|
|
'None' if there was no build-id for this file. */
|
|
|
|
|
|
PyObject *build_id;
|
|
|
|
|
|
|
|
|
|
|
|
/* A List of gdb.CorefileMappedFileRegion objects. */
|
|
|
|
|
|
PyObject *regions;
|
|
|
|
|
|
|
|
|
|
|
|
/* True if this represents the main executable from which the core file
|
|
|
|
|
|
was created. */
|
|
|
|
|
|
bool is_main_exec_p;
|
|
|
|
|
|
};
|
|
|
|
|
|
|
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-14 09:39:57 +01:00
|
|
|
|
static_assert (gdb::is_python_allocatable_v<corefile_mapped_file_object>);
|
|
|
|
|
|
|
2025-10-21 10:00:20 -06:00
|
|
|
|
extern PyTypeObject corefile_mapped_file_object_type;
|
2025-08-25 16:48:22 +01:00
|
|
|
|
|
|
|
|
|
|
/* A gdb.CorefileMappedFileRegion object. */
|
|
|
|
|
|
|
2025-10-25 23:55:29 +01:00
|
|
|
|
struct corefile_mapped_file_region_object : public PyObject
|
2025-08-25 16:48:22 +01:00
|
|
|
|
{
|
|
|
|
|
|
/* The start and end addresses for this mapping, these are addresses
|
|
|
|
|
|
within the inferior's address space. */
|
|
|
|
|
|
CORE_ADDR start;
|
|
|
|
|
|
CORE_ADDR end;
|
|
|
|
|
|
|
|
|
|
|
|
/* The offset within the mapped file for this mapping. */
|
|
|
|
|
|
ULONGEST file_offset;
|
|
|
|
|
|
};
|
|
|
|
|
|
|
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-14 09:39:57 +01:00
|
|
|
|
static_assert (gdb::is_python_allocatable_v<corefile_mapped_file_region_object>);
|
|
|
|
|
|
|
2025-10-21 10:00:20 -06:00
|
|
|
|
extern PyTypeObject corefile_mapped_file_region_object_type;
|
2025-08-25 16:48:22 +01:00
|
|
|
|
|
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-08-21 09:45:18 +01:00
|
|
|
|
/* Clear the inferior pointer in a Corefile object OBJ when an inferior is
|
|
|
|
|
|
deleted. */
|
|
|
|
|
|
|
|
|
|
|
|
struct inferior_corefile_deleter
|
|
|
|
|
|
{
|
|
|
|
|
|
void operator() (corefile_object *obj)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (!gdb_python_initialized)
|
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
|
|
gdbpy_enter enter_py;
|
|
|
|
|
|
|
|
|
|
|
|
/* When OBJECT goes out of scope this will Py_DECREF on OBJ. */
|
|
|
|
|
|
gdbpy_ref<corefile_object> object (obj);
|
|
|
|
|
|
|
|
|
|
|
|
/* Clearing the inferior pointer marks the gdb.Corefile as invalid. */
|
|
|
|
|
|
object->inferior = nullptr;
|
|
|
|
|
|
}
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
/* Store a gdb.Corefile object in an inferior's registry. */
|
|
|
|
|
|
|
|
|
|
|
|
static const registry<inferior>::key<corefile_object,
|
|
|
|
|
|
inferior_corefile_deleter>
|
|
|
|
|
|
cfpy_inferior_corefile_data_key;
|
|
|
|
|
|
|
|
|
|
|
|
/* See python-internal.h. */
|
|
|
|
|
|
|
|
|
|
|
|
gdbpy_ref<>
|
|
|
|
|
|
gdbpy_core_file_from_inferior (inferior *inf)
|
|
|
|
|
|
{
|
|
|
|
|
|
gdb_assert (inf != nullptr);
|
|
|
|
|
|
gdb_assert (inf->pspace != nullptr);
|
|
|
|
|
|
|
gdb: move core file bfd from program_space into core_target
This commit moves the 'gdb_bfd_ref_ptr cbfd' out of program_space and
into core_target, where it is now called m_core_bfd.
I believe this change makes sense as the core_target instance holds
additional information that is parsed from the core file BFD, and so
storing the parsed information separately from the BFD doesn't make
much sense to me.
To minimise the churn in this commit, I have retained the
program_space::core_bfd member function as a temporary hack. This
function forwards the request to the new function
get_inferior_core_bfd. This works fine for now as
program_space::core_bfd is, after this commit, only called on the
current_program_space. If this all seems like a total hack, then it
is, but don't worry too much, the next commit will clean this all up.
I was tempted to make the new function get_inferior_core_bfd, a member
function of the inferior class, inferior::core_bfd. In fact, that
would have been my preferred change. However, the new function needs
visibility of the core_target class, which, right now is private
within the corelow.c file.
This shouldn't be a problem, we could just declare the member function
in inferior.h, and implement the function in corelow.c. But this
would mean the implementation of inferior::core_bfd, would not live in
inferior.c. Previously when I've implemented member functions outside
their natural home (e.g. an inferior function not in inferior.c) I've
received review feedback that this is not desirable. So, for now,
I've gone with a free function.
I also needed to change get_current_core_target, renaming it to
get_core_target, and taking an inferior as an argument. Existing call
sites are updated to pass 'current_inferior ()', but
get_inferior_core_bfd passes something that might not be the current
inferior.
There should be no user visible changes after this commit.
Approved-By: Tom Tromey <tom@tromey.com>
2025-10-08 11:18:07 +01:00
|
|
|
|
if (get_inferior_core_bfd (inf) == nullptr)
|
2026-05-15 21:38:12 +02:00
|
|
|
|
return py_none ();
|
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-08-21 09:45:18 +01:00
|
|
|
|
|
|
|
|
|
|
PyObject *result = (PyObject *) cfpy_inferior_corefile_data_key.get (inf);
|
2026-02-26 16:08:27 +00:00
|
|
|
|
if (result != nullptr)
|
|
|
|
|
|
return gdbpy_ref<>::new_reference (result);
|
|
|
|
|
|
|
|
|
|
|
|
gdbpy_ref<corefile_object> object
|
|
|
|
|
|
(PyObject_New (corefile_object, &corefile_object_type));
|
|
|
|
|
|
if (object == nullptr)
|
|
|
|
|
|
return nullptr;
|
|
|
|
|
|
|
|
|
|
|
|
/* Ensure the 'inferior' field is set to NULL. If the PyDict_New call fails
|
|
|
|
|
|
then the gdb.Corefile will be discarded and cfpy_dealloc will be called,
|
|
|
|
|
|
which requires that the 'inferior' be set to NULL. */
|
|
|
|
|
|
object->inferior = nullptr;
|
|
|
|
|
|
object->mapped_files = nullptr;
|
2026-02-27 10:30:36 +00:00
|
|
|
|
if (!object->allocate_dict ())
|
2026-02-26 16:08:27 +00:00
|
|
|
|
return nullptr;
|
|
|
|
|
|
|
|
|
|
|
|
/* Now that the gdb.Corefile has been successfully initialised and we know
|
|
|
|
|
|
that it is going to be passed back to the user, move it out of the invalid
|
|
|
|
|
|
state by setting the 'inferior' field to a non NULL value. */
|
|
|
|
|
|
object->inferior = inf;
|
|
|
|
|
|
|
|
|
|
|
|
/* PyObject_New initializes the new object with a refcount of 1. This counts
|
|
|
|
|
|
for the reference we are keeping in the inferior corefile data. */
|
|
|
|
|
|
cfpy_inferior_corefile_data_key.set (inf, object.get ());
|
|
|
|
|
|
|
|
|
|
|
|
return gdbpy_ref<>::new_reference (object.release ());
|
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-08-21 09:45:18 +01:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* Return true if OBJ is valid. */
|
|
|
|
|
|
|
|
|
|
|
|
static bool
|
|
|
|
|
|
cfpy_corefile_object_is_valid (const corefile_object *obj)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (obj->inferior == nullptr)
|
|
|
|
|
|
return false;
|
|
|
|
|
|
|
gdb: move core file bfd from program_space into core_target
This commit moves the 'gdb_bfd_ref_ptr cbfd' out of program_space and
into core_target, where it is now called m_core_bfd.
I believe this change makes sense as the core_target instance holds
additional information that is parsed from the core file BFD, and so
storing the parsed information separately from the BFD doesn't make
much sense to me.
To minimise the churn in this commit, I have retained the
program_space::core_bfd member function as a temporary hack. This
function forwards the request to the new function
get_inferior_core_bfd. This works fine for now as
program_space::core_bfd is, after this commit, only called on the
current_program_space. If this all seems like a total hack, then it
is, but don't worry too much, the next commit will clean this all up.
I was tempted to make the new function get_inferior_core_bfd, a member
function of the inferior class, inferior::core_bfd. In fact, that
would have been my preferred change. However, the new function needs
visibility of the core_target class, which, right now is private
within the corelow.c file.
This shouldn't be a problem, we could just declare the member function
in inferior.h, and implement the function in corelow.c. But this
would mean the implementation of inferior::core_bfd, would not live in
inferior.c. Previously when I've implemented member functions outside
their natural home (e.g. an inferior function not in inferior.c) I've
received review feedback that this is not desirable. So, for now,
I've gone with a free function.
I also needed to change get_current_core_target, renaming it to
get_core_target, and taking an inferior as an argument. Existing call
sites are updated to pass 'current_inferior ()', but
get_inferior_core_bfd passes something that might not be the current
inferior.
There should be no user visible changes after this commit.
Approved-By: Tom Tromey <tom@tromey.com>
2025-10-08 11:18:07 +01:00
|
|
|
|
return get_inferior_core_bfd (obj->inferior) != nullptr;
|
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-08-21 09:45:18 +01:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* Require that COREFILE_OBJ be a valid core file. A valid core file
|
|
|
|
|
|
object has a valid program space, and the program space has a core file
|
|
|
|
|
|
loaded into it. */
|
|
|
|
|
|
#define CFPY_REQUIRE_VALID(corefile_obj) \
|
|
|
|
|
|
do { \
|
|
|
|
|
|
if (!cfpy_corefile_object_is_valid (corefile_obj)) \
|
|
|
|
|
|
{ \
|
|
|
|
|
|
PyErr_SetString (PyExc_RuntimeError, \
|
|
|
|
|
|
_("Corefile no longer exists.")); \
|
|
|
|
|
|
return nullptr; \
|
|
|
|
|
|
} \
|
|
|
|
|
|
} while (0)
|
|
|
|
|
|
|
|
|
|
|
|
/* Read the gdb.Corefile.filename attribute. */
|
|
|
|
|
|
|
|
|
|
|
|
static PyObject *
|
|
|
|
|
|
cfpy_get_filename (PyObject *self, void *closure)
|
|
|
|
|
|
{
|
|
|
|
|
|
corefile_object *obj = (corefile_object *) self;
|
|
|
|
|
|
|
|
|
|
|
|
CFPY_REQUIRE_VALID (obj);
|
|
|
|
|
|
|
|
|
|
|
|
/* If the program space's core file had been cleared, then this Corefile
|
|
|
|
|
|
object would have been invalidated. */
|
gdb: move core file bfd from program_space into core_target
This commit moves the 'gdb_bfd_ref_ptr cbfd' out of program_space and
into core_target, where it is now called m_core_bfd.
I believe this change makes sense as the core_target instance holds
additional information that is parsed from the core file BFD, and so
storing the parsed information separately from the BFD doesn't make
much sense to me.
To minimise the churn in this commit, I have retained the
program_space::core_bfd member function as a temporary hack. This
function forwards the request to the new function
get_inferior_core_bfd. This works fine for now as
program_space::core_bfd is, after this commit, only called on the
current_program_space. If this all seems like a total hack, then it
is, but don't worry too much, the next commit will clean this all up.
I was tempted to make the new function get_inferior_core_bfd, a member
function of the inferior class, inferior::core_bfd. In fact, that
would have been my preferred change. However, the new function needs
visibility of the core_target class, which, right now is private
within the corelow.c file.
This shouldn't be a problem, we could just declare the member function
in inferior.h, and implement the function in corelow.c. But this
would mean the implementation of inferior::core_bfd, would not live in
inferior.c. Previously when I've implemented member functions outside
their natural home (e.g. an inferior function not in inferior.c) I've
received review feedback that this is not desirable. So, for now,
I've gone with a free function.
I also needed to change get_current_core_target, renaming it to
get_core_target, and taking an inferior as an argument. Existing call
sites are updated to pass 'current_inferior ()', but
get_inferior_core_bfd passes something that might not be the current
inferior.
There should be no user visible changes after this commit.
Approved-By: Tom Tromey <tom@tromey.com>
2025-10-08 11:18:07 +01:00
|
|
|
|
bfd *abfd = get_inferior_core_bfd (obj->inferior);
|
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-08-21 09:45:18 +01:00
|
|
|
|
gdb_assert (abfd != nullptr);
|
|
|
|
|
|
|
|
|
|
|
|
return host_string_to_python_string (bfd_get_filename (abfd)).release ();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* Implementation of gdb.Corefile.is_valid (self) -> Boolean.
|
|
|
|
|
|
Returns True if this core file object is associated with a program space
|
|
|
|
|
|
that still exists, an the program space still has a core file loaded. */
|
|
|
|
|
|
|
|
|
|
|
|
static PyObject *
|
|
|
|
|
|
cfpy_is_valid (PyObject *self, PyObject *args)
|
|
|
|
|
|
{
|
|
|
|
|
|
corefile_object *obj = (corefile_object *) self;
|
|
|
|
|
|
|
|
|
|
|
|
if (!cfpy_corefile_object_is_valid (obj))
|
2026-05-15 21:38:12 +02:00
|
|
|
|
return py_false ().release ();
|
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-08-21 09:45:18 +01:00
|
|
|
|
|
2026-05-15 21:38:12 +02:00
|
|
|
|
return py_true ().release ();
|
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-08-21 09:45:18 +01:00
|
|
|
|
}
|
|
|
|
|
|
|
2025-08-25 16:48:22 +01:00
|
|
|
|
/* Implement gdb.Corefile.mapped_files (). Return a List of
|
|
|
|
|
|
gdb.CorefileMappedFile objects. The list is created the first time
|
|
|
|
|
|
this method is called, and then cached within the gdb.Corefile object,
|
|
|
|
|
|
future calls just return a reference to the same list. */
|
|
|
|
|
|
|
|
|
|
|
|
static PyObject *
|
|
|
|
|
|
cfpy_mapped_files (PyObject *self, PyObject *args)
|
|
|
|
|
|
{
|
|
|
|
|
|
corefile_object *obj = (corefile_object *) self;
|
|
|
|
|
|
|
|
|
|
|
|
CFPY_REQUIRE_VALID (obj);
|
|
|
|
|
|
|
|
|
|
|
|
/* If we have already created the List then just return another reference
|
|
|
|
|
|
to the existing list. */
|
|
|
|
|
|
if (obj->mapped_files != nullptr)
|
|
|
|
|
|
{
|
|
|
|
|
|
Py_INCREF (obj->mapped_files);
|
|
|
|
|
|
return obj->mapped_files;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* Get all the mapping data from GDB. */
|
|
|
|
|
|
std::vector<core_mapped_file> mapped_files;
|
|
|
|
|
|
try
|
|
|
|
|
|
{
|
|
|
|
|
|
mapped_files
|
|
|
|
|
|
= gdb_read_core_file_mappings (obj->inferior->arch (),
|
gdb: move core file bfd from program_space into core_target
This commit moves the 'gdb_bfd_ref_ptr cbfd' out of program_space and
into core_target, where it is now called m_core_bfd.
I believe this change makes sense as the core_target instance holds
additional information that is parsed from the core file BFD, and so
storing the parsed information separately from the BFD doesn't make
much sense to me.
To minimise the churn in this commit, I have retained the
program_space::core_bfd member function as a temporary hack. This
function forwards the request to the new function
get_inferior_core_bfd. This works fine for now as
program_space::core_bfd is, after this commit, only called on the
current_program_space. If this all seems like a total hack, then it
is, but don't worry too much, the next commit will clean this all up.
I was tempted to make the new function get_inferior_core_bfd, a member
function of the inferior class, inferior::core_bfd. In fact, that
would have been my preferred change. However, the new function needs
visibility of the core_target class, which, right now is private
within the corelow.c file.
This shouldn't be a problem, we could just declare the member function
in inferior.h, and implement the function in corelow.c. But this
would mean the implementation of inferior::core_bfd, would not live in
inferior.c. Previously when I've implemented member functions outside
their natural home (e.g. an inferior function not in inferior.c) I've
received review feedback that this is not desirable. So, for now,
I've gone with a free function.
I also needed to change get_current_core_target, renaming it to
get_core_target, and taking an inferior as an argument. Existing call
sites are updated to pass 'current_inferior ()', but
get_inferior_core_bfd passes something that might not be the current
inferior.
There should be no user visible changes after this commit.
Approved-By: Tom Tromey <tom@tromey.com>
2025-10-08 11:18:07 +01:00
|
|
|
|
get_inferior_core_bfd (obj->inferior));
|
2025-08-25 16:48:22 +01:00
|
|
|
|
}
|
|
|
|
|
|
catch (const gdb_exception &except)
|
|
|
|
|
|
{
|
|
|
|
|
|
return gdbpy_handle_gdb_exception (nullptr, except);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* Create a new list to hold the results. */
|
|
|
|
|
|
gdbpy_ref<> tuple (PyTuple_New (mapped_files.size ()));
|
|
|
|
|
|
if (tuple == nullptr)
|
|
|
|
|
|
return nullptr;
|
|
|
|
|
|
|
|
|
|
|
|
/* Create each gdb.CorefileMappedFile object. */
|
|
|
|
|
|
Py_ssize_t tuple_idx = 0;
|
|
|
|
|
|
for (const core_mapped_file &file : mapped_files)
|
|
|
|
|
|
{
|
|
|
|
|
|
/* The filename 'str' object. */
|
|
|
|
|
|
gdbpy_ref<> filename
|
|
|
|
|
|
= host_string_to_python_string (file.filename.c_str ());
|
|
|
|
|
|
if (filename == nullptr)
|
|
|
|
|
|
return nullptr;
|
|
|
|
|
|
|
|
|
|
|
|
/* The build-id object. Either a 'str' or 'None'. */
|
|
|
|
|
|
gdbpy_ref<> build_id;
|
|
|
|
|
|
if (file.build_id != nullptr)
|
|
|
|
|
|
{
|
|
|
|
|
|
std::string hex_form = bin2hex (file.build_id->data,
|
|
|
|
|
|
file.build_id->size);
|
|
|
|
|
|
|
|
|
|
|
|
build_id
|
|
|
|
|
|
= host_string_to_python_string (hex_form.c_str ());
|
|
|
|
|
|
if (build_id == nullptr)
|
|
|
|
|
|
return nullptr;
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
2026-05-15 21:38:12 +02:00
|
|
|
|
build_id = py_none ();
|
2025-08-25 16:48:22 +01:00
|
|
|
|
|
|
|
|
|
|
/* List to hold all the gdb.CorefileMappedFileRegion objects. */
|
|
|
|
|
|
gdbpy_ref<> regions (PyTuple_New (file.regions.size ()));
|
|
|
|
|
|
if (regions == nullptr)
|
|
|
|
|
|
return nullptr;
|
|
|
|
|
|
|
|
|
|
|
|
/* Create all the gdb.CorefileMappedFileRegion objects. */
|
|
|
|
|
|
Py_ssize_t regions_idx = 0;
|
|
|
|
|
|
for (const core_mapped_file::region &r : file.regions)
|
|
|
|
|
|
{
|
|
|
|
|
|
/* Actually create the object. */
|
|
|
|
|
|
gdbpy_ref<corefile_mapped_file_region_object> region_obj
|
|
|
|
|
|
(PyObject_New (corefile_mapped_file_region_object,
|
|
|
|
|
|
&corefile_mapped_file_region_object_type));
|
|
|
|
|
|
if (region_obj == nullptr)
|
|
|
|
|
|
return nullptr;
|
|
|
|
|
|
|
|
|
|
|
|
/* Initialise the object. */
|
|
|
|
|
|
region_obj->start = r.start;
|
|
|
|
|
|
region_obj->end = r.end;
|
|
|
|
|
|
region_obj->file_offset = r.file_ofs;
|
|
|
|
|
|
|
|
|
|
|
|
/* Add to the gdb.CorefileMappedFileRegion list. */
|
|
|
|
|
|
if (PyTuple_SetItem (regions.get (), regions_idx++,
|
|
|
|
|
|
(PyObject *) region_obj.release ()) < 0)
|
|
|
|
|
|
return nullptr;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* Actually create the gdb.CorefileMappedFile object. */
|
|
|
|
|
|
gdbpy_ref<corefile_mapped_file_object> entry
|
|
|
|
|
|
(PyObject_New (corefile_mapped_file_object,
|
|
|
|
|
|
&corefile_mapped_file_object_type));
|
|
|
|
|
|
if (entry == nullptr)
|
|
|
|
|
|
return nullptr;
|
|
|
|
|
|
|
|
|
|
|
|
/* Initialise the object. */
|
|
|
|
|
|
entry->filename = filename.release ();
|
|
|
|
|
|
entry->build_id = build_id.release ();
|
|
|
|
|
|
entry->regions = regions.release ();
|
|
|
|
|
|
entry->is_main_exec_p = file.is_main_exec;
|
|
|
|
|
|
|
|
|
|
|
|
/* Add to the gdb.CorefileMappedFile list. */
|
|
|
|
|
|
if (PyTuple_SetItem (tuple.get (), tuple_idx++,
|
|
|
|
|
|
(PyObject *) entry.release ()) < 0)
|
|
|
|
|
|
return nullptr;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* No errors. Move the reference currently in LIST into the Corefile
|
|
|
|
|
|
object itself. Then create a new reference and hand this back to the
|
|
|
|
|
|
user. */
|
|
|
|
|
|
obj->mapped_files = tuple.release ();
|
|
|
|
|
|
Py_INCREF (obj->mapped_files);
|
|
|
|
|
|
return obj->mapped_files;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-03-27 09:52:55 +00:00
|
|
|
|
/* Emit a CorefileChangedEvent event, INF is the inferior in which the core
|
|
|
|
|
|
file changed. Return 0 on success, or a negative value on error. */
|
|
|
|
|
|
|
|
|
|
|
|
static int
|
|
|
|
|
|
emit_corefile_changed_event (inferior *inf)
|
|
|
|
|
|
{
|
|
|
|
|
|
/* If there are no listeners then we are done. */
|
|
|
|
|
|
if (evregpy_no_listeners_p (gdb_py_events.corefile_changed))
|
|
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
|
|
|
|
gdbpy_ref<> event_obj
|
|
|
|
|
|
= create_event_object (&corefile_changed_event_object_type);
|
|
|
|
|
|
if (event_obj == nullptr)
|
|
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
|
|
|
|
gdbpy_ref<inferior_object> inf_obj = inferior_to_inferior_object (inf);
|
|
|
|
|
|
if (inf_obj == nullptr
|
|
|
|
|
|
|| evpy_add_attribute (event_obj.get (), "inferior",
|
|
|
|
|
|
inf_obj.get ()) < 0)
|
|
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
|
|
|
|
return evpy_emit_event (event_obj.get (), gdb_py_events.corefile_changed);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* Callback from gdb::observers::core_file_changed. The core file for
|
|
|
|
|
|
INF has been changed. */
|
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-08-21 09:45:18 +01:00
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
|
cfpy_corefile_changed (inferior *inf)
|
|
|
|
|
|
{
|
2026-03-27 09:52:55 +00:00
|
|
|
|
/* It's safe to do this even if Python is not initialized, but there
|
|
|
|
|
|
should be nothing to clear in that case. */
|
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-08-21 09:45:18 +01:00
|
|
|
|
cfpy_inferior_corefile_data_key.clear (inf);
|
2026-03-27 09:52:55 +00:00
|
|
|
|
|
|
|
|
|
|
if (!gdb_python_initialized)
|
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
|
|
gdbpy_enter enter_py;
|
|
|
|
|
|
|
|
|
|
|
|
if (emit_corefile_changed_event (inf) < 0)
|
|
|
|
|
|
gdbpy_print_stack ();
|
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-08-21 09:45:18 +01:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* Called when a gdb.Corefile is destroyed. */
|
|
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
|
cfpy_dealloc (PyObject *obj)
|
|
|
|
|
|
{
|
|
|
|
|
|
corefile_object *corefile = (corefile_object *) obj;
|
|
|
|
|
|
|
|
|
|
|
|
/* Every gdb.Corefile is cached in an inferior's registry. The only way
|
|
|
|
|
|
for a gdb.Corefile to be deallocated is to remove the object reference
|
|
|
|
|
|
from the registry (and dec its ref count), but before we do that, we
|
|
|
|
|
|
set the object's inferior pointer to NULL. */
|
|
|
|
|
|
gdb_assert (corefile->inferior == nullptr);
|
|
|
|
|
|
|
|
|
|
|
|
Py_XDECREF (corefile->dict);
|
2025-08-25 16:48:22 +01:00
|
|
|
|
Py_XDECREF (corefile->mapped_files);
|
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-08-21 09:45:18 +01:00
|
|
|
|
|
|
|
|
|
|
Py_TYPE (obj)->tp_free (obj);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* __repr__ implementation for gdb.Corefile. */
|
|
|
|
|
|
|
|
|
|
|
|
static PyObject *
|
|
|
|
|
|
cfpy_repr (PyObject *self)
|
|
|
|
|
|
{
|
|
|
|
|
|
corefile_object *obj = (corefile_object *) self;
|
|
|
|
|
|
|
|
|
|
|
|
if (!cfpy_corefile_object_is_valid (obj))
|
|
|
|
|
|
return gdb_py_invalid_object_repr (self);
|
|
|
|
|
|
|
gdb: move core file bfd from program_space into core_target
This commit moves the 'gdb_bfd_ref_ptr cbfd' out of program_space and
into core_target, where it is now called m_core_bfd.
I believe this change makes sense as the core_target instance holds
additional information that is parsed from the core file BFD, and so
storing the parsed information separately from the BFD doesn't make
much sense to me.
To minimise the churn in this commit, I have retained the
program_space::core_bfd member function as a temporary hack. This
function forwards the request to the new function
get_inferior_core_bfd. This works fine for now as
program_space::core_bfd is, after this commit, only called on the
current_program_space. If this all seems like a total hack, then it
is, but don't worry too much, the next commit will clean this all up.
I was tempted to make the new function get_inferior_core_bfd, a member
function of the inferior class, inferior::core_bfd. In fact, that
would have been my preferred change. However, the new function needs
visibility of the core_target class, which, right now is private
within the corelow.c file.
This shouldn't be a problem, we could just declare the member function
in inferior.h, and implement the function in corelow.c. But this
would mean the implementation of inferior::core_bfd, would not live in
inferior.c. Previously when I've implemented member functions outside
their natural home (e.g. an inferior function not in inferior.c) I've
received review feedback that this is not desirable. So, for now,
I've gone with a free function.
I also needed to change get_current_core_target, renaming it to
get_core_target, and taking an inferior as an argument. Existing call
sites are updated to pass 'current_inferior ()', but
get_inferior_core_bfd passes something that might not be the current
inferior.
There should be no user visible changes after this commit.
Approved-By: Tom Tromey <tom@tromey.com>
2025-10-08 11:18:07 +01:00
|
|
|
|
bfd *core_bfd = get_inferior_core_bfd (obj->inferior);
|
|
|
|
|
|
gdb_assert (core_bfd != nullptr);
|
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-08-21 09:45:18 +01:00
|
|
|
|
return PyUnicode_FromFormat ("<%s inferior=%d filename='%s'>",
|
2026-05-26 11:46:29 +01:00
|
|
|
|
gdbpy_py_obj_tp_name (self).c_str (),
|
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-08-21 09:45:18 +01:00
|
|
|
|
obj->inferior->num,
|
gdb: move core file bfd from program_space into core_target
This commit moves the 'gdb_bfd_ref_ptr cbfd' out of program_space and
into core_target, where it is now called m_core_bfd.
I believe this change makes sense as the core_target instance holds
additional information that is parsed from the core file BFD, and so
storing the parsed information separately from the BFD doesn't make
much sense to me.
To minimise the churn in this commit, I have retained the
program_space::core_bfd member function as a temporary hack. This
function forwards the request to the new function
get_inferior_core_bfd. This works fine for now as
program_space::core_bfd is, after this commit, only called on the
current_program_space. If this all seems like a total hack, then it
is, but don't worry too much, the next commit will clean this all up.
I was tempted to make the new function get_inferior_core_bfd, a member
function of the inferior class, inferior::core_bfd. In fact, that
would have been my preferred change. However, the new function needs
visibility of the core_target class, which, right now is private
within the corelow.c file.
This shouldn't be a problem, we could just declare the member function
in inferior.h, and implement the function in corelow.c. But this
would mean the implementation of inferior::core_bfd, would not live in
inferior.c. Previously when I've implemented member functions outside
their natural home (e.g. an inferior function not in inferior.c) I've
received review feedback that this is not desirable. So, for now,
I've gone with a free function.
I also needed to change get_current_core_target, renaming it to
get_core_target, and taking an inferior as an argument. Existing call
sites are updated to pass 'current_inferior ()', but
get_inferior_core_bfd passes something that might not be the current
inferior.
There should be no user visible changes after this commit.
Approved-By: Tom Tromey <tom@tromey.com>
2025-10-08 11:18:07 +01:00
|
|
|
|
bfd_get_filename (core_bfd));
|
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-08-21 09:45:18 +01:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2025-08-25 16:48:22 +01:00
|
|
|
|
/* Called when a gdb.CorefileMappedFile is destroyed. */
|
|
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
|
cfmfpy_dealloc (PyObject *obj)
|
|
|
|
|
|
{
|
|
|
|
|
|
corefile_mapped_file_object *mapped_file
|
|
|
|
|
|
= (corefile_mapped_file_object *) obj;
|
|
|
|
|
|
|
|
|
|
|
|
Py_XDECREF (mapped_file->filename);
|
|
|
|
|
|
Py_XDECREF (mapped_file->build_id);
|
|
|
|
|
|
Py_XDECREF (mapped_file->regions);
|
|
|
|
|
|
|
|
|
|
|
|
Py_TYPE (obj)->tp_free (obj);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* Read the gdb.CorefileMappedFile.filename attribute. */
|
|
|
|
|
|
|
|
|
|
|
|
static PyObject *
|
|
|
|
|
|
cfmfpy_get_filename (PyObject *self, void *closure)
|
|
|
|
|
|
{
|
|
|
|
|
|
corefile_mapped_file_object *obj
|
|
|
|
|
|
= (corefile_mapped_file_object *) self;
|
|
|
|
|
|
|
|
|
|
|
|
gdb_assert (obj->filename != nullptr);
|
|
|
|
|
|
|
|
|
|
|
|
Py_INCREF (obj->filename);
|
|
|
|
|
|
return obj->filename;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* Read the gdb.CorefileMappedFile.build_id attribute. */
|
|
|
|
|
|
|
|
|
|
|
|
static PyObject *
|
|
|
|
|
|
cfmfpy_get_build_id (PyObject *self, void *closure)
|
|
|
|
|
|
{
|
|
|
|
|
|
corefile_mapped_file_object *obj
|
|
|
|
|
|
= (corefile_mapped_file_object *) self;
|
|
|
|
|
|
|
|
|
|
|
|
gdb_assert (obj->build_id != nullptr);
|
|
|
|
|
|
|
|
|
|
|
|
Py_INCREF (obj->build_id);
|
|
|
|
|
|
return obj->build_id;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* Read the gdb.CorefileMappedFile.regions attribute. */
|
|
|
|
|
|
|
|
|
|
|
|
static PyObject *
|
|
|
|
|
|
cfmfpy_get_regions (PyObject *self, void *closure)
|
|
|
|
|
|
{
|
|
|
|
|
|
corefile_mapped_file_object *obj
|
|
|
|
|
|
= (corefile_mapped_file_object *) self;
|
|
|
|
|
|
|
|
|
|
|
|
gdb_assert (obj->regions != nullptr);
|
|
|
|
|
|
|
|
|
|
|
|
Py_INCREF (obj->regions);
|
|
|
|
|
|
return obj->regions;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* Read the gdb.CorefileMappedFile.is_main_executable attribute. */
|
|
|
|
|
|
|
|
|
|
|
|
static PyObject *
|
|
|
|
|
|
cfmf_is_main_exec (PyObject *self, void *closure)
|
|
|
|
|
|
{
|
|
|
|
|
|
corefile_mapped_file_object *obj
|
|
|
|
|
|
= (corefile_mapped_file_object *) self;
|
|
|
|
|
|
|
|
|
|
|
|
if (obj->is_main_exec_p)
|
2026-05-15 21:38:12 +02:00
|
|
|
|
return py_true ().release ();
|
2025-08-25 16:48:22 +01:00
|
|
|
|
else
|
2026-05-15 21:38:12 +02:00
|
|
|
|
return py_false ().release ();
|
2025-08-25 16:48:22 +01:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* Read the gdb.CorefileMappedFileRegion.start attribute. */
|
|
|
|
|
|
|
|
|
|
|
|
static PyObject *
|
|
|
|
|
|
cfmfrpy_get_start (PyObject *self, void *closure)
|
|
|
|
|
|
{
|
|
|
|
|
|
corefile_mapped_file_region_object *obj
|
|
|
|
|
|
= (corefile_mapped_file_region_object *) self;
|
|
|
|
|
|
|
|
|
|
|
|
return gdb_py_object_from_ulongest (obj->start).release ();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* Read the gdb.CorefileMappedFileRegion.end attribute. */
|
|
|
|
|
|
|
|
|
|
|
|
static PyObject *
|
|
|
|
|
|
cfmfrpy_get_end (PyObject *self, void *closure)
|
|
|
|
|
|
{
|
|
|
|
|
|
corefile_mapped_file_region_object *obj
|
|
|
|
|
|
= (corefile_mapped_file_region_object *) self;
|
|
|
|
|
|
|
|
|
|
|
|
return gdb_py_object_from_ulongest (obj->end).release ();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* Read the gdb.CorefileMappedFileRegion.file_offset attribute. */
|
|
|
|
|
|
|
|
|
|
|
|
static PyObject *
|
|
|
|
|
|
cfmfrpy_get_file_offset (PyObject *self, void *closure)
|
|
|
|
|
|
{
|
|
|
|
|
|
corefile_mapped_file_region_object *obj
|
|
|
|
|
|
= (corefile_mapped_file_region_object *) self;
|
|
|
|
|
|
|
|
|
|
|
|
return gdb_py_object_from_ulongest (obj->file_offset).release ();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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-08-21 09:45:18 +01:00
|
|
|
|
static int
|
|
|
|
|
|
gdbpy_initialize_corefile ()
|
|
|
|
|
|
{
|
|
|
|
|
|
gdb::observers::core_file_changed.attach (cfpy_corefile_changed,
|
|
|
|
|
|
"py-corefile");
|
|
|
|
|
|
|
|
|
|
|
|
if (gdbpy_type_ready (&corefile_object_type) < 0)
|
|
|
|
|
|
return -1;
|
|
|
|
|
|
|
2025-08-25 16:48:22 +01:00
|
|
|
|
if (gdbpy_type_ready (&corefile_mapped_file_object_type) < 0)
|
|
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
|
|
|
|
if (gdbpy_type_ready (&corefile_mapped_file_region_object_type) < 0)
|
|
|
|
|
|
return -1;
|
|
|
|
|
|
|
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-08-21 09:45:18 +01:00
|
|
|
|
return 0;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
GDBPY_INITIALIZE_FILE (gdbpy_initialize_corefile);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static gdb_PyGetSetDef corefile_getset[] =
|
|
|
|
|
|
{
|
2026-02-27 14:13:26 +00:00
|
|
|
|
gdbpy_dict_wrapper_cfg_dict_getter ("corefile"),
|
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-08-21 09:45:18 +01:00
|
|
|
|
{ "filename", cfpy_get_filename, nullptr,
|
|
|
|
|
|
"The filename of a valid Corefile object.", nullptr },
|
|
|
|
|
|
{ nullptr }
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
static PyMethodDef corefile_object_methods[] =
|
|
|
|
|
|
{
|
|
|
|
|
|
{ "is_valid", cfpy_is_valid, METH_NOARGS,
|
|
|
|
|
|
"is_valid () -> Boolean.\n\
|
|
|
|
|
|
Return true if this Corefile is valid, false if not." },
|
2025-08-25 16:48:22 +01:00
|
|
|
|
{ "mapped_files", cfpy_mapped_files, METH_NOARGS,
|
|
|
|
|
|
"mapped_files () -> List of mapping tuples.\n\
|
|
|
|
|
|
Return a list of tuples. Each tuple represents a mapping from the\
|
|
|
|
|
|
core file." },
|
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-08-21 09:45:18 +01:00
|
|
|
|
{ nullptr }
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
PyTypeObject corefile_object_type =
|
|
|
|
|
|
{
|
|
|
|
|
|
PyVarObject_HEAD_INIT (nullptr, 0)
|
|
|
|
|
|
"gdb.Corefile", /*tp_name*/
|
|
|
|
|
|
sizeof (corefile_object), /*tp_basicsize*/
|
|
|
|
|
|
0, /*tp_itemsize*/
|
|
|
|
|
|
cfpy_dealloc, /*tp_dealloc*/
|
|
|
|
|
|
0, /*tp_print*/
|
|
|
|
|
|
0, /*tp_getattr*/
|
|
|
|
|
|
0, /*tp_setattr*/
|
|
|
|
|
|
0, /*tp_compare*/
|
|
|
|
|
|
cfpy_repr, /*tp_repr*/
|
|
|
|
|
|
0, /*tp_as_number*/
|
|
|
|
|
|
0, /*tp_as_sequence*/
|
|
|
|
|
|
0, /*tp_as_mapping*/
|
|
|
|
|
|
0, /*tp_hash */
|
|
|
|
|
|
0, /*tp_call*/
|
|
|
|
|
|
0, /*tp_str*/
|
2026-02-27 14:13:26 +00:00
|
|
|
|
gdbpy_dict_wrapper_getsetattro,
|
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-08-21 09:45:18 +01:00
|
|
|
|
0, /*tp_as_buffer*/
|
|
|
|
|
|
Py_TPFLAGS_DEFAULT, /*tp_flags*/
|
|
|
|
|
|
"GDB corefile object", /* tp_doc */
|
|
|
|
|
|
0, /* tp_traverse */
|
|
|
|
|
|
0, /* tp_clear */
|
|
|
|
|
|
0, /* tp_richcompare */
|
|
|
|
|
|
0, /* tp_weaklistoffset */
|
|
|
|
|
|
0, /* tp_iter */
|
|
|
|
|
|
0, /* tp_iternext */
|
|
|
|
|
|
corefile_object_methods, /* tp_methods */
|
|
|
|
|
|
0, /* tp_members */
|
|
|
|
|
|
corefile_getset, /* tp_getset */
|
|
|
|
|
|
0, /* tp_base */
|
|
|
|
|
|
0, /* tp_dict */
|
|
|
|
|
|
0, /* tp_descr_get */
|
|
|
|
|
|
0, /* tp_descr_set */
|
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>
2025-07-17 18:36:41 +01:00
|
|
|
|
0, /* tp_dictoffset */
|
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-08-21 09:45:18 +01:00
|
|
|
|
0, /* tp_init */
|
|
|
|
|
|
0, /* tp_alloc */
|
|
|
|
|
|
0, /* tp_new */
|
|
|
|
|
|
};
|
2025-08-25 16:48:22 +01:00
|
|
|
|
|
|
|
|
|
|
static gdb_PyGetSetDef corefile_mapped_file_object_getset[] =
|
|
|
|
|
|
{
|
|
|
|
|
|
{ "filename", cfmfpy_get_filename, nullptr,
|
|
|
|
|
|
"The filename of a CorefileMappedFile object.", nullptr },
|
|
|
|
|
|
{ "build_id", cfmfpy_get_build_id, nullptr,
|
|
|
|
|
|
"The build-id of a CorefileMappedFile object or None.", nullptr },
|
|
|
|
|
|
{ "regions", cfmfpy_get_regions, nullptr,
|
|
|
|
|
|
"The list of regions from a CorefileMappedFile object.", nullptr },
|
|
|
|
|
|
{ "is_main_executable", cfmf_is_main_exec, nullptr,
|
|
|
|
|
|
"True for the main executable mapping, otherwise False.", nullptr },
|
|
|
|
|
|
{ nullptr }
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
PyTypeObject corefile_mapped_file_object_type =
|
|
|
|
|
|
{
|
|
|
|
|
|
PyVarObject_HEAD_INIT (NULL, 0)
|
|
|
|
|
|
"gdb.CorefileMappedFile", /*tp_name*/
|
|
|
|
|
|
sizeof (corefile_mapped_file_object), /*tp_basicsize*/
|
|
|
|
|
|
0, /*tp_itemsize*/
|
|
|
|
|
|
cfmfpy_dealloc, /*tp_dealloc*/
|
|
|
|
|
|
0, /*tp_print*/
|
|
|
|
|
|
0, /*tp_getattr*/
|
|
|
|
|
|
0, /*tp_setattr*/
|
|
|
|
|
|
0, /*tp_compare*/
|
|
|
|
|
|
0, /*tp_repr*/
|
|
|
|
|
|
0, /*tp_as_number*/
|
|
|
|
|
|
0, /*tp_as_sequence*/
|
|
|
|
|
|
0, /*tp_as_mapping*/
|
|
|
|
|
|
0, /*tp_hash */
|
|
|
|
|
|
0, /*tp_call*/
|
|
|
|
|
|
0, /*tp_str*/
|
|
|
|
|
|
0, /*tp_getattro*/
|
|
|
|
|
|
0, /*tp_setattro*/
|
|
|
|
|
|
0, /*tp_as_buffer*/
|
|
|
|
|
|
Py_TPFLAGS_DEFAULT, /*tp_flags*/
|
|
|
|
|
|
"GDB corefile mapped file object", /* tp_doc */
|
|
|
|
|
|
0, /* tp_traverse */
|
|
|
|
|
|
0, /* tp_clear */
|
|
|
|
|
|
0, /* tp_richcompare */
|
|
|
|
|
|
0, /* tp_weaklistoffset */
|
|
|
|
|
|
0, /* tp_iter */
|
|
|
|
|
|
0, /* tp_iternext */
|
|
|
|
|
|
0, /* tp_methods */
|
|
|
|
|
|
0, /* tp_members */
|
|
|
|
|
|
corefile_mapped_file_object_getset, /* tp_getset */
|
|
|
|
|
|
0, /* tp_base */
|
|
|
|
|
|
0, /* tp_dict */
|
|
|
|
|
|
0, /* tp_descr_get */
|
|
|
|
|
|
0, /* tp_descr_set */
|
|
|
|
|
|
0, /* tp_dictoffset */
|
|
|
|
|
|
0, /* tp_init */
|
|
|
|
|
|
0, /* tp_alloc */
|
|
|
|
|
|
0, /* tp_new */
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
static gdb_PyGetSetDef corefile_mapped_file_region_object_getset[] =
|
|
|
|
|
|
{
|
|
|
|
|
|
{ "start", cfmfrpy_get_start, nullptr,
|
|
|
|
|
|
"The start address of a CorefileMappedFileRegion object.", nullptr },
|
|
|
|
|
|
{ "end", cfmfrpy_get_end, nullptr,
|
|
|
|
|
|
"The end address of a CorefileMappedFileRegion object.", nullptr },
|
|
|
|
|
|
{ "file_offset", cfmfrpy_get_file_offset, nullptr,
|
|
|
|
|
|
"The file offset of a CorefileMappedFileRegion object.", nullptr },
|
|
|
|
|
|
{ nullptr }
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
PyTypeObject corefile_mapped_file_region_object_type =
|
|
|
|
|
|
{
|
|
|
|
|
|
PyVarObject_HEAD_INIT (NULL, 0)
|
|
|
|
|
|
"gdb.CorefileMappedFileRegion", /*tp_name*/
|
|
|
|
|
|
sizeof (corefile_mapped_file_region_object), /*tp_basicsize*/
|
|
|
|
|
|
0, /*tp_itemsize*/
|
|
|
|
|
|
0, /*tp_dealloc*/
|
|
|
|
|
|
0, /*tp_print*/
|
|
|
|
|
|
0, /*tp_getattr*/
|
|
|
|
|
|
0, /*tp_setattr*/
|
|
|
|
|
|
0, /*tp_compare*/
|
|
|
|
|
|
0, /*tp_repr*/
|
|
|
|
|
|
0, /*tp_as_number*/
|
|
|
|
|
|
0, /*tp_as_sequence*/
|
|
|
|
|
|
0, /*tp_as_mapping*/
|
|
|
|
|
|
0, /*tp_hash */
|
|
|
|
|
|
0, /*tp_call*/
|
|
|
|
|
|
0, /*tp_str*/
|
|
|
|
|
|
0, /*tp_getattro*/
|
|
|
|
|
|
0, /*tp_setattro*/
|
|
|
|
|
|
0, /*tp_as_buffer*/
|
|
|
|
|
|
Py_TPFLAGS_DEFAULT, /*tp_flags*/
|
|
|
|
|
|
"GDB corefile mapped file region object", /* tp_doc */
|
|
|
|
|
|
0, /* tp_traverse */
|
|
|
|
|
|
0, /* tp_clear */
|
|
|
|
|
|
0, /* tp_richcompare */
|
|
|
|
|
|
0, /* tp_weaklistoffset */
|
|
|
|
|
|
0, /* tp_iter */
|
|
|
|
|
|
0, /* tp_iternext */
|
|
|
|
|
|
0, /* tp_methods */
|
|
|
|
|
|
0, /* tp_members */
|
|
|
|
|
|
corefile_mapped_file_region_object_getset, /* tp_getset */
|
|
|
|
|
|
0, /* tp_base */
|
|
|
|
|
|
0, /* tp_dict */
|
|
|
|
|
|
0, /* tp_descr_get */
|
|
|
|
|
|
0, /* tp_descr_set */
|
|
|
|
|
|
0, /* tp_dictoffset */
|
|
|
|
|
|
0, /* tp_init */
|
|
|
|
|
|
0, /* tp_alloc */
|
|
|
|
|
|
0, /* tp_new */
|
|
|
|
|
|
};
|