]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blob - gdb/disasm.c
Eliminate make_cleanup_ui_file_delete / make ui_file a class hierarchy
[thirdparty/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_insn (struct gdbarch *gdbarch, 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
199 ui_out_chain = make_cleanup_ui_out_tuple_begin_end (uiout, NULL);
200 pc = insn->addr;
201
202 if (insn->number != 0)
203 {
204 uiout->field_fmt ("insn-number", "%u", insn->number);
205 uiout->text ("\t");
206 }
207
208 if ((flags & DISASSEMBLY_SPECULATIVE) != 0)
209 {
210 if (insn->is_speculative)
211 {
212 uiout->field_string ("is-speculative", "?");
213
214 /* The speculative execution indication overwrites the first
215 character of the PC prefix.
216 We assume a PC prefix length of 3 characters. */
217 if ((flags & DISASSEMBLY_OMIT_PC) == 0)
218 uiout->text (pc_prefix (pc) + 1);
219 else
220 uiout->text (" ");
221 }
222 else if ((flags & DISASSEMBLY_OMIT_PC) == 0)
223 uiout->text (pc_prefix (pc));
224 else
225 uiout->text (" ");
226 }
227 else if ((flags & DISASSEMBLY_OMIT_PC) == 0)
228 uiout->text (pc_prefix (pc));
229 uiout->field_core_addr ("address", gdbarch, pc);
230
231 if (!build_address_symbolic (gdbarch, pc, 0, &name, &offset, &filename,
232 &line, &unmapped))
233 {
234 /* We don't care now about line, filename and unmapped. But we might in
235 the future. */
236 uiout->text (" <");
237 if ((flags & DISASSEMBLY_OMIT_FNAME) == 0)
238 uiout->field_string ("func-name", name);
239 uiout->text ("+");
240 uiout->field_int ("offset", offset);
241 uiout->text (">:\t");
242 }
243 else
244 uiout->text (":\t");
245
246 if (filename != NULL)
247 xfree (filename);
248 if (name != NULL)
249 xfree (name);
250
251 string_file stb;
252
253 if (flags & DISASSEMBLY_RAW_INSN)
254 {
255 CORE_ADDR end_pc;
256 bfd_byte data;
257 int err;
258 const char *spacer = "";
259
260 /* Build the opcodes using a temporary stream so we can
261 write them out in a single go for the MI. */
262 string_file opcode_stream;
263
264 size = gdb_print_insn (gdbarch, pc, &stb, NULL);
265 end_pc = pc + size;
266
267 for (;pc < end_pc; ++pc)
268 {
269 read_code (pc, &data, 1);
270 opcode_stream.printf ("%s%02x", spacer, (unsigned) data);
271 spacer = " ";
272 }
273
274 uiout->field_stream ("opcodes", opcode_stream);
275 uiout->text ("\t");
276 }
277 else
278 size = gdb_print_insn (gdbarch, pc, &stb, NULL);
279
280 uiout->field_stream ("inst", stb);
281 do_cleanups (ui_out_chain);
282 uiout->text ("\n");
283
284 return size;
285 }
286
287 static int
288 dump_insns (struct gdbarch *gdbarch,
289 struct ui_out *uiout, CORE_ADDR low, CORE_ADDR high,
290 int how_many, int flags, 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, &insn, flags);
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 symtab *symtab,
330 CORE_ADDR low, CORE_ADDR high,
331 int how_many, int flags)
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,
465 mle[i].start_pc, mle[i].end_pc,
466 how_many, flags, 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 uiout->text ("\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,
491 struct ui_out *uiout,
492 struct symtab *main_symtab,
493 CORE_ADDR low, CORE_ADDR high,
494 int how_many, int flags)
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 *ui_out_chain;
501 struct cleanup *ui_out_tuple_chain;
502 struct cleanup *ui_out_list_chain;
503 CORE_ADDR pc;
504 struct symtab *last_symtab;
505 int last_line;
506
507 gdb_assert (main_symtab != NULL && SYMTAB_LINETABLE (main_symtab) != NULL);
508
509 /* First pass: collect the list of all source files and lines.
510 We do this so that we can only print lines containing code once.
511 We try to print the source text leading up to the next instruction,
512 but if that text is for code that will be disassembled later, then
513 we'll want to defer printing it until later with its associated code. */
514
515 htab_up dis_line_table (allocate_dis_line_table ());
516
517 pc = low;
518
519 /* The prologue may be empty, but there may still be a line number entry
520 for the opening brace which is distinct from the first line of code.
521 If the prologue has been eliminated find_pc_line may return the source
522 line after the opening brace. We still want to print this opening brace.
523 first_le is used to implement this. */
524
525 nlines = SYMTAB_LINETABLE (main_symtab)->nitems;
526 le = SYMTAB_LINETABLE (main_symtab)->item;
527 first_le = NULL;
528
529 /* Skip all the preceding functions. */
530 for (i = 0; i < nlines && le[i].pc < low; i++)
531 continue;
532
533 if (i < nlines && le[i].pc < high)
534 first_le = &le[i];
535
536 /* Add lines for every pc value. */
537 while (pc < high)
538 {
539 struct symtab_and_line sal;
540 int length;
541
542 sal = find_pc_line (pc, 0);
543 length = gdb_insn_length (gdbarch, pc);
544 pc += length;
545
546 if (sal.symtab != NULL)
547 add_dis_line_entry (dis_line_table.get (), sal.symtab, sal.line);
548 }
549
550 /* Second pass: print the disassembly.
551
552 Output format, from an MI perspective:
553 The result is a ui_out list, field name "asm_insns", where elements have
554 name "src_and_asm_line".
555 Each element is a tuple of source line specs (field names line, file,
556 fullname), and field "line_asm_insn" which contains the disassembly.
557 Field "line_asm_insn" is a list of tuples: address, func-name, offset,
558 opcodes, inst.
559
560 CLI output works on top of this because MI ignores ui_out_text output,
561 which is where we put file name and source line contents output.
562
563 Cleanup usage:
564 ui_out_chain
565 Handles the outer "asm_insns" list.
566 ui_out_tuple_chain
567 The tuples for each group of consecutive disassemblies.
568 ui_out_list_chain
569 List of consecutive source lines or disassembled insns. */
570
571 if (flags & DISASSEMBLY_FILENAME)
572 psl_flags |= PRINT_SOURCE_LINES_FILENAME;
573
574 ui_out_chain = make_cleanup_ui_out_list_begin_end (uiout, "asm_insns");
575
576 ui_out_tuple_chain = NULL;
577 ui_out_list_chain = NULL;
578
579 last_symtab = NULL;
580 last_line = 0;
581 pc = low;
582
583 while (pc < high)
584 {
585 struct symtab_and_line sal;
586 CORE_ADDR end_pc;
587 int start_preceding_line_to_display = 0;
588 int end_preceding_line_to_display = 0;
589 int new_source_line = 0;
590
591 sal = find_pc_line (pc, 0);
592
593 if (sal.symtab != last_symtab)
594 {
595 /* New source file. */
596 new_source_line = 1;
597
598 /* If this is the first line of output, check for any preceding
599 lines. */
600 if (last_line == 0
601 && first_le != NULL
602 && first_le->line < sal.line)
603 {
604 start_preceding_line_to_display = first_le->line;
605 end_preceding_line_to_display = sal.line;
606 }
607 }
608 else
609 {
610 /* Same source file as last time. */
611 if (sal.symtab != NULL)
612 {
613 if (sal.line > last_line + 1 && last_line != 0)
614 {
615 int l;
616
617 /* Several preceding source lines. Print the trailing ones
618 not associated with code that we'll print later. */
619 for (l = sal.line - 1; l > last_line; --l)
620 {
621 if (line_has_code_p (dis_line_table.get (),
622 sal.symtab, l))
623 break;
624 }
625 if (l < sal.line - 1)
626 {
627 start_preceding_line_to_display = l + 1;
628 end_preceding_line_to_display = sal.line;
629 }
630 }
631 if (sal.line != last_line)
632 new_source_line = 1;
633 else
634 {
635 /* Same source line as last time. This can happen, depending
636 on the debug info. */
637 }
638 }
639 }
640
641 if (new_source_line)
642 {
643 /* Skip the newline if this is the first instruction. */
644 if (pc > low)
645 uiout->text ("\n");
646 if (ui_out_tuple_chain != NULL)
647 {
648 gdb_assert (ui_out_list_chain != NULL);
649 do_cleanups (ui_out_list_chain);
650 do_cleanups (ui_out_tuple_chain);
651 }
652 if (sal.symtab != last_symtab
653 && !(flags & DISASSEMBLY_FILENAME))
654 {
655 /* Remember MI ignores ui_out_text.
656 We don't have to do anything here for MI because MI
657 output includes the source specs for each line. */
658 if (sal.symtab != NULL)
659 {
660 uiout->text (symtab_to_filename_for_display (sal.symtab));
661 }
662 else
663 uiout->text ("unknown");
664 uiout->text (":\n");
665 }
666 if (start_preceding_line_to_display > 0)
667 {
668 /* Several source lines w/o asm instructions associated.
669 We need to preserve the structure of the output, so output
670 a bunch of line tuples with no asm entries. */
671 int l;
672 struct cleanup *ui_out_list_chain_line;
673 struct cleanup *ui_out_tuple_chain_line;
674
675 gdb_assert (sal.symtab != NULL);
676 for (l = start_preceding_line_to_display;
677 l < end_preceding_line_to_display;
678 ++l)
679 {
680 ui_out_tuple_chain_line
681 = make_cleanup_ui_out_tuple_begin_end (uiout,
682 "src_and_asm_line");
683 print_source_lines (sal.symtab, l, l + 1, psl_flags);
684 ui_out_list_chain_line
685 = make_cleanup_ui_out_list_begin_end (uiout,
686 "line_asm_insn");
687 do_cleanups (ui_out_list_chain_line);
688 do_cleanups (ui_out_tuple_chain_line);
689 }
690 }
691 ui_out_tuple_chain
692 = make_cleanup_ui_out_tuple_begin_end (uiout, "src_and_asm_line");
693 if (sal.symtab != NULL)
694 print_source_lines (sal.symtab, sal.line, sal.line + 1, psl_flags);
695 else
696 uiout->text (_("--- no source info for this pc ---\n"));
697 ui_out_list_chain
698 = make_cleanup_ui_out_list_begin_end (uiout, "line_asm_insn");
699 }
700 else
701 {
702 /* Here we're appending instructions to an existing line.
703 By construction the very first insn will have a symtab
704 and follow the new_source_line path above. */
705 gdb_assert (ui_out_tuple_chain != NULL);
706 gdb_assert (ui_out_list_chain != NULL);
707 }
708
709 if (sal.end != 0)
710 end_pc = std::min (sal.end, high);
711 else
712 end_pc = pc + 1;
713 num_displayed += dump_insns (gdbarch, uiout, pc, end_pc,
714 how_many, flags, &end_pc);
715 pc = end_pc;
716
717 if (how_many >= 0 && num_displayed >= how_many)
718 break;
719
720 last_symtab = sal.symtab;
721 last_line = sal.line;
722 }
723
724 do_cleanups (ui_out_chain);
725 }
726
727 static void
728 do_assembly_only (struct gdbarch *gdbarch, struct ui_out *uiout,
729 CORE_ADDR low, CORE_ADDR high,
730 int how_many, int flags)
731 {
732 struct cleanup *ui_out_chain;
733
734 ui_out_chain = make_cleanup_ui_out_list_begin_end (uiout, "asm_insns");
735
736 dump_insns (gdbarch, uiout, low, high, how_many, flags, NULL);
737
738 do_cleanups (ui_out_chain);
739 }
740
741 /* Initialize the disassemble info struct ready for the specified
742 stream. */
743
744 static int ATTRIBUTE_PRINTF (2, 3)
745 fprintf_disasm (void *stream, const char *format, ...)
746 {
747 va_list args;
748
749 va_start (args, format);
750 vfprintf_filtered ((struct ui_file *) stream, format, args);
751 va_end (args);
752 /* Something non -ve. */
753 return 0;
754 }
755
756 gdb_disassembler::gdb_disassembler (struct gdbarch *gdbarch,
757 struct ui_file *file,
758 di_read_memory_ftype read_memory_func)
759 : m_gdbarch (gdbarch),
760 m_err_memaddr (0)
761 {
762 init_disassemble_info (&m_di, file, fprintf_disasm);
763 m_di.flavour = bfd_target_unknown_flavour;
764 m_di.memory_error_func = dis_asm_memory_error;
765 m_di.print_address_func = dis_asm_print_address;
766 /* NOTE: cagney/2003-04-28: The original code, from the old Insight
767 disassembler had a local optomization here. By default it would
768 access the executable file, instead of the target memory (there
769 was a growing list of exceptions though). Unfortunately, the
770 heuristic was flawed. Commands like "disassemble &variable"
771 didn't work as they relied on the access going to the target.
772 Further, it has been supperseeded by trust-read-only-sections
773 (although that should be superseeded by target_trust..._p()). */
774 m_di.read_memory_func = read_memory_func;
775 m_di.arch = gdbarch_bfd_arch_info (gdbarch)->arch;
776 m_di.mach = gdbarch_bfd_arch_info (gdbarch)->mach;
777 m_di.endian = gdbarch_byte_order (gdbarch);
778 m_di.endian_code = gdbarch_byte_order_for_code (gdbarch);
779 m_di.application_data = this;
780 disassemble_init_for_target (&m_di);
781 }
782
783 int
784 gdb_disassembler::print_insn (CORE_ADDR memaddr,
785 int *branch_delay_insns)
786 {
787 m_err_memaddr = 0;
788
789 int length = gdbarch_print_insn (arch (), memaddr, &m_di);
790
791 if (length < 0)
792 memory_error (TARGET_XFER_E_IO, m_err_memaddr);
793
794 if (branch_delay_insns != NULL)
795 {
796 if (m_di.insn_info_valid)
797 *branch_delay_insns = m_di.branch_delay_insns;
798 else
799 *branch_delay_insns = 0;
800 }
801 return length;
802 }
803
804 void
805 gdb_disassembly (struct gdbarch *gdbarch, struct ui_out *uiout,
806 int flags, int how_many,
807 CORE_ADDR low, CORE_ADDR high)
808 {
809 struct symtab *symtab;
810 int nlines = -1;
811
812 /* Assume symtab is valid for whole PC range. */
813 symtab = find_pc_line_symtab (low);
814
815 if (symtab != NULL && SYMTAB_LINETABLE (symtab) != NULL)
816 nlines = SYMTAB_LINETABLE (symtab)->nitems;
817
818 if (!(flags & (DISASSEMBLY_SOURCE_DEPRECATED | DISASSEMBLY_SOURCE))
819 || nlines <= 0)
820 do_assembly_only (gdbarch, uiout, low, high, how_many, flags);
821
822 else if (flags & DISASSEMBLY_SOURCE)
823 do_mixed_source_and_assembly (gdbarch, uiout, symtab, low, high,
824 how_many, flags);
825
826 else if (flags & DISASSEMBLY_SOURCE_DEPRECATED)
827 do_mixed_source_and_assembly_deprecated (gdbarch, uiout, symtab,
828 low, high, how_many, flags);
829
830 gdb_flush (gdb_stdout);
831 }
832
833 /* Print the instruction at address MEMADDR in debugged memory,
834 on STREAM. Returns the length of the instruction, in bytes,
835 and, if requested, the number of branch delay slot instructions. */
836
837 int
838 gdb_print_insn (struct gdbarch *gdbarch, CORE_ADDR memaddr,
839 struct ui_file *stream, int *branch_delay_insns)
840 {
841
842 gdb_disassembler di (gdbarch, stream);
843
844 return di.print_insn (memaddr, branch_delay_insns);
845 }
846
847 /* Return the length in bytes of the instruction at address MEMADDR in
848 debugged memory. */
849
850 int
851 gdb_insn_length (struct gdbarch *gdbarch, CORE_ADDR addr)
852 {
853 return gdb_print_insn (gdbarch, addr, &null_stream, NULL);
854 }
855
856 /* fprintf-function for gdb_buffered_insn_length. This function is a
857 nop, we don't want to print anything, we just want to compute the
858 length of the insn. */
859
860 static int ATTRIBUTE_PRINTF (2, 3)
861 gdb_buffered_insn_length_fprintf (void *stream, const char *format, ...)
862 {
863 return 0;
864 }
865
866 /* Initialize a struct disassemble_info for gdb_buffered_insn_length. */
867
868 static void
869 gdb_buffered_insn_length_init_dis (struct gdbarch *gdbarch,
870 struct disassemble_info *di,
871 const gdb_byte *insn, int max_len,
872 CORE_ADDR addr)
873 {
874 init_disassemble_info (di, NULL, gdb_buffered_insn_length_fprintf);
875
876 /* init_disassemble_info installs buffer_read_memory, etc.
877 so we don't need to do that here.
878 The cast is necessary until disassemble_info is const-ified. */
879 di->buffer = (gdb_byte *) insn;
880 di->buffer_length = max_len;
881 di->buffer_vma = addr;
882
883 di->arch = gdbarch_bfd_arch_info (gdbarch)->arch;
884 di->mach = gdbarch_bfd_arch_info (gdbarch)->mach;
885 di->endian = gdbarch_byte_order (gdbarch);
886 di->endian_code = gdbarch_byte_order_for_code (gdbarch);
887
888 disassemble_init_for_target (di);
889 }
890
891 /* Return the length in bytes of INSN. MAX_LEN is the size of the
892 buffer containing INSN. */
893
894 int
895 gdb_buffered_insn_length (struct gdbarch *gdbarch,
896 const gdb_byte *insn, int max_len, CORE_ADDR addr)
897 {
898 struct disassemble_info di;
899
900 gdb_buffered_insn_length_init_dis (gdbarch, &di, insn, max_len, addr);
901
902 return gdbarch_print_insn (gdbarch, addr, &di);
903 }