aboutsummaryrefslogtreecommitdiff
path: root/gdb/gdbserver
diff options
context:
space:
mode:
authorDaniel Jacobowitz <drow@false.org>2006-11-16 15:08:25 +0000
committerDaniel Jacobowitz <drow@false.org>2006-11-16 15:08:25 +0000
commit89be2091496d2a3166460875fea2a2778686f8d3 (patch)
tree7a337983c051cc05869b6d120f0bc28d4bc3b2a1 /gdb/gdbserver
parent869ddf2a184e309b1deb9a8188dac514de6c4261 (diff)
downloadgdb-89be2091496d2a3166460875fea2a2778686f8d3.zip
gdb-89be2091496d2a3166460875fea2a2778686f8d3.tar.gz
gdb-89be2091496d2a3166460875fea2a2778686f8d3.tar.bz2
gdb/
* remote.c (PACKET_QPassSignals): New. (last_pass_packet, remote_pass_signals): New. (remote_protocol_features): Add QPassSignals. (remote_query_supported): Correct an infinite loop. (remote_open_1): Reset last_pass_packet. (remote_resume): Call remote_pass_signals. (_initialize_remote): Register "set remote pass-signals". gdb/doc/ * gdb.texinfo (Remote configuration): Mention "pass-signals-packet". (General Query Packets): Document QPassSignals. Fix a typo. gdb/gdbserver/ * linux-low.c (linux_wait_for_event): Reformat. Use the pass_signals array. * remote-utils.c (decode_address_to_semicolon): New. * server.c (pass_signals, handle_general_set): New. (handle_query): Mention QPassSignals for qSupported. (main): Call handle_general_set. * server.h (pass_signals, decode_address_to_semicolon): New.
Diffstat (limited to 'gdb/gdbserver')
-rw-r--r--gdb/gdbserver/ChangeLog10
-rw-r--r--gdb/gdbserver/linux-low.c113
-rw-r--r--gdb/gdbserver/remote-utils.c16
-rw-r--r--gdb/gdbserver/server.c41
-rw-r--r--gdb/gdbserver/server.h2
5 files changed, 128 insertions, 54 deletions
diff --git a/gdb/gdbserver/ChangeLog b/gdb/gdbserver/ChangeLog
index 3a53f86..fa7080f 100644
--- a/gdb/gdbserver/ChangeLog
+++ b/gdb/gdbserver/ChangeLog
@@ -1,3 +1,13 @@
+2006-11-16 Daniel Jacobowitz <dan@codesourcery.com>
+
+ * linux-low.c (linux_wait_for_event): Reformat. Use the
+ pass_signals array.
+ * remote-utils.c (decode_address_to_semicolon): New.
+ * server.c (pass_signals, handle_general_set): New.
+ (handle_query): Mention QPassSignals for qSupported.
+ (main): Call handle_general_set.
+ * server.h (pass_signals, decode_address_to_semicolon): New.
+
2006-11-06 Daniel Jacobowitz <dan@codesourcery.com>
* server.c (handle_query): Correct error handling for read_auxv.
diff --git a/gdb/gdbserver/linux-low.c b/gdb/gdbserver/linux-low.c
index 2a780ea..83a56aa 100644
--- a/gdb/gdbserver/linux-low.c
+++ b/gdb/gdbserver/linux-low.c
@@ -498,69 +498,76 @@ linux_wait_for_event (struct thread_info *child)
current_inferior = (struct thread_info *)
find_inferior_id (&all_threads, event_child->tid);
- if (using_threads)
+ /* Check for thread exit. */
+ if (using_threads && ! WIFSTOPPED (wstat))
{
- /* Check for thread exit. */
- if (! WIFSTOPPED (wstat))
- {
- if (debug_threads)
- fprintf (stderr, "Thread %ld (LWP %ld) exiting\n",
- event_child->tid, event_child->head.id);
+ if (debug_threads)
+ fprintf (stderr, "Thread %ld (LWP %ld) exiting\n",
+ event_child->tid, event_child->head.id);
- /* If the last thread is exiting, just return. */
- if (all_threads.head == all_threads.tail)
- return wstat;
+ /* If the last thread is exiting, just return. */
+ if (all_threads.head == all_threads.tail)
+ return wstat;
- dead_thread_notify (event_child->tid);
+ dead_thread_notify (event_child->tid);
- remove_inferior (&all_processes, &event_child->head);
- free (event_child);
- remove_thread (current_inferior);
- current_inferior = (struct thread_info *) all_threads.head;
+ remove_inferior (&all_processes, &event_child->head);
+ free (event_child);
+ remove_thread (current_inferior);
+ current_inferior = (struct thread_info *) all_threads.head;
- /* If we were waiting for this particular child to do something...
- well, it did something. */
- if (child != NULL)
- return wstat;
+ /* If we were waiting for this particular child to do something...
+ well, it did something. */
+ if (child != NULL)
+ return wstat;
- /* Wait for a more interesting event. */
- continue;
- }
+ /* Wait for a more interesting event. */
+ continue;
+ }
- if (WIFSTOPPED (wstat)
- && WSTOPSIG (wstat) == SIGSTOP
- && event_child->stop_expected)
- {
- if (debug_threads)
- fprintf (stderr, "Expected stop.\n");
- event_child->stop_expected = 0;
- linux_resume_one_process (&event_child->head,
- event_child->stepping, 0, NULL);
- continue;
- }
+ if (using_threads
+ && WIFSTOPPED (wstat)
+ && WSTOPSIG (wstat) == SIGSTOP
+ && event_child->stop_expected)
+ {
+ if (debug_threads)
+ fprintf (stderr, "Expected stop.\n");
+ event_child->stop_expected = 0;
+ linux_resume_one_process (&event_child->head,
+ event_child->stepping, 0, NULL);
+ continue;
+ }
- /* FIXME drow/2002-06-09: Get signal numbers from the inferior's
- thread library? */
- if (WIFSTOPPED (wstat)
- && (WSTOPSIG (wstat) == __SIGRTMIN
- || WSTOPSIG (wstat) == __SIGRTMIN + 1))
- {
- siginfo_t info, *info_p;
+ /* If GDB is not interested in this signal, don't stop other
+ threads, and don't report it to GDB. Just resume the
+ inferior right away. We do this for threading-related
+ signals as well as any that GDB specifically requested
+ we ignore. But never ignore SIGSTOP if we sent it
+ ourselves. */
+ /* FIXME drow/2002-06-09: Get signal numbers from the inferior's
+ thread library? */
+ if (WIFSTOPPED (wstat)
+ && ((using_threads && (WSTOPSIG (wstat) == __SIGRTMIN
+ || WSTOPSIG (wstat) == __SIGRTMIN + 1))
+ || (pass_signals[target_signal_from_host (WSTOPSIG (wstat))]
+ && (WSTOPSIG (wstat) != SIGSTOP
+ || !event_child->sigstop_sent))))
+ {
+ siginfo_t info, *info_p;
- if (debug_threads)
- fprintf (stderr, "Ignored signal %d for %ld (LWP %ld).\n",
- WSTOPSIG (wstat), event_child->tid,
- event_child->head.id);
+ if (debug_threads)
+ fprintf (stderr, "Ignored signal %d for %ld (LWP %ld).\n",
+ WSTOPSIG (wstat), event_child->tid,
+ event_child->head.id);
- if (ptrace (PTRACE_GETSIGINFO, event_child->lwpid, 0, &info) == 0)
- info_p = &info;
- else
- info_p = NULL;
- linux_resume_one_process (&event_child->head,
- event_child->stepping,
- WSTOPSIG (wstat), info_p);
- continue;
- }
+ if (ptrace (PTRACE_GETSIGINFO, event_child->lwpid, 0, &info) == 0)
+ info_p = &info;
+ else
+ info_p = NULL;
+ linux_resume_one_process (&event_child->head,
+ event_child->stepping,
+ WSTOPSIG (wstat), info_p);
+ continue;
}
/* If this event was not handled above, and is not a SIGTRAP, report
diff --git a/gdb/gdbserver/remote-utils.c b/gdb/gdbserver/remote-utils.c
index eb5d05d..fd5c844 100644
--- a/gdb/gdbserver/remote-utils.c
+++ b/gdb/gdbserver/remote-utils.c
@@ -296,6 +296,22 @@ decode_address (CORE_ADDR *addrp, const char *start, int len)
*addrp = addr;
}
+const char *
+decode_address_to_semicolon (CORE_ADDR *addrp, const char *start)
+{
+ const char *end;
+
+ end = start;
+ while (*end != '\0' && *end != ';')
+ end++;
+
+ decode_address (addrp, start, end - start);
+
+ if (*end == ';')
+ end++;
+ return end;
+}
+
/* Convert number NIB to a hex digit. */
static int
diff --git a/gdb/gdbserver/server.c b/gdb/gdbserver/server.c
index 5f78736..10a891e 100644
--- a/gdb/gdbserver/server.c
+++ b/gdb/gdbserver/server.c
@@ -36,6 +36,8 @@ unsigned long old_thread_from_wait;
int extended_protocol;
int server_waiting;
+int pass_signals[TARGET_SIGNAL_LAST];
+
jmp_buf toplevel;
/* The PID of the originally created or attached inferior. Used to
@@ -157,6 +159,40 @@ write_qxfer_response (char *buf, unsigned char *data, int len, int is_more)
PBUFSIZ - 2) + 1;
}
+/* Handle all of the extended 'Q' packets. */
+void
+handle_general_set (char *own_buf)
+{
+ if (strncmp ("QPassSignals:", own_buf, strlen ("QPassSignals:")) == 0)
+ {
+ int numsigs = (int) TARGET_SIGNAL_LAST, i;
+ const char *p = own_buf + strlen ("QPassSignals:");
+ CORE_ADDR cursig;
+
+ p = decode_address_to_semicolon (&cursig, p);
+ for (i = 0; i < numsigs; i++)
+ {
+ if (i == cursig)
+ {
+ pass_signals[i] = 1;
+ if (*p == '\0')
+ /* Keep looping, to clear the remaining signals. */
+ cursig = -1;
+ else
+ p = decode_address_to_semicolon (&cursig, p);
+ }
+ else
+ pass_signals[i] = 0;
+ }
+ strcpy (own_buf, "OK");
+ return;
+ }
+
+ /* Otherwise we didn't know what packet it was. Say we didn't
+ understand it. */
+ own_buf[0] = 0;
+}
+
/* Handle all of the extended 'q' packets. */
void
handle_query (char *own_buf, int *new_packet_len_p)
@@ -248,7 +284,7 @@ handle_query (char *own_buf, int *new_packet_len_p)
if (strncmp ("qSupported", own_buf, 10) == 0
&& (own_buf[10] == ':' || own_buf[10] == '\0'))
{
- sprintf (own_buf, "PacketSize=%x", PBUFSIZ - 1);
+ sprintf (own_buf, "PacketSize=%x;QPassSignals+", PBUFSIZ - 1);
if (the_target->read_auxv != NULL)
strcat (own_buf, ";qXfer:auxv:read+");
@@ -601,6 +637,9 @@ main (int argc, char *argv[])
case 'q':
handle_query (own_buf, &new_packet_len);
break;
+ case 'Q':
+ handle_general_set (own_buf);
+ break;
case 'd':
remote_debug = !remote_debug;
break;
diff --git a/gdb/gdbserver/server.h b/gdb/gdbserver/server.h
index 5e7d394..e1fad45 100644
--- a/gdb/gdbserver/server.h
+++ b/gdb/gdbserver/server.h
@@ -129,6 +129,7 @@ extern unsigned long step_thread;
extern unsigned long thread_from_wait;
extern unsigned long old_thread_from_wait;
extern int server_waiting;
+extern int pass_signals[];
extern jmp_buf toplevel;
@@ -153,6 +154,7 @@ void new_thread_notify (int id);
void dead_thread_notify (int id);
void prepare_resume_reply (char *buf, char status, unsigned char sig);
+const char *decode_address_to_semicolon (CORE_ADDR *addrp, const char *start);
void decode_address (CORE_ADDR *addrp, const char *start, int len);
void decode_m_packet (char *from, CORE_ADDR * mem_addr_ptr,
unsigned int *len_ptr);