From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 22573 invoked by alias); 24 Mar 2010 01:15:10 -0000 Received: (qmail 22476 invoked by uid 22791); 24 Mar 2010 01:15:07 -0000 X-SWARE-Spam-Status: No, hits=-2.5 required=5.0 tests=AWL,BAYES_00 X-Spam-Check-By: sourceware.org Received: from mail.codesourcery.com (HELO mail.codesourcery.com) (38.113.113.100) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Wed, 24 Mar 2010 01:15:02 +0000 Received: (qmail 27608 invoked from network); 24 Mar 2010 01:15:00 -0000 Received: from unknown (HELO orlando.localnet) (pedro@127.0.0.2) by mail.codesourcery.com with ESMTPA; 24 Mar 2010 01:15:00 -0000 From: Pedro Alves To: gdb-patches@sourceware.org Subject: Re: [RFA] gdbserver support for qCRC: (compare-sections) Date: Wed, 24 Mar 2010 01:15:00 -0000 User-Agent: KMail/1.12.2 (Linux/2.6.31-20-generic; KDE/4.3.2; x86_64; ; ) References: <4BA40867.4090703@vmware.com> <4BA9056D.8050206@vmware.com> <201003231832.12355.pedro@codesourcery.com> In-Reply-To: <201003231832.12355.pedro@codesourcery.com> MIME-Version: 1.0 Content-Type: Text/Plain; charset="utf-8" Content-Transfer-Encoding: 7bit Message-Id: <201003240114.57859.pedro@codesourcery.com> X-IsSubscribed: yes Mailing-List: contact gdb-patches-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner@sourceware.org X-SW-Source: 2010-03/txt/msg00809.txt.bz2 On Tuesday 23 March 2010 18:32:12, Pedro Alves wrote: > If you connect with "target extended-remote" > instead of "target remote", and do "compare-sections" before > issueing "run" or "attach" from gdb, hence gdbserver has no > inferior process to debug yet, you want gdbserver to reply > error (E01) instead of trying to read from a non-existing > inferior process (and possibly crashing). Actually, the compare-sections command is busted in that is doesn't work with extended-remote at all: (top-gdb) tar extended-remote :9999 Remote debugging using :9999 ... (top-gdb) compare-sections command can only be used with remote target Note: > /* 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. */ and: > if (!current_target.to_shortname || > strcmp (current_target.to_shortname, "remote") != 0) > error (_("command can only be used with remote target")); Ugh! This patch fixes it. I've applied it. -- Pedro Alves 2010-03-24 Pedro Alves 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/remote.c | 71 +++++++++++++++++++++++++++++++++-------------------------- gdb/target.c | 22 ++++++++++++++++++ gdb/target.h | 15 ++++++++++++ 3 files changed, 77 insertions(+), 31 deletions(-) Index: src/gdb/remote.c =================================================================== --- src.orig/gdb/remote.c 2010-03-24 00:38:23.000000000 +0000 +++ src/gdb/remote.c 2010-03-24 01:03:14.000000000 +0000 @@ -173,8 +173,6 @@ static CORE_ADDR remote_address_masked ( 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, unsi 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, in 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 connecte 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 Index: src/gdb/target.c =================================================================== --- src.orig/gdb/target.c 2010-03-24 01:04:17.000000000 +0000 +++ src/gdb/target.c 2010-03-24 01:04:25.000000000 +0000 @@ -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) { Index: src/gdb/target.h =================================================================== --- src.orig/gdb/target.h 2010-03-24 01:04:17.000000000 +0000 +++ src/gdb/target.h 2010-03-24 01:05:54.000000000 +0000 @@ -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_AD 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.