Don't throw exception in dis_asm_memory_error
[deliverable/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_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 ui_file *stb = stream ();
199 struct gdbarch *gdbarch = arch ();
200
201 ui_out_chain = make_cleanup_ui_out_tuple_begin_end (uiout, NULL);
202 pc = insn->addr;
203
204 if (insn->number != 0)
205 {
206 uiout->field_fmt ("insn-number", "%u", insn->number);
207 uiout->text ("\t");
208 }
209
210 if ((flags & DISASSEMBLY_SPECULATIVE) != 0)
211 {
212 if (insn->is_speculative)
213 {
214 uiout->field_string ("is-speculative", "?");
215
216 /* The speculative execution indication overwrites the first
217 character of the PC prefix.
218 We assume a PC prefix length of 3 characters. */
219 if ((flags & DISASSEMBLY_OMIT_PC) == 0)
220 uiout->text (pc_prefix (pc) + 1);
221 else
222 uiout->text (" ");
223 }
224 else if ((flags & DISASSEMBLY_OMIT_PC) == 0)
225 uiout->text (pc_prefix (pc));
226 else
227 uiout->text (" ");
228 }
229 else if ((flags & DISASSEMBLY_OMIT_PC) == 0)
230 uiout->text (pc_prefix (pc));
231 uiout->field_core_addr ("address", gdbarch, pc);
232
233 if (!build_address_symbolic (gdbarch, pc, 0, &name, &offset, &filename,
234 &line, &unmapped))
235 {
236 /* We don't care now about line, filename and unmapped. But we might in
237 the future. */
238 uiout->text (" <");
239 if ((flags & DISASSEMBLY_OMIT_FNAME) == 0)
240 uiout->field_string ("func-name", name);
241 uiout->text ("+");
242 uiout->field_int ("offset", offset);
243 uiout->text (">:\t");
244 }
245 else
246 uiout->text (":\t");
247
248 if (filename != NULL)
249 xfree (filename);
250 if (name != NULL)
251 xfree (name);
252
253 ui_file_rewind (stb);
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 struct ui_file *opcode_stream = mem_fileopen ();
264 struct cleanup *cleanups =
265 make_cleanup_ui_file_delete (opcode_stream);
266
267 size = print_insn (pc);
268 end_pc = pc + size;
269
270 for (;pc < end_pc; ++pc)
271 {
272 err = m_di.read_memory_func (pc, &data, 1, &m_di);
273 if (err != 0)
274 m_di.memory_error_func (err, pc, &m_di);
275 fprintf_filtered (opcode_stream, "%s%02x",
276 spacer, (unsigned) data);
277 spacer = " ";
278 }
279
280 uiout->field_stream ("opcodes", opcode_stream);
281 uiout->text ("\t");
282
283 do_cleanups (cleanups);
284 }
285 else
286 size = print_insn (pc);
287
288 uiout->field_stream ("inst", stb);
289 ui_file_rewind (stb);
290 do_cleanups (ui_out_chain);
291 uiout->text ("\n");
292
293 return size;
294 }
295
296 static int
297 dump_insns (struct ui_out *uiout, gdb_disassembler *di,
298 CORE_ADDR low, CORE_ADDR high,
299 int how_many, int flags,
300 CORE_ADDR *end_pc)
301 {
302 struct disasm_insn insn;
303 int num_displayed = 0;
304
305 memset (&insn, 0, sizeof (insn));
306 insn.addr = low;
307
308 while (insn.addr < high && (how_many < 0 || num_displayed < how_many))
309 {
310 int size;
311
312 size = di->pretty_print_insn (uiout, &insn, flags);
313 if (size <= 0)
314 break;
315
316 ++num_displayed;
317 insn.addr += size;
318
319 /* Allow user to bail out with ^C. */
320 QUIT;
321 }
322
323 if (end_pc != NULL)
324 *end_pc = insn.addr;
325
326 return num_displayed;
327 }
328
329 /* The idea here is to present a source-O-centric view of a
330 function to the user. This means that things are presented
331 in source order, with (possibly) out of order assembly
332 immediately following.
333
334 N.B. This view is deprecated. */
335
336 static void
337 do_mixed_source_and_assembly_deprecated
338 (struct ui_out *uiout,
339 gdb_disassembler *di, struct symtab *symtab,
340 CORE_ADDR low, CORE_ADDR high,
341 int how_many, int flags)
342 {
343 int newlines = 0;
344 int nlines;
345 struct linetable_entry *le;
346 struct deprecated_dis_line_entry *mle;
347 struct symtab_and_line sal;
348 int i;
349 int out_of_order = 0;
350 int next_line = 0;
351 int num_displayed = 0;
352 print_source_lines_flags psl_flags = 0;
353 struct cleanup *ui_out_chain;
354 struct cleanup *ui_out_tuple_chain = make_cleanup (null_cleanup, 0);
355 struct cleanup *ui_out_list_chain = make_cleanup (null_cleanup, 0);
356
357 gdb_assert (symtab != NULL && SYMTAB_LINETABLE (symtab) != NULL);
358
359 nlines = SYMTAB_LINETABLE (symtab)->nitems;
360 le = SYMTAB_LINETABLE (symtab)->item;
361
362 if (flags & DISASSEMBLY_FILENAME)
363 psl_flags |= PRINT_SOURCE_LINES_FILENAME;
364
365 mle = (struct deprecated_dis_line_entry *)
366 alloca (nlines * sizeof (struct deprecated_dis_line_entry));
367
368 /* Copy linetable entries for this function into our data
369 structure, creating end_pc's and setting out_of_order as
370 appropriate. */
371
372 /* First, skip all the preceding functions. */
373
374 for (i = 0; i < nlines - 1 && le[i].pc < low; i++);
375
376 /* Now, copy all entries before the end of this function. */
377
378 for (; i < nlines - 1 && le[i].pc < high; i++)
379 {
380 if (le[i].line == le[i + 1].line && le[i].pc == le[i + 1].pc)
381 continue; /* Ignore duplicates. */
382
383 /* Skip any end-of-function markers. */
384 if (le[i].line == 0)
385 continue;
386
387 mle[newlines].line = le[i].line;
388 if (le[i].line > le[i + 1].line)
389 out_of_order = 1;
390 mle[newlines].start_pc = le[i].pc;
391 mle[newlines].end_pc = le[i + 1].pc;
392 newlines++;
393 }
394
395 /* If we're on the last line, and it's part of the function,
396 then we need to get the end pc in a special way. */
397
398 if (i == nlines - 1 && le[i].pc < high)
399 {
400 mle[newlines].line = le[i].line;
401 mle[newlines].start_pc = le[i].pc;
402 sal = find_pc_line (le[i].pc, 0);
403 mle[newlines].end_pc = sal.end;
404 newlines++;
405 }
406
407 /* Now, sort mle by line #s (and, then by addresses within lines). */
408
409 if (out_of_order)
410 qsort (mle, newlines, sizeof (struct deprecated_dis_line_entry),
411 compare_lines);
412
413 /* Now, for each line entry, emit the specified lines (unless
414 they have been emitted before), followed by the assembly code
415 for that line. */
416
417 ui_out_chain = make_cleanup_ui_out_list_begin_end (uiout, "asm_insns");
418
419 for (i = 0; i < newlines; i++)
420 {
421 /* Print out everything from next_line to the current line. */
422 if (mle[i].line >= next_line)
423 {
424 if (next_line != 0)
425 {
426 /* Just one line to print. */
427 if (next_line == mle[i].line)
428 {
429 ui_out_tuple_chain
430 = make_cleanup_ui_out_tuple_begin_end (uiout,
431 "src_and_asm_line");
432 print_source_lines (symtab, next_line, mle[i].line + 1, psl_flags);
433 }
434 else
435 {
436 /* Several source lines w/o asm instructions associated. */
437 for (; next_line < mle[i].line; next_line++)
438 {
439 struct cleanup *ui_out_list_chain_line;
440 struct cleanup *ui_out_tuple_chain_line;
441
442 ui_out_tuple_chain_line
443 = make_cleanup_ui_out_tuple_begin_end (uiout,
444 "src_and_asm_line");
445 print_source_lines (symtab, next_line, next_line + 1,
446 psl_flags);
447 ui_out_list_chain_line
448 = make_cleanup_ui_out_list_begin_end (uiout,
449 "line_asm_insn");
450 do_cleanups (ui_out_list_chain_line);
451 do_cleanups (ui_out_tuple_chain_line);
452 }
453 /* Print the last line and leave list open for
454 asm instructions to be added. */
455 ui_out_tuple_chain
456 = make_cleanup_ui_out_tuple_begin_end (uiout,
457 "src_and_asm_line");
458 print_source_lines (symtab, next_line, mle[i].line + 1, psl_flags);
459 }
460 }
461 else
462 {
463 ui_out_tuple_chain
464 = make_cleanup_ui_out_tuple_begin_end (uiout,
465 "src_and_asm_line");
466 print_source_lines (symtab, mle[i].line, mle[i].line + 1, psl_flags);
467 }
468
469 next_line = mle[i].line + 1;
470 ui_out_list_chain
471 = make_cleanup_ui_out_list_begin_end (uiout, "line_asm_insn");
472 }
473
474 num_displayed += dump_insns (uiout, di,
475 mle[i].start_pc, mle[i].end_pc,
476 how_many, flags, NULL);
477
478 /* When we've reached the end of the mle array, or we've seen the last
479 assembly range for this source line, close out the list/tuple. */
480 if (i == (newlines - 1) || mle[i + 1].line > mle[i].line)
481 {
482 do_cleanups (ui_out_list_chain);
483 do_cleanups (ui_out_tuple_chain);
484 ui_out_tuple_chain = make_cleanup (null_cleanup, 0);
485 ui_out_list_chain = make_cleanup (null_cleanup, 0);
486 uiout->text ("\n");
487 }
488 if (how_many >= 0 && num_displayed >= how_many)
489 break;
490 }
491 do_cleanups (ui_out_chain);
492 }
493
494 /* The idea here is to present a source-O-centric view of a
495 function to the user. This means that things are presented
496 in source order, with (possibly) out of order assembly
497 immediately following. */
498
499 static void
500 do_mixed_source_and_assembly (struct gdbarch *gdbarch,
501 struct ui_out *uiout,
502 gdb_disassembler *di,
503 struct symtab *main_symtab,
504 CORE_ADDR low, CORE_ADDR high,
505 int how_many, int flags)
506 {
507 const struct linetable_entry *le, *first_le;
508 int i, nlines;
509 int num_displayed = 0;
510 print_source_lines_flags psl_flags = 0;
511 struct cleanup *ui_out_chain;
512 struct cleanup *ui_out_tuple_chain;
513 struct cleanup *ui_out_list_chain;
514 CORE_ADDR pc;
515 struct symtab *last_symtab;
516 int last_line;
517
518 gdb_assert (main_symtab != NULL && SYMTAB_LINETABLE (main_symtab) != NULL);
519
520 /* First pass: collect the list of all source files and lines.
521 We do this so that we can only print lines containing code once.
522 We try to print the source text leading up to the next instruction,
523 but if that text is for code that will be disassembled later, then
524 we'll want to defer printing it until later with its associated code. */
525
526 htab_up dis_line_table (allocate_dis_line_table ());
527
528 pc = low;
529
530 /* The prologue may be empty, but there may still be a line number entry
531 for the opening brace which is distinct from the first line of code.
532 If the prologue has been eliminated find_pc_line may return the source
533 line after the opening brace. We still want to print this opening brace.
534 first_le is used to implement this. */
535
536 nlines = SYMTAB_LINETABLE (main_symtab)->nitems;
537 le = SYMTAB_LINETABLE (main_symtab)->item;
538 first_le = NULL;
539
540 /* Skip all the preceding functions. */
541 for (i = 0; i < nlines && le[i].pc < low; i++)
542 continue;
543
544 if (i < nlines && le[i].pc < high)
545 first_le = &le[i];
546
547 /* Add lines for every pc value. */
548 while (pc < high)
549 {
550 struct symtab_and_line sal;
551 int length;
552
553 sal = find_pc_line (pc, 0);
554 length = gdb_insn_length (gdbarch, pc);
555 pc += length;
556
557 if (sal.symtab != NULL)
558 add_dis_line_entry (dis_line_table.get (), sal.symtab, sal.line);
559 }
560
561 /* Second pass: print the disassembly.
562
563 Output format, from an MI perspective:
564 The result is a ui_out list, field name "asm_insns", where elements have
565 name "src_and_asm_line".
566 Each element is a tuple of source line specs (field names line, file,
567 fullname), and field "line_asm_insn" which contains the disassembly.
568 Field "line_asm_insn" is a list of tuples: address, func-name, offset,
569 opcodes, inst.
570
571 CLI output works on top of this because MI ignores ui_out_text output,
572 which is where we put file name and source line contents output.
573
574 Cleanup usage:
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 symtab_and_line sal;
597 CORE_ADDR end_pc;
598 int start_preceding_line_to_display = 0;
599 int end_preceding_line_to_display = 0;
600 int new_source_line = 0;
601
602 sal = find_pc_line (pc, 0);
603
604 if (sal.symtab != last_symtab)
605 {
606 /* New source file. */
607 new_source_line = 1;
608
609 /* If this is the first line of output, check for any preceding
610 lines. */
611 if (last_line == 0
612 && first_le != NULL
613 && first_le->line < sal.line)
614 {
615 start_preceding_line_to_display = first_le->line;
616 end_preceding_line_to_display = sal.line;
617 }
618 }
619 else
620 {
621 /* Same source file as last time. */
622 if (sal.symtab != NULL)
623 {
624 if (sal.line > last_line + 1 && last_line != 0)
625 {
626 int l;
627
628 /* Several preceding source lines. Print the trailing ones
629 not associated with code that we'll print later. */
630 for (l = sal.line - 1; l > last_line; --l)
631 {
632 if (line_has_code_p (dis_line_table.get (),
633 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 uiout->text ("\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 uiout->text (symtab_to_filename_for_display (sal.symtab));
672 }
673 else
674 uiout->text ("unknown");
675 uiout->text (":\n");
676 }
677 if (start_preceding_line_to_display > 0)
678 {
679 /* Several source lines w/o asm instructions associated.
680 We need to preserve the structure of the output, so output
681 a bunch of line tuples with no asm entries. */
682 int l;
683 struct cleanup *ui_out_list_chain_line;
684 struct cleanup *ui_out_tuple_chain_line;
685
686 gdb_assert (sal.symtab != NULL);
687 for (l = start_preceding_line_to_display;
688 l < end_preceding_line_to_display;
689 ++l)
690 {
691 ui_out_tuple_chain_line
692 = make_cleanup_ui_out_tuple_begin_end (uiout,
693 "src_and_asm_line");
694 print_source_lines (sal.symtab, l, l + 1, psl_flags);
695 ui_out_list_chain_line
696 = make_cleanup_ui_out_list_begin_end (uiout,
697 "line_asm_insn");
698 do_cleanups (ui_out_list_chain_line);
699 do_cleanups (ui_out_tuple_chain_line);
700 }
701 }
702 ui_out_tuple_chain
703 = make_cleanup_ui_out_tuple_begin_end (uiout, "src_and_asm_line");
704 if (sal.symtab != NULL)
705 print_source_lines (sal.symtab, sal.line, sal.line + 1, psl_flags);
706 else
707 uiout->text (_("--- no source info for this pc ---\n"));
708 ui_out_list_chain
709 = make_cleanup_ui_out_list_begin_end (uiout, "line_asm_insn");
710 }
711 else
712 {
713 /* Here we're appending instructions to an existing line.
714 By construction the very first insn will have a symtab
715 and follow the new_source_line path above. */
716 gdb_assert (ui_out_tuple_chain != NULL);
717 gdb_assert (ui_out_list_chain != NULL);
718 }
719
720 if (sal.end != 0)
721 end_pc = std::min (sal.end, high);
722 else
723 end_pc = pc + 1;
724 num_displayed += dump_insns (uiout, di, pc, end_pc,
725 how_many, flags, &end_pc);
726 pc = end_pc;
727
728 if (how_many >= 0 && num_displayed >= how_many)
729 break;
730
731 last_symtab = sal.symtab;
732 last_line = sal.line;
733 }
734
735 do_cleanups (ui_out_chain);
736 }
737
738 static void
739 do_assembly_only (struct ui_out *uiout,
740 gdb_disassembler *di,
741 CORE_ADDR low, CORE_ADDR high,
742 int how_many, int flags)
743 {
744 struct cleanup *ui_out_chain;
745
746 ui_out_chain = make_cleanup_ui_out_list_begin_end (uiout, "asm_insns");
747
748 dump_insns (uiout, di, low, high, how_many, flags, NULL);
749
750 do_cleanups (ui_out_chain);
751 }
752
753 /* Initialize the disassemble info struct ready for the specified
754 stream. */
755
756 static int ATTRIBUTE_PRINTF (2, 3)
757 fprintf_disasm (void *stream, const char *format, ...)
758 {
759 va_list args;
760
761 va_start (args, format);
762 vfprintf_filtered ((struct ui_file *) stream, format, args);
763 va_end (args);
764 /* Something non -ve. */
765 return 0;
766 }
767
768 gdb_disassembler::gdb_disassembler (struct gdbarch *gdbarch,
769 struct ui_file *file,
770 di_read_memory_ftype read_memory_func)
771 : m_gdbarch (gdbarch),
772 m_err_memaddr (0)
773 {
774 init_disassemble_info (&m_di, file, fprintf_disasm);
775 m_di.flavour = bfd_target_unknown_flavour;
776 m_di.memory_error_func = dis_asm_memory_error;
777 m_di.print_address_func = dis_asm_print_address;
778 /* NOTE: cagney/2003-04-28: The original code, from the old Insight
779 disassembler had a local optomization here. By default it would
780 access the executable file, instead of the target memory (there
781 was a growing list of exceptions though). Unfortunately, the
782 heuristic was flawed. Commands like "disassemble &variable"
783 didn't work as they relied on the access going to the target.
784 Further, it has been supperseeded by trust-read-only-sections
785 (although that should be superseeded by target_trust..._p()). */
786 m_di.read_memory_func = read_memory_func;
787 m_di.arch = gdbarch_bfd_arch_info (gdbarch)->arch;
788 m_di.mach = gdbarch_bfd_arch_info (gdbarch)->mach;
789 m_di.endian = gdbarch_byte_order (gdbarch);
790 m_di.endian_code = gdbarch_byte_order_for_code (gdbarch);
791 m_di.application_data = this;
792 disassemble_init_for_target (&m_di);
793 }
794
795 int
796 gdb_disassembler::print_insn (CORE_ADDR memaddr,
797 int *branch_delay_insns)
798 {
799 m_err_memaddr = 0;
800
801 int length = gdbarch_print_insn (arch (), memaddr, &m_di);
802
803 if (length < 0)
804 memory_error (TARGET_XFER_E_IO, m_err_memaddr);
805
806 if (branch_delay_insns != NULL)
807 {
808 if (m_di.insn_info_valid)
809 *branch_delay_insns = m_di.branch_delay_insns;
810 else
811 *branch_delay_insns = 0;
812 }
813 return length;
814 }
815
816 void
817 gdb_disassembly (struct gdbarch *gdbarch, struct ui_out *uiout,
818 char *file_string, int flags, int how_many,
819 CORE_ADDR low, CORE_ADDR high)
820 {
821 struct ui_file *stb = mem_fileopen ();
822 struct cleanup *cleanups = make_cleanup_ui_file_delete (stb);
823 gdb_disassembler di (gdbarch, stb);
824 struct symtab *symtab;
825 int nlines = -1;
826
827 /* Assume symtab is valid for whole PC range. */
828 symtab = find_pc_line_symtab (low);
829
830 if (symtab != NULL && SYMTAB_LINETABLE (symtab) != NULL)
831 nlines = SYMTAB_LINETABLE (symtab)->nitems;
832
833 if (!(flags & (DISASSEMBLY_SOURCE_DEPRECATED | DISASSEMBLY_SOURCE))
834 || nlines <= 0)
835 do_assembly_only (uiout, &di, low, high, how_many, flags);
836
837 else if (flags & DISASSEMBLY_SOURCE)
838 do_mixed_source_and_assembly (gdbarch, uiout, &di, symtab, low, high,
839 how_many, flags);
840
841 else if (flags & DISASSEMBLY_SOURCE_DEPRECATED)
842 do_mixed_source_and_assembly_deprecated (uiout, &di, symtab,
843 low, high, how_many, flags);
844
845 do_cleanups (cleanups);
846 gdb_flush (gdb_stdout);
847 }
848
849 /* Print the instruction at address MEMADDR in debugged memory,
850 on STREAM. Returns the length of the instruction, in bytes,
851 and, if requested, the number of branch delay slot instructions. */
852
853 int
854 gdb_print_insn (struct gdbarch *gdbarch, CORE_ADDR memaddr,
855 struct ui_file *stream, int *branch_delay_insns)
856 {
857
858 gdb_disassembler di (gdbarch, stream);
859
860 return di.print_insn (memaddr, branch_delay_insns);
861 }
862
863 /* Return the length in bytes of the instruction at address MEMADDR in
864 debugged memory. */
865
866 int
867 gdb_insn_length (struct gdbarch *gdbarch, CORE_ADDR addr)
868 {
869 return gdb_print_insn (gdbarch, addr, null_stream (), NULL);
870 }
871
872 /* fprintf-function for gdb_buffered_insn_length. This function is a
873 nop, we don't want to print anything, we just want to compute the
874 length of the insn. */
875
876 static int ATTRIBUTE_PRINTF (2, 3)
877 gdb_buffered_insn_length_fprintf (void *stream, const char *format, ...)
878 {
879 return 0;
880 }
881
882 /* Initialize a struct disassemble_info for gdb_buffered_insn_length. */
883
884 static void
885 gdb_buffered_insn_length_init_dis (struct gdbarch *gdbarch,
886 struct disassemble_info *di,
887 const gdb_byte *insn, int max_len,
888 CORE_ADDR addr)
889 {
890 init_disassemble_info (di, NULL, gdb_buffered_insn_length_fprintf);
891
892 /* init_disassemble_info installs buffer_read_memory, etc.
893 so we don't need to do that here.
894 The cast is necessary until disassemble_info is const-ified. */
895 di->buffer = (gdb_byte *) insn;
896 di->buffer_length = max_len;
897 di->buffer_vma = addr;
898
899 di->arch = gdbarch_bfd_arch_info (gdbarch)->arch;
900 di->mach = gdbarch_bfd_arch_info (gdbarch)->mach;
901 di->endian = gdbarch_byte_order (gdbarch);
902 di->endian_code = gdbarch_byte_order_for_code (gdbarch);
903
904 disassemble_init_for_target (di);
905 }
906
907 /* Return the length in bytes of INSN. MAX_LEN is the size of the
908 buffer containing INSN. */
909
910 int
911 gdb_buffered_insn_length (struct gdbarch *gdbarch,
912 const gdb_byte *insn, int max_len, CORE_ADDR addr)
913 {
914 struct disassemble_info di;
915
916 gdb_buffered_insn_length_init_dis (gdbarch, &di, insn, max_len, addr);
917
918 return gdbarch_print_insn (gdbarch, addr, &di);
919 }
This page took 0.051111 seconds and 5 git commands to generate.