aboutsummaryrefslogtreecommitdiff
path: root/gdb/python
AgeCommit message (Collapse)AuthorFilesLines
2026-04-23gdb/dap: add support for opening core filesAndrew Burgess3-5/+42
This patch adds core file support to GDB's DAP interface. Core files are supported as a GDB specific argument to 'attach', the new argument is 'coreFile', the name of the core file to debug. I think handling core files via attach makes the most sense; attach is for connecting to existing processes, but these targets are (usually) stopped as soon as GDB attaches, and that's what a core file looks like, a target that was running, but is now stopped. It just happens that core file targets are special in that the target cannot be resumed again, nor can the user modify the program state (e.g. write to memory or registers). Prior to starting this work I took a look at what lldb does. The documentation is not super clear, but this page seems to indicate that lldb might also use the 'coreFile' argument to 'attach': https://lldb.llvm.org/use/lldbdap.html#configuration-settings-reference Like I said, it's not very clear, but search for "coreFile" and you'll see it mentioned, just once, under the "attach" header. In order to be compatible with lldb I used the same argument name with the same capitalisation. The new argument is added to the documentation and mentioned in NEWS. I had to make some changes to testsuite/lib/dap-support.exp to support this new feature. There's a new dap_corefile proc to handle setting up the initial connection. This seemed cleaner that overloading dap_attach, even though under the hood it is still an 'attach' request that gets sent. The new test tries to write to memory and registers with the core file target in place, neither of these requests succeed, which is what we want, but the exceptions are logged into the dap log file. The dap_shutdown proc calls dap_check_log_file to check the log for exceptions, and these two exceptions are spotted and trigger a FAIL. To avoid this I've added a new "expected_exception_count" argument for dap_shutdown. Now we check that we see the expected number of exceptions. We don't check for the specific exception types right now, but as the test is already checking that the expected requests fail, I think we're OK. Approved-By: Tom Tromey <tom@tromey.com>
2026-04-20gdb/python: new events.corefile_changed eventAndrew Burgess3-2/+43
Add a new Python event registry, events.corefile_changed. This event is emitted each time the corefile within an inferior changes. The event object has a single 'inferior' attribute which is the gdb.Inferior object for which the core file changed. The user can then inspect Inferior.corefile to see details about the new core file, or this will be None if the core file was removed from the inferior. I've updated the existing test to cover this new event. The new test covers both the corefile_changed event, but also monitors the exited event. This ties into the work done in the previous commit where we use whether the inferior has exited or not as a guard for whether core_target::exit_core_file_inferior should be called. Unloading a core file should result in a single corefile_changed event and a single exited event. Reviewed-By: Eli Zaretskii <eliz@gnu.org>
2026-04-17gdb: introduce iteration_status enum, use it for search callbacksSimon Marchi1-6/+12
There are a bunch of iteration functions that take a callback returning true or false to indicate whether to continue or stop iterating. These functions then return the same value, indicate whether the iteration was done until the end of interrupted. I think this is confusing and error-prone, as I never know which value means what. It is especially confusing when two opposite conventions collide, such as in objfile::map_symtabs_matching_filename. I propose to make that more obvious by introducing a new iteration_status enum with self-documenting values. I started to change the callback type compunit_symtab_iteration_callback, taken by quick_symbol_functions::search, and then followed that path to update a bunch of other functions. I chose the name to be kind of generic, so that it can be used for other similar iteration patterns. I also put it in gdbsupport, in case we want to use it in gdbserver too. Change-Id: I55d84d0c1af8ac0b82cc9f49ccf0d6b60e1769e0 Approved-By: Andrew Burgess <aburgess@redhat.com>
2026-04-08Add command styling to error messagesTom Tromey1-1/+2
This changes a number of error messages in gdb to use command_style. In some places I've added double quotes around the command name for consistency with other messages. Approved-By: Andrew Burgess <aburgess@redhat.com>
2026-04-08gdb: add new helpers for retrieving a type's fully qualified nameMatthieu Longo19-38/+151
Py_TYPE (self)->tp_name is the traditional idiomatic way to get a Python type's fully qualified name. However, in the context of the Python limited API, PyTypeObject is opaque, so the 'tp_name' attribute is no longer accessible. Additionally, retrieving the type of a Python object requires Py_TYPE, which is only available as part of the stable API starting with Python 3.14. This patch increases minimal Python limited API version from 3.11 to 3.14. It also introduces two new helpers to retrieve a type's fully qualified name: gdb_py_tp_name() and gdbpy_py_obj_tp_name(), which extract the fully qualified name from a PyTypeObject and a PyObject, respectively. Ifdefery allows these wrappers to select the appropriate API depending on the Python version and whether the Python limited API is enabled. For any Python version less than 3.13, gdb_py_tp_name() fallbacks using __qualname__ instead. However, the result may differ slightly in some cases, e.g. the module name may be missing. Finally, this patch adapts the existing code to use these wrappers, and adjusts some test expectations to use the fully qualified name (or __qualname__ for versions <= 3.13) where it was not previously used. Note that the corner case where the module name would be missing does not appear in the testsuite. Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=23830 Approved-By: Tom Tromey <tom@tromey.com>
2026-04-06thread_info::executing+resumed -> thread_info::internal_statePedro Alves1-3/+3
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
2026-03-25Hold the GIL while clearing gdbpy_reggroup_object_mapTom Tromey2-8/+19
Tom de Vries pointed out that a certain Python test left a core file. Looking into this, I think the problem is that the GIL is not held when gdbpy_reggroup_object_map is destroyed. This patch changes the code to explicitly clear the global while holding the GIL. This fixed the crash for me. This also adds a comment to gdbpy_initialize_file to explicitly mention that the GIL is held while the finalizers are run. Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=34013 Reviewed-By: Tom de Vries <tdevries@suse.de>
2026-03-25gdb/python: add property ranges to gdb.Block objectJan Vrany1-0/+39
This commit adds a new property - ranges - to gdb.Block object. It holds a tuple of ranges for that block. Each range is a tuple of (start, end) address. For contiguous blocks it contains only one range. Reviewed-By: Eli Zaretskii <eliz@gnu.org> Approved-By: Tom Tromey <tom@tromey.com>
2026-03-23gdb/python: allow Architecture.disassemble to give styled outputAndrew Burgess1-4/+7
Extend the Architecture.disassemble API to allow the user to request styled disassembler output via a new styling argument. A user can now write: insn = arch.disassemble(address, styling = True) The instruction strings returned within INSN will contain ANSI escape sequences so long as 'set style enabled on' is in effect. This means that the user's personal settings (disabling styling) will override a GDB extension that requests styled disassembler output. I think this makes sense. The default for the styling argument is False, this maintains the current unstyled output as default. Reviewed-By: Eli Zaretskii <eliz@gnu.org> Approved-By: Tom Tromey <tom@tromey.com>
2026-03-19gdb: change new_objfile observer to take an objfile referenceAndrew Burgess1-6/+5
I was looking at the new_objfile observer and noticed a comment in reread_symbols (symfile.c) that seemed out of date, it talked about calling the new objfile observer with a NULL objfile argument. A little digging indicates that the comment is indeed out of date, and that we never call the new_objfile observer with a NULL argument any more. So in this commit I have: 1. Updated the out of date comment in reread_symbols. 2. Changed the argument type for the new_objfile observer from 'objfile *' to 'objfile &'. Passing a NULL pointer is no longer an option. 3. Updated the existing new_objfile observers to take 'objfile &' and updated their implementations as needed. There should be no user visible changes after this commit. Approved-By: Simon Marchi <simon.marchi@efficios.com>
2026-03-16gdb, gdbserver, gdbsupport: replace many uses of strcmp with streqSimon Marchi7-18/+16
Replace all occurrences of: strcmp (...) == 0 strcmp (...) != 0 !strcmp (...) 0 == strcmp (...) strcmp (...) directly used as a boolean predicate with the equivalent expression using streq. This is for consistency (we already use streq as some places in the testsuite) but also for clarity. I think that streq is clearer on the intent than strcmp. It's also a bit shorter. Change-Id: Ibbf5261b1872c240bc0c982c147f6a5477275a91 Approved-By: Andrew Burgess <aburgess@redhat.com>
2026-03-14gdb/python: add accessor helpers for __dict__ in Python extension objectsMatthieu Longo8-31/+31
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>
2026-03-11Return bool from valid_task_idTom Tromey1-1/+1
This changes valid_task_id to return bool and updates some callers. Approved-By: Simon Marchi <simon.marchi@efficios.com>
2026-03-10Return bool from iterate_over_objfiles_in_search_order callbacksTom Tromey1-10/+10
I noticed that many callbacks passed to iterate_over_objfiles_in_search_order were still returning 0/1 rather than false/true. Approved-By: Simon Marchi <simon.marchi@efficios.com>
2026-03-10gdb/python: add gdbpy_dict_wrapper:allocate_dict helperMatthieu Longo8-24/+24
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>
2026-03-10gdb/python: flatten functions calling PyObject_New and use gdbpy_refMatthieu Longo3-57/+57
This patch aims at systematically using gdbpy_ref<> at all call sites of PyObject_New(). This prepares for future patches that expect gdbby_ref<> parameters and affect return handling. As part of this change, flattening the affected functions so that the return logic becomes clearer and more flexible to adjust. Approved-By: Tom Tromey <tom@tromey.com>
2026-03-10gdb/python: allow ref_ptr<T, Policy>::new_reference to accept subclasses of TMatthieu Longo2-2/+2
When ref_ptr<T,Policy>::new_reference() is specialized for 'PyObject' (i.e. gdbpy_ref<>), it currently requires the argument type to be exactly 'PyObject *'. As a result, pointers to subclasses of 'PyObject' must be explicitly cast before being passed, making call sites unnecessarily verbose. This patch makes ref_ptr<T,Policy>::new_reference() a template method that accepts both T and subclasses of T, performing the cast to 'T *' internally when needed. This removes redundant casts at call sites without changing behavior. Approved-By: Tom Tromey <tom@tromey.com>
2026-03-10gdb: introduce rgb_color type to simplify existing codeMatthieu Longo1-6/+4
This patch replaces the raw uint8[3] buffer used to represent RGB values with a more convenient wrapper, rgb_color, around std::array<uint8_t, 3>. It also changes the return type of ui_file_style::color::get_rgb to rgb_color instead of filling a caller-provided buffer, and updates all callers accordingly. This expected benefit of this change consists in: - removing the manual size handling. - proving accessors without using hard-coded indexes. - making the API safer. - simplifying call sites. This refactoring does not introduce any functional change. Approved-By: Tom Tromey <tom@tromey.com>
2026-03-09gdb/python: accept gdbpy_ref in init helpers and return boolMatthieu Longo2-26/+23
Passing 'gdbpy_ref<> &' instead of raw 'PyObject *' to init helpers makes ownership of PyObject clearer at call sites, and removes unnecessary '.get()' calls. Changing the return type from 'int' to 'bool' improves readability and better expresses the success/failure semantics. Approved-By: Tom Tromey <tom@tromey.com>
2026-03-05gdb/python: fix gdb.FinishBreakpoint returning to a tail call frameAndrew Burgess1-0/+3
I noticed that gdb.FinishBreakpoint doesn't work if the parent function is a tail call function. In bpfinishpy_init we use get_frame_pc to find the address at which the finish breakpoint should be placed within the previous frame. However, if the previous frame is a tail call frame, then get_frame_pc will return an address outside of the tail call function, an address which will not be reached on the return path. Unlike other recent tail call fixes I've made, we cannot switch to using something like get_frame_address_in_block here as in the tail call case this will return an address within the function, but not an address that will be executed when we return. What we need to do in the tail call case is create the finish breakpoint in the frame that called the tail call function. Or if that frame is itself a tail call, then we should walk back up the call stack until we find a non-tail call function. This can be achieved by adding a call to skip_tailcall_frames into bpfinishpy_init after our existing call to get_prev_frame. I've extended the existing test case to cover this additional situation. Approved-By: Tom Tromey <tom@tromey.com>
2026-03-05gdb/python: don't allow FinishBreakpoints for inline framesAndrew Burgess1-1/+7
Creating a Python gdb.FinishBreakpoint for an inline frame doesn't work. If we look at the 'finish' command, in the finish_command function (infcmd.c) then we see that GDB handles inline frames very different to non-inline frames. For non-inline frames GDB creates a temporary breakpoint and then resumes the inferior until the breakpoint is hit. But for inline frames, GDB steps forward until we have left the inline frame. When it comes to gdb.FinishBreakpoint we only have the "create a temporary breakpoint" mechanism; that is, after all, what the FinishBreakpoint is, it's a temporary breakpoint placed at the return address in the caller. Currently, when a FinishBreakpoint is created within an inline frame, GDB ends up creating the breakpoint at the current $pc. As a result the breakpoint will not be hit before the current function exits (unless there's a loop going on, but that's not the point). We could imagine what a solution to this problem would look like, GDB would need to figure out the set of addresses for all possible exit points from the inline function, and place a breakpoint at each of these locations. I don't propose doing that in this commit. Instead, I plan to update the docs to note that creating a FinishBreakpoint within an inline frame is not allowed, and I will catch this case within bpfinishpy_init (python/py-finishbreakpoint.c) and throw an error. Though the error is new, all I'm doing is raising an error for a case that never worked. There's a new test to cover this case. Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=18339 Reviewed-By: Eli Zaretskii <eliz@gnu.org> Approved-By: Tom Tromey <tom@tromey.com>
2026-03-05gdb/python: fix FinishBreakpoint.return_value for tail call functionsAndrew Burgess1-3/+3
The FinishBreakpoint.return_value attribute will not be populated correctly for tail call functions. In bpfinishpy_init (python/py-finishbreakpoint.c) we use the function get_frame_pc_if_available to return an address, and then use this address to lookup a function symbol. The problem is that, for tail call functions, the address returned by get_frame_pc_if_available can be outside the bounds of the function, as a result GDB might find no function symbol at all, or might find the wrong function symbol, if the tail call function is immediately adjacent to the next function. Fix this by using get_frame_address_in_block_if_available instead. For tail call functions this will return an address within the bounds of the function, which means that GDB should find the correct function symbol, and from this the correct return type. I've extended the existing FinishBreakpoint with tail call test case to include printing the return value, this test fails without this patch, but now works. Approved-By: Tom Tromey <tom@tromey.com>
2026-03-05gdb/python: introduce gdb.Symtab.source_lines methodAndrew Burgess3-5/+123
This commit adds a new method gdb.Symtab.source_lines. This method can be used to read the lines from a symtab's source file. This is similar to GDB's internal source_cache::get_source_lines function. Currently using the Python API, if a user wants to display source lines then they need to use Symtab.fullname() to get the source file name, then open this file and parse out the lines themselves. This isn't too much effort, but the problem is that these lines will not be styled. The user could style the source content themselves, but will this be styled exactly as GDB would style it? The new Symtab.source_lines() method returns source lines with styling included (as ANSI terminal escape sequences), assuming of course, that styling is currently enabled. Of course, in some cases, a user of the Python API might want source code without styling. That's supported too, the new method has an 'unstyled' argument. If this is True then the output is forced to be unstyled. The argument is named 'unstyled' rather than 'styled' because the API call cannot force styling on. If 'set style enabled off' is in effect then making the API call will never return styled source lines. The new API call allows for a range of lines to be requested if desired. As part of this commit I've updated the host_string_to_python_string utility function to take a std::string_view. Reviewed-By: Eli Zaretskii <eliz@gnu.org> Approved-By: Tom Tromey <tom@tromey.com>
2026-03-05gdb/python: new selected_context eventAndrew Burgess3-0/+60
This commit introduces a new Python event, selected_context. This event is attached to the user_selected_context_changed observer, which triggers when the user changes the currently selected inferior, thread, or frame. Adding this event allows a Python extension to update in response to user driven changes without having to poll the state from a before_prompt hook, which is what I currently do to achieve the same results. I did consider splitting the user_selected_context_changed observer into 3 separate Python events, inferior_changed, thread_changed, and frame_changed, but I couldn't see any significant advantage to doing this, so in the end I went with just a single event, and the event object contains the inferior, thread, and frame. Additionally, the user isn't informed about which aspect of the context changed. That is, every event carries the inferior, thread, and frame, so an event triggered when switching frames will looks identical to an event triggered when switching inferiors. If the user wants to know what changed then they will have to track the current state themselves, and then compare the event state to the stored current state. In many cases though I suspect that just being told something changed, and then updating everything will be sufficient, which is why I've not bothered trying to inform the user what changed. Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=24482 Reviewed-By: Eli Zaretskii <eliz@gnu.org> Approved-By: Tom Tromey <tom@tromey.com>
2026-03-04Use ref_ptr upcasts in Python codeTom Tromey5-7/+6
In some spots the Python code will do an explicit upcast of gdbpy_ref, like: return gdbpy_ref<> ((PyObject *) color_obj.release ()); Now that ref_ptr allows upcasts, and because gdb's Python objects derive from PyObject, these reshufflings can be expressed more simply. Approved-By: Andrew Burgess <aburgess@redhat.com>
2026-03-04Don't use template for gdbpy_ref_policyTom Tromey1-9/+5
Now that gdb's Python types derive from PyObject, there's no need to use a template for gdbpy_ref_policy. This simplifies the code a tiny bit. Approved-By: Andrew Burgess <aburgess@redhat.com>
2026-03-04gdb: switch bytes object helpers to Python limited API equivalentsMatthieu Longo1-2/+3
* PyBytes_AS_STRING -> PyBytes_AsString * PyBytes_GET_SIZE -> PyBytes_Size Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=23830 Approved-By: Tom Tromey <tom@tromey.com>
2026-03-04gdb: switch tuple object helpers to Python limited API equivalentsMatthieu Longo9-33/+53
* 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>
2026-02-27Use the "O!" format more in the Python codeTom Tromey4-26/+8
I noticed a few spots in the Python code that were decoding method arguments and then immediately type-checking an argument. This can be done more concisely using the "O!" format. Reviewed-By: Tom de Vries <tdevries@suse.de>
2026-02-27gdb: switch sequence protocol helpers to Python limited API equivalentsMatthieu Longo2-2/+2
* PySequence_ITEM -> PySequence_GetItem Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=23830 Approved-By: Tom Tromey <tom@tromey.com>
2026-02-23gdb/python: remove some unreachable Py_RETURN_NONESimon Marchi3-10/+0
They are unreachable because there is a return statement in all possible code paths before. Change-Id: I9db2f41f8017380c0c79f97af9bbf8734038ba9a Approved-By: Tom Tromey <tom@tromey.com>
2026-02-23Return gdbpy_ref<> from gdbpy_registry::lookupTom Tromey4-23/+21
This changes gdbpy_registry::lookup to return a gdbpy_ref<>, using the type system to convey that a new reference is always returned. Approved-By: Simon Marchi <simon.marchi@efficios.com>
2026-02-23Return gdbpy_ref<> from gdbarch_to_arch_objectTom Tromey7-8/+8
This changes gdbarch_to_arch_object to return a gdbpy_ref<>, using the type system to convey that a new reference is always returned. Approved-By: Simon Marchi <simon.marchi@efficios.com>
2026-02-23Return gdbpy_ref<> from symtab_to_linetable_objectTom Tromey3-4/+4
This changes symtab_to_linetable_object to return a gdbpy_ref<>, using the type system to convey that a new reference is always returned. Approved-By: Simon Marchi <simon.marchi@efficios.com>
2026-02-23Return gdbpy_ref<> from frame_info_to_frame_objectTom Tromey4-20/+14
This changes frame_info_to_frame_object to return a gdbpy_ref<>, using the type system to convey that a new reference is always returned. Approved-By: Simon Marchi <simon.marchi@efficios.com>
2026-02-23Return gdbpy_ref<> from type_to_type_objectTom Tromey8-32/+31
This changes type_to_type_object to return a gdbpy_ref<>, using the type system to convey that a new reference is always returned. Approved-By: Simon Marchi <simon.marchi@efficios.com>
2026-02-23Return gdbpy_ref<> from value_to_value_objectTom Tromey13-66/+64
This changes value_to_value_object to return a gdbpy_ref<>, using the type system to convey that a new reference is always returned. Approved-By: Simon Marchi <simon.marchi@efficios.com>
2026-02-23Return gdbpy_ref<> from block_to_block_objectTom Tromey6-20/+18
This changes block_to_block_object to return a gdbpy_ref<>, using the type system to convey that a new reference is always returned. Approved-By: Simon Marchi <simon.marchi@efficios.com>
2026-02-23Return gdbpy_ref<> from symtab_to_symtab_objectTom Tromey3-6/+6
This changes symtab_to_symtab_object to return a gdbpy_ref<>, using the type system to convey that a new reference is always returned. Approved-By: Simon Marchi <simon.marchi@efficios.com>
2026-02-23Return gdbpy_ref<> from symbol_to_symbol_objectTom Tromey8-39/+32
This changes symbol_to_symbol_object to return a gdbpy_ref<>, using the type system to convey that a new reference is always returned. Approved-By: Simon Marchi <simon.marchi@efficios.com>
2026-02-23Return gdbpy_ref<> from symtab_and_line_to_sal_objectTom Tromey7-22/+12
This changes symtab_and_line_to_sal_object to return a gdbpy_ref<>, using the type system to convey that a new reference is always returned. Approved-By: Simon Marchi <simon.marchi@efficios.com>
2026-02-13gdb/gdbserver: move argument setting complexity into gdbsupport/Andrew Burgess1-5/+2
This commit removes some uses of gdb::argv_vec from GDB. The gdb::argv_vec class exists in part due to our need to convert from one container type to another in a few places, and I think by using templates we can push this conversion down into gdbsupport/common-inferior.{cc,h} and remove the conversion logic from higher level code in GDB. This should make core GDB simpler. For examples of this simplification, see python/py-inferior.c, remote.c, and unittests/remote-arg-selftests.c, where this commit has allowed for the removal of some code that only exists in order to convert the container type. Ideally I'd like to see all uses of gdb::argv_vec removed, but I'm still not sure about the use in nat/fork-inferior.c, I think its use there might be the best solution, so for now at least, I have no plans to touch that code. There should be no user visible changes after this commit. Approved-By: Tom Tromey <tom@tromey.com>
2026-02-09gdb/registry: add registry::key::try_emplaceSimon Marchi3-14/+3
We have many times the pattern: current_source_location *loc = current_source_key.get (pspace); if (loc == nullptr) loc = current_source_key.emplace (pspace); return loc; I thought it would be nice to have it directly part of registry::key. Add a try_emplace method, which is like emplace, except that it returns the existing data, if any. The try_emplace name comes from similar methods in std::map or gdb::unordered_map (ankerl::unordered_dense::map). Replace as many callers as I could find to use it. Change-Id: I21f922ca065a354f041caaf70484d6cfbcbb76ed Approved-By: Tom Tromey <tom@tromey.com>
2026-02-09gdb/registry: make registry::key::emplace return a referenceSimon Marchi2-2/+2
Since we use C++ and not C, I think that we should gradually move to using references for things that can never be nullptr. One example of this is the return value of the emplace method. Change it to return a reference, and (to keep the patch straightforward) update all callers to take the address. More patches could follow to propagate the use of references further. Change-Id: I725539694cf496f8288918cc29d7aaae9aca2292 Approved-By: Tom Tromey <tom@tromey.com>
2026-02-09Rewrite output redirection and loggingTom Tromey1-8/+2
This patch changes how gdb output redirection is done. Currently, output is done via the UI. gdb_stdout, for example, is a define the expands to an lvalue referencing a field in the current UI. When redirecting, this field may temporarily be reset; and when logging is enabled or disabled, this is also done. This has lead to bugs where the combination of redirection and logging results in use-after-free. Crashes are readily observable; see the new test cases. This patch upends this. Now, gdb_stdout is simply an rvalue, and refers to the current interpreter. The interpreter provides ui_files that do whatever rewriting is needed (mostly for MI); then output is forward to the current UI via an indirection (see the new ui::passthrough_file). The ui provides paging, logging, timestamps, and the final stream that writes to an actual file descriptor. Redirection is handled at the ui layer. Rather than changing the output pipeline, new ui_files are simply swapped in by rewriting pointers, hopefully with a scoped_restore. Redirecting at the ui layer means that interpreter rewriting is still applied when capturing output. This fixes one of the reported bugs. Not changing the pipeline means that the problems with the combination of redirect and logging simply vanish. Logging just changes a flag and doesn't involve object destruction. Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=17697 Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=28620 Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=28798 Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=28948 Approved-By: Andrew Burgess <aburgess@redhat.com>
2026-02-09Remove m_applied_style from ui_fileTom Tromey1-2/+3
While working on this series, I found a number of odd styling issues recurred. For instance, the issue where the pager would lose track and style subsequent output incorrectly reappeared. It turned out that different ui_file objects in the output pipeline would get confused about their current style. And, looking deeper at this, I realized that mainly it is the pager that really needs to track the current style at all. All the other file implementations can be purely reactive (except the buffered stream code, as Andrew pointed out). This patch moves m_applied_style from ui_file and into pager_file. This necessitated making ui_file::vprintf virtual, so that the base class could pass in the "plain" style as the starting point, whereas the pager could use the applied style. (I did not investigate whether this was truly necessary, and I somewhat suspect it might not be.) This straightforward approach caused some regressions, mostly involving extra ANSI escapes being emitted. I fixed most of these by arranging for ui_out::call_do_message to track styles a little more thoroughly. Co-Authored-By: Andrew Burgess <aburgess@redhat.com> Approved-By: Andrew Burgess <aburgess@redhat.com>
2026-01-29[gdb/python] Fix whitespace in py-ref.hTom de Vries1-1/+1
Fix a whitespace problem pre-commit complains about: ... check-whitespace........................................................Failed - hook id: check-whitespace - exit code: 2 gdb/python/py-ref.h:58: indent with spaces. + "The __dict__ for this object.", nullptr }, ...
2026-01-29gdb: make remaining Python extension objects inherit from PyObjectMatthieu Longo16-62/+37
Previous patches made some Python extension objects ipublicly inherit directly or indirectly from PyObject. In the interest of consistency, this patch makes all remaining Python extension objects still not inheriting from PyObject do so. Approved-By: Tom Tromey <tom@tromey.com>
2026-01-29gdb: cast all Python extension objects passed to gdbpy_ref_policy to PyObject*Matthieu Longo14-49/+25
When enabling the Python limited API, pointers to Python C extension objects can no longer be implicitly converted to 'PyObject *' by the compiler. gdbpy_ref_policy is a templated class that provides a generic interface for incrementing and decrementing the reference counter on the given object. It is used as a specialisation of the policy parameter in gdb::ref_ptr, together with PyObject as the parameter type. As a result, gdbpy_ref_policy always expects an argument derived from PyObject. This patch fixes the resulting compilation issue by adding an explicit static_cast to 'PyObject *' before passing the value to Py_INCREF and Py_DECREF. As a side effect, these casts enforce, at compile time, that the template type passed to gdbpy_ref_policy is a subclass of PyObject. To provide a clearer diagnostic when an incorrect type is used, a static_assert is added to gdbpy_ref_policy, avoiding obscure errors originating from the static_cast. Finally, all C Python extension types passed to gdbpy_ref_policy are updated to inherit from PyObject. Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=23830 Approved-By: Tom Tromey <tom@tromey.com>
2026-01-29gdb: new setters and getters for __dict__, and attributesMatthieu Longo11-108/+184
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>