xref: /dflybsd-src/contrib/gdb-7/gdb/disasm.c (revision 5796c8dc12c637f18a1740c26afd8d40ffa9b719)
1*5796c8dcSSimon Schubert /* Disassemble support for GDB.
2*5796c8dcSSimon Schubert 
3*5796c8dcSSimon Schubert    Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2007, 2008, 2009
4*5796c8dcSSimon Schubert    Free Software Foundation, Inc.
5*5796c8dcSSimon Schubert 
6*5796c8dcSSimon Schubert    This file is part of GDB.
7*5796c8dcSSimon Schubert 
8*5796c8dcSSimon Schubert    This program is free software; you can redistribute it and/or modify
9*5796c8dcSSimon Schubert    it under the terms of the GNU General Public License as published by
10*5796c8dcSSimon Schubert    the Free Software Foundation; either version 3 of the License, or
11*5796c8dcSSimon Schubert    (at your option) any later version.
12*5796c8dcSSimon Schubert 
13*5796c8dcSSimon Schubert    This program is distributed in the hope that it will be useful,
14*5796c8dcSSimon Schubert    but WITHOUT ANY WARRANTY; without even the implied warranty of
15*5796c8dcSSimon Schubert    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16*5796c8dcSSimon Schubert    GNU General Public License for more details.
17*5796c8dcSSimon Schubert 
18*5796c8dcSSimon Schubert    You should have received a copy of the GNU General Public License
19*5796c8dcSSimon Schubert    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
20*5796c8dcSSimon Schubert 
21*5796c8dcSSimon Schubert #include "defs.h"
22*5796c8dcSSimon Schubert #include "target.h"
23*5796c8dcSSimon Schubert #include "value.h"
24*5796c8dcSSimon Schubert #include "ui-out.h"
25*5796c8dcSSimon Schubert #include "gdb_string.h"
26*5796c8dcSSimon Schubert #include "disasm.h"
27*5796c8dcSSimon Schubert #include "gdbcore.h"
28*5796c8dcSSimon Schubert #include "dis-asm.h"
29*5796c8dcSSimon Schubert 
30*5796c8dcSSimon Schubert /* Disassemble functions.
31*5796c8dcSSimon Schubert    FIXME: We should get rid of all the duplicate code in gdb that does
32*5796c8dcSSimon Schubert    the same thing: disassemble_command() and the gdbtk variation. */
33*5796c8dcSSimon Schubert 
34*5796c8dcSSimon Schubert /* This Structure is used to store line number information.
35*5796c8dcSSimon Schubert    We need a different sort of line table from the normal one cuz we can't
36*5796c8dcSSimon Schubert    depend upon implicit line-end pc's for lines to do the
37*5796c8dcSSimon Schubert    reordering in this function.  */
38*5796c8dcSSimon Schubert 
39*5796c8dcSSimon Schubert struct dis_line_entry
40*5796c8dcSSimon Schubert {
41*5796c8dcSSimon Schubert   int line;
42*5796c8dcSSimon Schubert   CORE_ADDR start_pc;
43*5796c8dcSSimon Schubert   CORE_ADDR end_pc;
44*5796c8dcSSimon Schubert };
45*5796c8dcSSimon Schubert 
46*5796c8dcSSimon Schubert /* Like target_read_memory, but slightly different parameters.  */
47*5796c8dcSSimon Schubert static int
48*5796c8dcSSimon Schubert dis_asm_read_memory (bfd_vma memaddr, gdb_byte *myaddr, unsigned int len,
49*5796c8dcSSimon Schubert 		     struct disassemble_info *info)
50*5796c8dcSSimon Schubert {
51*5796c8dcSSimon Schubert   return target_read_memory (memaddr, myaddr, len);
52*5796c8dcSSimon Schubert }
53*5796c8dcSSimon Schubert 
54*5796c8dcSSimon Schubert /* Like memory_error with slightly different parameters.  */
55*5796c8dcSSimon Schubert static void
56*5796c8dcSSimon Schubert dis_asm_memory_error (int status, bfd_vma memaddr,
57*5796c8dcSSimon Schubert 		      struct disassemble_info *info)
58*5796c8dcSSimon Schubert {
59*5796c8dcSSimon Schubert   memory_error (status, memaddr);
60*5796c8dcSSimon Schubert }
61*5796c8dcSSimon Schubert 
62*5796c8dcSSimon Schubert /* Like print_address with slightly different parameters.  */
63*5796c8dcSSimon Schubert static void
64*5796c8dcSSimon Schubert dis_asm_print_address (bfd_vma addr, struct disassemble_info *info)
65*5796c8dcSSimon Schubert {
66*5796c8dcSSimon Schubert   struct gdbarch *gdbarch = info->application_data;
67*5796c8dcSSimon Schubert   print_address (gdbarch, addr, info->stream);
68*5796c8dcSSimon Schubert }
69*5796c8dcSSimon Schubert 
70*5796c8dcSSimon Schubert static int
71*5796c8dcSSimon Schubert compare_lines (const void *mle1p, const void *mle2p)
72*5796c8dcSSimon Schubert {
73*5796c8dcSSimon Schubert   struct dis_line_entry *mle1, *mle2;
74*5796c8dcSSimon Schubert   int val;
75*5796c8dcSSimon Schubert 
76*5796c8dcSSimon Schubert   mle1 = (struct dis_line_entry *) mle1p;
77*5796c8dcSSimon Schubert   mle2 = (struct dis_line_entry *) mle2p;
78*5796c8dcSSimon Schubert 
79*5796c8dcSSimon Schubert   val = mle1->line - mle2->line;
80*5796c8dcSSimon Schubert 
81*5796c8dcSSimon Schubert   if (val != 0)
82*5796c8dcSSimon Schubert     return val;
83*5796c8dcSSimon Schubert 
84*5796c8dcSSimon Schubert   return mle1->start_pc - mle2->start_pc;
85*5796c8dcSSimon Schubert }
86*5796c8dcSSimon Schubert 
87*5796c8dcSSimon Schubert static int
88*5796c8dcSSimon Schubert dump_insns (struct gdbarch *gdbarch, struct ui_out *uiout,
89*5796c8dcSSimon Schubert 	    struct disassemble_info * di,
90*5796c8dcSSimon Schubert 	    CORE_ADDR low, CORE_ADDR high,
91*5796c8dcSSimon Schubert 	    int how_many, int flags, struct ui_stream *stb)
92*5796c8dcSSimon Schubert {
93*5796c8dcSSimon Schubert   int num_displayed = 0;
94*5796c8dcSSimon Schubert   CORE_ADDR pc;
95*5796c8dcSSimon Schubert 
96*5796c8dcSSimon Schubert   /* parts of the symbolic representation of the address */
97*5796c8dcSSimon Schubert   int unmapped;
98*5796c8dcSSimon Schubert   int offset;
99*5796c8dcSSimon Schubert   int line;
100*5796c8dcSSimon Schubert   struct cleanup *ui_out_chain;
101*5796c8dcSSimon Schubert 
102*5796c8dcSSimon Schubert   for (pc = low; pc < high;)
103*5796c8dcSSimon Schubert     {
104*5796c8dcSSimon Schubert       char *filename = NULL;
105*5796c8dcSSimon Schubert       char *name = NULL;
106*5796c8dcSSimon Schubert 
107*5796c8dcSSimon Schubert       QUIT;
108*5796c8dcSSimon Schubert       if (how_many >= 0)
109*5796c8dcSSimon Schubert 	{
110*5796c8dcSSimon Schubert 	  if (num_displayed >= how_many)
111*5796c8dcSSimon Schubert 	    break;
112*5796c8dcSSimon Schubert 	  else
113*5796c8dcSSimon Schubert 	    num_displayed++;
114*5796c8dcSSimon Schubert 	}
115*5796c8dcSSimon Schubert       ui_out_chain = make_cleanup_ui_out_tuple_begin_end (uiout, NULL);
116*5796c8dcSSimon Schubert       ui_out_field_core_addr (uiout, "address", gdbarch, pc);
117*5796c8dcSSimon Schubert 
118*5796c8dcSSimon Schubert       if (!build_address_symbolic (pc, 0, &name, &offset, &filename,
119*5796c8dcSSimon Schubert 				   &line, &unmapped))
120*5796c8dcSSimon Schubert 	{
121*5796c8dcSSimon Schubert 	  /* We don't care now about line, filename and
122*5796c8dcSSimon Schubert 	     unmapped. But we might in the future. */
123*5796c8dcSSimon Schubert 	  ui_out_text (uiout, " <");
124*5796c8dcSSimon Schubert 	  ui_out_field_string (uiout, "func-name", name);
125*5796c8dcSSimon Schubert 	  ui_out_text (uiout, "+");
126*5796c8dcSSimon Schubert 	  ui_out_field_int (uiout, "offset", offset);
127*5796c8dcSSimon Schubert 	  ui_out_text (uiout, ">:\t");
128*5796c8dcSSimon Schubert 	}
129*5796c8dcSSimon Schubert       else
130*5796c8dcSSimon Schubert 	ui_out_text (uiout, ":\t");
131*5796c8dcSSimon Schubert 
132*5796c8dcSSimon Schubert       if (filename != NULL)
133*5796c8dcSSimon Schubert 	xfree (filename);
134*5796c8dcSSimon Schubert       if (name != NULL)
135*5796c8dcSSimon Schubert 	xfree (name);
136*5796c8dcSSimon Schubert 
137*5796c8dcSSimon Schubert       ui_file_rewind (stb->stream);
138*5796c8dcSSimon Schubert       if (flags & DISASSEMBLY_RAW_INSN)
139*5796c8dcSSimon Schubert         {
140*5796c8dcSSimon Schubert           CORE_ADDR old_pc = pc;
141*5796c8dcSSimon Schubert           bfd_byte data;
142*5796c8dcSSimon Schubert           int status;
143*5796c8dcSSimon Schubert           pc += gdbarch_print_insn (gdbarch, pc, di);
144*5796c8dcSSimon Schubert           for (;old_pc < pc; old_pc++)
145*5796c8dcSSimon Schubert             {
146*5796c8dcSSimon Schubert               status = (*di->read_memory_func) (old_pc, &data, 1, di);
147*5796c8dcSSimon Schubert               if (status != 0)
148*5796c8dcSSimon Schubert                 (*di->memory_error_func) (status, old_pc, di);
149*5796c8dcSSimon Schubert               ui_out_message (uiout, 0, " %02x", (unsigned)data);
150*5796c8dcSSimon Schubert             }
151*5796c8dcSSimon Schubert           ui_out_text (uiout, "\t");
152*5796c8dcSSimon Schubert         }
153*5796c8dcSSimon Schubert       else
154*5796c8dcSSimon Schubert         pc += gdbarch_print_insn (gdbarch, pc, di);
155*5796c8dcSSimon Schubert       ui_out_field_stream (uiout, "inst", stb);
156*5796c8dcSSimon Schubert       ui_file_rewind (stb->stream);
157*5796c8dcSSimon Schubert       do_cleanups (ui_out_chain);
158*5796c8dcSSimon Schubert       ui_out_text (uiout, "\n");
159*5796c8dcSSimon Schubert     }
160*5796c8dcSSimon Schubert   return num_displayed;
161*5796c8dcSSimon Schubert }
162*5796c8dcSSimon Schubert 
163*5796c8dcSSimon Schubert /* The idea here is to present a source-O-centric view of a
164*5796c8dcSSimon Schubert    function to the user.  This means that things are presented
165*5796c8dcSSimon Schubert    in source order, with (possibly) out of order assembly
166*5796c8dcSSimon Schubert    immediately following.  */
167*5796c8dcSSimon Schubert static void
168*5796c8dcSSimon Schubert do_mixed_source_and_assembly (struct gdbarch *gdbarch, struct ui_out *uiout,
169*5796c8dcSSimon Schubert 			      struct disassemble_info *di, int nlines,
170*5796c8dcSSimon Schubert 			      struct linetable_entry *le,
171*5796c8dcSSimon Schubert 			      CORE_ADDR low, CORE_ADDR high,
172*5796c8dcSSimon Schubert 			      struct symtab *symtab,
173*5796c8dcSSimon Schubert 			      int how_many, int flags, struct ui_stream *stb)
174*5796c8dcSSimon Schubert {
175*5796c8dcSSimon Schubert   int newlines = 0;
176*5796c8dcSSimon Schubert   struct dis_line_entry *mle;
177*5796c8dcSSimon Schubert   struct symtab_and_line sal;
178*5796c8dcSSimon Schubert   int i;
179*5796c8dcSSimon Schubert   int out_of_order = 0;
180*5796c8dcSSimon Schubert   int next_line = 0;
181*5796c8dcSSimon Schubert   CORE_ADDR pc;
182*5796c8dcSSimon Schubert   int num_displayed = 0;
183*5796c8dcSSimon Schubert   struct cleanup *ui_out_chain;
184*5796c8dcSSimon Schubert   struct cleanup *ui_out_tuple_chain = make_cleanup (null_cleanup, 0);
185*5796c8dcSSimon Schubert   struct cleanup *ui_out_list_chain = make_cleanup (null_cleanup, 0);
186*5796c8dcSSimon Schubert 
187*5796c8dcSSimon Schubert   mle = (struct dis_line_entry *) alloca (nlines
188*5796c8dcSSimon Schubert 					  * sizeof (struct dis_line_entry));
189*5796c8dcSSimon Schubert 
190*5796c8dcSSimon Schubert   /* Copy linetable entries for this function into our data
191*5796c8dcSSimon Schubert      structure, creating end_pc's and setting out_of_order as
192*5796c8dcSSimon Schubert      appropriate.  */
193*5796c8dcSSimon Schubert 
194*5796c8dcSSimon Schubert   /* First, skip all the preceding functions.  */
195*5796c8dcSSimon Schubert 
196*5796c8dcSSimon Schubert   for (i = 0; i < nlines - 1 && le[i].pc < low; i++);
197*5796c8dcSSimon Schubert 
198*5796c8dcSSimon Schubert   /* Now, copy all entries before the end of this function.  */
199*5796c8dcSSimon Schubert 
200*5796c8dcSSimon Schubert   for (; i < nlines - 1 && le[i].pc < high; i++)
201*5796c8dcSSimon Schubert     {
202*5796c8dcSSimon Schubert       if (le[i].line == le[i + 1].line && le[i].pc == le[i + 1].pc)
203*5796c8dcSSimon Schubert 	continue;		/* Ignore duplicates */
204*5796c8dcSSimon Schubert 
205*5796c8dcSSimon Schubert       /* Skip any end-of-function markers.  */
206*5796c8dcSSimon Schubert       if (le[i].line == 0)
207*5796c8dcSSimon Schubert 	continue;
208*5796c8dcSSimon Schubert 
209*5796c8dcSSimon Schubert       mle[newlines].line = le[i].line;
210*5796c8dcSSimon Schubert       if (le[i].line > le[i + 1].line)
211*5796c8dcSSimon Schubert 	out_of_order = 1;
212*5796c8dcSSimon Schubert       mle[newlines].start_pc = le[i].pc;
213*5796c8dcSSimon Schubert       mle[newlines].end_pc = le[i + 1].pc;
214*5796c8dcSSimon Schubert       newlines++;
215*5796c8dcSSimon Schubert     }
216*5796c8dcSSimon Schubert 
217*5796c8dcSSimon Schubert   /* If we're on the last line, and it's part of the function,
218*5796c8dcSSimon Schubert      then we need to get the end pc in a special way.  */
219*5796c8dcSSimon Schubert 
220*5796c8dcSSimon Schubert   if (i == nlines - 1 && le[i].pc < high)
221*5796c8dcSSimon Schubert     {
222*5796c8dcSSimon Schubert       mle[newlines].line = le[i].line;
223*5796c8dcSSimon Schubert       mle[newlines].start_pc = le[i].pc;
224*5796c8dcSSimon Schubert       sal = find_pc_line (le[i].pc, 0);
225*5796c8dcSSimon Schubert       mle[newlines].end_pc = sal.end;
226*5796c8dcSSimon Schubert       newlines++;
227*5796c8dcSSimon Schubert     }
228*5796c8dcSSimon Schubert 
229*5796c8dcSSimon Schubert   /* Now, sort mle by line #s (and, then by addresses within
230*5796c8dcSSimon Schubert      lines). */
231*5796c8dcSSimon Schubert 
232*5796c8dcSSimon Schubert   if (out_of_order)
233*5796c8dcSSimon Schubert     qsort (mle, newlines, sizeof (struct dis_line_entry), compare_lines);
234*5796c8dcSSimon Schubert 
235*5796c8dcSSimon Schubert   /* Now, for each line entry, emit the specified lines (unless
236*5796c8dcSSimon Schubert      they have been emitted before), followed by the assembly code
237*5796c8dcSSimon Schubert      for that line.  */
238*5796c8dcSSimon Schubert 
239*5796c8dcSSimon Schubert   ui_out_chain = make_cleanup_ui_out_list_begin_end (uiout, "asm_insns");
240*5796c8dcSSimon Schubert 
241*5796c8dcSSimon Schubert   for (i = 0; i < newlines; i++)
242*5796c8dcSSimon Schubert     {
243*5796c8dcSSimon Schubert       /* Print out everything from next_line to the current line.  */
244*5796c8dcSSimon Schubert       if (mle[i].line >= next_line)
245*5796c8dcSSimon Schubert 	{
246*5796c8dcSSimon Schubert 	  if (next_line != 0)
247*5796c8dcSSimon Schubert 	    {
248*5796c8dcSSimon Schubert 	      /* Just one line to print. */
249*5796c8dcSSimon Schubert 	      if (next_line == mle[i].line)
250*5796c8dcSSimon Schubert 		{
251*5796c8dcSSimon Schubert 		  ui_out_tuple_chain
252*5796c8dcSSimon Schubert 		    = make_cleanup_ui_out_tuple_begin_end (uiout,
253*5796c8dcSSimon Schubert 							   "src_and_asm_line");
254*5796c8dcSSimon Schubert 		  print_source_lines (symtab, next_line, mle[i].line + 1, 0);
255*5796c8dcSSimon Schubert 		}
256*5796c8dcSSimon Schubert 	      else
257*5796c8dcSSimon Schubert 		{
258*5796c8dcSSimon Schubert 		  /* Several source lines w/o asm instructions associated. */
259*5796c8dcSSimon Schubert 		  for (; next_line < mle[i].line; next_line++)
260*5796c8dcSSimon Schubert 		    {
261*5796c8dcSSimon Schubert 		      struct cleanup *ui_out_list_chain_line;
262*5796c8dcSSimon Schubert 		      struct cleanup *ui_out_tuple_chain_line;
263*5796c8dcSSimon Schubert 
264*5796c8dcSSimon Schubert 		      ui_out_tuple_chain_line
265*5796c8dcSSimon Schubert 			= make_cleanup_ui_out_tuple_begin_end (uiout,
266*5796c8dcSSimon Schubert 							       "src_and_asm_line");
267*5796c8dcSSimon Schubert 		      print_source_lines (symtab, next_line, next_line + 1,
268*5796c8dcSSimon Schubert 					  0);
269*5796c8dcSSimon Schubert 		      ui_out_list_chain_line
270*5796c8dcSSimon Schubert 			= make_cleanup_ui_out_list_begin_end (uiout,
271*5796c8dcSSimon Schubert 							      "line_asm_insn");
272*5796c8dcSSimon Schubert 		      do_cleanups (ui_out_list_chain_line);
273*5796c8dcSSimon Schubert 		      do_cleanups (ui_out_tuple_chain_line);
274*5796c8dcSSimon Schubert 		    }
275*5796c8dcSSimon Schubert 		  /* Print the last line and leave list open for
276*5796c8dcSSimon Schubert 		     asm instructions to be added. */
277*5796c8dcSSimon Schubert 		  ui_out_tuple_chain
278*5796c8dcSSimon Schubert 		    = make_cleanup_ui_out_tuple_begin_end (uiout,
279*5796c8dcSSimon Schubert 							   "src_and_asm_line");
280*5796c8dcSSimon Schubert 		  print_source_lines (symtab, next_line, mle[i].line + 1, 0);
281*5796c8dcSSimon Schubert 		}
282*5796c8dcSSimon Schubert 	    }
283*5796c8dcSSimon Schubert 	  else
284*5796c8dcSSimon Schubert 	    {
285*5796c8dcSSimon Schubert 	      ui_out_tuple_chain
286*5796c8dcSSimon Schubert 		= make_cleanup_ui_out_tuple_begin_end (uiout, "src_and_asm_line");
287*5796c8dcSSimon Schubert 	      print_source_lines (symtab, mle[i].line, mle[i].line + 1, 0);
288*5796c8dcSSimon Schubert 	    }
289*5796c8dcSSimon Schubert 
290*5796c8dcSSimon Schubert 	  next_line = mle[i].line + 1;
291*5796c8dcSSimon Schubert 	  ui_out_list_chain
292*5796c8dcSSimon Schubert 	    = make_cleanup_ui_out_list_begin_end (uiout, "line_asm_insn");
293*5796c8dcSSimon Schubert 	}
294*5796c8dcSSimon Schubert 
295*5796c8dcSSimon Schubert       num_displayed += dump_insns (gdbarch, uiout, di,
296*5796c8dcSSimon Schubert 				   mle[i].start_pc, mle[i].end_pc,
297*5796c8dcSSimon Schubert 				   how_many, flags, stb);
298*5796c8dcSSimon Schubert 
299*5796c8dcSSimon Schubert       /* When we've reached the end of the mle array, or we've seen the last
300*5796c8dcSSimon Schubert          assembly range for this source line, close out the list/tuple.  */
301*5796c8dcSSimon Schubert       if (i == (newlines - 1) || mle[i + 1].line > mle[i].line)
302*5796c8dcSSimon Schubert 	{
303*5796c8dcSSimon Schubert 	  do_cleanups (ui_out_list_chain);
304*5796c8dcSSimon Schubert 	  do_cleanups (ui_out_tuple_chain);
305*5796c8dcSSimon Schubert 	  ui_out_tuple_chain = make_cleanup (null_cleanup, 0);
306*5796c8dcSSimon Schubert 	  ui_out_list_chain = make_cleanup (null_cleanup, 0);
307*5796c8dcSSimon Schubert 	  ui_out_text (uiout, "\n");
308*5796c8dcSSimon Schubert 	}
309*5796c8dcSSimon Schubert       if (how_many >= 0 && num_displayed >= how_many)
310*5796c8dcSSimon Schubert 	break;
311*5796c8dcSSimon Schubert     }
312*5796c8dcSSimon Schubert   do_cleanups (ui_out_chain);
313*5796c8dcSSimon Schubert }
314*5796c8dcSSimon Schubert 
315*5796c8dcSSimon Schubert 
316*5796c8dcSSimon Schubert static void
317*5796c8dcSSimon Schubert do_assembly_only (struct gdbarch *gdbarch, struct ui_out *uiout,
318*5796c8dcSSimon Schubert 		  struct disassemble_info * di,
319*5796c8dcSSimon Schubert 		  CORE_ADDR low, CORE_ADDR high,
320*5796c8dcSSimon Schubert 		  int how_many, int flags, struct ui_stream *stb)
321*5796c8dcSSimon Schubert {
322*5796c8dcSSimon Schubert   int num_displayed = 0;
323*5796c8dcSSimon Schubert   struct cleanup *ui_out_chain;
324*5796c8dcSSimon Schubert 
325*5796c8dcSSimon Schubert   ui_out_chain = make_cleanup_ui_out_list_begin_end (uiout, "asm_insns");
326*5796c8dcSSimon Schubert 
327*5796c8dcSSimon Schubert   num_displayed = dump_insns (gdbarch, uiout, di, low, high, how_many,
328*5796c8dcSSimon Schubert                               flags, stb);
329*5796c8dcSSimon Schubert 
330*5796c8dcSSimon Schubert   do_cleanups (ui_out_chain);
331*5796c8dcSSimon Schubert }
332*5796c8dcSSimon Schubert 
333*5796c8dcSSimon Schubert /* Initialize the disassemble info struct ready for the specified
334*5796c8dcSSimon Schubert    stream.  */
335*5796c8dcSSimon Schubert 
336*5796c8dcSSimon Schubert static int ATTR_FORMAT (printf, 2, 3)
337*5796c8dcSSimon Schubert fprintf_disasm (void *stream, const char *format, ...)
338*5796c8dcSSimon Schubert {
339*5796c8dcSSimon Schubert   va_list args;
340*5796c8dcSSimon Schubert   va_start (args, format);
341*5796c8dcSSimon Schubert   vfprintf_filtered (stream, format, args);
342*5796c8dcSSimon Schubert   va_end (args);
343*5796c8dcSSimon Schubert   /* Something non -ve.  */
344*5796c8dcSSimon Schubert   return 0;
345*5796c8dcSSimon Schubert }
346*5796c8dcSSimon Schubert 
347*5796c8dcSSimon Schubert static struct disassemble_info
348*5796c8dcSSimon Schubert gdb_disassemble_info (struct gdbarch *gdbarch, struct ui_file *file)
349*5796c8dcSSimon Schubert {
350*5796c8dcSSimon Schubert   struct disassemble_info di;
351*5796c8dcSSimon Schubert   init_disassemble_info (&di, file, fprintf_disasm);
352*5796c8dcSSimon Schubert   di.flavour = bfd_target_unknown_flavour;
353*5796c8dcSSimon Schubert   di.memory_error_func = dis_asm_memory_error;
354*5796c8dcSSimon Schubert   di.print_address_func = dis_asm_print_address;
355*5796c8dcSSimon Schubert   /* NOTE: cagney/2003-04-28: The original code, from the old Insight
356*5796c8dcSSimon Schubert      disassembler had a local optomization here.  By default it would
357*5796c8dcSSimon Schubert      access the executable file, instead of the target memory (there
358*5796c8dcSSimon Schubert      was a growing list of exceptions though).  Unfortunately, the
359*5796c8dcSSimon Schubert      heuristic was flawed.  Commands like "disassemble &variable"
360*5796c8dcSSimon Schubert      didn't work as they relied on the access going to the target.
361*5796c8dcSSimon Schubert      Further, it has been supperseeded by trust-read-only-sections
362*5796c8dcSSimon Schubert      (although that should be superseeded by target_trust..._p()).  */
363*5796c8dcSSimon Schubert   di.read_memory_func = dis_asm_read_memory;
364*5796c8dcSSimon Schubert   di.arch = gdbarch_bfd_arch_info (gdbarch)->arch;
365*5796c8dcSSimon Schubert   di.mach = gdbarch_bfd_arch_info (gdbarch)->mach;
366*5796c8dcSSimon Schubert   di.endian = gdbarch_byte_order (gdbarch);
367*5796c8dcSSimon Schubert   di.endian_code = gdbarch_byte_order_for_code (gdbarch);
368*5796c8dcSSimon Schubert   di.application_data = gdbarch;
369*5796c8dcSSimon Schubert   disassemble_init_for_target (&di);
370*5796c8dcSSimon Schubert   return di;
371*5796c8dcSSimon Schubert }
372*5796c8dcSSimon Schubert 
373*5796c8dcSSimon Schubert void
374*5796c8dcSSimon Schubert gdb_disassembly (struct gdbarch *gdbarch, struct ui_out *uiout,
375*5796c8dcSSimon Schubert 		char *file_string,
376*5796c8dcSSimon Schubert 		int flags,
377*5796c8dcSSimon Schubert 		int how_many, CORE_ADDR low, CORE_ADDR high)
378*5796c8dcSSimon Schubert {
379*5796c8dcSSimon Schubert   struct ui_stream *stb = ui_out_stream_new (uiout);
380*5796c8dcSSimon Schubert   struct cleanup *cleanups = make_cleanup_ui_out_stream_delete (stb);
381*5796c8dcSSimon Schubert   struct disassemble_info di = gdb_disassemble_info (gdbarch, stb->stream);
382*5796c8dcSSimon Schubert   /* To collect the instruction outputted from opcodes. */
383*5796c8dcSSimon Schubert   struct symtab *symtab = NULL;
384*5796c8dcSSimon Schubert   struct linetable_entry *le = NULL;
385*5796c8dcSSimon Schubert   int nlines = -1;
386*5796c8dcSSimon Schubert 
387*5796c8dcSSimon Schubert   /* Assume symtab is valid for whole PC range */
388*5796c8dcSSimon Schubert   symtab = find_pc_symtab (low);
389*5796c8dcSSimon Schubert 
390*5796c8dcSSimon Schubert   if (symtab != NULL && symtab->linetable != NULL)
391*5796c8dcSSimon Schubert     {
392*5796c8dcSSimon Schubert       /* Convert the linetable to a bunch of my_line_entry's.  */
393*5796c8dcSSimon Schubert       le = symtab->linetable->item;
394*5796c8dcSSimon Schubert       nlines = symtab->linetable->nitems;
395*5796c8dcSSimon Schubert     }
396*5796c8dcSSimon Schubert 
397*5796c8dcSSimon Schubert   if (!(flags & DISASSEMBLY_SOURCE) || nlines <= 0
398*5796c8dcSSimon Schubert       || symtab == NULL || symtab->linetable == NULL)
399*5796c8dcSSimon Schubert     do_assembly_only (gdbarch, uiout, &di, low, high, how_many, flags, stb);
400*5796c8dcSSimon Schubert 
401*5796c8dcSSimon Schubert   else if (flags & DISASSEMBLY_SOURCE)
402*5796c8dcSSimon Schubert     do_mixed_source_and_assembly (gdbarch, uiout, &di, nlines, le, low,
403*5796c8dcSSimon Schubert 				  high, symtab, how_many, flags, stb);
404*5796c8dcSSimon Schubert 
405*5796c8dcSSimon Schubert   do_cleanups (cleanups);
406*5796c8dcSSimon Schubert   gdb_flush (gdb_stdout);
407*5796c8dcSSimon Schubert }
408*5796c8dcSSimon Schubert 
409*5796c8dcSSimon Schubert /* Print the instruction at address MEMADDR in debugged memory,
410*5796c8dcSSimon Schubert    on STREAM.  Returns the length of the instruction, in bytes,
411*5796c8dcSSimon Schubert    and, if requested, the number of branch delay slot instructions.  */
412*5796c8dcSSimon Schubert 
413*5796c8dcSSimon Schubert int
414*5796c8dcSSimon Schubert gdb_print_insn (struct gdbarch *gdbarch, CORE_ADDR memaddr,
415*5796c8dcSSimon Schubert 		struct ui_file *stream, int *branch_delay_insns)
416*5796c8dcSSimon Schubert {
417*5796c8dcSSimon Schubert   struct disassemble_info di;
418*5796c8dcSSimon Schubert   int length;
419*5796c8dcSSimon Schubert 
420*5796c8dcSSimon Schubert   di = gdb_disassemble_info (gdbarch, stream);
421*5796c8dcSSimon Schubert   length = gdbarch_print_insn (gdbarch, memaddr, &di);
422*5796c8dcSSimon Schubert   if (branch_delay_insns)
423*5796c8dcSSimon Schubert     {
424*5796c8dcSSimon Schubert       if (di.insn_info_valid)
425*5796c8dcSSimon Schubert 	*branch_delay_insns = di.branch_delay_insns;
426*5796c8dcSSimon Schubert       else
427*5796c8dcSSimon Schubert 	*branch_delay_insns = 0;
428*5796c8dcSSimon Schubert     }
429*5796c8dcSSimon Schubert   return length;
430*5796c8dcSSimon Schubert }
431