This is the mail archive of the gdb-patches@sources.redhat.com mailing list for the GDB project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

Re: [patch] new command: 'dump' a region of memory in ascii and hex


> How about the following strategy:
> 
>   - always print the first "Dumping from... to..." line;
> 
>   - if the dump takes more than a screenful, print the trailing "End
>     of dump from... to..." line as well.

I couldn't find a clean way of doing that, the screen size information
is trapped inside utils.c (and I don't see a good reason to let it
out.) I simply removed the "End of dump line" (it is #if 0'd in the
patch in case anyone knew a clever way of determining screen size.

> Hmm... this begins to creep into a full-fledged emulation of the GNU
> `od'...  Not necessarily a bad thing, but perhaps you should take the
> various options from `od' as well?
not today :-)


> 
> > --- doc/gdb.texinfo.orig	Wed Nov 22 14:34:16 2000
> > +++ doc/gdb.texinfo	Wed Nov 22 14:45:02 2000
> 
> If and when the change to the sources is approved, the docs changes
> are approved as well, provided that you take care of these minor
> gotchas:
fixed in the attached patch.

Additional changes with the new patch:

-the dump act more like the other 'x' commands where the convienence
variables $_ and $__ are concerned, that is, it updates them like the
documentation says it should.
-if the number of bytes the user requested doesn't divide evenly by 16
the last line is padded with spaces. In past patches I was simply
finishing out the line even though the user didn't ask for those
bytes.
-the repeat count used to be always understood as being in bytes, but
now we look at the unit size. (unit_size*repeat_count=num bytes to
dump)


-David


2000-11-21  David Whedon <dwhedon@gordian.com>
	* printcmd.c (x_command) : repeat count is now remembered and reused
	across 'examines', new format type 'r'(raw) dumps hex and
	ascii.
	* doc/gdb.texinfo : updated 'examine' command documentation.
	* testsuite/gdb.base/printcmds.exp : added a test case for
	'r'(raw) format memory examine.


--- printcmd.c.orig	Tue Nov 21 18:03:08 2000
+++ printcmd.c	Mon Nov 27 19:19:40 2000
@@ -57,6 +57,9 @@ static char last_format = 'x';
 
 static char last_size = 'w';
 
+/* last specified output count */
+static int last_count = 1;
+
 /* Default address to examine next.  */
 
 static CORE_ADDR next_address;
@@ -168,6 +171,8 @@ static void validate_format PARAMS ((str
 
 static void do_examine PARAMS ((struct format_data, CORE_ADDR addr, asection * section));
 
+static void do_dump (struct format_data fmt, CORE_ADDR low);
+
 static void print_formatted (value_ptr, int, int, struct ui_file *);
 
 static struct format_data decode_format PARAMS ((char **, int, int));
@@ -1352,7 +1357,7 @@ x_command (exp, from_tty)
 
   fmt.format = last_format;
   fmt.size = last_size;
-  fmt.count = 1;
+  fmt.count = last_count;
 
   if (exp && *exp == '/')
     {
@@ -1388,11 +1393,15 @@ x_command (exp, from_tty)
       do_cleanups (old_chain);
     }
 
-  do_examine (fmt, next_address, next_section);
+  if (fmt.format == 'r')
+    do_dump (fmt, next_address);
+  else
+    do_examine (fmt, next_address, next_section);
 
   /* If the examine succeeds, we remember its size and format for next time.  */
   last_size = fmt.size;
   last_format = fmt.format;
+  last_count = fmt.count;
 
   /* Set a couple of internal variables if appropriate. */
   if (last_examine_value)
@@ -2521,6 +2530,108 @@ print_insn (memaddr, stream)
 }
 
 
+
+/* 
+   Dump a specified region in memory starting at 'low'.  
+   Output is hex and ascii.
+   Length and delimitation controlled by 'fmt'
+ */
+#define CHARS_PER_LINE 16
+
+static void
+do_dump (struct format_data fmt, CORE_ADDR low)
+{
+  CORE_ADDR high, symbol_low, symbol_high;
+  value_ptr val;
+  struct type *val_type = examine_b_type;
+  int i;
+  char buffer[CHARS_PER_LINE + 1];
+  char *symbol_name;
+
+  switch (fmt.size)
+    {
+    case 'b':
+      val_type = examine_b_type;
+      break;
+    case 'h':
+      val_type = examine_h_type;
+      break;
+    case 'w':
+      val_type = examine_w_type;
+      break;
+    case 'g':
+      val_type = examine_g_type;
+      break;
+    default:
+      val_type = examine_w_type;
+    }
+
+  high = low + fmt.count * TYPE_LENGTH (val_type);
+  next_address = low;
+
+  fprintf_filtered (gdb_stdout, "Dumping from ");
+  print_address (low, gdb_stdout);
+  fprintf_filtered (gdb_stdout, " to ");
+  print_address (high, gdb_stdout);
+  fprintf_filtered (gdb_stdout, "\n");
+
+  find_pc_partial_function (next_address, &symbol_name, &symbol_low, &symbol_high);
+  print_address_symbolic (next_address, gdb_stdout, 1, "");
+  fprintf_filtered (gdb_stdout, ":\n");
+  while (next_address < high)
+    {
+      if (next_address > symbol_high)
+	{
+	  find_pc_partial_function (next_address, &symbol_name,
+				    &symbol_low, &symbol_high);
+	  print_address_symbolic (next_address, gdb_stdout, 1, "");
+	  fprintf_filtered (gdb_stdout, ":\n");
+	}
+      print_address_numeric (next_address, 1, gdb_stdout);
+      fprintf_filtered (gdb_stdout, ": ");
+
+      for (i = 0; (i < CHARS_PER_LINE) && (next_address < high); i++)
+	{
+	  if (i % TYPE_LENGTH (val_type) == 0)
+	    fprintf_filtered (gdb_stdout, " ");
+
+	  last_examine_address = next_address;
+
+	  if (last_examine_value)
+	    value_free (last_examine_value);
+
+	  last_examine_value = value_at (examine_b_type, next_address, next_section);
+	  if (last_examine_value)
+	    release_value (last_examine_value);
+
+	  buffer[i] = 0xFF & *(VALUE_CONTENTS_RAW (last_examine_value));
+	  fprintf_filtered (gdb_stdout, "%.2x", 0xFF & buffer[i]);
+	  if (buffer[i] < 33 || buffer[i] > 126)
+	    buffer[i] = '.';
+	  next_address++;
+	}
+      while (i < CHARS_PER_LINE)
+	{
+	  if (i % TYPE_LENGTH (val_type) == 0)
+	    fprintf_filtered (gdb_stdout, " ");
+	  fprintf_filtered (gdb_stdout, "  ");
+	  buffer[i++] = ' ';
+	}
+
+      buffer[i] = '\0';
+      fprintf_filtered (gdb_stdout, " %s\n", buffer);
+
+    }
+#if 0
+  fprintf_filtered (gdb_stdout, "End of dump from ");
+  print_address (low, gdb_stdout);
+  fprintf_filtered (gdb_stdout, " to ");
+  print_address (high, gdb_stdout);
+  fprintf_filtered (gdb_stdout, "\n");
+#endif
+
+}
+
 void
 _initialize_printcmd ()
 {
@@ -2538,7 +2649,8 @@ Only for symbols with fixed locations (g
 ADDRESS is an expression for the memory address to examine.\n\
 FMT is a repeat count followed by a format letter and a size letter.\n\
 Format letters are o(octal), x(hex), d(decimal), u(unsigned decimal),\n\
-  t(binary), f(float), a(address), i(instruction), c(char) and s(string).\n",
+  t(binary), f(float), a(address), i(instruction), c(char), s(string) \n\
+and r(raw).\n",
 		   "Size letters are b(byte), h(halfword), w(word), g(giant, 8 bytes).\n\
 The specified number of objects of the specified size are printed\n\
 according to the format.\n\n\
--- printcmds.exp.orig	Tue Nov 21 18:22:24 2000
+++ printcmds.exp	Wed Nov 22 14:57:59 2000
@@ -680,6 +680,13 @@ proc test_printf {} {
 0xfeedface, 0xdeadbeef, 5.0" "bad -99.54\[0-9\]+, z feedface, deadbeef, 5.0+"
 }
 
+proc test_x {} {
+
+gdb_test "x /4wr ctable2" \
+    ".*<ctable2>:.*0x.*61585858 58585858 58585858 58585858.*aXXXXXXXXXXXXXXX"
+
+
+}
 # Start with a fresh gdb.
 
 gdb_exit
@@ -714,6 +721,7 @@ if [set_lang_c] then {
 	test_print_string_constants
 	test_print_array_constants
 	test_printf
+	test_x
     }
 } else {
     fail "C print command tests suppressed"
--- gdb.texinfo.orig	Wed Nov 22 14:34:16 2000
+++ gdb.texinfo	Mon Nov 27 19:44:53 2000
@@ -4668,14 +4668,14 @@ Several commands set convenient defaults
 
 @table @r
 @item @var{n}, the repeat count
-The repeat count is a decimal integer; the default is 1.  It specifies
-how much memory (counting by units @var{u}) to display.
+The repeat count is a decimal integer.  It specifies
+how much memory (counting by units @var{u}) to display.  Each time you use @code{x} the default repeat count is updated.
 @c This really is **decimal**; unaffected by 'set radix' as of GDB
 @c 4.1.2.
 
 @item @var{f}, the display format
 The display format is one of the formats used by @code{print},
-@samp{s} (null-terminated string), or @samp{i} (machine instruction).
+@samp{r} (raw, displays hex and @sc{ascii} dump), @samp{s} (null-terminated string), or @samp{i} (machine instruction).
 The default is @samp{x} (hexadecimal) initially.
 The default changes each time you use either @code{x} or @code{print}.
 
@@ -4713,7 +4713,25 @@ For example, @samp{x/3uh 0x54320} is a r
 (@code{h}) of memory, formatted as unsigned decimal integers (@samp{u}),
 starting at address @code{0x54320}.  @samp{x/4xw $sp} prints the four
 words (@samp{w}) of memory above the stack pointer (here, @samp{$sp};
-@pxref{Registers, ,Registers}) in hexadecimal (@samp{x}).
+@pxref{Registers, ,Registers}) in hexadecimal (@samp{x}). 
+@cindex hex dump
+@cindex dumping memory contents
+
+Following is an example of examining memory with the raw (@samp{r}) format.  
+The unit size controls how the hex chars are delimited, as well as the meaning
+of the repeat count. 
+
+@smallexample
+(@value{GDBP}) @b{x /6rw ctable2}
+Dumping from 0x80496a0 <ctable2> to 0x80496b8 <ctable2+24>
+<ctable2>:
+0x80496a0:  61585858 58585858 58585858 58585858 aXXXXXXXXXXXXXXX
+0x80496b0:  61615858 58585858                   aaXXXXXX        
+(@value{GDBP}) @b{x /7rb}
+Dumping from 0x80496b8 <ctable2+24> to 0x80496bf <ctable2+31>
+<ctable2+24>:
+0x80496b8:  58 58 58 58 58 58 58                            XXXXXXX         
+@end smallexample
 
 Since the letters indicating unit sizes are all distinct from the
 letters specifying output formats, you do not have to remember whether

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]