diff options
author | Doug Evans <dje@google.com> | 2008-05-09 17:02:03 +0000 |
---|---|---|
committer | Doug Evans <dje@google.com> | 2008-05-09 17:02:03 +0000 |
commit | 08388c79d5a8553465b2de881bed15766837735c (patch) | |
tree | 1c0af907d5caa5836541d62803dd1775c683913c /gdb/gdbserver | |
parent | 7010a0c9019a68999ca6e43b4eec8b28d0907cbc (diff) | |
download | gdb-08388c79d5a8553465b2de881bed15766837735c.zip gdb-08388c79d5a8553465b2de881bed15766837735c.tar.gz gdb-08388c79d5a8553465b2de881bed15766837735c.tar.bz2 |
New "find" command.
* NEWS: Document find command and qSearch:memory packet.
* Makefile.in (SFILES): Add findcmd.c.
(COMMON_OBJS): Add findcmd.o.
(findcmd.o): New rule.
* findcmd.c: New file.
* target.h (target_ops): New member to_search_memory.
(simple_search_memory): Declare.
(target_search_memory): Declare.
* target.c (simple_search_memory): New fn.
(target_search_memory): New fn.
* remote.c (PACKET_qSearch_memory): New packet kind.
(remote_search_memory): New fn.
(init_remote_ops): Init to_search_memory.
(init_extended_remote_ops): Ditto.
(_initialize_remote): Add qSearch:memory packet config command.
* gdbserver/server.h (decode_search_memory_packet): Declare.
* gdbserver/remote-utils.c (decode_search_memory_packet): New fn.
* gdbserver/server.c (handle_search_memory_1): New fn.
(handle_search_memory): New fn.
(handle_query): Process qSearch:memory packets.
* doc/gdb.texinfo: Document "find" command, qSearch:memory packet.
* testsuite/gdb.base/find.exp: New file.
* testsuite/gdb.base/find.c: New file.
Diffstat (limited to 'gdb/gdbserver')
-rw-r--r-- | gdb/gdbserver/ChangeLog | 8 | ||||
-rw-r--r-- | gdb/gdbserver/remote-utils.c | 18 | ||||
-rw-r--r-- | gdb/gdbserver/server.c | 154 | ||||
-rw-r--r-- | gdb/gdbserver/server.h | 4 |
4 files changed, 184 insertions, 0 deletions
diff --git a/gdb/gdbserver/ChangeLog b/gdb/gdbserver/ChangeLog index ab53964..d8e4037 100644 --- a/gdb/gdbserver/ChangeLog +++ b/gdb/gdbserver/ChangeLog @@ -1,3 +1,11 @@ +2008-05-09 Doug Evans <dje@google.com> + + * gdbserver/server.h (decode_search_memory_packet): Declare. + * gdbserver/remote-utils.c (decode_search_memory_packet): New fn. + * gdbserver/server.c (handle_search_memory_1): New fn. + (handle_search_memory): New fn. + (handle_query): Process qSearch:memory packets. + 2008-05-08 Ulrich Weigand <uweigand@de.ibm.com> * regcache.c (registers_length): Remove. diff --git a/gdb/gdbserver/remote-utils.c b/gdb/gdbserver/remote-utils.c index 2e049ee..16d5442 100644 --- a/gdb/gdbserver/remote-utils.c +++ b/gdb/gdbserver/remote-utils.c @@ -1080,6 +1080,24 @@ decode_xfer_write (char *buf, int packet_len, char **annex, CORE_ADDR *offset, return 0; } +/* Decode the parameters of a qSearch:memory packet. */ + +int +decode_search_memory_packet (const char *buf, int packet_len, + CORE_ADDR *start_addrp, + CORE_ADDR *search_space_lenp, + gdb_byte *pattern, unsigned int *pattern_lenp) +{ + const char *p = buf; + + p = decode_address_to_semicolon (start_addrp, p); + p = decode_address_to_semicolon (search_space_lenp, p); + packet_len -= p - buf; + *pattern_lenp = remote_unescape_input ((const gdb_byte *) p, packet_len, + pattern, packet_len); + return 0; +} + /* Ask GDB for the address of NAME, and return it in ADDRP if found. Returns 1 if the symbol is found, 0 if it is not, -1 on error. */ diff --git a/gdb/gdbserver/server.c b/gdb/gdbserver/server.c index 852a0bd..6993ae3 100644 --- a/gdb/gdbserver/server.c +++ b/gdb/gdbserver/server.c @@ -314,6 +314,153 @@ monitor_show_help (void) monitor_output (" Quit GDBserver\n"); } +/* Subroutine of handle_search_memory to simplify it. */ + +static int +handle_search_memory_1 (CORE_ADDR start_addr, CORE_ADDR search_space_len, + gdb_byte *pattern, unsigned pattern_len, + gdb_byte *search_buf, + unsigned chunk_size, unsigned search_buf_size, + CORE_ADDR *found_addrp) +{ + /* Prime the search buffer. */ + + if (read_inferior_memory (start_addr, search_buf, search_buf_size) != 0) + { + warning ("unable to access target memory at 0x%lx, halting search", + (long) start_addr); + return -1; + } + + /* Perform the search. + + The loop is kept simple by allocating [N + pattern-length - 1] bytes. + When we've scanned N bytes we copy the trailing bytes to the start and + read in another N bytes. */ + + while (search_space_len >= pattern_len) + { + gdb_byte *found_ptr; + unsigned nr_search_bytes = (search_space_len < search_buf_size + ? search_space_len + : search_buf_size); + + found_ptr = memmem (search_buf, nr_search_bytes, pattern, pattern_len); + + if (found_ptr != NULL) + { + CORE_ADDR found_addr = start_addr + (found_ptr - search_buf); + *found_addrp = found_addr; + return 1; + } + + /* Not found in this chunk, skip to next chunk. */ + + /* Don't let search_space_len wrap here, it's unsigned. */ + if (search_space_len >= chunk_size) + search_space_len -= chunk_size; + else + search_space_len = 0; + + if (search_space_len >= pattern_len) + { + unsigned keep_len = search_buf_size - chunk_size; + CORE_ADDR read_addr = start_addr + keep_len; + int nr_to_read; + + /* Copy the trailing part of the previous iteration to the front + of the buffer for the next iteration. */ + memcpy (search_buf, search_buf + chunk_size, keep_len); + + nr_to_read = (search_space_len - keep_len < chunk_size + ? search_space_len - keep_len + : chunk_size); + + if (read_inferior_memory (read_addr, search_buf + keep_len, + nr_to_read) != 0) + { + warning ("unable to access target memory at 0x%lx, halting search", + (long) read_addr); + return -1; + } + + start_addr += chunk_size; + } + } + + /* Not found. */ + + return 0; +} + +/* Handle qSearch:memory packets. */ + +static void +handle_search_memory (char *own_buf, int packet_len) +{ + CORE_ADDR start_addr; + CORE_ADDR search_space_len; + gdb_byte *pattern; + unsigned int pattern_len; + /* NOTE: also defined in find.c testcase. */ +#define SEARCH_CHUNK_SIZE 16000 + const unsigned chunk_size = SEARCH_CHUNK_SIZE; + /* Buffer to hold memory contents for searching. */ + gdb_byte *search_buf; + unsigned search_buf_size; + int found; + CORE_ADDR found_addr; + int cmd_name_len = sizeof ("qSearch:memory:") - 1; + + pattern = malloc (packet_len); + if (pattern == NULL) + { + error ("unable to allocate memory to perform the search"); + strcpy (own_buf, "E00"); + return; + } + if (decode_search_memory_packet (own_buf + cmd_name_len, + packet_len - cmd_name_len, + &start_addr, &search_space_len, + pattern, &pattern_len) < 0) + { + free (pattern); + error ("error in parsing qSearch:memory packet"); + strcpy (own_buf, "E00"); + return; + } + + search_buf_size = chunk_size + pattern_len - 1; + + /* No point in trying to allocate a buffer larger than the search space. */ + if (search_space_len < search_buf_size) + search_buf_size = search_space_len; + + search_buf = malloc (search_buf_size); + if (search_buf == NULL) + { + free (pattern); + error ("unable to allocate memory to perform the search"); + strcpy (own_buf, "E00"); + return; + } + + found = handle_search_memory_1 (start_addr, search_space_len, + pattern, pattern_len, + search_buf, chunk_size, search_buf_size, + &found_addr); + + if (found > 0) + sprintf (own_buf, "1,%lx", (long) found_addr); + else if (found == 0) + strcpy (own_buf, "0"); + else + strcpy (own_buf, "E00"); + + free (search_buf); + free (pattern); +} + #define require_running(BUF) \ if (!target_running ()) \ { \ @@ -731,6 +878,13 @@ 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) + { + require_running (own_buf); + handle_search_memory (own_buf, packet_len); + return; + } + /* Otherwise we didn't know what packet it was. Say we didn't understand it. */ own_buf[0] = 0; diff --git a/gdb/gdbserver/server.h b/gdb/gdbserver/server.h index 9d6c751..d0520d2 100644 --- a/gdb/gdbserver/server.h +++ b/gdb/gdbserver/server.h @@ -195,6 +195,10 @@ int decode_X_packet (char *from, int packet_len, CORE_ADDR * mem_addr_ptr, int decode_xfer_write (char *buf, int packet_len, char **annex, CORE_ADDR *offset, unsigned int *len, unsigned char *data); +int decode_search_memory_packet (const char *buf, int packet_len, + CORE_ADDR *start_addrp, + CORE_ADDR *search_space_lenp, + gdb_byte *pattern, unsigned int *pattern_lenp); int unhexify (char *bin, const char *hex, int count); int hexify (char *hex, const char *bin, int count); |