Mirror of the gdb-patches mailing list
 help / color / mirror / Atom feed
* [RFC] Info registers command produces no output for "standard register names"
@ 2005-05-28 14:22 Fred Fish
  2005-05-28 18:39 ` Daniel Jacobowitz
  0 siblings, 1 reply; 4+ messages in thread
From: Fred Fish @ 2005-05-28 14:22 UTC (permalink / raw)
  To: gdb-patches; +Cc: fnf

The "info register sp" command prints no output of any kind, not even
a message that this is not supported.  Same thing for the other "user
registers" (fp, pc, ps).

For example, run any executable to a breakpoint and try "info register sp".

 (gdb) br main
 Breakpoint 1 at 0x8048350: file t.c, line 3.
 (gdb) run
 Starting program: /links/build/sourceware/gdb/i686-pc-linux-gnu/gdb/t

 Breakpoint 1, main () at t.c:3
 3       }
 (gdb) info register sp
 (gdb) info register esp
 esp            0xbffff5d0       0xbffff5d0
 (gdb)

The attached patch fixes the problem, but may or may not be the best
way to deal with the issue.  Perhaps gdb should simply say that info
registers only supports printing using the canonical mnemonics for
registers (to use the terms in the gdb documentation).

This is reported as gdb bug #1926:

  http://sources.redhat.com/cgi-bin/gnatsweb.pl?cmd=view%20audit-trail&database=gdb&pr=1926

-Fred

============================================================================

	2005-05-27  Fred Fish  <fnf@specifixinc.com>
	* user-regs.h (default_print_user_registers_info): Declare.
	* user-regs.c: Include value.h and regcache.h.
	(default_print_user_registers_info): New function.
	* infcmd.c: Include user-regs.h.
	(default_print_registers_info): Handle user registers by
	calling default_print_user_registers_info.


Index: infcmd.c
===================================================================
RCS file: /cvs/src/src/gdb/infcmd.c,v
retrieving revision 1.136
diff -c -p -r1.136 infcmd.c
*** infcmd.c	8 Mar 2005 22:17:34 -0000	1.136
--- infcmd.c	25 Apr 2005 14:25:39 -0000
***************
*** 46,51 ****
--- 46,52 ----
  #include "block.h"
  #include <ctype.h>
  #include "gdb_assert.h"
+ #include "user-regs.h"
  
  /* Functions exported for general use, in inferior.h: */
  
*************** default_print_registers_info (struct gdb
*** 1525,1530 ****
--- 1526,1538 ----
    const int numregs = NUM_REGS + NUM_PSEUDO_REGS;
    char buffer[MAX_REGISTER_SIZE];
  
+   /* If this is a user register, try to print it */
+   if (regnum >= numregs)
+     {
+       default_print_user_registers_info (gdbarch, file, frame, regnum);
+       return;
+     }
+ 
    for (i = 0; i < numregs; i++)
      {
        /* Decide between printing all regs, non-float / vector regs, or
Index: user-regs.c
===================================================================
RCS file: /cvs/src/src/gdb/user-regs.c,v
retrieving revision 1.5
diff -c -p -r1.5 user-regs.c
*** user-regs.c	15 Mar 2004 20:38:08 -0000	1.5
--- user-regs.c	25 Apr 2005 14:25:39 -0000
***************
*** 27,32 ****
--- 27,34 ----
  #include "gdb_string.h"
  #include "gdb_assert.h"
  #include "frame.h"
+ #include "value.h"
+ #include "regcache.h"
  
  /* A table of user registers.
  
*************** value_of_user_reg (int regnum, struct fr
*** 202,207 ****
--- 204,251 ----
    return reg->read (frame);
  }
  
+ /* Print user register in same format as "info registers" so natural
+    things like "info register sp" works as expected.
+ 
+    FIXME: Assumes size and type of user reg is same as size of first
+    architecture register.
+ 
+    FIXME: Needs to track any changes in default_print_registers_info
+    formatting. */
+ 
+ void
+ default_print_user_registers_info (struct gdbarch *gdbarch,
+ 				   struct ui_file *file,
+ 				   struct frame_info *frame,
+ 				   int regnum)
+ {
+   const char *regname;
+   char raw_buffer[MAX_REGISTER_SIZE];
+   struct value *regval;
+   struct type *regtype;
+   int regsize;
+ 
+   regname = user_reg_map_regnum_to_name (gdbarch, regnum);
+   fputs_filtered (regname, file);
+   print_spaces_filtered (15 - strlen (regname), file);
+ 
+   regval = value_of_user_reg (regnum, frame);
+   if (! regval)
+     {
+       fprintf_filtered (file, "*value not available*\n");
+     }
+   else
+     {
+       regtype = register_type (gdbarch, 0);	/* FIXME */
+       regsize = register_size (gdbarch, 0);	/* FIXME */
+       memcpy (raw_buffer, value_contents_raw (regval), regsize);
+       val_print (regtype, raw_buffer, 0, 0, file, 'x', 1, 0, Val_pretty_default);
+       fprintf_filtered (file, "\t");
+       val_print (regtype, raw_buffer, 0, 0, file, 0, 1, 0, Val_pretty_default);
+       fprintf_filtered (file, "\n");
+     }
+ }
+ 
  extern initialize_file_ftype _initialize_user_regs; /* -Wmissing-prototypes */
  
  void
Index: user-regs.h
===================================================================
RCS file: /cvs/src/src/gdb/user-regs.h,v
retrieving revision 1.2
diff -c -p -r1.2 user-regs.h
*** user-regs.h	18 Jul 2003 19:01:14 -0000	1.2
--- user-regs.h	25 Apr 2005 14:25:39 -0000
***************
*** 37,43 ****
  /* TODO: cagney/2003-06-27: Need to think more about how these
     registers are added, read, and modified.  At present they are kind
     of assumed to be read-only.  Should it, for instance, return a
!    register descriptor that contains all the relvent access methods.  */
  
  struct frame_info;
  struct gdbarch;
--- 37,43 ----
  /* TODO: cagney/2003-06-27: Need to think more about how these
     registers are added, read, and modified.  At present they are kind
     of assumed to be read-only.  Should it, for instance, return a
!    register descriptor that contains all the relevent access methods.  */
  
  struct frame_info;
  struct gdbarch;
*************** extern const char *user_reg_map_regnum_t
*** 55,65 ****
  
     Note; These methods return a "struct value" instead of the raw
     bytes as, at the time the register is being added, the type needed
!    to describe the register has not bee initialized.  */
  
  typedef struct value *(user_reg_read_ftype) (struct frame_info *frame);
  extern struct value *value_of_user_reg (int regnum, struct frame_info *frame);
  
  /* Add a builtin register (present in all architectures).  */
  extern void user_reg_add_builtin (const char *name,
  				  user_reg_read_ftype *read);
--- 55,71 ----
  
     Note; These methods return a "struct value" instead of the raw
     bytes as, at the time the register is being added, the type needed
!    to describe the register has not been initialized.  */
  
  typedef struct value *(user_reg_read_ftype) (struct frame_info *frame);
  extern struct value *value_of_user_reg (int regnum, struct frame_info *frame);
  
+ /* Print user register in same format as "info registers". */
+ extern void default_print_user_registers_info (struct gdbarch *gdbarch,
+ 					       struct ui_file *file,
+ 					       struct frame_info *frame,
+ 					       int regnum);
+ 
  /* Add a builtin register (present in all architectures).  */
  extern void user_reg_add_builtin (const char *name,
  				  user_reg_read_ftype *read);




^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [RFC] Info registers command produces no output for "standard register names"
  2005-05-28 14:22 [RFC] Info registers command produces no output for "standard register names" Fred Fish
@ 2005-05-28 18:39 ` Daniel Jacobowitz
  2005-05-29  6:13   ` Eli Zaretskii
  0 siblings, 1 reply; 4+ messages in thread
From: Daniel Jacobowitz @ 2005-05-28 18:39 UTC (permalink / raw)
  To: Fred Fish; +Cc: gdb-patches

On Fri, May 27, 2005 at 05:37:58PM -0400, Fred Fish wrote:
> The "info register sp" command prints no output of any kind, not even
> a message that this is not supported.  Same thing for the other "user
> registers" (fp, pc, ps).
> 
> For example, run any executable to a breakpoint and try "info register sp".
> 
>  (gdb) br main
>  Breakpoint 1 at 0x8048350: file t.c, line 3.
>  (gdb) run
>  Starting program: /links/build/sourceware/gdb/i686-pc-linux-gnu/gdb/t
> 
>  Breakpoint 1, main () at t.c:3
>  3       }
>  (gdb) info register sp
>  (gdb) info register esp
>  esp            0xbffff5d0       0xbffff5d0
>  (gdb)
> 
> The attached patch fixes the problem, but may or may not be the best
> way to deal with the issue.  Perhaps gdb should simply say that info
> registers only supports printing using the canonical mnemonics for
> registers (to use the terms in the gdb documentation).

Well, I agree that we shouldn't leave it the way it is.  The final
result should be more-or-less consistent across targets; it looks like
every target with its own print_registers_info method will already do
this.  I only tested MIPS.

Your patch is overcomplicated for the problem.  The value of a user
register _can_ be read by value_of_user_reg, but it can also be read
just like any other register.  The only reason there's a problem is
that we iterate in [0, NUM_REGS + NUM_PSEUDO_REGS) and the user
registers are numbered outside that range.  Hmm, and we need a
different hook to get the register name.

How do you feel about this patch instead?  It brings the default
implementation in line with the few specializations; if you ask fo the
value of a user register, that's what you get.

While proofreading I noticed that some targets will issue an internal
error if you try to do this - for example SH.  There needs to be a test
case for this; I'm not going to commit the patch until I've done that.

However, the patch has raised some questions for me about register
names... the fact that there are acceptable REGNUM values that can't be
passed to gdbarch_register_name(), or most other gdbarch methods, is
really quite ugly.  I need to spend some more time thinking about this.
Also, there should probably be a register_name() function encapsulating
the current uses of user_reg_map_regnum_to_name.

-- 
Daniel Jacobowitz
CodeSourcery, LLC

2005-05-28  Daniel Jacobowitz  <dan@codesourcery.com>

	gdb/1926
	* Makefile.in (infcmd.o): Update dependencies.
	* infcmd.c: Include "user-regs.h".
	(default_print_register): New function, based on
	default_print_registers_info.  Use user_reg_map_regnum_to_name
	and common_val_print.
	(default_print_registers_info): Use it.

Index: Makefile.in
===================================================================
RCS file: /cvs/src/src/gdb/Makefile.in,v
retrieving revision 1.733
diff -u -p -r1.733 Makefile.in
--- Makefile.in	22 May 2005 20:36:18 -0000	1.733
+++ Makefile.in	28 May 2005 18:03:08 -0000
@@ -2113,7 +2113,7 @@ infcmd.o: infcmd.c $(defs_h) $(gdb_strin
 	$(symfile_h) $(gdbcore_h) $(target_h) $(language_h) $(symfile_h) \
 	$(objfiles_h) $(completer_h) $(ui_out_h) $(event_top_h) \
 	$(parser_defs_h) $(regcache_h) $(reggroups_h) $(block_h) \
-	$(solib_h) $(gdb_assert_h)
+	$(solib_h) $(user_regs_h) $(gdb_assert_h)
 inf-loop.o: inf-loop.c $(defs_h) $(inferior_h) $(target_h) $(event_loop_h) \
 	$(event_top_h) $(inf_loop_h) $(remote_h) $(exceptions_h)
 inflow.o: inflow.c $(defs_h) $(frame_h) $(inferior_h) $(command_h) \
Index: infcmd.c
===================================================================
RCS file: /cvs/src/src/gdb/infcmd.c,v
retrieving revision 1.138
diff -u -p -r1.138 infcmd.c
--- infcmd.c	22 May 2005 14:53:34 -0000	1.138
+++ infcmd.c	28 May 2005 18:03:09 -0000
@@ -45,6 +45,8 @@
 #include "reggroups.h"
 #include "block.h"
 #include "solib.h"
+#include "user-regs.h"
+
 #include <ctype.h>
 #include "gdb_assert.h"
 
@@ -1505,9 +1507,77 @@ path_command (char *dirname, int from_tt
 }
 \f
 
-/* Print out the machine register regnum. If regnum is -1, print all
-   registers (print_all == 1) or all non-float and non-vector
-   registers (print_all == 0).
+/* Print the value of machine register REGNUM from FRAME to FILE, in the
+   default format.  REGNUM must be a valid register number.  */
+
+void
+default_print_register (struct gdbarch *gdbarch, struct ui_file *file,
+			struct frame_info *frame, int regnum)
+{
+  struct value *regval;
+  const char *name;
+
+  name = user_reg_map_regnum_to_name (gdbarch, regnum);
+
+  /* If the register name is empty, it is undefined for this processor, so
+     don't display anything.  */
+  if (name == NULL)
+    return;
+
+  fputs_filtered (name, file);
+  print_spaces_filtered (15 - strlen (name), file);
+
+  /* Read the value.  */
+  regval = value_of_register (regnum, frame);
+  if (regval == NULL)
+    {
+      fprintf_filtered (file, "*value not available*\n");
+      return;
+    }
+
+  /* If virtual format is floating, print it that way, and in raw
+     hex.  */
+  if (TYPE_CODE (value_type (regval)) == TYPE_CODE_FLT)
+    {
+      int j, len;
+      const gdb_byte *buffer;
+
+      common_val_print (regval, file, 0, 1, 0, Val_pretty_default);
+
+      fprintf_filtered (file, "\t(raw 0x");
+      len = TYPE_LENGTH (value_type (regval));
+      buffer = value_contents (regval);
+      for (j = 0; j < len; j++)
+	{
+	  int idx;
+	  if (TARGET_BYTE_ORDER == BFD_ENDIAN_BIG)
+	    idx = j;
+	  else
+	    idx = len - 1 - j;
+	  fprintf_filtered (file, "%02x", (unsigned char) buffer[idx]);
+	}
+      fprintf_filtered (file, ")");
+    }
+  else
+    {
+      /* Print the register in hex.  */
+      common_val_print (regval, file, 'x', 1, 0, Val_pretty_default);
+
+      /* If not a vector register, print it also according to its
+	 natural format.  */
+      if (TYPE_VECTOR (value_type (regval)) == 0)
+	{
+	  fprintf_filtered (file, "\t");
+	  common_val_print (regval, file, 0, 1, 0, Val_pretty_default);
+	}
+    }
+
+  fprintf_filtered (file, "\n");
+}
+
+/* Print out the machine register REGNUM.  If regnum is -1, print all
+   registers (PRINT_ALL == 1) or all non-float and non-vector
+   registers (PRINT_ALL == 0).
 
    For most machines, having all_registers_info() print the
    register(s) one per line is good enough.  If a different format is
@@ -1524,83 +1594,22 @@ default_print_registers_info (struct gdb
 {
   int i;
   const int numregs = NUM_REGS + NUM_PSEUDO_REGS;
-  gdb_byte buffer[MAX_REGISTER_SIZE];
 
-  for (i = 0; i < numregs; i++)
+  if (regnum >= 0)
     {
-      /* Decide between printing all regs, non-float / vector regs, or
-         specific reg.  */
-      if (regnum == -1)
-	{
-	  if (print_all)
-	    {
-	      if (!gdbarch_register_reggroup_p (gdbarch, i, all_reggroup))
-		continue;
-	    }
-	  else
-	    {
-	      if (!gdbarch_register_reggroup_p (gdbarch, i, general_reggroup))
-		continue;
-	    }
-	}
-      else
-	{
-	  if (i != regnum)
-	    continue;
-	}
-
-      /* If the register name is empty, it is undefined for this
-         processor, so don't display anything.  */
-      if (REGISTER_NAME (i) == NULL || *(REGISTER_NAME (i)) == '\0')
-	continue;
-
-      fputs_filtered (REGISTER_NAME (i), file);
-      print_spaces_filtered (15 - strlen (REGISTER_NAME (i)), file);
-
-      /* Get the data in raw format.  */
-      if (! frame_register_read (frame, i, buffer))
-	{
-	  fprintf_filtered (file, "*value not available*\n");
-	  continue;
-	}
-
-      /* If virtual format is floating, print it that way, and in raw
-         hex.  */
-      if (TYPE_CODE (register_type (current_gdbarch, i)) == TYPE_CODE_FLT)
-	{
-	  int j;
-
-	  val_print (register_type (current_gdbarch, i), buffer, 0, 0,
-		     file, 0, 1, 0, Val_pretty_default);
-
-	  fprintf_filtered (file, "\t(raw 0x");
-	  for (j = 0; j < register_size (current_gdbarch, i); j++)
-	    {
-	      int idx;
-	      if (TARGET_BYTE_ORDER == BFD_ENDIAN_BIG)
-		idx = j;
-	      else
-		idx = register_size (current_gdbarch, i) - 1 - j;
-	      fprintf_filtered (file, "%02x", (unsigned char) buffer[idx]);
-	    }
-	  fprintf_filtered (file, ")");
-	}
-      else
-	{
-	  /* Print the register in hex.  */
-	  val_print (register_type (current_gdbarch, i), buffer, 0, 0,
-		     file, 'x', 1, 0, Val_pretty_default);
-          /* If not a vector register, print it also according to its
-             natural format.  */
-	  if (TYPE_VECTOR (register_type (current_gdbarch, i)) == 0)
-	    {
-	      fprintf_filtered (file, "\t");
-	      val_print (register_type (current_gdbarch, i), buffer, 0, 0,
-			 file, 0, 1, 0, Val_pretty_default);
-	    }
-	}
+      default_print_register (gdbarch, file, frame, regnum);
+      return;
+    }
 
-      fprintf_filtered (file, "\n");
+  for (i = 0; i < numregs; i++)
+    {
+      /* Decide between printing all regs or non-float / vector regs.  */
+      if (print_all
+	  && gdbarch_register_reggroup_p (gdbarch, i, all_reggroup))
+	default_print_register (gdbarch, file, frame, i);
+      else if (!print_all
+	       && gdbarch_register_reggroup_p (gdbarch, i, general_reggroup))
+	default_print_register (gdbarch, file, frame, i);
     }
 }
 


^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [RFC] Info registers command produces no output for "standard register names"
  2005-05-28 18:39 ` Daniel Jacobowitz
@ 2005-05-29  6:13   ` Eli Zaretskii
  2005-05-29 20:54     ` Daniel Jacobowitz
  0 siblings, 1 reply; 4+ messages in thread
From: Eli Zaretskii @ 2005-05-29  6:13 UTC (permalink / raw)
  To: Fred Fish; +Cc: gdb-patches

> Date: Sat, 28 May 2005 14:06:57 -0400
> From: Daniel Jacobowitz <drow@false.org>
> Cc: gdb-patches@sources.redhat.com
> 
> +      fprintf_filtered (file, "\t(raw 0x");
> +      len = TYPE_LENGTH (value_type (regval));
> +      buffer = value_contents (regval);
> +      for (j = 0; j < len; j++)
> +	{
> +	  int idx;
> +	  if (TARGET_BYTE_ORDER == BFD_ENDIAN_BIG)
> +	    idx = j;
> +	  else
> +	    idx = len - 1 - j;
> +	  fprintf_filtered (file, "%02x", (unsigned char) buffer[idx]);
> +	}
> +      fprintf_filtered (file, ")");

Daniel, this kind of output generation loop is bad for i18n.  So how
about if we produce the entire numerical string in memory, then print
it all, as a string, in one go, together with its decorations?  (Yes,
I know you just copied the old code, but as long as we are
changing...)


^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [RFC] Info registers command produces no output for "standard register names"
  2005-05-29  6:13   ` Eli Zaretskii
@ 2005-05-29 20:54     ` Daniel Jacobowitz
  0 siblings, 0 replies; 4+ messages in thread
From: Daniel Jacobowitz @ 2005-05-29 20:54 UTC (permalink / raw)
  To: gdb-patches

On Sun, May 29, 2005 at 08:53:50AM +0300, Eli Zaretskii wrote:
> > Date: Sat, 28 May 2005 14:06:57 -0400
> > From: Daniel Jacobowitz <drow@false.org>
> > Cc: gdb-patches@sources.redhat.com
> > 
> > +      fprintf_filtered (file, "\t(raw 0x");
> > +      len = TYPE_LENGTH (value_type (regval));
> > +      buffer = value_contents (regval);
> > +      for (j = 0; j < len; j++)
> > +	{
> > +	  int idx;
> > +	  if (TARGET_BYTE_ORDER == BFD_ENDIAN_BIG)
> > +	    idx = j;
> > +	  else
> > +	    idx = len - 1 - j;
> > +	  fprintf_filtered (file, "%02x", (unsigned char) buffer[idx]);
> > +	}
> > +      fprintf_filtered (file, ")");
> 
> Daniel, this kind of output generation loop is bad for i18n.  So how
> about if we produce the entire numerical string in memory, then print
> it all, as a string, in one go, together with its decorations?  (Yes,
> I know you just copied the old code, but as long as we are
> changing...)

Good point.  In this case I don't think it makes much difference, but
it's definitely a good habit to get into; I'll fix that if the patch
goes in.

-- 
Daniel Jacobowitz
CodeSourcery, LLC


^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2005-05-29 19:28 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2005-05-28 14:22 [RFC] Info registers command produces no output for "standard register names" Fred Fish
2005-05-28 18:39 ` Daniel Jacobowitz
2005-05-29  6:13   ` Eli Zaretskii
2005-05-29 20:54     ` Daniel Jacobowitz

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox