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