1 /* Disassemble support for GDB.
3 Copyright (C) 2000-2005, 2007-2012 Free Software Foundation, Inc.
5 This file is part of GDB.
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.
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.
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/>. */
24 #include "gdb_string.h"
29 /* Disassemble functions.
30 FIXME: We should get rid of all the duplicate code in gdb that does
31 the same thing: disassemble_command() and the gdbtk variation. */
33 /* This Structure is used to store line number information.
34 We need a different sort of line table from the normal one cuz we can't
35 depend upon implicit line-end pc's for lines to do the
36 reordering in this function. */
45 /* Like target_read_memory, but slightly different parameters. */
47 dis_asm_read_memory (bfd_vma memaddr
, gdb_byte
*myaddr
, unsigned int len
,
48 struct disassemble_info
*info
)
50 return target_read_memory (memaddr
, myaddr
, len
);
53 /* Like memory_error with slightly different parameters. */
55 dis_asm_memory_error (int status
, bfd_vma memaddr
,
56 struct disassemble_info
*info
)
58 memory_error (status
, memaddr
);
61 /* Like print_address with slightly different parameters. */
63 dis_asm_print_address (bfd_vma addr
, struct disassemble_info
*info
)
65 struct gdbarch
*gdbarch
= info
->application_data
;
67 print_address (gdbarch
, addr
, info
->stream
);
71 compare_lines (const void *mle1p
, const void *mle2p
)
73 struct dis_line_entry
*mle1
, *mle2
;
76 mle1
= (struct dis_line_entry
*) mle1p
;
77 mle2
= (struct dis_line_entry
*) mle2p
;
79 /* End of sequence markers have a line number of 0 but don't want to
80 be sorted to the head of the list, instead sort by PC. */
81 if (mle1
->line
== 0 || mle2
->line
== 0)
83 val
= mle1
->start_pc
- mle2
->start_pc
;
85 val
= mle1
->line
- mle2
->line
;
89 val
= mle1
->line
- mle2
->line
;
91 val
= mle1
->start_pc
- mle2
->start_pc
;
97 dump_insns (struct gdbarch
*gdbarch
, struct ui_out
*uiout
,
98 struct disassemble_info
* di
,
99 CORE_ADDR low
, CORE_ADDR high
,
100 int how_many
, int flags
, struct ui_file
*stb
)
102 int num_displayed
= 0;
105 /* parts of the symbolic representation of the address */
109 struct cleanup
*ui_out_chain
;
111 for (pc
= low
; pc
< high
;)
113 char *filename
= NULL
;
119 if (num_displayed
>= how_many
)
124 ui_out_chain
= make_cleanup_ui_out_tuple_begin_end (uiout
, NULL
);
125 ui_out_text (uiout
, pc_prefix (pc
));
126 ui_out_field_core_addr (uiout
, "address", gdbarch
, pc
);
128 if (!build_address_symbolic (gdbarch
, pc
, 0, &name
, &offset
, &filename
,
131 /* We don't care now about line, filename and
132 unmapped. But we might in the future. */
133 ui_out_text (uiout
, " <");
134 if ((flags
& DISASSEMBLY_OMIT_FNAME
) == 0)
135 ui_out_field_string (uiout
, "func-name", name
);
136 ui_out_text (uiout
, "+");
137 ui_out_field_int (uiout
, "offset", offset
);
138 ui_out_text (uiout
, ">:\t");
141 ui_out_text (uiout
, ":\t");
143 if (filename
!= NULL
)
148 ui_file_rewind (stb
);
149 if (flags
& DISASSEMBLY_RAW_INSN
)
151 CORE_ADDR old_pc
= pc
;
154 const char *spacer
= "";
156 /* Build the opcodes using a temporary stream so we can
157 write them out in a single go for the MI. */
158 struct ui_file
*opcode_stream
= mem_fileopen ();
159 struct cleanup
*cleanups
=
160 make_cleanup_ui_file_delete (opcode_stream
);
162 pc
+= gdbarch_print_insn (gdbarch
, pc
, di
);
163 for (;old_pc
< pc
; old_pc
++)
165 status
= (*di
->read_memory_func
) (old_pc
, &data
, 1, di
);
167 (*di
->memory_error_func
) (status
, old_pc
, di
);
168 fprintf_filtered (opcode_stream
, "%s%02x",
169 spacer
, (unsigned) data
);
172 ui_out_field_stream (uiout
, "opcodes", opcode_stream
);
173 ui_out_text (uiout
, "\t");
175 do_cleanups (cleanups
);
178 pc
+= gdbarch_print_insn (gdbarch
, pc
, di
);
179 ui_out_field_stream (uiout
, "inst", stb
);
180 ui_file_rewind (stb
);
181 do_cleanups (ui_out_chain
);
182 ui_out_text (uiout
, "\n");
184 return num_displayed
;
187 /* The idea here is to present a source-O-centric view of a
188 function to the user. This means that things are presented
189 in source order, with (possibly) out of order assembly
190 immediately following. */
193 do_mixed_source_and_assembly (struct gdbarch
*gdbarch
, struct ui_out
*uiout
,
194 struct disassemble_info
*di
, int nlines
,
195 struct linetable_entry
*le
,
196 CORE_ADDR low
, CORE_ADDR high
,
197 struct symtab
*symtab
,
198 int how_many
, int flags
, struct ui_file
*stb
)
201 struct dis_line_entry
*mle
;
202 struct symtab_and_line sal
;
204 int out_of_order
= 0;
206 int num_displayed
= 0;
207 struct cleanup
*ui_out_chain
;
208 struct cleanup
*ui_out_tuple_chain
= make_cleanup (null_cleanup
, 0);
209 struct cleanup
*ui_out_list_chain
= make_cleanup (null_cleanup
, 0);
211 mle
= (struct dis_line_entry
*) alloca (nlines
212 * sizeof (struct dis_line_entry
));
214 /* Copy linetable entries for this function into our data
215 structure, creating end_pc's and setting out_of_order as
218 /* First, skip all the preceding functions. */
220 for (i
= 0; i
< nlines
- 1 && le
[i
].pc
< low
; i
++);
222 /* Now, copy all entries before the end of this function. */
224 for (; i
< nlines
- 1 && le
[i
].pc
< high
; i
++)
226 if (le
[i
].line
== le
[i
+ 1].line
&& le
[i
].pc
== le
[i
+ 1].pc
)
227 continue; /* Ignore duplicates. */
229 /* Skip any end-of-function markers. */
233 mle
[newlines
].line
= le
[i
].line
;
234 if (le
[i
].line
> le
[i
+ 1].line
)
236 mle
[newlines
].start_pc
= le
[i
].pc
;
237 mle
[newlines
].end_pc
= le
[i
+ 1].pc
;
241 /* If we're on the last line, and it's part of the function,
242 then we need to get the end pc in a special way. */
244 if (i
== nlines
- 1 && le
[i
].pc
< high
)
246 mle
[newlines
].line
= le
[i
].line
;
247 mle
[newlines
].start_pc
= le
[i
].pc
;
248 sal
= find_pc_line (le
[i
].pc
, 0);
249 mle
[newlines
].end_pc
= sal
.end
;
253 /* Now, sort mle by line #s (and, then by addresses within
257 qsort (mle
, newlines
, sizeof (struct dis_line_entry
), compare_lines
);
259 /* Now, for each line entry, emit the specified lines (unless
260 they have been emitted before), followed by the assembly code
263 ui_out_chain
= make_cleanup_ui_out_list_begin_end (uiout
, "asm_insns");
265 for (i
= 0; i
< newlines
; i
++)
267 /* Print out everything from next_line to the current line. */
268 if (mle
[i
].line
>= next_line
)
272 /* Just one line to print. */
273 if (next_line
== mle
[i
].line
)
276 = make_cleanup_ui_out_tuple_begin_end (uiout
,
278 print_source_lines (symtab
, next_line
, mle
[i
].line
+ 1, 0);
282 /* Several source lines w/o asm instructions associated. */
283 for (; next_line
< mle
[i
].line
; next_line
++)
285 struct cleanup
*ui_out_list_chain_line
;
286 struct cleanup
*ui_out_tuple_chain_line
;
288 ui_out_tuple_chain_line
289 = make_cleanup_ui_out_tuple_begin_end (uiout
,
291 print_source_lines (symtab
, next_line
, next_line
+ 1,
293 ui_out_list_chain_line
294 = make_cleanup_ui_out_list_begin_end (uiout
,
296 do_cleanups (ui_out_list_chain_line
);
297 do_cleanups (ui_out_tuple_chain_line
);
299 /* Print the last line and leave list open for
300 asm instructions to be added. */
302 = make_cleanup_ui_out_tuple_begin_end (uiout
,
304 print_source_lines (symtab
, next_line
, mle
[i
].line
+ 1, 0);
310 = make_cleanup_ui_out_tuple_begin_end (uiout
,
312 print_source_lines (symtab
, mle
[i
].line
, mle
[i
].line
+ 1, 0);
315 next_line
= mle
[i
].line
+ 1;
317 = make_cleanup_ui_out_list_begin_end (uiout
, "line_asm_insn");
320 num_displayed
+= dump_insns (gdbarch
, uiout
, di
,
321 mle
[i
].start_pc
, mle
[i
].end_pc
,
322 how_many
, flags
, stb
);
324 /* When we've reached the end of the mle array, or we've seen the last
325 assembly range for this source line, close out the list/tuple. */
326 if (i
== (newlines
- 1) || mle
[i
+ 1].line
> mle
[i
].line
)
328 do_cleanups (ui_out_list_chain
);
329 do_cleanups (ui_out_tuple_chain
);
330 ui_out_tuple_chain
= make_cleanup (null_cleanup
, 0);
331 ui_out_list_chain
= make_cleanup (null_cleanup
, 0);
332 ui_out_text (uiout
, "\n");
334 if (how_many
>= 0 && num_displayed
>= how_many
)
337 do_cleanups (ui_out_chain
);
342 do_assembly_only (struct gdbarch
*gdbarch
, struct ui_out
*uiout
,
343 struct disassemble_info
* di
,
344 CORE_ADDR low
, CORE_ADDR high
,
345 int how_many
, int flags
, struct ui_file
*stb
)
347 int num_displayed
= 0;
348 struct cleanup
*ui_out_chain
;
350 ui_out_chain
= make_cleanup_ui_out_list_begin_end (uiout
, "asm_insns");
352 num_displayed
= dump_insns (gdbarch
, uiout
, di
, low
, high
, how_many
,
355 do_cleanups (ui_out_chain
);
358 /* Initialize the disassemble info struct ready for the specified
361 static int ATTRIBUTE_PRINTF (2, 3)
362 fprintf_disasm (void *stream
, const char *format
, ...)
366 va_start (args
, format
);
367 vfprintf_filtered (stream
, format
, args
);
369 /* Something non -ve. */
373 static struct disassemble_info
374 gdb_disassemble_info (struct gdbarch
*gdbarch
, struct ui_file
*file
)
376 struct disassemble_info di
;
378 init_disassemble_info (&di
, file
, fprintf_disasm
);
379 di
.flavour
= bfd_target_unknown_flavour
;
380 di
.memory_error_func
= dis_asm_memory_error
;
381 di
.print_address_func
= dis_asm_print_address
;
382 /* NOTE: cagney/2003-04-28: The original code, from the old Insight
383 disassembler had a local optomization here. By default it would
384 access the executable file, instead of the target memory (there
385 was a growing list of exceptions though). Unfortunately, the
386 heuristic was flawed. Commands like "disassemble &variable"
387 didn't work as they relied on the access going to the target.
388 Further, it has been supperseeded by trust-read-only-sections
389 (although that should be superseeded by target_trust..._p()). */
390 di
.read_memory_func
= dis_asm_read_memory
;
391 di
.arch
= gdbarch_bfd_arch_info (gdbarch
)->arch
;
392 di
.mach
= gdbarch_bfd_arch_info (gdbarch
)->mach
;
393 di
.endian
= gdbarch_byte_order (gdbarch
);
394 di
.endian_code
= gdbarch_byte_order_for_code (gdbarch
);
395 di
.application_data
= gdbarch
;
396 disassemble_init_for_target (&di
);
401 gdb_disassembly (struct gdbarch
*gdbarch
, struct ui_out
*uiout
,
402 char *file_string
, int flags
, int how_many
,
403 CORE_ADDR low
, CORE_ADDR high
)
405 struct ui_file
*stb
= mem_fileopen ();
406 struct cleanup
*cleanups
= make_cleanup_ui_file_delete (stb
);
407 struct disassemble_info di
= gdb_disassemble_info (gdbarch
, stb
);
408 /* To collect the instruction outputted from opcodes. */
409 struct symtab
*symtab
= NULL
;
410 struct linetable_entry
*le
= NULL
;
413 /* Assume symtab is valid for whole PC range. */
414 symtab
= find_pc_symtab (low
);
416 if (symtab
!= NULL
&& symtab
->linetable
!= NULL
)
418 /* Convert the linetable to a bunch of my_line_entry's. */
419 le
= symtab
->linetable
->item
;
420 nlines
= symtab
->linetable
->nitems
;
423 if (!(flags
& DISASSEMBLY_SOURCE
) || nlines
<= 0
424 || symtab
== NULL
|| symtab
->linetable
== NULL
)
425 do_assembly_only (gdbarch
, uiout
, &di
, low
, high
, how_many
, flags
, stb
);
427 else if (flags
& DISASSEMBLY_SOURCE
)
428 do_mixed_source_and_assembly (gdbarch
, uiout
, &di
, nlines
, le
, low
,
429 high
, symtab
, how_many
, flags
, stb
);
431 do_cleanups (cleanups
);
432 gdb_flush (gdb_stdout
);
435 /* Print the instruction at address MEMADDR in debugged memory,
436 on STREAM. Returns the length of the instruction, in bytes,
437 and, if requested, the number of branch delay slot instructions. */
440 gdb_print_insn (struct gdbarch
*gdbarch
, CORE_ADDR memaddr
,
441 struct ui_file
*stream
, int *branch_delay_insns
)
443 struct disassemble_info di
;
446 di
= gdb_disassemble_info (gdbarch
, stream
);
447 length
= gdbarch_print_insn (gdbarch
, memaddr
, &di
);
448 if (branch_delay_insns
)
450 if (di
.insn_info_valid
)
451 *branch_delay_insns
= di
.branch_delay_insns
;
453 *branch_delay_insns
= 0;
459 do_ui_file_delete (void *arg
)
461 ui_file_delete (arg
);
464 /* Return the length in bytes of the instruction at address MEMADDR in
468 gdb_insn_length (struct gdbarch
*gdbarch
, CORE_ADDR addr
)
470 static struct ui_file
*null_stream
= NULL
;
472 /* Dummy file descriptor for the disassembler. */
475 null_stream
= ui_file_new ();
476 make_final_cleanup (do_ui_file_delete
, null_stream
);
479 return gdb_print_insn (gdbarch
, addr
, null_stream
, NULL
);
482 /* fprintf-function for gdb_buffered_insn_length. This function is a
483 nop, we don't want to print anything, we just want to compute the
484 length of the insn. */
486 static int ATTRIBUTE_PRINTF (2, 3)
487 gdb_buffered_insn_length_fprintf (void *stream
, const char *format
, ...)
492 /* Initialize a struct disassemble_info for gdb_buffered_insn_length. */
495 gdb_buffered_insn_length_init_dis (struct gdbarch
*gdbarch
,
496 struct disassemble_info
*di
,
497 const gdb_byte
*insn
, int max_len
,
500 init_disassemble_info (di
, NULL
, gdb_buffered_insn_length_fprintf
);
502 /* init_disassemble_info installs buffer_read_memory, etc.
503 so we don't need to do that here.
504 The cast is necessary until disassemble_info is const-ified. */
505 di
->buffer
= (gdb_byte
*) insn
;
506 di
->buffer_length
= max_len
;
507 di
->buffer_vma
= addr
;
509 di
->arch
= gdbarch_bfd_arch_info (gdbarch
)->arch
;
510 di
->mach
= gdbarch_bfd_arch_info (gdbarch
)->mach
;
511 di
->endian
= gdbarch_byte_order (gdbarch
);
512 di
->endian_code
= gdbarch_byte_order_for_code (gdbarch
);
514 disassemble_init_for_target (di
);
517 /* Return the length in bytes of INSN. MAX_LEN is the size of the
518 buffer containing INSN. */
521 gdb_buffered_insn_length (struct gdbarch
*gdbarch
,
522 const gdb_byte
*insn
, int max_len
, CORE_ADDR addr
)
524 struct disassemble_info di
;
526 gdb_buffered_insn_length_init_dis (gdbarch
, &di
, insn
, max_len
, addr
);
528 return gdbarch_print_insn (gdbarch
, addr
, &di
);