X-Git-Url: http://git.efficios.com/?a=blobdiff_plain;f=gdb%2Fdisasm.c;h=9d36f151f30444a60086f491b055fbf97e82f6e5;hb=7a8eb317c5bce0f1ff290a9343777db74adec663;hp=940592864387c83a71a977398556c18db178807a;hpb=618f726fcb851883a0094aa7fa17003889b7189f;p=deliverable%2Fbinutils-gdb.git diff --git a/gdb/disasm.c b/gdb/disasm.c index 9405928643..9d36f151f3 100644 --- a/gdb/disasm.c +++ b/gdb/disasm.c @@ -1,6 +1,6 @@ /* Disassemble support for GDB. - Copyright (C) 2000-2016 Free Software Foundation, Inc. + Copyright (C) 2000-2017 Free Software Foundation, Inc. This file is part of GDB. @@ -25,6 +25,7 @@ #include "gdbcore.h" #include "dis-asm.h" #include "source.h" +#include /* Disassemble functions. FIXME: We should get rid of all the duplicate code in gdb that does @@ -86,11 +87,10 @@ allocate_dis_line_table (void) xfree, xcalloc, xfree); } -/* Add DLE to TABLE. - Returns 1 if added, 0 if already present. */ +/* Add a new dis_line_entry containing SYMTAB and LINE to TABLE. */ static void -maybe_add_dis_line_entry (htab_t table, struct symtab *symtab, int line) +add_dis_line_entry (htab_t table, struct symtab *symtab, int line) { void **slot; struct dis_line_entry dle, *dlep; @@ -119,29 +119,38 @@ line_has_code_p (htab_t table, struct symtab *symtab, int line) return htab_find (table, &dle) != NULL; } -/* Like target_read_memory, but slightly different parameters. */ -static int -dis_asm_read_memory (bfd_vma memaddr, gdb_byte *myaddr, unsigned int len, - struct disassemble_info *info) +/* Wrapper of target_read_code. */ + +int +gdb_disassembler::dis_asm_read_memory (bfd_vma memaddr, gdb_byte *myaddr, + unsigned int len, + struct disassemble_info *info) { return target_read_code (memaddr, myaddr, len); } -/* Like memory_error with slightly different parameters. */ -static void -dis_asm_memory_error (int err, bfd_vma memaddr, - struct disassemble_info *info) +/* Wrapper of memory_error. */ + +void +gdb_disassembler::dis_asm_memory_error (int err, bfd_vma memaddr, + struct disassemble_info *info) { - memory_error (TARGET_XFER_E_IO, memaddr); + gdb_disassembler *self + = static_cast(info->application_data); + + self->m_err_memaddr = memaddr; } -/* Like print_address with slightly different parameters. */ -static void -dis_asm_print_address (bfd_vma addr, struct disassemble_info *info) +/* Wrapper of print_address. */ + +void +gdb_disassembler::dis_asm_print_address (bfd_vma addr, + struct disassemble_info *info) { - struct gdbarch *gdbarch = (struct gdbarch *) info->application_data; + gdb_disassembler *self + = static_cast(info->application_data); - print_address (gdbarch, addr, (struct ui_file *) info->stream); + print_address (self->arch (), addr, self->stream ()); } static int @@ -173,10 +182,9 @@ compare_lines (const void *mle1p, const void *mle2p) /* See disasm.h. */ int -gdb_pretty_print_insn (struct gdbarch *gdbarch, struct ui_out *uiout, - struct disassemble_info * di, - const struct disasm_insn *insn, int flags, - struct ui_file *stb) +gdb_disassembler::pretty_print_insn (struct ui_out *uiout, + const struct disasm_insn *insn, + int flags) { /* parts of the symbolic representation of the address */ int unmapped; @@ -187,53 +195,55 @@ gdb_pretty_print_insn (struct gdbarch *gdbarch, struct ui_out *uiout, char *filename = NULL; char *name = NULL; CORE_ADDR pc; + struct ui_file *stb = stream (); + struct gdbarch *gdbarch = arch (); ui_out_chain = make_cleanup_ui_out_tuple_begin_end (uiout, NULL); pc = insn->addr; if (insn->number != 0) { - ui_out_field_fmt (uiout, "insn-number", "%u", insn->number); - ui_out_text (uiout, "\t"); + uiout->field_fmt ("insn-number", "%u", insn->number); + uiout->text ("\t"); } if ((flags & DISASSEMBLY_SPECULATIVE) != 0) { if (insn->is_speculative) { - ui_out_field_string (uiout, "is-speculative", "?"); + uiout->field_string ("is-speculative", "?"); /* The speculative execution indication overwrites the first character of the PC prefix. We assume a PC prefix length of 3 characters. */ if ((flags & DISASSEMBLY_OMIT_PC) == 0) - ui_out_text (uiout, pc_prefix (pc) + 1); + uiout->text (pc_prefix (pc) + 1); else - ui_out_text (uiout, " "); + uiout->text (" "); } else if ((flags & DISASSEMBLY_OMIT_PC) == 0) - ui_out_text (uiout, pc_prefix (pc)); + uiout->text (pc_prefix (pc)); else - ui_out_text (uiout, " "); + uiout->text (" "); } else if ((flags & DISASSEMBLY_OMIT_PC) == 0) - ui_out_text (uiout, pc_prefix (pc)); - ui_out_field_core_addr (uiout, "address", gdbarch, pc); + uiout->text (pc_prefix (pc)); + uiout->field_core_addr ("address", gdbarch, pc); if (!build_address_symbolic (gdbarch, pc, 0, &name, &offset, &filename, &line, &unmapped)) { /* We don't care now about line, filename and unmapped. But we might in the future. */ - ui_out_text (uiout, " <"); + uiout->text (" <"); if ((flags & DISASSEMBLY_OMIT_FNAME) == 0) - ui_out_field_string (uiout, "func-name", name); - ui_out_text (uiout, "+"); - ui_out_field_int (uiout, "offset", offset); - ui_out_text (uiout, ">:\t"); + uiout->field_string ("func-name", name); + uiout->text ("+"); + uiout->field_int ("offset", offset); + uiout->text (">:\t"); } else - ui_out_text (uiout, ":\t"); + uiout->text (":\t"); if (filename != NULL) xfree (filename); @@ -254,40 +264,39 @@ gdb_pretty_print_insn (struct gdbarch *gdbarch, struct ui_out *uiout, struct cleanup *cleanups = make_cleanup_ui_file_delete (opcode_stream); - size = gdbarch_print_insn (gdbarch, pc, di); + size = print_insn (pc); end_pc = pc + size; for (;pc < end_pc; ++pc) { - err = (*di->read_memory_func) (pc, &data, 1, di); + err = m_di.read_memory_func (pc, &data, 1, &m_di); if (err != 0) - (*di->memory_error_func) (err, pc, di); + m_di.memory_error_func (err, pc, &m_di); fprintf_filtered (opcode_stream, "%s%02x", spacer, (unsigned) data); spacer = " "; } - ui_out_field_stream (uiout, "opcodes", opcode_stream); - ui_out_text (uiout, "\t"); + uiout->field_stream ("opcodes", opcode_stream); + uiout->text ("\t"); do_cleanups (cleanups); } else - size = gdbarch_print_insn (gdbarch, pc, di); + size = print_insn (pc); - ui_out_field_stream (uiout, "inst", stb); + uiout->field_stream ("inst", stb); ui_file_rewind (stb); do_cleanups (ui_out_chain); - ui_out_text (uiout, "\n"); + uiout->text ("\n"); return size; } static int -dump_insns (struct gdbarch *gdbarch, struct ui_out *uiout, - struct disassemble_info * di, +dump_insns (struct ui_out *uiout, gdb_disassembler *di, CORE_ADDR low, CORE_ADDR high, - int how_many, int flags, struct ui_file *stb, + int how_many, int flags, CORE_ADDR *end_pc) { struct disasm_insn insn; @@ -300,7 +309,7 @@ dump_insns (struct gdbarch *gdbarch, struct ui_out *uiout, { int size; - size = gdb_pretty_print_insn (gdbarch, uiout, di, &insn, flags, stb); + size = di->pretty_print_insn (uiout, &insn, flags); if (size <= 0) break; @@ -326,10 +335,10 @@ dump_insns (struct gdbarch *gdbarch, struct ui_out *uiout, static void do_mixed_source_and_assembly_deprecated - (struct gdbarch *gdbarch, struct ui_out *uiout, - struct disassemble_info *di, struct symtab *symtab, + (struct ui_out *uiout, + gdb_disassembler *di, struct symtab *symtab, CORE_ADDR low, CORE_ADDR high, - int how_many, int flags, struct ui_file *stb) + int how_many, int flags) { int newlines = 0; int nlines; @@ -462,9 +471,9 @@ do_mixed_source_and_assembly_deprecated = make_cleanup_ui_out_list_begin_end (uiout, "line_asm_insn"); } - num_displayed += dump_insns (gdbarch, uiout, di, + num_displayed += dump_insns (uiout, di, mle[i].start_pc, mle[i].end_pc, - how_many, flags, stb, NULL); + how_many, flags, NULL); /* When we've reached the end of the mle array, or we've seen the last assembly range for this source line, close out the list/tuple. */ @@ -474,7 +483,7 @@ do_mixed_source_and_assembly_deprecated do_cleanups (ui_out_tuple_chain); ui_out_tuple_chain = make_cleanup (null_cleanup, 0); ui_out_list_chain = make_cleanup (null_cleanup, 0); - ui_out_text (uiout, "\n"); + uiout->text ("\n"); } if (how_many >= 0 && num_displayed >= how_many) break; @@ -488,28 +497,23 @@ do_mixed_source_and_assembly_deprecated immediately following. */ static void -do_mixed_source_and_assembly (struct gdbarch *gdbarch, struct ui_out *uiout, - struct disassemble_info *di, +do_mixed_source_and_assembly (struct gdbarch *gdbarch, + struct ui_out *uiout, + gdb_disassembler *di, struct symtab *main_symtab, CORE_ADDR low, CORE_ADDR high, - int how_many, int flags, struct ui_file *stb) + int how_many, int flags) { - int newlines = 0; const struct linetable_entry *le, *first_le; - struct symtab_and_line sal; int i, nlines; - int out_of_order = 0; - int next_line = 0; int num_displayed = 0; print_source_lines_flags psl_flags = 0; - struct cleanup *cleanups; struct cleanup *ui_out_chain; struct cleanup *ui_out_tuple_chain; struct cleanup *ui_out_list_chain; CORE_ADDR pc; struct symtab *last_symtab; int last_line; - htab_t dis_line_table; gdb_assert (main_symtab != NULL && SYMTAB_LINETABLE (main_symtab) != NULL); @@ -519,8 +523,7 @@ do_mixed_source_and_assembly (struct gdbarch *gdbarch, struct ui_out *uiout, but if that text is for code that will be disassembled later, then we'll want to defer printing it until later with its associated code. */ - dis_line_table = allocate_dis_line_table (); - cleanups = make_cleanup_htab_delete (dis_line_table); + htab_up dis_line_table (allocate_dis_line_table ()); pc = low; @@ -552,7 +555,7 @@ do_mixed_source_and_assembly (struct gdbarch *gdbarch, struct ui_out *uiout, pc += length; if (sal.symtab != NULL) - maybe_add_dis_line_entry (dis_line_table, sal.symtab, sal.line); + add_dis_line_entry (dis_line_table.get (), sal.symtab, sal.line); } /* Second pass: print the disassembly. @@ -569,9 +572,6 @@ do_mixed_source_and_assembly (struct gdbarch *gdbarch, struct ui_out *uiout, which is where we put file name and source line contents output. Cleanup usage: - cleanups: - For things created at the beginning of this function and need to be - kept until the end of this function. ui_out_chain Handles the outer "asm_insns" list. ui_out_tuple_chain @@ -593,7 +593,6 @@ do_mixed_source_and_assembly (struct gdbarch *gdbarch, struct ui_out *uiout, while (pc < high) { - struct linetable_entry *le = NULL; struct symtab_and_line sal; CORE_ADDR end_pc; int start_preceding_line_to_display = 0; @@ -630,7 +629,8 @@ do_mixed_source_and_assembly (struct gdbarch *gdbarch, struct ui_out *uiout, not associated with code that we'll print later. */ for (l = sal.line - 1; l > last_line; --l) { - if (line_has_code_p (dis_line_table, sal.symtab, l)) + if (line_has_code_p (dis_line_table.get (), + sal.symtab, l)) break; } if (l < sal.line - 1) @@ -653,7 +653,7 @@ do_mixed_source_and_assembly (struct gdbarch *gdbarch, struct ui_out *uiout, { /* Skip the newline if this is the first instruction. */ if (pc > low) - ui_out_text (uiout, "\n"); + uiout->text ("\n"); if (ui_out_tuple_chain != NULL) { gdb_assert (ui_out_list_chain != NULL); @@ -668,12 +668,11 @@ do_mixed_source_and_assembly (struct gdbarch *gdbarch, struct ui_out *uiout, output includes the source specs for each line. */ if (sal.symtab != NULL) { - ui_out_text (uiout, - symtab_to_filename_for_display (sal.symtab)); + uiout->text (symtab_to_filename_for_display (sal.symtab)); } else - ui_out_text (uiout, "unknown"); - ui_out_text (uiout, ":\n"); + uiout->text ("unknown"); + uiout->text (":\n"); } if (start_preceding_line_to_display > 0) { @@ -705,7 +704,7 @@ do_mixed_source_and_assembly (struct gdbarch *gdbarch, struct ui_out *uiout, if (sal.symtab != NULL) print_source_lines (sal.symtab, sal.line, sal.line + 1, psl_flags); else - ui_out_text (uiout, _("--- no source info for this pc ---\n")); + uiout->text (_("--- no source info for this pc ---\n")); ui_out_list_chain = make_cleanup_ui_out_list_begin_end (uiout, "line_asm_insn"); } @@ -719,11 +718,11 @@ do_mixed_source_and_assembly (struct gdbarch *gdbarch, struct ui_out *uiout, } if (sal.end != 0) - end_pc = min (sal.end, high); + end_pc = std::min (sal.end, high); else end_pc = pc + 1; - num_displayed += dump_insns (gdbarch, uiout, di, pc, end_pc, - how_many, flags, stb, &end_pc); + num_displayed += dump_insns (uiout, di, pc, end_pc, + how_many, flags, &end_pc); pc = end_pc; if (how_many >= 0 && num_displayed >= how_many) @@ -734,22 +733,19 @@ do_mixed_source_and_assembly (struct gdbarch *gdbarch, struct ui_out *uiout, } do_cleanups (ui_out_chain); - do_cleanups (cleanups); } static void -do_assembly_only (struct gdbarch *gdbarch, struct ui_out *uiout, - struct disassemble_info * di, +do_assembly_only (struct ui_out *uiout, + gdb_disassembler *di, CORE_ADDR low, CORE_ADDR high, - int how_many, int flags, struct ui_file *stb) + int how_many, int flags) { - int num_displayed = 0; struct cleanup *ui_out_chain; ui_out_chain = make_cleanup_ui_out_list_begin_end (uiout, "asm_insns"); - num_displayed = dump_insns (gdbarch, uiout, di, low, high, how_many, - flags, stb, NULL); + dump_insns (uiout, di, low, high, how_many, flags, NULL); do_cleanups (ui_out_chain); } @@ -769,15 +765,16 @@ fprintf_disasm (void *stream, const char *format, ...) return 0; } -struct disassemble_info -gdb_disassemble_info (struct gdbarch *gdbarch, struct ui_file *file) +gdb_disassembler::gdb_disassembler (struct gdbarch *gdbarch, + struct ui_file *file, + di_read_memory_ftype read_memory_func) + : m_gdbarch (gdbarch), + m_err_memaddr (0) { - struct disassemble_info di; - - init_disassemble_info (&di, file, fprintf_disasm); - di.flavour = bfd_target_unknown_flavour; - di.memory_error_func = dis_asm_memory_error; - di.print_address_func = dis_asm_print_address; + init_disassemble_info (&m_di, file, fprintf_disasm); + m_di.flavour = bfd_target_unknown_flavour; + m_di.memory_error_func = dis_asm_memory_error; + m_di.print_address_func = dis_asm_print_address; /* NOTE: cagney/2003-04-28: The original code, from the old Insight disassembler had a local optomization here. By default it would access the executable file, instead of the target memory (there @@ -786,26 +783,45 @@ gdb_disassemble_info (struct gdbarch *gdbarch, struct ui_file *file) didn't work as they relied on the access going to the target. Further, it has been supperseeded by trust-read-only-sections (although that should be superseeded by target_trust..._p()). */ - di.read_memory_func = dis_asm_read_memory; - di.arch = gdbarch_bfd_arch_info (gdbarch)->arch; - di.mach = gdbarch_bfd_arch_info (gdbarch)->mach; - di.endian = gdbarch_byte_order (gdbarch); - di.endian_code = gdbarch_byte_order_for_code (gdbarch); - di.application_data = gdbarch; - disassemble_init_for_target (&di); - return di; + m_di.read_memory_func = read_memory_func; + m_di.arch = gdbarch_bfd_arch_info (gdbarch)->arch; + m_di.mach = gdbarch_bfd_arch_info (gdbarch)->mach; + m_di.endian = gdbarch_byte_order (gdbarch); + m_di.endian_code = gdbarch_byte_order_for_code (gdbarch); + m_di.application_data = this; + disassemble_init_for_target (&m_di); +} + +int +gdb_disassembler::print_insn (CORE_ADDR memaddr, + int *branch_delay_insns) +{ + m_err_memaddr = 0; + + int length = gdbarch_print_insn (arch (), memaddr, &m_di); + + if (length < 0) + memory_error (TARGET_XFER_E_IO, m_err_memaddr); + + if (branch_delay_insns != NULL) + { + if (m_di.insn_info_valid) + *branch_delay_insns = m_di.branch_delay_insns; + else + *branch_delay_insns = 0; + } + return length; } void gdb_disassembly (struct gdbarch *gdbarch, struct ui_out *uiout, - char *file_string, int flags, int how_many, + int flags, int how_many, CORE_ADDR low, CORE_ADDR high) { struct ui_file *stb = mem_fileopen (); struct cleanup *cleanups = make_cleanup_ui_file_delete (stb); - struct disassemble_info di = gdb_disassemble_info (gdbarch, stb); + gdb_disassembler di (gdbarch, stb); struct symtab *symtab; - struct linetable_entry *le = NULL; int nlines = -1; /* Assume symtab is valid for whole PC range. */ @@ -816,15 +832,15 @@ gdb_disassembly (struct gdbarch *gdbarch, struct ui_out *uiout, if (!(flags & (DISASSEMBLY_SOURCE_DEPRECATED | DISASSEMBLY_SOURCE)) || nlines <= 0) - do_assembly_only (gdbarch, uiout, &di, low, high, how_many, flags, stb); + do_assembly_only (uiout, &di, low, high, how_many, flags); else if (flags & DISASSEMBLY_SOURCE) do_mixed_source_and_assembly (gdbarch, uiout, &di, symtab, low, high, - how_many, flags, stb); + how_many, flags); else if (flags & DISASSEMBLY_SOURCE_DEPRECATED) - do_mixed_source_and_assembly_deprecated (gdbarch, uiout, &di, symtab, - low, high, how_many, flags, stb); + do_mixed_source_and_assembly_deprecated (uiout, &di, symtab, + low, high, how_many, flags); do_cleanups (cleanups); gdb_flush (gdb_stdout); @@ -838,25 +854,10 @@ int gdb_print_insn (struct gdbarch *gdbarch, CORE_ADDR memaddr, struct ui_file *stream, int *branch_delay_insns) { - struct disassemble_info di; - int length; - di = gdb_disassemble_info (gdbarch, stream); - length = gdbarch_print_insn (gdbarch, memaddr, &di); - if (branch_delay_insns) - { - if (di.insn_info_valid) - *branch_delay_insns = di.branch_delay_insns; - else - *branch_delay_insns = 0; - } - return length; -} + gdb_disassembler di (gdbarch, stream); -static void -do_ui_file_delete (void *arg) -{ - ui_file_delete ((struct ui_file *) arg); + return di.print_insn (memaddr, branch_delay_insns); } /* Return the length in bytes of the instruction at address MEMADDR in @@ -865,16 +866,7 @@ do_ui_file_delete (void *arg) int gdb_insn_length (struct gdbarch *gdbarch, CORE_ADDR addr) { - static struct ui_file *null_stream = NULL; - - /* Dummy file descriptor for the disassembler. */ - if (!null_stream) - { - null_stream = ui_file_new (); - make_final_cleanup (do_ui_file_delete, null_stream); - } - - return gdb_print_insn (gdbarch, addr, null_stream, NULL); + return gdb_print_insn (gdbarch, addr, null_stream (), NULL); } /* fprintf-function for gdb_buffered_insn_length. This function is a