diff options
author | Daniel Jacobowitz <drow@false.org> | 2006-11-28 22:14:31 +0000 |
---|---|---|
committer | Daniel Jacobowitz <drow@false.org> | 2006-11-28 22:14:31 +0000 |
commit | 29709017e835906e3e95bc230d393331636234e1 (patch) | |
tree | 0c60f098cfaeadad329383e1447ee9fbf2e1c375 /gdb/remote.c | |
parent | 424163ea1524c5823612a24284cb900cd70e2e2b (diff) | |
download | gdb-29709017e835906e3e95bc230d393331636234e1.zip gdb-29709017e835906e3e95bc230d393331636234e1.tar.gz gdb-29709017e835906e3e95bc230d393331636234e1.tar.bz2 |
* Makefile.in (mips-tdep.o, target-descriptions.o): Update.
* target-descriptions.c (struct property): New.
(struct target_desc): Add properties member.
(tdesc_property, set_tdesc_property): New.
* target-descriptions.h (tdesc_property, set_tdesc_property):
Declare.
* mips-tdep.c (PROPERTY_GP32, PROPERTY_GP64): New constants.
(struct gdbarch_tdep): Add register_size_valid_p and register_size.
(mips_isa_regsize): Use them.
(mips_register_g_packet_guesses): New.
(mips_gdbarch_init): Call it. If a target description is supplied,
check for internal properties. Check for register size mismatches.
* remote.c (send_g_packet, process_g_packet): New functions, split
out from fetch_registers_using_g.
(fetch_registers_using_g): Use them.
(struct remote_g_packet_guess, remote_g_packet_guess_s)
(struct remote_g_packet_data, remote_g_packet_data_handle)
(remote_g_packet_data_init, register_remote_g_packet_guess)
(remote_read_description): New.
(init_remote_ops, init_remote_async_ops): Set to_read_description.
(_initialize_remote): Register remote_g_packet_data_handle.
* remote.h (register_remote_g_packet_guess): Declare.
Diffstat (limited to 'gdb/remote.c')
-rw-r--r-- | gdb/remote.c | 137 |
1 files changed, 120 insertions, 17 deletions
diff --git a/gdb/remote.c b/gdb/remote.c index e758412..69bc65b 100644 --- a/gdb/remote.c +++ b/gdb/remote.c @@ -3535,11 +3535,10 @@ fetch_register_using_p (struct packet_reg *reg) /* Fetch the registers included in the target's 'g' packet. */ -static void -fetch_registers_using_g (void) +static int +send_g_packet (void) { struct remote_state *rs = get_remote_state (); - struct remote_arch_state *rsa = get_remote_arch_state (); int i, buf_len; char *p; char *regs; @@ -3547,11 +3546,41 @@ fetch_registers_using_g (void) sprintf (rs->buf, "g"); remote_send (&rs->buf, &rs->buf_size); + /* We can get out of synch in various cases. If the first character + in the buffer is not a hex character, assume that has happened + and try to fetch another packet to read. */ + while ((rs->buf[0] < '0' || rs->buf[0] > '9') + && (rs->buf[0] < 'A' || rs->buf[0] > 'F') + && (rs->buf[0] < 'a' || rs->buf[0] > 'f') + && rs->buf[0] != 'x') /* New: unavailable register value. */ + { + if (remote_debug) + fprintf_unfiltered (gdb_stdlog, + "Bad register packet; fetching a new packet\n"); + getpkt (&rs->buf, &rs->buf_size, 0); + } + buf_len = strlen (rs->buf); /* Sanity check the received packet. */ if (buf_len % 2 != 0) error (_("Remote 'g' packet reply is of odd length: %s"), rs->buf); + + return buf_len / 2; +} + +static void +process_g_packet (void) +{ + struct remote_state *rs = get_remote_state (); + struct remote_arch_state *rsa = get_remote_arch_state (); + int i, buf_len; + char *p; + char *regs; + + buf_len = strlen (rs->buf); + + /* Further sanity checks, with knowledge of the architecture. */ if (REGISTER_BYTES_OK_P () && !REGISTER_BYTES_OK (buf_len / 2)) error (_("Remote 'g' packet reply is wrong length: %s"), rs->buf); if (buf_len > 2 * rsa->sizeof_g_packet) @@ -3588,20 +3617,6 @@ fetch_registers_using_g (void) /* Unimplemented registers read as all bits zero. */ memset (regs, 0, rsa->sizeof_g_packet); - /* We can get out of synch in various cases. If the first character - in the buffer is not a hex character, assume that has happened - and try to fetch another packet to read. */ - while ((rs->buf[0] < '0' || rs->buf[0] > '9') - && (rs->buf[0] < 'A' || rs->buf[0] > 'F') - && (rs->buf[0] < 'a' || rs->buf[0] > 'f') - && rs->buf[0] != 'x') /* New: unavailable register value. */ - { - if (remote_debug) - fprintf_unfiltered (gdb_stdlog, - "Bad register packet; fetching a new packet\n"); - getpkt (&rs->buf, &rs->buf_size, 0); - } - /* Reply describes registers byte by byte, each byte encoded as two hex characters. Suck them all up, then supply them to the register cacheing/storage mechanism. */ @@ -3649,6 +3664,13 @@ fetch_registers_using_g (void) } static void +fetch_registers_using_g (void) +{ + send_g_packet (); + process_g_packet (); +} + +static void remote_fetch_registers (int regnum) { struct remote_state *rs = get_remote_state (); @@ -6052,6 +6074,83 @@ remote_get_thread_local_address (ptid_t ptid, CORE_ADDR lm, CORE_ADDR offset) return 0; } +/* Support for inferring a target description based on the current + architecture and the size of a 'g' packet. While the 'g' packet + can have any size (since optional registers can be left off the + end), some sizes are easily recognizable given knowledge of the + approximate architecture. */ + +struct remote_g_packet_guess +{ + int bytes; + const struct target_desc *tdesc; +}; +typedef struct remote_g_packet_guess remote_g_packet_guess_s; +DEF_VEC_O(remote_g_packet_guess_s); + +struct remote_g_packet_data +{ + VEC(remote_g_packet_guess_s) *guesses; +}; + +static struct gdbarch_data *remote_g_packet_data_handle; + +static void * +remote_g_packet_data_init (struct obstack *obstack) +{ + return OBSTACK_ZALLOC (obstack, struct remote_g_packet_data); +} + +void +register_remote_g_packet_guess (struct gdbarch *gdbarch, int bytes, + const struct target_desc *tdesc) +{ + struct remote_g_packet_data *data + = gdbarch_data (gdbarch, remote_g_packet_data_handle); + struct remote_g_packet_guess new_guess, *guess; + int ix; + + gdb_assert (tdesc != NULL); + + for (ix = 0; + VEC_iterate (remote_g_packet_guess_s, data->guesses, ix, guess); + ix++) + if (guess->bytes == bytes) + internal_error (__FILE__, __LINE__, + "Duplicate g packet description added for size %d", + bytes); + + new_guess.bytes = bytes; + new_guess.tdesc = tdesc; + VEC_safe_push (remote_g_packet_guess_s, data->guesses, &new_guess); +} + +static const struct target_desc * +remote_read_description (struct target_ops *target) +{ + struct remote_g_packet_data *data + = gdbarch_data (current_gdbarch, remote_g_packet_data_handle); + + if (!VEC_empty (remote_g_packet_guess_s, data->guesses)) + { + struct remote_g_packet_guess *guess; + int ix; + int bytes = send_g_packet (); + + for (ix = 0; + VEC_iterate (remote_g_packet_guess_s, data->guesses, ix, guess); + ix++) + if (guess->bytes == bytes) + return guess->tdesc; + + /* We discard the g packet. A minor optimization would be to + hold on to it, and fill the register cache once we have selected + an architecture, but it's too tricky to do safely. */ + } + + return NULL; +} + static void init_remote_ops (void) { @@ -6103,6 +6202,7 @@ Specify the serial device it is connected to\n\ remote_ops.to_memory_map = remote_memory_map; remote_ops.to_flash_erase = remote_flash_erase; remote_ops.to_flash_done = remote_flash_done; + remote_ops.to_read_description = remote_read_description; } /* Set up the extended remote vector by making a copy of the standard @@ -6235,6 +6335,7 @@ Specify the serial device it is connected to (e.g. /dev/ttya)."; remote_async_ops.to_memory_map = remote_memory_map; remote_async_ops.to_flash_erase = remote_flash_erase; remote_async_ops.to_flash_done = remote_flash_done; + remote_ops.to_read_description = remote_read_description; } /* Set up the async extended remote vector by making a copy of the standard @@ -6326,6 +6427,8 @@ _initialize_remote (void) /* architecture specific data */ remote_gdbarch_data_handle = gdbarch_data_register_post_init (init_remote_state); + remote_g_packet_data_handle = + gdbarch_data_register_pre_init (remote_g_packet_data_init); /* Old tacky stuff. NOTE: This comes after the remote protocol so that the remote protocol has been initialized. */ |