summaryrefslogtreecommitdiff
path: root/gdb/infcmd.c
diff options
context:
space:
mode:
authorPedro Alves <pedro@palves.net>2022-11-17 23:21:04 +0000
committerPedro Alves <pedro@palves.net>2023-02-27 19:12:28 +0000
commit6bf09ec03d86fdea8476eb137025c701a85e6dec (patch)
treec7b25018a171b3db02fbfb24dfc2c801b0235f89 /gdb/infcmd.c
parenta81871f7136c0c0ae6e9d921cb0717829543ee61 (diff)
downloadbinutils-gdb-6bf09ec03d86fdea8476eb137025c701a85e6dec.tar.gz
Improve "info program"
With gdb.base/catch-follow-exec.exp, we currently see: ~~~~~~~~~~~~~~~ (gdb) continue Continuing. process 693251 is executing new program: /usr/bin/ls [New inferior 2] [New process 693251] [Switching to process 693251] Thread 2.1 "ls" hit Catchpoint 2 (exec'd /usr/bin/ls), 0x00007ffff7fd0100 in _start () from /lib64/ld-linux-x86-64.so.2 (gdb) info prog No selected thread. ~~~~~~~~~~~~~~~ Note the "No selected thread" output. That is totally bogus, because there _is_ a selected thread. What GDB really means, is that it can't find the thread that had the latest (user-visible) stop. And that happens because "info program" gets that info from get_last_target_status, and the last target status has been cleared. However, GDB also checks if there is a selected thread, here: if (ptid == null_ptid || ptid == minus_one_ptid) error (_("No selected thread.")); .. the null_ptid part. That is also bogus, because what matters is the thread that last reported a stop, not the current thread: - in all-stop mode, "info program" displays info about the last stop. That may have happened on a thread different from the selected thread. - in non-stop mode, because all threads are controlled individually, "info program" shows info about the last stop of the selected thread. The current code already behaves this way, though in a poor way. This patch reimplements it, such that the all-stop version now finds the thread that last reported an event via the 'previous_thread' strong reference. Being a strong reference means that if that thread has exited since the event was reported, 'previous_thread' will still point to it, so we can say that the thread exited meanwhile. The patch also extends "info program" output a little, to let the user know which thread we are printing info for. For example, for the gdb.base/catch-follow-exec.exp case we shown above, we now get: (gdb) info prog Last stopped for thread 2.1 (process 710867). Using the running image of child process 710867. Program stopped at 0x7ffff7fd0100. It stopped at breakpoint 2. Type "info stack" or "info registers" for more information. (gdb) while in non-stop mode, we get: (gdb) info prog Selected thread 2.1 (process 710867). Using the running image of child process 710867. Program stopped at 0x7ffff7fd0100. It stopped at breakpoint 2. Type "info stack" or "info registers" for more information. (gdb) In both cases, the first line of output is new. The existing code considered these running/exited cases as an error, but I think that that's incorrect, since this is IMO just plain execution info as well. So the patch makes those cases regular prints, not errors. If the thread is running, we get, in non-stop mode: (gdb) info prog Selected thread 2.1 (process 710867). Selected thread is running. ... and in all-stop: (gdb) info prog Last stopped for thread 2.1 (process 710867). Thread is now running. If the thread has exited, we get, in non-stop mode: (gdb) info prog Selected thread 2.1 (process 710867). Selected thread has exited. ... and in all-stop: (gdb) info prog Last stopped for thread 2.1 (process 710867). Thread has since exited. The gdb.base/info-program.exp testcase was much extended to test all-stop/non-stop and single-threaded/multi-threaded. Change-Id: I51d9d445f772d872af3eead3449ad4aa445781b1
Diffstat (limited to 'gdb/infcmd.c')
-rw-r--r--gdb/infcmd.c79
1 files changed, 58 insertions, 21 deletions
diff --git a/gdb/infcmd.c b/gdb/infcmd.c
index 76453402c93..e3436470b7c 100644
--- a/gdb/infcmd.c
+++ b/gdb/infcmd.c
@@ -1932,37 +1932,74 @@ finish_command (const char *arg, int from_tty)
static void
info_program_command (const char *args, int from_tty)
{
- bpstat *bs;
- int num, stat;
- ptid_t ptid;
- process_stratum_target *proc_target;
+ scoped_restore_current_thread restore_thread;
- if (!target_has_execution ())
- {
- gdb_printf (_("The program being debugged is not being run.\n"));
- return;
- }
+ thread_info *tp;
+
+ /* In non-stop, since every thread is controlled individually, we'll
+ show execution info about the current thread. In all-stop, we'll
+ show execution info about the last stop. */
if (non_stop)
{
- ptid = inferior_ptid;
- proc_target = current_inferior ()->process_target ();
+ if (!target_has_execution ())
+ {
+ gdb_printf (_("The program being debugged is not being run.\n"));
+ return;
+ }
+
+ if (inferior_ptid == null_ptid)
+ error (_("No selected thread."));
+
+ tp = inferior_thread ();
+
+ gdb_printf (_("Selected thread %s (%s).\n"),
+ print_thread_id (tp),
+ target_pid_to_str (tp->ptid).c_str ());
+
+ if (tp->state == THREAD_EXITED)
+ {
+ gdb_printf (_("Selected thread has exited.\n"));
+ return;
+ }
+ else if (tp->state == THREAD_RUNNING)
+ {
+ gdb_printf (_("Selected thread is running.\n"));
+ return;
+ }
}
else
- get_last_target_status (&proc_target, &ptid, nullptr);
+ {
+ tp = get_previous_thread ();
+
+ if (tp == nullptr)
+ {
+ gdb_printf (_("The program being debugged is not being run.\n"));
+ return;
+ }
- if (ptid == null_ptid || ptid == minus_one_ptid)
- error (_("No selected thread."));
+ switch_to_thread (tp);
- thread_info *tp = find_thread_ptid (proc_target, ptid);
+ gdb_printf (_("Last stopped for thread %s (%s).\n"),
+ print_thread_id (tp),
+ target_pid_to_str (tp->ptid).c_str ());
- if (tp->state == THREAD_EXITED)
- error (_("Invalid selected thread."));
- else if (tp->state == THREAD_RUNNING)
- error (_("Selected thread is running."));
+ if (tp->state == THREAD_EXITED)
+ {
+ gdb_printf (_("Thread has since exited.\n"));
+ return;
+ }
+
+ if (tp->state == THREAD_RUNNING)
+ {
+ gdb_printf (_("Thread is now running.\n"));
+ return;
+ }
+ }
- bs = tp->control.stop_bpstat;
- stat = bpstat_num (&bs, &num);
+ int num;
+ bpstat *bs = tp->control.stop_bpstat;
+ int stat = bpstat_num (&bs, &num);
target_files_info ();
gdb_printf (_("Program stopped at %s.\n"),