gdb/gdbserver:
* server.h: Move some code to ...
* gdbthread.h: ... here. New.
* Makefile.in (inferiors.o, regcache.o): Depends on gdbthread.h
(remote-utils.o, server.o, target.o tracepoint.o): Likewise.
(nto-low.o, win32-low.o): Likewise.
* inferiors.c, linux-low.h, nto-low.c: Include gdbthread.h.
* regcache.c, remote-utils.c, server.c: Likewise.
* target.c, tracepoint.c, win32-low.c: Likewise.
2012-04-29 08:28:30 +02:00
|
|
|
/* Multi-thread control defs for remote server for GDB.
|
2014-01-01 04:54:24 +01:00
|
|
|
Copyright (C) 1993-2014 Free Software Foundation, Inc.
|
gdb/gdbserver:
* server.h: Move some code to ...
* gdbthread.h: ... here. New.
* Makefile.in (inferiors.o, regcache.o): Depends on gdbthread.h
(remote-utils.o, server.o, target.o tracepoint.o): Likewise.
(nto-low.o, win32-low.o): Likewise.
* inferiors.c, linux-low.h, nto-low.c: Include gdbthread.h.
* regcache.c, remote-utils.c, server.c: Likewise.
* target.c, tracepoint.c, win32-low.c: Likewise.
2012-04-29 08:28:30 +02:00
|
|
|
|
|
|
|
This file is part of GDB.
|
|
|
|
|
|
|
|
This program is free software; you can redistribute it and/or modify
|
|
|
|
it under the terms of the GNU General Public License as published by
|
|
|
|
the Free Software Foundation; either version 3 of the License, or
|
|
|
|
(at your option) any later version.
|
|
|
|
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
GNU General Public License for more details.
|
|
|
|
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
|
|
along with this program. If not, see <http://www.gnu.org/licenses/>. */
|
|
|
|
|
|
|
|
#ifndef GDB_THREAD_H
|
|
|
|
#define GDB_THREAD_H
|
|
|
|
|
[gdbserver] Split a new inferiors.h file out of server.h.
gdb/gdbserver/
2013-09-05 Pedro Alves <palves@redhat.com>
* server.h (current_process, get_thread_process, all_processes)
(add_inferior_to_list, for_each_inferior, current_inferior)
(remove_inferior, add_process, remove_process, find_process_pid)
(have_started_inferiors_p, have_attached_inferiors_p)
(thread_id_to_gdb_id, thread_to_gdb_id, gdb_id_to_thread_id)
(clear_inferiors, find_inferior, find_inferior_id)
(inferior_target_data, set_inferior_target_data)
(inferior_regcache_data, set_inferior_regcache_data): Move to
inferiors.h, and include it.
* inferiors.h: New file.
2013-09-05 22:41:22 +02:00
|
|
|
#include "inferiors.h"
|
gdb/gdbserver:
* server.h: Move some code to ...
* gdbthread.h: ... here. New.
* Makefile.in (inferiors.o, regcache.o): Depends on gdbthread.h
(remote-utils.o, server.o, target.o tracepoint.o): Likewise.
(nto-low.o, win32-low.o): Likewise.
* inferiors.c, linux-low.h, nto-low.c: Include gdbthread.h.
* regcache.c, remote-utils.c, server.c: Likewise.
* target.c, tracepoint.c, win32-low.c: Likewise.
2012-04-29 08:28:30 +02:00
|
|
|
|
2013-03-11 09:35:11 +01:00
|
|
|
struct btrace_target_info;
|
|
|
|
|
gdb/gdbserver:
* server.h: Move some code to ...
* gdbthread.h: ... here. New.
* Makefile.in (inferiors.o, regcache.o): Depends on gdbthread.h
(remote-utils.o, server.o, target.o tracepoint.o): Likewise.
(nto-low.o, win32-low.o): Likewise.
* inferiors.c, linux-low.h, nto-low.c: Include gdbthread.h.
* regcache.c, remote-utils.c, server.c: Likewise.
* target.c, tracepoint.c, win32-low.c: Likewise.
2012-04-29 08:28:30 +02:00
|
|
|
struct thread_info
|
|
|
|
{
|
2014-02-19 23:51:55 +01:00
|
|
|
/* This must appear first. See inferiors.h.
|
|
|
|
The list iterator functions assume it. */
|
gdb/gdbserver:
* server.h: Move some code to ...
* gdbthread.h: ... here. New.
* Makefile.in (inferiors.o, regcache.o): Depends on gdbthread.h
(remote-utils.o, server.o, target.o tracepoint.o): Likewise.
(nto-low.o, win32-low.o): Likewise.
* inferiors.c, linux-low.h, nto-low.c: Include gdbthread.h.
* regcache.c, remote-utils.c, server.c: Likewise.
* target.c, tracepoint.c, win32-low.c: Likewise.
2012-04-29 08:28:30 +02:00
|
|
|
struct inferior_list_entry entry;
|
2014-02-19 23:51:55 +01:00
|
|
|
|
gdb/gdbserver:
* server.h: Move some code to ...
* gdbthread.h: ... here. New.
* Makefile.in (inferiors.o, regcache.o): Depends on gdbthread.h
(remote-utils.o, server.o, target.o tracepoint.o): Likewise.
(nto-low.o, win32-low.o): Likewise.
* inferiors.c, linux-low.h, nto-low.c: Include gdbthread.h.
* regcache.c, remote-utils.c, server.c: Likewise.
* target.c, tracepoint.c, win32-low.c: Likewise.
2012-04-29 08:28:30 +02:00
|
|
|
void *target_data;
|
|
|
|
void *regcache_data;
|
|
|
|
|
|
|
|
/* The last resume GDB requested on this thread. */
|
|
|
|
enum resume_kind last_resume_kind;
|
|
|
|
|
|
|
|
/* The last wait status reported for this thread. */
|
|
|
|
struct target_waitstatus last_status;
|
|
|
|
|
[remote/gdbserver] Don't lose signals when reconnecting.
Currently, when GDB connects in all-stop mode, GDBserver always
responds to the status packet with a GDB_SIGNAL_TRAP, even if the
program is actually stopped for some other signal.
(gdb) tar rem ...
...
(gdb) c
Program received signal SIGUSR1, User defined signal 1.
(gdb) disconnect
(gdb) tar rem ...
(gdb) c
(Or a GDB crash instead of an explicit disconnect.)
This results in the program losing that signal on that last continue,
because gdb will tell the target to resume with no signal (to suppress
the GDB_SIGNAL_TRAP, due to 'handle SISGTRAP nopass'), and that will
actually suppress the real signal the program had stopped for
(SIGUSR1). To fix that, I think we should make GDBserver report the
real signal the thread had stopped for in response to the status
packet:
@item ?
@cindex @samp{?} packet
Indicate the reason the target halted. The reply is the same as for
step and continue.
But, that raises the question -- which thread are we reporting the
status for? Due to how the RSP in all-stop works, we can only report
one status. The status packet's response is a stop reply packet, so
it includes the thread identifier, so it's not a problem packet-wise.
However, GDBserver is currently always reporting the status for first
thread in the thread list, even though that may well not be the thread
that got the signal that caused the program to stop. So the next
logical step would be to report the status for the
last_ptid/last_status thread (the last event reported to gdb), if it's
still around; and if not, fallback to some other thread.
There's an issue on the GDB side with that, though...
GDB currently always adds the thread reported in response to the
status query as the first thread in its list. That means that if we
start with e.g.,
(gdb) info threads
3 Thread 1003 ...
* 2 Thread 1002 ...
1 Thread 1001 ...
And reconnect:
(gdb) disconnect
(gdb) tar rem ...
We end up with:
(gdb) info threads
3 Thread 1003 ...
2 Thread 1001 ...
* 1 Thread 1002 ...
Not a real big issue, but it's reasonably fixable, by having GDB
fetch/sync the thread list before fetching the status/'?', and then
using the status to select the right thread as current on the GDB
side. Holes in the thread numbers are squashed before/after
reconnection (e.g., 2,3,5 becomes 1,2,3), but the order is preserved,
which I think is both good, and good enough.
However (yes, there's more...), the previous GDB that was connected
might have had gdbserver running in non-stop mode, or could have left
gdbserver doing disconnected tracing (which also forces non-stop), and
if the new gdb/connection is in all-stop mode, we can end up with more
than one thread with a signal to report back to gdb. As we can only
report one thread/status (in the all-stop RSP variant; the non-stop
variant doesn't have this issue), we get to do what we do at every
other place we have this situation -- leave events we can't report
right now as pending, so that the next resume picks them up.
Note all this ammounts to a QoI change, within the existing framework.
There's really no RSP change here.
The only user visible change (other than that the signal is program is
stopped at isn't lost / is passed to the program), is in "info
program", that now can show the signal the program stopped for. Of
course, the next resume will respect the pass/nopass setting for the
signal in question. It'd be reasonable to have the initial connection
tell the user the program was stopped with a signal, similar to when
we load a core to debug, but I'm leaving that out for a future change.
I think we'll need to either change how handle_inferior_event & co
handle stop_soon, or maybe bypass them completely (like
fork-child.c:startup_inferior) for that.
Tested on x86_64 Fedora 17.
gdb/gdbserver/
2014-01-08 Pedro Alves <palves@redhat.com>
* gdbthread.h (struct thread_info) <status_pending_p>: New field.
* server.c (visit_actioned_threads, handle_pending_status): New
function.
(handle_v_cont): Factor out parts to ...
(resume): ... this new function. If in all-stop, and a thread
being resumed has a pending status, report it without actually
resuming.
(myresume): Adjust to use the new 'resume' function.
(clear_pending_status_callback, set_pending_status_callback)
(find_status_pending_thread_callback): New functions.
(handle_status): Handle the case of multiple threads having
interesting statuses to report. Report threads' real last signal
instead of always reporting GDB_SIGNAL_TRAP. Look for a thread
with an interesting thread to report the status for, instead of
always reporting the status of the first thread.
gdb/
2014-01-08 Pedro Alves <palves@redhat.com>
* remote.c (remote_add_thread): Add threads silently if starting
up.
(remote_notice_new_inferior): If in all-stop, and starting up,
don't call notice_new_inferior.
(get_current_thread): New function, factored out from ...
(add_current_inferior_and_thread): ... this. Adjust.
(remote_start_remote) <all-stop>: Fetch the thread list. If we
found any thread, then select the remote's current thread as GDB's
current thread too.
gdb/testsuite/
2014-01-08 Pedro Alves <palves@redhat.com>
* gdb.threads/reconnect-signal.c: New file.
* gdb.threads/reconnect-signal.exp: New file.
2014-01-08 19:55:51 +01:00
|
|
|
/* True if LAST_STATUS hasn't been reported to GDB yet. */
|
|
|
|
int status_pending_p;
|
|
|
|
|
gdb/gdbserver:
* server.h: Move some code to ...
* gdbthread.h: ... here. New.
* Makefile.in (inferiors.o, regcache.o): Depends on gdbthread.h
(remote-utils.o, server.o, target.o tracepoint.o): Likewise.
(nto-low.o, win32-low.o): Likewise.
* inferiors.c, linux-low.h, nto-low.c: Include gdbthread.h.
* regcache.c, remote-utils.c, server.c: Likewise.
* target.c, tracepoint.c, win32-low.c: Likewise.
2012-04-29 08:28:30 +02:00
|
|
|
/* Given `while-stepping', a thread may be collecting data for more
|
|
|
|
than one tracepoint simultaneously. E.g.:
|
|
|
|
|
|
|
|
ff0001 INSN1 <-- TP1, while-stepping 10 collect $regs
|
|
|
|
ff0002 INSN2
|
|
|
|
ff0003 INSN3 <-- TP2, collect $regs
|
|
|
|
ff0004 INSN4 <-- TP3, while-stepping 10 collect $regs
|
|
|
|
ff0005 INSN5
|
|
|
|
|
|
|
|
Notice that when instruction INSN5 is reached, the while-stepping
|
|
|
|
actions of both TP1 and TP3 are still being collected, and that TP2
|
|
|
|
had been collected meanwhile. The whole range of ff0001-ff0005
|
|
|
|
should be single-stepped, due to at least TP1's while-stepping
|
|
|
|
action covering the whole range.
|
|
|
|
|
|
|
|
On the other hand, the same tracepoint with a while-stepping action
|
|
|
|
may be hit by more than one thread simultaneously, hence we can't
|
|
|
|
keep the current step count in the tracepoint itself.
|
|
|
|
|
|
|
|
This is the head of the list of the states of `while-stepping'
|
|
|
|
tracepoint actions this thread is now collecting; NULL if empty.
|
|
|
|
Each item in the list holds the current step of the while-stepping
|
|
|
|
action. */
|
|
|
|
struct wstep_state *while_stepping;
|
2013-03-11 09:35:11 +01:00
|
|
|
|
|
|
|
/* Branch trace target information for this thread. */
|
|
|
|
struct btrace_target_info *btrace;
|
gdb/gdbserver:
* server.h: Move some code to ...
* gdbthread.h: ... here. New.
* Makefile.in (inferiors.o, regcache.o): Depends on gdbthread.h
(remote-utils.o, server.o, target.o tracepoint.o): Likewise.
(nto-low.o, win32-low.o): Likewise.
* inferiors.c, linux-low.h, nto-low.c: Include gdbthread.h.
* regcache.c, remote-utils.c, server.c: Likewise.
* target.c, tracepoint.c, win32-low.c: Likewise.
2012-04-29 08:28:30 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
extern struct inferior_list all_threads;
|
|
|
|
|
|
|
|
void remove_thread (struct thread_info *thread);
|
2014-02-20 01:38:44 +01:00
|
|
|
struct thread_info *add_thread (ptid_t ptid, void *target_data);
|
gdb/gdbserver:
* server.h: Move some code to ...
* gdbthread.h: ... here. New.
* Makefile.in (inferiors.o, regcache.o): Depends on gdbthread.h
(remote-utils.o, server.o, target.o tracepoint.o): Likewise.
(nto-low.o, win32-low.o): Likewise.
* inferiors.c, linux-low.h, nto-low.c: Include gdbthread.h.
* regcache.c, remote-utils.c, server.c: Likewise.
* target.c, tracepoint.c, win32-low.c: Likewise.
2012-04-29 08:28:30 +02:00
|
|
|
|
2014-02-20 00:28:50 +01:00
|
|
|
struct thread_info *get_first_thread (void);
|
|
|
|
|
gdb/gdbserver:
* server.h: Move some code to ...
* gdbthread.h: ... here. New.
* Makefile.in (inferiors.o, regcache.o): Depends on gdbthread.h
(remote-utils.o, server.o, target.o tracepoint.o): Likewise.
(nto-low.o, win32-low.o): Likewise.
* inferiors.c, linux-low.h, nto-low.c: Include gdbthread.h.
* regcache.c, remote-utils.c, server.c: Likewise.
* target.c, tracepoint.c, win32-low.c: Likewise.
2012-04-29 08:28:30 +02:00
|
|
|
struct thread_info *find_thread_ptid (ptid_t ptid);
|
|
|
|
|
2012-11-09 03:58:50 +01:00
|
|
|
/* Get current thread ID (Linux task ID). */
|
2014-02-19 23:51:55 +01:00
|
|
|
#define current_ptid (current_inferior->entry.id)
|
2014-01-23 01:39:29 +01:00
|
|
|
|
gdb/gdbserver:
* server.h: Move some code to ...
* gdbthread.h: ... here. New.
* Makefile.in (inferiors.o, regcache.o): Depends on gdbthread.h
(remote-utils.o, server.o, target.o tracepoint.o): Likewise.
(nto-low.o, win32-low.o): Likewise.
* inferiors.c, linux-low.h, nto-low.c: Include gdbthread.h.
* regcache.c, remote-utils.c, server.c: Likewise.
* target.c, tracepoint.c, win32-low.c: Likewise.
2012-04-29 08:28:30 +02:00
|
|
|
#endif /* GDB_THREAD_H */
|