diff options
-rw-r--r-- | gdb/ChangeLog | 11 | ||||
-rw-r--r-- | gdb/remote.c | 80 |
2 files changed, 82 insertions, 9 deletions
diff --git a/gdb/ChangeLog b/gdb/ChangeLog index af0d7e6..2804269 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,14 @@ +2013-01-25 Pedro Alves <palves@redhat.com> + + * remote.c (stop_reply_extract_thread): New. + (add_current_inferior_and_thread): New parameter 'wait_status'. + Handle it. + (remote_start_remote): Pass wait status to + add_current_inferior_and_thread. + (extended_remote_run): Update comment. + (extended_remote_create_inferior_1): Pass wait status to + add_current_inferior_and_thread. + 2013-01-25 Andrew Burgess <aburgess@broadcom.com> Ulrich Weigand <uweigand@de.ibm.com> diff --git a/gdb/remote.c b/gdb/remote.c index 7ea9597..18fe61d 100644 --- a/gdb/remote.c +++ b/gdb/remote.c @@ -3224,22 +3224,77 @@ send_interrupt_sequence (void) interrupt_sequence_mode); } + +/* If STOP_REPLY is a T stop reply, look for the "thread" register, + and extract the PTID. Returns NULL_PTID if not found. */ + +static ptid_t +stop_reply_extract_thread (char *stop_reply) +{ + if (stop_reply[0] == 'T' && strlen (stop_reply) > 3) + { + char *p; + + /* Txx r:val ; r:val (...) */ + p = &stop_reply[3]; + + /* Look for "register" named "thread". */ + while (*p != '\0') + { + char *p1; + + p1 = strchr (p, ':'); + if (p1 == NULL) + return null_ptid; + + if (strncmp (p, "thread", p1 - p) == 0) + return read_ptid (++p1, &p); + + p1 = strchr (p, ';'); + if (p1 == NULL) + return null_ptid; + p1++; + + p = p1; + } + } + + return null_ptid; +} + /* Query the remote target for which is the current thread/process, add it to our tables, and update INFERIOR_PTID. The caller is responsible for setting the state such that the remote end is ready - to return the current thread. */ + to return the current thread. + + This function is called after handling the '?' or 'vRun' packets, + whose response is a stop reply from which we can also try + extracting the thread. If the target doesn't support the explicit + qC query, we infer the current thread from that stop reply, passed + in in WAIT_STATUS, which may be NULL. */ static void -add_current_inferior_and_thread (void) +add_current_inferior_and_thread (char *wait_status) { struct remote_state *rs = get_remote_state (); int fake_pid_p = 0; - ptid_t ptid; + ptid_t ptid = null_ptid; inferior_ptid = null_ptid; - /* Now, if we have thread information, update inferior_ptid. */ - ptid = remote_current_thread (inferior_ptid); + /* Now, if we have thread information, update inferior_ptid. First + if we have a stop reply handy, maybe it's a T stop reply with a + "thread" register we can extract the current thread from. If + not, ask the remote which is the current thread, with qC. The + former method avoids a roundtrip. Note we don't use + remote_parse_stop_reply as that makes use of the target + architecture, which we haven't yet fully determined at this + point. */ + if (wait_status != NULL) + ptid = stop_reply_extract_thread (wait_status); + if (ptid_equal (ptid, null_ptid)) + ptid = remote_current_thread (inferior_ptid); + if (!ptid_equal (ptid, null_ptid)) { if (!remote_multi_process_p (rs)) @@ -3400,7 +3455,7 @@ remote_start_remote (int from_tty, struct target_ops *target, int extended_p) /* Let the stub know that we want it to return the thread. */ set_continue_thread (minus_one_ptid); - add_current_inferior_and_thread (); + add_current_inferior_and_thread (wait_status); /* init_wait_for_inferior should be called before get_offsets in order to manage `inserted' flag in bp loc in a correct state. @@ -7836,7 +7891,7 @@ extended_remote_run (char *args) if (packet_ok (rs->buf, &remote_protocol_packets[PACKET_vRun]) == PACKET_OK) { - /* We have a wait response; we don't need it, though. All is well. */ + /* We have a wait response. All is well. */ return 0; } else if (remote_protocol_packets[PACKET_vRun].support == PACKET_DISABLE) @@ -7863,6 +7918,10 @@ static void extended_remote_create_inferior_1 (char *exec_file, char *args, char **env, int from_tty) { + int run_worked; + char *stop_reply; + struct remote_state *rs = get_remote_state (); + /* If running asynchronously, register the target file descriptor with the event loop. */ if (target_can_async_p ()) @@ -7873,7 +7932,8 @@ extended_remote_create_inferior_1 (char *exec_file, char *args, extended_remote_disable_randomization (disable_randomization); /* Now restart the remote server. */ - if (extended_remote_run (args) == -1) + run_worked = extended_remote_run (args) != -1; + if (!run_worked) { /* vRun was not supported. Fail if we need it to do what the user requested. */ @@ -7895,7 +7955,9 @@ extended_remote_create_inferior_1 (char *exec_file, char *args, init_wait_for_inferior (); } - add_current_inferior_and_thread (); + /* vRun's success return is a stop reply. */ + stop_reply = run_worked ? rs->buf : NULL; + add_current_inferior_and_thread (stop_reply); /* Get updated offsets, if the stub uses qOffsets. */ get_offsets (); |