xref: /dflybsd-src/contrib/gdb-7/gdb/disasm.c (revision cf7f2e2d389e8012d562650bd94d7e433f449d6e)
15796c8dcSSimon Schubert /* Disassemble support for GDB.
25796c8dcSSimon Schubert 
3*cf7f2e2dSJohn Marino    Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2007, 2008, 2009, 2010
45796c8dcSSimon Schubert    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;
67*cf7f2e2dSJohn 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 
805796c8dcSSimon Schubert   val = mle1->line - mle2->line;
815796c8dcSSimon Schubert 
825796c8dcSSimon Schubert   if (val != 0)
835796c8dcSSimon Schubert     return val;
845796c8dcSSimon Schubert 
855796c8dcSSimon Schubert   return mle1->start_pc - mle2->start_pc;
865796c8dcSSimon Schubert }
875796c8dcSSimon Schubert 
885796c8dcSSimon Schubert static int
895796c8dcSSimon Schubert dump_insns (struct gdbarch *gdbarch, struct ui_out *uiout,
905796c8dcSSimon Schubert 	    struct disassemble_info * di,
915796c8dcSSimon Schubert 	    CORE_ADDR low, CORE_ADDR high,
925796c8dcSSimon Schubert 	    int how_many, int flags, struct ui_stream *stb)
935796c8dcSSimon Schubert {
945796c8dcSSimon Schubert   int num_displayed = 0;
955796c8dcSSimon Schubert   CORE_ADDR pc;
965796c8dcSSimon Schubert 
975796c8dcSSimon Schubert   /* parts of the symbolic representation of the address */
985796c8dcSSimon Schubert   int unmapped;
995796c8dcSSimon Schubert   int offset;
1005796c8dcSSimon Schubert   int line;
1015796c8dcSSimon Schubert   struct cleanup *ui_out_chain;
1025796c8dcSSimon Schubert 
1035796c8dcSSimon Schubert   for (pc = low; pc < high;)
1045796c8dcSSimon Schubert     {
1055796c8dcSSimon Schubert       char *filename = NULL;
1065796c8dcSSimon Schubert       char *name = NULL;
1075796c8dcSSimon Schubert 
1085796c8dcSSimon Schubert       QUIT;
1095796c8dcSSimon Schubert       if (how_many >= 0)
1105796c8dcSSimon Schubert 	{
1115796c8dcSSimon Schubert 	  if (num_displayed >= how_many)
1125796c8dcSSimon Schubert 	    break;
1135796c8dcSSimon Schubert 	  else
1145796c8dcSSimon Schubert 	    num_displayed++;
1155796c8dcSSimon Schubert 	}
1165796c8dcSSimon Schubert       ui_out_chain = make_cleanup_ui_out_tuple_begin_end (uiout, NULL);
117*cf7f2e2dSJohn Marino       ui_out_text (uiout, pc_prefix (pc));
1185796c8dcSSimon Schubert       ui_out_field_core_addr (uiout, "address", gdbarch, pc);
1195796c8dcSSimon Schubert 
120*cf7f2e2dSJohn Marino       if (!build_address_symbolic (gdbarch, pc, 0, &name, &offset, &filename,
1215796c8dcSSimon Schubert 				   &line, &unmapped))
1225796c8dcSSimon Schubert 	{
1235796c8dcSSimon Schubert 	  /* We don't care now about line, filename and
1245796c8dcSSimon Schubert 	     unmapped. But we might in the future. */
1255796c8dcSSimon Schubert 	  ui_out_text (uiout, " <");
126*cf7f2e2dSJohn Marino 	  if ((flags & DISASSEMBLY_OMIT_FNAME) == 0)
1275796c8dcSSimon Schubert 	    ui_out_field_string (uiout, "func-name", name);
1285796c8dcSSimon Schubert 	  ui_out_text (uiout, "+");
1295796c8dcSSimon Schubert 	  ui_out_field_int (uiout, "offset", offset);
1305796c8dcSSimon Schubert 	  ui_out_text (uiout, ">:\t");
1315796c8dcSSimon Schubert 	}
1325796c8dcSSimon Schubert       else
1335796c8dcSSimon Schubert 	ui_out_text (uiout, ":\t");
1345796c8dcSSimon Schubert 
1355796c8dcSSimon Schubert       if (filename != NULL)
1365796c8dcSSimon Schubert 	xfree (filename);
1375796c8dcSSimon Schubert       if (name != NULL)
1385796c8dcSSimon Schubert 	xfree (name);
1395796c8dcSSimon Schubert 
1405796c8dcSSimon Schubert       ui_file_rewind (stb->stream);
1415796c8dcSSimon Schubert       if (flags & DISASSEMBLY_RAW_INSN)
1425796c8dcSSimon Schubert         {
1435796c8dcSSimon Schubert           CORE_ADDR old_pc = pc;
1445796c8dcSSimon Schubert           bfd_byte data;
1455796c8dcSSimon Schubert           int status;
146*cf7f2e2dSJohn Marino 
1475796c8dcSSimon Schubert           pc += gdbarch_print_insn (gdbarch, pc, di);
1485796c8dcSSimon Schubert           for (;old_pc < pc; old_pc++)
1495796c8dcSSimon Schubert             {
1505796c8dcSSimon Schubert               status = (*di->read_memory_func) (old_pc, &data, 1, di);
1515796c8dcSSimon Schubert               if (status != 0)
1525796c8dcSSimon Schubert                 (*di->memory_error_func) (status, old_pc, di);
1535796c8dcSSimon Schubert               ui_out_message (uiout, 0, " %02x", (unsigned)data);
1545796c8dcSSimon Schubert             }
1555796c8dcSSimon Schubert           ui_out_text (uiout, "\t");
1565796c8dcSSimon Schubert         }
1575796c8dcSSimon Schubert       else
1585796c8dcSSimon Schubert         pc += gdbarch_print_insn (gdbarch, pc, di);
1595796c8dcSSimon Schubert       ui_out_field_stream (uiout, "inst", stb);
1605796c8dcSSimon Schubert       ui_file_rewind (stb->stream);
1615796c8dcSSimon Schubert       do_cleanups (ui_out_chain);
1625796c8dcSSimon Schubert       ui_out_text (uiout, "\n");
1635796c8dcSSimon Schubert     }
1645796c8dcSSimon Schubert   return num_displayed;
1655796c8dcSSimon Schubert }
1665796c8dcSSimon Schubert 
1675796c8dcSSimon Schubert /* The idea here is to present a source-O-centric view of a
1685796c8dcSSimon Schubert    function to the user.  This means that things are presented
1695796c8dcSSimon Schubert    in source order, with (possibly) out of order assembly
1705796c8dcSSimon Schubert    immediately following.  */
1715796c8dcSSimon Schubert static void
1725796c8dcSSimon Schubert do_mixed_source_and_assembly (struct gdbarch *gdbarch, struct ui_out *uiout,
1735796c8dcSSimon Schubert 			      struct disassemble_info *di, int nlines,
1745796c8dcSSimon Schubert 			      struct linetable_entry *le,
1755796c8dcSSimon Schubert 			      CORE_ADDR low, CORE_ADDR high,
1765796c8dcSSimon Schubert 			      struct symtab *symtab,
1775796c8dcSSimon Schubert 			      int how_many, int flags, struct ui_stream *stb)
1785796c8dcSSimon Schubert {
1795796c8dcSSimon Schubert   int newlines = 0;
1805796c8dcSSimon Schubert   struct dis_line_entry *mle;
1815796c8dcSSimon Schubert   struct symtab_and_line sal;
1825796c8dcSSimon Schubert   int i;
1835796c8dcSSimon Schubert   int out_of_order = 0;
1845796c8dcSSimon Schubert   int next_line = 0;
1855796c8dcSSimon Schubert   int num_displayed = 0;
1865796c8dcSSimon Schubert   struct cleanup *ui_out_chain;
1875796c8dcSSimon Schubert   struct cleanup *ui_out_tuple_chain = make_cleanup (null_cleanup, 0);
1885796c8dcSSimon Schubert   struct cleanup *ui_out_list_chain = make_cleanup (null_cleanup, 0);
1895796c8dcSSimon Schubert 
1905796c8dcSSimon Schubert   mle = (struct dis_line_entry *) alloca (nlines
1915796c8dcSSimon Schubert 					  * sizeof (struct dis_line_entry));
1925796c8dcSSimon Schubert 
1935796c8dcSSimon Schubert   /* Copy linetable entries for this function into our data
1945796c8dcSSimon Schubert      structure, creating end_pc's and setting out_of_order as
1955796c8dcSSimon Schubert      appropriate.  */
1965796c8dcSSimon Schubert 
1975796c8dcSSimon Schubert   /* First, skip all the preceding functions.  */
1985796c8dcSSimon Schubert 
1995796c8dcSSimon Schubert   for (i = 0; i < nlines - 1 && le[i].pc < low; i++);
2005796c8dcSSimon Schubert 
2015796c8dcSSimon Schubert   /* Now, copy all entries before the end of this function.  */
2025796c8dcSSimon Schubert 
2035796c8dcSSimon Schubert   for (; i < nlines - 1 && le[i].pc < high; i++)
2045796c8dcSSimon Schubert     {
2055796c8dcSSimon Schubert       if (le[i].line == le[i + 1].line && le[i].pc == le[i + 1].pc)
2065796c8dcSSimon Schubert 	continue;		/* Ignore duplicates */
2075796c8dcSSimon Schubert 
2085796c8dcSSimon Schubert       /* Skip any end-of-function markers.  */
2095796c8dcSSimon Schubert       if (le[i].line == 0)
2105796c8dcSSimon Schubert 	continue;
2115796c8dcSSimon Schubert 
2125796c8dcSSimon Schubert       mle[newlines].line = le[i].line;
2135796c8dcSSimon Schubert       if (le[i].line > le[i + 1].line)
2145796c8dcSSimon Schubert 	out_of_order = 1;
2155796c8dcSSimon Schubert       mle[newlines].start_pc = le[i].pc;
2165796c8dcSSimon Schubert       mle[newlines].end_pc = le[i + 1].pc;
2175796c8dcSSimon Schubert       newlines++;
2185796c8dcSSimon Schubert     }
2195796c8dcSSimon Schubert 
2205796c8dcSSimon Schubert   /* If we're on the last line, and it's part of the function,
2215796c8dcSSimon Schubert      then we need to get the end pc in a special way.  */
2225796c8dcSSimon Schubert 
2235796c8dcSSimon Schubert   if (i == nlines - 1 && le[i].pc < high)
2245796c8dcSSimon Schubert     {
2255796c8dcSSimon Schubert       mle[newlines].line = le[i].line;
2265796c8dcSSimon Schubert       mle[newlines].start_pc = le[i].pc;
2275796c8dcSSimon Schubert       sal = find_pc_line (le[i].pc, 0);
2285796c8dcSSimon Schubert       mle[newlines].end_pc = sal.end;
2295796c8dcSSimon Schubert       newlines++;
2305796c8dcSSimon Schubert     }
2315796c8dcSSimon Schubert 
2325796c8dcSSimon Schubert   /* Now, sort mle by line #s (and, then by addresses within
2335796c8dcSSimon Schubert      lines). */
2345796c8dcSSimon Schubert 
2355796c8dcSSimon Schubert   if (out_of_order)
2365796c8dcSSimon Schubert     qsort (mle, newlines, sizeof (struct dis_line_entry), compare_lines);
2375796c8dcSSimon Schubert 
2385796c8dcSSimon Schubert   /* Now, for each line entry, emit the specified lines (unless
2395796c8dcSSimon Schubert      they have been emitted before), followed by the assembly code
2405796c8dcSSimon Schubert      for that line.  */
2415796c8dcSSimon Schubert 
2425796c8dcSSimon Schubert   ui_out_chain = make_cleanup_ui_out_list_begin_end (uiout, "asm_insns");
2435796c8dcSSimon Schubert 
2445796c8dcSSimon Schubert   for (i = 0; i < newlines; i++)
2455796c8dcSSimon Schubert     {
2465796c8dcSSimon Schubert       /* Print out everything from next_line to the current line.  */
2475796c8dcSSimon Schubert       if (mle[i].line >= next_line)
2485796c8dcSSimon Schubert 	{
2495796c8dcSSimon Schubert 	  if (next_line != 0)
2505796c8dcSSimon Schubert 	    {
2515796c8dcSSimon Schubert 	      /* Just one line to print. */
2525796c8dcSSimon Schubert 	      if (next_line == mle[i].line)
2535796c8dcSSimon Schubert 		{
2545796c8dcSSimon Schubert 		  ui_out_tuple_chain
2555796c8dcSSimon Schubert 		    = make_cleanup_ui_out_tuple_begin_end (uiout,
2565796c8dcSSimon Schubert 							   "src_and_asm_line");
2575796c8dcSSimon Schubert 		  print_source_lines (symtab, next_line, mle[i].line + 1, 0);
2585796c8dcSSimon Schubert 		}
2595796c8dcSSimon Schubert 	      else
2605796c8dcSSimon Schubert 		{
2615796c8dcSSimon Schubert 		  /* Several source lines w/o asm instructions associated. */
2625796c8dcSSimon Schubert 		  for (; next_line < mle[i].line; next_line++)
2635796c8dcSSimon Schubert 		    {
2645796c8dcSSimon Schubert 		      struct cleanup *ui_out_list_chain_line;
2655796c8dcSSimon Schubert 		      struct cleanup *ui_out_tuple_chain_line;
2665796c8dcSSimon Schubert 
2675796c8dcSSimon Schubert 		      ui_out_tuple_chain_line
2685796c8dcSSimon Schubert 			= make_cleanup_ui_out_tuple_begin_end (uiout,
2695796c8dcSSimon Schubert 							       "src_and_asm_line");
2705796c8dcSSimon Schubert 		      print_source_lines (symtab, next_line, next_line + 1,
2715796c8dcSSimon Schubert 					  0);
2725796c8dcSSimon Schubert 		      ui_out_list_chain_line
2735796c8dcSSimon Schubert 			= make_cleanup_ui_out_list_begin_end (uiout,
2745796c8dcSSimon Schubert 							      "line_asm_insn");
2755796c8dcSSimon Schubert 		      do_cleanups (ui_out_list_chain_line);
2765796c8dcSSimon Schubert 		      do_cleanups (ui_out_tuple_chain_line);
2775796c8dcSSimon Schubert 		    }
2785796c8dcSSimon Schubert 		  /* Print the last line and leave list open for
2795796c8dcSSimon Schubert 		     asm instructions to be added. */
2805796c8dcSSimon Schubert 		  ui_out_tuple_chain
2815796c8dcSSimon Schubert 		    = make_cleanup_ui_out_tuple_begin_end (uiout,
2825796c8dcSSimon Schubert 							   "src_and_asm_line");
2835796c8dcSSimon Schubert 		  print_source_lines (symtab, next_line, mle[i].line + 1, 0);
2845796c8dcSSimon Schubert 		}
2855796c8dcSSimon Schubert 	    }
2865796c8dcSSimon Schubert 	  else
2875796c8dcSSimon Schubert 	    {
2885796c8dcSSimon Schubert 	      ui_out_tuple_chain
2895796c8dcSSimon Schubert 		= make_cleanup_ui_out_tuple_begin_end (uiout, "src_and_asm_line");
2905796c8dcSSimon Schubert 	      print_source_lines (symtab, mle[i].line, mle[i].line + 1, 0);
2915796c8dcSSimon Schubert 	    }
2925796c8dcSSimon Schubert 
2935796c8dcSSimon Schubert 	  next_line = mle[i].line + 1;
2945796c8dcSSimon Schubert 	  ui_out_list_chain
2955796c8dcSSimon Schubert 	    = make_cleanup_ui_out_list_begin_end (uiout, "line_asm_insn");
2965796c8dcSSimon Schubert 	}
2975796c8dcSSimon Schubert 
2985796c8dcSSimon Schubert       num_displayed += dump_insns (gdbarch, uiout, di,
2995796c8dcSSimon Schubert 				   mle[i].start_pc, mle[i].end_pc,
3005796c8dcSSimon Schubert 				   how_many, flags, stb);
3015796c8dcSSimon Schubert 
3025796c8dcSSimon Schubert       /* When we've reached the end of the mle array, or we've seen the last
3035796c8dcSSimon Schubert          assembly range for this source line, close out the list/tuple.  */
3045796c8dcSSimon Schubert       if (i == (newlines - 1) || mle[i + 1].line > mle[i].line)
3055796c8dcSSimon Schubert 	{
3065796c8dcSSimon Schubert 	  do_cleanups (ui_out_list_chain);
3075796c8dcSSimon Schubert 	  do_cleanups (ui_out_tuple_chain);
3085796c8dcSSimon Schubert 	  ui_out_tuple_chain = make_cleanup (null_cleanup, 0);
3095796c8dcSSimon Schubert 	  ui_out_list_chain = make_cleanup (null_cleanup, 0);
3105796c8dcSSimon Schubert 	  ui_out_text (uiout, "\n");
3115796c8dcSSimon Schubert 	}
3125796c8dcSSimon Schubert       if (how_many >= 0 && num_displayed >= how_many)
3135796c8dcSSimon Schubert 	break;
3145796c8dcSSimon Schubert     }
3155796c8dcSSimon Schubert   do_cleanups (ui_out_chain);
3165796c8dcSSimon Schubert }
3175796c8dcSSimon Schubert 
3185796c8dcSSimon Schubert 
3195796c8dcSSimon Schubert static void
3205796c8dcSSimon Schubert do_assembly_only (struct gdbarch *gdbarch, struct ui_out *uiout,
3215796c8dcSSimon Schubert 		  struct disassemble_info * di,
3225796c8dcSSimon Schubert 		  CORE_ADDR low, CORE_ADDR high,
3235796c8dcSSimon Schubert 		  int how_many, int flags, struct ui_stream *stb)
3245796c8dcSSimon Schubert {
3255796c8dcSSimon Schubert   int num_displayed = 0;
3265796c8dcSSimon Schubert   struct cleanup *ui_out_chain;
3275796c8dcSSimon Schubert 
3285796c8dcSSimon Schubert   ui_out_chain = make_cleanup_ui_out_list_begin_end (uiout, "asm_insns");
3295796c8dcSSimon Schubert 
3305796c8dcSSimon Schubert   num_displayed = dump_insns (gdbarch, uiout, di, low, high, how_many,
3315796c8dcSSimon Schubert                               flags, stb);
3325796c8dcSSimon Schubert 
3335796c8dcSSimon Schubert   do_cleanups (ui_out_chain);
3345796c8dcSSimon Schubert }
3355796c8dcSSimon Schubert 
3365796c8dcSSimon Schubert /* Initialize the disassemble info struct ready for the specified
3375796c8dcSSimon Schubert    stream.  */
3385796c8dcSSimon Schubert 
339*cf7f2e2dSJohn Marino static int ATTRIBUTE_PRINTF (2, 3)
3405796c8dcSSimon Schubert fprintf_disasm (void *stream, const char *format, ...)
3415796c8dcSSimon Schubert {
3425796c8dcSSimon Schubert   va_list args;
343*cf7f2e2dSJohn Marino 
3445796c8dcSSimon Schubert   va_start (args, format);
3455796c8dcSSimon Schubert   vfprintf_filtered (stream, format, args);
3465796c8dcSSimon Schubert   va_end (args);
3475796c8dcSSimon Schubert   /* Something non -ve.  */
3485796c8dcSSimon Schubert   return 0;
3495796c8dcSSimon Schubert }
3505796c8dcSSimon Schubert 
3515796c8dcSSimon Schubert static struct disassemble_info
3525796c8dcSSimon Schubert gdb_disassemble_info (struct gdbarch *gdbarch, struct ui_file *file)
3535796c8dcSSimon Schubert {
3545796c8dcSSimon Schubert   struct disassemble_info di;
355*cf7f2e2dSJohn Marino 
3565796c8dcSSimon Schubert   init_disassemble_info (&di, file, fprintf_disasm);
3575796c8dcSSimon Schubert   di.flavour = bfd_target_unknown_flavour;
3585796c8dcSSimon Schubert   di.memory_error_func = dis_asm_memory_error;
3595796c8dcSSimon Schubert   di.print_address_func = dis_asm_print_address;
3605796c8dcSSimon Schubert   /* NOTE: cagney/2003-04-28: The original code, from the old Insight
3615796c8dcSSimon Schubert      disassembler had a local optomization here.  By default it would
3625796c8dcSSimon Schubert      access the executable file, instead of the target memory (there
3635796c8dcSSimon Schubert      was a growing list of exceptions though).  Unfortunately, the
3645796c8dcSSimon Schubert      heuristic was flawed.  Commands like "disassemble &variable"
3655796c8dcSSimon Schubert      didn't work as they relied on the access going to the target.
3665796c8dcSSimon Schubert      Further, it has been supperseeded by trust-read-only-sections
3675796c8dcSSimon Schubert      (although that should be superseeded by target_trust..._p()).  */
3685796c8dcSSimon Schubert   di.read_memory_func = dis_asm_read_memory;
3695796c8dcSSimon Schubert   di.arch = gdbarch_bfd_arch_info (gdbarch)->arch;
3705796c8dcSSimon Schubert   di.mach = gdbarch_bfd_arch_info (gdbarch)->mach;
3715796c8dcSSimon Schubert   di.endian = gdbarch_byte_order (gdbarch);
3725796c8dcSSimon Schubert   di.endian_code = gdbarch_byte_order_for_code (gdbarch);
3735796c8dcSSimon Schubert   di.application_data = gdbarch;
3745796c8dcSSimon Schubert   disassemble_init_for_target (&di);
3755796c8dcSSimon Schubert   return di;
3765796c8dcSSimon Schubert }
3775796c8dcSSimon Schubert 
3785796c8dcSSimon Schubert void
3795796c8dcSSimon Schubert gdb_disassembly (struct gdbarch *gdbarch, struct ui_out *uiout,
380*cf7f2e2dSJohn Marino 		 char *file_string, int flags, int how_many,
381*cf7f2e2dSJohn Marino 		 CORE_ADDR low, CORE_ADDR high)
3825796c8dcSSimon Schubert {
3835796c8dcSSimon Schubert   struct ui_stream *stb = ui_out_stream_new (uiout);
3845796c8dcSSimon Schubert   struct cleanup *cleanups = make_cleanup_ui_out_stream_delete (stb);
3855796c8dcSSimon Schubert   struct disassemble_info di = gdb_disassemble_info (gdbarch, stb->stream);
3865796c8dcSSimon Schubert   /* To collect the instruction outputted from opcodes. */
3875796c8dcSSimon Schubert   struct symtab *symtab = NULL;
3885796c8dcSSimon Schubert   struct linetable_entry *le = NULL;
3895796c8dcSSimon Schubert   int nlines = -1;
3905796c8dcSSimon Schubert 
3915796c8dcSSimon Schubert   /* Assume symtab is valid for whole PC range */
3925796c8dcSSimon Schubert   symtab = find_pc_symtab (low);
3935796c8dcSSimon Schubert 
3945796c8dcSSimon Schubert   if (symtab != NULL && symtab->linetable != NULL)
3955796c8dcSSimon Schubert     {
3965796c8dcSSimon Schubert       /* Convert the linetable to a bunch of my_line_entry's.  */
3975796c8dcSSimon Schubert       le = symtab->linetable->item;
3985796c8dcSSimon Schubert       nlines = symtab->linetable->nitems;
3995796c8dcSSimon Schubert     }
4005796c8dcSSimon Schubert 
4015796c8dcSSimon Schubert   if (!(flags & DISASSEMBLY_SOURCE) || nlines <= 0
4025796c8dcSSimon Schubert       || symtab == NULL || symtab->linetable == NULL)
4035796c8dcSSimon Schubert     do_assembly_only (gdbarch, uiout, &di, low, high, how_many, flags, stb);
4045796c8dcSSimon Schubert 
4055796c8dcSSimon Schubert   else if (flags & DISASSEMBLY_SOURCE)
4065796c8dcSSimon Schubert     do_mixed_source_and_assembly (gdbarch, uiout, &di, nlines, le, low,
4075796c8dcSSimon Schubert 				  high, symtab, how_many, flags, stb);
4085796c8dcSSimon Schubert 
4095796c8dcSSimon Schubert   do_cleanups (cleanups);
4105796c8dcSSimon Schubert   gdb_flush (gdb_stdout);
4115796c8dcSSimon Schubert }
4125796c8dcSSimon Schubert 
4135796c8dcSSimon Schubert /* Print the instruction at address MEMADDR in debugged memory,
4145796c8dcSSimon Schubert    on STREAM.  Returns the length of the instruction, in bytes,
4155796c8dcSSimon Schubert    and, if requested, the number of branch delay slot instructions.  */
4165796c8dcSSimon Schubert 
4175796c8dcSSimon Schubert int
4185796c8dcSSimon Schubert gdb_print_insn (struct gdbarch *gdbarch, CORE_ADDR memaddr,
4195796c8dcSSimon Schubert 		struct ui_file *stream, int *branch_delay_insns)
4205796c8dcSSimon Schubert {
4215796c8dcSSimon Schubert   struct disassemble_info di;
4225796c8dcSSimon Schubert   int length;
4235796c8dcSSimon Schubert 
4245796c8dcSSimon Schubert   di = gdb_disassemble_info (gdbarch, stream);
4255796c8dcSSimon Schubert   length = gdbarch_print_insn (gdbarch, memaddr, &di);
4265796c8dcSSimon Schubert   if (branch_delay_insns)
4275796c8dcSSimon Schubert     {
4285796c8dcSSimon Schubert       if (di.insn_info_valid)
4295796c8dcSSimon Schubert 	*branch_delay_insns = di.branch_delay_insns;
4305796c8dcSSimon Schubert       else
4315796c8dcSSimon Schubert 	*branch_delay_insns = 0;
4325796c8dcSSimon Schubert     }
4335796c8dcSSimon Schubert   return length;
4345796c8dcSSimon Schubert }
435*cf7f2e2dSJohn Marino 
436*cf7f2e2dSJohn Marino static void
437*cf7f2e2dSJohn Marino do_ui_file_delete (void *arg)
438*cf7f2e2dSJohn Marino {
439*cf7f2e2dSJohn Marino   ui_file_delete (arg);
440*cf7f2e2dSJohn Marino }
441*cf7f2e2dSJohn Marino 
442*cf7f2e2dSJohn Marino /* Return the length in bytes of the instruction at address MEMADDR in
443*cf7f2e2dSJohn Marino    debugged memory.  */
444*cf7f2e2dSJohn Marino 
445*cf7f2e2dSJohn Marino int
446*cf7f2e2dSJohn Marino gdb_insn_length (struct gdbarch *gdbarch, CORE_ADDR addr)
447*cf7f2e2dSJohn Marino {
448*cf7f2e2dSJohn Marino   static struct ui_file *null_stream = NULL;
449*cf7f2e2dSJohn Marino 
450*cf7f2e2dSJohn Marino   /* Dummy file descriptor for the disassembler.  */
451*cf7f2e2dSJohn Marino   if (!null_stream)
452*cf7f2e2dSJohn Marino     {
453*cf7f2e2dSJohn Marino       null_stream = ui_file_new ();
454*cf7f2e2dSJohn Marino       make_final_cleanup (do_ui_file_delete, null_stream);
455*cf7f2e2dSJohn Marino     }
456*cf7f2e2dSJohn Marino 
457*cf7f2e2dSJohn Marino   return gdb_print_insn (gdbarch, addr, null_stream, NULL);
458*cf7f2e2dSJohn Marino }
459*cf7f2e2dSJohn Marino 
460*cf7f2e2dSJohn Marino /* fprintf-function for gdb_buffered_insn_length.  This function is a
461*cf7f2e2dSJohn Marino    nop, we don't want to print anything, we just want to compute the
462*cf7f2e2dSJohn Marino    length of the insn.  */
463*cf7f2e2dSJohn Marino 
464*cf7f2e2dSJohn Marino static int ATTRIBUTE_PRINTF (2, 3)
465*cf7f2e2dSJohn Marino gdb_buffered_insn_length_fprintf (void *stream, const char *format, ...)
466*cf7f2e2dSJohn Marino {
467*cf7f2e2dSJohn Marino   return 0;
468*cf7f2e2dSJohn Marino }
469*cf7f2e2dSJohn Marino 
470*cf7f2e2dSJohn Marino /* Initialize a struct disassemble_info for gdb_buffered_insn_length.  */
471*cf7f2e2dSJohn Marino 
472*cf7f2e2dSJohn Marino static void
473*cf7f2e2dSJohn Marino gdb_buffered_insn_length_init_dis (struct gdbarch *gdbarch,
474*cf7f2e2dSJohn Marino 				   struct disassemble_info *di,
475*cf7f2e2dSJohn Marino 				   const gdb_byte *insn, int max_len,
476*cf7f2e2dSJohn Marino 				   CORE_ADDR addr)
477*cf7f2e2dSJohn Marino {
478*cf7f2e2dSJohn Marino   init_disassemble_info (di, NULL, gdb_buffered_insn_length_fprintf);
479*cf7f2e2dSJohn Marino 
480*cf7f2e2dSJohn Marino   /* init_disassemble_info installs buffer_read_memory, etc.
481*cf7f2e2dSJohn Marino      so we don't need to do that here.
482*cf7f2e2dSJohn Marino      The cast is necessary until disassemble_info is const-ified.  */
483*cf7f2e2dSJohn Marino   di->buffer = (gdb_byte *) insn;
484*cf7f2e2dSJohn Marino   di->buffer_length = max_len;
485*cf7f2e2dSJohn Marino   di->buffer_vma = addr;
486*cf7f2e2dSJohn Marino 
487*cf7f2e2dSJohn Marino   di->arch = gdbarch_bfd_arch_info (gdbarch)->arch;
488*cf7f2e2dSJohn Marino   di->mach = gdbarch_bfd_arch_info (gdbarch)->mach;
489*cf7f2e2dSJohn Marino   di->endian = gdbarch_byte_order (gdbarch);
490*cf7f2e2dSJohn Marino   di->endian_code = gdbarch_byte_order_for_code (gdbarch);
491*cf7f2e2dSJohn Marino 
492*cf7f2e2dSJohn Marino   disassemble_init_for_target (di);
493*cf7f2e2dSJohn Marino }
494*cf7f2e2dSJohn Marino 
495*cf7f2e2dSJohn Marino /* Return the length in bytes of INSN.  MAX_LEN is the size of the
496*cf7f2e2dSJohn Marino    buffer containing INSN.  */
497*cf7f2e2dSJohn Marino 
498*cf7f2e2dSJohn Marino int
499*cf7f2e2dSJohn Marino gdb_buffered_insn_length (struct gdbarch *gdbarch,
500*cf7f2e2dSJohn Marino 			  const gdb_byte *insn, int max_len, CORE_ADDR addr)
501*cf7f2e2dSJohn Marino {
502*cf7f2e2dSJohn Marino   struct disassemble_info di;
503*cf7f2e2dSJohn Marino 
504*cf7f2e2dSJohn Marino   gdb_buffered_insn_length_init_dis (gdbarch, &di, insn, max_len, addr);
505*cf7f2e2dSJohn Marino 
506*cf7f2e2dSJohn Marino   return gdbarch_print_insn (gdbarch, addr, &di);
507*cf7f2e2dSJohn Marino }
508