xref: /netbsd-src/external/gpl3/gdb.old/dist/gdb/disasm.c (revision bdc22b2e01993381dcefeff2bc9b56ca75a4235c)
1 /* Disassemble support for GDB.
2 
3    Copyright (C) 2000-2016 Free Software Foundation, Inc.
4 
5    This file is part of GDB.
6 
7    This program is free software; you can redistribute it and/or modify
8    it under the terms of the GNU General Public License as published by
9    the Free Software Foundation; either version 3 of the License, or
10    (at your option) any later version.
11 
12    This program is distributed in the hope that it will be useful,
13    but WITHOUT ANY WARRANTY; without even the implied warranty of
14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15    GNU General Public License for more details.
16 
17    You should have received a copy of the GNU General Public License
18    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
19 
20 #include "defs.h"
21 #include "target.h"
22 #include "value.h"
23 #include "ui-out.h"
24 #include "disasm.h"
25 #include "gdbcore.h"
26 #include "dis-asm.h"
27 #include "source.h"
28 
29 /* Disassemble functions.
30    FIXME: We should get rid of all the duplicate code in gdb that does
31    the same thing: disassemble_command() and the gdbtk variation.  */
32 
33 /* This structure is used to store line number information for the
34    deprecated /m option.
35    We need a different sort of line table from the normal one cuz we can't
36    depend upon implicit line-end pc's for lines to do the
37    reordering in this function.  */
38 
39 struct deprecated_dis_line_entry
40 {
41   int line;
42   CORE_ADDR start_pc;
43   CORE_ADDR end_pc;
44 };
45 
46 /* This Structure is used to store line number information.
47    We need a different sort of line table from the normal one cuz we can't
48    depend upon implicit line-end pc's for lines to do the
49    reordering in this function.  */
50 
51 struct dis_line_entry
52 {
53   struct symtab *symtab;
54   int line;
55 };
56 
57 /* Hash function for dis_line_entry.  */
58 
59 static hashval_t
60 hash_dis_line_entry (const void *item)
61 {
62   const struct dis_line_entry *dle = (const struct dis_line_entry *) item;
63 
64   return htab_hash_pointer (dle->symtab) + dle->line;
65 }
66 
67 /* Equal function for dis_line_entry.  */
68 
69 static int
70 eq_dis_line_entry (const void *item_lhs, const void *item_rhs)
71 {
72   const struct dis_line_entry *lhs = (const struct dis_line_entry *) item_lhs;
73   const struct dis_line_entry *rhs = (const struct dis_line_entry *) item_rhs;
74 
75   return (lhs->symtab == rhs->symtab
76 	  && lhs->line == rhs->line);
77 }
78 
79 /* Create the table to manage lines for mixed source/disassembly.  */
80 
81 static htab_t
82 allocate_dis_line_table (void)
83 {
84   return htab_create_alloc (41,
85 			    hash_dis_line_entry, eq_dis_line_entry,
86 			    xfree, xcalloc, xfree);
87 }
88 
89 /* Add a new dis_line_entry containing SYMTAB and LINE to TABLE.  */
90 
91 static void
92 add_dis_line_entry (htab_t table, struct symtab *symtab, int line)
93 {
94   void **slot;
95   struct dis_line_entry dle, *dlep;
96 
97   dle.symtab = symtab;
98   dle.line = line;
99   slot = htab_find_slot (table, &dle, INSERT);
100   if (*slot == NULL)
101     {
102       dlep = XNEW (struct dis_line_entry);
103       dlep->symtab = symtab;
104       dlep->line = line;
105       *slot = dlep;
106     }
107 }
108 
109 /* Return non-zero if SYMTAB, LINE are in TABLE.  */
110 
111 static int
112 line_has_code_p (htab_t table, struct symtab *symtab, int line)
113 {
114   struct dis_line_entry dle;
115 
116   dle.symtab = symtab;
117   dle.line = line;
118   return htab_find (table, &dle) != NULL;
119 }
120 
121 /* Like target_read_memory, but slightly different parameters.  */
122 static int
123 dis_asm_read_memory (bfd_vma memaddr, gdb_byte *myaddr, unsigned int len,
124 		     struct disassemble_info *info)
125 {
126   return target_read_code (memaddr, myaddr, len);
127 }
128 
129 /* Like memory_error with slightly different parameters.  */
130 static void
131 dis_asm_memory_error (int err, bfd_vma memaddr,
132 		      struct disassemble_info *info)
133 {
134   memory_error (TARGET_XFER_E_IO, memaddr);
135 }
136 
137 /* Like print_address with slightly different parameters.  */
138 static void
139 dis_asm_print_address (bfd_vma addr, struct disassemble_info *info)
140 {
141   struct gdbarch *gdbarch = (struct gdbarch *) info->application_data;
142 
143   print_address (gdbarch, addr, (struct ui_file *) info->stream);
144 }
145 
146 static int
147 compare_lines (const void *mle1p, const void *mle2p)
148 {
149   struct deprecated_dis_line_entry *mle1, *mle2;
150   int val;
151 
152   mle1 = (struct deprecated_dis_line_entry *) mle1p;
153   mle2 = (struct deprecated_dis_line_entry *) mle2p;
154 
155   /* End of sequence markers have a line number of 0 but don't want to
156      be sorted to the head of the list, instead sort by PC.  */
157   if (mle1->line == 0 || mle2->line == 0)
158     {
159       val = mle1->start_pc - mle2->start_pc;
160       if (val == 0)
161         val = mle1->line - mle2->line;
162     }
163   else
164     {
165       val = mle1->line - mle2->line;
166       if (val == 0)
167         val = mle1->start_pc - mle2->start_pc;
168     }
169   return val;
170 }
171 
172 /* See disasm.h.  */
173 
174 int
175 gdb_pretty_print_insn (struct gdbarch *gdbarch, struct ui_out *uiout,
176 		       struct disassemble_info * di,
177 		       const struct disasm_insn *insn, int flags,
178 		       struct ui_file *stb)
179 {
180   /* parts of the symbolic representation of the address */
181   int unmapped;
182   int offset;
183   int line;
184   int size;
185   struct cleanup *ui_out_chain;
186   char *filename = NULL;
187   char *name = NULL;
188   CORE_ADDR pc;
189 
190   ui_out_chain = make_cleanup_ui_out_tuple_begin_end (uiout, NULL);
191   pc = insn->addr;
192 
193   if (insn->number != 0)
194     {
195       ui_out_field_fmt (uiout, "insn-number", "%u", insn->number);
196       ui_out_text (uiout, "\t");
197     }
198 
199   if ((flags & DISASSEMBLY_SPECULATIVE) != 0)
200     {
201       if (insn->is_speculative)
202 	{
203 	  ui_out_field_string (uiout, "is-speculative", "?");
204 
205 	  /* The speculative execution indication overwrites the first
206 	     character of the PC prefix.
207 	     We assume a PC prefix length of 3 characters.  */
208 	  if ((flags & DISASSEMBLY_OMIT_PC) == 0)
209 	    ui_out_text (uiout, pc_prefix (pc) + 1);
210 	  else
211 	    ui_out_text (uiout, "  ");
212 	}
213       else if ((flags & DISASSEMBLY_OMIT_PC) == 0)
214 	ui_out_text (uiout, pc_prefix (pc));
215       else
216 	ui_out_text (uiout, "   ");
217     }
218   else if ((flags & DISASSEMBLY_OMIT_PC) == 0)
219     ui_out_text (uiout, pc_prefix (pc));
220   ui_out_field_core_addr (uiout, "address", gdbarch, pc);
221 
222   if (!build_address_symbolic (gdbarch, pc, 0, &name, &offset, &filename,
223 			       &line, &unmapped))
224     {
225       /* We don't care now about line, filename and unmapped.  But we might in
226 	 the future.  */
227       ui_out_text (uiout, " <");
228       if ((flags & DISASSEMBLY_OMIT_FNAME) == 0)
229 	ui_out_field_string (uiout, "func-name", name);
230       ui_out_text (uiout, "+");
231       ui_out_field_int (uiout, "offset", offset);
232       ui_out_text (uiout, ">:\t");
233     }
234   else
235     ui_out_text (uiout, ":\t");
236 
237   if (filename != NULL)
238     xfree (filename);
239   if (name != NULL)
240     xfree (name);
241 
242   ui_file_rewind (stb);
243   if (flags & DISASSEMBLY_RAW_INSN)
244     {
245       CORE_ADDR end_pc;
246       bfd_byte data;
247       int err;
248       const char *spacer = "";
249 
250       /* Build the opcodes using a temporary stream so we can
251 	 write them out in a single go for the MI.  */
252       struct ui_file *opcode_stream = mem_fileopen ();
253       struct cleanup *cleanups =
254 	make_cleanup_ui_file_delete (opcode_stream);
255 
256       size = gdbarch_print_insn (gdbarch, pc, di);
257       end_pc = pc + size;
258 
259       for (;pc < end_pc; ++pc)
260 	{
261 	  err = (*di->read_memory_func) (pc, &data, 1, di);
262 	  if (err != 0)
263 	    (*di->memory_error_func) (err, pc, di);
264 	  fprintf_filtered (opcode_stream, "%s%02x",
265 			    spacer, (unsigned) data);
266 	  spacer = " ";
267 	}
268 
269       ui_out_field_stream (uiout, "opcodes", opcode_stream);
270       ui_out_text (uiout, "\t");
271 
272       do_cleanups (cleanups);
273     }
274   else
275     size = gdbarch_print_insn (gdbarch, pc, di);
276 
277   ui_out_field_stream (uiout, "inst", stb);
278   ui_file_rewind (stb);
279   do_cleanups (ui_out_chain);
280   ui_out_text (uiout, "\n");
281 
282   return size;
283 }
284 
285 static int
286 dump_insns (struct gdbarch *gdbarch, struct ui_out *uiout,
287 	    struct disassemble_info * di,
288 	    CORE_ADDR low, CORE_ADDR high,
289 	    int how_many, int flags, struct ui_file *stb,
290 	    CORE_ADDR *end_pc)
291 {
292   struct disasm_insn insn;
293   int num_displayed = 0;
294 
295   memset (&insn, 0, sizeof (insn));
296   insn.addr = low;
297 
298   while (insn.addr < high && (how_many < 0 || num_displayed < how_many))
299     {
300       int size;
301 
302       size = gdb_pretty_print_insn (gdbarch, uiout, di, &insn, flags, stb);
303       if (size <= 0)
304 	break;
305 
306       ++num_displayed;
307       insn.addr += size;
308 
309       /* Allow user to bail out with ^C.  */
310       QUIT;
311     }
312 
313   if (end_pc != NULL)
314     *end_pc = insn.addr;
315 
316   return num_displayed;
317 }
318 
319 /* The idea here is to present a source-O-centric view of a
320    function to the user.  This means that things are presented
321    in source order, with (possibly) out of order assembly
322    immediately following.
323 
324    N.B. This view is deprecated.  */
325 
326 static void
327 do_mixed_source_and_assembly_deprecated
328   (struct gdbarch *gdbarch, struct ui_out *uiout,
329    struct disassemble_info *di, struct symtab *symtab,
330    CORE_ADDR low, CORE_ADDR high,
331    int how_many, int flags, struct ui_file *stb)
332 {
333   int newlines = 0;
334   int nlines;
335   struct linetable_entry *le;
336   struct deprecated_dis_line_entry *mle;
337   struct symtab_and_line sal;
338   int i;
339   int out_of_order = 0;
340   int next_line = 0;
341   int num_displayed = 0;
342   print_source_lines_flags psl_flags = 0;
343   struct cleanup *ui_out_chain;
344   struct cleanup *ui_out_tuple_chain = make_cleanup (null_cleanup, 0);
345   struct cleanup *ui_out_list_chain = make_cleanup (null_cleanup, 0);
346 
347   gdb_assert (symtab != NULL && SYMTAB_LINETABLE (symtab) != NULL);
348 
349   nlines = SYMTAB_LINETABLE (symtab)->nitems;
350   le = SYMTAB_LINETABLE (symtab)->item;
351 
352   if (flags & DISASSEMBLY_FILENAME)
353     psl_flags |= PRINT_SOURCE_LINES_FILENAME;
354 
355   mle = (struct deprecated_dis_line_entry *)
356     alloca (nlines * sizeof (struct deprecated_dis_line_entry));
357 
358   /* Copy linetable entries for this function into our data
359      structure, creating end_pc's and setting out_of_order as
360      appropriate.  */
361 
362   /* First, skip all the preceding functions.  */
363 
364   for (i = 0; i < nlines - 1 && le[i].pc < low; i++);
365 
366   /* Now, copy all entries before the end of this function.  */
367 
368   for (; i < nlines - 1 && le[i].pc < high; i++)
369     {
370       if (le[i].line == le[i + 1].line && le[i].pc == le[i + 1].pc)
371 	continue;		/* Ignore duplicates.  */
372 
373       /* Skip any end-of-function markers.  */
374       if (le[i].line == 0)
375 	continue;
376 
377       mle[newlines].line = le[i].line;
378       if (le[i].line > le[i + 1].line)
379 	out_of_order = 1;
380       mle[newlines].start_pc = le[i].pc;
381       mle[newlines].end_pc = le[i + 1].pc;
382       newlines++;
383     }
384 
385   /* If we're on the last line, and it's part of the function,
386      then we need to get the end pc in a special way.  */
387 
388   if (i == nlines - 1 && le[i].pc < high)
389     {
390       mle[newlines].line = le[i].line;
391       mle[newlines].start_pc = le[i].pc;
392       sal = find_pc_line (le[i].pc, 0);
393       mle[newlines].end_pc = sal.end;
394       newlines++;
395     }
396 
397   /* Now, sort mle by line #s (and, then by addresses within lines).  */
398 
399   if (out_of_order)
400     qsort (mle, newlines, sizeof (struct deprecated_dis_line_entry),
401 	   compare_lines);
402 
403   /* Now, for each line entry, emit the specified lines (unless
404      they have been emitted before), followed by the assembly code
405      for that line.  */
406 
407   ui_out_chain = make_cleanup_ui_out_list_begin_end (uiout, "asm_insns");
408 
409   for (i = 0; i < newlines; i++)
410     {
411       /* Print out everything from next_line to the current line.  */
412       if (mle[i].line >= next_line)
413 	{
414 	  if (next_line != 0)
415 	    {
416 	      /* Just one line to print.  */
417 	      if (next_line == mle[i].line)
418 		{
419 		  ui_out_tuple_chain
420 		    = make_cleanup_ui_out_tuple_begin_end (uiout,
421 							   "src_and_asm_line");
422 		  print_source_lines (symtab, next_line, mle[i].line + 1, psl_flags);
423 		}
424 	      else
425 		{
426 		  /* Several source lines w/o asm instructions associated.  */
427 		  for (; next_line < mle[i].line; next_line++)
428 		    {
429 		      struct cleanup *ui_out_list_chain_line;
430 		      struct cleanup *ui_out_tuple_chain_line;
431 
432 		      ui_out_tuple_chain_line
433 			= make_cleanup_ui_out_tuple_begin_end (uiout,
434 							       "src_and_asm_line");
435 		      print_source_lines (symtab, next_line, next_line + 1,
436 					  psl_flags);
437 		      ui_out_list_chain_line
438 			= make_cleanup_ui_out_list_begin_end (uiout,
439 							      "line_asm_insn");
440 		      do_cleanups (ui_out_list_chain_line);
441 		      do_cleanups (ui_out_tuple_chain_line);
442 		    }
443 		  /* Print the last line and leave list open for
444 		     asm instructions to be added.  */
445 		  ui_out_tuple_chain
446 		    = make_cleanup_ui_out_tuple_begin_end (uiout,
447 							   "src_and_asm_line");
448 		  print_source_lines (symtab, next_line, mle[i].line + 1, psl_flags);
449 		}
450 	    }
451 	  else
452 	    {
453 	      ui_out_tuple_chain
454 		= make_cleanup_ui_out_tuple_begin_end (uiout,
455 						       "src_and_asm_line");
456 	      print_source_lines (symtab, mle[i].line, mle[i].line + 1, psl_flags);
457 	    }
458 
459 	  next_line = mle[i].line + 1;
460 	  ui_out_list_chain
461 	    = make_cleanup_ui_out_list_begin_end (uiout, "line_asm_insn");
462 	}
463 
464       num_displayed += dump_insns (gdbarch, uiout, di,
465 				   mle[i].start_pc, mle[i].end_pc,
466 				   how_many, flags, stb, NULL);
467 
468       /* When we've reached the end of the mle array, or we've seen the last
469          assembly range for this source line, close out the list/tuple.  */
470       if (i == (newlines - 1) || mle[i + 1].line > mle[i].line)
471 	{
472 	  do_cleanups (ui_out_list_chain);
473 	  do_cleanups (ui_out_tuple_chain);
474 	  ui_out_tuple_chain = make_cleanup (null_cleanup, 0);
475 	  ui_out_list_chain = make_cleanup (null_cleanup, 0);
476 	  ui_out_text (uiout, "\n");
477 	}
478       if (how_many >= 0 && num_displayed >= how_many)
479 	break;
480     }
481   do_cleanups (ui_out_chain);
482 }
483 
484 /* The idea here is to present a source-O-centric view of a
485    function to the user.  This means that things are presented
486    in source order, with (possibly) out of order assembly
487    immediately following.  */
488 
489 static void
490 do_mixed_source_and_assembly (struct gdbarch *gdbarch, struct ui_out *uiout,
491 			      struct disassemble_info *di,
492 			      struct symtab *main_symtab,
493 			      CORE_ADDR low, CORE_ADDR high,
494 			      int how_many, int flags, struct ui_file *stb)
495 {
496   const struct linetable_entry *le, *first_le;
497   int i, nlines;
498   int num_displayed = 0;
499   print_source_lines_flags psl_flags = 0;
500   struct cleanup *cleanups;
501   struct cleanup *ui_out_chain;
502   struct cleanup *ui_out_tuple_chain;
503   struct cleanup *ui_out_list_chain;
504   CORE_ADDR pc;
505   struct symtab *last_symtab;
506   int last_line;
507   htab_t dis_line_table;
508 
509   gdb_assert (main_symtab != NULL && SYMTAB_LINETABLE (main_symtab) != NULL);
510 
511   /* First pass: collect the list of all source files and lines.
512      We do this so that we can only print lines containing code once.
513      We try to print the source text leading up to the next instruction,
514      but if that text is for code that will be disassembled later, then
515      we'll want to defer printing it until later with its associated code.  */
516 
517   dis_line_table = allocate_dis_line_table ();
518   cleanups = make_cleanup_htab_delete (dis_line_table);
519 
520   pc = low;
521 
522   /* The prologue may be empty, but there may still be a line number entry
523      for the opening brace which is distinct from the first line of code.
524      If the prologue has been eliminated find_pc_line may return the source
525      line after the opening brace.  We still want to print this opening brace.
526      first_le is used to implement this.  */
527 
528   nlines = SYMTAB_LINETABLE (main_symtab)->nitems;
529   le = SYMTAB_LINETABLE (main_symtab)->item;
530   first_le = NULL;
531 
532   /* Skip all the preceding functions.  */
533   for (i = 0; i < nlines && le[i].pc < low; i++)
534     continue;
535 
536   if (i < nlines && le[i].pc < high)
537     first_le = &le[i];
538 
539   /* Add lines for every pc value.  */
540   while (pc < high)
541     {
542       struct symtab_and_line sal;
543       int length;
544 
545       sal = find_pc_line (pc, 0);
546       length = gdb_insn_length (gdbarch, pc);
547       pc += length;
548 
549       if (sal.symtab != NULL)
550 	add_dis_line_entry (dis_line_table, sal.symtab, sal.line);
551     }
552 
553   /* Second pass: print the disassembly.
554 
555      Output format, from an MI perspective:
556        The result is a ui_out list, field name "asm_insns", where elements have
557        name "src_and_asm_line".
558        Each element is a tuple of source line specs (field names line, file,
559        fullname), and field "line_asm_insn" which contains the disassembly.
560        Field "line_asm_insn" is a list of tuples: address, func-name, offset,
561        opcodes, inst.
562 
563      CLI output works on top of this because MI ignores ui_out_text output,
564      which is where we put file name and source line contents output.
565 
566      Cleanup usage:
567      cleanups:
568        For things created at the beginning of this function and need to be
569        kept until the end of this function.
570      ui_out_chain
571        Handles the outer "asm_insns" list.
572      ui_out_tuple_chain
573        The tuples for each group of consecutive disassemblies.
574      ui_out_list_chain
575        List of consecutive source lines or disassembled insns.  */
576 
577   if (flags & DISASSEMBLY_FILENAME)
578     psl_flags |= PRINT_SOURCE_LINES_FILENAME;
579 
580   ui_out_chain = make_cleanup_ui_out_list_begin_end (uiout, "asm_insns");
581 
582   ui_out_tuple_chain = NULL;
583   ui_out_list_chain = NULL;
584 
585   last_symtab = NULL;
586   last_line = 0;
587   pc = low;
588 
589   while (pc < high)
590     {
591       struct symtab_and_line sal;
592       CORE_ADDR end_pc;
593       int start_preceding_line_to_display = 0;
594       int end_preceding_line_to_display = 0;
595       int new_source_line = 0;
596 
597       sal = find_pc_line (pc, 0);
598 
599       if (sal.symtab != last_symtab)
600 	{
601 	  /* New source file.  */
602 	  new_source_line = 1;
603 
604 	  /* If this is the first line of output, check for any preceding
605 	     lines.  */
606 	  if (last_line == 0
607 	      && first_le != NULL
608 	      && first_le->line < sal.line)
609 	    {
610 	      start_preceding_line_to_display = first_le->line;
611 	      end_preceding_line_to_display = sal.line;
612 	    }
613 	}
614       else
615 	{
616 	  /* Same source file as last time.  */
617 	  if (sal.symtab != NULL)
618 	    {
619 	      if (sal.line > last_line + 1 && last_line != 0)
620 		{
621 		  int l;
622 
623 		  /* Several preceding source lines.  Print the trailing ones
624 		     not associated with code that we'll print later.  */
625 		  for (l = sal.line - 1; l > last_line; --l)
626 		    {
627 		      if (line_has_code_p (dis_line_table, sal.symtab, l))
628 			break;
629 		    }
630 		  if (l < sal.line - 1)
631 		    {
632 		      start_preceding_line_to_display = l + 1;
633 		      end_preceding_line_to_display = sal.line;
634 		    }
635 		}
636 	      if (sal.line != last_line)
637 		new_source_line = 1;
638 	      else
639 		{
640 		  /* Same source line as last time.  This can happen, depending
641 		     on the debug info.  */
642 		}
643 	    }
644 	}
645 
646       if (new_source_line)
647 	{
648 	  /* Skip the newline if this is the first instruction.  */
649 	  if (pc > low)
650 	    ui_out_text (uiout, "\n");
651 	  if (ui_out_tuple_chain != NULL)
652 	    {
653 	      gdb_assert (ui_out_list_chain != NULL);
654 	      do_cleanups (ui_out_list_chain);
655 	      do_cleanups (ui_out_tuple_chain);
656 	    }
657 	  if (sal.symtab != last_symtab
658 	      && !(flags & DISASSEMBLY_FILENAME))
659 	    {
660 	      /* Remember MI ignores ui_out_text.
661 		 We don't have to do anything here for MI because MI
662 		 output includes the source specs for each line.  */
663 	      if (sal.symtab != NULL)
664 		{
665 		  ui_out_text (uiout,
666 			       symtab_to_filename_for_display (sal.symtab));
667 		}
668 	      else
669 		ui_out_text (uiout, "unknown");
670 	      ui_out_text (uiout, ":\n");
671 	    }
672 	  if (start_preceding_line_to_display > 0)
673 	    {
674 	      /* Several source lines w/o asm instructions associated.
675 		 We need to preserve the structure of the output, so output
676 		 a bunch of line tuples with no asm entries.  */
677 	      int l;
678 	      struct cleanup *ui_out_list_chain_line;
679 	      struct cleanup *ui_out_tuple_chain_line;
680 
681 	      gdb_assert (sal.symtab != NULL);
682 	      for (l = start_preceding_line_to_display;
683 		   l < end_preceding_line_to_display;
684 		   ++l)
685 		{
686 		  ui_out_tuple_chain_line
687 		    = make_cleanup_ui_out_tuple_begin_end (uiout,
688 							   "src_and_asm_line");
689 		  print_source_lines (sal.symtab, l, l + 1, psl_flags);
690 		  ui_out_list_chain_line
691 		    = make_cleanup_ui_out_list_begin_end (uiout,
692 							  "line_asm_insn");
693 		  do_cleanups (ui_out_list_chain_line);
694 		  do_cleanups (ui_out_tuple_chain_line);
695 		}
696 	    }
697 	  ui_out_tuple_chain
698 	    = make_cleanup_ui_out_tuple_begin_end (uiout, "src_and_asm_line");
699 	  if (sal.symtab != NULL)
700 	    print_source_lines (sal.symtab, sal.line, sal.line + 1, psl_flags);
701 	  else
702 	    ui_out_text (uiout, _("--- no source info for this pc ---\n"));
703 	  ui_out_list_chain
704 	    = make_cleanup_ui_out_list_begin_end (uiout, "line_asm_insn");
705 	}
706       else
707 	{
708 	  /* Here we're appending instructions to an existing line.
709 	     By construction the very first insn will have a symtab
710 	     and follow the new_source_line path above.  */
711 	  gdb_assert (ui_out_tuple_chain != NULL);
712 	  gdb_assert (ui_out_list_chain != NULL);
713 	}
714 
715       if (sal.end != 0)
716 	end_pc = min (sal.end, high);
717       else
718 	end_pc = pc + 1;
719       num_displayed += dump_insns (gdbarch, uiout, di, pc, end_pc,
720 				   how_many, flags, stb, &end_pc);
721       pc = end_pc;
722 
723       if (how_many >= 0 && num_displayed >= how_many)
724 	break;
725 
726       last_symtab = sal.symtab;
727       last_line = sal.line;
728     }
729 
730   do_cleanups (ui_out_chain);
731   do_cleanups (cleanups);
732 }
733 
734 static void
735 do_assembly_only (struct gdbarch *gdbarch, struct ui_out *uiout,
736 		  struct disassemble_info * di,
737 		  CORE_ADDR low, CORE_ADDR high,
738 		  int how_many, int flags, struct ui_file *stb)
739 {
740   struct cleanup *ui_out_chain;
741 
742   ui_out_chain = make_cleanup_ui_out_list_begin_end (uiout, "asm_insns");
743 
744   dump_insns (gdbarch, uiout, di, low, high, how_many, flags, stb, NULL);
745 
746   do_cleanups (ui_out_chain);
747 }
748 
749 /* Initialize the disassemble info struct ready for the specified
750    stream.  */
751 
752 static int ATTRIBUTE_PRINTF (2, 3)
753 fprintf_disasm (void *stream, const char *format, ...)
754 {
755   va_list args;
756 
757   va_start (args, format);
758   vfprintf_filtered ((struct ui_file *) stream, format, args);
759   va_end (args);
760   /* Something non -ve.  */
761   return 0;
762 }
763 
764 struct disassemble_info
765 gdb_disassemble_info (struct gdbarch *gdbarch, struct ui_file *file)
766 {
767   struct disassemble_info di;
768 
769   init_disassemble_info (&di, file, fprintf_disasm);
770   di.flavour = bfd_target_unknown_flavour;
771   di.memory_error_func = dis_asm_memory_error;
772   di.print_address_func = dis_asm_print_address;
773   /* NOTE: cagney/2003-04-28: The original code, from the old Insight
774      disassembler had a local optomization here.  By default it would
775      access the executable file, instead of the target memory (there
776      was a growing list of exceptions though).  Unfortunately, the
777      heuristic was flawed.  Commands like "disassemble &variable"
778      didn't work as they relied on the access going to the target.
779      Further, it has been supperseeded by trust-read-only-sections
780      (although that should be superseeded by target_trust..._p()).  */
781   di.read_memory_func = dis_asm_read_memory;
782   di.arch = gdbarch_bfd_arch_info (gdbarch)->arch;
783   di.mach = gdbarch_bfd_arch_info (gdbarch)->mach;
784   di.endian = gdbarch_byte_order (gdbarch);
785   di.endian_code = gdbarch_byte_order_for_code (gdbarch);
786   di.application_data = gdbarch;
787   disassemble_init_for_target (&di);
788   return di;
789 }
790 
791 void
792 gdb_disassembly (struct gdbarch *gdbarch, struct ui_out *uiout,
793 		 char *file_string, int flags, int how_many,
794 		 CORE_ADDR low, CORE_ADDR high)
795 {
796   struct ui_file *stb = mem_fileopen ();
797   struct cleanup *cleanups = make_cleanup_ui_file_delete (stb);
798   struct disassemble_info di = gdb_disassemble_info (gdbarch, stb);
799   struct symtab *symtab;
800   int nlines = -1;
801 
802   /* Assume symtab is valid for whole PC range.  */
803   symtab = find_pc_line_symtab (low);
804 
805   if (symtab != NULL && SYMTAB_LINETABLE (symtab) != NULL)
806     nlines = SYMTAB_LINETABLE (symtab)->nitems;
807 
808   if (!(flags & (DISASSEMBLY_SOURCE_DEPRECATED | DISASSEMBLY_SOURCE))
809       || nlines <= 0)
810     do_assembly_only (gdbarch, uiout, &di, low, high, how_many, flags, stb);
811 
812   else if (flags & DISASSEMBLY_SOURCE)
813     do_mixed_source_and_assembly (gdbarch, uiout, &di, symtab, low, high,
814 				  how_many, flags, stb);
815 
816   else if (flags & DISASSEMBLY_SOURCE_DEPRECATED)
817     do_mixed_source_and_assembly_deprecated (gdbarch, uiout, &di, symtab,
818 					     low, high, how_many, flags, stb);
819 
820   do_cleanups (cleanups);
821   gdb_flush (gdb_stdout);
822 }
823 
824 /* Print the instruction at address MEMADDR in debugged memory,
825    on STREAM.  Returns the length of the instruction, in bytes,
826    and, if requested, the number of branch delay slot instructions.  */
827 
828 int
829 gdb_print_insn (struct gdbarch *gdbarch, CORE_ADDR memaddr,
830 		struct ui_file *stream, int *branch_delay_insns)
831 {
832   struct disassemble_info di;
833   int length;
834 
835   di = gdb_disassemble_info (gdbarch, stream);
836   length = gdbarch_print_insn (gdbarch, memaddr, &di);
837   if (branch_delay_insns)
838     {
839       if (di.insn_info_valid)
840 	*branch_delay_insns = di.branch_delay_insns;
841       else
842 	*branch_delay_insns = 0;
843     }
844   return length;
845 }
846 
847 static void
848 do_ui_file_delete (void *arg)
849 {
850   ui_file_delete ((struct ui_file *) arg);
851 }
852 
853 /* Return the length in bytes of the instruction at address MEMADDR in
854    debugged memory.  */
855 
856 int
857 gdb_insn_length (struct gdbarch *gdbarch, CORE_ADDR addr)
858 {
859   static struct ui_file *null_stream = NULL;
860 
861   /* Dummy file descriptor for the disassembler.  */
862   if (!null_stream)
863     {
864       null_stream = ui_file_new ();
865       make_final_cleanup (do_ui_file_delete, null_stream);
866     }
867 
868   return gdb_print_insn (gdbarch, addr, null_stream, NULL);
869 }
870 
871 /* fprintf-function for gdb_buffered_insn_length.  This function is a
872    nop, we don't want to print anything, we just want to compute the
873    length of the insn.  */
874 
875 static int ATTRIBUTE_PRINTF (2, 3)
876 gdb_buffered_insn_length_fprintf (void *stream, const char *format, ...)
877 {
878   return 0;
879 }
880 
881 /* Initialize a struct disassemble_info for gdb_buffered_insn_length.  */
882 
883 static void
884 gdb_buffered_insn_length_init_dis (struct gdbarch *gdbarch,
885 				   struct disassemble_info *di,
886 				   const gdb_byte *insn, int max_len,
887 				   CORE_ADDR addr)
888 {
889   init_disassemble_info (di, NULL, gdb_buffered_insn_length_fprintf);
890 
891   /* init_disassemble_info installs buffer_read_memory, etc.
892      so we don't need to do that here.
893      The cast is necessary until disassemble_info is const-ified.  */
894   di->buffer = (gdb_byte *) insn;
895   di->buffer_length = max_len;
896   di->buffer_vma = addr;
897 
898   di->arch = gdbarch_bfd_arch_info (gdbarch)->arch;
899   di->mach = gdbarch_bfd_arch_info (gdbarch)->mach;
900   di->endian = gdbarch_byte_order (gdbarch);
901   di->endian_code = gdbarch_byte_order_for_code (gdbarch);
902 
903   disassemble_init_for_target (di);
904 }
905 
906 /* Return the length in bytes of INSN.  MAX_LEN is the size of the
907    buffer containing INSN.  */
908 
909 int
910 gdb_buffered_insn_length (struct gdbarch *gdbarch,
911 			  const gdb_byte *insn, int max_len, CORE_ADDR addr)
912 {
913   struct disassemble_info di;
914 
915   gdb_buffered_insn_length_init_dis (gdbarch, &di, insn, max_len, addr);
916 
917   return gdbarch_print_insn (gdbarch, addr, &di);
918 }
919