[Crash-utility] [PATCH] crash: dis: introduce count in reverse and forward mode

Dave Anderson anderson at redhat.com
Tue Jun 18 19:01:52 UTC 2019



----- Original Message -----
> The purpose of this patch is to add support for a count value in reverse
> or forward mode, during disassembly:
> 
> 	'dis [-r|-f] [symbol|address] [count]'
> 
> For example:
> 
>   crash> dis -f list_del+0x16 4
>   0xffffffff812b3346 <list_del+22>:       jne    0xffffffff812b3381
>   <list_del+81>
>   0xffffffff812b3348 <list_del+24>:       mov    (%rbx),%rax
>   0xffffffff812b334b <list_del+27>:       mov    0x8(%rax),%r8
>   0xffffffff812b334f <list_del+31>:       cmp    %r8,%rbx
> 
>   crash> dis -r list_del+0x16 4
>   0xffffffff812b333c <list_del+12>:       mov    0x8(%rdi),%rax
>   0xffffffff812b3340 <list_del+16>:       mov    (%rax),%r8
>   0xffffffff812b3343 <list_del+19>:       cmp    %r8,%rdi
>   0xffffffff812b3346 <list_del+22>:       jne    0xffffffff812b3381
>   <list_del+81>
> 
> To support this feature, I have essentially incorported GDB commit
> bb556f1facb ("Add negative repeat count to 'x' command"), with some
> additional changes to maintain default behaviour i.e. always display the
> target instruction with the examine command.

Hi Aaron,

The concept looks good, but the printcmd.c part of the patch doesn't apply cleanly:

$ make warn
TARGET: PPC64
 CRASH: 7.2.6++
   GDB: 7.6

... [ cut ] ...
patching file gdb-7.6/gdb/printcmd.c
Hunk #2 FAILED at 800.
Hunk #5 FAILED at 966.
Hunk #6 succeeded at 2579 (offset 1 line).
2 out of 6 hunks FAILED
... [ cut ] ...
gcc -g -O2 -m64 -fPIC -mminimal-toc  -I. -I. -I./common -I./config -DLOCALEDIR="\"/usr/local/share/locale\"" -DCRASH_MERGE -DHAVE_CONFIG_H -I./../include/opcode -I./../opcodes/.. -I./../readline/.. -I../bfd -I./../bfd -I./../include -I../libdecnumber -I./../libdecnumber  -I./gnulib/import -Ibuild-gnulib/import   -DTUI=1  -Wall -Wdeclaration-after-statement -Wpointer-arith -Wformat-nonliteral -Wno-pointer-sign -Wno-unused -Wunused-value -Wunused-function -Wno-switch -Wno-char-subscripts -Wmissing-prototypes -Wdeclaration-after-statement -Wempty-body  `echo " -Wall -Wdeclaration-after-statement -Wpointer-arith -Wformat-nonliteral -Wno-pointer-sign -Wno-unused -Wunused-value -Wunused-function -Wno-switch -Wno-char-subscripts -Wmissing-prototypes -Wdeclaration-after-statement -Wempty-body " | sed "s/ -Wformat-nonliteral / -Wno-format-nonliteral /g"` \
	-c -o printcmd.o -MT printcmd.o -MMD -MP -MF .deps/printcmd.Tpo ./printcmd.c
./printcmd.c: In function ‘do_examine’:
./printcmd.c:899:26: warning: implicit declaration of function ‘find_instruction_backward’; did you mean ‘generic_instruction_nullified’? [-Wimplicit-function-declaration]
           next_address = find_instruction_backward (gdbarch, addr, count,
                          ^~~~~~~~~~~~~~~~~~~~~~~~~
                          generic_instruction_nullified
./printcmd.c:904:26: warning: implicit declaration of function ‘find_string_backward’ [-Wimplicit-function-declaration]
           next_address = find_string_backward (gdbarch, addr, count,
                          ^~~~~~~~~~~~~~~~~~~~
Making init.c
... [ cut ] ...
gcc -g -O2 -m64 -fPIC -mminimal-toc     \
	-o ../../crash ../../crashlib.a rs6000-tdep.o ppc-linux-tdep.o ppc-sysv-tdep.o ppc64-tdep.o solib-svr4.o solib-spu.o spu-multiarch.o glibc-tdep.o symfile-mem.o linux-tdep.o ravenscar-thread.o ppc-ravenscar-thread.o ser-base.o ser-unix.o ser-pipe.o ser-tcp.o inf-ptrace.o fork-child.o ppc-linux-nat.o proc-service.o linux-thread-db.o linux-nat.o linux-osdata.o linux-fork.o linux-procfs.o linux-ptrace.o remote.o dcache.o tracepoint.o ax-general.o ax-gdb.o remote-fileio.o remote-notif.o  cli-dump.o cli-decode.o cli-script.o cli-cmds.o cli-setshow.o cli-logging.o cli-interp.o cli-utils.o mi-out.o mi-console.o mi-cmds.o mi-cmd-catch.o mi-cmd-env.o mi-cmd-var.o mi-cmd-break.o mi-cmd-stack.o mi-cmd-file.o mi-cmd-disas.o mi-symbol-cmds.o mi-cmd-target.o mi-cmd-info.o mi-interp.o mi-main.o mi-parse.o mi-getopt.o tui-command.o tui-data.o tui-disasm.o tui-file.o tui-hooks.o tui-interp.o tui-io.o tui-layout.o tui-out.o tui-regs.o tui-source.o tui-stack.o tui-win.o tui-windata.o tui-wingeneral.o tui-winsource.o tui.o python.o py-value.o py-prettyprint.o py-auto-load.o elfread.o stap-probe.o posix-hdep.o c-exp.o cp-name-parser.o ada-exp.o jv-exp.o f-exp.o go-exp.o m2-exp.o p-exp.o version.o annotate.o addrmap.o auto-load.o auxv.o agent.o bfd-target.o blockframe.o breakpoint.o break-catch-sig.o findvar.o regcache.o cleanups.o charset.o continuations.o corelow.o disasm.o dummy-frame.o dfp.o source.o value.o eval.o valops.o valarith.o valprint.o printcmd.o block.o symtab.o psymtab.o symfile.o symmisc.o linespec.o dictionary.o infcall.o infcmd.o infrun.o expprint.o environ.o stack.o thread.o exceptions.o filesystem.o inf-child.o interps.o minidebug.o main.o macrotab.o macrocmd.o macroexp.o macroscope.o mi-common.o event-loop.o event-top.o inf-loop.o completer.o gdbarch.o arch-utils.o gdbtypes.o gdb_bfd.o gdb_obstack.o osabi.o copying.o memattr.o mem-break.o target.o parse.o language.o buildsym.o findcmd.o std-regs.o signals.o exec.o reverse.o bcache.o objfiles.o observer.o minsyms.o maint.o demangle.o dbxread.o coffread.o coff-pe-read.o dwarf2read.o mipsread.o stabsread.o corefile.o dwarf2expr.o dwarf2loc.o dwarf2-frame.o dwarf2-frame-tailcall.o ada-lang.o c-lang.o d-lang.o f-lang.o objc-lang.o ada-tasks.o ada-varobj.o ui-out.o cli-out.o varobj.o vec.o go-lang.o go-valprint.o go-typeprint.o jv-lang.o jv-valprint.o jv-typeprint.o m2-lang.o opencl-lang.o p-lang.o p-typeprint.o p-valprint.o sentinel-frame.o complaints.o typeprint.o ada-typeprint.o c-typeprint.o f-typeprint.o m2-typeprint.o ada-valprint.o c-valprint.o cp-valprint.o d-valprint.o f-valprint.o m2-valprint.o serial.o mdebugread.o top.o utils.o ui-file.o user-regs.o frame.o frame-unwind.o doublest.o frame-base.o inline-frame.o gnu-v2-abi.o gnu-v3-abi.o cp-abi.o cp-support.o cp-namespace.o reggroups.o regset.o trad-frame.o tramp-frame.o solib.o solib-target.o prologue-value.o memory-map.o memrange.o xml-support.o xml-syscall.o xml-utils.o target-descriptions.o target-memory.o xml-tdesc.o xml-builtin.o inferior.o osdata.o gdb_usleep.o record.o record-full.o gcore.o gdb_vecs.o jit.o progspace.o skip.o probe.o common-utils.o buffer.o ptid.o gdb-dlfcn.o common-agent.o format.o registry.o btrace.o record-btrace.o inflow.o    init.o \
	   ../readline/libreadline.a ../opcodes/libopcodes.a ../bfd/libbfd.a  ../libiberty/libiberty.a ../libdecnumber/libdecnumber.a    -ldl -lncurses -lz -lm   ../libiberty/libiberty.a  build-gnulib/import/libgnu.a -ldl -Wl,--dynamic-list=./proc-service.list  -lz -ldl -rdynamic
printcmd.o: In function `do_examine':
/root/crash.git/gdb-7.6/gdb/./printcmd.c:899: undefined reference to `find_instruction_backward'
/root/crash.git/gdb-7.6/gdb/./printcmd.c:904: undefined reference to `find_string_backward'
collect2: error: ld returned 1 exit status
make[5]: *** [Makefile:1195: gdb] Error 1
make[4]: *** [Makefile:8265: all-gdb] Error 2
make[3]: *** [Makefile:835: all] Error 2
make[2]: *** [Makefile:245: rebuild] Error 2
make[1]: *** [Makefile:233: gdb_merge] Error 2
make: *** [Makefile:314: warn] Error 2
$ 

It will need some additions to help.c as well.

Thanks,
  Dave


> 
> Signed-off-by: Aaron Tomlin <atomlin at redhat.com>
> ---
>  gdb-7.6.patch | 331 ++++++++++++++++++++++++++++++++++++++++++++++++++
>  kernel.c      |  33 ++---
>  2 files changed, 349 insertions(+), 15 deletions(-)
> 
> diff --git a/gdb-7.6.patch b/gdb-7.6.patch
> index cd75dcf..96cdef4 100644
> --- a/gdb-7.6.patch
> +++ b/gdb-7.6.patch
> @@ -2447,3 +2447,334 @@ diff -up gdb-7.6/opcodes/configure.orig
> gdb-7.6/opcodes/configure
>   #else
>   # error "!__i386__ && !__x86_64__"
>   #endif
> +--- gdb-7.6/gdb/printcmd.c.orig
> ++++ gdb-7.6/gdb/printcmd.c
> +@@ -201,8 +201,13 @@ decode_format (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++;
> +
> +@@ -795,6 +800,232 @@ print_address_demangle (const struct
> value_print_options *opts,
> + }
> +
> +
> ++/* 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, func_addr;
> ++  VEC (CORE_ADDR) *pcs = NULL;
> ++  struct symtab_and_line sal;
> ++  struct cleanup *cleanup = make_cleanup (VEC_cleanup (CORE_ADDR), &pcs);
> ++  int actual_count = 0;
> ++
> ++  *inst_read = 0;
> ++  inst_count--;
> ++  loop_start = loop_end = addr;
> ++
> ++  find_pc_partial_function (addr, NULL, &func_addr, NULL);
> ++  for (p = func_addr; p != addr;)
> ++    {
> ++      p += gdb_insn_length (gdbarch, p);
> ++      actual_count++;
> ++    }
> ++  if (inst_count > actual_count)
> ++     inst_count = actual_count;
> ++
> ++  /* 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.  */
> +
> +@@ -808,12 +1039,16 @@ 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;
> ++  int is_backward;
> +
> +   format = fmt.format;
> +   size = fmt.size;
> +   count = fmt.count;
> +   next_gdbarch = gdbarch;
> +   next_address = addr;
> ++  is_backward = count < 0;
> +
> +   /* Instruction format implies fetch single bytes
> +      regardless of the specified size.
> +@@ -878,9 +1113,43 @@ do_examine (struct format_data fmt, struct gdbarch
> *gdbarch, CORE_ADDR addr)
> +
> +   get_formatted_print_options (&opts, format);
> +
> ++  if (is_backward)
> ++    {
> ++      /* 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.  */
> +
> ++  if (is_backward)
> ++    count++;
> +   while (count > 0)
> +     {
> +       QUIT;
> +@@ -923,6 +1192,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;
> + }
> +
> + static void
> +@@ -2535,7 +2807,8 @@ 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\
> + 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/kernel.c b/kernel.c
> index 22909d2..f5960fc 100644
> --- a/kernel.c
> +++ b/kernel.c
> @@ -1931,16 +1931,10 @@ cmd_dis(void)
>                  }
>  
>                  if (args[++optind]) {
> -			if (reverse || forward) {
> -				error(INFO,
> -			            "count argument ignored with -%s option\n",
> -				    	reverse ? "r" : "f");
> -			} else {
> -                        	req->count = stol(args[optind],
> +			req->count = stol(args[optind],
>  					FAULT_ON_ERROR, NULL);
> -				req->flags &= ~GNU_FUNCTION_ONLY;
> -				count_entered++;
> -			}
> +			req->flags &= ~GNU_FUNCTION_ONLY;
> +			count_entered++;
>  		}
>  
>  		if (sources) {
> @@ -1992,6 +1986,10 @@ cmd_dis(void)
>  			}
>  		}
>  
> +		if (reverse || forward)
> +			if (count_entered && req->count == 1)
> +				reverse = forward = 0;
> +
>  		if (reverse || forward) {
>  			target = req->addr;
>  			if ((sp = value_search(target, NULL)) == NULL)
> @@ -2006,14 +2004,19 @@ cmd_dis(void)
>  		do_machdep_filter = machdep->dis_filter(req->addr, NULL, radix);
>  		open_tmpfile();
>  
> -		if (reverse)
> -			sprintf(buf5, "x/%ldi 0x%lx",
> -				(target - req->addr) ? target - req->addr : 1,
> -				req->addr);
> -		else
> +		if (reverse || forward) {
> +			if (count_entered && req->count)
> +				sprintf(buf5, "x/%s%ldi 0x%lx", reverse ? "-" : "",
> +					req->count, target);
> +			else
> +				sprintf(buf5, "x/%ldi 0x%lx",
> +					forward ?  req->addr2 - req->addr :
> +					(target - req->addr) ? target - req->addr : 1,
> +					forward ? target : req->addr);
> +		} else
>  			sprintf(buf5, "x/%ldi 0x%lx",
>  				count_entered && req->count ? req->count :
> -				forward || req->flags & GNU_FUNCTION_ONLY ?
> +				req->flags & GNU_FUNCTION_ONLY ?
>  				req->addr2 - req->addr : 1,
>  				req->addr);
>  		gdb_pass_through(buf5, NULL, GNU_RETURN_ON_ERROR);
> --
> 2.20.1
> 
> --
> Crash-utility mailing list
> Crash-utility at redhat.com
> https://www.redhat.com/mailman/listinfo/crash-utility
> 




More information about the Crash-utility mailing list