diff options
author | Daniel Jacobowitz <drow@false.org> | 2006-11-16 15:08:25 +0000 |
---|---|---|
committer | Daniel Jacobowitz <drow@false.org> | 2006-11-16 15:08:25 +0000 |
commit | 89be2091496d2a3166460875fea2a2778686f8d3 (patch) | |
tree | 7a337983c051cc05869b6d120f0bc28d4bc3b2a1 /gdb/gdbserver | |
parent | 869ddf2a184e309b1deb9a8188dac514de6c4261 (diff) | |
download | gdb-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/ChangeLog | 10 | ||||
-rw-r--r-- | gdb/gdbserver/linux-low.c | 113 | ||||
-rw-r--r-- | gdb/gdbserver/remote-utils.c | 16 | ||||
-rw-r--r-- | gdb/gdbserver/server.c | 41 | ||||
-rw-r--r-- | gdb/gdbserver/server.h | 2 |
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); |