Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(4)

Unified Diff: gdb/gdbserver/server.c

Issue 11969036: Merge GDB 7.5.1 (Closed) Base URL: http://git.chromium.org/native_client/nacl-gdb.git@master
Patch Set: Created 7 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « gdb/gdbserver/server.h ('k') | gdb/gdbserver/spu-low.c » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: gdb/gdbserver/server.c
diff --git a/gdb/gdbserver/server.c b/gdb/gdbserver/server.c
index c75a58ef151887515154123a297646eb7933ba0a..4e15b3c9fa977dd6551ce85a6b8418a7801c9d68 100644
--- a/gdb/gdbserver/server.c
+++ b/gdb/gdbserver/server.c
@@ -18,6 +18,8 @@
along with this program. If not, see <http://www.gnu.org/licenses/>. */
#include "server.h"
+#include "gdbthread.h"
+#include "agent.h"
#if HAVE_UNISTD_H
#include <unistd.h>
@@ -29,7 +31,19 @@
#include <sys/wait.h>
#endif
+/* The thread set with an `Hc' packet. `Hc' is deprecated in favor of
+ `vCont'. Note the multi-process extensions made `vCont' a
+ requirement, so `Hc pPID.TID' is pretty much undefined. So
+ CONT_THREAD can be null_ptid for no `Hc' thread, minus_one_ptid for
+ resuming all threads of the process (again, `Hc' isn't used for
+ multi-process), or a specific thread ptid_t.
+
+ We also set this when handling a single-thread `vCont' resume, as
+ some places in the backends check it to know when (and for which
+ thread) single-thread scheduler-locking is in effect. */
ptid_t cont_thread;
+
+/* The thread set with an `Hg' packet. */
ptid_t general_thread;
int server_waiting;
@@ -57,7 +71,9 @@ int debug_threads;
/* Enable debugging of h/w breakpoint/watchpoint support. */
int debug_hw_points;
-int pass_signals[TARGET_SIGNAL_LAST];
+int pass_signals[GDB_SIGNAL_LAST];
+int program_signals[GDB_SIGNAL_LAST];
+int program_signals_p;
jmp_buf toplevel;
@@ -259,6 +275,10 @@ start_inferior (char **argv)
signal (SIGTTIN, SIG_DFL);
#endif
+ /* Clear this so the backend doesn't get confused, thinking
+ CONT_THREAD died, and it needs to resume all threads. */
+ cont_thread = null_ptid;
+
signal_pid = create_inferior (new_argv[0], new_argv);
/* FIXME: we don't actually know at this point that the create
@@ -284,7 +304,7 @@ start_inferior (char **argv)
resume_info.kind = resume_continue;
resume_info.sig = 0;
- mywait (pid_to_ptid (signal_pid), &last_status, 0, 0);
+ last_ptid = mywait (pid_to_ptid (signal_pid), &last_status, 0, 0);
if (last_status.kind != TARGET_WAITKIND_STOPPED)
return signal_pid;
@@ -293,17 +313,15 @@ start_inferior (char **argv)
{
(*the_target->resume) (&resume_info, 1);
- mywait (pid_to_ptid (signal_pid), &last_status, 0, 0);
+ last_ptid = mywait (pid_to_ptid (signal_pid), &last_status, 0, 0);
if (last_status.kind != TARGET_WAITKIND_STOPPED)
return signal_pid;
current_inferior->last_resume_kind = resume_stop;
current_inferior->last_status = last_status;
}
- while (last_status.value.sig != TARGET_SIGNAL_TRAP);
+ while (last_status.value.sig != GDB_SIGNAL_TRAP);
- current_inferior->last_resume_kind = resume_stop;
- current_inferior->last_status = last_status;
return signal_pid;
}
@@ -338,6 +356,10 @@ attach_inferior (int pid)
whichever we were told to attach to. */
signal_pid = pid;
+ /* Clear this so the backend doesn't get confused, thinking
+ CONT_THREAD died, and it needs to resume all threads. */
+ cont_thread = null_ptid;
+
if (!non_stop)
{
last_ptid = mywait (pid_to_ptid (pid), &last_status, 0, 0);
@@ -346,8 +368,8 @@ attach_inferior (int pid)
process using the "attach" command, but this is different; it's
just using "target remote". Pretend it's just starting up. */
if (last_status.kind == TARGET_WAITKIND_STOPPED
- && last_status.value.sig == TARGET_SIGNAL_STOP)
- last_status.value.sig = TARGET_SIGNAL_TRAP;
+ && last_status.value.sig == GDB_SIGNAL_STOP)
+ last_status.value.sig = GDB_SIGNAL_TRAP;
current_inferior->last_resume_kind = resume_stop;
current_inferior->last_status = last_status;
@@ -427,7 +449,7 @@ handle_general_set (char *own_buf)
{
if (strncmp ("QPassSignals:", own_buf, strlen ("QPassSignals:")) == 0)
{
- int numsigs = (int) TARGET_SIGNAL_LAST, i;
+ int numsigs = (int) GDB_SIGNAL_LAST, i;
const char *p = own_buf + strlen ("QPassSignals:");
CORE_ADDR cursig;
@@ -450,6 +472,33 @@ handle_general_set (char *own_buf)
return;
}
+ if (strncmp ("QProgramSignals:", own_buf, strlen ("QProgramSignals:")) == 0)
+ {
+ int numsigs = (int) GDB_SIGNAL_LAST, i;
+ const char *p = own_buf + strlen ("QProgramSignals:");
+ CORE_ADDR cursig;
+
+ program_signals_p = 1;
+
+ p = decode_address_to_semicolon (&cursig, p);
+ for (i = 0; i < numsigs; i++)
+ {
+ if (i == cursig)
+ {
+ program_signals[i] = 1;
+ if (*p == '\0')
+ /* Keep looping, to clear the remaining signals. */
+ cursig = -1;
+ else
+ p = decode_address_to_semicolon (&cursig, p);
+ }
+ else
+ program_signals[i] = 0;
+ }
+ strcpy (own_buf, "OK");
+ return;
+ }
+
if (strcmp (own_buf, "QStartNoAckMode") == 0)
{
if (remote_debug)
@@ -525,6 +574,30 @@ handle_general_set (char *own_buf)
&& handle_tracepoint_general_set (own_buf))
return;
+ if (strncmp ("QAgent:", own_buf, strlen ("QAgent:")) == 0)
+ {
+ char *mode = own_buf + strlen ("QAgent:");
+ int req = 0;
+
+ if (strcmp (mode, "0") == 0)
+ req = 0;
+ else if (strcmp (mode, "1") == 0)
+ req = 1;
+ else
+ {
+ /* We don't know what this value is, so complain to GDB. */
+ sprintf (own_buf, "E.Unknown QAgent value");
+ return;
+ }
+
+ /* Update the flag. */
+ use_agent = req;
+ if (remote_debug)
+ fprintf (stderr, "[%s agent]\n", req ? "Enable" : "Disable");
+ write_ok (own_buf);
+ return;
+ }
+
/* Otherwise we didn't know what packet it was. Say we didn't
understand it. */
own_buf[0] = 0;
@@ -807,7 +880,7 @@ handle_search_memory (char *own_buf, int packet_len)
/* Handle monitor commands not handled by target-specific handlers. */
static void
-handle_monitor_command (char *mon)
+handle_monitor_command (char *mon, char *own_buf)
{
if (strcmp (mon, "set debug 1") == 0)
{
@@ -941,10 +1014,6 @@ handle_qxfer_libraries (const char *annex,
if (annex[0] != '\0' || !target_running ())
return -1;
- /* Do not confuse this packet with qXfer:libraries-svr4:read. */
- if (the_target->qxfer_libraries_svr4 != NULL)
- return 0;
-
/* Over-estimate the necessary memory. Assume that every character
in the library name must be escaped. */
total_len = 64;
@@ -1091,14 +1160,11 @@ handle_qxfer_threads_proper (struct buffer *buffer)
{
ptid_t ptid = thread_to_gdb_id ((struct thread_info *)thread);
char ptid_s[100];
- int core = -1;
+ int core = target_core_of_thread (ptid);
char core_s[21];
write_ptid (ptid_s, ptid);
- if (the_target->core_of_thread)
- core = (*the_target->core_of_thread) (ptid);
-
if (core != -1)
{
sprintf (core_s, "%d", core);
@@ -1555,7 +1621,9 @@ handle_query (char *own_buf, int packet_len, int *new_packet_len_p)
free (qsupported);
}
- sprintf (own_buf, "PacketSize=%x;QPassSignals+", PBUFSIZ - 1);
+ sprintf (own_buf,
+ "PacketSize=%x;QPassSignals+;QProgramSignals+",
+ PBUFSIZ - 1);
if (the_target->qxfer_libraries_svr4 != NULL)
strcat (own_buf, ";qXfer:libraries-svr4:read+");
@@ -1617,6 +1685,13 @@ handle_query (char *own_buf, int packet_len, int *new_packet_len_p)
strcat (own_buf, ";tracenz+");
}
+ /* Support target-side breakpoint conditions and commands. */
+ strcat (own_buf, ";ConditionalBreakpoints+");
+ strcat (own_buf, ";BreakpointCommands+");
+
+ if (target_supports_agent ())
+ strcat (own_buf, ";QAgent+");
+
return;
}
@@ -1733,7 +1808,7 @@ handle_query (char *own_buf, int packet_len, int *new_packet_len_p)
if (the_target->handle_monitor_command == NULL
|| (*the_target->handle_monitor_command) (mon) == 0)
/* Default processing. */
- handle_monitor_command (mon);
+ handle_monitor_command (mon, own_buf);
free (mon);
return;
@@ -1859,9 +1934,9 @@ handle_v_cont (char *own_buf)
goto err;
p = q;
- if (!target_signal_to_host_p (sig))
+ if (!gdb_signal_to_host_p (sig))
goto err;
- resume_info[i].sig = target_signal_to_host (sig);
+ resume_info[i].sig = gdb_signal_to_host (sig);
}
else
{
@@ -1896,9 +1971,13 @@ handle_v_cont (char *own_buf)
if (i < n)
resume_info[i] = default_action;
- /* Still used in occasional places in the backend. */
+ /* `cont_thread' is still used in occasional places in the backend,
+ to implement single-thread scheduler-locking. Doesn't make sense
+ to set it if we see a stop request, or a wildcard action (one
+ with '-1' (all threads), or 'pPID.-1' (all threads of PID)). */
if (n == 1
- && !ptid_equal (resume_info[0].thread, minus_one_ptid)
+ && !(ptid_equal (resume_info[0].thread, minus_one_ptid)
+ || ptid_get_lwp (resume_info[0].thread) == -1)
&& resume_info[0].kind != resume_stop)
cont_thread = resume_info[0].thread;
else
@@ -2078,7 +2157,7 @@ handle_v_kill (char *own_buf)
if (pid != 0 && kill_inferior (pid) == 0)
{
last_status.kind = TARGET_WAITKIND_SIGNALLED;
- last_status.value.sig = TARGET_SIGNAL_KILL;
+ last_status.value.sig = GDB_SIGNAL_KILL;
last_ptid = pid_to_ptid (pid);
discard_queued_stop_replies (pid);
write_ok (own_buf);
@@ -2140,7 +2219,7 @@ handle_v_requests (char *own_buf, int packet_len, int *new_packet_len)
if (strncmp (own_buf, "vAttach;", 8) == 0)
{
- if (!multi_process && target_running ())
+ if ((!extended_protocol || !multi_process) && target_running ())
{
fprintf (stderr, "Already debugging a process\n");
write_enn (own_buf);
@@ -2152,7 +2231,7 @@ handle_v_requests (char *own_buf, int packet_len, int *new_packet_len)
if (strncmp (own_buf, "vRun;", 5) == 0)
{
- if (!multi_process && target_running ())
+ if ((!extended_protocol || !multi_process) && target_running ())
{
fprintf (stderr, "Already debugging a process\n");
write_enn (own_buf);
@@ -2301,7 +2380,7 @@ gdb_wants_thread_stopped (struct inferior_list_entry *entry)
/* Most threads are stopped implicitly (all-stop); tag that with
signal 0. */
thread->last_status.kind = TARGET_WAITKIND_STOPPED;
- thread->last_status.value.sig = TARGET_SIGNAL_0;
+ thread->last_status.value.sig = GDB_SIGNAL_0;
}
}
@@ -2356,7 +2435,7 @@ handle_status (char *own_buf)
struct target_waitstatus status;
status.kind = TARGET_WAITKIND_STOPPED;
- status.value.sig = TARGET_SIGNAL_TRAP;
+ status.value.sig = GDB_SIGNAL_TRAP;
prepare_resume_reply (own_buf,
all_threads.head->id, &status);
}
@@ -2524,8 +2603,8 @@ main (int argc, char *argv[])
int pid;
char *arg_end, *port;
char **next_arg = &argv[1];
- int multi_mode = 0;
- int attach = 0;
+ volatile int multi_mode = 0;
+ volatile int attach = 0;
int was_running;
while (*next_arg != NULL && **next_arg == '-')
@@ -2605,6 +2684,13 @@ main (int argc, char *argv[])
}
}
}
+ else if (strcmp (*next_arg, "-") == 0)
+ {
+ /* "-" specifies a stdio connection and is a form of port
+ specification. */
+ *next_arg = STDIO_CONNECTION_NAME;
+ break;
+ }
else if (strcmp (*next_arg, "--disable-randomization") == 0)
disable_randomization = 1;
else if (strcmp (*next_arg, "--no-disable-randomization") == 0)
@@ -2635,6 +2721,12 @@ main (int argc, char *argv[])
exit (1);
}
+ /* We need to know whether the remote connection is stdio before
+ starting the inferior. Inferiors created in this scenario have
+ stdin,stdout redirected. So do this here before we call
+ start_inferior. */
+ remote_prepare (port);
+
bad_attach = 0;
pid = 0;
@@ -2706,7 +2798,14 @@ main (int argc, char *argv[])
if (setjmp (toplevel))
{
- detach_or_kill_for_exit ();
+ /* If something fails and longjmps while detaching or killing
+ inferiors, we'd end up here again, stuck in an infinite loop
+ trap. Be sure that if that happens, we exit immediately
+ instead. */
+ if (setjmp (toplevel) == 0)
+ detach_or_kill_for_exit ();
+ else
+ fprintf (stderr, "Detach or kill failed. Exiting\n");
exit (1);
}
@@ -2722,8 +2821,6 @@ main (int argc, char *argv[])
exit (1);
}
- remote_prepare (port);
-
while (1)
{
noack_mode = 0;
@@ -2754,8 +2851,20 @@ main (int argc, char *argv[])
if (exit_requested || run_once)
{
- detach_or_kill_for_exit ();
- exit (0);
+ /* If something fails and longjmps while detaching or
+ killing inferiors, we'd end up here again, stuck in an
+ infinite loop trap. Be sure that if that happens, we
+ exit immediately instead. */
+ if (setjmp (toplevel) == 0)
+ {
+ detach_or_kill_for_exit ();
+ exit (0);
+ }
+ else
+ {
+ fprintf (stderr, "Detach or kill failed. Exiting\n");
+ exit (1);
+ }
}
fprintf (stderr,
@@ -2791,6 +2900,56 @@ main (int argc, char *argv[])
}
}
+/* Process options coming from Z packets for *point at address
+ POINT_ADDR. PACKET is the packet buffer. *PACKET is updated
+ to point to the first char after the last processed option. */
+
+static void
+process_point_options (CORE_ADDR point_addr, char **packet)
+{
+ char *dataptr = *packet;
+ int persist;
+
+ /* Check if data has the correct format. */
+ if (*dataptr != ';')
+ return;
+
+ dataptr++;
+
+ while (*dataptr)
+ {
+ if (*dataptr == ';')
+ ++dataptr;
+
+ if (*dataptr == 'X')
+ {
+ /* Conditional expression. */
+ fprintf (stderr, "Found breakpoint condition.\n");
+ add_breakpoint_condition (point_addr, &dataptr);
+ }
+ else if (strncmp (dataptr, "cmds:", strlen ("cmds:")) == 0)
+ {
+ dataptr += strlen ("cmds:");
+ if (debug_threads)
+ fprintf (stderr, "Found breakpoint commands %s.\n", dataptr);
+ persist = (*dataptr == '1');
+ dataptr += 2;
+ add_breakpoint_commands (point_addr, &dataptr, persist);
+ }
+ else
+ {
+ /* Unrecognized token, just skip it. */
+ fprintf (stderr, "Unknown token %c, ignoring.\n",
+ *dataptr);
+ }
+
+ /* Skip tokens until we find one that we recognize. */
+ while (*dataptr && *dataptr != 'X' && *dataptr != ';')
+ dataptr++;
+ }
+ *packet = dataptr;
+}
+
/* Event loop callback that handles a serial event. The first byte in
the serial buffer gets us here. We expect characters to arrive at
a brisk pace, so we read the rest of the packet with a blocking
@@ -2851,7 +3010,7 @@ process_serial_event (void)
pid =
ptid_get_pid (((struct inferior_list_entry *) current_inferior)->id);
- if (tracing && disconnected_tracing)
+ if ((tracing && disconnected_tracing) || any_persistent_commands ())
{
struct thread_resume resume_info;
struct process_info *process = find_process_pid (pid);
@@ -2862,9 +3021,15 @@ process_serial_event (void)
break;
}
- fprintf (stderr,
- "Disconnected tracing in effect, "
- "leaving gdbserver attached to the process\n");
+ if (tracing && disconnected_tracing)
+ fprintf (stderr,
+ "Disconnected tracing in effect, "
+ "leaving gdbserver attached to the process\n");
+
+ if (any_persistent_commands ())
+ fprintf (stderr,
+ "Persistent commands are present, "
+ "leaving gdbserver attached to the process\n");
/* Make sure we're in non-stop/async mode, so we we can both
wait for an async socket accept, and handle async target
@@ -3065,8 +3230,8 @@ process_serial_event (void)
case 'C':
require_running (own_buf);
convert_ascii_to_int (own_buf + 1, &sig, 1);
- if (target_signal_to_host_p (sig))
- signal = target_signal_to_host (sig);
+ if (gdb_signal_to_host_p (sig))
+ signal = gdb_signal_to_host (sig);
else
signal = 0;
myresume (own_buf, 0, signal);
@@ -3074,8 +3239,8 @@ process_serial_event (void)
case 'S':
require_running (own_buf);
convert_ascii_to_int (own_buf + 1, &sig, 1);
- if (target_signal_to_host_p (sig))
- signal = target_signal_to_host (sig);
+ if (gdb_signal_to_host_p (sig))
+ signal = gdb_signal_to_host (sig);
else
signal = 0;
myresume (own_buf, 1, signal);
@@ -3113,7 +3278,22 @@ process_serial_event (void)
case '4': /* access watchpoint */
require_running (own_buf);
if (insert && the_target->insert_point != NULL)
- res = (*the_target->insert_point) (type, addr, len);
+ {
+ /* Insert the breakpoint. If it is already inserted, nothing
+ will take place. */
+ res = (*the_target->insert_point) (type, addr, len);
+
+ /* GDB may have sent us a list of *point parameters to be
+ evaluated on the target's side. Read such list here. If we
+ already have a list of parameters, GDB is telling us to drop
+ that list and use this one instead. */
+ if (!res && (type == '0' || type == '1'))
+ {
+ /* Remove previous conditions. */
+ clear_gdb_breakpoint_conditions (addr);
+ process_point_options (addr, &dataptr);
+ }
+ }
else if (!insert && the_target->remove_point != NULL)
res = (*the_target->remove_point) (type, addr, len);
break;
@@ -3145,7 +3325,7 @@ process_serial_event (void)
if (extended_protocol)
{
last_status.kind = TARGET_WAITKIND_EXITED;
- last_status.value.sig = TARGET_SIGNAL_KILL;
+ last_status.value.sig = GDB_SIGNAL_KILL;
return 0;
}
else
@@ -3189,7 +3369,7 @@ process_serial_event (void)
else
{
last_status.kind = TARGET_WAITKIND_EXITED;
- last_status.value.sig = TARGET_SIGNAL_KILL;
+ last_status.value.sig = GDB_SIGNAL_KILL;
}
return 0;
}
@@ -3313,7 +3493,7 @@ handle_target_event (int err, gdb_client_data client_data)
resume_info.thread = last_ptid;
resume_info.kind = resume_continue;
- resume_info.sig = target_signal_to_host (last_status.value.sig);
+ resume_info.sig = gdb_signal_to_host (last_status.value.sig);
(*the_target->resume) (&resume_info, 1);
}
else if (debug_threads)
« no previous file with comments | « gdb/gdbserver/server.h ('k') | gdb/gdbserver/spu-low.c » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698