diff --git a/gdb/printcmd.c b/gdb/printcmd.c index f5c4211..a6cf141 100644 --- a/gdb/printcmd.c +++ b/gdb/printcmd.c @@ -47,6 +47,7 @@ #include "cli/cli-utils.h" #include "format.h" #include "source.h" +#include "linespec.h" #ifdef TUI #include "tui/tui.h" /* For tui_active et al. */ @@ -785,6 +786,97 @@ print_address_demangle (const struct value_print_options *opts, } +/* These empty functions are used in disassemble_backward to + suppress standard output during the call to gdbarch_print_insn. */ + +static int +null_fprintf (void *stream, const char *format ATTRIBUTE_UNUSED, ...) +{ + return 0; +} + +static void +null_print_address (bfd_vma addr, struct disassemble_info *info) +{ + return; +} + +/* Rewind assembly from addr and return the start address after the given + number of lines are disassembled. To avoid disassembling in a wrong frame, + we get addresses in a correct frame using line information. + If we go out of the symbol range during disassembling, we return + the smallest address we've got so far. */ + +static CORE_ADDR +disassemble_backward(struct gdbarch *gdbarch, CORE_ADDR addr, + int count, int *linesread) +{ + char addrstr[64]; + struct symtabs_and_lines sals; + CORE_ADDR start_pc, end_pc, ret; + + start_pc = end_pc = ret = 0; + *linesread = 0; + + sprintf (addrstr, "*%p", (void *) (addr - 1)); + sals = decode_line_with_last_displayed (addrstr, DECODE_LINE_FUNFIRSTLINE); + if (sals.nelts >= 1) + { + if ((!sals.sals[0].line) + || (!find_line_pc_range (sals.sals[0], &start_pc, &end_pc))) + { + printf_filtered (_("No line number information available " + "for address ")); + wrap_here (" "); + print_address (gdbarch, addr - 1, gdb_stdout); + printf_filtered ("\n"); + start_pc = end_pc = 0; + } + xfree (sals.sals); + } + + if (start_pc) + { + VEC (CORE_ADDR) *pcs = NULL; + struct disassemble_info di; + CORE_ADDR p; + int i; + + VEC_reserve (CORE_ADDR, pcs, count); + + di = gdb_disassemble_info (gdbarch, NULL); + di.fprintf_func = null_fprintf; + di.print_address_func = null_print_address; + + p = start_pc; + for (i = 0; p < addr; ++i) + { + VEC_safe_push (CORE_ADDR, pcs, p); + p += gdbarch_print_insn (gdbarch, (CORE_ADDR)p, &di); + } + + if (i >= count) + { + ret = VEC_index (CORE_ADDR, pcs, i - count); + *linesread = count; + } + else + { + int linesread_internal = 0; + ret = disassemble_backward (gdbarch, VEC_index (CORE_ADDR, pcs, 0), + count - i, &linesread_internal); + *linesread = i + linesread_internal; + + /* Return the smallest valid address we've got + if the recursive call above failed. */ + if (!ret) + ret = VEC_index (CORE_ADDR, pcs, 0); + } + VEC_free (CORE_ADDR, pcs); + } + return ret; +} + /* Examine data at address ADDR in format FMT. Fetch it from memory and print on gdb_stdout. */ @@ -798,6 +890,7 @@ do_examine (struct format_data fmt, struct gdbarch *gdbarch, CORE_ADDR addr) int i; int maxelts; struct value_print_options opts; + CORE_ADDR addr_rewound = 0; format = fmt.format; size = fmt.size; @@ -805,6 +898,24 @@ do_examine (struct format_data fmt, struct gdbarch *gdbarch, CORE_ADDR addr) next_gdbarch = gdbarch; next_address = addr; + if (format == 'j') + { + /* If 'j' is given, we get the address after going back + by 'count' instructions from addr and dump instructions + from it by setting format to 'i'. + At the end of this function, we adjust next_address + for subsequent command calls. */ + int linesread = 0; + addr_rewound = next_address = disassemble_backward (gdbarch, + addr, count, &linesread); + if (!next_address) + { + return; + } + count = linesread; + format = 'i'; + } + /* Instruction format implies fetch single bytes regardless of the specified size. The case of strings is handled in decode_format, only explicit @@ -913,6 +1024,9 @@ do_examine (struct format_data fmt, struct gdbarch *gdbarch, CORE_ADDR addr) printf_filtered ("\n"); gdb_flush (gdb_stdout); } + + if (addr_rewound) + next_address = addr_rewound; } static void @@ -2518,8 +2632,8 @@ Examine memory: x/FMT ADDRESS.\n\ ADDRESS is an expression for the memory address to examine.\n\ FMT is a repeat count followed by a format letter and a size letter.\n\ Format letters are o(octal), x(hex), d(decimal), u(unsigned decimal),\n\ - t(binary), f(float), a(address), i(instruction), c(char), s(string)\n\ - and z(hex, zero padded on the left).\n\ + t(binary), f(float), a(address), i(instruction), j(instruction backward),\n\ + c(char), s(string) 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\