From 4a5e7a5b0ae022b3cd116e64a45d84f8ad51bc0d Mon Sep 17 00:00:00 2001 From: Pedro Alves Date: Wed, 24 Mar 2010 01:12:13 +0000 Subject: [PATCH] gdb/ * remote.c (crc32): Constify `buf' parameter. (remote_verify_memory): New, abstracted out from... (compare_sections_command): ... this. Remove hardcoded target checks. (init_remote_ops): Install remote_verify_memory. * target.c (target_verify_memory): New. * target.h (struct target_ops) : New field. (target_verify_memory): Declare. --- gdb/ChangeLog | 11 ++++++++ gdb/remote.c | 71 +++++++++++++++++++++++++++++---------------------- gdb/target.c | 22 ++++++++++++++++ gdb/target.h | 15 +++++++++++ 4 files changed, 88 insertions(+), 31 deletions(-) diff --git a/gdb/ChangeLog b/gdb/ChangeLog index 21a1c382042..fdd2b2c3d4e 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,14 @@ +2010-03-24 Pedro Alves + + * remote.c (crc32): Constify `buf' parameter. + (remote_verify_memory): New, abstracted out from... + (compare_sections_command): ... this. Remove hardcoded target + checks. + (init_remote_ops): Install remote_verify_memory. + * target.c (target_verify_memory): New. + * target.h (struct target_ops) : New field. + (target_verify_memory): Declare. + 2010-03-24 Vladimir Prus Implement -trace-save. diff --git a/gdb/remote.c b/gdb/remote.c index bb19b723c61..0c791aa220f 100644 --- a/gdb/remote.c +++ b/gdb/remote.c @@ -173,8 +173,6 @@ static CORE_ADDR remote_address_masked (CORE_ADDR); static void print_packet (char *); -static unsigned long crc32 (unsigned char *, int, unsigned int); - static void compare_sections_command (char *, int); static void packet_command (char *, int); @@ -7542,7 +7540,7 @@ static unsigned long crc32_table[256] = {0, 0}; static unsigned long -crc32 (unsigned char *buf, int len, unsigned int crc) +crc32 (const unsigned char *buf, int len, unsigned int crc) { if (!crc32_table[1]) { @@ -7566,38 +7564,59 @@ crc32 (unsigned char *buf, int len, unsigned int crc) return crc; } +/* Verify memory using the "qCRC:" request. */ + +static int +remote_verify_memory (struct target_ops *ops, + const gdb_byte *data, CORE_ADDR lma, ULONGEST size) +{ + struct remote_state *rs = get_remote_state (); + unsigned long host_crc, target_crc; + char *tmp; + + /* FIXME: assumes lma can fit into long. */ + xsnprintf (rs->buf, get_remote_packet_size (), "qCRC:%lx,%lx", + (long) lma, (long) size); + putpkt (rs->buf); + + /* Be clever; compute the host_crc before waiting for target + reply. */ + host_crc = crc32 (data, size, 0xffffffff); + + getpkt (&rs->buf, &rs->buf_size, 0); + if (rs->buf[0] == 'E') + return -1; + + if (rs->buf[0] != 'C') + error (_("remote target does not support this operation")); + + for (target_crc = 0, tmp = &rs->buf[1]; *tmp; tmp++) + target_crc = target_crc * 16 + fromhex (*tmp); + + return (host_crc == target_crc); +} + /* compare-sections command With no arguments, compares each loadable section in the exec bfd with the same memory range on the target, and reports mismatches. - Useful for verifying the image on the target against the exec file. - Depends on the target understanding the new "qCRC:" request. */ - -/* FIXME: cagney/1999-10-26: This command should be broken down into a - target method (target verify memory) and generic version of the - actual command. This will allow other high-level code (especially - generic_load()) to make use of this target functionality. */ + Useful for verifying the image on the target against the exec file. */ static void compare_sections_command (char *args, int from_tty) { - struct remote_state *rs = get_remote_state (); asection *s; - unsigned long host_crc, target_crc; struct cleanup *old_chain; - char *tmp; char *sectdata; const char *sectname; bfd_size_type size; bfd_vma lma; int matched = 0; int mismatched = 0; + int res; if (!exec_bfd) error (_("command cannot be used without an exec file")); - if (!current_target.to_shortname || - strcmp (current_target.to_shortname, "remote") != 0) - error (_("command can only be used with remote target")); for (s = exec_bfd->sections; s; s = s->next) { @@ -7614,33 +7633,22 @@ compare_sections_command (char *args, int from_tty) matched = 1; /* do this section */ lma = s->lma; - /* FIXME: assumes lma can fit into long. */ - xsnprintf (rs->buf, get_remote_packet_size (), "qCRC:%lx,%lx", - (long) lma, (long) size); - putpkt (rs->buf); - /* Be clever; compute the host_crc before waiting for target - reply. */ sectdata = xmalloc (size); old_chain = make_cleanup (xfree, sectdata); bfd_get_section_contents (exec_bfd, s, sectdata, 0, size); - host_crc = crc32 ((unsigned char *) sectdata, size, 0xffffffff); - getpkt (&rs->buf, &rs->buf_size, 0); - if (rs->buf[0] == 'E') + res = target_verify_memory (sectdata, lma, size); + + if (res == -1) error (_("target memory fault, section %s, range %s -- %s"), sectname, paddress (target_gdbarch, lma), paddress (target_gdbarch, lma + size)); - if (rs->buf[0] != 'C') - error (_("remote target does not support this operation")); - - for (target_crc = 0, tmp = &rs->buf[1]; *tmp; tmp++) - target_crc = target_crc * 16 + fromhex (*tmp); printf_filtered ("Section %s, range %s -- %s: ", sectname, paddress (target_gdbarch, lma), paddress (target_gdbarch, lma + size)); - if (host_crc == target_crc) + if (res) printf_filtered ("matched.\n"); else { @@ -9756,6 +9764,7 @@ Specify the serial device it is connected to\n\ remote_ops.to_set_disconnected_tracing = remote_set_disconnected_tracing; remote_ops.to_set_circular_trace_buffer = remote_set_circular_trace_buffer; remote_ops.to_core_of_thread = remote_core_of_thread; + remote_ops.to_verify_memory = remote_verify_memory; } /* Set up the extended remote vector by making a copy of the standard diff --git a/gdb/target.c b/gdb/target.c index 24d29850348..5657f89b945 100644 --- a/gdb/target.c +++ b/gdb/target.c @@ -3073,6 +3073,28 @@ target_core_of_thread (ptid_t ptid) return -1; } +int +target_verify_memory (const gdb_byte *data, CORE_ADDR memaddr, ULONGEST size) +{ + struct target_ops *t; + + for (t = current_target.beneath; t != NULL; t = t->beneath) + { + if (t->to_verify_memory != NULL) + { + int retval = t->to_verify_memory (t, data, memaddr, size); + if (targetdebug) + fprintf_unfiltered (gdb_stdlog, "target_verify_memory (%s, %s) = %d\n", + paddress (target_gdbarch, memaddr), + pulongest (size), + retval); + return retval; + } + } + + tcomplain (); +} + static void debug_to_prepare_to_store (struct regcache *regcache) { diff --git a/gdb/target.h b/gdb/target.h index 9e87440ae3e..0d16139f45c 100644 --- a/gdb/target.h +++ b/gdb/target.h @@ -675,6 +675,13 @@ struct target_ops right now, or in this debug session, or for this target -- return -1. */ int (*to_core_of_thread) (struct target_ops *, ptid_t ptid); + /* Verify that the memory in the [MEMADDR, MEMADDR+SIZE) range + matches the contents of [DATA,DATA+SIZE). Returns 1 if there's + a match, 0 if there's a mismatch, and -1 if an error is + encountered while reading memory. */ + int (*to_verify_memory) (struct target_ops *, const gdb_byte *data, + CORE_ADDR memaddr, ULONGEST size); + int to_magic; /* Need sub-structure for target machine related rather than comm related? */ @@ -1375,6 +1382,14 @@ extern int target_search_memory (CORE_ADDR start_addr, extern int target_core_of_thread (ptid_t ptid); +/* Verify that the memory in the [MEMADDR, MEMADDR+SIZE) range matches + the contents of [DATA,DATA+SIZE). Returns 1 if there's a match, 0 + if there's a mismatch, and -1 if an error is encountered while + reading memory. Throws an error if the functionality is found not + to be supported by the current target. */ +int target_verify_memory (const gdb_byte *data, + CORE_ADDR memaddr, ULONGEST size); + /* Routines for maintenance of the target structures... add_target: Add a target to the list of all possible targets. -- 2.30.2