[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