15796c8dcSSimon Schubert /* Disassemble support for GDB. 25796c8dcSSimon Schubert 3*c50c785cSJohn Marino Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2007, 2008, 2009, 2010, 4*c50c785cSJohn Marino 2011 Free Software Foundation, Inc. 55796c8dcSSimon Schubert 65796c8dcSSimon Schubert This file is part of GDB. 75796c8dcSSimon Schubert 85796c8dcSSimon Schubert This program is free software; you can redistribute it and/or modify 95796c8dcSSimon Schubert it under the terms of the GNU General Public License as published by 105796c8dcSSimon Schubert the Free Software Foundation; either version 3 of the License, or 115796c8dcSSimon Schubert (at your option) any later version. 125796c8dcSSimon Schubert 135796c8dcSSimon Schubert This program is distributed in the hope that it will be useful, 145796c8dcSSimon Schubert but WITHOUT ANY WARRANTY; without even the implied warranty of 155796c8dcSSimon Schubert MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 165796c8dcSSimon Schubert GNU General Public License for more details. 175796c8dcSSimon Schubert 185796c8dcSSimon Schubert You should have received a copy of the GNU General Public License 195796c8dcSSimon Schubert along with this program. If not, see <http://www.gnu.org/licenses/>. */ 205796c8dcSSimon Schubert 215796c8dcSSimon Schubert #include "defs.h" 225796c8dcSSimon Schubert #include "target.h" 235796c8dcSSimon Schubert #include "value.h" 245796c8dcSSimon Schubert #include "ui-out.h" 255796c8dcSSimon Schubert #include "gdb_string.h" 265796c8dcSSimon Schubert #include "disasm.h" 275796c8dcSSimon Schubert #include "gdbcore.h" 285796c8dcSSimon Schubert #include "dis-asm.h" 295796c8dcSSimon Schubert 305796c8dcSSimon Schubert /* Disassemble functions. 315796c8dcSSimon Schubert FIXME: We should get rid of all the duplicate code in gdb that does 325796c8dcSSimon Schubert the same thing: disassemble_command() and the gdbtk variation. */ 335796c8dcSSimon Schubert 345796c8dcSSimon Schubert /* This Structure is used to store line number information. 355796c8dcSSimon Schubert We need a different sort of line table from the normal one cuz we can't 365796c8dcSSimon Schubert depend upon implicit line-end pc's for lines to do the 375796c8dcSSimon Schubert reordering in this function. */ 385796c8dcSSimon Schubert 395796c8dcSSimon Schubert struct dis_line_entry 405796c8dcSSimon Schubert { 415796c8dcSSimon Schubert int line; 425796c8dcSSimon Schubert CORE_ADDR start_pc; 435796c8dcSSimon Schubert CORE_ADDR end_pc; 445796c8dcSSimon Schubert }; 455796c8dcSSimon Schubert 465796c8dcSSimon Schubert /* Like target_read_memory, but slightly different parameters. */ 475796c8dcSSimon Schubert static int 485796c8dcSSimon Schubert dis_asm_read_memory (bfd_vma memaddr, gdb_byte *myaddr, unsigned int len, 495796c8dcSSimon Schubert struct disassemble_info *info) 505796c8dcSSimon Schubert { 515796c8dcSSimon Schubert return target_read_memory (memaddr, myaddr, len); 525796c8dcSSimon Schubert } 535796c8dcSSimon Schubert 545796c8dcSSimon Schubert /* Like memory_error with slightly different parameters. */ 555796c8dcSSimon Schubert static void 565796c8dcSSimon Schubert dis_asm_memory_error (int status, bfd_vma memaddr, 575796c8dcSSimon Schubert struct disassemble_info *info) 585796c8dcSSimon Schubert { 595796c8dcSSimon Schubert memory_error (status, memaddr); 605796c8dcSSimon Schubert } 615796c8dcSSimon Schubert 625796c8dcSSimon Schubert /* Like print_address with slightly different parameters. */ 635796c8dcSSimon Schubert static void 645796c8dcSSimon Schubert dis_asm_print_address (bfd_vma addr, struct disassemble_info *info) 655796c8dcSSimon Schubert { 665796c8dcSSimon Schubert struct gdbarch *gdbarch = info->application_data; 67cf7f2e2dSJohn Marino 685796c8dcSSimon Schubert print_address (gdbarch, addr, info->stream); 695796c8dcSSimon Schubert } 705796c8dcSSimon Schubert 715796c8dcSSimon Schubert static int 725796c8dcSSimon Schubert compare_lines (const void *mle1p, const void *mle2p) 735796c8dcSSimon Schubert { 745796c8dcSSimon Schubert struct dis_line_entry *mle1, *mle2; 755796c8dcSSimon Schubert int val; 765796c8dcSSimon Schubert 775796c8dcSSimon Schubert mle1 = (struct dis_line_entry *) mle1p; 785796c8dcSSimon Schubert mle2 = (struct dis_line_entry *) mle2p; 795796c8dcSSimon Schubert 80*c50c785cSJohn Marino /* End of sequence markers have a line number of 0 but don't want to 81*c50c785cSJohn Marino be sorted to the head of the list, instead sort by PC. */ 82*c50c785cSJohn Marino if (mle1->line == 0 || mle2->line == 0) 83*c50c785cSJohn Marino { 84*c50c785cSJohn Marino val = mle1->start_pc - mle2->start_pc; 85*c50c785cSJohn Marino if (val == 0) 865796c8dcSSimon Schubert val = mle1->line - mle2->line; 87*c50c785cSJohn Marino } 88*c50c785cSJohn Marino else 89*c50c785cSJohn Marino { 90*c50c785cSJohn Marino val = mle1->line - mle2->line; 91*c50c785cSJohn Marino if (val == 0) 92*c50c785cSJohn Marino val = mle1->start_pc - mle2->start_pc; 93*c50c785cSJohn Marino } 945796c8dcSSimon Schubert return val; 955796c8dcSSimon Schubert } 965796c8dcSSimon Schubert 975796c8dcSSimon Schubert static int 985796c8dcSSimon Schubert dump_insns (struct gdbarch *gdbarch, struct ui_out *uiout, 995796c8dcSSimon Schubert struct disassemble_info * di, 1005796c8dcSSimon Schubert CORE_ADDR low, CORE_ADDR high, 1015796c8dcSSimon Schubert int how_many, int flags, struct ui_stream *stb) 1025796c8dcSSimon Schubert { 1035796c8dcSSimon Schubert int num_displayed = 0; 1045796c8dcSSimon Schubert CORE_ADDR pc; 1055796c8dcSSimon Schubert 1065796c8dcSSimon Schubert /* parts of the symbolic representation of the address */ 1075796c8dcSSimon Schubert int unmapped; 1085796c8dcSSimon Schubert int offset; 1095796c8dcSSimon Schubert int line; 1105796c8dcSSimon Schubert struct cleanup *ui_out_chain; 1115796c8dcSSimon Schubert 1125796c8dcSSimon Schubert for (pc = low; pc < high;) 1135796c8dcSSimon Schubert { 1145796c8dcSSimon Schubert char *filename = NULL; 1155796c8dcSSimon Schubert char *name = NULL; 1165796c8dcSSimon Schubert 1175796c8dcSSimon Schubert QUIT; 1185796c8dcSSimon Schubert if (how_many >= 0) 1195796c8dcSSimon Schubert { 1205796c8dcSSimon Schubert if (num_displayed >= how_many) 1215796c8dcSSimon Schubert break; 1225796c8dcSSimon Schubert else 1235796c8dcSSimon Schubert num_displayed++; 1245796c8dcSSimon Schubert } 1255796c8dcSSimon Schubert ui_out_chain = make_cleanup_ui_out_tuple_begin_end (uiout, NULL); 126cf7f2e2dSJohn Marino ui_out_text (uiout, pc_prefix (pc)); 1275796c8dcSSimon Schubert ui_out_field_core_addr (uiout, "address", gdbarch, pc); 1285796c8dcSSimon Schubert 129cf7f2e2dSJohn Marino if (!build_address_symbolic (gdbarch, pc, 0, &name, &offset, &filename, 1305796c8dcSSimon Schubert &line, &unmapped)) 1315796c8dcSSimon Schubert { 1325796c8dcSSimon Schubert /* We don't care now about line, filename and 1335796c8dcSSimon Schubert unmapped. But we might in the future. */ 1345796c8dcSSimon Schubert ui_out_text (uiout, " <"); 135cf7f2e2dSJohn Marino if ((flags & DISASSEMBLY_OMIT_FNAME) == 0) 1365796c8dcSSimon Schubert ui_out_field_string (uiout, "func-name", name); 1375796c8dcSSimon Schubert ui_out_text (uiout, "+"); 1385796c8dcSSimon Schubert ui_out_field_int (uiout, "offset", offset); 1395796c8dcSSimon Schubert ui_out_text (uiout, ">:\t"); 1405796c8dcSSimon Schubert } 1415796c8dcSSimon Schubert else 1425796c8dcSSimon Schubert ui_out_text (uiout, ":\t"); 1435796c8dcSSimon Schubert 1445796c8dcSSimon Schubert if (filename != NULL) 1455796c8dcSSimon Schubert xfree (filename); 1465796c8dcSSimon Schubert if (name != NULL) 1475796c8dcSSimon Schubert xfree (name); 1485796c8dcSSimon Schubert 1495796c8dcSSimon Schubert ui_file_rewind (stb->stream); 1505796c8dcSSimon Schubert if (flags & DISASSEMBLY_RAW_INSN) 1515796c8dcSSimon Schubert { 1525796c8dcSSimon Schubert CORE_ADDR old_pc = pc; 1535796c8dcSSimon Schubert bfd_byte data; 1545796c8dcSSimon Schubert int status; 155*c50c785cSJohn Marino const char *spacer = ""; 156*c50c785cSJohn Marino 157*c50c785cSJohn Marino /* Build the opcodes using a temporary stream so we can 158*c50c785cSJohn Marino write them out in a single go for the MI. */ 159*c50c785cSJohn Marino struct ui_stream *opcode_stream = ui_out_stream_new (uiout); 160*c50c785cSJohn Marino struct cleanup *cleanups = 161*c50c785cSJohn Marino make_cleanup_ui_out_stream_delete (opcode_stream); 162cf7f2e2dSJohn Marino 1635796c8dcSSimon Schubert pc += gdbarch_print_insn (gdbarch, pc, di); 1645796c8dcSSimon Schubert for (;old_pc < pc; old_pc++) 1655796c8dcSSimon Schubert { 1665796c8dcSSimon Schubert status = (*di->read_memory_func) (old_pc, &data, 1, di); 1675796c8dcSSimon Schubert if (status != 0) 1685796c8dcSSimon Schubert (*di->memory_error_func) (status, old_pc, di); 169*c50c785cSJohn Marino fprintf_filtered (opcode_stream->stream, "%s%02x", 170*c50c785cSJohn Marino spacer, (unsigned) data); 171*c50c785cSJohn Marino spacer = " "; 1725796c8dcSSimon Schubert } 173*c50c785cSJohn Marino ui_out_field_stream (uiout, "opcodes", opcode_stream); 1745796c8dcSSimon Schubert ui_out_text (uiout, "\t"); 175*c50c785cSJohn Marino 176*c50c785cSJohn Marino do_cleanups (cleanups); 1775796c8dcSSimon Schubert } 1785796c8dcSSimon Schubert else 1795796c8dcSSimon Schubert pc += gdbarch_print_insn (gdbarch, pc, di); 1805796c8dcSSimon Schubert ui_out_field_stream (uiout, "inst", stb); 1815796c8dcSSimon Schubert ui_file_rewind (stb->stream); 1825796c8dcSSimon Schubert do_cleanups (ui_out_chain); 1835796c8dcSSimon Schubert ui_out_text (uiout, "\n"); 1845796c8dcSSimon Schubert } 1855796c8dcSSimon Schubert return num_displayed; 1865796c8dcSSimon Schubert } 1875796c8dcSSimon Schubert 1885796c8dcSSimon Schubert /* The idea here is to present a source-O-centric view of a 1895796c8dcSSimon Schubert function to the user. This means that things are presented 1905796c8dcSSimon Schubert in source order, with (possibly) out of order assembly 1915796c8dcSSimon Schubert immediately following. */ 192*c50c785cSJohn Marino 1935796c8dcSSimon Schubert static void 1945796c8dcSSimon Schubert do_mixed_source_and_assembly (struct gdbarch *gdbarch, struct ui_out *uiout, 1955796c8dcSSimon Schubert struct disassemble_info *di, int nlines, 1965796c8dcSSimon Schubert struct linetable_entry *le, 1975796c8dcSSimon Schubert CORE_ADDR low, CORE_ADDR high, 1985796c8dcSSimon Schubert struct symtab *symtab, 1995796c8dcSSimon Schubert int how_many, int flags, struct ui_stream *stb) 2005796c8dcSSimon Schubert { 2015796c8dcSSimon Schubert int newlines = 0; 2025796c8dcSSimon Schubert struct dis_line_entry *mle; 2035796c8dcSSimon Schubert struct symtab_and_line sal; 2045796c8dcSSimon Schubert int i; 2055796c8dcSSimon Schubert int out_of_order = 0; 2065796c8dcSSimon Schubert int next_line = 0; 2075796c8dcSSimon Schubert int num_displayed = 0; 2085796c8dcSSimon Schubert struct cleanup *ui_out_chain; 2095796c8dcSSimon Schubert struct cleanup *ui_out_tuple_chain = make_cleanup (null_cleanup, 0); 2105796c8dcSSimon Schubert struct cleanup *ui_out_list_chain = make_cleanup (null_cleanup, 0); 2115796c8dcSSimon Schubert 2125796c8dcSSimon Schubert mle = (struct dis_line_entry *) alloca (nlines 2135796c8dcSSimon Schubert * sizeof (struct dis_line_entry)); 2145796c8dcSSimon Schubert 2155796c8dcSSimon Schubert /* Copy linetable entries for this function into our data 2165796c8dcSSimon Schubert structure, creating end_pc's and setting out_of_order as 2175796c8dcSSimon Schubert appropriate. */ 2185796c8dcSSimon Schubert 2195796c8dcSSimon Schubert /* First, skip all the preceding functions. */ 2205796c8dcSSimon Schubert 2215796c8dcSSimon Schubert for (i = 0; i < nlines - 1 && le[i].pc < low; i++); 2225796c8dcSSimon Schubert 2235796c8dcSSimon Schubert /* Now, copy all entries before the end of this function. */ 2245796c8dcSSimon Schubert 2255796c8dcSSimon Schubert for (; i < nlines - 1 && le[i].pc < high; i++) 2265796c8dcSSimon Schubert { 2275796c8dcSSimon Schubert if (le[i].line == le[i + 1].line && le[i].pc == le[i + 1].pc) 228*c50c785cSJohn Marino continue; /* Ignore duplicates. */ 2295796c8dcSSimon Schubert 2305796c8dcSSimon Schubert /* Skip any end-of-function markers. */ 2315796c8dcSSimon Schubert if (le[i].line == 0) 2325796c8dcSSimon Schubert continue; 2335796c8dcSSimon Schubert 2345796c8dcSSimon Schubert mle[newlines].line = le[i].line; 2355796c8dcSSimon Schubert if (le[i].line > le[i + 1].line) 2365796c8dcSSimon Schubert out_of_order = 1; 2375796c8dcSSimon Schubert mle[newlines].start_pc = le[i].pc; 2385796c8dcSSimon Schubert mle[newlines].end_pc = le[i + 1].pc; 2395796c8dcSSimon Schubert newlines++; 2405796c8dcSSimon Schubert } 2415796c8dcSSimon Schubert 2425796c8dcSSimon Schubert /* If we're on the last line, and it's part of the function, 2435796c8dcSSimon Schubert then we need to get the end pc in a special way. */ 2445796c8dcSSimon Schubert 2455796c8dcSSimon Schubert if (i == nlines - 1 && le[i].pc < high) 2465796c8dcSSimon Schubert { 2475796c8dcSSimon Schubert mle[newlines].line = le[i].line; 2485796c8dcSSimon Schubert mle[newlines].start_pc = le[i].pc; 2495796c8dcSSimon Schubert sal = find_pc_line (le[i].pc, 0); 2505796c8dcSSimon Schubert mle[newlines].end_pc = sal.end; 2515796c8dcSSimon Schubert newlines++; 2525796c8dcSSimon Schubert } 2535796c8dcSSimon Schubert 2545796c8dcSSimon Schubert /* Now, sort mle by line #s (and, then by addresses within 2555796c8dcSSimon Schubert lines). */ 2565796c8dcSSimon Schubert 2575796c8dcSSimon Schubert if (out_of_order) 2585796c8dcSSimon Schubert qsort (mle, newlines, sizeof (struct dis_line_entry), compare_lines); 2595796c8dcSSimon Schubert 2605796c8dcSSimon Schubert /* Now, for each line entry, emit the specified lines (unless 2615796c8dcSSimon Schubert they have been emitted before), followed by the assembly code 2625796c8dcSSimon Schubert for that line. */ 2635796c8dcSSimon Schubert 2645796c8dcSSimon Schubert ui_out_chain = make_cleanup_ui_out_list_begin_end (uiout, "asm_insns"); 2655796c8dcSSimon Schubert 2665796c8dcSSimon Schubert for (i = 0; i < newlines; i++) 2675796c8dcSSimon Schubert { 2685796c8dcSSimon Schubert /* Print out everything from next_line to the current line. */ 2695796c8dcSSimon Schubert if (mle[i].line >= next_line) 2705796c8dcSSimon Schubert { 2715796c8dcSSimon Schubert if (next_line != 0) 2725796c8dcSSimon Schubert { 2735796c8dcSSimon Schubert /* Just one line to print. */ 2745796c8dcSSimon Schubert if (next_line == mle[i].line) 2755796c8dcSSimon Schubert { 2765796c8dcSSimon Schubert ui_out_tuple_chain 2775796c8dcSSimon Schubert = make_cleanup_ui_out_tuple_begin_end (uiout, 2785796c8dcSSimon Schubert "src_and_asm_line"); 2795796c8dcSSimon Schubert print_source_lines (symtab, next_line, mle[i].line + 1, 0); 2805796c8dcSSimon Schubert } 2815796c8dcSSimon Schubert else 2825796c8dcSSimon Schubert { 2835796c8dcSSimon Schubert /* Several source lines w/o asm instructions associated. */ 2845796c8dcSSimon Schubert for (; next_line < mle[i].line; next_line++) 2855796c8dcSSimon Schubert { 2865796c8dcSSimon Schubert struct cleanup *ui_out_list_chain_line; 2875796c8dcSSimon Schubert struct cleanup *ui_out_tuple_chain_line; 2885796c8dcSSimon Schubert 2895796c8dcSSimon Schubert ui_out_tuple_chain_line 2905796c8dcSSimon Schubert = make_cleanup_ui_out_tuple_begin_end (uiout, 2915796c8dcSSimon Schubert "src_and_asm_line"); 2925796c8dcSSimon Schubert print_source_lines (symtab, next_line, next_line + 1, 2935796c8dcSSimon Schubert 0); 2945796c8dcSSimon Schubert ui_out_list_chain_line 2955796c8dcSSimon Schubert = make_cleanup_ui_out_list_begin_end (uiout, 2965796c8dcSSimon Schubert "line_asm_insn"); 2975796c8dcSSimon Schubert do_cleanups (ui_out_list_chain_line); 2985796c8dcSSimon Schubert do_cleanups (ui_out_tuple_chain_line); 2995796c8dcSSimon Schubert } 3005796c8dcSSimon Schubert /* Print the last line and leave list open for 3015796c8dcSSimon Schubert asm instructions to be added. */ 3025796c8dcSSimon Schubert ui_out_tuple_chain 3035796c8dcSSimon Schubert = make_cleanup_ui_out_tuple_begin_end (uiout, 3045796c8dcSSimon Schubert "src_and_asm_line"); 3055796c8dcSSimon Schubert print_source_lines (symtab, next_line, mle[i].line + 1, 0); 3065796c8dcSSimon Schubert } 3075796c8dcSSimon Schubert } 3085796c8dcSSimon Schubert else 3095796c8dcSSimon Schubert { 3105796c8dcSSimon Schubert ui_out_tuple_chain 311*c50c785cSJohn Marino = make_cleanup_ui_out_tuple_begin_end (uiout, 312*c50c785cSJohn Marino "src_and_asm_line"); 3135796c8dcSSimon Schubert print_source_lines (symtab, mle[i].line, mle[i].line + 1, 0); 3145796c8dcSSimon Schubert } 3155796c8dcSSimon Schubert 3165796c8dcSSimon Schubert next_line = mle[i].line + 1; 3175796c8dcSSimon Schubert ui_out_list_chain 3185796c8dcSSimon Schubert = make_cleanup_ui_out_list_begin_end (uiout, "line_asm_insn"); 3195796c8dcSSimon Schubert } 3205796c8dcSSimon Schubert 3215796c8dcSSimon Schubert num_displayed += dump_insns (gdbarch, uiout, di, 3225796c8dcSSimon Schubert mle[i].start_pc, mle[i].end_pc, 3235796c8dcSSimon Schubert how_many, flags, stb); 3245796c8dcSSimon Schubert 3255796c8dcSSimon Schubert /* When we've reached the end of the mle array, or we've seen the last 3265796c8dcSSimon Schubert assembly range for this source line, close out the list/tuple. */ 3275796c8dcSSimon Schubert if (i == (newlines - 1) || mle[i + 1].line > mle[i].line) 3285796c8dcSSimon Schubert { 3295796c8dcSSimon Schubert do_cleanups (ui_out_list_chain); 3305796c8dcSSimon Schubert do_cleanups (ui_out_tuple_chain); 3315796c8dcSSimon Schubert ui_out_tuple_chain = make_cleanup (null_cleanup, 0); 3325796c8dcSSimon Schubert ui_out_list_chain = make_cleanup (null_cleanup, 0); 3335796c8dcSSimon Schubert ui_out_text (uiout, "\n"); 3345796c8dcSSimon Schubert } 3355796c8dcSSimon Schubert if (how_many >= 0 && num_displayed >= how_many) 3365796c8dcSSimon Schubert break; 3375796c8dcSSimon Schubert } 3385796c8dcSSimon Schubert do_cleanups (ui_out_chain); 3395796c8dcSSimon Schubert } 3405796c8dcSSimon Schubert 3415796c8dcSSimon Schubert 3425796c8dcSSimon Schubert static void 3435796c8dcSSimon Schubert do_assembly_only (struct gdbarch *gdbarch, struct ui_out *uiout, 3445796c8dcSSimon Schubert struct disassemble_info * di, 3455796c8dcSSimon Schubert CORE_ADDR low, CORE_ADDR high, 3465796c8dcSSimon Schubert int how_many, int flags, struct ui_stream *stb) 3475796c8dcSSimon Schubert { 3485796c8dcSSimon Schubert int num_displayed = 0; 3495796c8dcSSimon Schubert struct cleanup *ui_out_chain; 3505796c8dcSSimon Schubert 3515796c8dcSSimon Schubert ui_out_chain = make_cleanup_ui_out_list_begin_end (uiout, "asm_insns"); 3525796c8dcSSimon Schubert 3535796c8dcSSimon Schubert num_displayed = dump_insns (gdbarch, uiout, di, low, high, how_many, 3545796c8dcSSimon Schubert flags, stb); 3555796c8dcSSimon Schubert 3565796c8dcSSimon Schubert do_cleanups (ui_out_chain); 3575796c8dcSSimon Schubert } 3585796c8dcSSimon Schubert 3595796c8dcSSimon Schubert /* Initialize the disassemble info struct ready for the specified 3605796c8dcSSimon Schubert stream. */ 3615796c8dcSSimon Schubert 362cf7f2e2dSJohn Marino static int ATTRIBUTE_PRINTF (2, 3) 3635796c8dcSSimon Schubert fprintf_disasm (void *stream, const char *format, ...) 3645796c8dcSSimon Schubert { 3655796c8dcSSimon Schubert va_list args; 366cf7f2e2dSJohn Marino 3675796c8dcSSimon Schubert va_start (args, format); 3685796c8dcSSimon Schubert vfprintf_filtered (stream, format, args); 3695796c8dcSSimon Schubert va_end (args); 3705796c8dcSSimon Schubert /* Something non -ve. */ 3715796c8dcSSimon Schubert return 0; 3725796c8dcSSimon Schubert } 3735796c8dcSSimon Schubert 3745796c8dcSSimon Schubert static struct disassemble_info 3755796c8dcSSimon Schubert gdb_disassemble_info (struct gdbarch *gdbarch, struct ui_file *file) 3765796c8dcSSimon Schubert { 3775796c8dcSSimon Schubert struct disassemble_info di; 378cf7f2e2dSJohn Marino 3795796c8dcSSimon Schubert init_disassemble_info (&di, file, fprintf_disasm); 3805796c8dcSSimon Schubert di.flavour = bfd_target_unknown_flavour; 3815796c8dcSSimon Schubert di.memory_error_func = dis_asm_memory_error; 3825796c8dcSSimon Schubert di.print_address_func = dis_asm_print_address; 3835796c8dcSSimon Schubert /* NOTE: cagney/2003-04-28: The original code, from the old Insight 3845796c8dcSSimon Schubert disassembler had a local optomization here. By default it would 3855796c8dcSSimon Schubert access the executable file, instead of the target memory (there 3865796c8dcSSimon Schubert was a growing list of exceptions though). Unfortunately, the 3875796c8dcSSimon Schubert heuristic was flawed. Commands like "disassemble &variable" 3885796c8dcSSimon Schubert didn't work as they relied on the access going to the target. 3895796c8dcSSimon Schubert Further, it has been supperseeded by trust-read-only-sections 3905796c8dcSSimon Schubert (although that should be superseeded by target_trust..._p()). */ 3915796c8dcSSimon Schubert di.read_memory_func = dis_asm_read_memory; 3925796c8dcSSimon Schubert di.arch = gdbarch_bfd_arch_info (gdbarch)->arch; 3935796c8dcSSimon Schubert di.mach = gdbarch_bfd_arch_info (gdbarch)->mach; 3945796c8dcSSimon Schubert di.endian = gdbarch_byte_order (gdbarch); 3955796c8dcSSimon Schubert di.endian_code = gdbarch_byte_order_for_code (gdbarch); 3965796c8dcSSimon Schubert di.application_data = gdbarch; 3975796c8dcSSimon Schubert disassemble_init_for_target (&di); 3985796c8dcSSimon Schubert return di; 3995796c8dcSSimon Schubert } 4005796c8dcSSimon Schubert 4015796c8dcSSimon Schubert void 4025796c8dcSSimon Schubert gdb_disassembly (struct gdbarch *gdbarch, struct ui_out *uiout, 403cf7f2e2dSJohn Marino char *file_string, int flags, int how_many, 404cf7f2e2dSJohn Marino CORE_ADDR low, CORE_ADDR high) 4055796c8dcSSimon Schubert { 4065796c8dcSSimon Schubert struct ui_stream *stb = ui_out_stream_new (uiout); 4075796c8dcSSimon Schubert struct cleanup *cleanups = make_cleanup_ui_out_stream_delete (stb); 4085796c8dcSSimon Schubert struct disassemble_info di = gdb_disassemble_info (gdbarch, stb->stream); 4095796c8dcSSimon Schubert /* To collect the instruction outputted from opcodes. */ 4105796c8dcSSimon Schubert struct symtab *symtab = NULL; 4115796c8dcSSimon Schubert struct linetable_entry *le = NULL; 4125796c8dcSSimon Schubert int nlines = -1; 4135796c8dcSSimon Schubert 414*c50c785cSJohn Marino /* Assume symtab is valid for whole PC range. */ 4155796c8dcSSimon Schubert symtab = find_pc_symtab (low); 4165796c8dcSSimon Schubert 4175796c8dcSSimon Schubert if (symtab != NULL && symtab->linetable != NULL) 4185796c8dcSSimon Schubert { 4195796c8dcSSimon Schubert /* Convert the linetable to a bunch of my_line_entry's. */ 4205796c8dcSSimon Schubert le = symtab->linetable->item; 4215796c8dcSSimon Schubert nlines = symtab->linetable->nitems; 4225796c8dcSSimon Schubert } 4235796c8dcSSimon Schubert 4245796c8dcSSimon Schubert if (!(flags & DISASSEMBLY_SOURCE) || nlines <= 0 4255796c8dcSSimon Schubert || symtab == NULL || symtab->linetable == NULL) 4265796c8dcSSimon Schubert do_assembly_only (gdbarch, uiout, &di, low, high, how_many, flags, stb); 4275796c8dcSSimon Schubert 4285796c8dcSSimon Schubert else if (flags & DISASSEMBLY_SOURCE) 4295796c8dcSSimon Schubert do_mixed_source_and_assembly (gdbarch, uiout, &di, nlines, le, low, 4305796c8dcSSimon Schubert high, symtab, how_many, flags, stb); 4315796c8dcSSimon Schubert 4325796c8dcSSimon Schubert do_cleanups (cleanups); 4335796c8dcSSimon Schubert gdb_flush (gdb_stdout); 4345796c8dcSSimon Schubert } 4355796c8dcSSimon Schubert 4365796c8dcSSimon Schubert /* Print the instruction at address MEMADDR in debugged memory, 4375796c8dcSSimon Schubert on STREAM. Returns the length of the instruction, in bytes, 4385796c8dcSSimon Schubert and, if requested, the number of branch delay slot instructions. */ 4395796c8dcSSimon Schubert 4405796c8dcSSimon Schubert int 4415796c8dcSSimon Schubert gdb_print_insn (struct gdbarch *gdbarch, CORE_ADDR memaddr, 4425796c8dcSSimon Schubert struct ui_file *stream, int *branch_delay_insns) 4435796c8dcSSimon Schubert { 4445796c8dcSSimon Schubert struct disassemble_info di; 4455796c8dcSSimon Schubert int length; 4465796c8dcSSimon Schubert 4475796c8dcSSimon Schubert di = gdb_disassemble_info (gdbarch, stream); 4485796c8dcSSimon Schubert length = gdbarch_print_insn (gdbarch, memaddr, &di); 4495796c8dcSSimon Schubert if (branch_delay_insns) 4505796c8dcSSimon Schubert { 4515796c8dcSSimon Schubert if (di.insn_info_valid) 4525796c8dcSSimon Schubert *branch_delay_insns = di.branch_delay_insns; 4535796c8dcSSimon Schubert else 4545796c8dcSSimon Schubert *branch_delay_insns = 0; 4555796c8dcSSimon Schubert } 4565796c8dcSSimon Schubert return length; 4575796c8dcSSimon Schubert } 458cf7f2e2dSJohn Marino 459cf7f2e2dSJohn Marino static void 460cf7f2e2dSJohn Marino do_ui_file_delete (void *arg) 461cf7f2e2dSJohn Marino { 462cf7f2e2dSJohn Marino ui_file_delete (arg); 463cf7f2e2dSJohn Marino } 464cf7f2e2dSJohn Marino 465cf7f2e2dSJohn Marino /* Return the length in bytes of the instruction at address MEMADDR in 466cf7f2e2dSJohn Marino debugged memory. */ 467cf7f2e2dSJohn Marino 468cf7f2e2dSJohn Marino int 469cf7f2e2dSJohn Marino gdb_insn_length (struct gdbarch *gdbarch, CORE_ADDR addr) 470cf7f2e2dSJohn Marino { 471cf7f2e2dSJohn Marino static struct ui_file *null_stream = NULL; 472cf7f2e2dSJohn Marino 473cf7f2e2dSJohn Marino /* Dummy file descriptor for the disassembler. */ 474cf7f2e2dSJohn Marino if (!null_stream) 475cf7f2e2dSJohn Marino { 476cf7f2e2dSJohn Marino null_stream = ui_file_new (); 477cf7f2e2dSJohn Marino make_final_cleanup (do_ui_file_delete, null_stream); 478cf7f2e2dSJohn Marino } 479cf7f2e2dSJohn Marino 480cf7f2e2dSJohn Marino return gdb_print_insn (gdbarch, addr, null_stream, NULL); 481cf7f2e2dSJohn Marino } 482cf7f2e2dSJohn Marino 483cf7f2e2dSJohn Marino /* fprintf-function for gdb_buffered_insn_length. This function is a 484cf7f2e2dSJohn Marino nop, we don't want to print anything, we just want to compute the 485cf7f2e2dSJohn Marino length of the insn. */ 486cf7f2e2dSJohn Marino 487cf7f2e2dSJohn Marino static int ATTRIBUTE_PRINTF (2, 3) 488cf7f2e2dSJohn Marino gdb_buffered_insn_length_fprintf (void *stream, const char *format, ...) 489cf7f2e2dSJohn Marino { 490cf7f2e2dSJohn Marino return 0; 491cf7f2e2dSJohn Marino } 492cf7f2e2dSJohn Marino 493cf7f2e2dSJohn Marino /* Initialize a struct disassemble_info for gdb_buffered_insn_length. */ 494cf7f2e2dSJohn Marino 495cf7f2e2dSJohn Marino static void 496cf7f2e2dSJohn Marino gdb_buffered_insn_length_init_dis (struct gdbarch *gdbarch, 497cf7f2e2dSJohn Marino struct disassemble_info *di, 498cf7f2e2dSJohn Marino const gdb_byte *insn, int max_len, 499cf7f2e2dSJohn Marino CORE_ADDR addr) 500cf7f2e2dSJohn Marino { 501cf7f2e2dSJohn Marino init_disassemble_info (di, NULL, gdb_buffered_insn_length_fprintf); 502cf7f2e2dSJohn Marino 503cf7f2e2dSJohn Marino /* init_disassemble_info installs buffer_read_memory, etc. 504cf7f2e2dSJohn Marino so we don't need to do that here. 505cf7f2e2dSJohn Marino The cast is necessary until disassemble_info is const-ified. */ 506cf7f2e2dSJohn Marino di->buffer = (gdb_byte *) insn; 507cf7f2e2dSJohn Marino di->buffer_length = max_len; 508cf7f2e2dSJohn Marino di->buffer_vma = addr; 509cf7f2e2dSJohn Marino 510cf7f2e2dSJohn Marino di->arch = gdbarch_bfd_arch_info (gdbarch)->arch; 511cf7f2e2dSJohn Marino di->mach = gdbarch_bfd_arch_info (gdbarch)->mach; 512cf7f2e2dSJohn Marino di->endian = gdbarch_byte_order (gdbarch); 513cf7f2e2dSJohn Marino di->endian_code = gdbarch_byte_order_for_code (gdbarch); 514cf7f2e2dSJohn Marino 515cf7f2e2dSJohn Marino disassemble_init_for_target (di); 516cf7f2e2dSJohn Marino } 517cf7f2e2dSJohn Marino 518cf7f2e2dSJohn Marino /* Return the length in bytes of INSN. MAX_LEN is the size of the 519cf7f2e2dSJohn Marino buffer containing INSN. */ 520cf7f2e2dSJohn Marino 521cf7f2e2dSJohn Marino int 522cf7f2e2dSJohn Marino gdb_buffered_insn_length (struct gdbarch *gdbarch, 523cf7f2e2dSJohn Marino const gdb_byte *insn, int max_len, CORE_ADDR addr) 524cf7f2e2dSJohn Marino { 525cf7f2e2dSJohn Marino struct disassemble_info di; 526cf7f2e2dSJohn Marino 527cf7f2e2dSJohn Marino gdb_buffered_insn_length_init_dis (gdbarch, &di, insn, max_len, addr); 528cf7f2e2dSJohn Marino 529cf7f2e2dSJohn Marino return gdbarch_print_insn (gdbarch, addr, &di); 530cf7f2e2dSJohn Marino } 531