aboutsummaryrefslogtreecommitdiff
path: root/gdb/thread.c
AgeCommit message (Collapse)AuthorFilesLines
2023-01-01Update copyright year range in header of all files managed by GDBJoel Brobecker1-1/+1
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.
2022-11-24gdb: fix typo in debug output messageAndrew Burgess1-1/+1
Spotted a minor type, a missing ')', in a debug message.
2022-11-17gdb: new $_inferior_thread_count convenience variableAndrew Burgess1-0/+26
Add a new convenience variable $_inferior_thread_count that contains the number of live (non-exited) threads in the current inferior. This can be used in command scripts, or breakpoint conditions, etc to adjust the behaviour for multi-threaded inferiors. This value is only stable in all-stop mode. In non-stop mode, where new threads can be started, and existing threads exit, at any time, this convenience variable can give a different value each time it is evaluated.
2022-10-10gdb: extra debug output in thread.cAndrew Burgess1-0/+9
Add some extra 'threads' debug in a couple of places in thread.c. I've also added an additional gdb_assert in one case.
2022-06-24Revert "Delete delete_thread_silent"Pedro Alves1-5/+23
Turns out we'll be gaining a new use of this function very soon, the incoming AMDGPU port needs it. Let's add it back, as it isn't really hurting anything. This reverts commit 39b8a8090ed7e8967ceca3655aa5f3a2ae91219d.
2022-06-24Delete delete_thread_silentPedro Alves1-23/+5
delete_thread_silent is no longer used anywhere. Delete it. Change-Id: Iafcec12339861d5ab2e29c14d7b1f884c9e11c0f
2022-03-29Unify gdb printf functionsTom Tromey1-24/+24
Now that filtered and unfiltered output can be treated identically, we can unify the printf family of functions. This is done under the name "gdb_printf". Most of this patch was written by script.
2022-03-29Remove some uses of printf_unfilteredTom Tromey1-1/+1
A number of spots call printf_unfiltered only because they are in code that should not be interrupted by the pager. However, I believe these cases are all handled by infrun's blanket ban on paging, and so can be converted to the default (_filtered) API. After this patch, I think all the remaining _unfiltered calls are ones that really ought to be. A few -- namely in complete_command -- could be replaced by a scoped assignment to pagination_enabled, but for the remainder, the code seems simple enough like this.
2022-03-06gdb: remove internalvar_funcs::destroySimon Marchi1-2/+0
No kind of internal var uses it remove it. This makes the transition to using a variant easier, since we don't need to think about where this should be called (in a destructor or not), if it can throw, etc. Change-Id: Iebbc867d1ce6716480450d9790410d6684cbe4dd
2022-02-07gdb: make thread_info::m_thread_fsm a std::unique_ptrLancelot SIX1-4/+3
While working on function calls, I realized that the thread_fsm member of struct thread_info is a raw pointer to a resource it owns. This commit changes the type of the thread_fsm member to a std::unique_ptr in order to signify this ownership relationship and slightly ease resource management (no need to manually call delete). To ensure consistent use, the field is made a private member (m_thread_fsm). The setter method (set_thread_fsm) can then check that it is incorrect to associate a FSM to a thread_info object if another one is already in place. This is ensured by an assertion. The function run_inferior_call takes an argument as a pointer to a call_thread_fsm and installs it in it in a thread_info instance. Also change this function's signature to accept a unique_ptr in order to signify that the ownership of the call_thread_fsm is transferred during the call. No user visible change expected after this commit. Tested on x86_64-linux with no regression observed. Change-Id: Ia1224f72a4afa247801ce6650ce82f90224a9ae8
2022-01-18Move gdb_regex to gdbsupportTom Tromey1-1/+1
This moves the gdb_regex convenience class to gdbsupport.
2022-01-18gdb: use ptid_t::to_string instead of target_pid_to_str in debug statementsSimon Marchi1-2/+2
Same idea as 0fab79556484 ("gdb: use ptid_t::to_string in infrun debug messages"), but throughout GDB. Change-Id: I62ba36eaef29935316d7187b9b13d7b88491acc1
2022-01-13gdb: add some extra debug information to attach_commandAndrew Burgess1-0/+20
While working on another patch I wanted to add some extra debug information to the attach_command function. This required me to add a new function to convert the thread_info::state variable to a string. The new debug might be useful to others, and the state to string function might be useful in other locations, so I thought I'd merge it.
2022-01-01Automatic Copyright Year update after running gdb/copyright.pyJoel Brobecker1-1/+1
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.
2021-12-22gdb: add threads debugging switchAndrew Burgess1-0/+38
Add new commands: set debug threads on|off show debug threads Prints additional debug information relating to thread creation and deletion. GDB already announces when threads are created of course.... most of the time, but sometimes threads are added silently, in which case this debug message is the only mechanism to see the thread being added. Also, though GDB does announce when a thread exits, it doesn't announce when the thread object is deleted, I've added a debug message for that. Additionally, having message printed through the debug system will cause the messages to be nested to an appropriate depth when other debug sub-systems are turned on (especially things like `infrun` and `lin-lwp`).
2021-12-02Implement 'task apply'Tom Tromey1-15/+16
This adds a 'task apply' command, which is the Ada tasking analogue of 'thread apply'. Unlike 'thread apply', it doesn't offer the 'ascending' flag; but otherwise it's essentially the same.
2021-10-21gdb, gdbserver: make target_waitstatus safeSimon Marchi1-3/+1
I stumbled on a bug caused by the fact that a code path read target_waitstatus::value::sig (expecting it to contain a gdb_signal value) while target_waitstatus::kind was TARGET_WAITKIND_FORKED. This meant that the active union field was in fact target_waitstatus::value::related_pid, and contained a ptid. The read signal value was therefore garbage, and that caused GDB to crash soon after. Or, since that GDB was built with ubsan, this nice error message: /home/simark/src/binutils-gdb/gdb/linux-nat.c:1271:12: runtime error: load of value 2686365, which is not a valid value for type 'gdb_signal' Despite being a large-ish change, I think it would be nice to make target_waitstatus safe against that kind of bug. As already done elsewhere (e.g. dynamic_prop), validate that the type of value read from the union matches what is supposed to be the active field. - Make the kind and value of target_waitstatus private. - Make the kind initialized to TARGET_WAITKIND_IGNORE on target_waitstatus construction. This is what most users appear to do explicitly. - Add setters, one for each kind. Each setter takes as a parameter the data associated to that kind, if any. This makes it impossible to forget to attach the associated data. - Add getters, one for each associated data type. Each getter validates that the data type fetched by the user matches the wait status kind. - Change "integer" to "exit_status", "related_pid" to "child_ptid", just because that's more precise terminology. - Fix all users. That last point is semi-mechanical. There are a lot of obvious changes, but some less obvious ones. For example, it's not possible to set the kind at some point and the associated data later, as some users did. But in any case, the intent of the code should not change in this patch. This was tested on x86-64 Linux (unix, native-gdbserver and native-extended-gdbserver boards). It was built-tested on x86-64 FreeBSD, NetBSD, MinGW and macOS. The rest of the changes to native files was done as a best effort. If I forgot any place to update in these files, it should be easy to fix (unless the change happens to reveal an actual bug). Change-Id: I0ae967df1ff6e28de78abbe3ac9b4b2ff4ad03b7
2021-10-09[gdb] Make execute_command_to_string return string on throwTom de Vries1-2/+3
The pattern for using execute_command_to_string is: ... std::string output; output = execute_fn_to_string (fn, term_out); ... This results in a problem when using it in a try/catch: ... try { output = execute_fn_to_string (fn, term_out) } catch (const gdb_exception &e) { /* Use output. */ } ... If an expection was thrown during execute_fn_to_string, then the output remains unassigned, while it could be worthwhile to known what output was generated by gdb before the expection was thrown. Fix this by returning the string using a parameter instead: ... execute_fn_to_string (output, fn, term_out) ... Also add a variant without string parameter, to support places where the function is used while ignoring the result: ... execute_fn_to_string (fn, term_out) ... Tested on x86_64-linux.
2021-09-24gdb: change thread_info::name to unique_xmalloc_ptr, add helper functionSimon Marchi1-13/+23
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
2021-09-08gdb: make thread_suspend_state::stop_pc optionalAndrew Burgess1-1/+1
Currently the stop_pc field of thread_suspect_state is a CORE_ADDR and when we want to indicate that there is no stop_pc available we set this field back to a special value. There are actually two special values used, in post_create_inferior the stop_pc is set to 0. This is a little unfortunate, there are plenty of embedded targets where 0 is a valid pc value. The more common special value for stop_pc though, is set in thread_info::set_executing, where the value (~(CORE_ADDR) 0) is used. This commit changes things so that the stop_pc is instead a gdb::optional. We can now explicitly reset the field to an uninitialised state, we also have asserts that we don't read the stop_pc when its in an uninitialised state (both in gdbsupport/gdb_optional.h, when compiling with _GLIBCXX_DEBUG defined, and in thread_info::stop_pc). One situation where a thread will not have a stop_pc value is when the thread is stopped as a consequence of GDB being in all stop mode, and some other thread stopped at an interesting event. When GDB brings all the other threads to a stop those other threads will not have a stop_pc set (thus avoiding an unnecessary read of the pc register). Previously, when GDB passed through handle_one (in infrun.c) the threads executing flag was set to false and the stop_pc field was left unchanged, i.e. it would (previous) have been left as ~0. Now, handle_one leaves the stop_pc with no value. This caused a problem when we later try to set these threads running again, in proceed() we compare the current pc with the cached stop_pc. If the thread was stopped via handle_one then the stop_pc would have been left as ~0, and the compare (in proceed) would (likely) fail. Now however, this compare tries to read the stop_pc when it has no value and this would trigger an assert. To resolve this I've added thread_info::stop_pc_p() which returns true if the thread has a cached stop_pc. We should only ever call thread_info::stop_pc() if we know that there is a cached stop_pc, however, this doesn't mean that every call to thread_info::stop_pc() needs to be guarded with a call to thread_info::stop_pc_p(), in most cases we know that the thread we are looking at stopped due to some interesting event in that thread, and so, we know that the stop_pc is valid. After running the testsuite I've seen no other situations where stop_pc is read uninitialised. There should be no user visible changes after this commit.
2021-09-07gdb: make thread_info::executing privateAndrew Burgess1-20/+17
Rename thread_info::executing to thread_info::m_executing, and make it private. Add a new get/set member functions, and convert GDB to make use of these. The only real change of interest in this patch is in thread.c where I have deleted the helper function set_executing_thread, and now just use the new set function thread_info::set_executing. However, the old helper function set_executing_thread included some code to reset the thread's stop_pc, so I moved this code into the new function thread_info::set_executing. However, I don't believe there is anywhere that this results in a change of behaviour, previously the executing flag was always set true through a call to set_executing_thread anyway.
2021-08-17gdb: fix thread_step_over_chain_lengthSimon Marchi1-1/+1
If I debug a single-thread program and look at the infrun debug logs, I see: [infrun] start_step_over: stealing global queue of threads to step, length = 2 That makes no sense... turns out there's a buglet in thread_step_over_chain_length, "num" should be initialized to 0. I think this bug is a leftover from an earlier version of the code (not merged upstream) that manually walked the list, where the first item was implicitly counted (hence the 1). Change-Id: I0af03aa93509aed36528be5076894dc156a0b5ce
2021-07-12gdb: maintain ptid -> thread map, optimize find_thread_ptidSimon Marchi1-5/+24
When debugging a large number of threads (thousands), looking up a thread by ptid_t using the inferior::thread_list linked list can add up. Add inferior::thread_map, an std::unordered_map indexed by ptid_t, and change the find_thread_ptid function to look up a thread using std::unordered_map::find, instead of iterating on all of the inferior's threads. This should make it faster to look up a thread from its ptid. Change-Id: I3a8da0a839e18dee5bb98b8b7dbeb7f3dfa8ae1c Co-Authored-By: Pedro Alves <pedro@palves.net>
2021-07-12gdb: maintain per-process-target list of resumed threads with pending wait ↵Simon Marchi1-0/+40
status Looking up threads that are both resumed and have a pending wait status to report is something that we do quite often in the fast path and is expensive if there are many threads, since it currently requires walking whole thread lists. The first instance is in maybe_set_commit_resumed_all_targets. This is called after handling each event in fetch_inferior_event, to see if we should ask targets to commit their resumed threads or not. If at least one thread is resumed but has a pending wait status, we don't ask the targets to commit their resumed threads, because we want to consume and handle the pending wait status first. The second instance is in random_pending_event_thread, where we want to select a random thread among all those that are resumed and have a pending wait status. This is called every time we try to consume events, to see if there are any pending events that we we want to consume, before asking the targets for more events. To allow optimizing these cases, maintain a per-process-target list of threads that are resumed and have a pending wait status. In maybe_set_commit_resumed_all_targets, we'll be able to check in O(1) if there are any such threads simply by checking whether the list is empty. In random_pending_event_thread, we'll be able to use that list, which will be quicker than iterating the list of threads, especially when there are no resumed with pending wait status threads. About implementation details: using the new setters on class thread_info, it's relatively easy to maintain that list. Any time the "resumed" or "pending wait status" property is changed, we check whether that should cause the thread to be added or removed from the list. In set_thread_exited, we try to remove the thread from the list, because keeping an exited thread in that list would make no sense (especially if the thread is freed). My first implementation assumed that a process stratum target was always present when set_thread_exited is called. That's however, not the case: in some cases, targets unpush themselves from an inferior and then call "exit_inferior", which exits all the threads. If the target is unpushed before set_thread_exited is called on the threads, it means we could mistakenly leave some threads in the list. I tried to see how hard it would be to make it such that targets have to exit all threads before unpushing themselves from the inferior (that would seem logical to me, we don't want threads belonging to an inferior that has no process target). That seemed quite difficult and not worth the time at the moment. Instead, I changed inferior::unpush_target to remove all threads of that inferior from the list. As of this patch, the list is not used, this is done in the subsequent patches. The debug messages in process-stratum-target.c need to print some ptids. However, they can't use target_pid_to_str to print them without introducing a dependency on the current inferior (the current inferior is used to get the current target stack). For debug messages, I find it clearer to print the spelled out ptid anyway (the pid, lwp and tid values). Add a ptid_t::to_string method that returns a string representation of the ptid that is meant for debug messages, a bit like we already have frame_id::to_string. Change-Id: Iad8f93db2d13984dd5aa5867db940ed1169dbb67
2021-07-12gdb: make thread_info::suspend private, add getters / settersSimon Marchi1-2/+23
A following patch will want to take some action when a pending wait status is set on or removed from a thread. Add a getter and a setter on thread_info for the pending waitstatus, so that we can add some code in the setter later. The thing is, the pending wait status field is in the thread_suspend_state, along with other fields that we need to backup before and restore after the thread does an inferior function call. Therefore, make the thread_suspend_state member private (thread_info::suspend becomes thread_info::m_suspend), and add getters / setters for all of its fields: - pending wait status - stop signal - stop reason - stop pc For the pending wait status, add the additional has_pending_waitstatus and clear_pending_waitstatus methods. I think this makes the thread_info interface a bit nicer, because we now access the fields as: thread->stop_pc () rather than thread->suspend.stop_pc The stop_pc field being in the `suspend` structure is an implementation detail of thread_info that callers don't need to be aware of. For the backup / restore of the thread_suspend_state structure, add save_suspend_to and restore_suspend_from methods. You might wonder why `save_suspend_to`, as opposed to a simple getter like thread_suspend_state &suspend (); I want to make it clear that this is to be used only for backing up and restoring the suspend state, _not_ to access fields like: thread->suspend ()->stop_pc Adding some getters / setters allows adding some assertions. I find that this helps understand how things are supposed to work. Add: - When getting the pending status (pending_waitstatus method), ensure that there is a pending status. - When setting a pending status (set_pending_waitstatus method), ensure there is no pending status. There is one case I found where this wasn't true - in remote_target::process_initial_stop_replies - which needed adjustments to respect that contract. I think it's because process_initial_stop_replies is kind of (ab)using the thread_info::suspend::waitstatus to store some statuses temporarily, for its internal use (statuses it doesn't intent on leaving pending). process_initial_stop_replies pulls out stop replies received during the initial connection using target_wait. It always stores the received event in `evthread->suspend.waitstatus`. But it only sets waitstatus_pending_p, if it deems the event interesting enough to leave pending, to be reported to the core: if (ws.kind != TARGET_WAITKIND_STOPPED || ws.value.sig != GDB_SIGNAL_0) evthread->suspend.waitstatus_pending_p = 1; It later uses this flag a bit below, to choose which thread to make the "selected" one: if (selected == NULL && thread->suspend.waitstatus_pending_p) selected = thread; And ultimately that's used if the user-visible mode is all-stop, so that we print the stop for that interesting thread: /* In all-stop, we only print the status of one thread, and leave others with their status pending. */ if (!non_stop) { thread_info *thread = selected; if (thread == NULL) thread = lowest_stopped; if (thread == NULL) thread = first; print_one_stopped_thread (thread); } But in any case (all-stop or non-stop), print_one_stopped_thread needs to access the waitstatus value of these threads that don't have a pending waitstatus (those that had TARGET_WAITKIND_STOPPED + GDB_SIGNAL_0). This doesn't work with the assertions I've put. So, change the code to only set the thread's wait status if it is an interesting one that we are going to leave pending. If the thread stopped due to a non-interesting event (TARGET_WAITKIND_STOPPED + GDB_SIGNAL_0), don't store it. Adjust print_one_stopped_thread to understand that if a thread has no pending waitstatus, it's because it stopped with TARGET_WAITKIND_STOPPED + GDB_SIGNAL_0. The call to set_last_target_status also uses the pending waitstatus. However, given that the pending waitstatus for the thread may have been cleared in print_one_stopped_thread (and that there might not even be a pending waitstatus in the first place, as explained above), it is no longer possible to do it at this point. To fix that, move the call to set_last_target_status in print_one_stopped_thread. I think this will preserve the existing behavior, because set_last_target_status is currently using the current thread's wait status. And the current thread is the last one for which print_one_stopped_thread is called. So by calling set_last_target_status in print_one_stopped_thread, we'll get the same result. set_last_target_status will possibly be called multiple times, but only the last call will matter. It just means possibly more calls to set_last_target_status, but those are cheap. Change-Id: Iedab9653238eaf8231abcf0baa20145acc8b77a7
2021-07-12gdb: add setter / getter for thread_info resumed stateSimon Marchi1-1/+1
A following patch will want to do things when a thread's resumed state changes. Make the `resumed` field private (renamed to `m_resumed`) and add a getter and a setter for it. The following patch in question will therefore be able to add some code to the setter. Change-Id: I360c48cc55a036503174313261ce4e757d795319
2021-07-12gdb: use intrusive list for step-over chainSimon Marchi1-94/+12
The threads that need a step-over are currently linked using an hand-written intrusive doubly-linked list, so that seems a very good candidate for intrusive_list, convert it. For this, we have a use case of appending a list to another one (in start_step_over). Based on the std::list and Boost APIs, add a splice method. However, only support splicing the other list at the end of the `this` list, since that's all we need. Add explicit default assignment operators to reference_to_pointer_iterator, which are otherwise implicitly deleted. This is needed because to define thread_step_over_list_safe_iterator, we wrap reference_to_pointer_iterator inside a basic_safe_iterator, and basic_safe_iterator needs to be able to copy-assign the wrapped iterator. The move-assignment operator is therefore not needed, only the copy-assignment operator is. But for completeness, add both. Change-Id: I31b2ff67c7b78251314646b31887ef1dfebe510c
2021-07-12gdb: make inferior_list use intrusive_listPedro Alves1-1/+5
Change inferior_list, the global list of inferiors, to use intrusive_list. I think most other changes are somewhat obvious fallouts from this change. There is a small change in behavior in scoped_mock_context. Before this patch, constructing a scoped_mock_context would replace the whole inferior list with only the new mock inferior. Tests using two scoped_mock_contexts therefore needed to manually link the two inferiors together, as the second scoped_mock_context would bump the first mock inferior from the thread list. With this patch, a scoped_mock_context adds its mock inferior to the inferior list on construction, and removes it on destruction. This means that tests run with mock inferiors in the inferior list in addition to any pre-existing inferiors (there is always at least one). There is no possible pid clash problem, since each scoped mock inferior uses its own process target, and pids are per process target. Co-Authored-By: Simon Marchi <simon.marchi@efficios.com> Change-Id: I7eb6a8f867d4dcf8b8cd2dcffd118f7270756018
2021-07-12gdb: introduce intrusive_list, make thread_info use itPedro Alves1-46/+15
GDB currently has several objects that are put in a singly linked list, by having the object's type have a "next" pointer directly. For example, struct thread_info and struct inferior. Because these are simply-linked lists, and we don't keep track of a "tail" pointer, when we want to append a new element on the list, we need to walk the whole list to find the current tail. It would be nice to get rid of that walk. Removing elements from such lists also requires a walk, to find the "previous" position relative to the element being removed. To eliminate the need for that walk, we could make those lists doubly-linked, by adding a "prev" pointer alongside "next". It would be nice to avoid the boilerplate associated with maintaining such a list manually, though. That is what the new intrusive_list type addresses. With an intrusive list, it's also possible to move items out of the list without destroying them, which is interesting in our case for example for threads, when we exit them, but can't destroy them immediately. We currently keep exited threads on the thread list, but we could change that which would simplify some things. Note that with std::list, element removal is O(N). I.e., with std::list, we need to walk the list to find the iterator pointing to the position to remove. However, we could store a list iterator inside the object as soon as we put the object in the list, to address it, because std::list iterators are not invalidated when other elements are added/removed. However, if you need to put the same object in more than one list, then std::list<object> doesn't work. You need to instead use std::list<object *>, which is less efficient for requiring extra memory allocations. For an example of an object in multiple lists, see the step_over_next/step_over_prev fields in thread_info: /* Step-over chain. A thread is in the step-over queue if these are non-NULL. If only a single thread is in the chain, then these fields point to self. */ struct thread_info *step_over_prev = NULL; struct thread_info *step_over_next = NULL; The new intrusive_list type gives us the advantages of an intrusive linked list, while avoiding the boilerplate associated with manually maintaining it. intrusive_list's API follows the standard container interface, and thus std::list's interface. It is based the API of Boost's intrusive list, here: https://www.boost.org/doc/libs/1_73_0/doc/html/boost/intrusive/list.html Our implementation is relatively simple, while Boost's is complicated and intertwined due to a lot of customization options, which our version doesn't have. The easiest way to use an intrusive_list is to make the list's element type inherit from intrusive_node. This adds a prev/next pointers to the element type. However, to support putting the same object in more than one list, intrusive_list supports putting the "node" info as a field member, so you can have more than one such nodes, one per list. As a first guinea pig, this patch makes the per-inferior thread list use intrusive_list using the base class method. Unlike Boost's implementation, ours is not a circular list. An earlier version of the patch was circular: the intrusive_list type included an intrusive_list_node "head". In this design, a node contained pointers to the previous and next nodes, not the previous and next elements. This wasn't great for when debugging GDB with GDB, as it was difficult to get from a pointer to the node to a pointer to the element. With the design proposed in this patch, nodes contain pointers to the previous and next elements, making it easy to traverse the list by hand and inspect each element. The intrusive_list object contains pointers to the first and last elements of the list. They are nullptr if the list is empty. Each element's node contains a pointer to the previous and next elements. The first element's previous pointer is nullptr and the last element's next pointer is nullptr. Therefore, if there's a single element in the list, both its previous and next pointers are nullptr. To differentiate such an element from an element that is not linked into a list, the previous and next pointers contain a special value (-1) when the node is not linked. This is necessary to be able to reliably tell if a given node is currently linked or not. A begin() iterator points to the first item in the list. An end() iterator contains nullptr. This makes iteration until end naturally work, as advancing past the last element will make the iterator contain nullptr, making it equal to the end iterator. If the list is empty, a begin() iterator will contain nullptr from the start, and therefore be immediately equal to the end. Iterating on an intrusive_list yields references to objects (e.g. `thread_info&`). The rest of GDB currently expects iterators and ranges to yield pointers (e.g. `thread_info*`). To bridge the gap, add the reference_to_pointer_iterator type. It is used to define inf_threads_iterator. Add a Python pretty-printer, to help inspecting intrusive lists when debugging GDB with GDB. Here's an example of the output: (top-gdb) p current_inferior_.m_obj.thread_list $1 = intrusive list of thread_info = {0x61700002c000, 0x617000069080, 0x617000069400, 0x61700006d680, 0x61700006eb80} It's not possible with current master, but with this patch [1] that I hope will be merged eventually, it's possible to index the list and access the pretty-printed value's children: (top-gdb) p current_inferior_.m_obj.thread_list[1] $2 = (thread_info *) 0x617000069080 (top-gdb) p current_inferior_.m_obj.thread_list[1].ptid $3 = { m_pid = 406499, m_lwp = 406503, m_tid = 0 } Even though iterating the list in C++ yields references, the Python pretty-printer yields pointers. The reason for this is that the output of printing the thread list above would be unreadable, IMO, if each thread_info object was printed in-line, since they contain so much information. I think it's more useful to print pointers, and let the user drill down as needed. [1] https://sourceware.org/pipermail/gdb-patches/2021-April/178050.html Co-Authored-By: Simon Marchi <simon.marchi@efficios.com> Change-Id: I3412a14dc77f25876d742dab8f44e0ba7c7586c0
2021-05-27gdb: make add_com_alias accept target as a cmd_list_elementSimon Marchi1-4/+5
The alias creation functions currently accept a name to specify the target command. They pass this to add_alias_cmd, which needs to lookup the target command by name. Given that: - We don't support creating an alias for a command before that command exists. - We always use add_info_alias just after creating that target command, and therefore have access to the target command's cmd_list_element. ... change add_com_alias to accept the target command as a cmd_list_element (other functions are done in subsequent patches). This ensures we don't create the alias before the target command, because you need to get the cmd_list_element from somewhere when you call the alias creation function. And it avoids an unecessary command lookup. So it seems better to me in every aspect. gdb/ChangeLog: * command.h (add_com_alias): Accept target as cmd_list_element. Update callers. Change-Id: I24bed7da57221cc77606034de3023fedac015150
2021-05-19gdb: Pass std::strings to ui_out::field_string () where convenientMarco Barisione1-2/+1
While adding a ui_out::text () overload accepting a std::string, I noticed that several callers of ui_out::field_string () were converting std::string instances to char pointers even if not necessary. gdb/ChangeLog: * ui-out.c (ui_out::field_string): Add missing style_argument to the overload accepting a std::string, to make it equivalent to the char pointer version. * ui-out.h (class ui_out): Ditto. * break-catch-sig.c (signal_catchpoint_print_one): Do not convert std::strings to char pointers before passing them to ui_out::field_string (). * break-catch-throw.c (print_one_detail_exception_catchpoint): Ditto. * cli/cli-setshow.c (do_show_command): Ditto. * disasm.c (gdb_pretty_print_disassembler::pretty_print_insn): Ditto. * infcmd.c (print_return_value_1): Ditto. * inferior.c (print_inferior): Ditto. * linux-thread-db.c (info_auto_load_libthread_db): Ditto. * mi/mi-cmd-var.c (print_varobj): Ditto. (mi_cmd_var_set_format): Ditto. (mi_cmd_var_info_type): Ditto. (mi_cmd_var_info_expression): Ditto. (mi_cmd_var_evaluate_expression): Ditto. (mi_cmd_var_assign): Ditto. (varobj_update_one): Ditto. * mi/mi-main.c (list_available_thread_groups): Ditto. (mi_cmd_data_read_memory_bytes): Ditto. (mi_cmd_trace_frame_collected): Ditto. * osdata.c (info_osdata): Ditto. * probe.c (info_probes_for_spops): Ditto. * target-connection.c (print_connection): Ditto. * thread.c (print_thread_info_1): Ditto. * tracepoint.c (print_one_static_tracepoint_marker): Ditto.
2021-05-19gdb: Add an overloaded ui_out::text accepting a const std::string &Marco Barisione1-1/+1
gdb/ChangeLog: * ui-out.h (class ui_out): Add ui_out::text accepting a constant reference to a std::string. Fix all callers using std::string::c_str. * ui-out.c (ui_out::text): Ditto.
2021-05-12gdb: generate the prefix name for prefix commands on demandMarco Barisione1-2/+2
Previously, the prefixname field of struct cmd_list_element was manually set for prefix commands. This seems verbose and error prone as it required every single call to functions adding prefix commands to specify the prefix name while the same information can be easily generated. Historically, this was not possible as the prefix field was null for many commands, but this was fixed in commit 3f4d92ebdf7f848b5ccc9e8d8e8514c64fde1183 by Philippe Waroquiers, so we can rely on the prefix field being set when generating the prefix name. This commit also fixes a use after free in this scenario: * A command gets created via Python (using the gdb.Command class). The prefix name member is dynamically allocated. * An alias to the new command is created. The alias's prefixname is set to point to the prefixname for the original command with a direct assignment. * A new command with the same name as the Python command is created. * The object for the original Python command gets freed and its prefixname gets freed as well. * The alias is updated to point to the new command, but its prefixname is not updated so it keeps pointing to the freed one. gdb/ChangeLog: * command.h (add_prefix_cmd): Remove the prefixname argument as it can now be generated automatically. Update all callers. (add_basic_prefix_cmd): Ditto. (add_show_prefix_cmd): Ditto. (add_prefix_cmd_suppress_notification): Ditto. (add_abbrev_prefix_cmd): Ditto. * cli/cli-decode.c (add_prefix_cmd): Ditto. (add_basic_prefix_cmd): Ditto. (add_show_prefix_cmd): Ditto. (add_prefix_cmd_suppress_notification): Ditto. (add_prefix_cmd_suppress_notification): Ditto. (add_abbrev_prefix_cmd): Ditto. * cli/cli-decode.h (struct cmd_list_element): Replace the prefixname member variable with a method which generates the prefix name at runtime. Update all code reading the prefix name to use the method, and remove all code setting it. * python/py-cmd.c (cmdpy_destroyer): Remove code to free the prefixname member as it's now a method. (cmdpy_function): Determine if the command is a prefix by looking at prefixlist, not prefixname.
2021-03-19Fix any_thread_of_inferiorPedro Alves1-2/+2
Running gdb-term.exp against gdbserver with "maint set target-non-stop on", runs into this: [infrun] fetch_inferior_event: exit [infrun] fetch_inferior_event: enter /home/pedro/gdb/binutils-gdb/src/gdb/thread.c:72: internal-error: thread_info* inferior_thread(): Assertion `current_thread_ != nullptr' failed. A problem internal to GDB has been detected, further debugging may prove unreliable. This is a bug, please report it. For instructions, see: <https://www.gnu.org/software/gdb/bugs/>. FAIL: gdb.base/gdb-sigterm.exp: expect eof #2 (GDB internal error) Resyncing due to internal error. ERROR: : spawn id exp9 not open while executing "expect { -i exp9 -timeout 10 -re "Quit this debugging session\\? \\(y or n\\) $" { send_gdb "n\n" answer incr count } -re "Create ..." ("uplevel" body line 1) invoked from within "uplevel $body" NONE : spawn id exp9 not open ERROR: Could not resync from internal error (timeout) gdb.base/gdb-sigterm.exp: expect eof #2: stepped 0 times UNRESOLVED: gdb.base/gdb-sigterm.exp: 50 SIGTERM passes The assertion fails here: ... #5 0x000055af4b4a7164 in internal_error (file=0x55af4b5e5de8 "/home/pedro/gdb/binutils-gdb/src/gdb/thread.c", line=72, fmt=0x55af4b5e5ce9 "%s: Assertion `%s' failed.") at /home/pedro/gdb/binutils-gdb/src/gdbsupport/errors.cc:55 #6 0x000055af4b25fc43 in inferior_thread () at /home/pedro/gdb/binutils-gdb/src/gdb/thread.c:72 #7 0x000055af4b26177e in any_thread_of_inferior (inf=0x55af4cf874f0) at /home/pedro/gdb/binutils-gdb/src/gdb/thread.c:638 #8 0x000055af4b26eec8 in kill_or_detach (inf=0x55af4cf874f0, from_tty=0) at /home/pedro/gdb/binutils-gdb/src/gdb/top.c:1665 #9 0x000055af4b26f37f in quit_force (exit_arg=0x0, from_tty=0) at /home/pedro/gdb/binutils-gdb/src/gdb/top.c:1767 #10 0x000055af4b2f72a7 in quit () at /home/pedro/gdb/binutils-gdb/src/gdb/utils.c:633 #11 0x000055af4b2f730b in maybe_quit () at /home/pedro/gdb/binutils-gdb/src/gdb/utils.c:657 #12 0x000055af4b1adb74 in ser_base_wait_for (scb=0x55af4d02e460, timeout=0) at /home/pedro/gdb/binutils-gdb/src/gdb/ser-base.c:236 #13 0x000055af4b1adf0f in do_ser_base_readchar (scb=0x55af4d02e460, timeout=0) at /home/pedro/gdb/binutils-gdb/src/gdb/ser-base.c:365 #14 0x000055af4b1ae06d in generic_readchar (scb=0x55af4d02e460, timeout=0, do_readchar=0x55af4b1adeb1 <do_ser_base_readchar(serial*, int)>) at /home/pedro/gdb/binutils-gdb/src/gdb/ser-base.c:444 ... The bug is that any_thread_of_inferior incorrectly assumes that there's always a selected thread. This fixes it. gdb/ChangeLog: * thread.c (any_thread_of_inferior): Check if there's a selected thread before calling inferior_thread(). Change-Id: Ica4b9ec746121a7a7c22bef09baea72103b3853d
2021-02-22gdb: add asserts in thread codeSimon Marchi1-0/+4
Unlike the previous patch, I don't propose that we take this patch into gdb-10-branch. This patch adds two asserts, prompted by investigating and fixing the bug fixed by the previous patch. The assert in find_thread_ptid would have caught the original issue before the segfault (I think it's slightly more use friendly). The assert in add_thread_silent would have made it clear that the solution proposed in [1] isn't the right one. The solution ended up passing nullptr as a target to add_thread. We don't want that, because add_thread_silent uses it to look up the inferior to which to add the thread. If the target is nullptr, we could find an inferior with the same pid, but belonging to an unrelated target. So we always want a non-nullptr target in add_thread_silent. gdb/ChangeLog: * thread.c (add_thread_silent): Add assert. (find_thread_ptid): Add assert. [1] https://sourceware.org/pipermail/gdb-patches/2021-February/176202.html Change-Id: Ie593ee45c5eb02235e8e9fbcda612d48ce883852
2021-01-28gdb: remove unneeded switch_to_thread from thr_try_catch_cmdAndrew Burgess1-3/+4
I spotted that every time thr_try_catch_cmd is called GDB has already switched to the required thread. The call to switch_to_thread at the head of thr_try_catch_cmd is therefore redundant. This commit replaces the call to switch_to_thread with an assertion that we already have the required thread selected. I also extended the header comment on thr_try_catch_cmd to make it clearer when this function could throw an exception. There should be no user visible changes after this commit. gdb/ChangeLog: * thread.c (thr_try_catch_cmd): Replace swith_to_thread with an assert. Extend the header comment.
2021-01-01Update copyright year range in all GDB filesJoel Brobecker1-1/+1
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.
2020-12-11Remove scoped_inc_dec_refTom Tromey1-34/+7
We can remove scoped_inc_dec_ref by changing the sole user to instead keep a vector of thread_info_ref objects. This removes some manual reference counting and simplifies the code a bit. gdb/ChangeLog 2020-12-11 Tom Tromey <tom@tromey.com> * thread.c (class scoped_inc_dec_ref): Remove. (tp_array_compar_ascending, tp_array_compar_descending): Change parameter types. (thread_apply_all_command): Use thread_info_ref.
2020-12-04gdb: move displaced stepping logic to gdbarch, allow starting concurrent ↵Simon Marchi1-6/+62
displaced steps Today, GDB only allows a single displaced stepping operation to happen per inferior at a time. There is a single displaced stepping buffer per inferior, whose address is fixed (obtained with gdbarch_displaced_step_location), managed by infrun.c. In the case of the AMD ROCm target [1] (in the context of which this work has been done), it is typical to have thousands of threads (or waves, in SMT terminology) executing the same code, hitting the same breakpoint (possibly conditional) and needing to to displaced step it at the same time. The limitation of only one displaced step executing at a any given time becomes a real bottleneck. To fix this bottleneck, we want to make it possible for threads of a same inferior to execute multiple displaced steps in parallel. This patch builds the foundation for that. In essence, this patch moves the task of preparing a displaced step and cleaning up after to gdbarch functions. This allows using different schemes for allocating and managing displaced stepping buffers for different platforms. The gdbarch decides how to assign a buffer to a thread that needs to execute a displaced step. On the ROCm target, we are able to allocate one displaced stepping buffer per thread, so a thread will never have to wait to execute a displaced step. On Linux, the entry point of the executable if used as the displaced stepping buffer, since we assume that this code won't get used after startup. From what I saw (I checked with a binary generated against glibc and musl), on AMD64 we have enough space there to fit two displaced stepping buffers. A subsequent patch makes AMD64/Linux use two buffers. In addition to having multiple displaced stepping buffers, there is also the idea of sharing displaced stepping buffers between threads. Two threads doing displaced steps for the same PC could use the same buffer at the same time. Two threads stepping over the same instruction (same opcode) at two different PCs may also be able to share a displaced stepping buffer. This is an idea for future patches, but the architecture built by this patch is made to allow this. Now, the implementation details. The main part of this patch is moving the responsibility of preparing and finishing a displaced step to the gdbarch. Before this patch, preparing a displaced step is driven by the displaced_step_prepare_throw function. It does some calls to the gdbarch to do some low-level operations, but the high-level logic is there. The steps are roughly: - Ask the gdbarch for the displaced step buffer location - Save the existing bytes in the displaced step buffer - Ask the gdbarch to copy the instruction into the displaced step buffer - Set the pc of the thread to the beginning of the displaced step buffer Similarly, the "fixup" phase, executed after the instruction was successfully single-stepped, is driven by the infrun code (function displaced_step_finish). The steps are roughly: - Restore the original bytes in the displaced stepping buffer - Ask the gdbarch to fixup the instruction result (adjust the target's registers or memory to do as if the instruction had been executed in its original location) The displaced_step_inferior_state::step_thread field indicates which thread (if any) is currently using the displaced stepping buffer, so it is used by displaced_step_prepare_throw to check if the displaced stepping buffer is free to use or not. This patch defers the whole task of preparing and cleaning up after a displaced step to the gdbarch. Two new main gdbarch methods are added, with the following semantics: - gdbarch_displaced_step_prepare: Prepare for the given thread to execute a displaced step of the instruction located at its current PC. Upon return, everything should be ready for GDB to resume the thread (with either a single step or continue, as indicated by gdbarch_displaced_step_hw_singlestep) to make it displaced step the instruction. - gdbarch_displaced_step_finish: Called when the thread stopped after having started a displaced step. Verify if the instruction was executed, if so apply any fixup required to compensate for the fact that the instruction was executed at a different place than its original pc. Release any resources that were allocated for this displaced step. Upon return, everything should be ready for GDB to resume the thread in its "normal" code path. The displaced_step_prepare_throw function now pretty much just offloads to gdbarch_displaced_step_prepare and the displaced_step_finish function offloads to gdbarch_displaced_step_finish. The gdbarch_displaced_step_location method is now unnecessary, so is removed. Indeed, the core of GDB doesn't know how many displaced step buffers there are nor where they are. To keep the existing behavior for existing architectures, the logic that was previously implemented in infrun.c for preparing and finishing a displaced step is moved to displaced-stepping.c, to the displaced_step_buffer class. Architectures are modified to implement the new gdbarch methods using this class. The behavior is not expected to change. The other important change (which arises from the above) is that the core of GDB no longer prevents concurrent displaced steps. Before this patch, start_step_over walks the global step over chain and tries to initiate a step over (whether it is in-line or displaced). It follows these rules: - if an in-line step is in progress (in any inferior), don't start any other step over - if a displaced step is in progress for an inferior, don't start another displaced step for that inferior After starting a displaced step for a given inferior, it won't start another displaced step for that inferior. In the new code, start_step_over simply tries to initiate step overs for all the threads in the list. But because threads may be added back to the global list as it iterates the global list, trying to initiate step overs, start_step_over now starts by stealing the global queue into a local queue and iterates on the local queue. In the typical case, each thread will either: - have initiated a displaced step and be resumed - have been added back by the global step over queue by displaced_step_prepare_throw, because the gdbarch will have returned that there aren't enough resources (i.e. buffers) to initiate a displaced step for that thread Lastly, if start_step_over initiates an in-line step, it stops iterating, and moves back whatever remaining threads it had in its local step over queue to the global step over queue. Two other gdbarch methods are added, to handle some slightly annoying corner cases. They feel awkwardly specific to these cases, but I don't see any way around them: - gdbarch_displaced_step_copy_insn_closure_by_addr: in arm_pc_is_thumb, arm-tdep.c wants to get the closure for a given buffer address. - gdbarch_displaced_step_restore_all_in_ptid: when a process forks (at least on Linux), the address space is copied. If some displaced step buffers were in use at the time of the fork, we need to restore the original bytes in the child's address space. These two adjustments are also made in infrun.c: - prepare_for_detach: there may be multiple threads doing displaced steps when we detach, so wait until all of them are done - handle_inferior_event: when we handle a fork event for a given thread, it's possible that other threads are doing a displaced step at the same time. Make sure to restore the displaced step buffer contents in the child for them. [1] https://github.com/ROCm-Developer-Tools/ROCgdb gdb/ChangeLog: * displaced-stepping.h (struct displaced_step_copy_insn_closure): Adjust comments. (struct displaced_step_inferior_state) <step_thread, step_gdbarch, step_closure, step_original, step_copy, step_saved_copy>: Remove fields. (struct displaced_step_thread_state): New. (struct displaced_step_buffer): New. * displaced-stepping.c (displaced_step_buffer::prepare): New. (write_memory_ptid): Move from infrun.c. (displaced_step_instruction_executed_successfully): New, factored out of displaced_step_finish. (displaced_step_buffer::finish): New. (displaced_step_buffer::copy_insn_closure_by_addr): New. (displaced_step_buffer::restore_in_ptid): New. * gdbarch.sh (displaced_step_location): Remove. (displaced_step_prepare, displaced_step_finish, displaced_step_copy_insn_closure_by_addr, displaced_step_restore_all_in_ptid): New. * gdbarch.c: Re-generate. * gdbarch.h: Re-generate. * gdbthread.h (class thread_info) <displaced_step_state>: New field. (thread_step_over_chain_remove): New declaration. (thread_step_over_chain_next): New declaration. (thread_step_over_chain_length): New declaration. * thread.c (thread_step_over_chain_remove): Make non-static. (thread_step_over_chain_next): New. (global_thread_step_over_chain_next): Use thread_step_over_chain_next. (thread_step_over_chain_length): New. (global_thread_step_over_chain_enqueue): Add debug print. (global_thread_step_over_chain_remove): Add debug print. * infrun.h (get_displaced_step_copy_insn_closure_by_addr): Remove. * infrun.c (get_displaced_stepping_state): New. (displaced_step_in_progress_any_inferior): Remove. (displaced_step_in_progress_thread): Adjust. (displaced_step_in_progress): Adjust. (displaced_step_in_progress_any_thread): New. (get_displaced_step_copy_insn_closure_by_addr): Remove. (gdbarch_supports_displaced_stepping): Use gdbarch_displaced_step_prepare_p. (displaced_step_reset): Change parameter from inferior to thread. (displaced_step_prepare_throw): Implement using gdbarch_displaced_step_prepare. (write_memory_ptid): Move to displaced-step.c. (displaced_step_restore): Remove. (displaced_step_finish): Implement using gdbarch_displaced_step_finish. (start_step_over): Allow starting more than one displaced step. (prepare_for_detach): Handle possibly multiple threads doing displaced steps. (handle_inferior_event): Handle possibility that fork event happens while another thread displaced steps. * linux-tdep.h (linux_displaced_step_prepare): New. (linux_displaced_step_finish): New. (linux_displaced_step_copy_insn_closure_by_addr): New. (linux_displaced_step_restore_all_in_ptid): New. (linux_init_abi): Add supports_displaced_step parameter. * linux-tdep.c (struct linux_info) <disp_step_buf>: New field. (linux_displaced_step_prepare): New. (linux_displaced_step_finish): New. (linux_displaced_step_copy_insn_closure_by_addr): New. (linux_displaced_step_restore_all_in_ptid): New. (linux_init_abi): Add supports_displaced_step parameter, register displaced step methods if true. (_initialize_linux_tdep): Register inferior_execd observer. * amd64-linux-tdep.c (amd64_linux_init_abi_common): Add supports_displaced_step parameter, adjust call to linux_init_abi. Remove call to set_gdbarch_displaced_step_location. (amd64_linux_init_abi): Adjust call to amd64_linux_init_abi_common. (amd64_x32_linux_init_abi): Likewise. * aarch64-linux-tdep.c (aarch64_linux_init_abi): Adjust call to linux_init_abi. Remove call to set_gdbarch_displaced_step_location. * arm-linux-tdep.c (arm_linux_init_abi): Likewise. * i386-linux-tdep.c (i386_linux_init_abi): Likewise. * alpha-linux-tdep.c (alpha_linux_init_abi): Adjust call to linux_init_abi. * arc-linux-tdep.c (arc_linux_init_osabi): Likewise. * bfin-linux-tdep.c (bfin_linux_init_abi): Likewise. * cris-linux-tdep.c (cris_linux_init_abi): Likewise. * csky-linux-tdep.c (csky_linux_init_abi): Likewise. * frv-linux-tdep.c (frv_linux_init_abi): Likewise. * hppa-linux-tdep.c (hppa_linux_init_abi): Likewise. * ia64-linux-tdep.c (ia64_linux_init_abi): Likewise. * m32r-linux-tdep.c (m32r_linux_init_abi): Likewise. * m68k-linux-tdep.c (m68k_linux_init_abi): Likewise. * microblaze-linux-tdep.c (microblaze_linux_init_abi): Likewise. * mips-linux-tdep.c (mips_linux_init_abi): Likewise. * mn10300-linux-tdep.c (am33_linux_init_osabi): Likewise. * nios2-linux-tdep.c (nios2_linux_init_abi): Likewise. * or1k-linux-tdep.c (or1k_linux_init_abi): Likewise. * riscv-linux-tdep.c (riscv_linux_init_abi): Likewise. * s390-linux-tdep.c (s390_linux_init_abi_any): Likewise. * sh-linux-tdep.c (sh_linux_init_abi): Likewise. * sparc-linux-tdep.c (sparc32_linux_init_abi): Likewise. * sparc64-linux-tdep.c (sparc64_linux_init_abi): Likewise. * tic6x-linux-tdep.c (tic6x_uclinux_init_abi): Likewise. * tilegx-linux-tdep.c (tilegx_linux_init_abi): Likewise. * xtensa-linux-tdep.c (xtensa_linux_init_abi): Likewise. * ppc-linux-tdep.c (ppc_linux_init_abi): Adjust call to linux_init_abi. Remove call to set_gdbarch_displaced_step_location. * arm-tdep.c (arm_pc_is_thumb): Call gdbarch_displaced_step_copy_insn_closure_by_addr instead of get_displaced_step_copy_insn_closure_by_addr. * rs6000-aix-tdep.c (rs6000_aix_init_osabi): Adjust calls to clear gdbarch methods. * rs6000-tdep.c (struct ppc_inferior_data): New structure. (get_ppc_per_inferior): New function. (ppc_displaced_step_prepare): New function. (ppc_displaced_step_finish): New function. (ppc_displaced_step_restore_all_in_ptid): New function. (rs6000_gdbarch_init): Register new gdbarch methods. * s390-tdep.c (s390_gdbarch_init): Don't call set_gdbarch_displaced_step_location, set new gdbarch methods. gdb/testsuite/ChangeLog: * gdb.arch/amd64-disp-step-avx.exp: Adjust pattern. * gdb.threads/forking-threads-plus-breakpoint.exp: Likewise. * gdb.threads/non-stop-fair-events.exp: Likewise. Change-Id: I387cd235a442d0620ec43608fd3dc0097fcbf8c8
2020-12-04gdb: rename things related to step over chainsSimon Marchi1-10/+10
Rename step_over_queue_head to global_thread_step_over_chain_head, to make it more obvious when reading code that we are touching the global queue. Rename all functions that operate on it to have "global" in their name, to make it clear on which chain they operate on. Also, in a subsequent patch, we'll need both global and non-global versions of these functions, so it will be easier to do the distinction if they are named properly. Normalize the naming to use "chain" everywhere instead of sometimes "queue", sometimes "chain". I also reworded a few comments in gdbthread.h. They implied that the step over chain is per-inferior, when in reality there is only one global chain, not one per inferior, as far as I understand. gdb/ChangeLog: * gdbthread.h (thread_step_over_chain_enqueue): Rename to... (global_thread_step_over_chain_enqueue): ... this. Update all users. (thread_step_over_chain_remove): Rename to... (global_thread_step_over_chain_remove): ... this. Update all users. (thread_step_over_chain_next): Rename to... (global_thread_step_over_chain_next): ... this. Update all users. * infrun.h (step_over_queue_head): Rename to... (global_thread_step_over_chain_head): ... this. Update all users. * infrun.c (step_over_queue_head): Rename to... (global_thread_step_over_chain_head): ... this. Update all users. * thread.c (step_over_chain_remove): Rename to... (thread_step_over_chain_remove): ... this. Update all users. (thread_step_over_chain_next): Rename to... (global_thread_step_over_chain_next): ... this. Update all users. (thread_step_over_chain_enqueue): Rename to... (global_thread_step_over_chain_enqueue): ... this. Update all users. (thread_step_over_chain_remove): Rename to... (global_thread_step_over_chain_remove): ... this. Update all users. Change-Id: Iabbf57d83c01321ca199d83fadb57f5b04e4d6d9
2020-10-30Move lookup_selected_frame to frame.cPedro Alves1-63/+0
This function is now external, and isn't really threads related. Move it to frame.c. gdb/ChangeLog: * thread.c (lookup_selected_frame): Move ... * frame.c (lookup_selected_frame): ... here. Change-Id: Ia96b79c15767337c68efd3358bcc715ce8e26c15
2020-10-30Make scoped_restore_current_thread's cdtors exception free (RFC)Pedro Alves1-47/+17
If the remote target closes while we're reading registers/memory for restoring the selected frame in scoped_restore_current_thread's dtor, the corresponding TARGET_CLOSE_ERROR error is swallowed by the scoped_restore_current_thread's dtor, because letting exceptions escape from a dtor is bad. It isn't great to lose that errors like that, though. I've been thinking about how to avoid it, and I came up with this patch. The idea here is to make scoped_restore_current_thread's dtor do as little as possible, to avoid any work that might throw in the first place. And to do that, instead of having the dtor call restore_selected_frame, which re-finds the previously selected frame, just record the frame_id/level of the desired selected frame, and have get_selected_frame find the frame the next time it is called. In effect, this implements most of Cagney's suggestion, here: /* On demand, create the selected frame and then return it. If the selected frame can not be created, this function prints then throws an error. When MESSAGE is non-NULL, use it for the error message, otherwize use a generic error message. */ /* FIXME: cagney/2002-11-28: At present, when there is no selected frame, this function always returns the current (inner most) frame. It should instead, when a thread has previously had its frame selected (but not resumed) and the frame cache invalidated, find and then return that thread's previously selected frame. */ extern struct frame_info *get_selected_frame (const char *message); The only thing missing to fully implement that would be to make reinit_frame_cache just clear selected_frame instead of calling select_frame(NULL), and the call select_frame(NULL) explicitly in the places where we really wanted reinit_frame_cache to go back to the current frame too. That can done separately, though, I'm not proposing to do that in this patch. Note that this patch renames restore_selected_frame to lookup_selected_frame, and adds a new restore_selected_frame function that doesn't throw, to be paired with the also-new save_selected_frame function. There's a restore_selected_frame function in infrun.c that I think can be replaced by the new one in frame.c. Also done in this patch is make the get_selected_frame's parameter be optional, so that we don't have to pass down nullptr explicitly all over the place. lookup_selected_frame should really move from thread.c to frame.c, but I didn't do that here, just to avoid churn in the patch while it collects comments. I did make it extern and declared it in frame.h already, preparing for the move. I will do the move as a follow up patch if people agree with this approach. Incidentally, this patch alone would fix the crashes fixed by the previous patches in the series, because with this, scoped_restore_current_thread's constructor doesn't throw either. gdb/ChangeLog: * blockframe.c (block_innermost_frame): Use get_selected_frame. * frame.c (scoped_restore_selected_frame::scoped_restore_selected_frame): Use save_selected_frame. Save language as well. (scoped_restore_selected_frame::~scoped_restore_selected_frame): Use restore_selected_frame, and restore language as well. (selected_frame_id, selected_frame_level): New. (selected_frame): Update comments. (save_selected_frame, restore_selected_frame): New. (get_selected_frame): Use lookup_selected_frame. (get_selected_frame_if_set): Delete. (select_frame): Record selected_frame_level and selected_frame_id. * frame.h (scoped_restore_selected_frame) <m_level, m_lang>: New fields. (get_selected_frame): Make 'message' parameter optional. (get_selected_frame_if_set): Delete declaration. (select_frame): Update comments. (save_selected_frame, restore_selected_frame) (lookup_selected_frame): Declare. * gdbthread.h (scoped_restore_current_thread) <m_lang>: New field. * infrun.c (struct infcall_control_state) <selected_frame_level>: New field. (save_infcall_control_state): Use save_selected_frame. (restore_selected_frame): Delete. (restore_infcall_control_state): Use restore_selected_frame. * stack.c (select_frame_command_core, frame_command_core): Use get_selected_frame. * thread.c (restore_selected_frame): Rename to ... (lookup_selected_frame): ... this and make extern. Select the current frame if the frame level is -1. (scoped_restore_current_thread::restore): Also restore the language. (scoped_restore_current_thread::~scoped_restore_current_thread): Don't try/catch. (scoped_restore_current_thread::scoped_restore_current_thread): Save the language as well. Use save_selected_frame. Change-Id: I73fd1cfc40d8513c28e5596383b7ecd8bcfe700f
2020-10-19gdb/thread: fine-tune 'info threads' help textTankut Baris Aktemur1-3/+3
The help text of 'info threads' is below: (gdb) help info threads Display currently known threads. Usage: info threads [OPTION]... [ID]... Options: -gid Show global thread IDs.If ID is given, it is a space-separated list of IDs of threads to display. Otherwise, all threads are displayed. (gdb) I think the "If ID is given ..." info should have come right below the the usage line. This patch reorganizes the text so that we get (gdb) help info threads Display currently known threads. Usage: info threads [OPTION]... [ID]... If ID is given, it is a space-separated list of IDs of threads to display. Otherwise, all threads are displayed. Options: -gid Show global thread IDs. (gdb) gdb/ChangeLog: 2020-10-19 Tankut Baris Aktemur <tankut.baris.aktemur@intel.com> * thread.c (_initialize_thread): Fine-tune the help text of 'info threads'.
2020-09-28Remove target_has_registers macroTom Tromey1-2/+2
This removes the target_has_registers object-like macro, replacing it with the underlying function. gdb/ChangeLog 2020-09-28 Tom Tromey <tom@tromey.com> * tui/tui-regs.c (tui_get_register) (tui_data_window::show_registers): Update. * thread.c (scoped_restore_current_thread::restore) (scoped_restore_current_thread::scoped_restore_current_thread): Update. * regcache-dump.c (regcache_print): Update. * python/py-finishbreakpoint.c (bpfinishpy_detect_out_scope_cb): Update. * mi/mi-main.c (mi_cmd_data_write_register_values): Update. * mep-tdep.c (current_me_module, current_options): Update. * linux-thread-db.c (thread_db_load): Update. * infcmd.c (registers_info, info_vector_command) (info_float_command): Update. * ia64-tdep.c (ia64_frame_prev_register) (ia64_sigtramp_frame_prev_register): Update. * ia64-libunwind-tdep.c (libunwind_frame_prev_register): Update. * gcore.c (derive_stack_segment): Update. * frame.c (get_current_frame, has_stack_frames): Update. * findvar.c (language_defn::read_var_value): Update. * arm-tdep.c (arm_pc_is_thumb): Update. * target.c (target_has_registers): Rename from target_has_registers_1. * target.h (target_has_registers): Remove macro. (target_has_registers): Rename from target_has_registers_1.
2020-09-28Remove target_has_stack macroTom Tromey1-3/+3
This removes the target_has_stack object-like macro, replacing it with the underlying function. gdb/ChangeLog 2020-09-28 Tom Tromey <tom@tromey.com> * windows-tdep.c (tlb_make_value): Update. * tui/tui-regs.c (tui_data_window::show_registers): Update. * thread.c (scoped_restore_current_thread::restore) (scoped_restore_current_thread::scoped_restore_current_thread) (thread_command): Update. * stack.c (backtrace_command_1, frame_apply_level_command) (frame_apply_all_command, frame_apply_command): Update. * infrun.c (siginfo_make_value, restore_infcall_control_state): Update. * gcore.c (derive_stack_segment): Update. * frame.c (get_current_frame, has_stack_frames): Update. * auxv.c (info_auxv_command): Update. * ada-tasks.c (ada_build_task_list): Update. * target.c (target_has_stack): Rename from target_has_stack_1. * target.h (target_has_stack): Remove macro. (target_has_stack): Rename from target_has_stack_1.
2020-09-28Remove target_has_memory macroTom Tromey1-2/+2
This removes the target_has_memory object-like macro, replacing it with the underlying function. gdb/ChangeLog 2020-09-28 Tom Tromey <tom@tromey.com> * target.c (target_has_memory): Rename from target_has_memory_1. * tui/tui-regs.c (tui_data_window::show_registers): Update. * thread.c (scoped_restore_current_thread::restore) (scoped_restore_current_thread::scoped_restore_current_thread): Update. * frame.c (get_current_frame, has_stack_frames): Update. * target.h (target_has_memory): Remove macro. (target_has_memory): Rename from target_has_memory_1.
2020-09-18Fix "thread find" with multiple inferiors/targets (PR gdb/26631)Pedro Alves1-0/+6
"thread find" with multiple inferiors got broken with the multi-target work: Thread 1 "gdb" hit Breakpoint 1, internal_error (...) at ../../src/gdbsupport/errors.cc:51 51 { (top-gdb) bt #0 internal_error (file=0xffffd4d0 <error: Cannot access memory at address 0xffffd4d0>, line=0, fmt=0x555556330320 "en_US.UTF-8") at ../../src/gdbsupport/errors.cc:51 #1 0x0000555555bca4c7 in target_thread_name (info=0x555556801290) at ../../src/gdb/target.c:2035 #2 0x0000555555beb07a in thread_find_command (arg=0x7fffffffe08e "1", from_tty=0) at ../../src/gdb/thread.c:1959 #3 0x000055555572ec49 in do_const_cfunc (c=0x555556786bc0, args=0x7fffffffe08e "1", from_tty=0) at ../../src/gdb/cli/cli-decode.c:95 #4 0x0000555555732abd in cmd_func (cmd=0x555556786bc0, args=0x7fffffffe08e "1", from_tty=0) at ../../src/gdb/cli/cli-decode.c:2181 #5 0x0000555555bf1245 in execute_command (p=0x7fffffffe08e "1", from_tty=0) at ../../src/gdb/top.c:664 #6 0x00005555559cad10 in catch_command_errors (command=0x555555bf0c31 <execute_command(char const*, int)>, arg=0x7fffffffe082 "thread find 1", from_tty=0) at ../../src/gdb/main.c:457 #7 0x00005555559cc33d in captured_main_1 (context=0x7fffffffdb60) at ../../src/gdb/main.c:1218 #8 0x00005555559cc571 in captured_main (data=0x7fffffffdb60) at ../../src/gdb/main.c:1243 #9 0x00005555559cc5e8 in gdb_main (args=0x7fffffffdb60) at ../../src/gdb/main.c:1268 #10 0x0000555555623816 in main (argc=17, argv=0x7fffffffdc78) at ../../src/gdb/gdb.c:32 The problem is that we're not switching to the inferior/target before calling target methods, which trips on an assertion put in place exactly to catch this sort of problem. gdb/testsuite/ChangeLog: PR gdb/26631 * gdb.multi/multi-target-thread-find.exp: New file. gdb/ChangeLog: PR gdb/26631 * thread.c (thread_find_command): Switch inferior before calling target methods.
2020-08-07gdb: pass target to thread_ptid_changed observableSimon Marchi1-1/+1
I noticed what I think is a potential bug. I did not observe it nor was I able to reproduce it using actual debugging. It's quite unlikely, because it involves multi-target and ptid clashes. I added selftests that demonstrate it though. The thread_ptid_changed observer says that thread with OLD_PTID now has NEW_PTID. Now, if for some reason we happen to have two targets defining a thread with OLD_PTID, the observers don't know which thread this is about. regcache::regcache_thread_ptid_changed changes all regcaches with OLD_PTID. If there is a regcache for a thread with ptid OLD_PTID, but that belongs to a different target, this regcache will be erroneously changed. Similarly, infrun_thread_ptid_changed updates inferior_ptid if inferior_ptid matches OLD_PTID. But if inferior_ptid currently refers not to the thread is being changed, but to a thread with the same ptid belonging to a different target, then inferior_ptid will erroneously be changed. This patch adds a `process_stratum_target *` parameter to the `thread_ptid_changed` observable and makes the two observers use it. Tests for both are added, which would fail if the corresponding fix wasn't done. gdb/ChangeLog: * observable.h (thread_ptid_changed): Add parameter `process_stratum_target *`. * infrun.c (infrun_thread_ptid_changed): Add parameter `process_stratum_target *` and use it. (selftests): New namespace. (infrun_thread_ptid_changed): New function. (_initialize_infrun): Register selftest. * regcache.c (regcache_thread_ptid_changed): Add parameter `process_stratum_target *` and use it. (regcache_thread_ptid_changed): New function. (_initialize_regcache): Register selftest. * thread.c (thread_change_ptid): Pass target to thread_ptid_changed observable. Change-Id: I0599e61224b6d154a7b55088a894cb88298c3c71
2020-07-10Fix crash if connection drops in scoped_restore_current_thread's ctor, part 2Pedro Alves1-15/+10
Running the testsuite against an Asan-enabled build of GDB makes gdb.base/multi-target.exp expose this bug. scoped_restore_current_thread's ctor calls get_frame_id to record the selected frame's ID to restore later. If the frame ID hasn't been computed yet, it will be computed on the spot, and that will usually require accessing the target's memory and registers. If the remote connection closes, while we're computing the frame ID, the remote target exits its inferiors, unpushes itself, and throws a TARGET_CLOSE_ERROR error. Exiting the inferiors deletes the inferior's threads. scoped_restore_current_thread increments the current thread's refcount to prevent the thread from being deleted from under its feet. However, the code that does that isn't considering the case of the thread being deleted from within get_frame_id. It only increments the refcount _after_ get_frame_id returns. So if the current thread is indeed deleted, the tp->incref (); statement references a stale TP pointer. Incrementing the refcounts earlier fixes it. We should probably also let the TARGET_CLOSE_ERROR error propagate in this case. That alone would fix it, though it seems better to tweak the refcount handling too. And to avoid having to manually decref before throwing, convert to use gdb::ref_ptr. Unfortunately, we can't define inferior_ref in inferior.h and then use it in scoped_restore_current_thread, because scoped_restore_current_thread is defined before inferior is (inferior.h includes gdbthread.h). To break that dependency, we would have to move scoped_restore_current_thread to its own header. I'm not doing that here. gdb/ChangeLog: * gdbthread.h (inferior_ref): Define. (scoped_restore_current_thread) <m_thread>: Now a thread_info_ref. (scoped_restore_current_thread) <m_inf>: Now an inferior_ref. * thread.c (scoped_restore_current_thread::restore): Adjust to gdb::ref_ptr. (scoped_restore_current_thread::~scoped_restore_current_thread): Remove manual decref handling. (scoped_restore_current_thread::scoped_restore_current_thread): Adjust to use inferior_ref::new_reference/thread_info_ref::new_reference. Incref the thread before calling get_frame_id instead of after. Let TARGET_CLOSE_ERROR propagate.
2020-06-18Decouple inferior_ptid/inferior_thread(); dup ptids in thread list (PR 25412)Pedro Alves1-64/+33
In PR 25412, Simon noticed that after the multi-target series, the tid-reuse.exp testcase manages to create a duplicate thread in the thread list. Or rather, two threads with the same PTID. add_thread_silent has code in place to detect the case of a new thread reusing some older thread's ptid, but it doesn't work correctly anymore when the old thread is NOT the current thread and it has a refcount higher than 0. Either condition prevents a thread from being deleted, but the refcount case wasn't being considered. I think the reason that case wasn't considered is that that code predates thread_info refcounting. Back when it was originally written, delete_thread always deleted the thread. That add_thread_silent code in question has some now-unnecessary warts, BTW. For instance, this: /* Make switch_to_thread not read from the thread. */ new_thr->state = THREAD_EXITED; ... used to be required because switch_to_thread would update 'stop_pc' otherwise. I.e., it would read registers from an exited thread otherwise. switch_to_thread no longer reads the stop_pc, since: commit f2ffa92bbce9dd5fbedc138ac2a3bc8a88327d09 Author: Pedro Alves <palves@redhat.com> AuthorDate: Thu Jun 28 20:18:24 2018 +0100 gdb: Eliminate the 'stop_pc' global Also, if the ptid of the now-gone current thread is reused, we currently return from add_thread_silent with the current thread pointing at the _new_ thread. Either pointing at the old thread, or at no thread selected would be reasonable. But pointing at an unrelated thread (the new thread that happens to reuse the ptid) is just broken. Seems like I was the one who wrote it like that but I have no clue why, FWIW. Currently, an exited thread kept in the thread list still holds its original ptid. The idea was that we need the ptid to be able to temporarily switch to another thread and then switch back to the original thread, because thread switching is really inferior_ptid switching. Switching back to the original thread requires a ptid lookup. Now, in order to avoid exited threads with the same ptid as a live thread in the same thread list, one thing I considered (and tried) was to change an exited thread's ptid to minus_one_ptid. However, with that, there's a case that we won't handle well, which is if we end up with more than one exited thread in the list, since then all exited threads will all have the same ptid. Since inferior_thread() relies on inferior_ptid, may well return the wrong thread. My next attempt to address this, was to switch an exited thread's ptid to a globally unique "exited" ptid, which is a ptid with pid == -1 and tid == 'the thread's global GDB thread number'. Note that GDB assumes that the GDB global thread number is monotonically increasing and doesn't wrap around. (We should probably make GDB thread numbers 64-bit to prevent that happening in practice; they're currently signed 32-bit.) This attempt went a long way, but still ran into a number of issues. It was a major hack too, obviously. My next attempt is the one that I'm proposing, which is to bite the bullet and break the connection between inferior_ptid and inferior_thread(), aka the current thread. I.e., make the current thread be a global thread_info pointer that is written to directly by switch_to_thread, etc., and making inferior_thread() return that pointer, instead of having inferior_thread() lookup up the inferior_ptid thread, by ptid_t. You can look at this as a continuation of the effort of using more thread_info pointers instead of ptids when possible. By making the current thread a global thread_info pointer, we can make switch_to_thread simply write to the global thread pointer, which makes scoped_restore_current_thread able to restore back to an exited thread without relying on unrelyable ptid look ups. I.e., this makes it not a real problem to have more than one thread with the same ptid in the thread list. There will always be only one live thread with a given ptid, so code that looks up a live thread by ptid will always be able to find the right one. This change required auditing the whole codebase for places where we were writing to inferior_ptid directly to change the current thread, and change them to use switch_to_thread instead or one of its siblings, because otherwise inferior_thread() would return a thread unrelated to the changed-to inferior_ptid. That was all (hopefully) done in previous patches. After this, inferior_ptid is mainly used by target backend code. It is also relied on by a number of target methods. E.g., the target_resume interface and the memory reading routines -- we still need it there because we need to be able to access memory off of processes for which we don't have a corresponding inferior/thread object, like when handling forks. Maybe we could pass down a context explicitly to target_read_memory, etc. gdb/ChangeLog: 2020-06-18 Pedro Alves <palves@redhat.com> PR gdb/25412 * gdbthread.h (delete_thread, delete_thread_silent) (find_thread_ptid): Update comments. * thread.c (current_thread_): New global. (is_current_thread): Move higher, and reimplement. (inferior_thread): Reimplement. (set_thread_exited): Use bool. Add assertions. (add_thread_silent): Simplify thread-reuse handling by always calling delete_thread. (delete_thread): Remove intro comment. (find_thread_ptid): Skip exited threads. (switch_to_thread_no_regs): Write to current_thread_. (switch_to_no_thread): Check CURRENT_THREAD_ instead of INFERIOR_PTID. Clear current_thread_.