X-Git-Url: http://drtracing.org/?a=blobdiff_plain;f=gdb%2Fremote.c;h=2f34c4c300f0f529bd726358ff980622459753dd;hb=59a561480d547d041127630b1ba17a284eef8225;hp=96f0ad5c7942194890314a139abc12fb4191a876;hpb=7b68ffbb32645c5383e74f27248a1c1c7ecd241a;p=deliverable%2Fbinutils-gdb.git diff --git a/gdb/remote.c b/gdb/remote.c index 96f0ad5c79..2f34c4c300 100644 --- a/gdb/remote.c +++ b/gdb/remote.c @@ -1,6 +1,6 @@ /* Remote target communications for serial-line targets in custom GDB protocol - Copyright (C) 1988-2016 Free Software Foundation, Inc. + Copyright (C) 1988-2017 Free Software Foundation, Inc. This file is part of GDB. @@ -283,6 +283,11 @@ typedef unsigned char threadref[OPAQUETHREADBYTES]; #define MAXTHREADLISTRESULTS 32 +/* The max number of chars in debug output. The rest of chars are + omitted. */ + +#define REMOTE_DEBUG_MAX_CHAR 512 + /* Data for the vFile:pread readahead cache. */ struct readahead_cache @@ -452,6 +457,24 @@ struct private_thread_info /* This is set to the data address of the access causing the target to stop for a watchpoint. */ CORE_ADDR watch_data_address; + + /* Fields used by the vCont action coalescing implemented in + remote_resume / remote_commit_resume. remote_resume stores each + thread's last resume request in these fields, so that a later + remote_commit_resume knows which is the proper action for this + thread to include in the vCont packet. */ + + /* True if the last target_resume call for this thread was a step + request, false if a continue request. */ + int last_resume_step; + + /* The signal specified in the last target_resume call for this + thread. */ + enum gdb_signal last_resume_sig; + + /* Whether this thread was already vCont-resumed on the remote + side. */ + int vcont_resumed; }; static void @@ -1805,6 +1828,9 @@ remote_add_inferior (int fake_pid_p, int pid, int attached, return inf; } +static struct private_thread_info * + get_private_info_thread (struct thread_info *info); + /* Add thread PTID to GDB's thread list. Tag it as executing/running according to RUNNING. */ @@ -1812,6 +1838,7 @@ static void remote_add_thread (ptid_t ptid, int running, int executing) { struct remote_state *rs = get_remote_state (); + struct thread_info *thread; /* GDB historically didn't pull threads in the initial connection setup. If the remote target doesn't even have a concept of @@ -1820,10 +1847,11 @@ remote_add_thread (ptid_t ptid, int running, int executing) might be confusing to the user. Be silent then, preserving the age old behavior. */ if (rs->starting_up) - add_thread_silent (ptid); + thread = add_thread_silent (ptid); else - add_thread (ptid); + thread = add_thread (ptid); + get_private_info_thread (thread)->vcont_resumed = executing; set_executing (ptid, executing); set_running (ptid, running); } @@ -1918,25 +1946,40 @@ remote_notice_new_inferior (ptid_t currthread, int executing) } } -/* Return the private thread data, creating it if necessary. */ +/* Return THREAD's private thread data, creating it if necessary. */ static struct private_thread_info * -demand_private_info (ptid_t ptid) +get_private_info_thread (struct thread_info *thread) { - struct thread_info *info = find_thread_ptid (ptid); - - gdb_assert (info); + gdb_assert (thread != NULL); - if (!info->priv) + if (thread->priv == NULL) { - info->priv = XNEW (struct private_thread_info); - info->private_dtor = free_private_thread_info; - info->priv->core = -1; - info->priv->extra = NULL; - info->priv->name = NULL; + struct private_thread_info *priv = XNEW (struct private_thread_info); + + thread->private_dtor = free_private_thread_info; + thread->priv = priv; + + priv->core = -1; + priv->extra = NULL; + priv->name = NULL; + priv->name = NULL; + priv->last_resume_step = 0; + priv->last_resume_sig = GDB_SIGNAL_0; + priv->vcont_resumed = 0; } - return info->priv; + return thread->priv; +} + +/* Return PTID's private thread data, creating it if necessary. */ + +static struct private_thread_info * +get_private_info_ptid (ptid_t ptid) +{ + struct thread_info *info = find_thread_ptid (ptid); + + return get_private_info_thread (info); } /* Call this function as a result of @@ -3280,7 +3323,7 @@ remote_update_thread_list (struct target_ops *ops) remote_notice_new_inferior (item->ptid, executing); - info = demand_private_info (item->ptid); + info = get_private_info_ptid (item->ptid); info->core = item->core; info->extra = item->extra; item->extra = NULL; @@ -3913,6 +3956,7 @@ process_initial_stop_replies (int from_tty) set_executing (event_ptid, 0); set_running (event_ptid, 0); + thread->priv->vcont_resumed = 0; } /* "Notice" the new inferiors before anything related to @@ -5701,6 +5745,26 @@ remote_resume (struct target_ops *ops, { struct remote_state *rs = get_remote_state (); + /* When connected in non-stop mode, the core resumes threads + individually. Resuming remote threads directly in target_resume + would thus result in sending one packet per thread. Instead, to + minimize roundtrip latency, here we just store the resume + request; the actual remote resumption will be done in + target_commit_resume / remote_commit_resume, where we'll be able + to do vCont action coalescing. */ + if (target_is_non_stop_p () && execution_direction != EXEC_REVERSE) + { + struct private_thread_info *remote_thr; + + if (ptid_equal (minus_one_ptid, ptid) || ptid_is_pid (ptid)) + remote_thr = get_private_info_ptid (inferior_ptid); + else + remote_thr = get_private_info_ptid (ptid); + remote_thr->last_resume_step = step; + remote_thr->last_resume_sig = siggnal; + return; + } + /* In all-stop, we can't mark REMOTE_ASYNC_GET_PENDING_EVENTS_TOKEN (explained in remote-notif.c:handle_notification) so remote_notif_process is not called. We need find a place where @@ -5736,6 +5800,283 @@ remote_resume (struct target_ops *ops, if (!target_is_non_stop_p ()) rs->waiting_for_stop_reply = 1; } + +static void check_pending_events_prevent_wildcard_vcont + (int *may_global_wildcard_vcont); +static int is_pending_fork_parent_thread (struct thread_info *thread); + +/* Private per-inferior info for target remote processes. */ + +struct private_inferior +{ + /* Whether we can send a wildcard vCont for this process. */ + int may_wildcard_vcont; +}; + +/* Structure used to track the construction of a vCont packet in the + outgoing packet buffer. This is used to send multiple vCont + packets if we have more actions than would fit a single packet. */ + +struct vcont_builder +{ + /* Pointer to the first action. P points here if no action has been + appended yet. */ + char *first_action; + + /* Where the next action will be appended. */ + char *p; + + /* The end of the buffer. Must never write past this. */ + char *endp; +}; + +/* Prepare the outgoing buffer for a new vCont packet. */ + +static void +vcont_builder_restart (struct vcont_builder *builder) +{ + struct remote_state *rs = get_remote_state (); + + builder->p = rs->buf; + builder->endp = rs->buf + get_remote_packet_size (); + builder->p += xsnprintf (builder->p, builder->endp - builder->p, "vCont"); + builder->first_action = builder->p; +} + +/* If the vCont packet being built has any action, send it to the + remote end. */ + +static void +vcont_builder_flush (struct vcont_builder *builder) +{ + struct remote_state *rs; + + if (builder->p == builder->first_action) + return; + + rs = get_remote_state (); + putpkt (rs->buf); + getpkt (&rs->buf, &rs->buf_size, 0); + if (strcmp (rs->buf, "OK") != 0) + error (_("Unexpected vCont reply in non-stop mode: %s"), rs->buf); +} + +/* The largest action is range-stepping, with its two addresses. This + is more than sufficient. If a new, bigger action is created, it'll + quickly trigger a failed assertion in append_resumption (and we'll + just bump this). */ +#define MAX_ACTION_SIZE 200 + +/* Append a new vCont action in the outgoing packet being built. If + the action doesn't fit the packet along with previous actions, push + what we've got so far to the remote end and start over a new vCont + packet (with the new action). */ + +static void +vcont_builder_push_action (struct vcont_builder *builder, + ptid_t ptid, int step, enum gdb_signal siggnal) +{ + char buf[MAX_ACTION_SIZE + 1]; + char *endp; + size_t rsize; + + endp = append_resumption (buf, buf + sizeof (buf), + ptid, step, siggnal); + + /* Check whether this new action would fit in the vCont packet along + with previous actions. If not, send what we've got so far and + start a new vCont packet. */ + rsize = endp - buf; + if (rsize > builder->endp - builder->p) + { + vcont_builder_flush (builder); + vcont_builder_restart (builder); + + /* Should now fit. */ + gdb_assert (rsize <= builder->endp - builder->p); + } + + memcpy (builder->p, buf, rsize); + builder->p += rsize; + *builder->p = '\0'; +} + +/* to_commit_resume implementation. */ + +static void +remote_commit_resume (struct target_ops *ops) +{ + struct remote_state *rs = get_remote_state (); + struct inferior *inf; + struct thread_info *tp; + int any_process_wildcard; + int may_global_wildcard_vcont; + struct vcont_builder vcont_builder; + + /* If connected in all-stop mode, we'd send the remote resume + request directly from remote_resume. Likewise if + reverse-debugging, as there are no defined vCont actions for + reverse execution. */ + if (!target_is_non_stop_p () || execution_direction == EXEC_REVERSE) + return; + + /* Try to send wildcard actions ("vCont;c" or "vCont;c:pPID.-1") + instead of resuming all threads of each process individually. + However, if any thread of a process must remain halted, we can't + send wildcard resumes and must send one action per thread. + + Care must be taken to not resume threads/processes the server + side already told us are stopped, but the core doesn't know about + yet, because the events are still in the vStopped notification + queue. For example: + + #1 => vCont s:p1.1;c + #2 <= OK + #3 <= %Stopped T05 p1.1 + #4 => vStopped + #5 <= T05 p1.2 + #6 => vStopped + #7 <= OK + #8 (infrun handles the stop for p1.1 and continues stepping) + #9 => vCont s:p1.1;c + + The last vCont above would resume thread p1.2 by mistake, because + the server has no idea that the event for p1.2 had not been + handled yet. + + The server side must similarly ignore resume actions for the + thread that has a pending %Stopped notification (and any other + threads with events pending), until GDB acks the notification + with vStopped. Otherwise, e.g., the following case is + mishandled: + + #1 => g (or any other packet) + #2 <= [registers] + #3 <= %Stopped T05 p1.2 + #4 => vCont s:p1.1;c + #5 <= OK + + Above, the server must not resume thread p1.2. GDB can't know + that p1.2 stopped until it acks the %Stopped notification, and + since from GDB's perspective all threads should be running, it + sends a "c" action. + + Finally, special care must also be given to handling fork/vfork + events. A (v)fork event actually tells us that two processes + stopped -- the parent and the child. Until we follow the fork, + we must not resume the child. Therefore, if we have a pending + fork follow, we must not send a global wildcard resume action + (vCont;c). We can still send process-wide wildcards though. */ + + /* Start by assuming a global wildcard (vCont;c) is possible. */ + may_global_wildcard_vcont = 1; + + /* And assume every process is individually wildcard-able too. */ + ALL_NON_EXITED_INFERIORS (inf) + { + if (inf->priv == NULL) + inf->priv = XNEW (struct private_inferior); + inf->priv->may_wildcard_vcont = 1; + } + + /* Check for any pending events (not reported or processed yet) and + disable process and global wildcard resumes appropriately. */ + check_pending_events_prevent_wildcard_vcont (&may_global_wildcard_vcont); + + ALL_NON_EXITED_THREADS (tp) + { + /* If a thread of a process is not meant to be resumed, then we + can't wildcard that process. */ + if (!tp->executing) + { + tp->inf->priv->may_wildcard_vcont = 0; + + /* And if we can't wildcard a process, we can't wildcard + everything either. */ + may_global_wildcard_vcont = 0; + continue; + } + + /* If a thread is the parent of an unfollowed fork, then we + can't do a global wildcard, as that would resume the fork + child. */ + if (is_pending_fork_parent_thread (tp)) + may_global_wildcard_vcont = 0; + } + + /* Now let's build the vCont packet(s). Actions must be appended + from narrower to wider scopes (thread -> process -> global). If + we end up with too many actions for a single packet vcont_builder + flushes the current vCont packet to the remote side and starts a + new one. */ + vcont_builder_restart (&vcont_builder); + + /* Threads first. */ + ALL_NON_EXITED_THREADS (tp) + { + struct private_thread_info *remote_thr = tp->priv; + + if (!tp->executing || remote_thr->vcont_resumed) + continue; + + gdb_assert (!thread_is_in_step_over_chain (tp)); + + if (!remote_thr->last_resume_step + && remote_thr->last_resume_sig == GDB_SIGNAL_0 + && tp->inf->priv->may_wildcard_vcont) + { + /* We'll send a wildcard resume instead. */ + remote_thr->vcont_resumed = 1; + continue; + } + + vcont_builder_push_action (&vcont_builder, tp->ptid, + remote_thr->last_resume_step, + remote_thr->last_resume_sig); + remote_thr->vcont_resumed = 1; + } + + /* Now check whether we can send any process-wide wildcard. This is + to avoid sending a global wildcard in the case nothing is + supposed to be resumed. */ + any_process_wildcard = 0; + + ALL_NON_EXITED_INFERIORS (inf) + { + if (inf->priv->may_wildcard_vcont) + { + any_process_wildcard = 1; + break; + } + } + + if (any_process_wildcard) + { + /* If all processes are wildcard-able, then send a single "c" + action, otherwise, send an "all (-1) threads of process" + continue action for each running process, if any. */ + if (may_global_wildcard_vcont) + { + vcont_builder_push_action (&vcont_builder, minus_one_ptid, + 0, GDB_SIGNAL_0); + } + else + { + ALL_NON_EXITED_INFERIORS (inf) + { + if (inf->priv->may_wildcard_vcont) + { + vcont_builder_push_action (&vcont_builder, + pid_to_ptid (inf->pid), + 0, GDB_SIGNAL_0); + } + } + } + } + + vcont_builder_flush (&vcont_builder); +} + /* Non-stop version of target_stop. Uses `vCont;t' to stop a remote @@ -5970,7 +6311,7 @@ remote_console_output (char *msg) typedef struct cached_reg { int num; - gdb_byte data[MAX_REGISTER_SIZE]; + gdb_byte *data; } cached_reg_t; DEF_VEC_O(cached_reg_t); @@ -6066,6 +6407,13 @@ static void stop_reply_dtr (struct notif_event *event) { struct stop_reply *r = (struct stop_reply *) event; + cached_reg_t *reg; + int ix; + + for (ix = 0; + VEC_iterate (cached_reg_t, r->regcache, ix, reg); + ix++) + xfree (reg->data); VEC_free (cached_reg_t, r->regcache); } @@ -6102,7 +6450,7 @@ struct queue_iter_param struct stop_reply *output; }; -/* Determine if THREAD is a pending fork parent thread. ARG contains +/* Determine if THREAD_PTID is a pending fork parent thread. ARG contains the pid of the process that owns the threads we want to check, or -1 if we want to check all threads. */ @@ -6120,6 +6468,29 @@ is_pending_fork_parent (struct target_waitstatus *ws, int event_pid, return 0; } +/* Return the thread's pending status used to determine whether the + thread is a fork parent stopped at a fork event. */ + +static struct target_waitstatus * +thread_pending_fork_status (struct thread_info *thread) +{ + if (thread->suspend.waitstatus_pending_p) + return &thread->suspend.waitstatus; + else + return &thread->pending_follow; +} + +/* Determine if THREAD is a pending fork parent thread. */ + +static int +is_pending_fork_parent_thread (struct thread_info *thread) +{ + struct target_waitstatus *ws = thread_pending_fork_status (thread); + int pid = -1; + + return is_pending_fork_parent (ws, pid, thread->ptid); +} + /* Check whether EVENT is a fork event, and if it is, remove the fork child from the context list passed in DATA. */ @@ -6159,12 +6530,7 @@ remove_new_fork_children (struct threads_listing_context *context) fork child threads from the CONTEXT list. */ ALL_NON_EXITED_THREADS (thread) { - struct target_waitstatus *ws; - - if (thread->suspend.waitstatus_pending_p) - ws = &thread->suspend.waitstatus; - else - ws = &thread->pending_follow; + struct target_waitstatus *ws = thread_pending_fork_status (thread); if (is_pending_fork_parent (ws, pid, thread->ptid)) { @@ -6182,6 +6548,56 @@ remove_new_fork_children (struct threads_listing_context *context) remove_child_of_pending_fork, ¶m); } +/* Check whether EVENT would prevent a global or process wildcard + vCont action. */ + +static int +check_pending_event_prevents_wildcard_vcont_callback + (QUEUE (stop_reply_p) *q, + QUEUE_ITER (stop_reply_p) *iter, + stop_reply_p event, + void *data) +{ + struct inferior *inf; + int *may_global_wildcard_vcont = (int *) data; + + if (event->ws.kind == TARGET_WAITKIND_NO_RESUMED + || event->ws.kind == TARGET_WAITKIND_NO_HISTORY) + return 1; + + if (event->ws.kind == TARGET_WAITKIND_FORKED + || event->ws.kind == TARGET_WAITKIND_VFORKED) + *may_global_wildcard_vcont = 0; + + inf = find_inferior_ptid (event->ptid); + + /* This may be the first time we heard about this process. + Regardless, we must not do a global wildcard resume, otherwise + we'd resume this process too. */ + *may_global_wildcard_vcont = 0; + if (inf != NULL) + inf->priv->may_wildcard_vcont = 0; + + return 1; +} + +/* Check whether any event pending in the vStopped queue would prevent + a global or process wildcard vCont action. Clear + *may_global_wildcard if we can't do a global wildcard (vCont;c), + and clear the event inferior's may_wildcard_vcont flag if we can't + do a process-wide wildcard resume (vCont;c:pPID.-1). */ + +static void +check_pending_events_prevent_wildcard_vcont (int *may_global_wildcard) +{ + struct notif_client *notif = ¬if_client_stop; + + remote_notif_get_pending_events (notif); + QUEUE_iterate (stop_reply_p, stop_reply_queue, + check_pending_event_prevents_wildcard_vcont_callback, + may_global_wildcard); +} + /* Remove stop replies in the queue if its pid is equal to the given inferior's pid. */ @@ -6570,6 +6986,7 @@ Packet: '%s'\n"), { struct packet_reg *reg = packet_reg_from_pnum (rsa, pnum); cached_reg_t cached_reg; + struct gdbarch *gdbarch = target_gdbarch (); if (reg == NULL) error (_("Remote sent bad register number %s: %s\n\ @@ -6577,14 +6994,14 @@ Packet: '%s'\n"), hex_string (pnum), p, buf); cached_reg.num = reg->regnum; + cached_reg.data = (gdb_byte *) + xmalloc (register_size (gdbarch, reg->regnum)); p = p1 + 1; fieldsize = hex2bin (p, cached_reg.data, - register_size (target_gdbarch (), - reg->regnum)); + register_size (gdbarch, reg->regnum)); p += 2 * fieldsize; - if (fieldsize < register_size (target_gdbarch (), - reg->regnum)) + if (fieldsize < register_size (gdbarch, reg->regnum)) warning (_("Remote reply is too short: %s"), buf); VEC_safe_push (cached_reg_t, event->regcache, &cached_reg); @@ -6805,17 +7222,22 @@ process_stop_reply (struct stop_reply *stop_reply, int ix; for (ix = 0; - VEC_iterate(cached_reg_t, stop_reply->regcache, ix, reg); + VEC_iterate (cached_reg_t, stop_reply->regcache, ix, reg); ix++) + { regcache_raw_supply (regcache, reg->num, reg->data); + xfree (reg->data); + } + VEC_free (cached_reg_t, stop_reply->regcache); } remote_notice_new_inferior (ptid, 0); - remote_thr = demand_private_info (ptid); + remote_thr = get_private_info_ptid (ptid); remote_thr->core = stop_reply->core; remote_thr->stop_reason = stop_reply->stop_reason; remote_thr->watch_data_address = stop_reply->watch_data_address; + remote_thr->vcont_resumed = 0; } stop_reply_xfree (stop_reply); @@ -7057,9 +7479,10 @@ remote_wait (struct target_ops *ops, static int fetch_register_using_p (struct regcache *regcache, struct packet_reg *reg) { + struct gdbarch *gdbarch = get_regcache_arch (regcache); struct remote_state *rs = get_remote_state (); char *buf, *p; - char regp[MAX_REGISTER_SIZE]; + gdb_byte *regp = (gdb_byte *) alloca (register_size (gdbarch, reg->regnum)); int i; if (packet_support (PACKET_p) == PACKET_DISABLE) @@ -7174,18 +7597,31 @@ process_g_packet (struct regcache *regcache) the 'p' packet must be used. */ if (buf_len < 2 * rsa->sizeof_g_packet) { - rsa->sizeof_g_packet = buf_len / 2; + long sizeof_g_packet = buf_len / 2; for (i = 0; i < gdbarch_num_regs (gdbarch); i++) { + long offset = rsa->regs[i].offset; + long reg_size = register_size (gdbarch, i); + if (rsa->regs[i].pnum == -1) continue; - if (rsa->regs[i].offset >= rsa->sizeof_g_packet) + if (offset >= sizeof_g_packet) rsa->regs[i].in_g_packet = 0; + else if (offset + reg_size > sizeof_g_packet) + error (_("Truncated register %d in remote 'g' packet"), i); else rsa->regs[i].in_g_packet = 1; } + + /* Looks valid enough, we can assume this is the correct length + for a 'g' packet. It's important not to adjust + rsa->sizeof_g_packet if we have truncated registers otherwise + this "if" won't be run the next time the method is called + with a packet of the same size and one of the internal errors + below will trigger instead. */ + rsa->sizeof_g_packet = sizeof_g_packet; } regs = (char *) alloca (rsa->sizeof_g_packet); @@ -7215,10 +7651,11 @@ process_g_packet (struct regcache *regcache) for (i = 0; i < gdbarch_num_regs (gdbarch); i++) { struct packet_reg *r = &rsa->regs[i]; + long reg_size = register_size (gdbarch, i); if (r->in_g_packet) { - if (r->offset * 2 >= strlen (rs->buf)) + if ((r->offset + reg_size) * 2 > strlen (rs->buf)) /* This shouldn't happen - we adjusted in_g_packet above. */ internal_error (__FILE__, __LINE__, _("unexpected end of 'g' packet reply")); @@ -7322,7 +7759,6 @@ remote_prepare_to_store (struct target_ops *self, struct regcache *regcache) { struct remote_arch_state *rsa = get_remote_arch_state (); int i; - gdb_byte buf[MAX_REGISTER_SIZE]; /* Make sure the entire registers array is valid. */ switch (packet_support (PACKET_P)) @@ -7332,7 +7768,7 @@ remote_prepare_to_store (struct target_ops *self, struct regcache *regcache) /* Make sure all the necessary registers are cached. */ for (i = 0; i < gdbarch_num_regs (get_regcache_arch (regcache)); i++) if (rsa->regs[i].in_g_packet) - regcache_raw_read (regcache, rsa->regs[i].regnum, buf); + regcache_raw_update (regcache, rsa->regs[i].regnum); break; case PACKET_ENABLE: break; @@ -7350,7 +7786,7 @@ store_register_using_P (const struct regcache *regcache, struct remote_state *rs = get_remote_state (); /* Try storing a single register. */ char *buf = rs->buf; - gdb_byte regp[MAX_REGISTER_SIZE]; + gdb_byte *regp = (gdb_byte *) alloca (register_size (gdbarch, reg->regnum)); char *p; if (packet_support (PACKET_P) == PACKET_DISABLE) @@ -8231,25 +8667,16 @@ remote_send (char **buf, error (_("Remote failure reply: %s"), *buf); } -/* Return a pointer to an xmalloc'ed string representing an escaped - version of BUF, of len N. E.g. \n is converted to \\n, \t to \\t, - etc. The caller is responsible for releasing the returned - memory. */ +/* Return a string representing an escaped version of BUF, of len N. + E.g. \n is converted to \\n, \t to \\t, etc. */ -static char * +static std::string escape_buffer (const char *buf, int n) { - struct cleanup *old_chain; - struct ui_file *stb; - char *str; + string_file stb; - stb = mem_fileopen (); - old_chain = make_cleanup_ui_file_delete (stb); - - fputstrn_unfiltered (buf, n, '\\', stb); - str = ui_file_xstrdup (stb, NULL); - do_cleanups (old_chain); - return str; + stb.putstrn (buf, n, '\\'); + return std::move (stb.string ()); } /* Display a null-terminated packet on stdout, for debugging, using C @@ -8331,15 +8758,24 @@ putpkt_binary (const char *buf, int cnt) if (remote_debug) { - struct cleanup *old_chain; - char *str; - *p = '\0'; - str = escape_buffer (buf2, p - buf2); - old_chain = make_cleanup (xfree, str); - fprintf_unfiltered (gdb_stdlog, "Sending packet: %s...", str); + + int len = (int) (p - buf2); + + std::string str + = escape_buffer (buf2, std::min (len, REMOTE_DEBUG_MAX_CHAR)); + + fprintf_unfiltered (gdb_stdlog, "Sending packet: %s", str.c_str ()); + + if (str.length () > REMOTE_DEBUG_MAX_CHAR) + { + fprintf_unfiltered (gdb_stdlog, "[%zu bytes omitted]", + str.length () - REMOTE_DEBUG_MAX_CHAR); + } + + fprintf_unfiltered (gdb_stdlog, "..."); + gdb_flush (gdb_stdlog); - do_cleanups (old_chain); } remote_serial_write (buf2, p - buf2); @@ -8417,15 +8853,11 @@ putpkt_binary (const char *buf, int cnt) { if (remote_debug) { - struct cleanup *old_chain; - char *str; + std::string str = escape_buffer (rs->buf, val); - str = escape_buffer (rs->buf, val); - old_chain = make_cleanup (xfree, str); fprintf_unfiltered (gdb_stdlog, " Notification received: %s\n", - str); - do_cleanups (old_chain); + str.c_str ()); } handle_notification (rs->notif_state, rs->buf); /* We're in sync now, rewait for the ack. */ @@ -8591,16 +9023,12 @@ read_frame (char **buf_p, if (remote_debug) { - struct cleanup *old_chain; - char *str; + std::string str = escape_buffer (buf, bc); - str = escape_buffer (buf, bc); - old_chain = make_cleanup (xfree, str); fprintf_unfiltered (gdb_stdlog, "Bad checksum, sentsum=0x%x, " "csum=0x%x, buf=%s\n", - pktcsum, csum, str); - do_cleanups (old_chain); + pktcsum, csum, str.c_str ()); } /* Number of characters in buffer ignoring trailing NULL. */ @@ -8774,13 +9202,20 @@ getpkt_or_notif_sane_1 (char **buf, long *sizeof_buf, int forever, { if (remote_debug) { - struct cleanup *old_chain; - char *str; + std::string str + = escape_buffer (*buf, + std::min (val, REMOTE_DEBUG_MAX_CHAR)); - str = escape_buffer (*buf, val); - old_chain = make_cleanup (xfree, str); - fprintf_unfiltered (gdb_stdlog, "Packet received: %s\n", str); - do_cleanups (old_chain); + fprintf_unfiltered (gdb_stdlog, "Packet received: %s", + str.c_str ()); + + if (str.length () > REMOTE_DEBUG_MAX_CHAR) + { + fprintf_unfiltered (gdb_stdlog, "[%zu bytes omitted]", + str.length () - REMOTE_DEBUG_MAX_CHAR); + } + + fprintf_unfiltered (gdb_stdlog, "\n"); } /* Skip the ack char if we're in no-ack mode. */ @@ -8799,15 +9234,11 @@ getpkt_or_notif_sane_1 (char **buf, long *sizeof_buf, int forever, if (remote_debug) { - struct cleanup *old_chain; - char *str; + std::string str = escape_buffer (*buf, val); - str = escape_buffer (*buf, val); - old_chain = make_cleanup (xfree, str); fprintf_unfiltered (gdb_stdlog, " Notification received: %s\n", - str); - do_cleanups (old_chain); + str.c_str ()); } if (is_notif != NULL) *is_notif = 1; @@ -9226,24 +9657,19 @@ remote_add_target_side_condition (struct gdbarch *gdbarch, struct bp_target_info *bp_tgt, char *buf, char *buf_end) { - struct agent_expr *aexpr = NULL; - int i, ix; - - if (VEC_empty (agent_expr_p, bp_tgt->conditions)) + if (bp_tgt->conditions.empty ()) return 0; buf += strlen (buf); xsnprintf (buf, buf_end - buf, "%s", ";"); buf++; - /* Send conditions to the target and free the vector. */ - for (ix = 0; - VEC_iterate (agent_expr_p, bp_tgt->conditions, ix, aexpr); - ix++) + /* Send conditions to the target. */ + for (agent_expr *aexpr : bp_tgt->conditions) { xsnprintf (buf, buf_end - buf, "X%x,", aexpr->len); buf += strlen (buf); - for (i = 0; i < aexpr->len; ++i) + for (int i = 0; i < aexpr->len; ++i) buf = pack_hex_byte (buf, aexpr->buf[i]); *buf = '\0'; } @@ -9254,10 +9680,7 @@ static void remote_add_target_side_commands (struct gdbarch *gdbarch, struct bp_target_info *bp_tgt, char *buf) { - struct agent_expr *aexpr = NULL; - int i, ix; - - if (VEC_empty (agent_expr_p, bp_tgt->tcommands)) + if (bp_tgt->tcommands.empty ()) return; buf += strlen (buf); @@ -9267,13 +9690,11 @@ remote_add_target_side_commands (struct gdbarch *gdbarch, /* Concatenate all the agent expressions that are commands into the cmds parameter. */ - for (ix = 0; - VEC_iterate (agent_expr_p, bp_tgt->tcommands, ix, aexpr); - ix++) + for (agent_expr *aexpr : bp_tgt->tcommands) { sprintf (buf, "X%x,", aexpr->len); buf += strlen (buf); - for (i = 0; i < aexpr->len; ++i) + for (int i = 0; i < aexpr->len; ++i) buf = pack_hex_byte (buf, aexpr->buf[i]); *buf = '\0'; } @@ -9305,8 +9726,6 @@ remote_insert_breakpoint (struct target_ops *ops, if (!gdbarch_has_global_breakpoints (target_gdbarch ())) set_general_process (); - gdbarch_remote_breakpoint_from_pc (gdbarch, &addr, &bpsize); - rs = get_remote_state (); p = rs->buf; endbuf = rs->buf + get_remote_packet_size (); @@ -9316,7 +9735,7 @@ remote_insert_breakpoint (struct target_ops *ops, *(p++) = ','; addr = (ULONGEST) remote_address_masked (addr); p += hexnumstr (p, addr); - xsnprintf (p, endbuf - p, ",%d", bpsize); + xsnprintf (p, endbuf - p, ",%d", bp_tgt->kind); if (remote_supports_cond_breakpoints (ops)) remote_add_target_side_condition (gdbarch, bp_tgt, p, endbuf); @@ -9332,8 +9751,6 @@ remote_insert_breakpoint (struct target_ops *ops, case PACKET_ERROR: return -1; case PACKET_OK: - bp_tgt->placed_address = addr; - bp_tgt->placed_size = bpsize; return 0; case PACKET_UNKNOWN: break; @@ -9342,7 +9759,7 @@ remote_insert_breakpoint (struct target_ops *ops, /* If this breakpoint has target-side commands but this stub doesn't support Z0 packets, throw error. */ - if (!VEC_empty (agent_expr_p, bp_tgt->tcommands)) + if (!bp_tgt->tcommands.empty ()) throw_error (NOT_SUPPORTED_ERROR, _("\ Target doesn't support breakpoints that have target side commands.")); @@ -9374,7 +9791,7 @@ remote_remove_breakpoint (struct target_ops *ops, addr = (ULONGEST) remote_address_masked (bp_tgt->placed_address); p += hexnumstr (p, addr); - xsnprintf (p, endbuf - p, ",%d", bp_tgt->placed_size); + xsnprintf (p, endbuf - p, ",%d", bp_tgt->kind); putpkt (rs->buf); getpkt (&rs->buf, &rs->buf_size, 0); @@ -9610,12 +10027,6 @@ remote_insert_hw_breakpoint (struct target_ops *self, struct gdbarch *gdbarch, struct remote_state *rs; char *p, *endbuf; char *message; - int bpsize; - - /* The length field should be set to the size of a breakpoint - instruction, even though we aren't inserting one ourselves. */ - - gdbarch_remote_breakpoint_from_pc (gdbarch, &addr, &bpsize); if (packet_support (PACKET_Z1) == PACKET_DISABLE) return -1; @@ -9635,7 +10046,7 @@ remote_insert_hw_breakpoint (struct target_ops *self, struct gdbarch *gdbarch, addr = remote_address_masked (addr); p += hexnumstr (p, (ULONGEST) addr); - xsnprintf (p, endbuf - p, ",%x", bpsize); + xsnprintf (p, endbuf - p, ",%x", bp_tgt->kind); if (remote_supports_cond_breakpoints (self)) remote_add_target_side_condition (gdbarch, bp_tgt, p, endbuf); @@ -9659,8 +10070,6 @@ remote_insert_hw_breakpoint (struct target_ops *self, struct gdbarch *gdbarch, case PACKET_UNKNOWN: return -1; case PACKET_OK: - bp_tgt->placed_address = addr; - bp_tgt->placed_size = bpsize; return 0; } internal_error (__FILE__, __LINE__, @@ -9691,7 +10100,7 @@ remote_remove_hw_breakpoint (struct target_ops *self, struct gdbarch *gdbarch, addr = remote_address_masked (bp_tgt->placed_address); p += hexnumstr (p, (ULONGEST) addr); - xsnprintf (p, endbuf - p, ",%x", bp_tgt->placed_size); + xsnprintf (p, endbuf - p, ",%x", bp_tgt->kind); putpkt (rs->buf); getpkt (&rs->buf, &rs->buf_size, 0); @@ -11875,8 +12284,6 @@ remote_download_tracepoint (struct target_ops *self, struct bp_location *loc) char **stepping_actions; int ndx; struct cleanup *old_chain = NULL; - struct agent_expr *aexpr; - struct cleanup *aexpr_chain = NULL; char *pkt; struct breakpoint *b = loc->owner; struct tracepoint *t = (struct tracepoint *) b; @@ -11947,15 +12354,13 @@ remote_download_tracepoint (struct target_ops *self, struct bp_location *loc) capabilities at definition time. */ if (remote_supports_cond_tracepoints ()) { - aexpr = gen_eval_for_expr (tpaddr, loc->cond); - aexpr_chain = make_cleanup_free_agent_expr (aexpr); + agent_expr_up aexpr = gen_eval_for_expr (tpaddr, loc->cond.get ()); xsnprintf (buf + strlen (buf), BUF_SIZE - strlen (buf), ":X%x,", aexpr->len); pkt = buf + strlen (buf); for (ndx = 0; ndx < aexpr->len; ++ndx) pkt = pack_hex_byte (pkt, aexpr->buf[ndx]); *pkt = '\0'; - do_cleanups (aexpr_chain); } else warning (_("Target does not support conditional tracepoints, " @@ -13114,6 +13519,7 @@ Specify the serial device it is connected to\n\ remote_ops.to_detach = remote_detach; remote_ops.to_disconnect = remote_disconnect; remote_ops.to_resume = remote_resume; + remote_ops.to_commit_resume = remote_commit_resume; remote_ops.to_wait = remote_wait; remote_ops.to_fetch_registers = remote_fetch_registers; remote_ops.to_store_registers = remote_store_registers; @@ -13277,8 +13683,9 @@ remote_can_async_p (struct target_ops *ops) { struct remote_state *rs = get_remote_state (); + /* We don't go async if the user has explicitly prevented it with the + "maint set target-async" command. */ if (!target_async_permitted) - /* We only enable async when the user specifically asks for it. */ return 0; /* We're async whenever the serial device is. */ @@ -13409,8 +13816,8 @@ show_remote_cmd (char *args, int from_tty) struct cleanup *option_chain = make_cleanup_ui_out_tuple_begin_end (uiout, "option"); - ui_out_field_string (uiout, "name", list->name); - ui_out_text (uiout, ": "); + uiout->field_string ("name", list->name); + uiout->text (": "); if (list->type == show_cmd) do_show_command (NULL, from_tty, list); else