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


I applied suggestion from Stephane and Eli; here's rev two.  There
still may be some changes in order, I've enumerated what I believe
might still be imperfect:

1. gdb doesn't currently remember and reuse the repeat count of an examine.  I
think it should.  It makes all the examine commands behave better, IMHO.  This
required only about 3 lines to change and there weren't any testsuite
regressions.  This is actually not related to the change at hand, except that it
makes the 'x' command more user friendly.  This change is included in
the below patch.

2. I sort of like the "Dumping from . . ." that Eli suggested, but I think it
looks bad when you are only dumping 16 or so bytes:
(top-gdb) x /r main
Dumping from 0x806bf08 <main> to 0x806bf09 <main+1>
<main>:
0x806bf08:  5589e583 ec188b45 088b550c 8945f88d U......E..U..E..
End of dump from 0x806bf08 <main> to 0x806bf09 <main+1>
(top-gdb)
It looks good for the larger dumps.  One option is to make the header/footer
conditional on the size of the dump.  That is what I have now, though it feels
somewhat bad, arbitrary, questionable.

3. Now that 'dump' is integrated with the examine ('x') command I wanted to do
something with the size letters.  I decided to make the size letters control
where I put spaces in the output.
(top-gdb) x /r main
<main>:
0x806bf08:  5589e583 ec188b45 088b550c 8945f88d U......E..U..E..
(top-gdb) x /br main
<main>:
0x806bf08:  55 89 e5 83 ec 18 8b 45 08 8b 55 0c 89 45 f8 8d U......E..U..E..
(top-gdb) 
That looks nice, might be easier to understand, but it might be confusing if the
user is expecting the command to be taking endianess into account. The way the
ascii is displayed, and the fact that the format is called 'raw' might clue the
user in that the bytes aren't swapped, I don't know. I want to do something
with the size letters, but maybe I should just ignore them the way they are
ignored when the format is 'i' (instruction).


-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	Wed Nov 22 14:30:27 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,94 @@ print_insn (memaddr, stream)
 }
 
 
+
+/* 
+   Dump a specified region in memory starting at 'low'.  
+   Output is hex and ascii.
+   Length and delimination 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;
+  next_address = low;
+
+  if (fmt.count > 32)
+    {
+      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; i++)
+	{
+	  if (i % TYPE_LENGTH (val_type) == 0)
+	    fprintf_filtered (gdb_stdout, " ");
+
+	  val = value_at (examine_b_type, next_address, next_section);
+	  buffer[i] = 0xFF & *(VALUE_CONTENTS_RAW (val));
+	  fprintf_filtered (gdb_stdout, "%.2x", 0xFF & buffer[i]);
+	  if (buffer[i] < 33 || buffer[i] > 126)
+	    buffer[i] = '.';
+	  next_address++;
+	}
+      buffer[i] = '\0';
+      fprintf_filtered (gdb_stdout, " %s\n", buffer);
+
+    }
+  if (fmt.count > 32)
+    {
+      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");
+    }
+}
+
 void
 _initialize_printcmd ()
 {
@@ -2538,7 +2635,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\
--- doc/gdb.texinfo.orig	Wed Nov 22 14:34:16 2000
+++ doc/gdb.texinfo	Wed Nov 22 14:45:02 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 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}.
 
--- testsuite/gdb.base/printcmds.exp.orig	Tue Nov 21 18:22:24 2000
+++ testsuite/gdb.base/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 /r 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"

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