public inbox for gdb-patches@sourceware.org
 help / color / mirror / Atom feed
* [PATCH v5] Add negative repeat count to 'x' command
@ 2016-06-02  8:52 Toshihito Kikuchi
  2016-06-03 10:54 ` Pedro Alves
  2016-08-08 14:45 ` Thomas Preudhomme
  0 siblings, 2 replies; 11+ messages in thread
From: Toshihito Kikuchi @ 2016-06-02  8:52 UTC (permalink / raw)
  To: gdb-patches; +Cc: Toshihito Kikuchi, Simon Marchi, Pedro Alves

This change adds support for specifying a negative repeat count to
all the formats of the 'x' command to examine memory backward.
A new testcase 'examine-backward' is added to cover this new feature.

Here's the example output from the new feature:

<format 'i'>
(gdb) bt
#0  Func1 (n=42, p=0x40432e "hogehoge") at main.cpp:5
#1  0x00000000004041fa in main (argc=1, argv=0x7fffffffdff8) at main.cpp:19
(gdb) x/-4i 0x4041fa
  0x4041e5 <main(int, char**)+11>: mov   %rsi,-0x10(%rbp)
  0x4041e9 <main(int, char**)+15>: lea   0x13e(%rip),%rsi
  0x4041f0 <main(int, char**)+22>: mov   $0x2a,%edi
  0x4041f5 <main(int, char**)+27>: callq 0x404147

<format 'x'>
(gdb) x/-4xw 0x404200
0x4041f0 <main(int, char**)+22>: 0x00002abf 0xff4de800 0x76e8ffff 0xb8ffffff
(gdb) x/-4
0x4041e0 <main(int, char**)+6>:  0x7d8910ec 0x758948fc 0x358d48f0 0x0000013e

gdb/ChangeLog:

	* NEWS: Mention that GDB now supports a negative repeat count in
	the 'x' command.
	* printcmd.c (decode_format): Allow '-' in the parameter
	"string_ptr" to accept a negative repeat count.
	(find_instruction_backward): New function.
	(read_memory_backward): New function.
	(integer_is_zero): New function.
	(find_string_backward): New function.
	(do_examine): Use new functions to examine memory backward.
	(_initialize_printcmd): Mention that 'x' command supports a negative
	repeat count.

gdb/doc/ChangeLog:

	* gdb.texinfo (Examining Memory): Document negative repeat
	count in the 'x' command.

gdb/testsuite/ChangeLog:

	* gdb.base/examine-backward.c: New file.
	* gdb.base/examine-backward.exp: New file.
---
 gdb/NEWS                                    |  14 ++
 gdb/doc/gdb.texinfo                         |  14 +-
 gdb/printcmd.c                              | 262 +++++++++++++++++++++-
 gdb/testsuite/gdb.base/examine-backward.c   | 106 +++++++++
 gdb/testsuite/gdb.base/examine-backward.exp | 324 ++++++++++++++++++++++++++++
 5 files changed, 717 insertions(+), 3 deletions(-)
 create mode 100644 gdb/testsuite/gdb.base/examine-backward.c
 create mode 100644 gdb/testsuite/gdb.base/examine-backward.exp

diff --git a/gdb/NEWS b/gdb/NEWS
index dce79a2..6b6cc4f 100644
--- a/gdb/NEWS
+++ b/gdb/NEWS
@@ -3,6 +3,20 @@
 
 *** Changes since GDB 7.11
 
+* GDB now supports a negative repeat count in the 'x' command to examine
+  memory backward from the given address.  For example:
+
+    (gdb) bt
+    #0  Func1 (n=42, p=0x40061c "hogehoge") at main.cpp:4
+    #1  0x400580 in main (argc=1, argv=0x7fffffffe5c8) at main.cpp:8
+    (gdb) x/-5i 0x0000000000400580
+       0x40056a <main(int, char**)+8>:      mov    %edi,-0x4(%rbp)
+       0x40056d <main(int, char**)+11>:     mov    %rsi,-0x10(%rbp)
+       0x400571 <main(int, char**)+15>:     mov    $0x40061c,%esi
+       0x400576 <main(int, char**)+20>:     mov    $0x2a,%edi
+       0x40057b <main(int, char**)+25>:
+        callq  0x400536 <Func1(int, char const*)>
+
 * Fortran: Support structures with fields of dynamic types and 
   arrays of dynamic types.
 
diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo
index 7e89003..12d0140 100644
--- a/gdb/doc/gdb.texinfo
+++ b/gdb/doc/gdb.texinfo
@@ -9295,7 +9295,8 @@ Several commands set convenient defaults for @var{addr}.
 @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.
+how much memory (counting by units @var{u}) to display.  If a negative
+number is specified, memory is examined backward from @var{addr}.
 @c This really is **decimal**; unaffected by 'set radix' as of GDB
 @c 4.1.2.
 
@@ -9350,6 +9351,10 @@ 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}).
 
+You can also specify a negative repeat count to examine memory backward
+from the given address.  For example, @samp{x/-3uh 0x54320} prints three
+halfwords (@code{h}) at @code{0x54314}, @code{0x54328}, and @code{0x5431c}.
+
 Since the letters indicating unit sizes are all distinct from the
 letters specifying output formats, you do not have to remember whether
 unit size or format comes first; either order works.  The output
@@ -9366,6 +9371,13 @@ follow the last instruction that is within the count.  The command
 @code{disassemble} gives an alternative way of inspecting machine
 instructions; see @ref{Machine Code,,Source and Machine Code}.
 
+If a negative repeat count is specified for the formats @samp{s} or @samp{i},
+the command displays null-terminated strings or instructions before the given
+address as many as the absolute value of the given number.  For the @samp{i}
+format, we use line number information in the debug info to accurately locate
+instruction boundaries while disassembling backward.  If line info is not
+available, the command stops examining memory with an error message.
+
 All the defaults for the arguments to @code{x} are designed to make it
 easy to continue scanning memory with minimal specifications each time
 you use @code{x}.  For example, after you have inspected three machine
diff --git a/gdb/printcmd.c b/gdb/printcmd.c
index f5c4211..d4a4b9e 100644
--- a/gdb/printcmd.c
+++ b/gdb/printcmd.c
@@ -186,8 +186,13 @@ decode_format (const char **string_ptr, int oformat, int osize)
   val.count = 1;
   val.raw = 0;
 
+  if (*p == '-')
+    {
+      val.count = -1;
+      p++;
+    }
   if (*p >= '0' && *p <= '9')
-    val.count = atoi (p);
+    val.count *= atoi (p);
   while (*p >= '0' && *p <= '9')
     p++;
 
@@ -785,6 +790,221 @@ print_address_demangle (const struct value_print_options *opts,
 }
 \f
 
+/* Find the address of the instruction that is INST_COUNT instructions before
+   the instruction at ADDR.
+   Since some architectures have variable-length instructions, we can't just
+   simply subtract INST_COUNT * INSN_LEN from ADDR.  Instead, we use line
+   number information to locate the nearest known instruction boundary,
+   and disassemble forward from there.  If we go out of the symbol range
+   during disassembling, we return the lowest address we've got so far and
+   set the number of instructions read to INST_READ.  */
+
+static CORE_ADDR
+find_instruction_backward (struct gdbarch *gdbarch, CORE_ADDR addr,
+                           int inst_count, int *inst_read)
+{
+  /* The vector PCS is used to store instruction addresses within
+     a pc range.  */
+  CORE_ADDR loop_start, loop_end, p;
+  VEC (CORE_ADDR) *pcs = NULL;
+  struct symtab_and_line sal;
+  struct cleanup *cleanup = make_cleanup (VEC_cleanup (CORE_ADDR), &pcs);
+
+  *inst_read = 0;
+  loop_start = loop_end = addr;
+
+  /* In each iteration of the outer loop, we get a pc range that ends before
+     LOOP_START, then we count and store every instruction address of the range
+     iterated in the loop.
+     If the number of instructions counted reaches INST_COUNT, return the
+     stored address that is located INST_COUNT instructions back from ADDR.
+     If INST_COUNT is not reached, we subtract the number of counted
+     instructions from INST_COUNT, and go to the next iteration.  */
+  do
+    {
+      VEC_truncate (CORE_ADDR, pcs, 0);
+      sal = find_pc_sect_line (loop_start, NULL, 1);
+      if (sal.line <= 0)
+        {
+          /* We reach here when line info is not available.  In this case,
+             we print a message and just exit the loop.  The return value
+             is calculated after the loop.  */
+          printf_filtered (_("No line number information available "
+                             "for address "));
+          wrap_here ("  ");
+          print_address (gdbarch, loop_start - 1, gdb_stdout);
+          printf_filtered ("\n");
+          break;
+        }
+
+      loop_end = loop_start;
+      loop_start = sal.pc;
+
+      /* This loop pushes instruction addresses in the range from
+         LOOP_START to LOOP_END.  */
+      for (p = loop_start; p < loop_end;)
+        {
+          VEC_safe_push (CORE_ADDR, pcs, p);
+          p += gdb_insn_length (gdbarch, p);
+        }
+
+      inst_count -= VEC_length (CORE_ADDR, pcs);
+      *inst_read += VEC_length (CORE_ADDR, pcs);
+    }
+  while (inst_count > 0);
+
+  /* After the loop, the vector PCS has instruction addresses of the last
+     source line we processed, and INST_COUNT has a negative value.
+     We return the address at the index of -INST_COUNT in the vector for
+     the reason below.
+     Let's assume the following instruction addresses and run 'x/-4i 0x400e'.
+       Line X of File
+          0x4000
+          0x4001
+          0x4005
+       Line Y of File
+          0x4009
+          0x400c
+       => 0x400e
+          0x4011
+     find_instruction_backward is called with INST_COUNT = 4 and expected to
+     return 0x4001.  When we reach here, INST_COUNT is set to -1 because
+     it was subtracted by 2 (from Line Y) and 3 (from Line X).  The value
+     4001 is located at the index 1 of the last iterated line (= Line X),
+     which is simply calculated by -INST_COUNT.
+     The case when the length of PCS is 0 means that we reached an area for
+     which line info is not available.  In such case, we return LOOP_START,
+     which was the lowest instruction address that had line info.  */
+  p = VEC_length (CORE_ADDR, pcs) > 0
+    ? VEC_index (CORE_ADDR, pcs, -inst_count)
+    : loop_start;
+
+  /* INST_READ includes all instruction addresses in a pc range.  Need to
+     exclude the beginning part up to the address we're returning.  That
+     is, exclude {0x4000} in the example above.  */
+  if (inst_count < 0)
+    *inst_read += inst_count;
+
+  do_cleanups (cleanup);
+  return p;
+}
+
+/* Backward read LEN bytes of target memory from address MEMADDR + LEN,
+   placing the results in GDB's memory from MYADDR + LEN.  Returns
+   a count of the bytes actually read.  */
+
+static int
+read_memory_backward (struct gdbarch *gdbarch,
+                      CORE_ADDR memaddr, gdb_byte *myaddr, int len)
+{
+  int errcode;
+  int nread;      /* Number of bytes actually read.  */
+
+  /* First try a complete read.  */
+  errcode = target_read_memory (memaddr, myaddr, len);
+  if (errcode == 0)
+    {
+      /* Got it all.  */
+      nread = len;
+    }
+  else
+    {
+      /* Loop, reading one byte at a time until we get as much as we can.  */
+      memaddr += len;
+      myaddr += len;
+      for (nread = 0; nread < len; ++nread)
+        {
+          errcode = target_read_memory (--memaddr, --myaddr, 1);
+          if (errcode != 0)
+            {
+              /* The read was unsuccessful, so exit the loop.  */
+              printf_filtered (_("Cannot access memory at address %s\n"),
+                               paddress (gdbarch, memaddr));
+              break;
+            }
+        }
+    }
+  return nread;
+}
+
+/* Returns true if X (which is LEN bytes wide) is the number zero.  */
+
+static int
+integer_is_zero (const gdb_byte *x, int len)
+{
+  int i = 0;
+
+  while (i < len && x[i] == 0)
+    ++i;
+  return (i == len);
+}
+
+/* Find the start address of a string in which ADDR is included.
+   Basically we search for '\0' and return the next address,
+   but if OPTIONS->PRINT_MAX is smaller than the length of a string,
+   we stop searching and return the address to print characters as many as
+   PRINT_MAX from the string.  */
+
+static CORE_ADDR
+find_string_backward (struct gdbarch *gdbarch,
+                      CORE_ADDR addr, int count, int char_size,
+                      const struct value_print_options *options,
+                      int *strings_counted)
+{
+  const int chunk_size = 0x20;
+  gdb_byte *buffer = NULL;
+  struct cleanup *cleanup = NULL;
+  int read_error = 0;
+  int chars_read = 0;
+  int chars_to_read = chunk_size;
+  int chars_counted = 0;
+  int count_original = count;
+  CORE_ADDR string_start_addr = addr;
+
+  gdb_assert (char_size == 1 || char_size == 2 || char_size == 4);
+  buffer = (gdb_byte *) xmalloc (chars_to_read * char_size);
+  cleanup = make_cleanup (xfree, buffer);
+  while (count > 0 && read_error == 0)
+    {
+      int i;
+
+      addr -= chars_to_read * char_size;
+      chars_read = read_memory_backward (gdbarch, addr, buffer,
+                                         chars_to_read * char_size);
+      chars_read /= char_size;
+      read_error = (chars_read == chars_to_read) ? 0 : 1;
+      /* Searching for '\0' from the end of buffer in backward direction.  */
+      for (i = 0; i < chars_read && count > 0 ; ++i, ++chars_counted)
+        {
+          int offset = (chars_to_read - i - 1) * char_size;
+
+          if (integer_is_zero (buffer + offset, char_size)
+              || chars_counted == options->print_max)
+            {
+              /* Found '\0' or reached print_max.  As OFFSET is the offset to
+                 '\0', we add CHAR_SIZE to return the start address of
+                 a string.  */
+              --count;
+              string_start_addr = addr + offset + char_size;
+              chars_counted = 0;
+            }
+        }
+    }
+
+  /* Update STRINGS_COUNTED with the actual number of loaded strings.  */
+  *strings_counted = count_original - count;
+
+  if (read_error != 0)
+    {
+      /* In error case, STRING_START_ADDR is pointing to the string that
+         was last successfully loaded.  Rewind the partially loaded string.  */
+      string_start_addr -= chars_counted * char_size;
+    }
+
+  do_cleanups (cleanup);
+  return string_start_addr;
+}
+
 /* Examine data at address ADDR in format FMT.
    Fetch it from memory and print on gdb_stdout.  */
 
@@ -798,6 +1018,8 @@ do_examine (struct format_data fmt, struct gdbarch *gdbarch, CORE_ADDR addr)
   int i;
   int maxelts;
   struct value_print_options opts;
+  int need_to_update_next_address = 0;
+  CORE_ADDR addr_rewound = 0;
 
   format = fmt.format;
   size = fmt.size;
@@ -868,6 +1090,38 @@ do_examine (struct format_data fmt, struct gdbarch *gdbarch, CORE_ADDR addr)
 
   get_formatted_print_options (&opts, format);
 
+  if (count < 0)
+    {
+      /* This is the negative repeat count case.
+         We rewind the address based on the given repeat count and format,
+         then examine memory from there in forward direction.  */
+
+      count = -count;
+      if (format == 'i')
+        {
+          next_address = find_instruction_backward (gdbarch, addr, count,
+                                                    &count);
+        }
+      else if (format == 's')
+        {
+          next_address = find_string_backward (gdbarch, addr, count,
+                                               TYPE_LENGTH (val_type),
+                                               &opts, &count);
+        }
+      else
+        {
+          next_address = addr - count * TYPE_LENGTH (val_type);
+        }
+
+      /* The following call to print_formatted updates next_address in every
+         iteration.  In backward case, we store the start address here
+         and update next_address with it before exiting the function.  */
+      addr_rewound = (format == 's'
+                      ? next_address - TYPE_LENGTH (val_type)
+                      : next_address);
+      need_to_update_next_address = 1;
+    }
+
   /* Print as many objects as specified in COUNT, at most maxelts per line,
      with the address of the next one at the start of each line.  */
 
@@ -913,6 +1167,9 @@ do_examine (struct format_data fmt, struct gdbarch *gdbarch, CORE_ADDR addr)
       printf_filtered ("\n");
       gdb_flush (gdb_stdout);
     }
+
+  if (need_to_update_next_address)
+    next_address = addr_rewound;
 }
 \f
 static void
@@ -2522,7 +2779,8 @@ Format letters are o(octal), x(hex), d(decimal), u(unsigned decimal),\n\
   and z(hex, zero padded on the left).\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\
+according to the format.  If a negative number is specified, memory is\n\
+examined backward from the address.\n\n\
 Defaults for format and size letters are those previously used.\n\
 Default count is 1.  Default address is following last thing printed\n\
 with this command or \"print\"."));
diff --git a/gdb/testsuite/gdb.base/examine-backward.c b/gdb/testsuite/gdb.base/examine-backward.c
new file mode 100644
index 0000000..b338503
--- /dev/null
+++ b/gdb/testsuite/gdb.base/examine-backward.c
@@ -0,0 +1,106 @@
+/* This testcase is part of GDB, the GNU debugger.
+
+   Copyright 2015-2016 Free Software Foundation, Inc.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+/*
+Define TestStrings, TestStringsH, and TestStringsW to test utf8, utf16,
+and utf32 strings respectively.
+To avoid compile errors due to old compiler mode, we don't use string
+literals.  The content of each array is the same as followings:
+
+  const char TestStrings[] = {
+      "ABCD"
+      "EFGHIJKLMNOPQRSTUVWXYZ\0"
+      "\0"
+      "\0"
+      "\u307B\u3052\u307B\u3052\0"
+      "012345678901234567890123456789\0"
+      "!!!!!!\0"
+  };
+*/
+
+const char TestStrings[] = {
+  0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48,
+  0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 0x50,
+  0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58,
+  0x59, 0x5a, 0x00, 0x00, 0x00, 0xe3, 0x81, 0xbb,
+  0xe3, 0x81, 0x92, 0xe3, 0x81, 0xbb, 0xe3, 0x81,
+  0x92, 0x00, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35,
+  0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, 0x33,
+  0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31,
+  0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39,
+  0x00, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x00,
+  0x00
+};
+
+const short TestStringsH[] = {
+  0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047, 0x0048,
+  0x0049, 0x004a, 0x004b, 0x004c, 0x004d, 0x004e, 0x004f, 0x0050,
+  0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057, 0x0058,
+  0x0059, 0x005a, 0x0000, 0x0000, 0x0000, 0x307b, 0x3052, 0x307b,
+  0x3052, 0x0000, 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035,
+  0x0036, 0x0037, 0x0038, 0x0039, 0x0030, 0x0031, 0x0032, 0x0033,
+  0x0034, 0x0035, 0x0036, 0x0037, 0x0038, 0x0039, 0x0030, 0x0031,
+  0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037, 0x0038, 0x0039,
+  0x0000, 0x0021, 0x0021, 0x0021, 0x0021, 0x0021, 0x0021, 0x0000,
+  0x0000
+};
+
+const int TestStringsW[] = {
+  0x00000041, 0x00000042, 0x00000043, 0x00000044,
+  0x00000045, 0x00000046, 0x00000047, 0x00000048,
+  0x00000049, 0x0000004a, 0x0000004b, 0x0000004c,
+  0x0000004d, 0x0000004e, 0x0000004f, 0x00000050,
+  0x00000051, 0x00000052, 0x00000053, 0x00000054,
+  0x00000055, 0x00000056, 0x00000057, 0x00000058,
+  0x00000059, 0x0000005a, 0x00000000, 0x00000000,
+  0x00000000, 0x0000307b, 0x00003052, 0x0000307b,
+  0x00003052, 0x00000000, 0x00000030, 0x00000031,
+  0x00000032, 0x00000033, 0x00000034, 0x00000035,
+  0x00000036, 0x00000037, 0x00000038, 0x00000039,
+  0x00000030, 0x00000031, 0x00000032, 0x00000033,
+  0x00000034, 0x00000035, 0x00000036, 0x00000037,
+  0x00000038, 0x00000039, 0x00000030, 0x00000031,
+  0x00000032, 0x00000033, 0x00000034, 0x00000035,
+  0x00000036, 0x00000037, 0x00000038, 0x00000039,
+  0x00000000, 0x00000021, 0x00000021, 0x00000021,
+  0x00000021, 0x00000021, 0x00000021, 0x00000000,
+  0x00000000
+};
+
+int
+main (void)
+{
+  /* Backward disassemble test requires at least 20 instructions in
+     this function.  Adding a simple bubble sort.  */
+  int i, j;
+  int n[] = {3, 1, 4, 1, 5, 9};
+  int len = sizeof (n) / sizeof (n[0]);
+
+  for (i = 0; i < len - 1; ++i)
+    {
+      for (j = i; j < len; ++j)
+        {
+          if (n[j] < n[i])
+            {
+              int tmp = n[i];
+              n[i] = n[j];
+              n[j] = tmp;
+            }
+        }
+    }
+  return 42;
+}
diff --git a/gdb/testsuite/gdb.base/examine-backward.exp b/gdb/testsuite/gdb.base/examine-backward.exp
new file mode 100644
index 0000000..e03cbfd
--- /dev/null
+++ b/gdb/testsuite/gdb.base/examine-backward.exp
@@ -0,0 +1,324 @@
+# Copyright 2015-2016 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+# This testsuite is to test examining memory backward by specifying a negative
+# number in the 'x' command.
+
+standard_testfile
+if { [prepare_for_testing "failed to prepare for examine-backward" \
+        ${testfile} ${srcfile}] } {
+    return -1
+}
+
+if ![runto_main] {
+    untested "could not run to main"
+    return -1
+}
+
+proc get_first_mapped_address {} {
+    global gdb_prompt
+
+    set addr "0"
+    gdb_test_multiple "info proc mappings" "info proc mappings" {
+        -re "objfile\[\r\n\t \]+(0x\[0-9a-fA-F\]+).*\[\r\n\]*$gdb_prompt $" {
+            set addr $expect_out(1,string)
+        }
+        -re "$gdb_prompt $" {
+            unsupported "Current target does not support 'info proc mappings'"
+        }
+    }
+    return ${addr}
+}
+
+with_test_prefix "invalid format" {
+    gdb_test "x/- 10xb main" "Invalid number \"10xb\"\." \
+        "a whitespace after a leading hyphen"
+    gdb_test "x/--10xb main" "Invalid number \"10xb\"\." \
+        "double hyphen"
+    gdb_test "x/-a10xb main" "Invalid number \"10xb\"\." \
+        "an alphabet after a leading hyphen"
+    gdb_test_no_output "x/-0i main" "zero with backward disassemble"
+    gdb_test_no_output "x/-0sh main" "zero with backward examine string"
+}
+
+with_test_prefix "memory page boundary" {
+    set boundary [get_first_mapped_address]
+    if {![is_address_zero_readable] && $boundary != 0} {
+        gdb_test_no_output "set print elements 0"
+        gdb_test_sequence "x/3s ${boundary}" "take 3 strings forward" {
+            "0x"
+            "0x"
+            "0x"
+        }
+        gdb_test_sequence "x/-4s" "take 4 strings backward" {
+            "Cannot access memory at address 0x"
+            "0x"
+            "0x"
+            "0x"
+        }
+        gdb_test_sequence "x/3s ${boundary}" "take 3 strings forward again" {
+            "0x"
+            "0x"
+            "0x"
+        }
+        gdb_test_sequence "x/-3s" "take 3 strings backward" {
+            "Cannot access memory at address 0x"
+            "0x"
+            "0x"
+            "0x"
+        }
+    }
+}
+
+with_test_prefix "address zero boundary" {
+    if {[is_address_zero_readable]} {
+        set address_zero "0x0"
+        set byte "\t0x\[0-9a-f\]+"
+        gdb_test "x/3xb ${address_zero}" \
+            "0x\[0-9a-f\]+00.*:${byte}${byte}${byte}" \
+            "examine 3 bytes forward from ${address_zero}"
+        gdb_test "x/-6x" \
+            "0x\[0-9a-f\]+fd.*:${byte}${byte}${byte}${byte}${byte}${byte}" \
+            "examine 6 bytes backward"
+        gdb_test "x/-3x ${address_zero}" \
+            "0x\[0-9a-f\]+fd.*:${byte}${byte}${byte}" \
+            "examine 3 bytes backward from ${address_zero}"
+    }
+}
+
+gdb_test_no_output "set charset ASCII"
+
+with_test_prefix "char-width=1, print-max=20" {
+    gdb_test_no_output "set print elements 20"
+    gdb_test_sequence "x/6s &TestStrings" "take 6 strings forward" {
+        "\"ABCDEFGHIJKLMNOPQRST\"\.\.\."
+        "\"UVWXYZ\""
+        "\"\""
+        "\"\""
+        "\"[^\"]+\""
+        "\"01234567890123456789\"\.\.\."
+    }
+    gdb_test "x/-1xb" "0x39" "take 1 char backward"
+    gdb_test_sequence "x/-6s" "take 6 strings backward" {
+        "\"ABCDEFGHIJKLMNOPQRST\"\.\.\."
+        "\"UVWXYZ\""
+        "\"\""
+        "\"\""
+        "\"[^\"]+\""
+        "\"01234567890123456789\"\.\.\."
+    }
+    gdb_test_sequence "x/6s &TestStrings" "take 6 strings forward again" {
+        "\"ABCDEFGHIJKLMNOPQRST\"\.\.\."
+        "\"UVWXYZ\""
+        "\"\""
+        "\"\""
+        "\"[^\"]+\""
+        "\"01234567890123456789\"\.\.\."
+    }
+    gdb_test "x/-xb" "0x39" "take 1 char backward again"
+    gdb_test "x/-s" "\"01234567890123456789\"\.\.\." \
+        "take 1 string backward (1/6)"
+    gdb_test "x/-s" "\".+\"" \
+        "take 1 string backward (2/6)"
+    gdb_test "x/-s" "\"\"" \
+        "take 1 string backward (3/6)"
+    gdb_test "x/-s" "\"\"" \
+        "take 1 string backward (4/6)"
+    gdb_test "x/-s" "\"GHIJKLMNOPQRSTUVWXYZ\"" \
+        "take 1 string backward (5/6)"
+    gdb_test "x/-s" "\"ABCDEFGHIJKLMNOPQRST\"\.\.\." \
+        "take 1 string backward (6/6)"
+}
+
+with_test_prefix "char-width=2, print-max=20" {
+    gdb_test_no_output "set print elements 20"
+    gdb_test_sequence "x/6sh &TestStringsH" "take 6 strings forward" {
+        "u\"ABCDEFGHIJKLMNOPQRST\"\.\.\."
+        "u\"UVWXYZ\""
+        "u\"\""
+        "u\"\""
+        "u\"[^\"]+\""
+        "u\"01234567890123456789\"\.\.\."
+    }
+    gdb_test "x/-1xh" "0x0039" "take 1 char backward"
+    gdb_test_sequence "x/-6sh" "take 6 strings backward" {
+        "u\"ABCDEFGHIJKLMNOPQRST\"\.\.\."
+        "u\"UVWXYZ\""
+        "u\"\""
+        "u\"\""
+        "u\"[^\"]+\""
+        "u\"01234567890123456789\"\.\.\."
+    }
+    gdb_test_sequence "x/6sh &TestStringsH" "take 6 strings forward again" {
+        "u\"ABCDEFGHIJKLMNOPQRST\"\.\.\."
+        "u\"UVWXYZ\""
+        "u\"\""
+        "u\"\""
+        "u\"[^\"]+\""
+        "u\"01234567890123456789\"\.\.\."
+    }
+    gdb_test "x/-xh" "0x0039" "take 1 char backward again"
+    gdb_test "x/-sh" "u\"01234567890123456789\"\.\.\." \
+        "take 1 string backward (1/6)"
+    gdb_test "x/-sh" "u\".+\"" \
+        "take 1 string backward (2/6)"
+    gdb_test "x/-sh" "u\"\"" \
+        "take 1 string backward (3/6)"
+    gdb_test "x/-sh" "u\"\"" \
+        "take 1 string backward (4/6)"
+    gdb_test "x/-sh" "u\"GHIJKLMNOPQRSTUVWXYZ\"" \
+        "take 1 string backward (5/6)"
+    gdb_test "x/-sh" "u\"ABCDEFGHIJKLMNOPQRST\"\.\.\." \
+        "take 1 string backward (6/6)"
+}
+
+with_test_prefix "char-width=4, print-max=20" {
+    gdb_test_no_output "set print elements 20"
+    gdb_test_sequence "x/6sw &TestStringsW" "take 6 strings forward" {
+        "U\"ABCDEFGHIJKLMNOPQRST\"\.\.\."
+        "U\"UVWXYZ\""
+        "U\"\""
+        "U\"\""
+        "U\"[^\"]+\""
+        "U\"01234567890123456789\"\.\.\."
+    }
+    gdb_test "x/-1xw" "0x00000039" "take 1 char backward"
+    gdb_test_sequence "x/-6sw" "take 6 strings backward" {
+        "U\"ABCDEFGHIJKLMNOPQRST\"\.\.\."
+        "U\"UVWXYZ\""
+        "U\"\""
+        "U\"\""
+        "U\"[^\"]+\""
+        "U\"01234567890123456789\"\.\.\."
+    }
+    gdb_test_sequence "x/6sw &TestStringsW" "take 6 strings forward again" {
+        "U\"ABCDEFGHIJKLMNOPQRST\"\.\.\."
+        "U\"UVWXYZ\""
+        "U\"\""
+        "U\"\""
+        "U\"[^\"]+\""
+        "U\"01234567890123456789\"\.\.\."
+    }
+    gdb_test "x/-xw" "0x00000039" "take 1 char backward again"
+    gdb_test "x/-sw" "U\"01234567890123456789\"\.\.\." \
+        "take 1 string backward (1/6)"
+    gdb_test "x/-sw" "U\".+\"" \
+        "take 1 string backward (2/6)"
+    gdb_test "x/-sw" "U\"\"" \
+        "take 1 string backward (3/6)"
+    gdb_test "x/-sw" "U\"\"" \
+        "take 1 string backward (4/6)"
+    gdb_test "x/-sw" "U\"GHIJKLMNOPQRSTUVWXYZ\"" \
+        "take 1 string backward (5/6)"
+    gdb_test "x/-sw" "U\"ABCDEFGHIJKLMNOPQRST\"\.\.\." \
+        "take 1 string backward (6/6)"
+}
+
+with_test_prefix "char-width=2, print-max=0" {
+    gdb_test_no_output "set print elements 0"
+    gdb_test_sequence "x/6sh &TestStringsH" "take 6 strings forward" {
+        "u\"ABCDEFGHIJKLMNOPQRSTUVWXYZ\""
+        "u\"\""
+        "u\"\""
+        "u\"\\\\x307b\\\\x3052\\\\x307b\\\\x3052\""
+        "u\"012345678901234567890123456789\""
+        "u\"!!!!!!\""
+    }
+    gdb_test "x/-4xh" "0x0021\[\t \]+0x0021\[\t \]+0x0021\[\t \]+0x0000" \
+        "take 4 characters backward"
+    gdb_test_sequence "x/-6sh" "take 6 strings backward" {
+        "u\"ABCDEFGHIJKLMNOPQRSTUVWXYZ\""
+        "u\"\""
+        "u\"\""
+        "u\"[^\"]+\""
+        "u\"012345678901234567890123456789\""
+        "u\"!!!!!!\""
+    }
+    gdb_test_sequence "x/6sh &TestStringsH" "take 6 strings forward again" {
+        "u\"ABCDEFGHIJKLMNOPQRSTUVWXYZ\""
+        "u\"\""
+        "u\"\""
+        "u\"\\\\x307b\\\\x3052\\\\x307b\\\\x3052\""
+        "u\"012345678901234567890123456789\""
+        "u\"!!!!!!\""
+    }
+    gdb_test "x/-xh" "0x0000" "take 1 char backward"
+    gdb_test "x/-sh" "u\"!!!!!!\"" \
+        "take 1 string backward (1/6)"
+    gdb_test "x/-sh" "u\"012345678901234567890123456789\"" \
+        "take 1 string backward (2/6)"
+    gdb_test "x/-sh" "u\".+\"" \
+        "take 1 string backward (3/6)"
+    gdb_test "x/-sh" "u\"\"" \
+        "take 1 string backward (4/6)"
+    gdb_test "x/-sh" "u\"\"" \
+        "take 1 string backward (5/6)"
+    gdb_test "x/-sh" "u\"ABCDEFGHIJKLMNOPQRSTUVWXYZ\"" \
+        "take 1 string backward (6/6)"
+}
+
+with_test_prefix "char-width=1, print-max=4" {
+    gdb_test_no_output "set print elements 4"
+    gdb_test_sequence "x/9s &TestStrings" "take 9 strings forward" {
+        "\"ABCD\"\.\.\."
+        "\"EFGH\"\.\.\."
+        "\"IJKL\"\.\.\."
+        "\"MNOP\"\.\.\."
+        "\"QRST\"\.\.\."
+        "\"UVWX\"\.\.\."
+        "\"YZ\""
+        "\"\""
+        "\"\""
+    }
+    gdb_test "x/-xb" "0x00" "take 1 byte backward"
+    gdb_test_sequence "x/-4s" "take 4 strings backward (1/2)" {
+        "\"TUVW\"\.\.\."
+        "\"XYZ\""
+        "\"\""
+        "\"\""
+    }
+    gdb_test_sequence "x/-4s" "take 4 strings backward (2/2)" {
+        "\"CDEF\"\.\.\."
+        "\"GHIJ\"\.\.\."
+        "\"KLMN\"\.\.\."
+        "\"OPQR\"\.\.\."
+    }
+}
+
+with_test_prefix "backward disassemble general" {
+    set length_to_examine {1 2 3 4 10}
+    set disassmbly {}
+
+    gdb_test "x/i main" "0x\[0-9a-fA-F\]+ <main>:\t.*" \
+        "move the current position to main (x/i)"
+    gdb_test "x/-i" "0x\[0-9a-fA-F\]+ <main>:\t.*" \
+        "move the current position to main (x/-i)"
+    for {set i 0} {$i < [llength $length_to_examine]} {incr i} {
+        set len [lindex $length_to_examine $i]
+        set instructions [capture_command_output "x/${len}i" ""]
+        lappend disassmbly $instructions
+    }
+    for {set i 0} {$i < [llength $length_to_examine]} {incr i} {
+        set idx [expr [llength $length_to_examine] - $i - 1]
+        set len [lindex $length_to_examine $idx]
+        set actual [capture_command_output "x/-${len}i" ""]
+        set expected [lindex $disassmbly $idx]
+        if {$actual == $expected} {
+            pass "inst:$idx"
+        } else {
+            fail "inst:$idx"
+        }
+    }
+}
-- 
2.7.4

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

* Re: [PATCH v5] Add negative repeat count to 'x' command
  2016-06-02  8:52 [PATCH v5] Add negative repeat count to 'x' command Toshihito Kikuchi
@ 2016-06-03 10:54 ` Pedro Alves
  2016-06-10  6:02   ` Toshihito Kikuchi
  2016-08-08 14:45 ` Thomas Preudhomme
  1 sibling, 1 reply; 11+ messages in thread
From: Pedro Alves @ 2016-06-03 10:54 UTC (permalink / raw)
  To: Toshihito Kikuchi, gdb-patches; +Cc: Simon Marchi

This is OK.  Please push.

Thanks,
Pedro Alves

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

* Re: [PATCH v5] Add negative repeat count to 'x' command
  2016-06-03 10:54 ` Pedro Alves
@ 2016-06-10  6:02   ` Toshihito Kikuchi
  0 siblings, 0 replies; 11+ messages in thread
From: Toshihito Kikuchi @ 2016-06-10  6:02 UTC (permalink / raw)
  To: Pedro Alves, gdb-patches; +Cc: Simon Marchi

Thank you for your great help.  This is in.

On 2016-06-03 03:54 AM, Pedro Alves wrote:
> This is OK.  Please push.
> 
> Thanks,
> Pedro Alves
> 

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

* Re: [PATCH v5] Add negative repeat count to 'x' command
  2016-06-02  8:52 [PATCH v5] Add negative repeat count to 'x' command Toshihito Kikuchi
  2016-06-03 10:54 ` Pedro Alves
@ 2016-08-08 14:45 ` Thomas Preudhomme
  2016-08-11  0:00   ` Pedro Alves
  1 sibling, 1 reply; 11+ messages in thread
From: Thomas Preudhomme @ 2016-08-08 14:45 UTC (permalink / raw)
  To: Toshihito Kikuchi, gdb-patches; +Cc: Simon Marchi, Pedro Alves

Sorry for the late reply but I noticed an issue in the tests added by 
this patch for arm-none-eabi:


FAIL: gdb.base/examine-backward.exp: address zero boundary: examine 3 
bytes forward from 0x0
NA->FAIL: gdb.base/examine-backward.exp char-width=1, print-max=20 take 
1 string backward (6/6)
NA->FAIL: gdb.base/examine-backward.exp char-width=1, print-max=20 take 
6 strings backward (pattern 1)


The first one is a testism:

we match for: 0x\[0-9a-f\]+00.*:${byte}${byte}${byte}
but we get: 0x0:    0x7f    0x45    0x4c

I'd thus suggest to match 0x\(\[0-9a-f\]+0\)?0 instead, with the right 
amount of escaping (I don't know whether ? needs escaping and why + does 
not need escaping in current pattern).


The other two seems like genuine errors. take 6 strings backward 
(pattern 1) gives:

gdb_expect_list pattern: /"ABCDEFGHIJKLMNOPQRST".../
x/-6s^M
0x9aff <_fini+2>: "\277\370\274\b\274\236FpGABCDEFGHIJK"...^M
0x9b13 <TestStrings+11>:        "LMNOPQRSTUVWXYZ"^M
0x9b23 <TestStrings+27>:        ""^M
0x9b24 <TestStrings+28>:        ""^M
0x9b25 <TestStrings+29>: 
"\343\201\273\343\201\222\343\201\273\343\201\222"^M
0x9b32 <TestStrings+42>:        "01234567890123456789"...^M
(gdb) FAIL: gdb.base/examine-backward.exp: char-width=1, print-max=20: 
take 6 strings backward (pattern 1)


take 1 string backward (6/6) gives:

0x9aff <_fini+2>: "\277\370\274\b\274\236FpGABCDEFGHIJK"...


Please let me know what I can do to help diagnose this error.


Best regards,


Thomas


On 02/06/16 09:49, Toshihito Kikuchi wrote:
> This change adds support for specifying a negative repeat count to
> all the formats of the 'x' command to examine memory backward.
> A new testcase 'examine-backward' is added to cover this new feature.
>
> Here's the example output from the new feature:
>
> <format 'i'>
> (gdb) bt
> #0  Func1 (n=42, p=0x40432e "hogehoge") at main.cpp:5
> #1  0x00000000004041fa in main (argc=1, argv=0x7fffffffdff8) at main.cpp:19
> (gdb) x/-4i 0x4041fa
>    0x4041e5 <main(int, char**)+11>: mov   %rsi,-0x10(%rbp)
>    0x4041e9 <main(int, char**)+15>: lea   0x13e(%rip),%rsi
>    0x4041f0 <main(int, char**)+22>: mov   $0x2a,%edi
>    0x4041f5 <main(int, char**)+27>: callq 0x404147
>
> <format 'x'>
> (gdb) x/-4xw 0x404200
> 0x4041f0 <main(int, char**)+22>: 0x00002abf 0xff4de800 0x76e8ffff 0xb8ffffff
> (gdb) x/-4
> 0x4041e0 <main(int, char**)+6>:  0x7d8910ec 0x758948fc 0x358d48f0 0x0000013e
>
> gdb/ChangeLog:
>
> 	* NEWS: Mention that GDB now supports a negative repeat count in
> 	the 'x' command.
> 	* printcmd.c (decode_format): Allow '-' in the parameter
> 	"string_ptr" to accept a negative repeat count.
> 	(find_instruction_backward): New function.
> 	(read_memory_backward): New function.
> 	(integer_is_zero): New function.
> 	(find_string_backward): New function.
> 	(do_examine): Use new functions to examine memory backward.
> 	(_initialize_printcmd): Mention that 'x' command supports a negative
> 	repeat count.
>
> gdb/doc/ChangeLog:
>
> 	* gdb.texinfo (Examining Memory): Document negative repeat
> 	count in the 'x' command.
>
> gdb/testsuite/ChangeLog:
>
> 	* gdb.base/examine-backward.c: New file.
> 	* gdb.base/examine-backward.exp: New file.
> ---
>   gdb/NEWS                                    |  14 ++
>   gdb/doc/gdb.texinfo                         |  14 +-
>   gdb/printcmd.c                              | 262 +++++++++++++++++++++-
>   gdb/testsuite/gdb.base/examine-backward.c   | 106 +++++++++
>   gdb/testsuite/gdb.base/examine-backward.exp | 324 ++++++++++++++++++++++++++++
>   5 files changed, 717 insertions(+), 3 deletions(-)
>   create mode 100644 gdb/testsuite/gdb.base/examine-backward.c
>   create mode 100644 gdb/testsuite/gdb.base/examine-backward.exp
>
> diff --git a/gdb/NEWS b/gdb/NEWS
> index dce79a2..6b6cc4f 100644
> --- a/gdb/NEWS
> +++ b/gdb/NEWS
> @@ -3,6 +3,20 @@
>   
>   *** Changes since GDB 7.11
>   
> +* GDB now supports a negative repeat count in the 'x' command to examine
> +  memory backward from the given address.  For example:
> +
> +    (gdb) bt
> +    #0  Func1 (n=42, p=0x40061c "hogehoge") at main.cpp:4
> +    #1  0x400580 in main (argc=1, argv=0x7fffffffe5c8) at main.cpp:8
> +    (gdb) x/-5i 0x0000000000400580
> +       0x40056a <main(int, char**)+8>:      mov    %edi,-0x4(%rbp)
> +       0x40056d <main(int, char**)+11>:     mov    %rsi,-0x10(%rbp)
> +       0x400571 <main(int, char**)+15>:     mov    $0x40061c,%esi
> +       0x400576 <main(int, char**)+20>:     mov    $0x2a,%edi
> +       0x40057b <main(int, char**)+25>:
> +        callq  0x400536 <Func1(int, char const*)>
> +
>   * Fortran: Support structures with fields of dynamic types and
>     arrays of dynamic types.
>   
> diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo
> index 7e89003..12d0140 100644
> --- a/gdb/doc/gdb.texinfo
> +++ b/gdb/doc/gdb.texinfo
> @@ -9295,7 +9295,8 @@ Several commands set convenient defaults for @var{addr}.
>   @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.
> +how much memory (counting by units @var{u}) to display.  If a negative
> +number is specified, memory is examined backward from @var{addr}.
>   @c This really is **decimal**; unaffected by 'set radix' as of GDB
>   @c 4.1.2.
>   
> @@ -9350,6 +9351,10 @@ 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}).
>   
> +You can also specify a negative repeat count to examine memory backward
> +from the given address.  For example, @samp{x/-3uh 0x54320} prints three
> +halfwords (@code{h}) at @code{0x54314}, @code{0x54328}, and @code{0x5431c}.
> +
>   Since the letters indicating unit sizes are all distinct from the
>   letters specifying output formats, you do not have to remember whether
>   unit size or format comes first; either order works.  The output
> @@ -9366,6 +9371,13 @@ follow the last instruction that is within the count.  The command
>   @code{disassemble} gives an alternative way of inspecting machine
>   instructions; see @ref{Machine Code,,Source and Machine Code}.
>   
> +If a negative repeat count is specified for the formats @samp{s} or @samp{i},
> +the command displays null-terminated strings or instructions before the given
> +address as many as the absolute value of the given number.  For the @samp{i}
> +format, we use line number information in the debug info to accurately locate
> +instruction boundaries while disassembling backward.  If line info is not
> +available, the command stops examining memory with an error message.
> +
>   All the defaults for the arguments to @code{x} are designed to make it
>   easy to continue scanning memory with minimal specifications each time
>   you use @code{x}.  For example, after you have inspected three machine
> diff --git a/gdb/printcmd.c b/gdb/printcmd.c
> index f5c4211..d4a4b9e 100644
> --- a/gdb/printcmd.c
> +++ b/gdb/printcmd.c
> @@ -186,8 +186,13 @@ decode_format (const char **string_ptr, int oformat, int osize)
>     val.count = 1;
>     val.raw = 0;
>   
> +  if (*p == '-')
> +    {
> +      val.count = -1;
> +      p++;
> +    }
>     if (*p >= '0' && *p <= '9')
> -    val.count = atoi (p);
> +    val.count *= atoi (p);
>     while (*p >= '0' && *p <= '9')
>       p++;
>   
> @@ -785,6 +790,221 @@ print_address_demangle (const struct value_print_options *opts,
>   }
>   \f
>   
> +/* Find the address of the instruction that is INST_COUNT instructions before
> +   the instruction at ADDR.
> +   Since some architectures have variable-length instructions, we can't just
> +   simply subtract INST_COUNT * INSN_LEN from ADDR.  Instead, we use line
> +   number information to locate the nearest known instruction boundary,
> +   and disassemble forward from there.  If we go out of the symbol range
> +   during disassembling, we return the lowest address we've got so far and
> +   set the number of instructions read to INST_READ.  */
> +
> +static CORE_ADDR
> +find_instruction_backward (struct gdbarch *gdbarch, CORE_ADDR addr,
> +                           int inst_count, int *inst_read)
> +{
> +  /* The vector PCS is used to store instruction addresses within
> +     a pc range.  */
> +  CORE_ADDR loop_start, loop_end, p;
> +  VEC (CORE_ADDR) *pcs = NULL;
> +  struct symtab_and_line sal;
> +  struct cleanup *cleanup = make_cleanup (VEC_cleanup (CORE_ADDR), &pcs);
> +
> +  *inst_read = 0;
> +  loop_start = loop_end = addr;
> +
> +  /* In each iteration of the outer loop, we get a pc range that ends before
> +     LOOP_START, then we count and store every instruction address of the range
> +     iterated in the loop.
> +     If the number of instructions counted reaches INST_COUNT, return the
> +     stored address that is located INST_COUNT instructions back from ADDR.
> +     If INST_COUNT is not reached, we subtract the number of counted
> +     instructions from INST_COUNT, and go to the next iteration.  */
> +  do
> +    {
> +      VEC_truncate (CORE_ADDR, pcs, 0);
> +      sal = find_pc_sect_line (loop_start, NULL, 1);
> +      if (sal.line <= 0)
> +        {
> +          /* We reach here when line info is not available.  In this case,
> +             we print a message and just exit the loop.  The return value
> +             is calculated after the loop.  */
> +          printf_filtered (_("No line number information available "
> +                             "for address "));
> +          wrap_here ("  ");
> +          print_address (gdbarch, loop_start - 1, gdb_stdout);
> +          printf_filtered ("\n");
> +          break;
> +        }
> +
> +      loop_end = loop_start;
> +      loop_start = sal.pc;
> +
> +      /* This loop pushes instruction addresses in the range from
> +         LOOP_START to LOOP_END.  */
> +      for (p = loop_start; p < loop_end;)
> +        {
> +          VEC_safe_push (CORE_ADDR, pcs, p);
> +          p += gdb_insn_length (gdbarch, p);
> +        }
> +
> +      inst_count -= VEC_length (CORE_ADDR, pcs);
> +      *inst_read += VEC_length (CORE_ADDR, pcs);
> +    }
> +  while (inst_count > 0);
> +
> +  /* After the loop, the vector PCS has instruction addresses of the last
> +     source line we processed, and INST_COUNT has a negative value.
> +     We return the address at the index of -INST_COUNT in the vector for
> +     the reason below.
> +     Let's assume the following instruction addresses and run 'x/-4i 0x400e'.
> +       Line X of File
> +          0x4000
> +          0x4001
> +          0x4005
> +       Line Y of File
> +          0x4009
> +          0x400c
> +       => 0x400e
> +          0x4011
> +     find_instruction_backward is called with INST_COUNT = 4 and expected to
> +     return 0x4001.  When we reach here, INST_COUNT is set to -1 because
> +     it was subtracted by 2 (from Line Y) and 3 (from Line X).  The value
> +     4001 is located at the index 1 of the last iterated line (= Line X),
> +     which is simply calculated by -INST_COUNT.
> +     The case when the length of PCS is 0 means that we reached an area for
> +     which line info is not available.  In such case, we return LOOP_START,
> +     which was the lowest instruction address that had line info.  */
> +  p = VEC_length (CORE_ADDR, pcs) > 0
> +    ? VEC_index (CORE_ADDR, pcs, -inst_count)
> +    : loop_start;
> +
> +  /* INST_READ includes all instruction addresses in a pc range.  Need to
> +     exclude the beginning part up to the address we're returning.  That
> +     is, exclude {0x4000} in the example above.  */
> +  if (inst_count < 0)
> +    *inst_read += inst_count;
> +
> +  do_cleanups (cleanup);
> +  return p;
> +}
> +
> +/* Backward read LEN bytes of target memory from address MEMADDR + LEN,
> +   placing the results in GDB's memory from MYADDR + LEN.  Returns
> +   a count of the bytes actually read.  */
> +
> +static int
> +read_memory_backward (struct gdbarch *gdbarch,
> +                      CORE_ADDR memaddr, gdb_byte *myaddr, int len)
> +{
> +  int errcode;
> +  int nread;      /* Number of bytes actually read.  */
> +
> +  /* First try a complete read.  */
> +  errcode = target_read_memory (memaddr, myaddr, len);
> +  if (errcode == 0)
> +    {
> +      /* Got it all.  */
> +      nread = len;
> +    }
> +  else
> +    {
> +      /* Loop, reading one byte at a time until we get as much as we can.  */
> +      memaddr += len;
> +      myaddr += len;
> +      for (nread = 0; nread < len; ++nread)
> +        {
> +          errcode = target_read_memory (--memaddr, --myaddr, 1);
> +          if (errcode != 0)
> +            {
> +              /* The read was unsuccessful, so exit the loop.  */
> +              printf_filtered (_("Cannot access memory at address %s\n"),
> +                               paddress (gdbarch, memaddr));
> +              break;
> +            }
> +        }
> +    }
> +  return nread;
> +}
> +
> +/* Returns true if X (which is LEN bytes wide) is the number zero.  */
> +
> +static int
> +integer_is_zero (const gdb_byte *x, int len)
> +{
> +  int i = 0;
> +
> +  while (i < len && x[i] == 0)
> +    ++i;
> +  return (i == len);
> +}
> +
> +/* Find the start address of a string in which ADDR is included.
> +   Basically we search for '\0' and return the next address,
> +   but if OPTIONS->PRINT_MAX is smaller than the length of a string,
> +   we stop searching and return the address to print characters as many as
> +   PRINT_MAX from the string.  */
> +
> +static CORE_ADDR
> +find_string_backward (struct gdbarch *gdbarch,
> +                      CORE_ADDR addr, int count, int char_size,
> +                      const struct value_print_options *options,
> +                      int *strings_counted)
> +{
> +  const int chunk_size = 0x20;
> +  gdb_byte *buffer = NULL;
> +  struct cleanup *cleanup = NULL;
> +  int read_error = 0;
> +  int chars_read = 0;
> +  int chars_to_read = chunk_size;
> +  int chars_counted = 0;
> +  int count_original = count;
> +  CORE_ADDR string_start_addr = addr;
> +
> +  gdb_assert (char_size == 1 || char_size == 2 || char_size == 4);
> +  buffer = (gdb_byte *) xmalloc (chars_to_read * char_size);
> +  cleanup = make_cleanup (xfree, buffer);
> +  while (count > 0 && read_error == 0)
> +    {
> +      int i;
> +
> +      addr -= chars_to_read * char_size;
> +      chars_read = read_memory_backward (gdbarch, addr, buffer,
> +                                         chars_to_read * char_size);
> +      chars_read /= char_size;
> +      read_error = (chars_read == chars_to_read) ? 0 : 1;
> +      /* Searching for '\0' from the end of buffer in backward direction.  */
> +      for (i = 0; i < chars_read && count > 0 ; ++i, ++chars_counted)
> +        {
> +          int offset = (chars_to_read - i - 1) * char_size;
> +
> +          if (integer_is_zero (buffer + offset, char_size)
> +              || chars_counted == options->print_max)
> +            {
> +              /* Found '\0' or reached print_max.  As OFFSET is the offset to
> +                 '\0', we add CHAR_SIZE to return the start address of
> +                 a string.  */
> +              --count;
> +              string_start_addr = addr + offset + char_size;
> +              chars_counted = 0;
> +            }
> +        }
> +    }
> +
> +  /* Update STRINGS_COUNTED with the actual number of loaded strings.  */
> +  *strings_counted = count_original - count;
> +
> +  if (read_error != 0)
> +    {
> +      /* In error case, STRING_START_ADDR is pointing to the string that
> +         was last successfully loaded.  Rewind the partially loaded string.  */
> +      string_start_addr -= chars_counted * char_size;
> +    }
> +
> +  do_cleanups (cleanup);
> +  return string_start_addr;
> +}
> +
>   /* Examine data at address ADDR in format FMT.
>      Fetch it from memory and print on gdb_stdout.  */
>   
> @@ -798,6 +1018,8 @@ do_examine (struct format_data fmt, struct gdbarch *gdbarch, CORE_ADDR addr)
>     int i;
>     int maxelts;
>     struct value_print_options opts;
> +  int need_to_update_next_address = 0;
> +  CORE_ADDR addr_rewound = 0;
>   
>     format = fmt.format;
>     size = fmt.size;
> @@ -868,6 +1090,38 @@ do_examine (struct format_data fmt, struct gdbarch *gdbarch, CORE_ADDR addr)
>   
>     get_formatted_print_options (&opts, format);
>   
> +  if (count < 0)
> +    {
> +      /* This is the negative repeat count case.
> +         We rewind the address based on the given repeat count and format,
> +         then examine memory from there in forward direction.  */
> +
> +      count = -count;
> +      if (format == 'i')
> +        {
> +          next_address = find_instruction_backward (gdbarch, addr, count,
> +                                                    &count);
> +        }
> +      else if (format == 's')
> +        {
> +          next_address = find_string_backward (gdbarch, addr, count,
> +                                               TYPE_LENGTH (val_type),
> +                                               &opts, &count);
> +        }
> +      else
> +        {
> +          next_address = addr - count * TYPE_LENGTH (val_type);
> +        }
> +
> +      /* The following call to print_formatted updates next_address in every
> +         iteration.  In backward case, we store the start address here
> +         and update next_address with it before exiting the function.  */
> +      addr_rewound = (format == 's'
> +                      ? next_address - TYPE_LENGTH (val_type)
> +                      : next_address);
> +      need_to_update_next_address = 1;
> +    }
> +
>     /* Print as many objects as specified in COUNT, at most maxelts per line,
>        with the address of the next one at the start of each line.  */
>   
> @@ -913,6 +1167,9 @@ do_examine (struct format_data fmt, struct gdbarch *gdbarch, CORE_ADDR addr)
>         printf_filtered ("\n");
>         gdb_flush (gdb_stdout);
>       }
> +
> +  if (need_to_update_next_address)
> +    next_address = addr_rewound;
>   }
>   \f
>   static void
> @@ -2522,7 +2779,8 @@ Format letters are o(octal), x(hex), d(decimal), u(unsigned decimal),\n\
>     and z(hex, zero padded on the left).\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\
> +according to the format.  If a negative number is specified, memory is\n\
> +examined backward from the address.\n\n\
>   Defaults for format and size letters are those previously used.\n\
>   Default count is 1.  Default address is following last thing printed\n\
>   with this command or \"print\"."));
> diff --git a/gdb/testsuite/gdb.base/examine-backward.c b/gdb/testsuite/gdb.base/examine-backward.c
> new file mode 100644
> index 0000000..b338503
> --- /dev/null
> +++ b/gdb/testsuite/gdb.base/examine-backward.c
> @@ -0,0 +1,106 @@
> +/* This testcase is part of GDB, the GNU debugger.
> +
> +   Copyright 2015-2016 Free Software Foundation, Inc.
> +
> +   This program is free software; you can redistribute it and/or modify
> +   it under the terms of the GNU General Public License as published by
> +   the Free Software Foundation; either version 3 of the License, or
> +   (at your option) any later version.
> +
> +   This program is distributed in the hope that it will be useful,
> +   but WITHOUT ANY WARRANTY; without even the implied warranty of
> +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> +   GNU General Public License for more details.
> +
> +   You should have received a copy of the GNU General Public License
> +   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
> +
> +/*
> +Define TestStrings, TestStringsH, and TestStringsW to test utf8, utf16,
> +and utf32 strings respectively.
> +To avoid compile errors due to old compiler mode, we don't use string
> +literals.  The content of each array is the same as followings:
> +
> +  const char TestStrings[] = {
> +      "ABCD"
> +      "EFGHIJKLMNOPQRSTUVWXYZ\0"
> +      "\0"
> +      "\0"
> +      "\u307B\u3052\u307B\u3052\0"
> +      "012345678901234567890123456789\0"
> +      "!!!!!!\0"
> +  };
> +*/
> +
> +const char TestStrings[] = {
> +  0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48,
> +  0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 0x50,
> +  0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58,
> +  0x59, 0x5a, 0x00, 0x00, 0x00, 0xe3, 0x81, 0xbb,
> +  0xe3, 0x81, 0x92, 0xe3, 0x81, 0xbb, 0xe3, 0x81,
> +  0x92, 0x00, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35,
> +  0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, 0x33,
> +  0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31,
> +  0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39,
> +  0x00, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x00,
> +  0x00
> +};
> +
> +const short TestStringsH[] = {
> +  0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047, 0x0048,
> +  0x0049, 0x004a, 0x004b, 0x004c, 0x004d, 0x004e, 0x004f, 0x0050,
> +  0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057, 0x0058,
> +  0x0059, 0x005a, 0x0000, 0x0000, 0x0000, 0x307b, 0x3052, 0x307b,
> +  0x3052, 0x0000, 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035,
> +  0x0036, 0x0037, 0x0038, 0x0039, 0x0030, 0x0031, 0x0032, 0x0033,
> +  0x0034, 0x0035, 0x0036, 0x0037, 0x0038, 0x0039, 0x0030, 0x0031,
> +  0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037, 0x0038, 0x0039,
> +  0x0000, 0x0021, 0x0021, 0x0021, 0x0021, 0x0021, 0x0021, 0x0000,
> +  0x0000
> +};
> +
> +const int TestStringsW[] = {
> +  0x00000041, 0x00000042, 0x00000043, 0x00000044,
> +  0x00000045, 0x00000046, 0x00000047, 0x00000048,
> +  0x00000049, 0x0000004a, 0x0000004b, 0x0000004c,
> +  0x0000004d, 0x0000004e, 0x0000004f, 0x00000050,
> +  0x00000051, 0x00000052, 0x00000053, 0x00000054,
> +  0x00000055, 0x00000056, 0x00000057, 0x00000058,
> +  0x00000059, 0x0000005a, 0x00000000, 0x00000000,
> +  0x00000000, 0x0000307b, 0x00003052, 0x0000307b,
> +  0x00003052, 0x00000000, 0x00000030, 0x00000031,
> +  0x00000032, 0x00000033, 0x00000034, 0x00000035,
> +  0x00000036, 0x00000037, 0x00000038, 0x00000039,
> +  0x00000030, 0x00000031, 0x00000032, 0x00000033,
> +  0x00000034, 0x00000035, 0x00000036, 0x00000037,
> +  0x00000038, 0x00000039, 0x00000030, 0x00000031,
> +  0x00000032, 0x00000033, 0x00000034, 0x00000035,
> +  0x00000036, 0x00000037, 0x00000038, 0x00000039,
> +  0x00000000, 0x00000021, 0x00000021, 0x00000021,
> +  0x00000021, 0x00000021, 0x00000021, 0x00000000,
> +  0x00000000
> +};
> +
> +int
> +main (void)
> +{
> +  /* Backward disassemble test requires at least 20 instructions in
> +     this function.  Adding a simple bubble sort.  */
> +  int i, j;
> +  int n[] = {3, 1, 4, 1, 5, 9};
> +  int len = sizeof (n) / sizeof (n[0]);
> +
> +  for (i = 0; i < len - 1; ++i)
> +    {
> +      for (j = i; j < len; ++j)
> +        {
> +          if (n[j] < n[i])
> +            {
> +              int tmp = n[i];
> +              n[i] = n[j];
> +              n[j] = tmp;
> +            }
> +        }
> +    }
> +  return 42;
> +}
> diff --git a/gdb/testsuite/gdb.base/examine-backward.exp b/gdb/testsuite/gdb.base/examine-backward.exp
> new file mode 100644
> index 0000000..e03cbfd
> --- /dev/null
> +++ b/gdb/testsuite/gdb.base/examine-backward.exp
> @@ -0,0 +1,324 @@
> +# Copyright 2015-2016 Free Software Foundation, Inc.
> +
> +# This program is free software; you can redistribute it and/or modify
> +# it under the terms of the GNU General Public License as published by
> +# the Free Software Foundation; either version 3 of the License, or
> +# (at your option) any later version.
> +#
> +# This program is distributed in the hope that it will be useful,
> +# but WITHOUT ANY WARRANTY; without even the implied warranty of
> +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> +# GNU General Public License for more details.
> +#
> +# You should have received a copy of the GNU General Public License
> +# along with this program.  If not, see <http://www.gnu.org/licenses/>.
> +
> +# This testsuite is to test examining memory backward by specifying a negative
> +# number in the 'x' command.
> +
> +standard_testfile
> +if { [prepare_for_testing "failed to prepare for examine-backward" \
> +        ${testfile} ${srcfile}] } {
> +    return -1
> +}
> +
> +if ![runto_main] {
> +    untested "could not run to main"
> +    return -1
> +}
> +
> +proc get_first_mapped_address {} {
> +    global gdb_prompt
> +
> +    set addr "0"
> +    gdb_test_multiple "info proc mappings" "info proc mappings" {
> +        -re "objfile\[\r\n\t \]+(0x\[0-9a-fA-F\]+).*\[\r\n\]*$gdb_prompt $" {
> +            set addr $expect_out(1,string)
> +        }
> +        -re "$gdb_prompt $" {
> +            unsupported "Current target does not support 'info proc mappings'"
> +        }
> +    }
> +    return ${addr}
> +}
> +
> +with_test_prefix "invalid format" {
> +    gdb_test "x/- 10xb main" "Invalid number \"10xb\"\." \
> +        "a whitespace after a leading hyphen"
> +    gdb_test "x/--10xb main" "Invalid number \"10xb\"\." \
> +        "double hyphen"
> +    gdb_test "x/-a10xb main" "Invalid number \"10xb\"\." \
> +        "an alphabet after a leading hyphen"
> +    gdb_test_no_output "x/-0i main" "zero with backward disassemble"
> +    gdb_test_no_output "x/-0sh main" "zero with backward examine string"
> +}
> +
> +with_test_prefix "memory page boundary" {
> +    set boundary [get_first_mapped_address]
> +    if {![is_address_zero_readable] && $boundary != 0} {
> +        gdb_test_no_output "set print elements 0"
> +        gdb_test_sequence "x/3s ${boundary}" "take 3 strings forward" {
> +            "0x"
> +            "0x"
> +            "0x"
> +        }
> +        gdb_test_sequence "x/-4s" "take 4 strings backward" {
> +            "Cannot access memory at address 0x"
> +            "0x"
> +            "0x"
> +            "0x"
> +        }
> +        gdb_test_sequence "x/3s ${boundary}" "take 3 strings forward again" {
> +            "0x"
> +            "0x"
> +            "0x"
> +        }
> +        gdb_test_sequence "x/-3s" "take 3 strings backward" {
> +            "Cannot access memory at address 0x"
> +            "0x"
> +            "0x"
> +            "0x"
> +        }
> +    }
> +}
> +
> +with_test_prefix "address zero boundary" {
> +    if {[is_address_zero_readable]} {
> +        set address_zero "0x0"
> +        set byte "\t0x\[0-9a-f\]+"
> +        gdb_test "x/3xb ${address_zero}" \
> +            "0x\[0-9a-f\]+00.*:${byte}${byte}${byte}" \
> +            "examine 3 bytes forward from ${address_zero}"
> +        gdb_test "x/-6x" \
> +            "0x\[0-9a-f\]+fd.*:${byte}${byte}${byte}${byte}${byte}${byte}" \
> +            "examine 6 bytes backward"
> +        gdb_test "x/-3x ${address_zero}" \
> +            "0x\[0-9a-f\]+fd.*:${byte}${byte}${byte}" \
> +            "examine 3 bytes backward from ${address_zero}"
> +    }
> +}
> +
> +gdb_test_no_output "set charset ASCII"
> +
> +with_test_prefix "char-width=1, print-max=20" {
> +    gdb_test_no_output "set print elements 20"
> +    gdb_test_sequence "x/6s &TestStrings" "take 6 strings forward" {
> +        "\"ABCDEFGHIJKLMNOPQRST\"\.\.\."
> +        "\"UVWXYZ\""
> +        "\"\""
> +        "\"\""
> +        "\"[^\"]+\""
> +        "\"01234567890123456789\"\.\.\."
> +    }
> +    gdb_test "x/-1xb" "0x39" "take 1 char backward"
> +    gdb_test_sequence "x/-6s" "take 6 strings backward" {
> +        "\"ABCDEFGHIJKLMNOPQRST\"\.\.\."
> +        "\"UVWXYZ\""
> +        "\"\""
> +        "\"\""
> +        "\"[^\"]+\""
> +        "\"01234567890123456789\"\.\.\."
> +    }
> +    gdb_test_sequence "x/6s &TestStrings" "take 6 strings forward again" {
> +        "\"ABCDEFGHIJKLMNOPQRST\"\.\.\."
> +        "\"UVWXYZ\""
> +        "\"\""
> +        "\"\""
> +        "\"[^\"]+\""
> +        "\"01234567890123456789\"\.\.\."
> +    }
> +    gdb_test "x/-xb" "0x39" "take 1 char backward again"
> +    gdb_test "x/-s" "\"01234567890123456789\"\.\.\." \
> +        "take 1 string backward (1/6)"
> +    gdb_test "x/-s" "\".+\"" \
> +        "take 1 string backward (2/6)"
> +    gdb_test "x/-s" "\"\"" \
> +        "take 1 string backward (3/6)"
> +    gdb_test "x/-s" "\"\"" \
> +        "take 1 string backward (4/6)"
> +    gdb_test "x/-s" "\"GHIJKLMNOPQRSTUVWXYZ\"" \
> +        "take 1 string backward (5/6)"
> +    gdb_test "x/-s" "\"ABCDEFGHIJKLMNOPQRST\"\.\.\." \
> +        "take 1 string backward (6/6)"
> +}
> +
> +with_test_prefix "char-width=2, print-max=20" {
> +    gdb_test_no_output "set print elements 20"
> +    gdb_test_sequence "x/6sh &TestStringsH" "take 6 strings forward" {
> +        "u\"ABCDEFGHIJKLMNOPQRST\"\.\.\."
> +        "u\"UVWXYZ\""
> +        "u\"\""
> +        "u\"\""
> +        "u\"[^\"]+\""
> +        "u\"01234567890123456789\"\.\.\."
> +    }
> +    gdb_test "x/-1xh" "0x0039" "take 1 char backward"
> +    gdb_test_sequence "x/-6sh" "take 6 strings backward" {
> +        "u\"ABCDEFGHIJKLMNOPQRST\"\.\.\."
> +        "u\"UVWXYZ\""
> +        "u\"\""
> +        "u\"\""
> +        "u\"[^\"]+\""
> +        "u\"01234567890123456789\"\.\.\."
> +    }
> +    gdb_test_sequence "x/6sh &TestStringsH" "take 6 strings forward again" {
> +        "u\"ABCDEFGHIJKLMNOPQRST\"\.\.\."
> +        "u\"UVWXYZ\""
> +        "u\"\""
> +        "u\"\""
> +        "u\"[^\"]+\""
> +        "u\"01234567890123456789\"\.\.\."
> +    }
> +    gdb_test "x/-xh" "0x0039" "take 1 char backward again"
> +    gdb_test "x/-sh" "u\"01234567890123456789\"\.\.\." \
> +        "take 1 string backward (1/6)"
> +    gdb_test "x/-sh" "u\".+\"" \
> +        "take 1 string backward (2/6)"
> +    gdb_test "x/-sh" "u\"\"" \
> +        "take 1 string backward (3/6)"
> +    gdb_test "x/-sh" "u\"\"" \
> +        "take 1 string backward (4/6)"
> +    gdb_test "x/-sh" "u\"GHIJKLMNOPQRSTUVWXYZ\"" \
> +        "take 1 string backward (5/6)"
> +    gdb_test "x/-sh" "u\"ABCDEFGHIJKLMNOPQRST\"\.\.\." \
> +        "take 1 string backward (6/6)"
> +}
> +
> +with_test_prefix "char-width=4, print-max=20" {
> +    gdb_test_no_output "set print elements 20"
> +    gdb_test_sequence "x/6sw &TestStringsW" "take 6 strings forward" {
> +        "U\"ABCDEFGHIJKLMNOPQRST\"\.\.\."
> +        "U\"UVWXYZ\""
> +        "U\"\""
> +        "U\"\""
> +        "U\"[^\"]+\""
> +        "U\"01234567890123456789\"\.\.\."
> +    }
> +    gdb_test "x/-1xw" "0x00000039" "take 1 char backward"
> +    gdb_test_sequence "x/-6sw" "take 6 strings backward" {
> +        "U\"ABCDEFGHIJKLMNOPQRST\"\.\.\."
> +        "U\"UVWXYZ\""
> +        "U\"\""
> +        "U\"\""
> +        "U\"[^\"]+\""
> +        "U\"01234567890123456789\"\.\.\."
> +    }
> +    gdb_test_sequence "x/6sw &TestStringsW" "take 6 strings forward again" {
> +        "U\"ABCDEFGHIJKLMNOPQRST\"\.\.\."
> +        "U\"UVWXYZ\""
> +        "U\"\""
> +        "U\"\""
> +        "U\"[^\"]+\""
> +        "U\"01234567890123456789\"\.\.\."
> +    }
> +    gdb_test "x/-xw" "0x00000039" "take 1 char backward again"
> +    gdb_test "x/-sw" "U\"01234567890123456789\"\.\.\." \
> +        "take 1 string backward (1/6)"
> +    gdb_test "x/-sw" "U\".+\"" \
> +        "take 1 string backward (2/6)"
> +    gdb_test "x/-sw" "U\"\"" \
> +        "take 1 string backward (3/6)"
> +    gdb_test "x/-sw" "U\"\"" \
> +        "take 1 string backward (4/6)"
> +    gdb_test "x/-sw" "U\"GHIJKLMNOPQRSTUVWXYZ\"" \
> +        "take 1 string backward (5/6)"
> +    gdb_test "x/-sw" "U\"ABCDEFGHIJKLMNOPQRST\"\.\.\." \
> +        "take 1 string backward (6/6)"
> +}
> +
> +with_test_prefix "char-width=2, print-max=0" {
> +    gdb_test_no_output "set print elements 0"
> +    gdb_test_sequence "x/6sh &TestStringsH" "take 6 strings forward" {
> +        "u\"ABCDEFGHIJKLMNOPQRSTUVWXYZ\""
> +        "u\"\""
> +        "u\"\""
> +        "u\"\\\\x307b\\\\x3052\\\\x307b\\\\x3052\""
> +        "u\"012345678901234567890123456789\""
> +        "u\"!!!!!!\""
> +    }
> +    gdb_test "x/-4xh" "0x0021\[\t \]+0x0021\[\t \]+0x0021\[\t \]+0x0000" \
> +        "take 4 characters backward"
> +    gdb_test_sequence "x/-6sh" "take 6 strings backward" {
> +        "u\"ABCDEFGHIJKLMNOPQRSTUVWXYZ\""
> +        "u\"\""
> +        "u\"\""
> +        "u\"[^\"]+\""
> +        "u\"012345678901234567890123456789\""
> +        "u\"!!!!!!\""
> +    }
> +    gdb_test_sequence "x/6sh &TestStringsH" "take 6 strings forward again" {
> +        "u\"ABCDEFGHIJKLMNOPQRSTUVWXYZ\""
> +        "u\"\""
> +        "u\"\""
> +        "u\"\\\\x307b\\\\x3052\\\\x307b\\\\x3052\""
> +        "u\"012345678901234567890123456789\""
> +        "u\"!!!!!!\""
> +    }
> +    gdb_test "x/-xh" "0x0000" "take 1 char backward"
> +    gdb_test "x/-sh" "u\"!!!!!!\"" \
> +        "take 1 string backward (1/6)"
> +    gdb_test "x/-sh" "u\"012345678901234567890123456789\"" \
> +        "take 1 string backward (2/6)"
> +    gdb_test "x/-sh" "u\".+\"" \
> +        "take 1 string backward (3/6)"
> +    gdb_test "x/-sh" "u\"\"" \
> +        "take 1 string backward (4/6)"
> +    gdb_test "x/-sh" "u\"\"" \
> +        "take 1 string backward (5/6)"
> +    gdb_test "x/-sh" "u\"ABCDEFGHIJKLMNOPQRSTUVWXYZ\"" \
> +        "take 1 string backward (6/6)"
> +}
> +
> +with_test_prefix "char-width=1, print-max=4" {
> +    gdb_test_no_output "set print elements 4"
> +    gdb_test_sequence "x/9s &TestStrings" "take 9 strings forward" {
> +        "\"ABCD\"\.\.\."
> +        "\"EFGH\"\.\.\."
> +        "\"IJKL\"\.\.\."
> +        "\"MNOP\"\.\.\."
> +        "\"QRST\"\.\.\."
> +        "\"UVWX\"\.\.\."
> +        "\"YZ\""
> +        "\"\""
> +        "\"\""
> +    }
> +    gdb_test "x/-xb" "0x00" "take 1 byte backward"
> +    gdb_test_sequence "x/-4s" "take 4 strings backward (1/2)" {
> +        "\"TUVW\"\.\.\."
> +        "\"XYZ\""
> +        "\"\""
> +        "\"\""
> +    }
> +    gdb_test_sequence "x/-4s" "take 4 strings backward (2/2)" {
> +        "\"CDEF\"\.\.\."
> +        "\"GHIJ\"\.\.\."
> +        "\"KLMN\"\.\.\."
> +        "\"OPQR\"\.\.\."
> +    }
> +}
> +
> +with_test_prefix "backward disassemble general" {
> +    set length_to_examine {1 2 3 4 10}
> +    set disassmbly {}
> +
> +    gdb_test "x/i main" "0x\[0-9a-fA-F\]+ <main>:\t.*" \
> +        "move the current position to main (x/i)"
> +    gdb_test "x/-i" "0x\[0-9a-fA-F\]+ <main>:\t.*" \
> +        "move the current position to main (x/-i)"
> +    for {set i 0} {$i < [llength $length_to_examine]} {incr i} {
> +        set len [lindex $length_to_examine $i]
> +        set instructions [capture_command_output "x/${len}i" ""]
> +        lappend disassmbly $instructions
> +    }
> +    for {set i 0} {$i < [llength $length_to_examine]} {incr i} {
> +        set idx [expr [llength $length_to_examine] - $i - 1]
> +        set len [lindex $length_to_examine $idx]
> +        set actual [capture_command_output "x/-${len}i" ""]
> +        set expected [lindex $disassmbly $idx]
> +        if {$actual == $expected} {
> +            pass "inst:$idx"
> +        } else {
> +            fail "inst:$idx"
> +        }
> +    }
> +}

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

* Re: [PATCH v5] Add negative repeat count to 'x' command
  2016-08-08 14:45 ` Thomas Preudhomme
@ 2016-08-11  0:00   ` Pedro Alves
  2016-08-11 12:51     ` Thomas Preudhomme
  0 siblings, 1 reply; 11+ messages in thread
From: Pedro Alves @ 2016-08-11  0:00 UTC (permalink / raw)
  To: Thomas Preudhomme, Toshihito Kikuchi, gdb-patches; +Cc: Simon Marchi

On 08/08/2016 03:45 PM, Thomas Preudhomme wrote:
> Sorry for the late reply but I noticed an issue in the tests added by
> this patch for arm-none-eabi:
> 
> 
> FAIL: gdb.base/examine-backward.exp: address zero boundary: examine 3
> bytes forward from 0x0
> NA->FAIL: gdb.base/examine-backward.exp char-width=1, print-max=20 take
> 1 string backward (6/6)
> NA->FAIL: gdb.base/examine-backward.exp char-width=1, print-max=20 take
> 6 strings backward (pattern 1)
> 
> 
> The first one is a testism:
> 
> we match for: 0x\[0-9a-f\]+00.*:${byte}${byte}${byte}
> but we get: 0x0:    0x7f    0x45    0x4c
> 
> I'd thus suggest to match 0x\(\[0-9a-f\]+0\)?0 instead, with the right
> amount of escaping (I don't know whether ? needs escaping and why + does
> not need escaping in current pattern).

We're examining at 0x0.  Shouldn't we expect literally "0x0"
instead then?

> 
> 
> The other two seems like genuine errors. take 6 strings backward
> (pattern 1) gives:
> 
> gdb_expect_list pattern: /"ABCDEFGHIJKLMNOPQRST".../
> x/-6s^M
> 0x9aff <_fini+2>: "\277\370\274\b\274\236FpGABCDEFGHIJK"...^M
> 0x9b13 <TestStrings+11>:        "LMNOPQRSTUVWXYZ"^M
> 0x9b23 <TestStrings+27>:        ""^M
> 0x9b24 <TestStrings+28>:        ""^M
> 0x9b25 <TestStrings+29>:
> "\343\201\273\343\201\222\343\201\273\343\201\222"^M
> 0x9b32 <TestStrings+42>:        "01234567890123456789"...^M
> (gdb) FAIL: gdb.base/examine-backward.exp: char-width=1, print-max=20:
> take 6 strings backward (pattern 1)
> 
> 
> take 1 string backward (6/6) gives:
> 
> 0x9aff <_fini+2>: "\277\370\274\b\274\236FpGABCDEFGHIJK"...
> 
> 
> Please let me know what I can do to help diagnose this error.

The find-strings-backwards algorithm just looks back for '\0' to
find string boundaries.  Looks like it just happens that in your
case, the TestStrings array is immediately preceded by the
tail of _fini, with no gap in between.

Try this.  It's not strictly correct to assume that the linker
places the objects consecutively, but it's probably safe
in practice.

diff --git c/gdb/testsuite/gdb.base/examine-backward.c w/gdb/testsuite/gdb.base/examine-backward.c
index b338503..187fad1 100644
--- c/gdb/testsuite/gdb.base/examine-backward.c
+++ w/gdb/testsuite/gdb.base/examine-backward.c
@@ -32,6 +32,14 @@ literals.  The content of each array is the same as followings:
   };
 */
 
+/* This is here just to ensure we have a null character before
+   TestStrings, to avoid showing garbage when we look for strings
+   backwards from TestStrings.  */
+
+const char NullString[] = {
+  0x00
+};
+
 const char TestStrings[] = {
   0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48,
   0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 0x50,


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

* Re: [PATCH v5] Add negative repeat count to 'x' command
  2016-08-11  0:00   ` Pedro Alves
@ 2016-08-11 12:51     ` Thomas Preudhomme
  2016-08-11 14:08       ` Thomas Preudhomme
  0 siblings, 1 reply; 11+ messages in thread
From: Thomas Preudhomme @ 2016-08-11 12:51 UTC (permalink / raw)
  To: Pedro Alves, Toshihito Kikuchi, gdb-patches; +Cc: Simon Marchi



On 11/08/16 00:58, Pedro Alves wrote:
> On 08/08/2016 03:45 PM, Thomas Preudhomme wrote:
>> Sorry for the late reply but I noticed an issue in the tests added by
>> this patch for arm-none-eabi:
>>
>>
>> FAIL: gdb.base/examine-backward.exp: address zero boundary: examine 3
>> bytes forward from 0x0
>> NA->FAIL: gdb.base/examine-backward.exp char-width=1, print-max=20 take
>> 1 string backward (6/6)
>> NA->FAIL: gdb.base/examine-backward.exp char-width=1, print-max=20 take
>> 6 strings backward (pattern 1)
>>
>>
>> The first one is a testism:
>>
>> we match for: 0x\[0-9a-f\]+00.*:${byte}${byte}${byte}
>> but we get: 0x0:    0x7f    0x45    0x4c
>>
>> I'd thus suggest to match 0x\(\[0-9a-f\]+0\)?0 instead, with the right
>> amount of escaping (I don't know whether ? needs escaping and why + does
>> not need escaping in current pattern).
>
> We're examining at 0x0.  Shouldn't we expect literally "0x0"
> instead then?

That's what I would have done but I assumed that the test was passing on the 
machine it was developed and thus that some machine display 0x00000000 or something.

>
>>
>>
>> The other two seems like genuine errors. take 6 strings backward
>> (pattern 1) gives:
>>
>> gdb_expect_list pattern: /"ABCDEFGHIJKLMNOPQRST".../
>> x/-6s^M
>> 0x9aff <_fini+2>: "\277\370\274\b\274\236FpGABCDEFGHIJK"...^M
>> 0x9b13 <TestStrings+11>:        "LMNOPQRSTUVWXYZ"^M
>> 0x9b23 <TestStrings+27>:        ""^M
>> 0x9b24 <TestStrings+28>:        ""^M
>> 0x9b25 <TestStrings+29>:
>> "\343\201\273\343\201\222\343\201\273\343\201\222"^M
>> 0x9b32 <TestStrings+42>:        "01234567890123456789"...^M
>> (gdb) FAIL: gdb.base/examine-backward.exp: char-width=1, print-max=20:
>> take 6 strings backward (pattern 1)
>>
>>
>> take 1 string backward (6/6) gives:
>>
>> 0x9aff <_fini+2>: "\277\370\274\b\274\236FpGABCDEFGHIJK"...
>>
>>
>> Please let me know what I can do to help diagnose this error.
>
> The find-strings-backwards algorithm just looks back for '\0' to
> find string boundaries.  Looks like it just happens that in your
> case, the TestStrings array is immediately preceded by the
> tail of _fini, with no gap in between.
>
> Try this.  It's not strictly correct to assume that the linker
> places the objects consecutively, but it's probably safe
> in practice.

The patch works indeed. Thanks for your quick answer.

Best regards,

Thomas

>
> diff --git c/gdb/testsuite/gdb.base/examine-backward.c w/gdb/testsuite/gdb.base/examine-backward.c
> index b338503..187fad1 100644
> --- c/gdb/testsuite/gdb.base/examine-backward.c
> +++ w/gdb/testsuite/gdb.base/examine-backward.c
> @@ -32,6 +32,14 @@ literals.  The content of each array is the same as followings:
>    };
>  */
>
> +/* This is here just to ensure we have a null character before
> +   TestStrings, to avoid showing garbage when we look for strings
> +   backwards from TestStrings.  */
> +
> +const char NullString[] = {
> +  0x00
> +};
> +
>  const char TestStrings[] = {
>    0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48,
>    0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 0x50,
>
>

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

* Re: [PATCH v5] Add negative repeat count to 'x' command
  2016-08-11 12:51     ` Thomas Preudhomme
@ 2016-08-11 14:08       ` Thomas Preudhomme
  2016-08-11 16:32         ` Pedro Alves
  0 siblings, 1 reply; 11+ messages in thread
From: Thomas Preudhomme @ 2016-08-11 14:08 UTC (permalink / raw)
  To: Pedro Alves, Toshihito Kikuchi, gdb-patches; +Cc: Simon Marchi

Hi Pedro,

On 11/08/16 13:51, Thomas Preudhomme wrote:
>>
>> The find-strings-backwards algorithm just looks back for '\0' to
>> find string boundaries.  Looks like it just happens that in your
>> case, the TestStrings array is immediately preceded by the
>> tail of _fini, with no gap in between.
>>
>> Try this.  It's not strictly correct to assume that the linker
>> places the objects consecutively, but it's probably safe
>> in practice.
>
> The patch works indeed. Thanks for your quick answer.

While trying this I noticed that the following 2 tests fail when running with 
qemu-user (it works with qemu-system):

gdb.base/examine-backward.exp: address zero boundary: examine 6 bytes backward
gdb.base/examine-backward.exp: address zero boundary: examine 3 bytes backward 
from 0x0

They fail with:

0xfffffffd:     Cannot access memory at address 0xfffffffd

I suppose these two tests should also be guarded or maybe have several expected 
results.

Best regards,

Thomas

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

* Re: [PATCH v5] Add negative repeat count to 'x' command
  2016-08-11 14:08       ` Thomas Preudhomme
@ 2016-08-11 16:32         ` Pedro Alves
  2016-08-16 14:03           ` Thomas Preudhomme
  0 siblings, 1 reply; 11+ messages in thread
From: Pedro Alves @ 2016-08-11 16:32 UTC (permalink / raw)
  To: Thomas Preudhomme, Toshihito Kikuchi, gdb-patches; +Cc: Simon Marchi

On 08/11/2016 03:08 PM, Thomas Preudhomme wrote:
>>
> 
> While trying this I noticed that the following 2 tests fail when running
> with qemu-user (it works with qemu-system):

So this is emulating a no-MMU configuration, right?  Since gdb managed to
read from address 0.  Otherwise, the problem is in is_address_zero_readable.

> 
> gdb.base/examine-backward.exp: address zero boundary: examine 6 bytes backward
> 
> gdb.base/examine-backward.exp: address zero boundary: examine 3 bytes
> backward from 0x0
> 
> They fail with:
> 
> 0xfffffffd:     Cannot access memory at address 0xfffffffd
> 
> I suppose these two tests should also be guarded or maybe have several
> expected results.

If you try reading from that address directly, does it work?
E.g. "x 0xfffffffd".

Wondering whether gdb is actually trying to read from 0xfffffffffffffffd,
and that failing somewhere.  The address print routine (paddress) trims
the upper 32-bits of CORE_ADDR when debugging a 32-bit target.

But probably this just means that that physical address really
does not exist on the emulated system, and so qemu's stub returns
error when gdb tries to read off of it?

Thanks,
Pedro Alves

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

* Re: [PATCH v5] Add negative repeat count to 'x' command
  2016-08-11 16:32         ` Pedro Alves
@ 2016-08-16 14:03           ` Thomas Preudhomme
  2016-08-19 18:59             ` Pedro Alves
  0 siblings, 1 reply; 11+ messages in thread
From: Thomas Preudhomme @ 2016-08-16 14:03 UTC (permalink / raw)
  To: Pedro Alves, Toshihito Kikuchi, gdb-patches; +Cc: Simon Marchi



On 11/08/16 17:32, Pedro Alves wrote:
> On 08/11/2016 03:08 PM, Thomas Preudhomme wrote:
>>>
>>
>> While trying this I noticed that the following 2 tests fail when running
>> with qemu-user (it works with qemu-system):
>
> So this is emulating a no-MMU configuration, right?  Since gdb managed to
> read from address 0.  Otherwise, the problem is in is_address_zero_readable.

qemu-system-user would be no MMU, qemu-user would have an MMU *but* the qemu gdb 
stub would bypass lots of memory access checks AFAIK.

>
>>
>> gdb.base/examine-backward.exp: address zero boundary: examine 6 bytes backward
>>
>> gdb.base/examine-backward.exp: address zero boundary: examine 3 bytes
>> backward from 0x0
>>
>> They fail with:
>>
>> 0xfffffffd:     Cannot access memory at address 0xfffffffd
>>
>> I suppose these two tests should also be guarded or maybe have several
>> expected results.
>
> If you try reading from that address directly, does it work?
> E.g. "x 0xfffffffd".

Same error: 0xfffffffd:     Cannot access memory at address 0xfffffffd

>
> Wondering whether gdb is actually trying to read from 0xfffffffffffffffd,
> and that failing somewhere.  The address print routine (paddress) trims
> the upper 32-bits of CORE_ADDR when debugging a 32-bit target.
>
> But probably this just means that that physical address really
> does not exist on the emulated system, and so qemu's stub returns
> error when gdb tries to read off of it?

Yes, I believe that's the case. For some reason reading from 0 works but not 
from the end of the address space. Why not use a multiple regex matching and 
make the test UNSUPPORTED with a new regex on this error message?

This is just a suggestion, I am not very familiar with how GDB deals with this 
kind of issue generally but have noticed testcases with several -re patterns.

Best regards,

Thomas

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

* Re: [PATCH v5] Add negative repeat count to 'x' command
  2016-08-16 14:03           ` Thomas Preudhomme
@ 2016-08-19 18:59             ` Pedro Alves
  2016-09-06 14:28               ` Thomas Preudhomme
  0 siblings, 1 reply; 11+ messages in thread
From: Pedro Alves @ 2016-08-19 18:59 UTC (permalink / raw)
  To: Thomas Preudhomme, Toshihito Kikuchi, gdb-patches; +Cc: Simon Marchi

On 08/16/2016 03:03 PM, Thomas Preudhomme wrote:
> 
>>
>> Wondering whether gdb is actually trying to read from 0xfffffffffffffffd,
>> and that failing somewhere.  The address print routine (paddress) trims
>> the upper 32-bits of CORE_ADDR when debugging a 32-bit target.
>>
>> But probably this just means that that physical address really
>> does not exist on the emulated system, and so qemu's stub returns
>> error when gdb tries to read off of it?
> 
> Yes, I believe that's the case. For some reason reading from 0 works but
> not from the end of the address space. Why not use a multiple regex
> matching and
> make the test UNSUPPORTED with a new regex on this error message?
> 
> This is just a suggestion, I am not very familiar with how GDB deals
> with this
> kind of issue generally but have noticed testcases with several -re patterns.
> 

First I think we should assess whether the behavior is correct or
whether there's a qemu or gdb bug.  If it's a gdb bug, we should fix
it, of course.  If it's a qemu bug, we should report it and maybe XFAIL
it.  If it's not a bug but a qemu personality quirk, then we can make
the tests cope, somehow.

I still wonder why does the read from 0 work at all.  I've tried
reproducing this, using x86_64 Fedora 23's stock qemu-arm:

$ qemu-arm -version
qemu-arm version 2.4.1 (qemu-2.4.1-11.fc23), Copyright (c) 2003-2008 Fabrice Bellard

... but couldn't.  Here's what I get instead:

Terminal 1:

 $ cat crash.c 
 int main ()
 {
   volatile int *null = 0; 

   return *null;
 }

 $ arm-linux-gnueabi -static crash.c

 $ qemu-arm -g 9999 a.out

Terminal 2:

 $ gdb a.out -ex "tar rem :9999"

 (gdb) x 0
 Sending packet: $m0,4#fd...Ack
 Packet received: E14
 0x0:    Cannot access memory at address 0x0

IIRC, arm's exception vector is at 0 and that that's
where execution starts.  But that shouldn't be applicable
to mmu userspace programs?

I wonder what's different between our environments.

Note: I had to use -static, because of:

 $ qemu-arm -g 9999  ./crash.arm 
 /lib/ld-linux.so.3: No such file or directory

I suppose I would need to point qemu at an arm sysroot,
somehow to get past that.

Is there a dejagnu board file somewhere handy one could steal
in order to run tests against qemu-user ?

Thanks,
Pedro Alves

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

* Re: [PATCH v5] Add negative repeat count to 'x' command
  2016-08-19 18:59             ` Pedro Alves
@ 2016-09-06 14:28               ` Thomas Preudhomme
  0 siblings, 0 replies; 11+ messages in thread
From: Thomas Preudhomme @ 2016-09-06 14:28 UTC (permalink / raw)
  To: Pedro Alves, Toshihito Kikuchi, gdb-patches; +Cc: Simon Marchi

Hi Pedro,

Sorry for the delay in answering.

On 19/08/16 19:59, Pedro Alves wrote:
>>
>
> First I think we should assess whether the behavior is correct or
> whether there's a qemu or gdb bug.  If it's a gdb bug, we should fix
> it, of course.  If it's a qemu bug, we should report it and maybe XFAIL
> it.  If it's not a bug but a qemu personality quirk, then we can make
> the tests cope, somehow.
>
> I still wonder why does the read from 0 work at all.  I've tried
> reproducing this, using x86_64 Fedora 23's stock qemu-arm:
>
> $ qemu-arm -version
> qemu-arm version 2.4.1 (qemu-2.4.1-11.fc23), Copyright (c) 2003-2008 Fabrice Bellard
>
> ... but couldn't.  Here's what I get instead:
>
> Terminal 1:
>
>  $ cat crash.c
>  int main ()
>  {
>    volatile int *null = 0;
>
>    return *null;
>  }
>
>  $ arm-linux-gnueabi -static crash.c
>
>  $ qemu-arm -g 9999 a.out
>
> Terminal 2:
>
>  $ gdb a.out -ex "tar rem :9999"
>
>  (gdb) x 0
>  Sending packet: $m0,4#fd...Ack
>  Packet received: E14
>  0x0:    Cannot access memory at address 0x0
>
> IIRC, arm's exception vector is at 0 and that that's
> where execution starts.  But that shouldn't be applicable
> to mmu userspace programs?

I'm getting:

(gdb) x 0
0x0:    0x464c457f

However note that I compiled with arm-none-eabi-gcc so there would be some bits 
of the program (ARM's exception vector indeed) at this address.

>
> I wonder what's different between our environments.

We are targetting ARM bare-metal targets.

>
> Note: I had to use -static, because of:
>
>  $ qemu-arm -g 9999  ./crash.arm
>  /lib/ld-linux.so.3: No such file or directory
>
> I suppose I would need to point qemu at an arm sysroot,
> somehow to get past that.
>
> Is there a dejagnu board file somewhere handy one could steal
> in order to run tests against qemu-user ?

Nothing public that I am aware of I'm afraid. However I can reproduce this issue 
easily by compiling examine-backward.c with the GNU ARM embedded toolchain [1] 
using the following command line:

arm-none-eabi-gcc -o examine-backward.axf 
gdb/testuite/gdb.base/examine-backward.c -specs=rdimon.specs

and then running:

qemu-arm -g 2048 examine-backward.axf &
arm-none-eabi-gdb examine-backward.axf
(gdb) target remote :2048
x/3xb 0x0
x/-6x


[1] https://launchpad.net/gcc-arm-embedded

Thanks for your effort on understanding this Pedro.

Best regards,

Thomas

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

end of thread, other threads:[~2016-09-06 14:28 UTC | newest]

Thread overview: 11+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-06-02  8:52 [PATCH v5] Add negative repeat count to 'x' command Toshihito Kikuchi
2016-06-03 10:54 ` Pedro Alves
2016-06-10  6:02   ` Toshihito Kikuchi
2016-08-08 14:45 ` Thomas Preudhomme
2016-08-11  0:00   ` Pedro Alves
2016-08-11 12:51     ` Thomas Preudhomme
2016-08-11 14:08       ` Thomas Preudhomme
2016-08-11 16:32         ` Pedro Alves
2016-08-16 14:03           ` Thomas Preudhomme
2016-08-19 18:59             ` Pedro Alves
2016-09-06 14:28               ` Thomas Preudhomme

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).