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