X-Git-Url: http://drtracing.org/?a=blobdiff_plain;f=gdb%2Fremote.c;h=0c791aa220f345d3fa3735d822f61d73a56d9f74;hb=4fcd97eb159fbfdf2b6576762821900345f510b3;hp=b36a4b4694625a718783c58b465e3709f68aa51f;hpb=29c87f7ff2089f6ef9a07852e4ed382df5223007;p=deliverable%2Fbinutils-gdb.git diff --git a/gdb/remote.c b/gdb/remote.c index b36a4b4694..0c791aa220 100644 --- a/gdb/remote.c +++ b/gdb/remote.c @@ -1,8 +1,8 @@ /* Remote target communications for serial-line targets in custom GDB protocol Copyright (C) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, - 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 - Free Software Foundation, Inc. + 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, + 2010 Free Software Foundation, Inc. This file is part of GDB. @@ -60,9 +60,21 @@ #include "remote-fileio.h" #include "gdb/fileio.h" #include "gdb_stat.h" +#include "xml-support.h" #include "memory-map.h" +#include "tracepoint.h" +#include "ax.h" +#include "ax-gdb.h" + +/* temp hacks for tracepoint encoding migration */ +static char *target_buf; +static long target_buf_size; +/*static*/ void +encode_actions (struct breakpoint *t, struct bp_location *tloc, + char ***tdp_actions, char ***stepping_actions); + /* The size to align memory write packets, when practical. The protocol does not guarantee any alignment, and gdb will generate short writes and unaligned writes, but even as a best-effort attempt this @@ -91,10 +103,6 @@ static void remote_files_info (struct target_ops *ignore); static void remote_prepare_to_store (struct regcache *regcache); -static void remote_fetch_registers (struct regcache *regcache, int regno); - -static void remote_resume (ptid_t ptid, int step, - enum target_signal siggnal); static void remote_open (char *name, int from_tty); static void extended_remote_open (char *name, int from_tty); @@ -103,13 +111,11 @@ static void remote_open_1 (char *, int, struct target_ops *, int extended_p); static void remote_close (int quitting); -static void remote_store_registers (struct regcache *regcache, int regno); - -static void remote_mourn (void); +static void remote_mourn (struct target_ops *ops); static void extended_remote_restart (void); -static void extended_remote_mourn (void); +static void extended_remote_mourn (struct target_ops *); static void remote_mourn_1 (struct target_ops *); @@ -117,10 +123,7 @@ static void remote_send (char **buf, long *sizeof_buf_p); static int readchar (int timeout); -static ptid_t remote_wait (ptid_t ptid, - struct target_waitstatus *status); - -static void remote_kill (void); +static void remote_kill (struct target_ops *ops); static int tohex (int nib); @@ -133,7 +136,7 @@ static void remote_async (void (*callback) (enum inferior_event_type event_type, static int remote_async_mask (int new_mask); -static void remote_detach (char *args, int from_tty); +static void remote_detach (struct target_ops *ops, char *args, int from_tty); static void remote_interrupt (int signo); @@ -144,8 +147,6 @@ static void interrupt_query (void); static void set_general_thread (struct ptid ptid); static void set_continue_thread (struct ptid ptid); -static int remote_thread_alive (ptid_t); - static void get_offsets (void); static void skip_frame (void); @@ -172,8 +173,6 @@ static CORE_ADDR remote_address_masked (CORE_ADDR); static void print_packet (char *); -static unsigned long crc32 (unsigned char *, int, unsigned int); - static void compare_sections_command (char *, int); static void packet_command (char *, int); @@ -188,9 +187,9 @@ static void record_currthread (ptid_t currthread); static int fromhex (int a); -static int hex2bin (const char *hex, gdb_byte *bin, int count); +extern int hex2bin (const char *hex, gdb_byte *bin, int count); -static int bin2hex (const gdb_byte *bin, char *hex, int count); +extern int bin2hex (const gdb_byte *bin, char *hex, int count); static int putpkt_binary (char *buf, int cnt); @@ -213,6 +212,13 @@ static void show_remote_protocol_packet_cmd (struct ui_file *file, static char *write_ptid (char *buf, const char *endbuf, ptid_t ptid); static ptid_t read_ptid (char *buf, char **obuf); +struct remote_state; +static int remote_get_trace_status (struct trace_status *ts); + +static int remote_upload_tracepoints (struct uploaded_tp **utpp); + +static int remote_upload_trace_state_variables (struct uploaded_tsv **utsvp); + static void remote_query_supported (void); static void remote_check_symbols (struct objfile *objfile); @@ -234,6 +240,8 @@ static void remote_async_get_pending_events_handler (gdb_client_data); static void remote_terminal_ours (void); +static int remote_read_description_p (struct target_ops *target); + /* The non-stop remote protocol provisions for one pending stop reply. This is where we keep it until it is acknowledged. */ @@ -303,8 +311,36 @@ struct remote_state /* True if the stub reports support for vCont;t. */ int support_vCont_t; + + /* True if the stub reports support for conditional tracepoints. */ + int cond_tracepoints; + + /* True if the stub reports support for fast tracepoints. */ + int fast_tracepoints; + + /* True if the stub can continue running a trace while GDB is + disconnected. */ + int disconnected_tracing; + + /* Nonzero if the user has pressed Ctrl-C, but the target hasn't + responded to that. */ + int ctrlc_pending_p; +}; + +/* Private data that we'll store in (struct thread_info)->private. */ +struct private_thread_info +{ + char *extra; + int core; }; +static void +free_private_thread_info (struct private_thread_info *info) +{ + xfree (info->extra); + xfree (info); +} + /* Returns true if the multi-process extensions are in effect. */ static int remote_multi_process_p (struct remote_state *rs) @@ -360,6 +396,52 @@ struct remote_arch_state long remote_packet_size; }; +long sizeof_pkt = 2000; + +/* Utility: generate error from an incoming stub packet. */ +static void +trace_error (char *buf) +{ + if (*buf++ != 'E') + return; /* not an error msg */ + switch (*buf) + { + case '1': /* malformed packet error */ + if (*++buf == '0') /* general case: */ + error (_("remote.c: error in outgoing packet.")); + else + error (_("remote.c: error in outgoing packet at field #%ld."), + strtol (buf, NULL, 16)); + case '2': + error (_("trace API error 0x%s."), ++buf); + default: + error (_("Target returns error code '%s'."), buf); + } +} + +/* Utility: wait for reply from stub, while accepting "O" packets. */ +static char * +remote_get_noisy_reply (char **buf_p, + long *sizeof_buf) +{ + do /* Loop on reply from remote stub. */ + { + char *buf; + QUIT; /* allow user to bail out with ^C */ + getpkt (buf_p, sizeof_buf, 0); + buf = *buf_p; + if (buf[0] == 0) + error (_("Target does not support this command.")); + else if (buf[0] == 'E') + trace_error (buf); + else if (buf[0] == 'O' && + buf[1] != 'K') + remote_console_output (buf + 1); /* 'O' message from stub */ + else + return buf; /* here's the actual reply */ + } + while (1); +} /* Handle for retreving the remote protocol data from gdbarch. */ static struct gdbarch_data *remote_gdbarch_data_handle; @@ -552,14 +634,76 @@ static int remote_async_mask_value = 1; this can go away. */ static int wait_forever_enabled_p = 1; +/* Allow the user to specify what sequence to send to the remote + when he requests a program interruption: Although ^C is usually + what remote systems expect (this is the default, here), it is + sometimes preferable to send a break. On other systems such + as the Linux kernel, a break followed by g, which is Magic SysRq g + is required in order to interrupt the execution. */ +const char interrupt_sequence_control_c[] = "Ctrl-C"; +const char interrupt_sequence_break[] = "BREAK"; +const char interrupt_sequence_break_g[] = "BREAK-g"; +static const char *interrupt_sequence_modes[] = + { + interrupt_sequence_control_c, + interrupt_sequence_break, + interrupt_sequence_break_g, + NULL + }; +static const char *interrupt_sequence_mode = interrupt_sequence_control_c; + +static void +show_interrupt_sequence (struct ui_file *file, int from_tty, + struct cmd_list_element *c, + const char *value) +{ + if (interrupt_sequence_mode == interrupt_sequence_control_c) + fprintf_filtered (file, + _("Send the ASCII ETX character (Ctrl-c) " + "to the remote target to interrupt the " + "execution of the program.\n")); + else if (interrupt_sequence_mode == interrupt_sequence_break) + fprintf_filtered (file, + _("send a break signal to the remote target " + "to interrupt the execution of the program.\n")); + else if (interrupt_sequence_mode == interrupt_sequence_break_g) + fprintf_filtered (file, + _("Send a break signal and 'g' a.k.a. Magic SysRq g to " + "the remote target to interrupt the execution " + "of Linux kernel.\n")); + else + internal_error (__FILE__, __LINE__, + _("Invalid value for interrupt_sequence_mode: %s."), + interrupt_sequence_mode); +} -/* This variable chooses whether to send a ^C or a break when the user - requests program interruption. Although ^C is usually what remote - systems expect, and that is the default here, sometimes a break is - preferable instead. */ +/* This boolean variable specifies whether interrupt_sequence is sent + to the remote target when gdb connects to it. + This is mostly needed when you debug the Linux kernel: The Linux kernel + expects BREAK g which is Magic SysRq g for connecting gdb. */ +static int interrupt_on_connect = 0; +/* This variable is used to implement the "set/show remotebreak" commands. + Since these commands are now deprecated in favor of "set/show remote + interrupt-sequence", it no longer has any effect on the code. */ static int remote_break; +static void +set_remotebreak (char *args, int from_tty, struct cmd_list_element *c) +{ + if (remote_break) + interrupt_sequence_mode = interrupt_sequence_break; + else + interrupt_sequence_mode = interrupt_sequence_control_c; +} + +static void +show_remotebreak (struct ui_file *file, int from_tty, + struct cmd_list_element *c, + const char *value) +{ +} + /* Descriptor for I/O to remote machine. Initialize it to NULL so that remote_open knows that we don't have a file open when the program starts. */ @@ -871,6 +1015,9 @@ add_packet_config_cmd (struct packet_config *config, const char *name, set_remote_protocol_packet_cmd, show_remote_protocol_packet_cmd, &remote_set_cmdlist, &remote_show_cmdlist); + /* The command code copies the documentation strings. */ + xfree (set_doc); + xfree (show_doc); /* set/show remote NAME-packet {auto,on,off} -- legacy. */ if (legacy) { @@ -990,6 +1137,8 @@ enum { PACKET_qXfer_memory_map, PACKET_qXfer_spu_read, PACKET_qXfer_spu_write, + PACKET_qXfer_osdata, + PACKET_qXfer_threads, PACKET_qGetTLSAddr, PACKET_qSupported, PACKET_QPassSignals, @@ -998,6 +1147,13 @@ enum { PACKET_vRun, PACKET_QStartNoAckMode, PACKET_vKill, + PACKET_qXfer_siginfo_read, + PACKET_qXfer_siginfo_write, + PACKET_qAttached, + PACKET_ConditionalTracepoints, + PACKET_FastTracepoints, + PACKET_bc, + PACKET_bs, PACKET_MAX }; @@ -1124,8 +1280,107 @@ static ptid_t any_thread_ptid; static ptid_t general_thread; static ptid_t continue_thread; +/* Find out if the stub attached to PID (and hence GDB should offer to + detach instead of killing it when bailing out). */ + +static int +remote_query_attached (int pid) +{ + struct remote_state *rs = get_remote_state (); + + if (remote_protocol_packets[PACKET_qAttached].support == PACKET_DISABLE) + return 0; + + if (remote_multi_process_p (rs)) + sprintf (rs->buf, "qAttached:%x", pid); + else + sprintf (rs->buf, "qAttached"); + + putpkt (rs->buf); + getpkt (&rs->buf, &rs->buf_size, 0); + + switch (packet_ok (rs->buf, + &remote_protocol_packets[PACKET_qAttached])) + { + case PACKET_OK: + if (strcmp (rs->buf, "1") == 0) + return 1; + break; + case PACKET_ERROR: + warning (_("Remote failure reply: %s"), rs->buf); + break; + case PACKET_UNKNOWN: + break; + } + + return 0; +} + +/* Add PID to GDB's inferior table. Since we can be connected to a + remote system before before knowing about any inferior, mark the + target with execution when we find the first inferior. If ATTACHED + is 1, then we had just attached to this inferior. If it is 0, then + we just created this inferior. If it is -1, then try querying the + remote stub to find out if it had attached to the inferior or + not. */ + +static struct inferior * +remote_add_inferior (int pid, int attached) +{ + struct inferior *inf; + + /* Check whether this process we're learning about is to be + considered attached, or if is to be considered to have been + spawned by the stub. */ + if (attached == -1) + attached = remote_query_attached (pid); + + if (gdbarch_has_global_solist (target_gdbarch)) + { + /* If the target shares code across all inferiors, then every + attach adds a new inferior. */ + inf = add_inferior (pid); + + /* ... and every inferior is bound to the same program space. + However, each inferior may still have its own address + space. */ + inf->aspace = maybe_new_address_space (); + inf->pspace = current_program_space; + } + else + { + /* In the traditional debugging scenario, there's a 1-1 match + between program/address spaces. We simply bind the inferior + to the program space's address space. */ + inf = current_inferior (); + inferior_appeared (inf, pid); + } + + inf->attach_flag = attached; + + return inf; +} + +/* Add thread PTID to GDB's thread list. Tag it as executing/running + according to RUNNING. */ + +static void +remote_add_thread (ptid_t ptid, int running) +{ + add_thread (ptid); + + set_executing (ptid, running); + set_running (ptid, running); +} + +/* Come here when we learn about a thread id from the remote target. + It may be the first time we hear about such thread, so take the + opportunity to add it to GDB's thread list. In case this is the + first time we're noticing its corresponding inferior, add it to + GDB's inferior list as well. */ + static void -notice_new_inferiors (ptid_t currthread) +remote_notice_new_inferior (ptid_t currthread, int running) { /* If this is a new thread, add it to GDB's thread list. If we leave it up to WFI to do this, bad things will happen. */ @@ -1134,21 +1389,31 @@ notice_new_inferiors (ptid_t currthread) { /* We're seeing an event on a thread id we knew had exited. This has to be a new thread reusing the old id. Add it. */ - add_thread (currthread); + remote_add_thread (currthread, running); return; } if (!in_thread_list (currthread)) { - if (ptid_equal (pid_to_ptid (ptid_get_pid (currthread)), inferior_ptid)) + struct inferior *inf = NULL; + int pid = ptid_get_pid (currthread); + + if (ptid_is_pid (inferior_ptid) + && pid == ptid_get_pid (inferior_ptid)) { /* inferior_ptid has no thread member yet. This can happen with the vAttach -> remote_wait,"TAAthread:" path if the stub doesn't support qC. This is the first stop reported after an attach, so this is the main thread. Update the ptid in the thread list. */ - thread_change_ptid (inferior_ptid, currthread); - return; + if (in_thread_list (pid_to_ptid (pid))) + thread_change_ptid (inferior_ptid, currthread); + else + { + remote_add_thread (currthread, running); + inferior_ptid = currthread; + } + return; } if (ptid_equal (magic_null_ptid, inferior_ptid)) @@ -1158,7 +1423,7 @@ notice_new_inferiors (ptid_t currthread) doesn't support qC. This is the first stop reported after an attach, so this is the main thread. Update the ptid in the thread list. */ - thread_change_ptid (inferior_ptid, currthread); + thread_change_ptid (inferior_ptid, currthread); return; } @@ -1167,11 +1432,37 @@ notice_new_inferiors (ptid_t currthread) may not know about it yet. Add it before adding its child thread, so notifications are emitted in a sensible order. */ if (!in_inferior_list (ptid_get_pid (currthread))) - add_inferior (ptid_get_pid (currthread)); + inf = remote_add_inferior (ptid_get_pid (currthread), -1); /* This is really a new thread. Add it. */ - add_thread (currthread); + remote_add_thread (currthread, running); + + /* If we found a new inferior, let the common code do whatever + it needs to with it (e.g., read shared libraries, insert + breakpoints). */ + if (inf != NULL) + notice_new_inferior (currthread, running, 0); + } +} + +/* Return the private thread data, creating it if necessary. */ + +struct private_thread_info * +demand_private_info (ptid_t ptid) +{ + struct thread_info *info = find_thread_ptid (ptid); + + gdb_assert (info); + + if (!info->private) + { + info->private = xmalloc (sizeof (*(info->private))); + info->private_dtor = free_private_thread_info; + info->private->core = -1; + info->private->extra = 0; } + + return info->private; } /* Call this function as a result of @@ -1184,12 +1475,6 @@ static void record_currthread (ptid_t currthread) { general_thread = currthread; - - if (ptid_equal (currthread, minus_one_ptid)) - /* We're just invalidating the local thread mirror. */ - return; - - notice_new_inferiors (currthread); } static char *last_pass_packet; @@ -1325,10 +1610,9 @@ set_general_process (void) system. */ static int -remote_thread_alive (ptid_t ptid) +remote_thread_alive (struct target_ops *ops, ptid_t ptid) { struct remote_state *rs = get_remote_state (); - int tid = ptid_get_tid (ptid); char *p, *endp; if (ptid_equal (ptid, magic_null_ptid)) @@ -1504,7 +1788,6 @@ read_ptid (char *buf, char **obuf) char *p = buf; char *pp; ULONGEST pid = 0, tid = 0; - ptid_t ptid; if (*p == 'p') { @@ -1524,8 +1807,13 @@ read_ptid (char *buf, char **obuf) pp = unpack_varlen_hex (p, &tid); /* Since the stub is not sending a process id, then default to - what's in inferior_ptid. */ - pid = ptid_get_pid (inferior_ptid); + what's in inferior_ptid, unless it's null at this point. If so, + then since there's no way to know the pid of the reported + threads, use the magic number. */ + if (ptid_equal (inferior_ptid, null_ptid)) + pid = ptid_get_pid (magic_null_ptid); + else + pid = ptid_get_pid (inferior_ptid); if (obuf) *obuf = pp; @@ -2095,9 +2383,6 @@ static ptid_t remote_current_thread (ptid_t oldpid) { struct remote_state *rs = get_remote_state (); - char *p = rs->buf; - int tid; - int pid; putpkt ("qC"); getpkt (&rs->buf, &rs->buf_size, 0); @@ -2118,6 +2403,80 @@ remote_find_new_threads (void) CRAZY_MAX_THREADS); } +#if defined(HAVE_LIBEXPAT) + +typedef struct thread_item +{ + ptid_t ptid; + char *extra; + int core; +} thread_item_t; +DEF_VEC_O(thread_item_t); + +struct threads_parsing_context +{ + VEC (thread_item_t) *items; +}; + +static void +start_thread (struct gdb_xml_parser *parser, + const struct gdb_xml_element *element, + void *user_data, VEC(gdb_xml_value_s) *attributes) +{ + struct threads_parsing_context *data = user_data; + + struct thread_item item; + char *id; + + id = VEC_index (gdb_xml_value_s, attributes, 0)->value; + item.ptid = read_ptid (id, NULL); + + if (VEC_length (gdb_xml_value_s, attributes) > 1) + item.core = *(ULONGEST *) VEC_index (gdb_xml_value_s, attributes, 1)->value; + else + item.core = -1; + + item.extra = 0; + + VEC_safe_push (thread_item_t, data->items, &item); +} + +static void +end_thread (struct gdb_xml_parser *parser, + const struct gdb_xml_element *element, + void *user_data, const char *body_text) +{ + struct threads_parsing_context *data = user_data; + + if (body_text && *body_text) + VEC_last (thread_item_t, data->items)->extra = strdup (body_text); +} + +const struct gdb_xml_attribute thread_attributes[] = { + { "id", GDB_XML_AF_NONE, NULL, NULL }, + { "core", GDB_XML_AF_OPTIONAL, gdb_xml_parse_attr_ulongest, NULL }, + { NULL, GDB_XML_AF_NONE, NULL, NULL } +}; + +const struct gdb_xml_element thread_children[] = { + { NULL, NULL, NULL, GDB_XML_EF_NONE, NULL, NULL } +}; + +const struct gdb_xml_element threads_children[] = { + { "thread", thread_attributes, thread_children, + GDB_XML_EF_REPEATABLE | GDB_XML_EF_OPTIONAL, + start_thread, end_thread }, + { NULL, NULL, NULL, GDB_XML_EF_NONE, NULL, NULL } +}; + +const struct gdb_xml_element threads_elements[] = { + { "threads", NULL, threads_children, + GDB_XML_EF_NONE, NULL, NULL }, + { NULL, NULL, NULL, GDB_XML_EF_NONE, NULL, NULL } +}; + +#endif + /* * Find all threads for info threads command. * Uses new thread protocol contributed by Cisco. @@ -2126,7 +2485,7 @@ remote_find_new_threads (void) */ static void -remote_threads_info (void) +remote_threads_info (struct target_ops *ops) { struct remote_state *rs = get_remote_state (); char *bufp; @@ -2135,6 +2494,61 @@ remote_threads_info (void) if (remote_desc == 0) /* paranoia */ error (_("Command can only be used when connected to the remote target.")); +#if defined(HAVE_LIBEXPAT) + if (remote_protocol_packets[PACKET_qXfer_threads].support == PACKET_ENABLE) + { + char *xml = target_read_stralloc (¤t_target, + TARGET_OBJECT_THREADS, NULL); + + struct cleanup *back_to = make_cleanup (xfree, xml); + if (xml && *xml) + { + struct gdb_xml_parser *parser; + struct threads_parsing_context context; + struct cleanup *back_to = make_cleanup (null_cleanup, NULL); + + context.items = 0; + parser = gdb_xml_create_parser_and_cleanup (_("threads"), + threads_elements, + &context); + + gdb_xml_use_dtd (parser, "threads.dtd"); + + if (gdb_xml_parse (parser, xml) == 0) + { + int i; + struct thread_item *item; + + for (i = 0; VEC_iterate (thread_item_t, context.items, i, item); ++i) + { + if (!ptid_equal (item->ptid, null_ptid)) + { + struct private_thread_info *info; + /* In non-stop mode, we assume new found threads + are running until proven otherwise with a + stop reply. In all-stop, we can only get + here if all threads are stopped. */ + int running = non_stop ? 1 : 0; + + remote_notice_new_inferior (item->ptid, running); + + info = demand_private_info (item->ptid); + info->core = item->core; + info->extra = item->extra; + item->extra = 0; + } + xfree (item->extra); + } + } + + VEC_free (thread_item_t, context.items); + } + + do_cleanups (back_to); + return; + } +#endif + if (use_threadinfo_query) { putpkt ("qfThreadInfo"); @@ -2147,27 +2561,15 @@ remote_threads_info (void) do { new_thread = read_ptid (bufp, &bufp); - if (!ptid_equal (new_thread, null_ptid) - && (!in_thread_list (new_thread) - || is_exited (new_thread))) + if (!ptid_equal (new_thread, null_ptid)) { - /* When connected to a multi-process aware stub, - "info threads" may show up threads of - inferiors we didn't know about yet. Add them - now, and before adding any of its child - threads, so notifications are emitted in a - sensible order. */ - if (!in_inferior_list (ptid_get_pid (new_thread))) - add_inferior (ptid_get_pid (new_thread)); - - add_thread (new_thread); - /* In non-stop mode, we assume new found threads - are running until we proven otherwise with a + are running until proven otherwise with a stop reply. In all-stop, we can only get here if all threads are stopped. */ - set_executing (new_thread, non_stop ? 1 : 0); - set_running (new_thread, non_stop ? 1 : 0); + int running = non_stop ? 1 : 0; + + remote_notice_new_inferior (new_thread, running); } } while (*bufp++ == ','); /* comma-separated list */ @@ -2219,6 +2621,15 @@ remote_threads_extra_info (struct thread_info *tp) server doesn't know about it. */ return NULL; + if (remote_protocol_packets[PACKET_qXfer_threads].support == PACKET_ENABLE) + { + struct thread_info *info = find_thread_ptid (tp->ptid); + if (info && info->private) + return info->private->extra; + else + return NULL; + } + if (use_threadextra_query) { char *b = rs->buf; @@ -2269,6 +2680,15 @@ remote_threads_extra_info (struct thread_info *tp) } +/* Implement the to_get_ada_task_ptid function for the remote targets. */ + +static ptid_t +remote_get_ada_task_ptid (long lwp, long thread) +{ + return ptid_build (ptid_get_pid (inferior_ptid), 0, lwp); +} + + /* Restart the remote side; this is an extended protocol operation. */ static void @@ -2310,8 +2730,6 @@ remote_close (int quitting) delete_async_event_handler (&remote_async_inferior_event_token); if (remote_async_get_pending_events_token) delete_async_event_handler (&remote_async_get_pending_events_token); - - generic_mourn_inferior (); } /* Query the remote side for the text, data and bss offsets. */ @@ -2499,6 +2917,25 @@ struct start_remote_args int extended_p; }; +/* Send interrupt_sequence to remote target. */ +static void +send_interrupt_sequence () +{ + if (interrupt_sequence_mode == interrupt_sequence_control_c) + serial_write (remote_desc, "\x03", 1); + else if (interrupt_sequence_mode == interrupt_sequence_break) + serial_send_break (remote_desc); + else if (interrupt_sequence_mode == interrupt_sequence_break_g) + { + serial_send_break (remote_desc); + serial_write (remote_desc, "g", 1); + } + else + internal_error (__FILE__, __LINE__, + _("Invalid value for interrupt_sequence_mode: %s."), + interrupt_sequence_mode); +} + static void remote_start_remote (struct ui_out *uiout, void *opaque) { @@ -2512,6 +2949,9 @@ remote_start_remote (struct ui_out *uiout, void *opaque) /* Ack any packet which the remote side has already sent. */ serial_write (remote_desc, "+", 1); + if (interrupt_on_connect) + send_interrupt_sequence (); + /* The first packet we send to the target is the optional "supported packets" request. If the target can answer this, it will tell us which later probes to skip. */ @@ -2549,15 +2989,19 @@ remote_start_remote (struct ui_out *uiout, void *opaque) getpkt (&rs->buf, &rs->buf_size, 0); } + /* Next, if the target can specify a description, read it. We do + this before anything involving memory or registers. */ + target_find_description (); + + /* Next, now that we know something about the target, update the + address spaces in the program spaces. */ + update_address_spaces (); + /* On OSs where the list of libraries is global to all processes, we fetch them early. */ if (gdbarch_has_global_solist (target_gdbarch)) solib_add (NULL, args->from_tty, args->target, auto_solib_add); - /* Next, if the target can specify a description, read it. We do - this before anything involving memory or registers. */ - target_find_description (); - if (non_stop) { if (!rs->non_stop_aware) @@ -2573,14 +3017,7 @@ remote_start_remote (struct ui_out *uiout, void *opaque) controlling. We default to adding them in the running state. The '?' query below will then tell us about which threads are stopped. */ - - /* If we're not using the multi-process extensions, there's no - way to know the pid of the reported threads; use the magic - number. */ - if (!remote_multi_process_p (rs)) - inferior_ptid = magic_null_ptid; - - remote_threads_info (); + remote_threads_info (args->target); } else if (rs->non_stop_aware) { @@ -2601,21 +3038,15 @@ remote_start_remote (struct ui_out *uiout, void *opaque) { if (rs->buf[0] == 'W' || rs->buf[0] == 'X') { - if (args->extended_p) - { - /* We're connected, but not running. Drop out before we - call start_remote. */ - target_mark_exited (args->target); - return; - } - else + if (!args->extended_p) error (_("The target is not running (try extended-remote?)")); + + /* We're connected, but not running. Drop out before we + call start_remote. */ + return; } else { - if (args->extended_p) - target_mark_running (args->target); - /* Save the reply for later. */ wait_status = alloca (strlen (rs->buf) + 1); strcpy (wait_status, rs->buf); @@ -2636,13 +3067,24 @@ remote_start_remote (struct ui_out *uiout, void *opaque) /* Now, if we have thread information, update inferior_ptid. */ inferior_ptid = remote_current_thread (inferior_ptid); - add_inferior (ptid_get_pid (inferior_ptid)); + remote_add_inferior (ptid_get_pid (inferior_ptid), -1); /* Always add the main thread. */ add_thread_silent (inferior_ptid); get_offsets (); /* Get text, data & bss offsets. */ + /* If we could not find a description using qXfer, and we know + how to do it some other way, try again. This is not + supported for non-stop; it could be, but it is tricky if + there are no stopped threads when we connect. */ + if (remote_read_description_p (args->target) + && gdbarch_target_desc (target_gdbarch) == NULL) + { + target_clear_description (); + target_find_description (); + } + /* Use the previously fetched status. */ gdb_assert (wait_status != NULL); strcpy (rs->buf, wait_status); @@ -2653,6 +3095,13 @@ remote_start_remote (struct ui_out *uiout, void *opaque) } else { + /* Clear WFI global state. Do this before finding about new + threads and inferiors, and setting the current inferior. + Otherwise we would clear the proceed status of the current + inferior when we want its stop_soon state to be preserved + (see notice_new_inferior). */ + init_wait_for_inferior (); + /* In non-stop, we will either get an "OK", meaning that there are no stopped threads at this time; or, a regular stop reply. In the latter case, there may be more than one thread @@ -2684,19 +3133,13 @@ remote_start_remote (struct ui_out *uiout, void *opaque) if (thread_count () == 0) { - if (args->extended_p) - { - /* We're connected, but not running. Drop out before we - call start_remote. */ - target_mark_exited (args->target); - return; - } - else + if (!args->extended_p) error (_("The target is not running (try extended-remote?)")); - } - if (args->extended_p) - target_mark_running (args->target); + /* We're connected, but not running. Drop out before we + call start_remote. */ + return; + } /* Let the stub know that we want it to return the thread. */ @@ -2722,9 +3165,31 @@ remote_start_remote (struct ui_out *uiout, void *opaque) remote_check_symbols (symfile_objfile); } - /* If code is shared between processes, then breakpoints are global - too; Insert them now. */ - if (gdbarch_has_global_solist (target_gdbarch) + /* Possibly the target has been engaged in a trace run started + previously; find out where things are at. */ + if (rs->disconnected_tracing) + { + struct uploaded_tp *uploaded_tps = NULL; + struct uploaded_tsv *uploaded_tsvs = NULL; + + remote_get_trace_status (current_trace_status ()); + if (current_trace_status ()->running) + printf_filtered (_("Trace is already running on the target.\n")); + + /* Get trace state variables first, they may be checked when + parsing uploaded commands. */ + + remote_upload_trace_state_variables (&uploaded_tsvs); + + merge_uploaded_trace_state_variables (&uploaded_tsvs); + + remote_upload_tracepoints (&uploaded_tps); + + merge_uploaded_tracepoints (&uploaded_tps); + } + + /* If breakpoints are global, insert them now. */ + if (gdbarch_has_global_breakpoints (target_gdbarch) && breakpoints_always_inserted_mode ()) insert_breakpoints (); } @@ -2794,6 +3259,7 @@ remote_check_symbols (struct objfile *objfile) xsnprintf (msg, get_remote_packet_size (), "qSymbol::%s", &reply[8]); else { + int addr_size = gdbarch_addr_bit (target_gdbarch) / 8; CORE_ADDR sym_addr = SYMBOL_VALUE_ADDRESS (sym); /* If this is a function address, return the start of code @@ -2803,7 +3269,7 @@ remote_check_symbols (struct objfile *objfile) ¤t_target); xsnprintf (msg, get_remote_packet_size (), "qSymbol:%s:%s", - paddr_nz (sym_addr), &reply[8]); + phex_nz (sym_addr, addr_size), &reply[8]); } putpkt (msg); @@ -2931,26 +3397,71 @@ remote_non_stop_feature (const struct protocol_feature *feature, rs->non_stop_aware = (support == PACKET_ENABLE); } -static struct protocol_feature remote_protocol_features[] = { - { "PacketSize", PACKET_DISABLE, remote_packet_size, -1 }, - { "qXfer:auxv:read", PACKET_DISABLE, remote_supported_packet, - PACKET_qXfer_auxv }, - { "qXfer:features:read", PACKET_DISABLE, remote_supported_packet, - PACKET_qXfer_features }, - { "qXfer:libraries:read", PACKET_DISABLE, remote_supported_packet, - PACKET_qXfer_libraries }, - { "qXfer:memory-map:read", PACKET_DISABLE, remote_supported_packet, +static void +remote_cond_tracepoint_feature (const struct protocol_feature *feature, + enum packet_support support, + const char *value) +{ + struct remote_state *rs = get_remote_state (); + rs->cond_tracepoints = (support == PACKET_ENABLE); +} + +static void +remote_fast_tracepoint_feature (const struct protocol_feature *feature, + enum packet_support support, + const char *value) +{ + struct remote_state *rs = get_remote_state (); + rs->fast_tracepoints = (support == PACKET_ENABLE); +} + +static void +remote_disconnected_tracing_feature (const struct protocol_feature *feature, + enum packet_support support, + const char *value) +{ + struct remote_state *rs = get_remote_state (); + rs->disconnected_tracing = (support == PACKET_ENABLE); +} + +static struct protocol_feature remote_protocol_features[] = { + { "PacketSize", PACKET_DISABLE, remote_packet_size, -1 }, + { "qXfer:auxv:read", PACKET_DISABLE, remote_supported_packet, + PACKET_qXfer_auxv }, + { "qXfer:features:read", PACKET_DISABLE, remote_supported_packet, + PACKET_qXfer_features }, + { "qXfer:libraries:read", PACKET_DISABLE, remote_supported_packet, + PACKET_qXfer_libraries }, + { "qXfer:memory-map:read", PACKET_DISABLE, remote_supported_packet, PACKET_qXfer_memory_map }, { "qXfer:spu:read", PACKET_DISABLE, remote_supported_packet, PACKET_qXfer_spu_read }, { "qXfer:spu:write", PACKET_DISABLE, remote_supported_packet, PACKET_qXfer_spu_write }, + { "qXfer:osdata:read", PACKET_DISABLE, remote_supported_packet, + PACKET_qXfer_osdata }, + { "qXfer:threads:read", PACKET_DISABLE, remote_supported_packet, + PACKET_qXfer_threads }, { "QPassSignals", PACKET_DISABLE, remote_supported_packet, PACKET_QPassSignals }, { "QStartNoAckMode", PACKET_DISABLE, remote_supported_packet, PACKET_QStartNoAckMode }, { "multiprocess", PACKET_DISABLE, remote_multi_process_feature, -1 }, { "QNonStop", PACKET_DISABLE, remote_non_stop_feature, -1 }, + { "qXfer:siginfo:read", PACKET_DISABLE, remote_supported_packet, + PACKET_qXfer_siginfo_read }, + { "qXfer:siginfo:write", PACKET_DISABLE, remote_supported_packet, + PACKET_qXfer_siginfo_write }, + { "ConditionalTracepoints", PACKET_DISABLE, remote_cond_tracepoint_feature, + PACKET_ConditionalTracepoints }, + { "FastTracepoints", PACKET_DISABLE, remote_fast_tracepoint_feature, + PACKET_FastTracepoints }, + { "DisconnectedTracing", PACKET_DISABLE, remote_disconnected_tracing_feature, + -1 }, + { "ReverseContinue", PACKET_DISABLE, remote_supported_packet, + PACKET_bc }, + { "ReverseStep", PACKET_DISABLE, remote_supported_packet, + PACKET_bs }, }; static void @@ -2971,10 +3482,24 @@ remote_query_supported (void) rs->buf[0] = 0; if (remote_protocol_packets[PACKET_qSupported].support != PACKET_DISABLE) { - if (rs->extended) - putpkt ("qSupported:multiprocess+"); + const char *qsupported = gdbarch_qsupported (target_gdbarch); + if (qsupported) + { + char *q; + if (rs->extended) + q = concat ("qSupported:multiprocess+;", qsupported, NULL); + else + q = concat ("qSupported:", qsupported, NULL); + putpkt (q); + xfree (q); + } else - putpkt ("qSupported"); + { + if (rs->extended) + putpkt ("qSupported:multiprocess+"); + else + putpkt ("qSupported"); + } getpkt (&rs->buf, &rs->buf_size, 0); @@ -3102,7 +3627,7 @@ remote_open_1 (char *name, int from_tty, struct target_ops *target, int extended But if we're connected to a target system with no running process, then we will still be connected when it returns. Ask this question first, before target_preopen has a chance to kill anything. */ - if (remote_desc != NULL && !target_has_execution) + if (remote_desc != NULL && !have_inferiors ()) { if (!from_tty || query (_("Already connected to a remote target. Disconnect? "))) @@ -3120,7 +3645,7 @@ remote_open_1 (char *name, int from_tty, struct target_ops *target, int extended process, we may still be connected. If we are starting "target remote" now, the extended-remote target will not have been removed by unpush_target. */ - if (remote_desc != NULL && !target_has_execution) + if (remote_desc != NULL && !have_inferiors ()) pop_target (); /* Make sure we send the passed signals list the next time we resume. */ @@ -3163,9 +3688,6 @@ remote_open_1 (char *name, int from_tty, struct target_ops *target, int extended } push_target (target); /* Switch to using remote target now. */ - /* Assume that the target is running, unless we learn otherwise. */ - target_mark_running (target); - /* Register extra event sources in the event loop. */ remote_async_inferior_event_token = create_async_event_handler (remote_async_inferior_event_handler, @@ -3184,6 +3706,7 @@ remote_open_1 (char *name, int from_tty, struct target_ops *target, int extended rs->extended = extended_p; rs->non_stop_aware = 0; rs->waiting_for_stop_reply = 0; + rs->ctrlc_pending_p = 0; general_thread = not_sent_ptid; continue_thread = not_sent_ptid; @@ -3301,18 +3824,17 @@ remote_detach_1 (char *args, int from_tty, int extended) } discard_pending_stop_replies (pid); - detach_inferior (pid); target_mourn_inferior (); } static void -remote_detach (char *args, int from_tty) +remote_detach (struct target_ops *ops, char *args, int from_tty) { remote_detach_1 (args, from_tty, 0); } static void -extended_remote_detach (char *args, int from_tty) +extended_remote_detach (struct target_ops *ops, char *args, int from_tty) { remote_detach_1 (args, from_tty, 1); } @@ -3342,18 +3864,12 @@ extended_remote_attach_1 (struct target_ops *target, char *args, int from_tty) { struct remote_state *rs = get_remote_state (); int pid; - char *dummy; char *wait_status = NULL; - struct inferior *inf; - if (!args) - error_no_arg (_("process-id to attach")); + pid = parse_pid_to_attach (args); - dummy = args; - pid = strtol (args, &dummy, 0); - /* Some targets don't set errno on errors, grrr! */ - if (pid == 0 && args == dummy) - error (_("Illegal process-id: %s."), args); + /* Remote PID can be freely equal to getpid, do not check it here the same + way as in other targets. */ if (remote_protocol_packets[PACKET_vAttach].support == PACKET_DISABLE) error (_("This target does not support attaching to a process")); @@ -3385,21 +3901,34 @@ extended_remote_attach_1 (struct target_ops *target, char *args, int from_tty) error (_("Attaching to %s failed"), target_pid_to_str (pid_to_ptid (pid))); - target_mark_running (target); + set_current_inferior (remote_add_inferior (pid, 1)); + inferior_ptid = pid_to_ptid (pid); - /* Now, if we have thread information, update inferior_ptid. */ - inferior_ptid = remote_current_thread (inferior_ptid); + if (non_stop) + { + struct thread_info *thread; - inf = add_inferior (pid); - inf->attach_flag = 1; + /* Get list of threads. */ + remote_threads_info (target); - if (non_stop) - /* Get list of threads. */ - remote_threads_info (); + thread = first_thread_of_process (pid); + if (thread) + inferior_ptid = thread->ptid; + else + inferior_ptid = pid_to_ptid (pid); + + /* Invalidate our notion of the remote current thread. */ + record_currthread (minus_one_ptid); + } else - /* Add the main thread to the thread list. */ - add_thread_silent (inferior_ptid); + { + /* Now, if we have thread information, update inferior_ptid. */ + inferior_ptid = remote_current_thread (inferior_ptid); + + /* Add the main thread to the thread list. */ + add_thread_silent (inferior_ptid); + } /* Next, if the target can specify a description, read it. We do this before anything involving memory or registers. */ @@ -3435,9 +3964,9 @@ extended_remote_attach_1 (struct target_ops *target, char *args, int from_tty) } static void -extended_remote_attach (char *args, int from_tty) +extended_remote_attach (struct target_ops *ops, char *args, int from_tty) { - extended_remote_attach_1 (&extended_remote_ops, args, from_tty); + extended_remote_attach_1 (ops, args, from_tty); } /* Convert hex digit A to a number. */ @@ -3455,7 +3984,7 @@ fromhex (int a) error (_("Reply contains invalid hex digit %d"), a); } -static int +int hex2bin (const char *hex, gdb_byte *bin, int count) { int i; @@ -3485,7 +4014,7 @@ tohex (int nib) return 'a' + nib - 10; } -static int +int bin2hex (const gdb_byte *bin, char *hex, int count) { int i; @@ -3552,6 +4081,50 @@ remote_vcont_probe (struct remote_state *rs) packet_ok (buf, &remote_protocol_packets[PACKET_vCont]); } +/* Helper function for building "vCont" resumptions. Write a + resumption to P. ENDP points to one-passed-the-end of the buffer + we're allowed to write to. Returns BUF+CHARACTERS_WRITTEN. The + thread to be resumed is PTID; STEP and SIGGNAL indicate whether the + resumed thread should be single-stepped and/or signalled. If PTID + equals minus_one_ptid, then all threads are resumed; if PTID + represents a process, then all threads of the process are resumed; + the thread to be stepped and/or signalled is given in the global + INFERIOR_PTID. */ + +static char * +append_resumption (char *p, char *endp, + ptid_t ptid, int step, enum target_signal siggnal) +{ + struct remote_state *rs = get_remote_state (); + + if (step && siggnal != TARGET_SIGNAL_0) + p += xsnprintf (p, endp - p, ";S%02x", siggnal); + else if (step) + p += xsnprintf (p, endp - p, ";s"); + else if (siggnal != TARGET_SIGNAL_0) + p += xsnprintf (p, endp - p, ";C%02x", siggnal); + else + p += xsnprintf (p, endp - p, ";c"); + + if (remote_multi_process_p (rs) && ptid_is_pid (ptid)) + { + ptid_t nptid; + + /* All (-1) threads of process. */ + nptid = ptid_build (ptid_get_pid (ptid), 0, -1); + + p += xsnprintf (p, endp - p, ":"); + p = write_ptid (p, endp, nptid); + } + else if (!ptid_equal (ptid, minus_one_ptid)) + { + p += xsnprintf (p, endp - p, ":"); + p = write_ptid (p, endp, ptid); + } + + return p; +} + /* Resume the remote inferior by using a "vCont" packet. The thread to be resumed is PTID; STEP and SIGGNAL indicate whether the resumed thread should be single-stepped and/or signalled. If PTID @@ -3582,78 +4155,35 @@ remote_vcont_resume (ptid_t ptid, int step, enum target_signal siggnal) about overflowing BUF. Should there be a generic "multi-part-packet" packet? */ + p += xsnprintf (p, endp - p, "vCont"); + if (ptid_equal (ptid, magic_null_ptid)) { /* MAGIC_NULL_PTID means that we don't have any active threads, so we don't have any TID numbers the inferior will understand. Make sure to only send forms that do not specify a TID. */ - if (step && siggnal != TARGET_SIGNAL_0) - xsnprintf (p, endp - p, "vCont;S%02x", siggnal); - else if (step) - xsnprintf (p, endp - p, "vCont;s"); - else if (siggnal != TARGET_SIGNAL_0) - xsnprintf (p, endp - p, "vCont;C%02x", siggnal); - else - xsnprintf (p, endp - p, "vCont;c"); + p = append_resumption (p, endp, minus_one_ptid, step, siggnal); } - else if (ptid_equal (ptid, minus_one_ptid)) + else if (ptid_equal (ptid, minus_one_ptid) || ptid_is_pid (ptid)) { - /* Resume all threads, with preference for INFERIOR_PTID. */ - if (step && siggnal != TARGET_SIGNAL_0) - { - /* Step inferior_ptid with signal. */ - p += xsnprintf (p, endp - p, "vCont;S%02x:", siggnal); - p = write_ptid (p, endp, inferior_ptid); - /* And continue others. */ - p += xsnprintf (p, endp - p, ";c"); - } - else if (step) - { - /* Step inferior_ptid. */ - p += xsnprintf (p, endp - p, "vCont;s:"); - p = write_ptid (p, endp, inferior_ptid); - /* And continue others. */ - p += xsnprintf (p, endp - p, ";c"); - } - else if (siggnal != TARGET_SIGNAL_0) + /* Resume all threads (of all processes, or of a single + process), with preference for INFERIOR_PTID. This assumes + inferior_ptid belongs to the set of all threads we are about + to resume. */ + if (step || siggnal != TARGET_SIGNAL_0) { - /* Continue inferior_ptid with signal. */ - p += xsnprintf (p, endp - p, "vCont;C%02x:", siggnal); - p = write_ptid (p, endp, inferior_ptid); - /* And continue others. */ - p += xsnprintf (p, endp - p, ";c"); + /* Step inferior_ptid, with or without signal. */ + p = append_resumption (p, endp, inferior_ptid, step, siggnal); } - else - xsnprintf (p, endp - p, "vCont;c"); + + /* And continue others without a signal. */ + p = append_resumption (p, endp, ptid, /*step=*/ 0, TARGET_SIGNAL_0); } else { /* Scheduler locking; resume only PTID. */ - if (step && siggnal != TARGET_SIGNAL_0) - { - /* Step ptid with signal. */ - p += xsnprintf (p, endp - p, "vCont;S%02x:", siggnal); - p = write_ptid (p, endp, ptid); - } - else if (step) - { - /* Step ptid. */ - p += xsnprintf (p, endp - p, "vCont;s:"); - p = write_ptid (p, endp, ptid); - } - else if (siggnal != TARGET_SIGNAL_0) - { - /* Continue ptid with signal. */ - p += xsnprintf (p, endp - p, "vCont;C%02x:", siggnal); - p = write_ptid (p, endp, ptid); - } - else - { - /* Continue ptid. */ - p += xsnprintf (p, endp - p, "vCont;c:"); - p = write_ptid (p, endp, ptid); - } + p = append_resumption (p, endp, ptid, step, siggnal); } gdb_assert (strlen (rs->buf) < get_remote_packet_size ()); @@ -3679,7 +4209,8 @@ static enum target_signal last_sent_signal = TARGET_SIGNAL_0; static int last_sent_step; static void -remote_resume (ptid_t ptid, int step, enum target_signal siggnal) +remote_resume (struct target_ops *ops, + ptid_t ptid, int step, enum target_signal siggnal) { struct remote_state *rs = get_remote_state (); char *buf; @@ -3691,8 +4222,10 @@ remote_resume (ptid_t ptid, int step, enum target_signal siggnal) remote_pass_signals (); /* The vCont packet doesn't need to specify threads via Hc. */ - if (remote_vcont_resume (ptid, step, siggnal)) - goto done; + /* No reverse support (yet) for vCont. */ + if (execution_direction != EXEC_REVERSE) + if (remote_vcont_resume (ptid, step, siggnal)) + goto done; /* All other supported resume packets do use Hc, so set the continue thread. */ @@ -3708,6 +4241,14 @@ remote_resume (ptid_t ptid, int step, enum target_signal siggnal) if (info_verbose && siggnal != TARGET_SIGNAL_0) warning (" - Can't pass signal %d to target in reverse: ignored.\n", siggnal); + + if (step + && remote_protocol_packets[PACKET_bs].support == PACKET_DISABLE) + error (_("Remote reverse-step not supported.")); + if (!step + && remote_protocol_packets[PACKET_bc].support == PACKET_DISABLE) + error (_("Remote reverse-continue not supported.")); + strcpy (buf, step ? "bs" : "bc"); } else if (siggnal != TARGET_SIGNAL_0) @@ -3839,7 +4380,6 @@ remote_stop_ns (ptid_t ptid) struct remote_state *rs = get_remote_state (); char *p = rs->buf; char *endp = rs->buf + get_remote_packet_size (); - struct stop_reply *reply, *next; if (remote_protocol_packets[PACKET_vCont].support == PACKET_SUPPORT_UNKNOWN) remote_vcont_probe (rs); @@ -3847,13 +4387,13 @@ remote_stop_ns (ptid_t ptid) if (!rs->support_vCont_t) error (_("Remote server does not support stopping threads")); - if (ptid_equal (ptid, minus_one_ptid)) + if (ptid_equal (ptid, minus_one_ptid) + || (!remote_multi_process_p (rs) && ptid_is_pid (ptid))) p += xsnprintf (p, endp - p, "vCont;t"); else { ptid_t nptid; - /* Step inferior_ptid. */ p += xsnprintf (p, endp - p, "vCont;t:"); if (ptid_is_pid (ptid)) @@ -3890,18 +4430,16 @@ remote_stop_as (ptid_t ptid) { struct remote_state *rs = get_remote_state (); + rs->ctrlc_pending_p = 1; + /* If the inferior is stopped already, but the core didn't know about it yet, just ignore the request. The cached wait status will be collected in remote_wait. */ if (rs->cached_wait_status) return; - /* Send a break or a ^C, depending on user preference. */ - - if (remote_break) - serial_send_break (remote_desc); - else - serial_write (remote_desc, "\003", 1); + /* Send interrupt_sequence to remote target. */ + send_interrupt_sequence (); } /* This is the generic stop called via the target vector. When a target @@ -3934,8 +4472,8 @@ interrupt_query (void) } else { - if (query ("Interrupted while waiting for the program.\n\ -Give up (and stop debugging it)? ")) + if (query (_("Interrupted while waiting for the program.\n\ +Give up (and stop debugging it)? "))) { pop_target (); deprecated_throw_reason (RETURN_QUIT); @@ -3957,19 +4495,12 @@ remote_terminal_inferior (void) /* Nothing to do. */ return; - /* FIXME: cagney/1999-09-27: Shouldn't need to test for - sync_execution here. This function should only be called when - GDB is resuming the inferior in the forground. A background - resume (``run&'') should leave GDB in control of the terminal and - consequently should not call this code. */ - if (!sync_execution) - return; - /* FIXME: cagney/1999-09-27: Closely related to the above. Make - calls target_terminal_*() idenpotent. The event-loop GDB talking - to an asynchronous target with a synchronous command calls this - function from both event-top.c and infrun.c/infcmd.c. Once GDB - stops trying to transfer the terminal to the target when it - shouldn't this guard can go away. */ + /* FIXME: cagney/1999-09-27: Make calls to target_terminal_*() + idempotent. The event-loop GDB talking to an asynchronous target + with a synchronous command calls this function from both + event-top.c and infrun.c/infcmd.c. Once GDB stops trying to + transfer the terminal to the target when it shouldn't this guard + can go away. */ if (!remote_async_terminal_ours_p) return; delete_file_handler (input_fd); @@ -3988,9 +4519,6 @@ remote_terminal_ours (void) return; /* See FIXME in remote_terminal_inferior. */ - if (!sync_execution) - return; - /* See FIXME in remote_terminal_inferior. */ if (remote_async_terminal_ours_p) return; cleanup_sigint_signal_handler (NULL); @@ -4037,6 +4565,8 @@ struct stop_reply int solibs_changed; int replay_event; + + int core; }; /* The list of already fetched and acknowledged stop events. */ @@ -4114,26 +4644,23 @@ do_stop_reply_xfree (void *arg) static struct stop_reply * queued_stop_reply (ptid_t ptid) { - struct stop_reply *it, *prev; - struct stop_reply head; - - head.next = stop_reply_queue; - prev = &head; - - it = head.next; - - if (!ptid_equal (ptid, minus_one_ptid)) - for (; it; prev = it, it = it->next) - if (ptid_equal (ptid, it->ptid)) - break; + struct stop_reply *it; + struct stop_reply **it_link; - if (it) + it = stop_reply_queue; + it_link = &stop_reply_queue; + while (it) { - prev->next = it->next; - it->next = NULL; - } + if (ptid_match (it->ptid, ptid)) + { + *it_link = it->next; + it->next = NULL; + break; + } - stop_reply_queue = head.next; + it_link = &it->next; + it = *it_link; + } if (stop_reply_queue) /* There's still at least an event left. */ @@ -4200,126 +4727,130 @@ remote_parse_stop_reply (char *buf, struct stop_reply *event) event->replay_event = 0; event->stopped_by_watchpoint_p = 0; event->regcache = NULL; + event->core = -1; switch (buf[0]) { case 'T': /* Status with PC, SP, FP, ... */ - { - gdb_byte regs[MAX_REGISTER_SIZE]; - - /* Expedited reply, containing Signal, {regno, reg} repeat. */ - /* format is: 'Tssn...:r...;n...:r...;n...:r...;#cc', where - ss = signal number - n... = register number - r... = register contents - */ - - p = &buf[3]; /* after Txx */ - while (*p) - { - char *p1; - char *p_temp; - int fieldsize; - LONGEST pnum = 0; + /* Expedited reply, containing Signal, {regno, reg} repeat. */ + /* format is: 'Tssn...:r...;n...:r...;n...:r...;#cc', where + ss = signal number + n... = register number + r... = register contents + */ + + p = &buf[3]; /* after Txx */ + while (*p) + { + char *p1; + char *p_temp; + int fieldsize; + LONGEST pnum = 0; - /* If the packet contains a register number, save it in - pnum and set p1 to point to the character following it. - Otherwise p1 points to p. */ + /* If the packet contains a register number, save it in + pnum and set p1 to point to the character following it. + Otherwise p1 points to p. */ - /* If this packet is an awatch packet, don't parse the 'a' - as a register number. */ + /* If this packet is an awatch packet, don't parse the 'a' + as a register number. */ - if (strncmp (p, "awatch", strlen("awatch")) != 0) - { - /* Read the ``P'' register number. */ - pnum = strtol (p, &p_temp, 16); - p1 = p_temp; - } - else - p1 = p; + if (strncmp (p, "awatch", strlen("awatch")) != 0 + && strncmp (p, "core", strlen ("core") != 0)) + { + /* Read the ``P'' register number. */ + pnum = strtol (p, &p_temp, 16); + p1 = p_temp; + } + else + p1 = p; - if (p1 == p) /* No register number present here. */ - { - p1 = strchr (p, ':'); - if (p1 == NULL) - error (_("Malformed packet(a) (missing colon): %s\n\ + if (p1 == p) /* No register number present here. */ + { + p1 = strchr (p, ':'); + if (p1 == NULL) + error (_("Malformed packet(a) (missing colon): %s\n\ Packet: '%s'\n"), - p, buf); - if (strncmp (p, "thread", p1 - p) == 0) - event->ptid = read_ptid (++p1, &p); - else if ((strncmp (p, "watch", p1 - p) == 0) - || (strncmp (p, "rwatch", p1 - p) == 0) - || (strncmp (p, "awatch", p1 - p) == 0)) - { - event->stopped_by_watchpoint_p = 1; - p = unpack_varlen_hex (++p1, &addr); - event->watch_data_address = (CORE_ADDR) addr; - } - else if (strncmp (p, "library", p1 - p) == 0) - { - p1++; - p_temp = p1; - while (*p_temp && *p_temp != ';') - p_temp++; + p, buf); + if (strncmp (p, "thread", p1 - p) == 0) + event->ptid = read_ptid (++p1, &p); + else if ((strncmp (p, "watch", p1 - p) == 0) + || (strncmp (p, "rwatch", p1 - p) == 0) + || (strncmp (p, "awatch", p1 - p) == 0)) + { + event->stopped_by_watchpoint_p = 1; + p = unpack_varlen_hex (++p1, &addr); + event->watch_data_address = (CORE_ADDR) addr; + } + else if (strncmp (p, "library", p1 - p) == 0) + { + p1++; + p_temp = p1; + while (*p_temp && *p_temp != ';') + p_temp++; - event->solibs_changed = 1; + event->solibs_changed = 1; + p = p_temp; + } + else if (strncmp (p, "replaylog", p1 - p) == 0) + { + /* NO_HISTORY event. + p1 will indicate "begin" or "end", but + it makes no difference for now, so ignore it. */ + event->replay_event = 1; + p_temp = strchr (p1 + 1, ';'); + if (p_temp) p = p_temp; - } - else if (strncmp (p, "replaylog", p1 - p) == 0) - { - /* NO_HISTORY event. - p1 will indicate "begin" or "end", but - it makes no difference for now, so ignore it. */ - event->replay_event = 1; - p_temp = strchr (p1 + 1, ';'); - if (p_temp) - p = p_temp; - } - else - { - /* Silently skip unknown optional info. */ - p_temp = strchr (p1 + 1, ';'); - if (p_temp) - p = p_temp; - } - } - else - { - struct packet_reg *reg = packet_reg_from_pnum (rsa, pnum); - cached_reg_t cached_reg; - - cached_reg.num = reg->regnum; + } + else if (strncmp (p, "core", p1 - p) == 0) + { + ULONGEST c; + p = unpack_varlen_hex (++p1, &c); + event->core = c; + } + else + { + /* Silently skip unknown optional info. */ + p_temp = strchr (p1 + 1, ';'); + if (p_temp) + p = p_temp; + } + } + else + { + struct packet_reg *reg = packet_reg_from_pnum (rsa, pnum); + cached_reg_t cached_reg; - p = p1; + p = p1; - if (*p != ':') - error (_("Malformed packet(b) (missing colon): %s\n\ + if (*p != ':') + error (_("Malformed packet(b) (missing colon): %s\n\ Packet: '%s'\n"), - p, buf); - ++p; + p, buf); + ++p; - if (reg == NULL) - error (_("Remote sent bad register number %s: %s\n\ + if (reg == NULL) + error (_("Remote sent bad register number %s: %s\n\ Packet: '%s'\n"), - phex_nz (pnum, 0), p, buf); + phex_nz (pnum, 0), p, buf); - fieldsize = hex2bin (p, cached_reg.data, - register_size (target_gdbarch, - reg->regnum)); - p += 2 * fieldsize; - if (fieldsize < register_size (target_gdbarch, - reg->regnum)) - warning (_("Remote reply is too short: %s"), buf); + cached_reg.num = reg->regnum; - VEC_safe_push (cached_reg_t, event->regcache, &cached_reg); - } + fieldsize = hex2bin (p, cached_reg.data, + register_size (target_gdbarch, + reg->regnum)); + p += 2 * fieldsize; + if (fieldsize < register_size (target_gdbarch, + reg->regnum)) + warning (_("Remote reply is too short: %s"), buf); - if (*p != ';') - error (_("Remote register badly formatted: %s\nhere: %s"), - buf, p); - ++p; - } - } + VEC_safe_push (cached_reg_t, event->regcache, &cached_reg); + } + + if (*p != ';') + error (_("Remote register badly formatted: %s\nhere: %s"), + buf, p); + ++p; + } /* fall through */ case 'S': /* Old style status, just signal only. */ if (event->solibs_changed) @@ -4435,7 +4966,6 @@ static void remote_get_pending_stop_replies (void) { struct remote_state *rs = get_remote_state (); - int ret; if (pending_stop_reply) { @@ -4486,6 +5016,7 @@ process_stop_reply (struct stop_reply *stop_reply, struct target_waitstatus *status) { ptid_t ptid; + struct thread_info *info; *status = stop_reply->ws; ptid = stop_reply->ptid; @@ -4495,32 +5026,31 @@ process_stop_reply (struct stop_reply *stop_reply, if (ptid_equal (ptid, null_ptid)) ptid = inferior_ptid; - if (status->kind == TARGET_WAITKIND_EXITED - || status->kind == TARGET_WAITKIND_SIGNALLED) + if (status->kind != TARGET_WAITKIND_EXITED + && status->kind != TARGET_WAITKIND_SIGNALLED) { - int pid = ptid_get_pid (ptid); - delete_inferior (pid); - } - else - notice_new_inferiors (ptid); + /* Expedited registers. */ + if (stop_reply->regcache) + { + struct regcache *regcache + = get_thread_arch_regcache (ptid, target_gdbarch); + cached_reg_t *reg; + int ix; + + for (ix = 0; + VEC_iterate(cached_reg_t, stop_reply->regcache, ix, reg); + ix++) + regcache_raw_supply (regcache, reg->num, reg->data); + VEC_free (cached_reg_t, stop_reply->regcache); + } - /* Expedited registers. */ - if (stop_reply->regcache) - { - cached_reg_t *reg; - int ix; + remote_stopped_by_watchpoint_p = stop_reply->stopped_by_watchpoint_p; + remote_watch_data_address = stop_reply->watch_data_address; - for (ix = 0; - VEC_iterate(cached_reg_t, stop_reply->regcache, ix, reg); - ix++) - regcache_raw_supply (get_thread_regcache (ptid), - reg->num, reg->data); - VEC_free (cached_reg_t, stop_reply->regcache); + remote_notice_new_inferior (ptid, 0); + demand_private_info (ptid)->core = stop_reply->core; } - remote_stopped_by_watchpoint_p = stop_reply->stopped_by_watchpoint_p; - remote_watch_data_address = stop_reply->watch_data_address; - stop_reply_xfree (stop_reply); return ptid; } @@ -4528,11 +5058,9 @@ process_stop_reply (struct stop_reply *stop_reply, /* The non-stop mode version of target_wait. */ static ptid_t -remote_wait_ns (ptid_t ptid, struct target_waitstatus *status) +remote_wait_ns (ptid_t ptid, struct target_waitstatus *status, int options) { struct remote_state *rs = get_remote_state (); - struct remote_arch_state *rsa = get_remote_arch_state (); - ptid_t event_ptid = null_ptid; struct stop_reply *stop_reply; int ret; @@ -4570,16 +5098,15 @@ remote_wait_ns (ptid_t ptid, struct target_waitstatus *status) if (stop_reply != NULL) return process_stop_reply (stop_reply, status); - /* Still no event. If we're in asynchronous mode, then just + /* Still no event. If we're just polling for an event, then return to the event loop. */ - if (remote_is_async_p ()) + if (options & TARGET_WNOHANG) { status->kind = TARGET_WAITKIND_IGNORE; return minus_one_ptid; } - /* Otherwise, asynchronous mode is masked, so do a blocking - wait. */ + /* Otherwise do a blocking wait. */ ret = getpkt_or_notif_sane (&rs->buf, &rs->buf_size, 1 /* forever */); } @@ -4589,16 +5116,15 @@ remote_wait_ns (ptid_t ptid, struct target_waitstatus *status) STATUS just as `wait' would. */ static ptid_t -remote_wait_as (ptid_t ptid, struct target_waitstatus *status) +remote_wait_as (ptid_t ptid, struct target_waitstatus *status, int options) { struct remote_state *rs = get_remote_state (); - struct remote_arch_state *rsa = get_remote_arch_state (); ptid_t event_ptid = null_ptid; - ULONGEST addr; - int solibs_changed = 0; - char *buf, *p; + char *buf; struct stop_reply *stop_reply; + again: + status->kind = TARGET_WAITKIND_IGNORE; status->value.integer = 0; @@ -4641,6 +5167,11 @@ remote_wait_as (ptid_t ptid, struct target_waitstatus *status) /* We got something. */ rs->waiting_for_stop_reply = 0; + /* Assume that the target has acknowledged Ctrl-C unless we receive + an 'F' or 'O' packet. */ + if (buf[0] != 'F' && buf[0] != 'O') + rs->ctrlc_pending_p = 0; + switch (buf[0]) { case 'E': /* Error of some sort. */ @@ -4651,7 +5182,8 @@ remote_wait_as (ptid_t ptid, struct target_waitstatus *status) status->value.sig = TARGET_SIGNAL_0; break; case 'F': /* File-I/O request. */ - remote_fileio_request (buf); + remote_fileio_request (buf, rs->ctrlc_pending_p); + rs->ctrlc_pending_p = 0; break; case 'T': case 'S': case 'X': case 'W': { @@ -4701,8 +5233,14 @@ remote_wait_as (ptid_t ptid, struct target_waitstatus *status) } if (status->kind == TARGET_WAITKIND_IGNORE) - /* Nothing interesting happened. */ - return minus_one_ptid; + { + /* Nothing interesting happened. If we're doing a non-blocking + poll, we're done. Otherwise, go back to waiting. */ + if (options & TARGET_WNOHANG) + return minus_one_ptid; + else + goto again; + } else if (status->kind != TARGET_WAITKIND_EXITED && status->kind != TARGET_WAITKIND_SIGNALLED) { @@ -4722,24 +5260,15 @@ remote_wait_as (ptid_t ptid, struct target_waitstatus *status) STATUS just as `wait' would. */ static ptid_t -remote_wait (ptid_t ptid, struct target_waitstatus *status) +remote_wait (struct target_ops *ops, + ptid_t ptid, struct target_waitstatus *status, int options) { ptid_t event_ptid; if (non_stop) - event_ptid = remote_wait_ns (ptid, status); + event_ptid = remote_wait_ns (ptid, status, options); else - { - /* In synchronous mode, keep waiting until the target stops. In - asynchronous mode, always return to the event loop. */ - - do - { - event_ptid = remote_wait_as (ptid, status); - } - while (status->kind == TARGET_WAITKIND_IGNORE - && !target_can_async_p ()); - } + event_ptid = remote_wait_as (ptid, status, options); if (target_can_async_p ()) { @@ -4772,7 +5301,8 @@ fetch_register_using_p (struct regcache *regcache, struct packet_reg *reg) *p++ = 'p'; p += hexnumstr (p, reg->pnum); *p++ = '\0'; - remote_send (&rs->buf, &rs->buf_size); + putpkt (rs->buf); + getpkt (&rs->buf, &rs->buf_size, 0); buf = rs->buf; @@ -4783,8 +5313,10 @@ fetch_register_using_p (struct regcache *regcache, struct packet_reg *reg) case PACKET_UNKNOWN: return 0; case PACKET_ERROR: - error (_("Could not fetch register \"%s\""), - gdbarch_register_name (get_regcache_arch (regcache), reg->regnum)); + error (_("Could not fetch register \"%s\"; remote failure reply '%s'"), + gdbarch_register_name (get_regcache_arch (regcache), + reg->regnum), + buf); } /* If this register is unfetchable, tell the regcache. */ @@ -4815,9 +5347,7 @@ static int send_g_packet (void) { struct remote_state *rs = get_remote_state (); - int i, buf_len; - char *p; - char *regs; + int buf_len; sprintf (rs->buf, "g"); remote_send (&rs->buf, &rs->buf_size); @@ -4945,9 +5475,9 @@ fetch_registers_using_g (struct regcache *regcache) } static void -remote_fetch_registers (struct regcache *regcache, int regnum) +remote_fetch_registers (struct target_ops *ops, + struct regcache *regcache, int regnum) { - struct remote_state *rs = get_remote_state (); struct remote_arch_state *rsa = get_remote_arch_state (); int i; @@ -5019,11 +5549,11 @@ remote_prepare_to_store (struct regcache *regcache) packet was not recognized. */ static int -store_register_using_P (const struct regcache *regcache, struct packet_reg *reg) +store_register_using_P (const struct regcache *regcache, + struct packet_reg *reg) { struct gdbarch *gdbarch = get_regcache_arch (regcache); struct remote_state *rs = get_remote_state (); - struct remote_arch_state *rsa = get_remote_arch_state (); /* Try storing a single register. */ char *buf = rs->buf; gdb_byte regp[MAX_REGISTER_SIZE]; @@ -5039,15 +5569,16 @@ store_register_using_P (const struct regcache *regcache, struct packet_reg *reg) p = buf + strlen (buf); regcache_raw_collect (regcache, reg->regnum, regp); bin2hex (regp, p, register_size (gdbarch, reg->regnum)); - remote_send (&rs->buf, &rs->buf_size); + putpkt (rs->buf); + getpkt (&rs->buf, &rs->buf_size, 0); switch (packet_ok (rs->buf, &remote_protocol_packets[PACKET_P])) { case PACKET_OK: return 1; case PACKET_ERROR: - error (_("Could not write register \"%s\""), - gdbarch_register_name (gdbarch, reg->regnum)); + error (_("Could not write register \"%s\"; remote failure reply '%s'"), + gdbarch_register_name (gdbarch, reg->regnum), rs->buf); case PACKET_UNKNOWN: return 0; default: @@ -5087,16 +5618,20 @@ store_registers_using_G (const struct regcache *regcache) /* remote_prepare_to_store insures that rsa->sizeof_g_packet gets updated. */ bin2hex (regs, p, rsa->sizeof_g_packet); - remote_send (&rs->buf, &rs->buf_size); + putpkt (rs->buf); + getpkt (&rs->buf, &rs->buf_size, 0); + if (packet_check_result (rs->buf) == PACKET_ERROR) + error (_("Could not write registers; remote failure reply '%s'"), + rs->buf); } /* Store register REGNUM, or all registers if REGNUM == -1, from the contents of the register cache buffer. FIXME: ignores errors. */ static void -remote_store_registers (struct regcache *regcache, int regnum) +remote_store_registers (struct target_ops *ops, + struct regcache *regcache, int regnum) { - struct remote_state *rs = get_remote_state (); struct remote_arch_state *rsa = get_remote_arch_state (); int i; @@ -5638,10 +6173,13 @@ handle_notification (char *buf, size_t length) if (strncmp (buf, "Stop:", 5) == 0) { if (pending_stop_reply) - /* We've already parsed the in-flight stop-reply, but the stub - for some reason thought we didn't, possibly due to timeout - on its side. Just ignore it. */ - ; + { + /* We've already parsed the in-flight stop-reply, but the + stub for some reason thought we didn't, possibly due to + timeout on its side. Just ignore it. */ + if (remote_debug) + fprintf_unfiltered (gdb_stdlog, "ignoring resent notification\n"); + } else { struct cleanup *old_chain; @@ -5659,6 +6197,9 @@ handle_notification (char *buf, size_t length) /* Notify the event loop there's a stop reply to acknowledge and that there may be more events to fetch. */ mark_async_event_handler (remote_async_get_pending_events_token); + + if (remote_debug) + fprintf_unfiltered (gdb_stdlog, "stop notification captured\n"); } } else @@ -5694,7 +6235,7 @@ remote_xfer_memory (CORE_ADDR mem_addr, gdb_byte *buffer, int mem_len, FORMAT and the remaining arguments, then gets the reply. Returns whether the packet was a success, a failure, or unknown. */ -enum packet_result +static enum packet_result remote_send_printf (const char *format, ...) { struct remote_state *rs = get_remote_state (); @@ -5732,6 +6273,7 @@ static void remote_flash_erase (struct target_ops *ops, ULONGEST address, LONGEST length) { + int addr_size = gdbarch_addr_bit (target_gdbarch) / 8; int saved_remote_timeout = remote_timeout; enum packet_result ret; @@ -5740,7 +6282,7 @@ remote_flash_erase (struct target_ops *ops, remote_timeout = remote_flash_timeout; ret = remote_send_printf ("vFlashErase:%s,%s", - paddr (address), + phex (address, addr_size), phex (length, 4)); switch (ret) { @@ -5847,6 +6389,27 @@ 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. */ + +static char * +escape_buffer (const char *buf, int n) +{ + struct cleanup *old_chain; + struct ui_file *stb; + char *str; + + stb = mem_fileopen (); + old_chain = make_cleanup_ui_file_delete (stb); + + fputstrn_unfiltered (buf, n, 0, stb); + str = ui_file_xstrdup (stb, NULL); + do_cleanups (old_chain); + return str; +} + /* Display a null-terminated packet on stdout, for debugging, using C string notation. */ @@ -5919,11 +6482,15 @@ putpkt_binary (char *buf, int cnt) if (remote_debug) { + struct cleanup *old_chain; + char *str; + *p = '\0'; - fprintf_unfiltered (gdb_stdlog, "Sending packet: "); - fputstrn_unfiltered (buf2, p - buf2, 0, gdb_stdlog); - fprintf_unfiltered (gdb_stdlog, "..."); + str = escape_buffer (buf2, p - buf2); + old_chain = make_cleanup (xfree, str); + fprintf_unfiltered (gdb_stdlog, "Sending packet: %s...", str); gdb_flush (gdb_stdlog); + do_cleanups (old_chain); } if (serial_write (remote_desc, buf2, p - buf2)) perror_with_name (_("putpkt: write failed")); @@ -5997,9 +6564,15 @@ putpkt_binary (char *buf, int cnt) { if (remote_debug) { - fprintf_unfiltered (gdb_stdlog, " Notification received: "); - fputstrn_unfiltered (rs->buf, val, 0, gdb_stdlog); - fprintf_unfiltered (gdb_stdlog, "\n"); + struct cleanup *old_chain; + char *str; + + 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); } handle_notification (rs->buf, val); /* We're in sync now, rewait for the ack. */ @@ -6163,11 +6736,16 @@ read_frame (char **buf_p, if (remote_debug) { - fprintf_filtered (gdb_stdlog, - "Bad checksum, sentsum=0x%x, csum=0x%x, buf=", - pktcsum, csum); - fputstrn_filtered (buf, bc, 0, gdb_stdlog); - fputs_filtered ("\n", gdb_stdlog); + struct cleanup *old_chain; + char *str; + + 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); } /* Number of characters in buffer ignoring trailing NULL. */ @@ -6257,7 +6835,7 @@ getpkt_or_notif_sane_1 (char **buf, long *sizeof_buf, int forever, int c; int tries; int timeout; - int val; + int val = -1; /* We're reading a new response. Make sure we don't look at a previously cached response. */ @@ -6340,9 +6918,13 @@ getpkt_or_notif_sane_1 (char **buf, long *sizeof_buf, int forever, { if (remote_debug) { - fprintf_unfiltered (gdb_stdlog, "Packet received: "); - fputstrn_unfiltered (*buf, val, 0, gdb_stdlog); - fprintf_unfiltered (gdb_stdlog, "\n"); + struct cleanup *old_chain; + char *str; + + str = escape_buffer (*buf, val); + old_chain = make_cleanup (xfree, str); + fprintf_unfiltered (gdb_stdlog, "Packet received: %s\n", str); + do_cleanups (old_chain); } /* Skip the ack char if we're in no-ack mode. */ @@ -6359,9 +6941,15 @@ getpkt_or_notif_sane_1 (char **buf, long *sizeof_buf, int forever, if (remote_debug) { - fprintf_unfiltered (gdb_stdlog, " Notification received: "); - fputstrn_unfiltered (*buf, val, 0, gdb_stdlog); - fprintf_unfiltered (gdb_stdlog, "\n"); + struct cleanup *old_chain; + char *str; + + str = escape_buffer (*buf, val); + old_chain = make_cleanup (xfree, str); + fprintf_unfiltered (gdb_stdlog, + " Notification received: %s\n", + str); + do_cleanups (old_chain); } handle_notification (*buf, val); @@ -6388,7 +6976,7 @@ getpkt_or_notif_sane (char **buf, long *sizeof_buf, int forever) static void -remote_kill (void) +remote_kill (struct target_ops *ops) { /* Use catch_errors so the user can quit from gdb even when we aren't on speaking terms with the remote system. */ @@ -6420,7 +7008,7 @@ remote_vkill (int pid, struct remote_state *rs) } static void -extended_remote_kill (void) +extended_remote_kill (struct target_ops *ops) { int res; int pid = ptid_get_pid (inferior_ptid); @@ -6447,14 +7035,13 @@ extended_remote_kill (void) if (res != 0) error (_("Can't kill process")); - delete_inferior (pid); target_mourn_inferior (); } static void -remote_mourn (void) +remote_mourn (struct target_ops *ops) { - remote_mourn_1 (&remote_ops); + remote_mourn_1 (ops); } /* Worker function for remote_mourn. */ @@ -6463,20 +7050,8 @@ remote_mourn_1 (struct target_ops *target) { unpush_target (target); - /* remote_close takes care of cleaning up. */ -} - -static int -select_new_thread_callback (struct thread_info *th, void* data) -{ - if (!is_exited (th->ptid)) - { - switch_to_thread (th->ptid); - printf_filtered (_("[Switching to %s]\n"), - target_pid_to_str (inferior_ptid)); - return 1; - } - return 0; + /* remote_close takes care of doing most of the clean up. */ + generic_mourn_inferior (); } static void @@ -6491,24 +7066,39 @@ extended_remote_mourn_1 (struct target_ops *target) /* We're no longer interested in these events. */ discard_pending_stop_replies (ptid_get_pid (inferior_ptid)); + /* If the current general thread belonged to the process we just + detached from or has exited, the remote side current general + thread becomes undefined. Considering a case like this: + + - We just got here due to a detach. + - The process that we're detaching from happens to immediately + report a global breakpoint being hit in non-stop mode, in the + same thread we had selected before. + - GDB attaches to this process again. + - This event happens to be the next event we handle. + + GDB would consider that the current general thread didn't need to + be set on the stub side (with Hg), since for all it knew, + GENERAL_THREAD hadn't changed. + + Notice that although in all-stop mode, the remote server always + sets the current thread to the thread reporting the stop event, + that doesn't happen in non-stop mode; in non-stop, the stub *must + not* change the current thread when reporting a breakpoint hit, + due to the decoupling of event reporting and event handling. + + To keep things simple, we always invalidate our notion of the + current thread. */ + record_currthread (minus_one_ptid); + /* Unlike "target remote", we do not want to unpush the target; then the next time the user says "run", we won't be connected. */ - if (have_inferiors ()) - { - extern void nullify_last_target_wait_ptid (); - /* Multi-process case. The current process has exited, but - there are other processes to debug. Switch to the first - available. */ - iterate_over_threads (select_new_thread_callback, NULL); - nullify_last_target_wait_ptid (); - } - else - { - struct remote_state *rs = get_remote_state (); + /* Call common code to mark the inferior as not running. */ + generic_mourn_inferior (); - /* Call common code to mark the inferior as not running. */ - generic_mourn_inferior (); + if (!have_inferiors ()) + { if (!remote_multi_process_p (rs)) { /* Check whether the target is running now - some remote stubs @@ -6523,30 +7113,20 @@ extended_remote_mourn_1 (struct target_ops *target) so that the user can say "kill" again. */ inferior_ptid = magic_null_ptid; } - else - { - /* Mark this (still pushed) target as not executable until we - restart it. */ - target_mark_exited (target); - } } - else - /* Always remove execution if this was the last process. */ - target_mark_exited (target); } } static void -extended_remote_mourn (void) +extended_remote_mourn (struct target_ops *ops) { - extended_remote_mourn_1 (&extended_remote_ops); + extended_remote_mourn_1 (ops); } static int extended_remote_run (char *args) { struct remote_state *rs = get_remote_state (); - char *p; int len; /* If the user has disabled vRun support, or we have detected that @@ -6633,11 +7213,14 @@ extended_remote_create_inferior_1 (char *exec_file, char *args, extended_remote_restart (); } - /* Clean up from the last time we ran, before we mark the target - running again. This will mark breakpoints uninserted, and - get_offsets may insert breakpoints. */ - init_thread_list (); - init_wait_for_inferior (); + if (!have_inferiors ()) + { + /* Clean up from the last time we ran, before we mark the target + running again. This will mark breakpoints uninserted, and + get_offsets may insert breakpoints. */ + init_thread_list (); + init_wait_for_inferior (); + } /* Now mark the inferior as running before we do anything else. */ inferior_ptid = magic_null_ptid; @@ -6645,17 +7228,16 @@ extended_remote_create_inferior_1 (char *exec_file, char *args, /* Now, if we have thread information, update inferior_ptid. */ inferior_ptid = remote_current_thread (inferior_ptid); - add_inferior (ptid_get_pid (inferior_ptid)); + remote_add_inferior (ptid_get_pid (inferior_ptid), 0); add_thread_silent (inferior_ptid); - target_mark_running (&extended_remote_ops); - /* Get updated offsets, if the stub uses qOffsets. */ get_offsets (); } static void -extended_remote_create_inferior (char *exec_file, char *args, +extended_remote_create_inferior (struct target_ops *ops, + char *exec_file, char *args, char **env, int from_tty) { extended_remote_create_inferior_1 (exec_file, args, env, from_tty); @@ -6667,7 +7249,8 @@ extended_remote_create_inferior (char *exec_file, char *args, which don't, we insert a traditional memory breakpoint. */ static int -remote_insert_breakpoint (struct bp_target_info *bp_tgt) +remote_insert_breakpoint (struct gdbarch *gdbarch, + struct bp_target_info *bp_tgt) { /* Try the "Z" s/w breakpoint packet if it is not already disabled. If it succeeds, then set the support to PACKET_ENABLE. If it @@ -6681,7 +7264,7 @@ remote_insert_breakpoint (struct bp_target_info *bp_tgt) char *p; int bpsize; - gdbarch_breakpoint_from_pc (target_gdbarch, &addr, &bpsize); + gdbarch_remote_breakpoint_from_pc (gdbarch, &addr, &bpsize); rs = get_remote_state (); p = rs->buf; @@ -6709,15 +7292,15 @@ remote_insert_breakpoint (struct bp_target_info *bp_tgt) } } - return memory_insert_breakpoint (bp_tgt); + return memory_insert_breakpoint (gdbarch, bp_tgt); } static int -remote_remove_breakpoint (struct bp_target_info *bp_tgt) +remote_remove_breakpoint (struct gdbarch *gdbarch, + struct bp_target_info *bp_tgt) { CORE_ADDR addr = bp_tgt->placed_address; struct remote_state *rs = get_remote_state (); - int bp_size; if (remote_protocol_packets[PACKET_Z0].support != PACKET_DISABLE) { @@ -6737,7 +7320,7 @@ remote_remove_breakpoint (struct bp_target_info *bp_tgt) return (rs->buf[0] == 'E'); } - return memory_remove_breakpoint (bp_tgt); + return memory_remove_breakpoint (gdbarch, bp_tgt); } static int @@ -6768,7 +7351,7 @@ remote_insert_watchpoint (CORE_ADDR addr, int len, int type) enum Z_packet_type packet = watchpoint_to_Z_packet (type); if (remote_protocol_packets[PACKET_Z0 + packet].support == PACKET_DISABLE) - return -1; + return 1; sprintf (rs->buf, "Z%x,", packet); p = strchr (rs->buf, '\0'); @@ -6782,8 +7365,9 @@ remote_insert_watchpoint (CORE_ADDR addr, int len, int type) switch (packet_ok (rs->buf, &remote_protocol_packets[PACKET_Z0 + packet])) { case PACKET_ERROR: - case PACKET_UNKNOWN: return -1; + case PACKET_UNKNOWN: + return 1; case PACKET_OK: return 0; } @@ -6873,7 +7457,8 @@ remote_stopped_data_address (struct target_ops *target, CORE_ADDR *addr_p) static int -remote_insert_hw_breakpoint (struct bp_target_info *bp_tgt) +remote_insert_hw_breakpoint (struct gdbarch *gdbarch, + struct bp_target_info *bp_tgt) { CORE_ADDR addr; struct remote_state *rs; @@ -6882,8 +7467,8 @@ remote_insert_hw_breakpoint (struct bp_target_info *bp_tgt) /* The length field should be set to the size of a breakpoint instruction, even though we aren't inserting one ourselves. */ - gdbarch_breakpoint_from_pc - (target_gdbarch, &bp_tgt->placed_address, &bp_tgt->placed_size); + gdbarch_remote_breakpoint_from_pc + (gdbarch, &bp_tgt->placed_address, &bp_tgt->placed_size); if (remote_protocol_packets[PACKET_Z1].support == PACKET_DISABLE) return -1; @@ -6916,7 +7501,8 @@ remote_insert_hw_breakpoint (struct bp_target_info *bp_tgt) static int -remote_remove_hw_breakpoint (struct bp_target_info *bp_tgt) +remote_remove_hw_breakpoint (struct gdbarch *gdbarch, + struct bp_target_info *bp_tgt) { CORE_ADDR addr; struct remote_state *rs = get_remote_state (); @@ -6954,7 +7540,7 @@ static unsigned long crc32_table[256] = {0, 0}; static unsigned long -crc32 (unsigned char *buf, int len, unsigned int crc) +crc32 (const unsigned char *buf, int len, unsigned int crc) { if (!crc32_table[1]) { @@ -6978,39 +7564,59 @@ crc32 (unsigned char *buf, int len, unsigned int crc) return crc; } +/* Verify memory using the "qCRC:" request. */ + +static int +remote_verify_memory (struct target_ops *ops, + const gdb_byte *data, CORE_ADDR lma, ULONGEST size) +{ + struct remote_state *rs = get_remote_state (); + unsigned long host_crc, target_crc; + char *tmp; + + /* FIXME: assumes lma can fit into long. */ + xsnprintf (rs->buf, get_remote_packet_size (), "qCRC:%lx,%lx", + (long) lma, (long) size); + putpkt (rs->buf); + + /* Be clever; compute the host_crc before waiting for target + reply. */ + host_crc = crc32 (data, size, 0xffffffff); + + getpkt (&rs->buf, &rs->buf_size, 0); + if (rs->buf[0] == 'E') + return -1; + + if (rs->buf[0] != 'C') + error (_("remote target does not support this operation")); + + for (target_crc = 0, tmp = &rs->buf[1]; *tmp; tmp++) + target_crc = target_crc * 16 + fromhex (*tmp); + + return (host_crc == target_crc); +} + /* compare-sections command With no arguments, compares each loadable section in the exec bfd with the same memory range on the target, and reports mismatches. - Useful for verifying the image on the target against the exec file. - Depends on the target understanding the new "qCRC:" request. */ - -/* FIXME: cagney/1999-10-26: This command should be broken down into a - target method (target verify memory) and generic version of the - actual command. This will allow other high-level code (especially - generic_load()) to make use of this target functionality. */ + Useful for verifying the image on the target against the exec file. */ static void compare_sections_command (char *args, int from_tty) { - struct remote_state *rs = get_remote_state (); asection *s; - unsigned long host_crc, target_crc; - extern bfd *exec_bfd; struct cleanup *old_chain; - char *tmp; char *sectdata; const char *sectname; bfd_size_type size; bfd_vma lma; int matched = 0; int mismatched = 0; + int res; if (!exec_bfd) error (_("command cannot be used without an exec file")); - if (!current_target.to_shortname || - strcmp (current_target.to_shortname, "remote") != 0) - error (_("command can only be used with remote target")); for (s = exec_bfd->sections; s; s = s->next) { @@ -7027,31 +7633,22 @@ compare_sections_command (char *args, int from_tty) matched = 1; /* do this section */ lma = s->lma; - /* FIXME: assumes lma can fit into long. */ - xsnprintf (rs->buf, get_remote_packet_size (), "qCRC:%lx,%lx", - (long) lma, (long) size); - putpkt (rs->buf); - /* Be clever; compute the host_crc before waiting for target - reply. */ sectdata = xmalloc (size); old_chain = make_cleanup (xfree, sectdata); bfd_get_section_contents (exec_bfd, s, sectdata, 0, size); - host_crc = crc32 ((unsigned char *) sectdata, size, 0xffffffff); - getpkt (&rs->buf, &rs->buf_size, 0); - if (rs->buf[0] == 'E') - error (_("target memory fault, section %s, range 0x%s -- 0x%s"), - sectname, paddr (lma), paddr (lma + size)); - if (rs->buf[0] != 'C') - error (_("remote target does not support this operation")); - - for (target_crc = 0, tmp = &rs->buf[1]; *tmp; tmp++) - target_crc = target_crc * 16 + fromhex (*tmp); - - printf_filtered ("Section %s, range 0x%s -- 0x%s: ", - sectname, paddr (lma), paddr (lma + size)); - if (host_crc == target_crc) + res = target_verify_memory (sectdata, lma, size); + + if (res == -1) + error (_("target memory fault, section %s, range %s -- %s"), sectname, + paddress (target_gdbarch, lma), + paddress (target_gdbarch, lma + size)); + + printf_filtered ("Section %s, range %s -- %s: ", sectname, + paddress (target_gdbarch, lma), + paddress (target_gdbarch, lma + size)); + if (res) printf_filtered ("matched.\n"); else { @@ -7080,7 +7677,6 @@ remote_write_qxfer (struct target_ops *ops, const char *object_name, { int i, buf_len; ULONGEST n; - gdb_byte *wbuf; struct remote_state *rs = get_remote_state (); int max_size = get_memory_write_packet_size (); @@ -7125,7 +7721,6 @@ remote_read_qxfer (struct target_ops *ops, const char *object_name, static ULONGEST finished_offset; struct remote_state *rs = get_remote_state (); - unsigned int total = 0; LONGEST i, n, packet_len; if (packet->support == PACKET_DISABLE) @@ -7243,6 +7838,19 @@ remote_xfer_partial (struct target_ops *ops, enum target_object object, [PACKET_qXfer_spu_write]); } + /* Handle extra signal info using qxfer packets. */ + if (object == TARGET_OBJECT_SIGNAL_INFO) + { + if (readbuf) + return remote_read_qxfer (ops, "siginfo", annex, readbuf, offset, len, + &remote_protocol_packets + [PACKET_qXfer_siginfo_read]); + else + return remote_write_qxfer (ops, "siginfo", annex, writebuf, offset, len, + &remote_protocol_packets + [PACKET_qXfer_siginfo_write]); + } + /* Only handle flash writes. */ if (writebuf != NULL) { @@ -7293,6 +7901,18 @@ remote_xfer_partial (struct target_ops *ops, enum target_object object, return remote_read_qxfer (ops, "memory-map", annex, readbuf, offset, len, &remote_protocol_packets[PACKET_qXfer_memory_map]); + case TARGET_OBJECT_OSDATA: + /* Should only get here if we're connected. */ + gdb_assert (remote_desc); + return remote_read_qxfer + (ops, "osdata", annex, readbuf, offset, len, + &remote_protocol_packets[PACKET_qXfer_osdata]); + + case TARGET_OBJECT_THREADS: + gdb_assert (annex == NULL); + return remote_read_qxfer (ops, "threads", annex, readbuf, offset, len, + &remote_protocol_packets[PACKET_qXfer_threads]); + default: return -1; } @@ -7350,6 +7970,7 @@ remote_search_memory (struct target_ops* ops, const gdb_byte *pattern, ULONGEST pattern_len, CORE_ADDR *found_addrp) { + int addr_size = gdbarch_addr_bit (target_gdbarch) / 8; struct remote_state *rs = get_remote_state (); int max_size = get_memory_write_packet_size (); struct packet_config *packet = @@ -7388,7 +8009,7 @@ remote_search_memory (struct target_ops* ops, /* Insert header. */ i = snprintf (rs->buf, max_size, "qSearch:memory:%s;%s;", - paddr_nz (start_addr), + phex_nz (start_addr, addr_size), phex_nz (search_space_len, sizeof (search_space_len))); max_size -= (i + 1); @@ -7463,7 +8084,7 @@ remote_rcmd (char *command, { char *buf; - /* XXX - see also tracepoint.c:remote_get_noisy_reply(). */ + /* XXX - see also remote_get_noisy_reply(). */ rs->buf[0] = '\0'; getpkt (&rs->buf, &rs->buf_size, 0); buf = rs->buf; @@ -7680,38 +8301,52 @@ Fetch and print the remote list of thread identifiers, one pkt only")); buffer. */ static char * -remote_pid_to_str (ptid_t ptid) +remote_pid_to_str (struct target_ops *ops, ptid_t ptid) { static char buf[64]; struct remote_state *rs = get_remote_state (); - if (ptid_equal (magic_null_ptid, ptid)) - { - xsnprintf (buf, sizeof buf, "Thread
"); - return buf; - } - else if (remote_multi_process_p (rs) - && ptid_get_tid (ptid) != 0 && ptid_get_pid (ptid) != 0) + if (ptid_is_pid (ptid)) { - xsnprintf (buf, sizeof buf, "Thread %d.%ld", - ptid_get_pid (ptid), ptid_get_tid (ptid)); - return buf; + /* Printing an inferior target id. */ + + /* When multi-process extensions are off, there's no way in the + remote protocol to know the remote process id, if there's any + at all. There's one exception --- when we're connected with + target extended-remote, and we manually attached to a process + with "attach PID". We don't record anywhere a flag that + allows us to distinguish that case from the case of + connecting with extended-remote and the stub already being + attached to a process, and reporting yes to qAttached, hence + no smart special casing here. */ + if (!remote_multi_process_p (rs)) + { + xsnprintf (buf, sizeof buf, "Remote target"); + return buf; + } + + return normal_pid_to_str (ptid); } - else if (ptid_get_tid (ptid) != 0) + else { - xsnprintf (buf, sizeof buf, "Thread %ld", - ptid_get_tid (ptid)); + if (ptid_equal (magic_null_ptid, ptid)) + xsnprintf (buf, sizeof buf, "Thread
"); + else if (remote_multi_process_p (rs)) + xsnprintf (buf, sizeof buf, "Thread %d.%ld", + ptid_get_pid (ptid), ptid_get_tid (ptid)); + else + xsnprintf (buf, sizeof buf, "Thread %ld", + ptid_get_tid (ptid)); return buf; } - - return normal_pid_to_str (ptid); } /* Get the address of the thread local variable in OBJFILE which is stored at OFFSET within the thread local storage for thread PTID. */ static CORE_ADDR -remote_get_thread_local_address (ptid_t ptid, CORE_ADDR lm, CORE_ADDR offset) +remote_get_thread_local_address (struct target_ops *ops, + ptid_t ptid, CORE_ADDR lm, CORE_ADDR offset) { if (remote_protocol_packets[PACKET_qGetTLSAddr].support != PACKET_DISABLE) { @@ -7804,12 +8439,32 @@ register_remote_g_packet_guess (struct gdbarch *gdbarch, int bytes, VEC_safe_push (remote_g_packet_guess_s, data->guesses, &new_guess); } +/* Return 1 if remote_read_description would do anything on this target + and architecture, 0 otherwise. */ + +static int +remote_read_description_p (struct target_ops *target) +{ + struct remote_g_packet_data *data + = gdbarch_data (target_gdbarch, remote_g_packet_data_handle); + + if (!VEC_empty (remote_g_packet_guess_s, data->guesses)) + return 1; + + return 0; +} + static const struct target_desc * remote_read_description (struct target_ops *target) { struct remote_g_packet_data *data = gdbarch_data (target_gdbarch, remote_g_packet_data_handle); + /* Do not try this during initial connection, when we do not know + whether there is a running but stopped thread. */ + if (!target_has_execution || ptid_equal (inferior_ptid, null_ptid)) + return NULL; + if (!VEC_empty (remote_g_packet_guess_s, data->guesses)) { struct remote_g_packet_guess *guess; @@ -8414,7 +9069,7 @@ void remote_file_get (const char *remote_file, const char *local_file, int from_tty) { struct cleanup *back_to, *close_cleanup; - int retcode, fd, remote_errno, bytes, io_size; + int fd, remote_errno, bytes, io_size; FILE *file; gdb_byte *buffer; ULONGEST offset; @@ -8544,12 +9199,14 @@ remote_command (char *args, int from_tty) help_list (remote_cmdlist, "remote ", -1, gdb_stdout); } -static int remote_target_can_reverse = 1; - static int remote_can_execute_reverse (void) { - return remote_target_can_reverse; + if (remote_protocol_packets[PACKET_bs].support == PACKET_ENABLE + || remote_protocol_packets[PACKET_bc].support == PACKET_ENABLE) + return 1; + else + return 0; } static int @@ -8565,6 +9222,468 @@ remote_supports_multi_process (void) return remote_multi_process_p (rs); } +int +remote_supports_cond_tracepoints (void) +{ + struct remote_state *rs = get_remote_state (); + return rs->cond_tracepoints; +} + +int +remote_supports_fast_tracepoints (void) +{ + struct remote_state *rs = get_remote_state (); + return rs->fast_tracepoints; +} + +static void +remote_trace_init () +{ + putpkt ("QTinit"); + remote_get_noisy_reply (&target_buf, &target_buf_size); + if (strcmp (target_buf, "OK")) + error (_("Target does not support this command.")); +} + +static void free_actions_list (char **actions_list); +static void free_actions_list_cleanup_wrapper (void *); +static void +free_actions_list_cleanup_wrapper (void *al) +{ + free_actions_list (al); +} + +static void +free_actions_list (char **actions_list) +{ + int ndx; + + if (actions_list == 0) + return; + + for (ndx = 0; actions_list[ndx]; ndx++) + xfree (actions_list[ndx]); + + xfree (actions_list); +} + +static void +remote_download_tracepoint (struct breakpoint *t) +{ + struct bp_location *loc; + CORE_ADDR tpaddr; + char tmp[40]; + char buf[2048]; + char **tdp_actions; + char **stepping_actions; + int ndx; + struct cleanup *old_chain = NULL; + struct agent_expr *aexpr; + struct cleanup *aexpr_chain = NULL; + char *pkt; + + /* Iterate over all the tracepoint locations. It's up to the target to + notice multiple tracepoint packets with the same number but different + addresses, and treat them as multiple locations. */ + for (loc = t->loc; loc; loc = loc->next) + { + encode_actions (t, loc, &tdp_actions, &stepping_actions); + old_chain = make_cleanup (free_actions_list_cleanup_wrapper, + tdp_actions); + (void) make_cleanup (free_actions_list_cleanup_wrapper, stepping_actions); + + tpaddr = loc->address; + sprintf_vma (tmp, (loc ? tpaddr : 0)); + sprintf (buf, "QTDP:%x:%s:%c:%lx:%x", t->number, + tmp, /* address */ + (t->enable_state == bp_enabled ? 'E' : 'D'), + t->step_count, t->pass_count); + /* Fast tracepoints are mostly handled by the target, but we can + tell the target how big of an instruction block should be moved + around. */ + if (t->type == bp_fast_tracepoint) + { + /* Only test for support at download time; we may not know + target capabilities at definition time. */ + if (remote_supports_fast_tracepoints ()) + { + int isize; + + if (gdbarch_fast_tracepoint_valid_at (target_gdbarch, + tpaddr, &isize, NULL)) + sprintf (buf + strlen (buf), ":F%x", isize); + else + /* If it passed validation at definition but fails now, + something is very wrong. */ + internal_error (__FILE__, __LINE__, + "Fast tracepoint not valid during download"); + } + else + /* Fast tracepoints are functionally identical to regular + tracepoints, so don't take lack of support as a reason to + give up on the trace run. */ + warning (_("Target does not support fast tracepoints, downloading %d as regular tracepoint"), t->number); + } + /* If the tracepoint has a conditional, make it into an agent + expression and append to the definition. */ + if (loc->cond) + { + /* Only test support at download time, we may not know target + 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); + sprintf (buf + 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, ignoring tp %d cond"), t->number); + } + + if (t->commands || *default_collect) + strcat (buf, "-"); + putpkt (buf); + remote_get_noisy_reply (&target_buf, &target_buf_size); + if (strcmp (target_buf, "OK")) + error (_("Target does not support tracepoints.")); + + if (!t->commands && !*default_collect) + continue; + + /* do_single_steps (t); */ + if (tdp_actions) + { + for (ndx = 0; tdp_actions[ndx]; ndx++) + { + QUIT; /* allow user to bail out with ^C */ + sprintf (buf, "QTDP:-%x:%s:%s%c", + t->number, tmp, /* address */ + tdp_actions[ndx], + ((tdp_actions[ndx + 1] || stepping_actions) + ? '-' : 0)); + putpkt (buf); + remote_get_noisy_reply (&target_buf, + &target_buf_size); + if (strcmp (target_buf, "OK")) + error (_("Error on target while setting tracepoints.")); + } + } + if (stepping_actions) + { + for (ndx = 0; stepping_actions[ndx]; ndx++) + { + QUIT; /* allow user to bail out with ^C */ + sprintf (buf, "QTDP:-%x:%s:%s%s%s", + t->number, tmp, /* address */ + ((ndx == 0) ? "S" : ""), + stepping_actions[ndx], + (stepping_actions[ndx + 1] ? "-" : "")); + putpkt (buf); + remote_get_noisy_reply (&target_buf, + &target_buf_size); + if (strcmp (target_buf, "OK")) + error (_("Error on target while setting tracepoints.")); + } + } + do_cleanups (old_chain); + } +} + +static void +remote_download_trace_state_variable (struct trace_state_variable *tsv) +{ + struct remote_state *rs = get_remote_state (); + char *p; + + sprintf (rs->buf, "QTDV:%x:%s:%x:", + tsv->number, phex ((ULONGEST) tsv->initial_value, 8), tsv->builtin); + p = rs->buf + strlen (rs->buf); + if ((p - rs->buf) + strlen (tsv->name) * 2 >= get_remote_packet_size ()) + error (_("Trace state variable name too long for tsv definition packet")); + p += 2 * bin2hex ((gdb_byte *) (tsv->name), p, 0); + *p++ = '\0'; + putpkt (rs->buf); + remote_get_noisy_reply (&target_buf, &target_buf_size); +} + +static void +remote_trace_set_readonly_regions () +{ + asection *s; + bfd_size_type size; + bfd_vma lma; + int anysecs = 0; + + if (!exec_bfd) + return; /* No information to give. */ + + strcpy (target_buf, "QTro"); + for (s = exec_bfd->sections; s; s = s->next) + { + char tmp1[40], tmp2[40]; + + if ((s->flags & SEC_LOAD) == 0 || + /* (s->flags & SEC_CODE) == 0 || */ + (s->flags & SEC_READONLY) == 0) + continue; + + anysecs = 1; + lma = s->lma; + size = bfd_get_section_size (s); + sprintf_vma (tmp1, lma); + sprintf_vma (tmp2, lma + size); + sprintf (target_buf + strlen (target_buf), + ":%s,%s", tmp1, tmp2); + } + if (anysecs) + { + putpkt (target_buf); + getpkt (&target_buf, &target_buf_size, 0); + } +} + +static void +remote_trace_start () +{ + putpkt ("QTStart"); + remote_get_noisy_reply (&target_buf, &target_buf_size); + if (strcmp (target_buf, "OK")) + error (_("Bogus reply from target: %s"), target_buf); +} + +static int +remote_get_trace_status (struct trace_status *ts) +{ + char *p, *p1, *p_temp; + ULONGEST val; + /* FIXME we need to get register block size some other way */ + extern int trace_regblock_size; + trace_regblock_size = get_remote_arch_state ()->sizeof_g_packet; + + putpkt ("qTStatus"); + getpkt (&target_buf, &target_buf_size, 0); + /* FIXME should handle more variety of replies */ + + p = target_buf; + + /* If the remote target doesn't do tracing, flag it. */ + if (*p == '\0') + return -1; + + /* We're working with a live target. */ + ts->from_file = 0; + + /* Set some defaults. */ + ts->running_known = 0; + ts->stop_reason = trace_stop_reason_unknown; + ts->traceframe_count = -1; + ts->buffer_free = 0; + + if (*p++ != 'T') + error (_("Bogus trace status reply from target: %s"), target_buf); + + parse_trace_status (p, ts); + + return ts->running; +} + +static void +remote_trace_stop () +{ + putpkt ("QTStop"); + remote_get_noisy_reply (&target_buf, &target_buf_size); + if (strcmp (target_buf, "OK")) + error (_("Bogus reply from target: %s"), target_buf); +} + +static int +remote_trace_find (enum trace_find_type type, int num, + ULONGEST addr1, ULONGEST addr2, + int *tpp) +{ + struct remote_state *rs = get_remote_state (); + char *p, *reply; + int target_frameno = -1, target_tracept = -1; + + p = rs->buf; + strcpy (p, "QTFrame:"); + p = strchr (p, '\0'); + switch (type) + { + case tfind_number: + sprintf (p, "%x", num); + break; + case tfind_pc: + sprintf (p, "pc:%s", phex_nz (addr1, 0)); + break; + case tfind_tp: + sprintf (p, "tdp:%x", num); + break; + case tfind_range: + sprintf (p, "range:%s:%s", phex_nz (addr1, 0), phex_nz (addr2, 0)); + break; + case tfind_outside: + sprintf (p, "outside:%s:%s", phex_nz (addr1, 0), phex_nz (addr2, 0)); + break; + default: + error ("Unknown trace find type %d", type); + } + + putpkt (rs->buf); + reply = remote_get_noisy_reply (&(rs->buf), &sizeof_pkt); + + while (reply && *reply) + switch (*reply) + { + case 'F': + p = ++reply; + target_frameno = (int) strtol (p, &reply, 16); + if (reply == p) + error (_("Unable to parse trace frame number")); + if (target_frameno == -1) + return -1; + break; + case 'T': + p = ++reply; + target_tracept = (int) strtol (p, &reply, 16); + if (reply == p) + error (_("Unable to parse tracepoint number")); + break; + case 'O': /* "OK"? */ + if (reply[1] == 'K' && reply[2] == '\0') + reply += 2; + else + error (_("Bogus reply from target: %s"), reply); + break; + default: + error (_("Bogus reply from target: %s"), reply); + } + if (tpp) + *tpp = target_tracept; + return target_frameno; +} + +static int +remote_get_trace_state_variable_value (int tsvnum, LONGEST *val) +{ + struct remote_state *rs = get_remote_state (); + char *reply; + ULONGEST uval; + + sprintf (rs->buf, "qTV:%x", tsvnum); + putpkt (rs->buf); + reply = remote_get_noisy_reply (&target_buf, &target_buf_size); + if (reply && *reply) + { + if (*reply == 'V') + { + unpack_varlen_hex (reply + 1, &uval); + *val = (LONGEST) uval; + return 1; + } + } + return 0; +} + +static int +remote_save_trace_data (const char *filename) +{ + struct remote_state *rs = get_remote_state (); + char *p, *reply; + + p = rs->buf; + strcpy (p, "QTSave:"); + p += strlen (p); + if ((p - rs->buf) + strlen (filename) * 2 >= get_remote_packet_size ()) + error (_("Remote file name too long for trace save packet")); + p += 2 * bin2hex ((gdb_byte *) filename, p, 0); + *p++ = '\0'; + putpkt (rs->buf); + remote_get_noisy_reply (&target_buf, &target_buf_size); + return 0; +} + +/* This is basically a memory transfer, but needs to be its own packet + because we don't know how the target actually organizes its trace + memory, plus we want to be able to ask for as much as possible, but + not be unhappy if we don't get as much as we ask for. */ + +static LONGEST +remote_get_raw_trace_data (gdb_byte *buf, ULONGEST offset, LONGEST len) +{ + struct remote_state *rs = get_remote_state (); + char *reply; + char *p; + int rslt; + + p = rs->buf; + strcpy (p, "qTBuffer:"); + p += strlen (p); + p += hexnumstr (p, offset); + *p++ = ','; + p += hexnumstr (p, len); + *p++ = '\0'; + + putpkt (rs->buf); + reply = remote_get_noisy_reply (&target_buf, &target_buf_size); + if (reply && *reply) + { + /* 'l' by itself means we're at the end of the buffer and + there is nothing more to get. */ + if (*reply == 'l') + return 0; + + /* Convert the reply into binary. Limit the number of bytes to + convert according to our passed-in buffer size, rather than + what was returned in the packet; if the target is + unexpectedly generous and gives us a bigger reply than we + asked for, we don't want to crash. */ + rslt = hex2bin (target_buf, buf, len); + return rslt; + } + + /* Something went wrong, flag as an error. */ + return -1; +} + +static void +remote_set_disconnected_tracing (int val) +{ + struct remote_state *rs = get_remote_state (); + + sprintf (rs->buf, "QTDisconnected:%x", val); + putpkt (rs->buf); + remote_get_noisy_reply (&target_buf, &target_buf_size); + if (strcmp (target_buf, "OK")) + error (_("Target does not support this command.")); +} + +static int +remote_core_of_thread (struct target_ops *ops, ptid_t ptid) +{ + struct thread_info *info = find_thread_ptid (ptid); + if (info && info->private) + return info->private->core; + return -1; +} + +static void +remote_set_circular_trace_buffer (int val) +{ + struct remote_state *rs = get_remote_state (); + + sprintf (rs->buf, "QTBuffer:circular:%x", val); + putpkt (rs->buf); + remote_get_noisy_reply (&target_buf, &target_buf_size); + if (strcmp (target_buf, "OK")) + error (_("Target does not support this command.")); +} + static void init_remote_ops (void) { @@ -8601,17 +9720,18 @@ Specify the serial device it is connected to\n\ remote_ops.to_find_new_threads = remote_threads_info; remote_ops.to_pid_to_str = remote_pid_to_str; remote_ops.to_extra_thread_info = remote_threads_extra_info; + remote_ops.to_get_ada_task_ptid = remote_get_ada_task_ptid; remote_ops.to_stop = remote_stop; remote_ops.to_xfer_partial = remote_xfer_partial; remote_ops.to_rcmd = remote_rcmd; remote_ops.to_log_command = serial_log_command; remote_ops.to_get_thread_local_address = remote_get_thread_local_address; remote_ops.to_stratum = process_stratum; - remote_ops.to_has_all_memory = 1; - remote_ops.to_has_memory = 1; - remote_ops.to_has_stack = 1; - remote_ops.to_has_registers = 1; - remote_ops.to_has_execution = 1; + remote_ops.to_has_all_memory = default_child_has_all_memory; + remote_ops.to_has_memory = default_child_has_memory; + remote_ops.to_has_stack = default_child_has_stack; + remote_ops.to_has_registers = default_child_has_registers; + remote_ops.to_has_execution = default_child_has_execution; remote_ops.to_has_thread_control = tc_schedlock; /* can lock scheduler */ remote_ops.to_can_execute_reverse = remote_can_execute_reverse; remote_ops.to_magic = OPS_MAGIC; @@ -8628,6 +9748,23 @@ Specify the serial device it is connected to\n\ remote_ops.to_terminal_ours = remote_terminal_ours; remote_ops.to_supports_non_stop = remote_supports_non_stop; remote_ops.to_supports_multi_process = remote_supports_multi_process; + remote_ops.to_trace_init = remote_trace_init; + remote_ops.to_download_tracepoint = remote_download_tracepoint; + remote_ops.to_download_trace_state_variable = remote_download_trace_state_variable; + remote_ops.to_trace_set_readonly_regions = remote_trace_set_readonly_regions; + remote_ops.to_trace_start = remote_trace_start; + remote_ops.to_get_trace_status = remote_get_trace_status; + remote_ops.to_trace_stop = remote_trace_stop; + remote_ops.to_trace_find = remote_trace_find; + remote_ops.to_get_trace_state_variable_value = remote_get_trace_state_variable_value; + remote_ops.to_save_trace_data = remote_save_trace_data; + remote_ops.to_upload_tracepoints = remote_upload_tracepoints; + remote_ops.to_upload_trace_state_variables = remote_upload_trace_state_variables; + remote_ops.to_get_raw_trace_data = remote_get_raw_trace_data; + remote_ops.to_set_disconnected_tracing = remote_set_disconnected_tracing; + remote_ops.to_set_circular_trace_buffer = remote_set_circular_trace_buffer; + remote_ops.to_core_of_thread = remote_core_of_thread; + remote_ops.to_verify_memory = remote_verify_memory; } /* Set up the extended remote vector by making a copy of the standard @@ -8778,10 +9915,59 @@ remote_new_objfile (struct objfile *objfile) remote_check_symbols (objfile); } +/* Pull all the tracepoints defined on the target and create local + data structures representing them. We don't want to create real + tracepoints yet, we don't want to mess up the user's existing + collection. */ + +static int +remote_upload_tracepoints (struct uploaded_tp **utpp) +{ + struct remote_state *rs = get_remote_state (); + char *p; + + /* Ask for a first packet of tracepoint definition. */ + putpkt ("qTfP"); + getpkt (&rs->buf, &rs->buf_size, 0); + p = rs->buf; + while (*p && *p != 'l') + { + parse_tracepoint_definition (p, utpp); + /* Ask for another packet of tracepoint definition. */ + putpkt ("qTsP"); + getpkt (&rs->buf, &rs->buf_size, 0); + p = rs->buf; + } + return 0; +} + +static int +remote_upload_trace_state_variables (struct uploaded_tsv **utsvp) +{ + struct remote_state *rs = get_remote_state (); + char *p; + + /* Ask for a first packet of variable definition. */ + putpkt ("qTfV"); + getpkt (&rs->buf, &rs->buf_size, 0); + p = rs->buf; + while (*p && *p != 'l') + { + parse_tsv_definition (p, utsvp); + /* Ask for another packet of variable definition. */ + putpkt ("qTsV"); + getpkt (&rs->buf, &rs->buf_size, 0); + p = rs->buf; + } + return 0; +} + void _initialize_remote (void) { struct remote_state *rs; + struct cmd_list_element *cmd; + char *cmd_name; /* architecture specific data */ remote_gdbarch_data_handle = @@ -8849,8 +10035,31 @@ terminating `#' character and checksum."), Set whether to send break if interrupted."), _("\ Show whether to send break if interrupted."), _("\ If set, a break, instead of a cntrl-c, is sent to the remote target."), - NULL, NULL, /* FIXME: i18n: Whether to send break if interrupted is %s. */ + set_remotebreak, show_remotebreak, &setlist, &showlist); + cmd_name = "remotebreak"; + cmd = lookup_cmd (&cmd_name, setlist, "", -1, 1); + deprecate_cmd (cmd, "set remote interrupt-sequence"); + cmd_name = "remotebreak"; /* needed because lookup_cmd updates the pointer */ + cmd = lookup_cmd (&cmd_name, showlist, "", -1, 1); + deprecate_cmd (cmd, "show remote interrupt-sequence"); + + add_setshow_enum_cmd ("interrupt-sequence", class_support, + interrupt_sequence_modes, &interrupt_sequence_mode, _("\ +Set interrupt sequence to remote target."), _("\ +Show interrupt sequence to remote target."), _("\ +Valid value is \"Ctrl-C\", \"BREAK\" or \"BREAK-g\". The default is \"Ctrl-C\"."), + NULL, show_interrupt_sequence, + &remote_set_cmdlist, + &remote_show_cmdlist); + + add_setshow_boolean_cmd ("interrupt-on-connect", class_support, + &interrupt_on_connect, _("\ +Set whether interrupt-sequence is sent to remote target when gdb connects to."), _(" \ +Show whether interrupt-sequence is sent to remote target when gdb connects to."), _(" \ +If set, interrupt sequence is sent to remote target."), + NULL, NULL, + &remote_set_cmdlist, &remote_show_cmdlist); /* Install commands for configuring memory read/write packets. */ @@ -8959,10 +10168,28 @@ Show the maximum size of the address (in bits) in a memory packet."), NULL, add_packet_config_cmd (&remote_protocol_packets[PACKET_qXfer_spu_write], "qXfer:spu:write", "write-spu-object", 0); + add_packet_config_cmd (&remote_protocol_packets[PACKET_qXfer_osdata], + "qXfer:osdata:read", "osdata", 0); + + add_packet_config_cmd (&remote_protocol_packets[PACKET_qXfer_threads], + "qXfer:threads:read", "threads", 0); + + add_packet_config_cmd (&remote_protocol_packets[PACKET_qXfer_siginfo_read], + "qXfer:siginfo:read", "read-siginfo-object", 0); + + add_packet_config_cmd (&remote_protocol_packets[PACKET_qXfer_siginfo_write], + "qXfer:siginfo:write", "write-siginfo-object", 0); + add_packet_config_cmd (&remote_protocol_packets[PACKET_qGetTLSAddr], "qGetTLSAddr", "get-thread-local-storage-address", 0); + add_packet_config_cmd (&remote_protocol_packets[PACKET_bc], + "bc", "reverse-continue", 0); + + add_packet_config_cmd (&remote_protocol_packets[PACKET_bs], + "bs", "reverse-step", 0); + add_packet_config_cmd (&remote_protocol_packets[PACKET_qSupported], "qSupported", "supported-packets", 0); @@ -8996,6 +10223,14 @@ Show the maximum size of the address (in bits) in a memory packet."), NULL, add_packet_config_cmd (&remote_protocol_packets[PACKET_vKill], "vKill", "kill", 0); + add_packet_config_cmd (&remote_protocol_packets[PACKET_qAttached], + "qAttached", "query-attached", 0); + + add_packet_config_cmd (&remote_protocol_packets[PACKET_ConditionalTracepoints], + "ConditionalTracepoints", "conditional-tracepoints", 0); + add_packet_config_cmd (&remote_protocol_packets[PACKET_FastTracepoints], + "FastTracepoints", "fast-tracepoints", 0); + /* Keep the old ``set remote Z-packet ...'' working. Each individual Z sub-packet has its own set and show commands, but users may have sets to this variable in their .gdbinit files (or in their @@ -9043,4 +10278,8 @@ Show the remote pathname for \"run\""), NULL, NULL, NULL, magic_null_ptid = ptid_build (42000, 1, -1); not_sent_ptid = ptid_build (42000, 1, -2); any_thread_ptid = ptid_build (42000, 1, 0); + + target_buf_size = 2048; + target_buf = xmalloc (target_buf_size); } +