X-Git-Url: http://drtracing.org/?a=blobdiff_plain;f=gdb%2Fgdbserver%2Fserver.c;h=a170d85283e0632d6b15d703b4f86044cfefa1a0;hb=1c79eb8a7d7126b5fcb734fb374be42a717d4373;hp=226d123e56eb3572a5da5644a99f07f7521de249;hpb=1fd7cdc24b4a6f0c0fdd4771a88fcd1daae23231;p=deliverable%2Fbinutils-gdb.git diff --git a/gdb/gdbserver/server.c b/gdb/gdbserver/server.c index 226d123e56..a170d85283 100644 --- a/gdb/gdbserver/server.c +++ b/gdb/gdbserver/server.c @@ -1,6 +1,7 @@ /* Main code for remote server for GDB. Copyright (C) 1989, 1993, 1994, 1995, 1997, 1998, 1999, 2000, 2002, 2003, - 2004, 2005, 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc. + 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 + Free Software Foundation, Inc. This file is part of GDB. @@ -28,9 +29,6 @@ #if HAVE_SYS_WAIT_H #include #endif -#if HAVE_MALLOC_H -#include -#endif ptid_t cont_thread; ptid_t general_thread; @@ -158,6 +156,8 @@ queue_stop_reply (ptid_t ptid, struct target_waitstatus *status) void push_event (ptid_t ptid, struct target_waitstatus *status) { + gdb_assert (status->kind != TARGET_WAITKIND_IGNORE); + queue_stop_reply (ptid, status); /* If this is the first stop reply in the queue, then inform GDB @@ -274,13 +274,12 @@ start_inferior (char **argv) if (wrapper_argv != NULL) { struct thread_resume resume_info; - ptid_t ptid; resume_info.thread = pid_to_ptid (signal_pid); resume_info.kind = resume_continue; resume_info.sig = 0; - ptid = mywait (pid_to_ptid (signal_pid), &last_status, 0, 0); + mywait (pid_to_ptid (signal_pid), &last_status, 0, 0); if (last_status.kind != TARGET_WAITKIND_STOPPED) return signal_pid; @@ -292,9 +291,14 @@ start_inferior (char **argv) mywait (pid_to_ptid (signal_pid), &last_status, 0, 0); if (last_status.kind != TARGET_WAITKIND_STOPPED) return signal_pid; + + current_inferior->last_resume_kind = resume_stop; + current_inferior->last_status = last_status; } while (last_status.value.sig != TARGET_SIGNAL_TRAP); + current_inferior->last_resume_kind = resume_stop; + current_inferior->last_status = last_status; return signal_pid; } @@ -302,6 +306,13 @@ start_inferior (char **argv) (assuming success). */ last_ptid = mywait (pid_to_ptid (signal_pid), &last_status, 0, 0); + if (last_status.kind != TARGET_WAITKIND_EXITED + && last_status.kind != TARGET_WAITKIND_SIGNALLED) + { + current_inferior->last_resume_kind = resume_stop; + current_inferior->last_status = last_status; + } + return signal_pid; } @@ -332,6 +343,9 @@ attach_inferior (int pid) if (last_status.kind == TARGET_WAITKIND_STOPPED && last_status.value.sig == TARGET_SIGNAL_STOP) last_status.value.sig = TARGET_SIGNAL_TRAP; + + current_inferior->last_resume_kind = resume_stop; + current_inferior->last_status = last_status; } return 0; @@ -343,8 +357,34 @@ extern int remote_debug; or -1 otherwise. */ static int -decode_xfer_read (char *buf, char **annex, CORE_ADDR *ofs, unsigned int *len) +decode_xfer_read (char *buf, CORE_ADDR *ofs, unsigned int *len) +{ + /* After the read marker and annex, qXfer looks like a + traditional 'm' packet. */ + decode_m_packet (buf, ofs, len); + + return 0; +} + +static int +decode_xfer (char *buf, char **object, char **rw, char **annex, char **offset) { + /* Extract and NUL-terminate the object. */ + *object = buf; + while (*buf && *buf != ':') + buf++; + if (*buf == '\0') + return -1; + *buf++ = 0; + + /* Extract and NUL-terminate the read/write action. */ + *rw = buf; + while (*buf && *buf != ':') + buf++; + if (*buf == '\0') + return -1; + *buf++ = 0; + /* Extract and NUL-terminate the annex. */ *annex = buf; while (*buf && *buf != ':') @@ -353,10 +393,7 @@ decode_xfer_read (char *buf, char **annex, CORE_ADDR *ofs, unsigned int *len) return -1; *buf++ = 0; - /* After the read marker and annex, qXfer looks like a - traditional 'm' packet. */ - decode_m_packet (buf, ofs, len); - + *offset = buf; return 0; } @@ -522,8 +559,10 @@ monitor_show_help (void) /* Read trace frame or inferior memory. */ static int -read_memory (CORE_ADDR memaddr, unsigned char *myaddr, int len) +gdb_read_memory (CORE_ADDR memaddr, unsigned char *myaddr, int len) { + int ret; + if (current_traceframe >= 0) { ULONGEST nbytes; @@ -541,19 +580,36 @@ read_memory (CORE_ADDR memaddr, unsigned char *myaddr, int len) /* (assume no half-trace half-real blocks for now) */ } - return read_inferior_memory (memaddr, myaddr, len); + ret = prepare_to_access_memory (); + if (ret == 0) + { + ret = read_inferior_memory (memaddr, myaddr, len); + done_accessing_memory (); + } + + return ret; } /* Write trace frame or inferior memory. Actually, writing to trace frames is forbidden. */ static int -write_memory (CORE_ADDR memaddr, const unsigned char *myaddr, int len) +gdb_write_memory (CORE_ADDR memaddr, const unsigned char *myaddr, int len) { if (current_traceframe >= 0) return EIO; else - return write_inferior_memory (memaddr, myaddr, len); + { + int ret; + + ret = prepare_to_access_memory (); + if (ret == 0) + { + ret = write_inferior_memory (memaddr, myaddr, len); + done_accessing_memory (); + } + return ret; + } } /* Subroutine of handle_search_memory to simplify it. */ @@ -567,7 +623,7 @@ handle_search_memory_1 (CORE_ADDR start_addr, CORE_ADDR search_space_len, { /* Prime the search buffer. */ - if (read_memory (start_addr, search_buf, search_buf_size) != 0) + if (gdb_read_memory (start_addr, search_buf, search_buf_size) != 0) { warning ("Unable to access target memory at 0x%lx, halting search.", (long) start_addr); @@ -618,10 +674,11 @@ handle_search_memory_1 (CORE_ADDR start_addr, CORE_ADDR search_space_len, ? search_space_len - keep_len : chunk_size); - if (read_memory (read_addr, search_buf + keep_len, - nr_to_read) != 0) + if (gdb_read_memory (read_addr, search_buf + keep_len, + nr_to_read) != 0) { - warning ("Unable to access target memory at 0x%lx, halting search.", + warning ("Unable to access target memory " + "at 0x%lx, halting search.", (long) read_addr); return -1; } @@ -757,8 +814,216 @@ handle_monitor_command (char *mon) } } +/* Associates a callback with each supported qXfer'able object. */ + +struct qxfer +{ + /* The object this handler handles. */ + const char *object; + + /* Request that the target transfer up to LEN 8-bit bytes of the + target's OBJECT. The OFFSET, for a seekable object, specifies + the starting point. The ANNEX can be used to provide additional + data-specific information to the target. + + Return the number of bytes actually transfered, zero when no + further transfer is possible, -1 on error, and -2 when the + transfer is not supported. Return of a positive value smaller + than LEN does not indicate the end of the object, only the end of + the transfer. + + One, and only one, of readbuf or writebuf must be non-NULL. */ + int (*xfer) (const char *annex, + gdb_byte *readbuf, const gdb_byte *writebuf, + ULONGEST offset, LONGEST len); +}; + +/* Handle qXfer:auxv:read. */ + +static int +handle_qxfer_auxv (const char *annex, + gdb_byte *readbuf, const gdb_byte *writebuf, + ULONGEST offset, LONGEST len) +{ + if (the_target->read_auxv == NULL || writebuf != NULL) + return -2; + + if (annex[0] != '\0' || !target_running ()) + return -1; + + return (*the_target->read_auxv) (offset, readbuf, len); +} + +/* Handle qXfer:features:read. */ + +static int +handle_qxfer_features (const char *annex, + gdb_byte *readbuf, const gdb_byte *writebuf, + ULONGEST offset, LONGEST len) +{ + const char *document; + size_t total_len; + + if (writebuf != NULL) + return -2; + + if (!target_running ()) + return -1; + + /* Grab the correct annex. */ + document = get_features_xml (annex); + if (document == NULL) + return -1; + + total_len = strlen (document); + + if (offset > total_len) + return -1; + + if (offset + len > total_len) + len = total_len - offset; + + memcpy (readbuf, document + offset, len); + return len; +} + +/* Handle qXfer:libraries:read. */ + +static int +handle_qxfer_libraries (const char *annex, + gdb_byte *readbuf, const gdb_byte *writebuf, + ULONGEST offset, LONGEST len) +{ + unsigned int total_len; + char *document, *p; + struct inferior_list_entry *dll_ptr; + + if (writebuf != NULL) + return -2; + + if (annex[0] != '\0' || !target_running ()) + return -1; + + /* Over-estimate the necessary memory. Assume that every character + in the library name must be escaped. */ + total_len = 64; + for (dll_ptr = all_dlls.head; dll_ptr != NULL; dll_ptr = dll_ptr->next) + total_len += 128 + 6 * strlen (((struct dll_info *) dll_ptr)->name); + + document = malloc (total_len); + if (document == NULL) + return -1; + + strcpy (document, "\n"); + p = document + strlen (document); + + for (dll_ptr = all_dlls.head; dll_ptr != NULL; dll_ptr = dll_ptr->next) + { + struct dll_info *dll = (struct dll_info *) dll_ptr; + char *name; + + strcpy (p, " name); + strcpy (p, name); + free (name); + p = p + strlen (p); + strcpy (p, "\">base_addr); + p = p + strlen (p); + strcpy (p, "\"/>\n"); + p = p + strlen (p); + } + + strcpy (p, "\n"); + + total_len = strlen (document); + + if (offset > total_len) + { + free (document); + return -1; + } + + if (offset + len > total_len) + len = total_len - offset; + + memcpy (readbuf, document + offset, len); + free (document); + return len; +} + +/* Handle qXfer:osadata:read. */ + +static int +handle_qxfer_osdata (const char *annex, + gdb_byte *readbuf, const gdb_byte *writebuf, + ULONGEST offset, LONGEST len) +{ + if (the_target->qxfer_osdata == NULL || writebuf != NULL) + return -2; + + return (*the_target->qxfer_osdata) (annex, readbuf, NULL, offset, len); +} + +/* Handle qXfer:siginfo:read and qXfer:siginfo:write. */ + +static int +handle_qxfer_siginfo (const char *annex, + gdb_byte *readbuf, const gdb_byte *writebuf, + ULONGEST offset, LONGEST len) +{ + if (the_target->qxfer_siginfo == NULL) + return -2; + + if (annex[0] != '\0' || !target_running ()) + return -1; + + return (*the_target->qxfer_siginfo) (annex, readbuf, writebuf, offset, len); +} + +/* Handle qXfer:spu:read and qXfer:spu:write. */ + +static int +handle_qxfer_spu (const char *annex, + gdb_byte *readbuf, const gdb_byte *writebuf, + ULONGEST offset, LONGEST len) +{ + if (the_target->qxfer_spu == NULL) + return -2; + + if (!target_running ()) + return -1; + + return (*the_target->qxfer_spu) (annex, readbuf, writebuf, offset, len); +} + +/* Handle qXfer:statictrace:read. */ + +static int +handle_qxfer_statictrace (const char *annex, + gdb_byte *readbuf, const gdb_byte *writebuf, + ULONGEST offset, LONGEST len) +{ + ULONGEST nbytes; + + if (writebuf != NULL) + return -2; + + if (annex[0] != '\0' || !target_running () || current_traceframe == -1) + return -1; + + if (traceframe_read_sdata (current_traceframe, offset, + readbuf, len, &nbytes)) + return -1; + return nbytes; +} + +/* Helper for handle_qxfer_threads. */ + static void -handle_threads_qxfer_proper (struct buffer *buffer) +handle_qxfer_threads_proper (struct buffer *buffer) { struct inferior_list_entry *thread; @@ -792,16 +1057,21 @@ handle_threads_qxfer_proper (struct buffer *buffer) buffer_grow_str0 (buffer, "\n"); } +/* Handle qXfer:threads:read. */ + static int -handle_threads_qxfer (const char *annex, - unsigned char *readbuf, - CORE_ADDR offset, int length) +handle_qxfer_threads (const char *annex, + gdb_byte *readbuf, const gdb_byte *writebuf, + ULONGEST offset, LONGEST len) { static char *result = 0; static unsigned int result_length = 0; - if (annex && strcmp (annex, "") != 0) - return 0; + if (writebuf != NULL) + return -2; + + if (!target_running () || annex[0] != '\0') + return -1; if (offset == 0) { @@ -813,7 +1083,7 @@ handle_threads_qxfer (const char *annex, buffer_init (&buffer); - handle_threads_qxfer_proper (&buffer); + handle_qxfer_threads_proper (&buffer); result = buffer_finish (&buffer); result_length = strlen (result); @@ -829,13 +1099,135 @@ handle_threads_qxfer (const char *annex, return 0; } - if (length > result_length - offset) - length = result_length - offset; + if (len > result_length - offset) + len = result_length - offset; + + memcpy (readbuf, result + offset, len); - memcpy (readbuf, result + offset, length); + return len; +} + +static const struct qxfer qxfer_packets[] = + { + { "auxv", handle_qxfer_auxv }, + { "features", handle_qxfer_features }, + { "libraries", handle_qxfer_libraries }, + { "osdata", handle_qxfer_osdata }, + { "siginfo", handle_qxfer_siginfo }, + { "spu", handle_qxfer_spu }, + { "statictrace", handle_qxfer_statictrace }, + { "threads", handle_qxfer_threads }, + }; + +static int +handle_qxfer (char *own_buf, int packet_len, int *new_packet_len_p) +{ + int i; + char *object; + char *rw; + char *annex; + char *offset; - return length; + if (strncmp (own_buf, "qXfer:", 6) != 0) + return 0; + + /* Grab the object, r/w and annex. */ + if (decode_xfer (own_buf + 6, &object, &rw, &annex, &offset) < 0) + { + write_enn (own_buf); + return 1; + } + for (i = 0; + i < sizeof (qxfer_packets) / sizeof (qxfer_packets[0]); + i++) + { + const struct qxfer *q = &qxfer_packets[i]; + + if (strcmp (object, q->object) == 0) + { + if (strcmp (rw, "read") == 0) + { + unsigned char *data; + int n; + CORE_ADDR ofs; + unsigned int len; + + /* Grab the offset and length. */ + if (decode_xfer_read (offset, &ofs, &len) < 0) + { + write_enn (own_buf); + return 1; + } + + /* Read one extra byte, as an indicator of whether there is + more. */ + if (len > PBUFSIZ - 2) + len = PBUFSIZ - 2; + data = malloc (len + 1); + if (data == NULL) + { + write_enn (own_buf); + return 1; + } + n = (*q->xfer) (annex, data, NULL, ofs, len + 1); + if (n == -2) + { + free (data); + return 0; + } + else if (n < 0) + write_enn (own_buf); + else if (n > len) + *new_packet_len_p = write_qxfer_response (own_buf, data, len, 1); + else + *new_packet_len_p = write_qxfer_response (own_buf, data, n, 0); + + free (data); + return 1; + } + else if (strcmp (rw, "write") == 0) + { + int n; + unsigned int len; + CORE_ADDR ofs; + unsigned char *data; + + strcpy (own_buf, "E00"); + data = malloc (packet_len - (offset - own_buf)); + if (data == NULL) + { + write_enn (own_buf); + return 1; + } + if (decode_xfer_write (offset, packet_len - (offset - own_buf), + &ofs, &len, data) < 0) + { + free (data); + write_enn (own_buf); + return 1; + } + + n = (*q->xfer) (annex, NULL, data, ofs, len); + if (n == -2) + { + free (data); + return 0; + } + else if (n < 0) + write_enn (own_buf); + else + sprintf (own_buf, "%x", n); + + free (data); + return 1; + } + + return 0; + } + } + + return 0; } /* Table used by the crc32 function to calcuate the checksum. */ @@ -880,6 +1272,7 @@ crc32 (CORE_ADDR base, int len, unsigned int crc) } /* Handle all of the extended 'q' packets. */ + void handle_query (char *own_buf, int packet_len, int *new_packet_len_p) { @@ -982,406 +1375,6 @@ handle_query (char *own_buf, int packet_len, int *new_packet_len_p) return; } - if (the_target->qxfer_spu != NULL - && strncmp ("qXfer:spu:read:", own_buf, 15) == 0) - { - char *annex; - int n; - unsigned int len; - CORE_ADDR ofs; - unsigned char *spu_buf; - - require_running (own_buf); - strcpy (own_buf, "E00"); - if (decode_xfer_read (own_buf + 15, &annex, &ofs, &len) < 0) - return; - if (len > PBUFSIZ - 2) - len = PBUFSIZ - 2; - spu_buf = malloc (len + 1); - if (!spu_buf) - return; - - n = (*the_target->qxfer_spu) (annex, spu_buf, NULL, ofs, len + 1); - if (n < 0) - write_enn (own_buf); - else if (n > len) - *new_packet_len_p = write_qxfer_response (own_buf, spu_buf, len, 1); - else - *new_packet_len_p = write_qxfer_response (own_buf, spu_buf, n, 0); - - free (spu_buf); - return; - } - - if (the_target->qxfer_spu != NULL - && strncmp ("qXfer:spu:write:", own_buf, 16) == 0) - { - char *annex; - int n; - unsigned int len; - CORE_ADDR ofs; - unsigned char *spu_buf; - - require_running (own_buf); - strcpy (own_buf, "E00"); - spu_buf = malloc (packet_len - 15); - if (!spu_buf) - return; - if (decode_xfer_write (own_buf + 16, packet_len - 16, &annex, - &ofs, &len, spu_buf) < 0) - { - free (spu_buf); - return; - } - - n = (*the_target->qxfer_spu) - (annex, NULL, (unsigned const char *)spu_buf, ofs, len); - if (n < 0) - write_enn (own_buf); - else - sprintf (own_buf, "%x", n); - - free (spu_buf); - return; - } - - if (the_target->read_auxv != NULL - && strncmp ("qXfer:auxv:read:", own_buf, 16) == 0) - { - unsigned char *data; - int n; - CORE_ADDR ofs; - unsigned int len; - char *annex; - - require_running (own_buf); - - /* Reject any annex; grab the offset and length. */ - if (decode_xfer_read (own_buf + 16, &annex, &ofs, &len) < 0 - || annex[0] != '\0') - { - strcpy (own_buf, "E00"); - return; - } - - /* Read one extra byte, as an indicator of whether there is - more. */ - if (len > PBUFSIZ - 2) - len = PBUFSIZ - 2; - data = malloc (len + 1); - if (data == NULL) - { - write_enn (own_buf); - return; - } - n = (*the_target->read_auxv) (ofs, data, len + 1); - if (n < 0) - write_enn (own_buf); - else if (n > len) - *new_packet_len_p = write_qxfer_response (own_buf, data, len, 1); - else - *new_packet_len_p = write_qxfer_response (own_buf, data, n, 0); - - free (data); - - return; - } - - if (strncmp ("qXfer:features:read:", own_buf, 20) == 0) - { - CORE_ADDR ofs; - unsigned int len, total_len; - const char *document; - char *annex; - - require_running (own_buf); - - /* Grab the annex, offset, and length. */ - if (decode_xfer_read (own_buf + 20, &annex, &ofs, &len) < 0) - { - strcpy (own_buf, "E00"); - return; - } - - /* Now grab the correct annex. */ - document = get_features_xml (annex); - if (document == NULL) - { - strcpy (own_buf, "E00"); - return; - } - - total_len = strlen (document); - if (len > PBUFSIZ - 2) - len = PBUFSIZ - 2; - - if (ofs > total_len) - write_enn (own_buf); - else if (len < total_len - ofs) - *new_packet_len_p = write_qxfer_response (own_buf, document + ofs, - len, 1); - else - *new_packet_len_p = write_qxfer_response (own_buf, document + ofs, - total_len - ofs, 0); - - return; - } - - if (strncmp ("qXfer:libraries:read:", own_buf, 21) == 0) - { - CORE_ADDR ofs; - unsigned int len, total_len; - char *document, *p; - struct inferior_list_entry *dll_ptr; - char *annex; - - require_running (own_buf); - - /* Reject any annex; grab the offset and length. */ - if (decode_xfer_read (own_buf + 21, &annex, &ofs, &len) < 0 - || annex[0] != '\0') - { - strcpy (own_buf, "E00"); - return; - } - - /* Over-estimate the necessary memory. Assume that every character - in the library name must be escaped. */ - total_len = 64; - for (dll_ptr = all_dlls.head; dll_ptr != NULL; dll_ptr = dll_ptr->next) - total_len += 128 + 6 * strlen (((struct dll_info *) dll_ptr)->name); - - document = malloc (total_len); - if (document == NULL) - { - write_enn (own_buf); - return; - } - strcpy (document, "\n"); - p = document + strlen (document); - - for (dll_ptr = all_dlls.head; dll_ptr != NULL; dll_ptr = dll_ptr->next) - { - struct dll_info *dll = (struct dll_info *) dll_ptr; - char *name; - - strcpy (p, " name); - strcpy (p, name); - free (name); - p = p + strlen (p); - strcpy (p, "\">base_addr); - p = p + strlen (p); - strcpy (p, "\"/>\n"); - p = p + strlen (p); - } - - strcpy (p, "\n"); - - total_len = strlen (document); - if (len > PBUFSIZ - 2) - len = PBUFSIZ - 2; - - if (ofs > total_len) - write_enn (own_buf); - else if (len < total_len - ofs) - *new_packet_len_p = write_qxfer_response (own_buf, document + ofs, - len, 1); - else - *new_packet_len_p = write_qxfer_response (own_buf, document + ofs, - total_len - ofs, 0); - - free (document); - return; - } - - if (the_target->qxfer_osdata != NULL - && strncmp ("qXfer:osdata:read:", own_buf, 18) == 0) - { - char *annex; - int n; - unsigned int len; - CORE_ADDR ofs; - unsigned char *workbuf; - - strcpy (own_buf, "E00"); - if (decode_xfer_read (own_buf + 18, &annex, &ofs, &len) < 0) - return; - if (len > PBUFSIZ - 2) - len = PBUFSIZ - 2; - workbuf = malloc (len + 1); - if (!workbuf) - return; - - n = (*the_target->qxfer_osdata) (annex, workbuf, NULL, ofs, len + 1); - if (n < 0) - write_enn (own_buf); - else if (n > len) - *new_packet_len_p = write_qxfer_response (own_buf, workbuf, len, 1); - else - *new_packet_len_p = write_qxfer_response (own_buf, workbuf, n, 0); - - free (workbuf); - return; - } - - if (the_target->qxfer_siginfo != NULL - && strncmp ("qXfer:siginfo:read:", own_buf, 19) == 0) - { - unsigned char *data; - int n; - CORE_ADDR ofs; - unsigned int len; - char *annex; - - require_running (own_buf); - - /* Reject any annex; grab the offset and length. */ - if (decode_xfer_read (own_buf + 19, &annex, &ofs, &len) < 0 - || annex[0] != '\0') - { - strcpy (own_buf, "E00"); - return; - } - - /* Read one extra byte, as an indicator of whether there is - more. */ - if (len > PBUFSIZ - 2) - len = PBUFSIZ - 2; - data = malloc (len + 1); - if (!data) - return; - n = (*the_target->qxfer_siginfo) (annex, data, NULL, ofs, len + 1); - if (n < 0) - write_enn (own_buf); - else if (n > len) - *new_packet_len_p = write_qxfer_response (own_buf, data, len, 1); - else - *new_packet_len_p = write_qxfer_response (own_buf, data, n, 0); - - free (data); - return; - } - - if (the_target->qxfer_siginfo != NULL - && strncmp ("qXfer:siginfo:write:", own_buf, 20) == 0) - { - char *annex; - int n; - unsigned int len; - CORE_ADDR ofs; - unsigned char *data; - - require_running (own_buf); - - strcpy (own_buf, "E00"); - data = malloc (packet_len - 19); - if (!data) - return; - if (decode_xfer_write (own_buf + 20, packet_len - 20, &annex, - &ofs, &len, data) < 0) - { - free (data); - return; - } - - n = (*the_target->qxfer_siginfo) - (annex, NULL, (unsigned const char *)data, ofs, len); - if (n < 0) - write_enn (own_buf); - else - sprintf (own_buf, "%x", n); - - free (data); - return; - } - - if (strncmp ("qXfer:threads:read:", own_buf, 19) == 0) - { - unsigned char *data; - int n; - CORE_ADDR ofs; - unsigned int len; - char *annex; - - require_running (own_buf); - - /* Reject any annex; grab the offset and length. */ - if (decode_xfer_read (own_buf + 19, &annex, &ofs, &len) < 0 - || annex[0] != '\0') - { - strcpy (own_buf, "E00"); - return; - } - - /* Read one extra byte, as an indicator of whether there is - more. */ - if (len > PBUFSIZ - 2) - len = PBUFSIZ - 2; - data = malloc (len + 1); - if (!data) - return; - n = handle_threads_qxfer (annex, data, ofs, len + 1); - if (n < 0) - write_enn (own_buf); - else if (n > len) - *new_packet_len_p = write_qxfer_response (own_buf, data, len, 1); - else - *new_packet_len_p = write_qxfer_response (own_buf, data, n, 0); - - free (data); - return; - } - - if (strncmp ("qXfer:statictrace:read:", own_buf, - sizeof ("qXfer:statictrace:read:") -1) == 0) - { - unsigned char *data; - CORE_ADDR ofs; - unsigned int len; - char *annex; - ULONGEST nbytes; - - require_running (own_buf); - - if (current_traceframe == -1) - { - write_enn (own_buf); - return; - } - - /* Reject any annex; grab the offset and length. */ - if (decode_xfer_read (own_buf + sizeof ("qXfer:statictrace:read:") -1, - &annex, &ofs, &len) < 0 - || annex[0] != '\0') - { - strcpy (own_buf, "E00"); - return; - } - - /* Read one extra byte, as an indicator of whether there is - more. */ - if (len > PBUFSIZ - 2) - len = PBUFSIZ - 2; - data = malloc (len + 1); - if (!data) - return; - - if (traceframe_read_sdata (current_traceframe, ofs, - data, len + 1, &nbytes)) - write_enn (own_buf); - else if (nbytes > len) - *new_packet_len_p = write_qxfer_response (own_buf, data, len, 1); - else - *new_packet_len_p = write_qxfer_response (own_buf, data, nbytes, 0); - - free (data); - return; - } - /* Protocol features query. */ if (strncmp ("qSupported", own_buf, 10) == 0 && (own_buf[10] == ':' || own_buf[10] == '\0')) @@ -1539,7 +1532,7 @@ handle_query (char *own_buf, int packet_len, int *new_packet_len_p) if (err == 0) { - sprintf (own_buf, "%llx", address); + strcpy (own_buf, paddress(address)); return; } else if (err > 0) @@ -1563,7 +1556,7 @@ handle_query (char *own_buf, int packet_len, int *new_packet_len_p) n = (*the_target->get_tib_address) (ptid, &tlb); if (n == 1) { - sprintf (own_buf, "%llx", tlb); + strcpy (own_buf, paddress(tlb)); return; } else if (n == 0) @@ -1605,7 +1598,8 @@ handle_query (char *own_buf, int packet_len, int *new_packet_len_p) return; } - if (strncmp ("qSearch:memory:", own_buf, sizeof ("qSearch:memory:") - 1) == 0) + if (strncmp ("qSearch:memory:", own_buf, + sizeof ("qSearch:memory:") - 1) == 0) { require_running (own_buf); handle_search_memory (own_buf, packet_len); @@ -1666,6 +1660,9 @@ handle_query (char *own_buf, int packet_len, int *new_packet_len_p) return; } + if (handle_qxfer (own_buf, packet_len, new_packet_len_p)) + return; + if (target_supports_tracepoints () && handle_tracepoint_query (own_buf)) return; @@ -1674,6 +1671,8 @@ handle_query (char *own_buf, int packet_len, int *new_packet_len_p) own_buf[0] = 0; } +static void gdb_wants_all_threads_stopped (void); + /* Parse vCont packets. */ void handle_v_cont (char *own_buf) @@ -1777,8 +1776,22 @@ handle_v_cont (char *own_buf) else { last_ptid = mywait (minus_one_ptid, &last_status, 0, 1); + + if (last_status.kind != TARGET_WAITKIND_EXITED + && last_status.kind != TARGET_WAITKIND_SIGNALLED) + current_inferior->last_status = last_status; + + /* From the client's perspective, all-stop mode always stops all + threads implicitly (and the target backend has already done + so by now). Tag all threads as "want-stopped", so we don't + resume them implicitly without the client telling us to. */ + gdb_wants_all_threads_stopped (); prepare_resume_reply (own_buf, last_ptid, &last_status); disable_async_io (); + + if (last_status.kind == TARGET_WAITKIND_EXITED + || last_status.kind == TARGET_WAITKIND_SIGNALLED) + mourn_inferior (find_process_pid (ptid_get_pid (last_ptid))); } return; @@ -2077,8 +2090,20 @@ myresume (char *own_buf, int step, int sig) else { last_ptid = mywait (minus_one_ptid, &last_status, 0, 1); + + if (last_status.kind != TARGET_WAITKIND_EXITED + && last_status.kind != TARGET_WAITKIND_SIGNALLED) + { + current_inferior->last_resume_kind = resume_stop; + current_inferior->last_status = last_status; + } + prepare_resume_reply (own_buf, last_ptid, &last_status); disable_async_io (); + + if (last_status.kind == TARGET_WAITKIND_EXITED + || last_status.kind == TARGET_WAITKIND_SIGNALLED) + mourn_inferior (find_process_pid (ptid_get_pid (last_ptid))); } } @@ -2094,11 +2119,6 @@ queue_stop_reply_callback (struct inferior_list_entry *entry, void *arg) manage the thread's last_status field. */ if (the_target->thread_stopped == NULL) { - struct target_waitstatus status; - - status.kind = TARGET_WAITKIND_STOPPED; - status.value.sig = TARGET_SIGNAL_TRAP; - /* Pass the last stop reply back to GDB, but don't notify yet. */ queue_stop_reply (entry->id, &thread->last_status); @@ -2108,10 +2128,13 @@ queue_stop_reply_callback (struct inferior_list_entry *entry, void *arg) if (thread_stopped (thread)) { if (debug_threads) - fprintf (stderr, "Reporting thread %s as already stopped with %s\n", + fprintf (stderr, + "Reporting thread %s as already stopped with %s\n", target_pid_to_str (entry->id), target_waitstatus_to_string (&thread->last_status)); + gdb_assert (thread->last_status.kind != TARGET_WAITKIND_IGNORE); + /* Pass the last stop reply back to GDB, but don't notify yet. */ queue_stop_reply (entry->id, &thread->last_status); @@ -2121,8 +2144,9 @@ queue_stop_reply_callback (struct inferior_list_entry *entry, void *arg) return 0; } -/* Set this inferior LWP's state as "want-stopped". We won't resume - this LWP until the client gives us another action for it. */ +/* Set this inferior threads's state as "want-stopped". We won't + resume this thread until the client gives us another action for + it. */ static void gdb_wants_thread_stopped (struct inferior_list_entry *entry) @@ -2133,6 +2157,8 @@ gdb_wants_thread_stopped (struct inferior_list_entry *entry) if (thread->last_status.kind == TARGET_WAITKIND_IGNORE) { + /* Most threads are stopped implicitly (all-stop); tag that with + signal 0. */ thread->last_status.kind = TARGET_WAITKIND_STOPPED; thread->last_status.value.sig = TARGET_SIGNAL_0; } @@ -2202,8 +2228,9 @@ static void gdbserver_version (void) { printf ("GNU gdbserver %s%s\n" - "Copyright (C) 2010 Free Software Foundation, Inc.\n" - "gdbserver is free software, covered by the GNU General Public License.\n" + "Copyright (C) 2011 Free Software Foundation, Inc.\n" + "gdbserver is free software, covered by the " + "GNU General Public License.\n" "This gdbserver was configured as \"%s\"\n", PKGVERSION, version, host_name); } @@ -2234,7 +2261,8 @@ gdbserver_show_disableable (FILE *stream) " vCont \tAll vCont packets\n" " qC \tQuerying the current thread\n" " qfThreadInfo\tThread listing\n" - " Tthread \tPassing the thread specifier in the T stop reply packet\n" + " Tthread \tPassing the thread specifier in the " + "T stop reply packet\n" " threads \tAll of the above\n"); } @@ -2874,7 +2902,7 @@ process_serial_event (void) case 'm': require_running (own_buf); decode_m_packet (&own_buf[1], &mem_addr, &len); - if (read_memory (mem_addr, mem_buf, len) == 0) + if (gdb_read_memory (mem_addr, mem_buf, len) == 0) convert_int_to_ascii (mem_buf, own_buf, len); else write_enn (own_buf); @@ -2882,7 +2910,7 @@ process_serial_event (void) case 'M': require_running (own_buf); decode_M_packet (&own_buf[1], &mem_addr, &len, &mem_buf); - if (write_memory (mem_addr, mem_buf, len) == 0) + if (gdb_write_memory (mem_addr, mem_buf, len) == 0) write_ok (own_buf); else write_enn (own_buf); @@ -2891,7 +2919,7 @@ process_serial_event (void) require_running (own_buf); if (decode_X_packet (&own_buf[1], packet_len - 1, &mem_addr, &len, &mem_buf) < 0 - || write_memory (mem_addr, mem_buf, len) != 0) + || gdb_write_memory (mem_addr, mem_buf, len) != 0) write_enn (own_buf); else write_ok (own_buf); @@ -3115,6 +3143,14 @@ handle_target_event (int err, gdb_client_data client_data) mark_breakpoints_out (process); mourn_inferior (process); } + else + { + /* We're reporting this thread as stopped. Update its + "want-stopped" state to what the client wants, until it + gets a new resume action. */ + current_inferior->last_resume_kind = resume_stop; + current_inferior->last_status = last_status; + } if (forward_event) { @@ -3139,7 +3175,7 @@ handle_target_event (int err, gdb_client_data client_data) resume_info.thread = last_ptid; resume_info.kind = resume_continue; - resume_info.sig = last_status.value.sig; + resume_info.sig = target_signal_to_host (last_status.value.sig); (*the_target->resume) (&resume_info, 1); } else if (debug_threads)