From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 6696 invoked by alias); 20 Apr 2011 17:29:56 -0000 Received: (qmail 6687 invoked by uid 22791); 20 Apr 2011 17:29:53 -0000 X-SWARE-Spam-Status: No, hits=-1.9 required=5.0 tests=AWL,BAYES_00,TW_EG,T_RP_MATCHES_RCVD 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, 20 Apr 2011 17:29:38 +0000 Received: (qmail 13268 invoked from network); 20 Apr 2011 17:29:38 -0000 Received: from unknown (HELO scottsdale.localnet) (pedro@127.0.0.2) by mail.codesourcery.com with ESMTPA; 20 Apr 2011 17:29:38 -0000 From: Pedro Alves Date: Wed, 20 Apr 2011 17:29:00 -0000 User-Agent: KMail/1.13.5 (Linux/2.6.35-28-generic; KDE/4.6.2; x86_64; ; ) MIME-Version: 1.0 To: gdb-patches@sourceware.org Subject: [RFA] new "maint print remote-registers" command Content-Type: Text/Plain; charset="us-ascii" Content-Transfer-Encoding: 7bit Message-Id: <201104201829.35804.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: 2011-04/txt/msg00362.txt.bz2 This adds a new variant of "maint print registers", that prints what the remote register numbers are, compared to the internal regcache numbers, and what the offset of the raw registers is in the layout of the g/G packets. Here's an example: (gdb) maint print remote-registers Name Nr Rel Offset Size Type Rmt Nr g/G Offset r0 0 0 0 4 long 0 0 r1 1 1 4 4 long 1 4 r2 2 2 8 4 long 2 8 r3 3 3 12 4 long 3 12 r4 4 4 16 4 long 4 16 r5 5 5 20 4 long 5 20 r6 6 6 24 4 long 6 24 r7 7 7 28 4 long 7 28 r8 8 8 32 4 long 8 32 r9 9 9 36 4 long 9 36 r10 10 10 40 4 long 10 40 r11 11 11 44 4 long 11 44 r12 12 12 48 4 long 12 48 sp 13 13 52 4 *1 13 52 lr 14 14 56 4 long 14 56 pc 15 15 60 4 *1 15 60 '' 16 16 64 0 int0_t '' 17 17 64 0 int0_t '' 18 18 64 0 int0_t '' 19 19 64 0 int0_t '' 20 20 64 0 int0_t '' 21 21 64 0 int0_t '' 22 22 64 0 int0_t '' 23 23 64 0 int0_t '' 24 24 64 0 int0_t xpsr 25 25 64 4 long 25 164 '' 26 26 68 0 int0_t '' 27 27 68 0 int0_t '' 28 28 68 0 int0_t '' 29 29 68 0 int0_t '' 30 30 68 0 int0_t '' 31 31 68 0 int0_t '' 32 32 68 0 int0_t '' 33 33 68 0 int0_t '' 34 34 68 0 int0_t '' 35 35 68 0 int0_t '' 36 36 68 0 int0_t '' 37 37 68 0 int0_t '' 38 38 68 0 int0_t '' 39 39 68 0 int0_t '' 40 40 68 0 int0_t '' 41 41 68 0 int0_t '' 42 42 68 0 int0_t '' 43 43 68 0 int0_t '' 44 44 68 0 int0_t '' 45 45 68 0 int0_t '' 46 46 68 0 int0_t '' 47 47 68 0 int0_t '' 48 48 68 0 int0_t '' 49 49 68 0 int0_t '' 50 50 68 0 int0_t '' 51 51 68 0 int0_t '' 52 52 68 0 int0_t '' 53 53 68 0 int0_t '' 54 54 68 0 int0_t '' 55 55 68 0 int0_t '' 56 56 68 0 int0_t '' 57 57 68 0 int0_t '' 58 58 68 0 int0_t '' 59 59 68 0 int0_t '' 60 60 68 0 int0_t '' 61 61 68 0 int0_t '' 62 62 68 0 int0_t '' 63 63 68 0 int0_t '' 64 64 68 0 int0_t '' 65 65 68 0 int0_t '' 66 66 68 0 int0_t '' 67 67 68 0 int0_t '' 68 68 68 0 int0_t '' 69 69 68 0 int0_t '' 70 70 68 0 int0_t '' 71 71 68 0 int0_t '' 72 72 68 0 int0_t '' 73 73 68 0 int0_t '' 74 74 68 0 int0_t '' 75 75 68 0 int0_t '' 76 76 68 0 int0_t '' 77 77 68 0 int0_t '' 78 78 68 0 int0_t '' 79 79 68 0 int0_t '' 80 80 68 0 int0_t '' 81 81 68 0 int0_t '' 82 82 68 0 int0_t '' 83 83 68 0 int0_t '' 84 84 68 0 int0_t '' 85 85 68 0 int0_t '' 86 86 68 0 int0_t '' 87 87 68 0 int0_t '' 88 88 68 0 int0_t '' 89 89 68 0 int0_t '' 90 90 68 0 int0_t '' 91 91 68 12 _arm_ext 16 64 '' 92 92 80 12 _arm_ext 17 76 '' 93 93 92 12 _arm_ext 18 88 '' 94 94 104 12 _arm_ext 19 100 '' 95 95 116 12 _arm_ext 20 112 '' 96 96 128 12 _arm_ext 21 124 '' 97 97 140 12 _arm_ext 22 136 '' 98 98 152 12 _arm_ext 23 148 '' 99 99 164 4 long 24 160 *1: Register type's name NULL. (gdb) Implementation-wise, I'm rebuilding the remote g/G packet layout once for each register, but not doing that would require exporting more from remote.c's internals than I'd like. It's not like there's an architecture out there that has so many registers one would notice. :-) Do the docs changes look okay? Pedro Alves 2011-04-20 Pedro Alves gdb/ * regcache.c: Include remote.h. (enum regcache_dump_what) : New enum value. (regcache_dump): Handle regcache_dump_remote. (maintenance_print_remote_registers): New function. (_initialize_regcache): Install "maint print remote-registers" command. * remote.c (map_regcache_remote_table): New function, factored out from ... (init_remote_state): ... here. (remote_register_number_and_offset): New. * remote.h (remote_register_number_and_offset): Declare. gdb/doc/ * gdb.texinfo (Maintenance Commands): Document `maint print remote-registers'. --- gdb/doc/gdb.texinfo | 14 ++++++---- gdb/regcache.c | 33 ++++++++++++++++++++++++ gdb/remote.c | 69 +++++++++++++++++++++++++++++++++++++++------------- gdb/remote.h | 4 +++ 4 files changed, 98 insertions(+), 22 deletions(-) Index: src/gdb/regcache.c =================================================================== --- src.orig/gdb/regcache.c 2011-04-20 18:14:11.466406001 +0100 +++ src/gdb/regcache.c 2011-04-20 18:17:45.686406001 +0100 @@ -30,6 +30,7 @@ #include "gdbcmd.h" /* For maintenanceprintlist. */ #include "observer.h" #include "exceptions.h" +#include "remote.h" /* * DATA STRUCTURE @@ -1053,7 +1054,8 @@ dump_endian_bytes (struct ui_file *file, enum regcache_dump_what { regcache_dump_none, regcache_dump_raw, - regcache_dump_cooked, regcache_dump_groups + regcache_dump_cooked, regcache_dump_groups, + regcache_dump_remote }; static void @@ -1251,6 +1253,23 @@ regcache_dump (struct regcache *regcache } } + /* Remote packet configuration. */ + if (what_to_dump == regcache_dump_remote) + { + if (regnum < 0) + { + fprintf_unfiltered (file, "Rmt Nr g/G Offset"); + } + else if (regnum < regcache->descr->nr_raw_registers) + { + int pnum, poffset; + + if (remote_register_number_and_offset (get_regcache_arch (regcache), regnum, + &pnum, &poffset)) + fprintf_unfiltered (file, "%7d %11d", pnum, poffset); + } + } + fprintf_unfiltered (file, "\n"); } @@ -1309,6 +1328,12 @@ maintenance_print_register_groups (char regcache_print (args, regcache_dump_groups); } +static void +maintenance_print_remote_registers (char *args, int from_tty) +{ + regcache_print (args, regcache_dump_remote); +} + extern initialize_file_ftype _initialize_regcache; /* -Wmissing-prototype */ void @@ -1342,5 +1367,11 @@ _initialize_regcache (void) "including each register's group.\n" "Takes an optional file parameter."), &maintenanceprintlist); + add_cmd ("remote-registers", class_maintenance, + maintenance_print_remote_registers, _("\ +Print the internal register configuration including each register's\n\ +remote register number and buffer offset in the g/G packets.\n\ +Takes an optional file parameter."), + &maintenanceprintlist); } Index: src/gdb/remote.c =================================================================== --- src.orig/gdb/remote.c 2011-04-20 16:56:34.906406000 +0100 +++ src/gdb/remote.c 2011-04-20 18:27:02.035266005 +0100 @@ -535,24 +535,15 @@ compare_pnums (const void *lhs_, const v return 1; } -static void * -init_remote_state (struct gdbarch *gdbarch) +static int +map_regcache_remote_table (struct gdbarch *gdbarch, struct packet_reg *regs) { int regnum, num_remote_regs, offset; - struct remote_state *rs = get_remote_state_raw (); - struct remote_arch_state *rsa; struct packet_reg **remote_regs; - rsa = GDBARCH_OBSTACK_ZALLOC (gdbarch, struct remote_arch_state); - - /* Use the architecture to build a regnum<->pnum table, which will be - 1:1 unless a feature set specifies otherwise. */ - rsa->regs = GDBARCH_OBSTACK_CALLOC (gdbarch, - gdbarch_num_regs (gdbarch), - struct packet_reg); for (regnum = 0; regnum < gdbarch_num_regs (gdbarch); regnum++) { - struct packet_reg *r = &rsa->regs[regnum]; + struct packet_reg *r = ®s[regnum]; if (register_size (gdbarch, regnum) == 0) /* Do not try to fetch zero-sized (placeholder) registers. */ @@ -568,12 +559,12 @@ init_remote_state (struct gdbarch *gdbar number. */ remote_regs = alloca (gdbarch_num_regs (gdbarch) - * sizeof (struct packet_reg *)); + * sizeof (struct packet_reg *)); for (num_remote_regs = 0, regnum = 0; regnum < gdbarch_num_regs (gdbarch); regnum++) - if (rsa->regs[regnum].pnum != -1) - remote_regs[num_remote_regs++] = &rsa->regs[regnum]; + if (regs[regnum].pnum != -1) + remote_regs[num_remote_regs++] = ®s[regnum]; qsort (remote_regs, num_remote_regs, sizeof (struct packet_reg *), compare_pnums); @@ -585,9 +576,55 @@ init_remote_state (struct gdbarch *gdbar offset += register_size (gdbarch, remote_regs[regnum]->regnum); } + return offset; +} + +/* Given the architecture described by GDBARCH, return the remote + protocol register's number and the register's offset in the g/G + packets of GDB register REGNUM, in PNUM and POFFSET respectively. + If the target does not have a mapping for REGNUM, return false, + otherwise, return true. */ + +int +remote_register_number_and_offset (struct gdbarch *gdbarch, int regnum, + int *pnum, int *poffset) +{ + int sizeof_g_packet; + struct packet_reg *regs; + struct cleanup *old_chain; + + gdb_assert (regnum < gdbarch_num_regs (gdbarch)); + + regs = xcalloc (gdbarch_num_regs (gdbarch), sizeof (struct packet_reg)); + old_chain = make_cleanup (xfree, regs); + + sizeof_g_packet = map_regcache_remote_table (gdbarch, regs); + + *pnum = regs[regnum].pnum; + *poffset = regs[regnum].offset; + + do_cleanups (old_chain); + + return *pnum != -1; +} + +static void * +init_remote_state (struct gdbarch *gdbarch) +{ + struct remote_state *rs = get_remote_state_raw (); + struct remote_arch_state *rsa; + + rsa = GDBARCH_OBSTACK_ZALLOC (gdbarch, struct remote_arch_state); + + /* Use the architecture to build a regnum<->pnum table, which will be + 1:1 unless a feature set specifies otherwise. */ + rsa->regs = GDBARCH_OBSTACK_CALLOC (gdbarch, + gdbarch_num_regs (gdbarch), + struct packet_reg); + /* Record the maximum possible size of the g packet - it may turn out to be smaller. */ - rsa->sizeof_g_packet = offset; + rsa->sizeof_g_packet = map_regcache_remote_table (gdbarch, rsa->regs); /* Default maximum number of characters in a packet body. Many remote stubs have a hardwired buffer size of 400 bytes Index: src/gdb/remote.h =================================================================== --- src.orig/gdb/remote.h 2011-04-20 16:56:34.906406000 +0100 +++ src/gdb/remote.h 2011-04-20 18:14:27.816406002 +0100 @@ -56,4 +56,8 @@ bfd *remote_bfd_open (const char *remote int remote_filename_p (const char *filename); +extern int remote_register_number_and_offset (struct gdbarch *gdbarch, + int regnum, int *pnum, + int *poffset); + #endif Index: src/gdb/doc/gdb.texinfo =================================================================== --- src.orig/gdb/doc/gdb.texinfo 2011-04-20 16:56:34.906406000 +0100 +++ src/gdb/doc/gdb.texinfo 2011-04-20 18:14:27.866406002 +0100 @@ -31678,18 +31678,22 @@ Takes an optional file parameter. @kindex maint print raw-registers @kindex maint print cooked-registers @kindex maint print register-groups +@kindex maint print remote-registers @item maint print registers @r{[}@var{file}@r{]} @itemx maint print raw-registers @r{[}@var{file}@r{]} @itemx maint print cooked-registers @r{[}@var{file}@r{]} @itemx maint print register-groups @r{[}@var{file}@r{]} +@itemx maint print remote-registers @r{[}@var{file}@r{]} Print @value{GDBN}'s internal register data structures. The command @code{maint print raw-registers} includes the contents of -the raw register cache; the command @code{maint print cooked-registers} -includes the (cooked) value of all registers, including registers which -aren't available on the target nor visible to user; and the -command @code{maint print register-groups} includes the groups that each -register is a member of. @xref{Registers,, Registers, gdbint, +the raw register cache; the command @code{maint print +cooked-registers} includes the (cooked) value of all registers, +including registers which aren't available on the target nor visible +to user; the command @code{maint print register-groups} includes the +groups that each register is a member of; and the command @code{maint +print remote-registers} includes the remote target's register numbers +and offsets in the `G' packets. @xref{Registers,, Registers, gdbint, @value{GDBN} Internals}. These commands take an optional parameter, a file name to which to