The current implementation of gdb_py_tp_name() leaks a reference to the
object returned by PyType_GetFullyQualifiedName() for Python >= 3.13, and
PyType_GetQualName() for Python >= 3.11.
Managing the strong reference on the returned PyObject* with a gdbpy_ref<>
fixes the reference count, but also causes the temporary object to be
deallocated on function exit. As a consequence, the 'const char *' returned
by PyUnicode_AsUTF8AndSize() becomes dangling and can no longer safely be
returned.
The proposed approach consists in changing gdb_py_tp_name() to return a
std::string, and forcing a copy of the 'const char *' value, statically
or dynamically allocated, stored in a temporary or non-temporary PyObject,
depending on the version of Python it was compiled with.
An unfortunate side effect of this fix is that every call sites where the
tp_name is printed, must now use `.c_str()' because PyErr_Format()
and its siblings cannot handle std::string.
Approved-By: Andrew Burgess <aburgess@redhat.com>
Result of:
...
$ sed -i 's/Py_RETURN_NONE/return py_none ().release ()/' gdb/python/*.{c,h}
...
with the changes in py_none reverted.
Likewise for Py_RETURN_TRUE,Py_RETURN_FALSE and Py_RETURN_NOTIMPLEMENTED.
Approved-By: Tom Tromey <tom@tromey.com>
Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=34145
Py_TYPE (self)->tp_name is the traditional idiomatic way to get a Python
type's fully qualified name. However, in the context of the Python
limited API, PyTypeObject is opaque, so the 'tp_name' attribute is no
longer accessible. Additionally, retrieving the type of a Python object
requires Py_TYPE, which is only available as part of the stable API
starting with Python 3.14.
This patch increases minimal Python limited API version from 3.11 to 3.14.
It also introduces two new helpers to retrieve a type's fully qualified
name: gdb_py_tp_name() and gdbpy_py_obj_tp_name(), which extract the fully
qualified name from a PyTypeObject and a PyObject, respectively. Ifdefery
allows these wrappers to select the appropriate API depending on the Python
version and whether the Python limited API is enabled. For any Python
version less than 3.13, gdb_py_tp_name() fallbacks using __qualname__
instead. However, the result may differ slightly in some cases, e.g. the
module name may be missing.
Finally, this patch adapts the existing code to use these wrappers, and
adjusts some test expectations to use the fully qualified name (or
__qualname__ for versions <= 3.13) where it was not previously used.
Note that the corner case where the module name would be missing does not
appear in the testsuite.
Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=23830
Approved-By: Tom Tromey <tom@tromey.com>
While working on Windows non-stop support, I ran into a
very-hard-to-track-down bug.
The problem turned out to be that
infrun.c:proceed_resume_thread_checked resumed an already-executing
thread because the thread was marked as "executing=true,
resumed=false", and that function only skips resuming threads that are
marked resumed=true. The consequence was that GDB corrupted the
registers of the Windows DLL loader threads, eventually leading to a
GDB+inferior deadlock.
Originally, the "resumed" flag was only ever set when infrun decided
is was ready to process a thread's pending wait status. infrun has
since evolved to set the resumed flag when we set a thread's executing
flag too. We are not always consistent throughout in guaranteeing
that a thread is marked resumed=true whenever it is marked
executing=true, though. For instance, no target code that supports
non-stop mode (linux-nat, remote, and windows-nat with this series) is
making sure that new threads are marked resumed=true when they are
added to the thread list. They are only marked as {state=running,
executing=true}, the "resumed" flag is not touched.
Making proceed_resume_thread_checked check thr->executing() in
addition to thr->resumed(), feels like papering over a combination of
states that shouldn't happen nowadays.
OTOH, having to have the target backends mark new threads as
resumed=true just feels like too many different states (three) to set:
add_thread (...);
set_running (...);
set_executing (...);
set_resumed (...);
Yuck. I think we can do better.
We really have too many "state tracking" flags in a thread.
Basically:
- whether a thread is "running/stopped/exited" (from the user's
perspective). This is the thread_info::state field.
- whether a thread is "executing" (infrun asked the target to set the
thread executing). This is thread_info::executing().
- whether a thread is "resumed" (infrun wants the thread to be
resumed, but maybe can't yet because the thread has a pending wait
status). This is thread_info::resumed()
"running", "executing", and "resumed" are almost synonyms, so this can
be highly confusing English-wise too.
For "running" vs "executing", in comments, we tipically need to
explain that "running/stopped/exited" is for the user/frontend
perspective, while "executing true/false" is for gdb's internal run
control.
(Also, "executing or not" can also mean something else in GDB's
codebase -- "target has execution" does not mean that threads are
actually running right now -- it's a test for whether we have a live
process vs a core dump!)
One simplification we can do that avoids this running vs executing
ambiguity is to replace the "executing" field with an "internal_state"
field, similar to the thread_info::state field, and make that new
internal_state field reuse the same enum thread_state type that is
used by thread_info::state. Like:
struct thread_info
{
...
/* Frontend/public/external/user view of the thread state. */
enum thread_state m_state = THREAD_STOPPED;
/* The thread's internal state. When the thread is stopped
internally while handling an internal event, like a software
single-step breakpoint, the internal state will be
THREAD_STOPPED, but the external state will still be
THREAD_RUNNING. */
enum thread_state m_internal_state = THREAD_STOPPED;
};
(Assume we'd add state() and internal_state() getters.)
With that, every check for thr->executing() is replaced with a
'thr->internal_state() == THREAD_RUNNING' check, and the code is
clearer by design. There is no confusion between "running" vs
"executing" any more, because they now mean the exact same thing.
Instead, we say e.g., 'thread has (user) state "running", and internal
state "stopped"'. Or simpler, 'thread is running (from the user's
perspective), but internally stopped'. That is after all what we
would way in comments today already.
That still leaves the 'resumed' flag, though. That's the least
obvious one. Turns out we can get rid of it, and make it a new state
tracked by thread_info::internal_state. That is, we make
internal_state have its own enumeration type (decoupled from
thread_info::state's type), and convert the resumed true/false flag to
a new enumerator of this new enumeration. Like so:
enum thread_int_state
{
THREAD_INT_STOPPED,
THREAD_INT_RUNNING,
+ THREAD_INT_RESUMED_PENDING_STATUS,
THREAD_INT_EXITED,
};
That is what this patch does. So in summary, we go from:
thread_info::state {THREAD_STOPPED, THREAD_RUNNING, THREAD_EXITED}
thread_info::executing {false, true}
thread_info::resumed {false, true}
to:
thread_info::state {THREAD_STOPPED, THREAD_RUNNING, THREAD_EXITED}
thread_info::internal_state {THREAD_INT_STOPPED, THREAD_INT_RUNNING,
THREAD_INT_RESUMED_PENDING_STATUS,
THREAD_INT_EXITED}
The patch adds getters/setters for both (user) state and
internal_state, and adds assertions around state transitions, ensuring
that internal_state doesn't get out of sync with
thread::have_pending_wait_status().
The code that adds/removes threads from the proc_target's
resumed_with_pending_wait_status list is all centralized within
thread_info::set_internal_state, when we switch to/from the
resumed-pending-status state. With the assertions in place, it should
be impossible to end up with a THREAD_INT_RUNNING thread with a
pending status.
The thread.c:set_running, thread.c:set_executing, thread.c:set_resumed
global functions are all gone, replaced with new thread.c:set_state
and thread.c:set_internal_state functions.
Tested on x86_64-linux-gnu, native and gdbserver.
Change-Id: I4f5097d68f4694d44e1ae23fea3e9bce45fb078c
commit-id:42ba97d4
Python extension objects that support __dict__ must inherit from
gdbpy_dict_wrapper, a wrapper class that stores the PyObject
corresponding to the __dict__ attribute. Because this dictionary
is not managed directly by Python, each extension objects must
provide appropriate accessors so that attributes stored in __dict__
are looked up correctly.
Currently, management of this dictionary is not centralized, and
each Python extension object implements its own logic to create,
access, and destroy it.
A previous patch centralized the creation logic; this patch focuses
on centralizing the access to the dictionary. It introduces two new
macros:
- gdbpy_dict_wrapper_cfg_dict_getter, which defines a getter for
__dict__.
- gdbpy_dict_wrapper_getsetattro, which sets tp_getattro and
tp_setattro in PyTypeObject to gdb_py_generic_getattro and
gdb_py_generic_setattro, respectively. These helpers already
centralizes attribute access for Python extension objects having
a __dict__.
Note: this macro will eventually be removed once Python extension
types are migrated to heap-allocated types.
Approved-By: Tom Tromey <tom@tromey.com>
Python extension objects that support __dict__ must inherit from
gdbpy_dict_wrapper, a wrapper class that stores the PyObject
corresponding to the __dict__ attribute.
Currently, management of this dictionary is not centralized, and
each Python extension object implements its own logic to create,
access, and destroy it.
This patch focuses on the allocation of the dictionary, introduces
a new method, gdbpy_dict_wrapper::allocate_dict(), and
adapts the existing code to use this method.
Approved-By: Tom Tromey <tom@tromey.com>
* PyTuple_GET_ITEM -> PyTuple_GetItem
* PyTuple_SET_ITEM -> PyTuple_SetItem
* PyTuple_GET_SIZE -> PyTuple_Size
Unlike PyTuple_SET_ITEM(), PyTuple_SetItem() returns an integer: 0 on
success and -1 on error (e.g. IndexError). The existing code must therefore
be updated to handle this new behaviour.
Since processing now stops when PyTuple_SetItem() returns an error, some
resources (such as newly allocated tuples) must be properly deallocated in
error paths. To address this, this patch replaces the use of raw 'PyObject *'
pointers with gdbpy_ref<>, a reference-counted wrapper around 'PyObject *',
which automatically decrements the reference count on early exit.
Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=23830
Approved-By: Tom Tromey <tom@tromey.com>
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>
This updates the copyright headers to include 2026. I did this by
running gdb/copyright.py and then manually modifying a few files as
noted by the script.
The GCC plugin that implements the Python API checker does not appear
to really be maintained. And, as far as I know, it never really
worked for C++ code anyway. Considering those factors, and that no
one has tried to run it in years, I think it's time to remove the
macros from the gdb source.
Approved-By: Simon Marchi <simon.marchi@efficios.com>
Update gdbpy_create_ptid_object (python/py-infthread.c) to return a
gdbpy_ref<> rather than a 'PyObject *'. This reduces the chances that
a caller will leak an object, though no such memory leaks are fixed in
this commit, this is just a code improvement patch.
There should be no user visible changes after this commit.
Approved-By: Simon Marchi <simon.marchi@efficios.com>
I noticed a possible memory leak in gdbpy_create_ptid_object, in
py-infthread.c. We create a Tuple, and hold the reference in a
'PyObject*' local.
If we then fail to create any of the tuple contents we perform an
early exit, returning nullptr, this will leak the Tuple object.
Currently, we create the Tuple as the first action in the function,
but we don't really need the tuple until the end of the function.
In this commit I have:
1. Moved creation of the Tuple until the end of the function, just
before we need it.
2. Stored the Tuple reference in a gdbpy_ref<>. This is not
strictly needed any more, but is (I think) good practice as
future changes to the function will not need to worry about
releasing the Tuple object.
3. Taken the opportunity to replace a NULL with nullptr in this
function.
4. Inlined the local variable declarations to the point of first
use.
There should be no user visible changes after this commit.
No tests as I have no idea how to make gdb_py_object_from_longest (and
friends) fail, and so trigger the memory leak. I suspect we'd never
actually see this leak in the real world, but it doesn't hurt to clean
these things up.
Approved-By: Simon Marchi <simon.marchi@efficios.com>
This updates the copyright headers to include 2025. I did this by
running gdb/copyright.py and then manually modifying a few files as
noted by the script.
Approved-By: Eli Zaretskii <eliz@gnu.org>
Result of:
...
$ search="GDB_PY_HANDLE_EXCEPTION ("
$ replace="return gdbpy_handle_gdb_exception (nullptr, "
$ sed -i \
"s/$search/$replace/" \
gdb/python/*.c
...
Also remove the now unused GDB_PY_HANDLE_EXCEPTION.
No functional changes.
Tested on x86_64-linux.
Approved-By: Tom Tromey <tom@tromey.com>
PR python/32163 points out that various types provided by gdb are not
added to the gdb module, so they aren't available for interactive
inspection. I think this is just an oversight.
This patch fixes the problem by introducing a new helper function that
both readies the type and then adds it to the appropriate module. The
patch also poisons PyType_Ready, the idea being to avoid this bug in
the future.
v2:
* Fixed a bug in original patch in gdb.Architecture registration
* Added regression test for the types mentioned in the bug
Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=32163
Reviewed-By: Alexandra Petlanova Hajkova <ahajkova@redhat.com>
Now that defs.h, server.h and common-defs.h are included via the
`-include` option, it is no longer necessary for source files to include
them. Remove all the inclusions of these files I could find. Update
the generation scripts where relevant.
Change-Id: Ia026cff269c1b7ae7386dd3619bc9bb6a5332837
Approved-By: Pedro Alves <pedro@palves.net>
This removes the embedded 'if' from GDB_PY_HANDLE_EXCEPTION and
GDB_PY_SET_HANDLE_EXCEPTION. I believe this 'if' was necessary with
the old gdb try/catch macros, but it no longer is: these should only
ever be called from a 'catch' block, where it's already known that an
exception was thrown.
Simon pointed out, though, that in a few spots, these were in facts
called outside of 'catch' blocks. This patch cleans up these spots.
I also found one spot where a redundant 'return nullptr' could be
removed.
This commit is the result of the following actions:
- Running gdb/copyright.py to update all of the copyright headers to
include 2024,
- Manually updating a few files the copyright.py script told me to
update, these files had copyright headers embedded within the
file,
- Regenerating gdbsupport/Makefile.in to refresh it's copyright
date,
- Using grep to find other files that still mentioned 2023. If
these files were updated last year from 2022 to 2023 then I've
updated them this year to 2024.
I'm sure I've probably missed some dates. Feel free to fix them up as
you spot them.
The gdb.Objfile, gdb.Progspace, gdb.Type, and gdb.Inferior Python
types already have a __dict__ attribute, which allows users to create
user defined attributes within the objects. This is useful if the
user wants to cache information within an object.
This commit adds the same functionality to the gdb.InferiorThread
type.
After this commit there is a new gdb.InferiorThread.__dict__
attribute, which is a dictionary. A user can, for example, do this:
(gdb) pi
>>> t = gdb.selected_thread()
>>> t._user_attribute = 123
>>> t._user_attribute
123
>>>
There's a new test included.
Reviewed-By: Eli Zaretskii <eliz@gnu.org>
Approved-By: Tom Tromey <tom@tromey.com>
Add a gdb.InferiorThread.__repr__() method. Before this patch we
would see output like this:
(gdb) pi
>>> gdb.selected_thread()
<gdb.InferiorThread object at 0x7f4dcc49b970>
After this patch, we now see:
(gdb) pi
>>> gdb.selected_thread()
<gdb.InferiorThread id=1.2 target-id="Thread 0x7ffff7da1700 (LWP 458134)">
More verbose, but, I hope, more useful.
If the gdb.InferiorThread becomes invalid, then we will see:
(gdb) pi
>>> invalid_thread_variable
<gdb.InferiorThread (invalid)>
Which is inline with how other invalid objects are displayed.
Approved-By: Tom Tromey <tom@tromey.com>
This commit adds a new InferiorThread.ptid_string attribute. This
read-only attribute contains the string returned by target_pid_to_str,
which actually converts a ptid (not pid) to a string.
This is the string that appears (at least in part) in the output of
'info threads' in the 'Target Id' column, but also in the thread
exited message that GDB prints.
Having access to this string from Python is useful for allowing
extensions identify threads in a similar way to how GDB core would
identify the thread.
Reviewed-By: Eli Zaretskii <eliz@gnu.org>
Approved-By: Tom Tromey <tom@tromey.com>
In remote_target::thread_info_to_thread_handle we return a copy:
...
gdb::byte_vector
remote_target::thread_info_to_thread_handle (struct thread_info *tp)
{
remote_thread_info *priv = get_remote_thread_info (tp);
return priv->thread_handle;
}
...
Fix this by returning a gdb::array_view instead:
...
gdb::array_view<const gdb_byte>
remote_target::thread_info_to_thread_handle (struct thread_info *tp)
...
Tested on x86_64-linux.
This fixes the build when building with -std=c++20.
Approved-By: Pedro Alves <pedro@palves.net>
Currently, when we add a new python sub-system to GDB,
e.g. py-inferior.c, we end up having to create a new function like
gdbpy_initialize_inferior, which then has to be called from the
function do_start_initialization in python.c.
In some cases (py-micmd.c and py-tui.c), we have two functions
gdbpy_initialize_*, and gdbpy_finalize_*, with the second being called
from finalize_python which is also in python.c.
This commit proposes a mechanism to manage these initialization and
finalization calls, this means that adding a new Python subsystem will
no longer require changes to python.c or python-internal.h, instead,
the initialization and finalization functions will be registered
directly from the sub-system file, e.g. py-inferior.c, or py-micmd.c.
The initialization and finalization functions are managed through a
new class gdbpy_initialize_file in python-internal.h. This class
contains a single global vector of all the initialization and
finalization functions.
In each Python sub-system we create a new gdbpy_initialize_file
object, the object constructor takes care of registering the two
callback functions.
Now from python.c we can call static functions on the
gdbpy_initialize_file class which take care of walking the callback
list and invoking each callback in turn.
To slightly simplify the Python sub-system files I added a new macro
GDBPY_INITIALIZE_FILE, which hides the need to create an object. We
can now just do this:
GDBPY_INITIALIZE_FILE (gdbpy_initialize_registers);
One possible problem with this change is that there is now no
guaranteed ordering of how the various sub-systems are initialized (or
finalized). To try and avoid dependencies creeping in I have added a
use of the environment variable GDB_REVERSE_INIT_FUNCTIONS, this is
the same environment variable used in the generated init.c file.
Just like with init.c, when this environment variable is set we
reverse the list of Python initialization (and finalization)
functions. As there is already a test that starts GDB with the
environment variable set then this should offer some level of
protection against dependencies creeping in - though for full
protection I guess we'd need to run all gdb.python/*.exp tests with
the variable set.
I have tested this patch with the environment variable set, and saw no
regressions, so I think we are fine right now.
One other change of note was for gdbpy_initialize_gdb_readline, this
function previously returned void. In order to make this function
have the correct signature I've updated its return type to int, and we
now return 0 to indicate success.
All of the other initialize (and finalize) functions have been made
static within their respective sub-system files.
There should be no user visible changes after this commit.
This commit is the result of running the gdb/copyright.py script,
which automated the update of the copyright year range for all
source files managed by the GDB project to be updated to include
year 2023.
New in this version:
- Rebase on master, fix a few more issues that appeared.
python-internal.h contains a number of macros that helped make the code
work with both Python 2 and 3. Remove them and adjust the code to use
the Python 3 functions.
Change-Id: I99a3d80067fb2d65de4f69f6473ba6ffd16efb2d
I got this warning from py-infthread.c using the Fedora 34 system GCC:
../../binutils-gdb/gdb/python/py-infthread.c:102:30: warning: ‘extra_info’ may be used uninitialized in this function [-Wmaybe-uninitialized]
I think this happens because GDB_PY_HANDLE_EXCEPTION expands to an
'if' whose condition is always true -- but GCC can't know this. This
patch avoids the warning by adding a harmless initialization.
This adds a new read-only attribute gdb.InferiorThread.details, this
attribute contains a string, the results of target_extra_thread_info
for the thread, or None, if target_extra_thread_info returns nullptr.
As the string returned by target_extra_thread_info is unstructured,
this attribute is only really useful for echoing straight through to
the user, but, if a user wants to write a command that displays the
same, or a similar 'Thread Id' to the one seen in 'info threads', then
they need access to this string.
Given that the string produced by target_extra_thread_info varies by
target, there's only minimal testing of this attribute, I check that
the attribute can be accessed, and that the return value is either
None, or a string.
This commit brings all the changes made by running gdb/copyright.py
as per GDB's Start of New Year Procedure.
For the avoidance of doubt, all changes in this commits were
performed by the script.
This started out as changing thread_info::name to a unique_xmalloc_ptr.
That showed that almost all users of that field had the same logic to
get a thread's name: use thread_info::name if non-nullptr, else ask the
target. Factor out this logic in a new thread_name free function. Make
the field private (rename to m_name) and add some accessors.
Change-Id: Iebdd95f4cd21fbefc505249bd1d05befc466a2fc
The ptid_t 'tid' member is normally used as an address in gdb -- both
bsd-uthread and ravenscar-thread use it this way. However, because
the type is 'long', this can cause problems with sign extension.
This patch changes the type to ULONGEST to ensure that sign extension
does not occur.
Python 2 has a bit flag Py_TPFLAGS_HAVE_ITER which can be passed as
part of the tp_flags field when defining a new object type. This flag
is not defined in Python 3 and so we define it to 0 in
python-internal.h (when IS_PY3K is defined).
The meaning of this flag is that the object has the fields tp_iter and
tp_iternext. Note the use of "has" here, the flag says nothing about
the values in those fields, just that the type object has the fields.
In early versions of Python 2 these fields were no part of the
PyTypeObject struct, they were added in version 2.2 (see
https://docs.python.org/release/2.3/api/type-structs.html). And so,
there could be a some code compiled out there which has a PyTypeObject
structure within it that doesn't even have the tp_iter and tp_iternext
fields, attempting to access these fields would be undefined
behaviour.
And so Python added the Py_TPFLAGS_HAVE_ITER flag. If the flag is
present then Python is free to access the tp_iter and tp_iternext
fields.
If we consider GDB then we always assume that the tp_iter and
tp_iternext fields are part of PyTypeObject. If someone was crazy
enough to try and compile GDB against Python 2.1 then we'd get lots of
build errors saying that we were passing too many fields when
initializing PyTypeObject structures. And so, I claim, we can be sure
that GDB will always be compiled with a version of Python that has the
tp_iter and tp_iternext fields in PyTypeObject.
Next we can look at the Py_TPFLAGS_DEFAULT flag. In Python 2, each
time additional fields are added to PyTypeObject a new Py_TPFLAGS_*
flag would be defined to indicate whether those flags are present or
not. And, those new flags would be added to Py_TPFLAGS_DEFAULT. And
so, in the latest version of Python 2 the Py_TPFLAGS_DEFAULT flag
includes Py_TPFLAGS_HAVE_ITER (see
https://docs.python.org/2.7/c-api/typeobj.html).
In GDB we pass Py_TPFLAGS_DEFAULT as part of the tp_flags for all
objects we define.
And so, in this commit, I propose to remove all uses of
Py_TPFLAGS_HAVE_ITER from GDB, it's simply not needed.
There should be no user visible changes after this commit.
This commits the result of running gdb/copyright.py as per our Start
of New Year procedure...
gdb/ChangeLog
Update copyright year range in copyright header of all GDB files.
Avoid the use of PyInt_FromLong, preferring gdb_py_object_from_longest
instead. I found found another spot that was incorrectly handling
errors (see gdbpy_create_ptid_object) while writing this patch; it is
fixed here.
gdb/ChangeLog
2020-09-15 Tom Tromey <tromey@adacore.com>
* python/python-internal.h (PyInt_FromLong): Remove define.
* python/py-value.c (convert_value_from_python): Use
gdb_py_object_from_longest.
* python/py-type.c (typy_get_code): Use
gdb_py_object_from_longest.
* python/py-symtab.c (salpy_get_line): Use
gdb_py_object_from_longest.
* python/py-symbol.c (sympy_get_addr_class, sympy_line): Use
gdb_py_object_from_longest.
* python/py-record.c (recpy_gap_reason_code): Use
gdb_py_object_from_longest.
* python/py-record-btrace.c (recpy_bt_insn_size)
(recpy_bt_func_level, btpy_list_count): Use
gdb_py_object_from_longest.
* python/py-infthread.c (gdbpy_create_ptid_object): Use
gdb_py_object_from_longest. Fix error handling.
* python/py-framefilter.c (bootstrap_python_frame_filters): Use
gdb_py_object_from_longest.
* python/py-frame.c (frapy_type, frapy_unwind_stop_reason): Use
gdb_py_object_from_longest.
* python/py-breakpoint.c (bppy_get_type, bppy_get_number)
(bppy_get_thread, bppy_get_task, bppy_get_hit_count)
(bppy_get_ignore_count): Use gdb_py_object_from_longest.
This changes gdb to avoid PyLong_FromLong, preferring to
gdb_py_object_from_longest instead.
gdb/ChangeLog
2020-09-15 Tom Tromey <tromey@adacore.com>
* python/python.c (gdbpy_parameter_value): Use
gdb_py_object_from_longest.
* python/py-type.c (convert_field, typy_range): Use
gdb_py_object_from_longest.
* python/py-tui.c (gdbpy_tui_width, gdbpy_tui_height): Use
gdb_py_object_from_longest.
* python/py-lazy-string.c (stpy_get_length): Use
gdb_py_object_from_longest.
* python/py-infthread.c (thpy_get_num, thpy_get_global_num): Use
gdb_py_object_from_longest.
* python/py-infevents.c (create_memory_changed_event_object): Use
gdb_py_object_from_longest.
* python/py-inferior.c (infpy_get_num): Use
gdb_py_object_from_longest.
(infpy_get_pid): Likewise.
This patch changes py-inferior.c to use gdbpy_ref<> when possible,
reducing the amount of manual reference counting.
Tested on x86-64 Fedora 29.
gdb/ChangeLog
2019-07-10 Tom Tromey <tromey@adacore.com>
* python/python-internal.h (create_thread_object): Return
gdbpy_ref.
* python/py-infthread.c (create_thread_object): Return gdbpy_ref.
* python/py-inferior.c (struct threadlist_entry): Add
constructor.
<thread_obj>: Now a gdbpy_ref.
(thread_to_thread_object): Update.
(add_thread_object): Use new.
(delete_thread_object): Use delete.
(infpy_threads): Update.
(py_free_inferior): Update. Construct "inf_obj" after acquiring
GIL.
This rewrites gdb's TRY/CATCH to plain C++ try/catch. The patch was
largely written by script, though one change (to a comment in
common-exceptions.h) was reverted by hand.
gdb/ChangeLog
2019-04-08 Tom Tromey <tom@tromey.com>
* xml-support.c: Use C++ exception handling.
* x86-linux-nat.c: Use C++ exception handling.
* windows-nat.c: Use C++ exception handling.
* varobj.c: Use C++ exception handling.
* value.c: Use C++ exception handling.
* valprint.c: Use C++ exception handling.
* valops.c: Use C++ exception handling.
* unittests/parse-connection-spec-selftests.c: Use C++ exception
handling.
* unittests/cli-utils-selftests.c: Use C++ exception handling.
* typeprint.c: Use C++ exception handling.
* tui/tui.c: Use C++ exception handling.
* tracefile-tfile.c: Use C++ exception handling.
* top.c: Use C++ exception handling.
* thread.c: Use C++ exception handling.
* target.c: Use C++ exception handling.
* symmisc.c: Use C++ exception handling.
* symfile-mem.c: Use C++ exception handling.
* stack.c: Use C++ exception handling.
* sparc64-linux-tdep.c: Use C++ exception handling.
* solib.c: Use C++ exception handling.
* solib-svr4.c: Use C++ exception handling.
* solib-spu.c: Use C++ exception handling.
* solib-frv.c: Use C++ exception handling.
* solib-dsbt.c: Use C++ exception handling.
* selftest-arch.c: Use C++ exception handling.
* s390-tdep.c: Use C++ exception handling.
* rust-lang.c: Use C++ exception handling.
* rust-exp.y: Use C++ exception handling.
* rs6000-tdep.c: Use C++ exception handling.
* rs6000-aix-tdep.c: Use C++ exception handling.
* riscv-tdep.c: Use C++ exception handling.
* remote.c: Use C++ exception handling.
* remote-fileio.c: Use C++ exception handling.
* record-full.c: Use C++ exception handling.
* record-btrace.c: Use C++ exception handling.
* python/python.c: Use C++ exception handling.
* python/py-value.c: Use C++ exception handling.
* python/py-utils.c: Use C++ exception handling.
* python/py-unwind.c: Use C++ exception handling.
* python/py-type.c: Use C++ exception handling.
* python/py-symbol.c: Use C++ exception handling.
* python/py-record.c: Use C++ exception handling.
* python/py-record-btrace.c: Use C++ exception handling.
* python/py-progspace.c: Use C++ exception handling.
* python/py-prettyprint.c: Use C++ exception handling.
* python/py-param.c: Use C++ exception handling.
* python/py-objfile.c: Use C++ exception handling.
* python/py-linetable.c: Use C++ exception handling.
* python/py-lazy-string.c: Use C++ exception handling.
* python/py-infthread.c: Use C++ exception handling.
* python/py-inferior.c: Use C++ exception handling.
* python/py-gdb-readline.c: Use C++ exception handling.
* python/py-framefilter.c: Use C++ exception handling.
* python/py-frame.c: Use C++ exception handling.
* python/py-finishbreakpoint.c: Use C++ exception handling.
* python/py-cmd.c: Use C++ exception handling.
* python/py-breakpoint.c: Use C++ exception handling.
* python/py-arch.c: Use C++ exception handling.
* printcmd.c: Use C++ exception handling.
* ppc-linux-tdep.c: Use C++ exception handling.
* parse.c: Use C++ exception handling.
* p-valprint.c: Use C++ exception handling.
* objc-lang.c: Use C++ exception handling.
* mi/mi-main.c: Use C++ exception handling.
* mi/mi-interp.c: Use C++ exception handling.
* mi/mi-cmd-stack.c: Use C++ exception handling.
* mi/mi-cmd-break.c: Use C++ exception handling.
* main.c: Use C++ exception handling.
* linux-thread-db.c: Use C++ exception handling.
* linux-tdep.c: Use C++ exception handling.
* linux-nat.c: Use C++ exception handling.
* linux-fork.c: Use C++ exception handling.
* linespec.c: Use C++ exception handling.
* language.c: Use C++ exception handling.
* jit.c: Use C++ exception handling.
* infrun.c: Use C++ exception handling.
* infcmd.c: Use C++ exception handling.
* infcall.c: Use C++ exception handling.
* inf-loop.c: Use C++ exception handling.
* i386-tdep.c: Use C++ exception handling.
* i386-linux-tdep.c: Use C++ exception handling.
* guile/scm-value.c: Use C++ exception handling.
* guile/scm-type.c: Use C++ exception handling.
* guile/scm-symtab.c: Use C++ exception handling.
* guile/scm-symbol.c: Use C++ exception handling.
* guile/scm-pretty-print.c: Use C++ exception handling.
* guile/scm-ports.c: Use C++ exception handling.
* guile/scm-param.c: Use C++ exception handling.
* guile/scm-math.c: Use C++ exception handling.
* guile/scm-lazy-string.c: Use C++ exception handling.
* guile/scm-frame.c: Use C++ exception handling.
* guile/scm-disasm.c: Use C++ exception handling.
* guile/scm-cmd.c: Use C++ exception handling.
* guile/scm-breakpoint.c: Use C++ exception handling.
* guile/scm-block.c: Use C++ exception handling.
* guile/guile-internal.h: Use C++ exception handling.
* gnu-v3-abi.c: Use C++ exception handling.
* gdbtypes.c: Use C++ exception handling.
* frame.c: Use C++ exception handling.
* frame-unwind.c: Use C++ exception handling.
* fbsd-tdep.c: Use C++ exception handling.
* f-valprint.c: Use C++ exception handling.
* exec.c: Use C++ exception handling.
* event-top.c: Use C++ exception handling.
* event-loop.c: Use C++ exception handling.
* eval.c: Use C++ exception handling.
* dwarf2read.c: Use C++ exception handling.
* dwarf2loc.c: Use C++ exception handling.
* dwarf2-frame.c: Use C++ exception handling.
* dwarf2-frame-tailcall.c: Use C++ exception handling.
* dwarf-index-write.c: Use C++ exception handling.
* dwarf-index-cache.c: Use C++ exception handling.
* dtrace-probe.c: Use C++ exception handling.
* disasm-selftests.c: Use C++ exception handling.
* darwin-nat.c: Use C++ exception handling.
* cp-valprint.c: Use C++ exception handling.
* cp-support.c: Use C++ exception handling.
* cp-abi.c: Use C++ exception handling.
* corelow.c: Use C++ exception handling.
* completer.c: Use C++ exception handling.
* compile/compile-object-run.c: Use C++ exception handling.
* compile/compile-object-load.c: Use C++ exception handling.
* compile/compile-cplus-symbols.c: Use C++ exception handling.
* compile/compile-c-symbols.c: Use C++ exception handling.
* common/selftest.c: Use C++ exception handling.
* common/new-op.c: Use C++ exception handling.
* cli/cli-script.c: Use C++ exception handling.
* cli/cli-interp.c: Use C++ exception handling.
* cli/cli-cmds.c: Use C++ exception handling.
* c-varobj.c: Use C++ exception handling.
* btrace.c: Use C++ exception handling.
* breakpoint.c: Use C++ exception handling.
* break-catch-throw.c: Use C++ exception handling.
* arch-utils.c: Use C++ exception handling.
* amd64-tdep.c: Use C++ exception handling.
* ada-valprint.c: Use C++ exception handling.
* ada-typeprint.c: Use C++ exception handling.
* ada-lang.c: Use C++ exception handling.
* aarch64-tdep.c: Use C++ exception handling.
gdb/gdbserver/ChangeLog
2019-04-08 Tom Tromey <tom@tromey.com>
* server.c: Use C++ exception handling.
* linux-low.c: Use C++ exception handling.
* gdbreplay.c: Use C++ exception handling.
Most callers of inferior_to_inferior_object already use a gdbpy_ref,
so this changes inferior_to_inferior_object to return one. Doing this
revealed that create_thread_object was not correctly handling the case
where inferior_to_inferior_object failed, so this patch fixes this as
well.
gdb/ChangeLog
2019-01-02 Tom Tromey <tom@tromey.com>
* python/python-internal.h (inferior_to_inferior_object): Change
return type.
* python/py-exitedevent.c (create_exited_event_object): Update.
* python/py-inferior.c (inferior_to_inferior_object): Return
gdbpy_ref.
(python_new_inferior, python_inferior_deleted)
(thread_to_thread_object, delete_thread_object)
(build_inferior_list, gdbpy_selected_inferior): Update.
* python/py-infthread.c (create_thread_object): Update. Also fail
if inferior_to_inferior_object fails.
This commit applies all changes made after running the gdb/copyright.py
script.
Note that one file was flagged by the script, due to an invalid
copyright header
(gdb/unittests/basic_string_view/element_access/char/empty.cc).
As the file was copied from GCC's libstdc++-v3 testsuite, this commit
leaves this file untouched for the time being; a patch to fix the header
was sent to gcc-patches first.
gdb/ChangeLog:
Update copyright year range in all GDB files.
This changes thread_to_thread_object to return a new reference and
fixes up all the callers.
gdb/ChangeLog
2018-09-16 Tom Tromey <tom@tromey.com>
* python/python-internal.h (thread_to_thread_object): Change
return type.
* python/py-inferior.c (thread_to_thread_object): Return a new
reference.
(infpy_thread_from_thread_handle): Update.
* python/py-infthread.c (gdbpy_selected_thread): Update.
* python/py-stopevent.c (create_stop_event_object): Update.
* python/py-threadevent.c (py_get_event_thread): Return a new
reference.
(py_get_event_thread): Update.
* python/py-event.h (py_get_event_thread): Change return type.
* python/py-continueevent.c (create_continue_event_object):
Update.
This is more preparation bits for multi-target support.
In a multi-target scenario, we need to address the case of different
processes/threads running on different targets that happen to have the
same PID/PTID. E.g., we can have both process 123 in target 1, and
process 123 in target 2, while they're in reality different processes
running on different machines. Or maybe we've loaded multiple
instances of the same core file. Etc.
To address this, in my WIP multi-target branch, threads and processes
are uniquely identified by the (process_stratum target_ops *, ptid_t)
and (process_stratum target_ops *, pid) tuples respectively. I.e.,
each process_stratum instance has its own thread/process number space.
As you can imagine, that requires passing around target_ops * pointers
in a number of functions where we're currently passing only a ptid_t
or an int. E.g., when we look up a thread_info object by ptid_t in
find_thread_ptid, the ptid_t alone isn't sufficient.
In many cases though, we already have the thread_info or inferior
pointer handy, but we "lose" it somewhere along the call stack, only
to look it up again by ptid_t/pid. Since thread_info or inferior
objects know their parent target, if we pass around thread_info or
inferior pointers when possible, we avoid having to add extra
target_ops parameters to many functions, and also, we eliminate a
number of by ptid_t/int lookups.
So that's what this patch does. In a bit more detail:
- Changes a number of functions and methods to take a thread_info or
inferior pointer instead of a ptid_t or int parameter.
- Changes a number of structure fields from ptid_t/int to inferior or
thread_info pointers.
- Uses the inferior_thread() function whenever possible instead of
inferior_ptid.
- Uses thread_info pointers directly when possible instead of the
is_running/is_stopped etc. routines that require a lookup.
- A number of functions are eliminated along the way, such as:
int valid_gdb_inferior_id (int num);
int pid_to_gdb_inferior_id (int pid);
int gdb_inferior_id_to_pid (int num);
int in_inferior_list (int pid);
- A few structures and places hold a thread_info pointer across
inferior execution, so now they take a strong reference to the
(refcounted) thread_info object to avoid the thread_info pointer
getting stale. This is done in enable_thread_stack_temporaries and
in the infcall.c code.
- Related, there's a spot in infcall.c where using a RAII object to
handle the refcount would be handy, so a gdb::ref_ptr specialization
for thread_info is added (thread_info_ref, in gdbthread.h), along
with a gdb_ref_ptr policy that works for all refcounted_object types
(in common/refcounted-object.h).
gdb/ChangeLog:
2018-06-21 Pedro Alves <palves@redhat.com>
* ada-lang.h (ada_get_task_number): Take a thread_info pointer
instead of a ptid_t. All callers adjusted.
* ada-tasks.c (ada_get_task_number): Likewise. All callers
adjusted.
(print_ada_task_info, display_current_task_id, task_command_1):
Adjust.
* breakpoint.c (watchpoint_in_thread_scope): Adjust to use
inferior_thread.
(breakpoint_kind): Adjust.
(remove_breakpoints_pid): Rename to ...
(remove_breakpoints_inf): ... this. Adjust to take an inferior
pointer. All callers adjusted.
(bpstat_clear_actions): Use inferior_thread.
(get_bpstat_thread): New.
(bpstat_do_actions): Use it.
(bpstat_check_breakpoint_conditions, bpstat_stop_status): Adjust
to take a thread_info pointer. All callers adjusted.
(set_longjmp_breakpoint_for_call_dummy, set_momentary_breakpoint)
(breakpoint_re_set_thread): Use inferior_thread.
* breakpoint.h (struct inferior): Forward declare.
(bpstat_stop_status): Update.
(remove_breakpoints_pid): Delete.
(remove_breakpoints_inf): New.
* bsd-uthread.c (bsd_uthread_target::wait)
(bsd_uthread_target::update_thread_list): Use find_thread_ptid.
* btrace.c (btrace_add_pc, btrace_enable, btrace_fetch)
(maint_btrace_packet_history_cmd)
(maint_btrace_clear_packet_history_cmd): Adjust.
(maint_btrace_clear_cmd, maint_info_btrace_cmd): Adjust to use
inferior_thread.
* cli/cli-interp.c: Include "inferior.h".
* common/refcounted-object.h (struct
refcounted_object_ref_policy): New.
* compile/compile-object-load.c: Include gdbthread.h.
(store_regs): Use inferior_thread.
* corelow.c (core_target::close): Use current_inferior.
(core_target_open): Adjust to use first_thread_of_inferior and use
the current inferior.
* ctf.c (ctf_target::close): Adjust to use current_inferior.
* dummy-frame.c (dummy_frame_id) <ptid>: Delete, replaced by ...
<thread>: ... this new field. All references adjusted.
(dummy_frame_pop, dummy_frame_discard, register_dummy_frame_dtor):
Take a thread_info pointer instead of a ptid_t.
* dummy-frame.h (dummy_frame_push, dummy_frame_pop)
(dummy_frame_discard, register_dummy_frame_dtor): Take a
thread_info pointer instead of a ptid_t.
* elfread.c: Include "inferior.h".
(elf_gnu_ifunc_resolver_stop, elf_gnu_ifunc_resolver_return_stop):
Use inferior_thread.
* eval.c (evaluate_subexp): Likewise.
* frame.c (frame_pop, has_stack_frames, find_frame_sal): Use
inferior_thread.
* gdb_proc_service.h (struct thread_info): Forward declare.
(struct ps_prochandle) <ptid>: Delete, replaced by ...
<thread>: ... this new field. All references adjusted.
* gdbarch.h, gdbarch.c: Regenerate.
* gdbarch.sh (get_syscall_number): Replace 'ptid' parameter with a
'thread' parameter. All implementations and callers adjusted.
* gdbthread.h (thread_info) <set_running>: New method.
(delete_thread, delete_thread_silent): Take a thread_info pointer
instead of a ptid.
(global_thread_id_to_ptid, ptid_to_global_thread_id): Delete.
(first_thread_of_process): Delete, replaced by ...
(first_thread_of_inferior): ... this new function. All callers
adjusted.
(any_live_thread_of_process): Delete, replaced by ...
(any_live_thread_of_inferior): ... this new function. All callers
adjusted.
(switch_to_thread, switch_to_no_thread): Declare.
(is_executing): Delete.
(enable_thread_stack_temporaries): Update comment.
<enable_thread_stack_temporaries>: Take a thread_info pointer
instead of a ptid_t. Incref the thread.
<~enable_thread_stack_temporaries>: Decref the thread.
<m_ptid>: Delete
<m_thr>: New.
(thread_stack_temporaries_enabled_p, push_thread_stack_temporary)
(get_last_thread_stack_temporary)
(value_in_thread_stack_temporaries, can_access_registers_thread):
Take a thread_info pointer instead of a ptid_t. All callers
adjusted.
* infcall.c (get_call_return_value): Use inferior_thread.
(run_inferior_call): Work with thread pointers instead of ptid_t.
(call_function_by_hand_dummy): Work with thread pointers instead
of ptid_t. Use thread_info_ref.
* infcmd.c (proceed_thread_callback): Access thread's state
directly.
(ensure_valid_thread, ensure_not_running): Use inferior_thread,
access thread's state directly.
(continue_command): Use inferior_thread.
(info_program_command): Use find_thread_ptid and access thread
state directly.
(proceed_after_attach_callback): Use thread state directly.
(notice_new_inferior): Take a thread_info pointer instead of a
ptid_t. All callers adjusted.
(exit_inferior): Take an inferior pointer instead of a pid. All
callers adjusted.
(exit_inferior_silent): New.
(detach_inferior): Delete.
(valid_gdb_inferior_id, pid_to_gdb_inferior_id)
(gdb_inferior_id_to_pid, in_inferior_list): Delete.
(detach_inferior_command, kill_inferior_command): Use
find_inferior_id instead of valid_gdb_inferior_id and
gdb_inferior_id_to_pid.
(inferior_command): Use inferior and thread pointers.
* inferior.h (struct thread_info): Forward declare.
(notice_new_inferior): Take a thread_info pointer instead of a
ptid_t. All callers adjusted.
(detach_inferior): Delete declaration.
(exit_inferior, exit_inferior_silent): Take an inferior pointer
instead of a pid. All callers adjusted.
(gdb_inferior_id_to_pid, pid_to_gdb_inferior_id, in_inferior_list)
(valid_gdb_inferior_id): Delete.
* infrun.c (follow_fork_inferior, proceed_after_vfork_done)
(handle_vfork_child_exec_or_exit, follow_exec): Adjust.
(struct displaced_step_inferior_state) <pid>: Delete, replaced by
...
<inf>: ... this new field.
<step_ptid>: Delete, replaced by ...
<step_thread>: ... this new field.
(get_displaced_stepping_state): Take an inferior pointer instead
of a pid. All callers adjusted.
(displaced_step_in_progress_any_inferior): Adjust.
(displaced_step_in_progress_thread): Take a thread pointer instead
of a ptid_t. All callers adjusted.
(displaced_step_in_progress, add_displaced_stepping_state): Take
an inferior pointer instead of a pid. All callers adjusted.
(get_displaced_step_closure_by_addr): Adjust.
(remove_displaced_stepping_state): Take an inferior pointer
instead of a pid. All callers adjusted.
(displaced_step_prepare_throw, displaced_step_prepare)
(displaced_step_fixup): Take a thread pointer instead of a ptid_t.
All callers adjusted.
(start_step_over): Adjust.
(infrun_thread_ptid_changed): Remove bit updating ptids in the
displaced step queue.
(do_target_resume): Adjust.
(fetch_inferior_event): Use inferior_thread.
(context_switch, get_inferior_stop_soon): Take an
execution_control_state pointer instead of a ptid_t. All callers
adjusted.
(switch_to_thread_cleanup): Delete.
(stop_all_threads): Use scoped_restore_current_thread.
* inline-frame.c: Include "gdbthread.h".
(inline_state) <inline_state>: Take a thread pointer instead of a
ptid_t. All callers adjusted.
<ptid>: Delete, replaced by ...
<thread>: ... this new field.
(find_inline_frame_state): Take a thread pointer instead of a
ptid_t. All callers adjusted.
(skip_inline_frames, step_into_inline_frame)
(inline_skipped_frames, inline_skipped_symbol): Take a thread
pointer instead of a ptid_t. All callers adjusted.
* inline-frame.h (skip_inline_frames, step_into_inline_frame)
(inline_skipped_frames, inline_skipped_symbol): Likewise.
* linux-fork.c (delete_checkpoint_command): Adjust to use thread
pointers directly.
* linux-nat.c (get_detach_signal): Likewise.
* linux-thread-db.c (thread_from_lwp): New 'stopped' parameter.
(thread_db_notice_clone): Adjust.
(thread_db_find_new_threads_silently)
(thread_db_find_new_threads_2, thread_db_find_new_threads_1): Take
a thread pointer instead of a ptid_t. All callers adjusted.
* mi/mi-cmd-var.c: Include "inferior.h".
(mi_cmd_var_update_iter): Update to use thread pointers.
* mi/mi-interp.c (mi_new_thread): Update to use the thread's
inferior directly.
(mi_output_running_pid, mi_inferior_count): Delete, bits factored
out to ...
(mi_output_running): ... this new function.
(mi_on_resume_1): Adjust to use it.
(mi_user_selected_context_changed): Adjust to use inferior_thread.
* mi/mi-main.c (proceed_thread): Adjust to use thread pointers
directly.
(interrupt_thread_callback): : Adjust to use thread and inferior
pointers.
* proc-service.c: Include "gdbthread.h".
(ps_pglobal_lookup): Adjust to use the thread's inferior directly.
* progspace-and-thread.c: Include "inferior.h".
* progspace.c: Include "inferior.h".
* python/py-exitedevent.c (create_exited_event_object): Adjust to
hold a reference to an inferior_object.
* python/py-finishbreakpoint.c (bpfinishpy_init): Adjust to use
inferior_thread.
* python/py-inferior.c (struct inferior_object): Give the type a
tag name instead of a typedef.
(python_on_normal_stop): No need to check if the current thread is
listed.
(inferior_to_inferior_object): Change return type to
inferior_object. All callers adjusted.
(find_thread_object): Delete, bits factored out to ...
(thread_to_thread_object): ... this new function.
* python/py-infthread.c (create_thread_object): Use
inferior_to_inferior_object.
(thpy_is_stopped): Use thread pointer directly.
(gdbpy_selected_thread): Use inferior_thread.
* python/py-record-btrace.c (btpy_list_object) <ptid>: Delete
field, replaced with ...
<thread>: ... this new field. All users adjusted.
(btpy_insn_or_gap_new): Drop const.
(btpy_list_new): Take a thread pointer instead of a ptid_t. All
callers adjusted.
* python/py-record.c: Include "gdbthread.h".
(recpy_insn_new, recpy_func_new): Take a thread pointer instead of
a ptid_t. All callers adjusted.
(gdbpy_current_recording): Use inferior_thread.
* python/py-record.h (recpy_record_object) <ptid>: Delete
field, replaced with ...
<thread>: ... this new field. All users adjusted.
(recpy_element_object) <ptid>: Delete
field, replaced with ...
<thread>: ... this new field. All users adjusted.
(recpy_insn_new, recpy_func_new): Take a thread pointer instead of
a ptid_t. All callers adjusted.
* python/py-threadevent.c: Include "gdbthread.h".
(get_event_thread): Use thread_to_thread_object.
* python/python-internal.h (struct inferior_object): Forward
declare.
(find_thread_object, find_inferior_object): Delete declarations.
(thread_to_thread_object, inferior_to_inferior_object): New
declarations.
* record-btrace.c: Include "inferior.h".
(require_btrace_thread): Use inferior_thread.
(record_btrace_frame_sniffer)
(record_btrace_tailcall_frame_sniffer): Use inferior_thread.
(get_thread_current_frame): Use scoped_restore_current_thread and
switch_to_thread.
(get_thread_current_frame): Use thread pointer directly.
(record_btrace_replay_at_breakpoint): Use thread's inferior
pointer directly.
* record-full.c: Include "inferior.h".
* regcache.c: Include "gdbthread.h".
(get_thread_arch_regcache): Use the inferior's address space
directly.
(get_thread_regcache, registers_changed_thread): New.
* regcache.h (get_thread_regcache(thread_info *thread)): New
overload.
(registers_changed_thread): New.
(remote_target) <remote_detach_1>: Swap order of parameters.
(remote_add_thread): <remote_add_thread>: Return the new thread.
(get_remote_thread_info(ptid_t)): New overload.
(remote_target::remote_notice_new_inferior): Use thread pointers
directly.
(remote_target::process_initial_stop_replies): Use
thread_info::set_running.
(remote_target::remote_detach_1, remote_target::detach)
(extended_remote_target::detach): Adjust.
* stack.c (frame_show_address): Use inferior_thread.
* target-debug.h (target_debug_print_thread_info_pp): New.
* target-delegates.c: Regenerate.
* target.c (default_thread_address_space): Delete.
(memory_xfer_partial_1): Use current_inferior.
(target_detach): Use current_inferior.
(target_thread_address_space): Delete.
(generic_mourn_inferior): Use current_inferior.
* target.h (struct target_ops) <thread_address_space>: Delete.
(target_thread_address_space): Delete.
* thread.c (init_thread_list): Use ALL_THREADS_SAFE. Use thread
pointers directly.
(delete_thread_1, delete_thread, delete_thread_silent): Take a
thread pointer instead of a ptid_t. Adjust all callers.
(ptid_to_global_thread_id, global_thread_id_to_ptid): Delete.
(first_thread_of_process): Delete, replaced by ...
(first_thread_of_inferior): ... this new function. All callers
adjusted.
(any_thread_of_process): Rename to ...
(any_thread_of_inferior): ... this, and take an inferior pointer.
(any_live_thread_of_process): Rename to ...
(any_live_thread_of_inferior): ... this, and take an inferior
pointer.
(thread_stack_temporaries_enabled_p, push_thread_stack_temporary)
(value_in_thread_stack_temporaries)
(get_last_thread_stack_temporary): Take a thread pointer instead
of a ptid_t. Adjust all callers.
(thread_info::set_running): New.
(validate_registers_access): Use inferior_thread.
(can_access_registers_ptid): Rename to ...
(can_access_registers_thread): ... this, and take a thread
pointer.
(print_thread_info_1): Adjust to compare thread pointers instead
of ptids.
(switch_to_no_thread, switch_to_thread): Make extern.
(scoped_restore_current_thread::~scoped_restore_current_thread):
Use m_thread pointer directly.
(scoped_restore_current_thread::scoped_restore_current_thread):
Use inferior_thread.
(thread_command): Use thread pointer directly.
(thread_num_make_value_helper): Use inferior_thread.
* top.c (execute_command): Use inferior_thread.
* tui/tui-interp.c: Include "inferior.h".
* varobj.c (varobj_create): Use inferior_thread.
(value_of_root_1): Use find_thread_global_id instead of
global_thread_id_to_ptid.
thpy_get_inferior function should return a new reference to the
existing inferior object, and therefore should increment its refcount.
Fixed bug looks like this.
If multiple time call gdb.selected_thread ().inferior, gdb throws exception:
(gdb) pi gdb.selected_thread().inferior
<gdb.Inferior object at 0x7f1952bea698>
(gdb) pi gdb.selected_thread().inferior
Python Exception <type 'exceptions.AttributeError'> 'NoneType' object
has no attribute 'inferior':
Error while executing Python code.
(gdb) info threads
Id Target Id Frame
* 1 Thread 0x7f54f0474740 (LWP 584) "mc" 0x00007f54ef055c33 in
Unfortunately, PyGetSetDef's 'name' and 'doc' members are 'char *'
instead of 'const char *', meaning that in order to list-initialize
PyGetSetDef arrays using string literals requires writing explicit
'char *' casts. For example:
static PyGetSetDef value_object_getset[] = {
- { "address", valpy_get_address, NULL, "The address of the value.",
+ { (char *) "address", valpy_get_address, NULL,
+ (char *) "The address of the value.",
NULL },
- { "is_optimized_out", valpy_get_is_optimized_out, NULL,
- "Boolean telling whether the value is optimized "
+ { (char *) "is_optimized_out", valpy_get_is_optimized_out, NULL,
+ (char *) "Boolean telling whether the value is optimized "
"out (i.e., not available).",
NULL },
- { "type", valpy_get_type, NULL, "Type of the value.", NULL },
- { "dynamic_type", valpy_get_dynamic_type, NULL,
- "Dynamic type of the value.", NULL },
- { "is_lazy", valpy_get_is_lazy, NULL,
- "Boolean telling whether the value is lazy (not fetched yet\n\
+ { (char *) "type", valpy_get_type, NULL,
+ (char *) "Type of the value.", NULL },
+ { (char *) "dynamic_type", valpy_get_dynamic_type, NULL,
+ (char *) "Dynamic type of the value.", NULL },
+ { (char *) "is_lazy", valpy_get_is_lazy, NULL,
+ (char *) "Boolean telling whether the value is lazy (not fetched yet\n\
from the inferior). A lazy value is fetched when needed, or when\n\
the \"fetch_lazy()\" method is called.", NULL },
{NULL} /* Sentinel */
We have ~20 such arrays, and I first wrote a patch that fixed all of
them like that... It's not pretty...
One way to make these a bit less ugly would be add a new macro that
hides the casts, like:
#define GDBPY_GSDEF(NAME, GET, SET, DOC, CLOSURE) \
{ (char *) NAME, GET, SET, (char *) DOC, CLOSURE }
and then use it like:
static PyGetSetDef value_object_getset[] = {
GDBPY_GSDEF ("address", valpy_get_address, NULL,
"The address of the value.", NULL),
GDBPY_GSDEF ("is_optimized_out", valpy_get_is_optimized_out, NULL,
"Boolean telling whether the value is optimized ", NULL),
{NULL} /* Sentinel */
};
But since we have C++11, which gives us constexpr and list
initialization, I thought of a way that requires no changes where the
arrays are initialized:
We add a new type that extends PyGetSetDef (called gdb_PyGetSetDef),
and add constexpr constructors that accept const 'name' and 'doc', and
then list/aggregate initialization simply "calls" these matching
constructors instead.
I put "calls" in quotes, because given "constexpr", it's all done at
compile time, and there's no overhead either in binary size or at run
time. In fact, we get identical binaries, before/after this change.
Unlike the fixes that fix some old Python API to match the API of more
recent Python, this switches to using explicit "gdb_PyGetSetDef"
everywhere, just to be clear that we are using our own version of it.
gdb/ChangeLog:
2017-04-05 Pedro Alves <palves@redhat.com>
* python/python-internal.h (gdb_PyGetSetDef): New type.
* python/py-block.c (block_object_getset)
(breakpoint_object_getset): Now a gdb_PyGetSetDef array.
* python/py-event.c (event_object_getset)
(finish_breakpoint_object_getset): Likewise.
* python/py-inferior.c (inferior_object_getset): Likewise.
* python/py-infthread.c (thread_object_getset): Likewise.
* python/py-lazy-string.c (lazy_string_object_getset): Likewise.
* python/py-linetable.c (linetable_entry_object_getset): Likewise.
* python/py-objfile.c (objfile_getset): Likewise.
* python/py-progspace.c (pspace_getset): Likewise.
* python/py-record-btrace.c (btpy_insn_getset, btpy_call_getset):
Likewise.
* python/py-record.c (recpy_record_getset): Likewise.
* python/py-symbol.c (symbol_object_getset): Likewise.
* python/py-symtab.c (symtab_object_getset, sal_object_getset):
Likewise.
* python/py-type.c (type_object_getset, field_object_getset):
Likewise.
* python/py-value.c (value_object_getset): Likewise.