1 /* MI Command Set - disassemble commands.
2 Copyright 2000, 2001, 2002 Free Software Foundation, Inc.
3 Contributed by Cygnus Solutions (a Red Hat company).
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 2 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, write to the Free Software
19 Foundation, Inc., 59 Temple Place - Suite 330,
20 Boston, MA 02111-1307, USA. */
26 #include "mi-getopt.h"
28 #include "gdb_string.h"
30 /* Disassemble functions. FIXME: these do not really belong here. We
31 should get rid of all the duplicate code in gdb that does the same
32 thing: disassemble_command() and the gdbtk variation. */
34 /* This Structure is used in mi_cmd_disassemble.
35 We need a different sort of line table from the normal one cuz we can't
36 depend upon implicit line-end pc's for lines to do the
37 reordering in this function. */
46 /* This variable determines where memory used for disassembly is read from. */
47 int gdb_disassemble_from_exec
= -1;
49 /* This is the memory_read_func for gdb_disassemble when we are
50 disassembling from the exec file. */
52 gdb_dis_asm_read_memory (bfd_vma memaddr
, bfd_byte
* myaddr
,
53 unsigned int len
, disassemble_info
* info
)
55 extern struct target_ops exec_ops
;
59 res
= xfer_memory (memaddr
, myaddr
, len
, 0, 0, &exec_ops
);
70 compare_lines (const PTR mle1p
, const PTR mle2p
)
72 struct dis_line_entry
*mle1
, *mle2
;
75 mle1
= (struct dis_line_entry
*) mle1p
;
76 mle2
= (struct dis_line_entry
*) mle2p
;
78 val
= mle1
->line
- mle2
->line
;
83 return mle1
->start_pc
- mle2
->start_pc
;
87 dump_insns (disassemble_info
* di
, CORE_ADDR low
, CORE_ADDR high
,
88 int how_many
, struct ui_stream
*stb
)
90 int num_displayed
= 0;
93 /* parts of the symbolic representation of the address */
95 char *filename
= NULL
;
100 for (pc
= low
; pc
< high
;)
105 if (num_displayed
>= how_many
)
110 ui_out_tuple_begin (uiout
, NULL
);
111 ui_out_field_core_addr (uiout
, "address", pc
);
113 if (!build_address_symbolic (pc
, 0, &name
, &offset
, &filename
,
116 /* We don't care now about line, filename and
117 unmapped. But we might in the future. */
118 ui_out_text (uiout
, " <");
119 ui_out_field_string (uiout
, "func-name", name
);
120 ui_out_text (uiout
, "+");
121 ui_out_field_int (uiout
, "offset", offset
);
122 ui_out_text (uiout
, ">:\t");
124 if (filename
!= NULL
)
129 ui_file_rewind (stb
->stream
);
130 pc
+= TARGET_PRINT_INSN (pc
, di
);
131 ui_out_field_stream (uiout
, "inst", stb
);
132 ui_file_rewind (stb
->stream
);
133 ui_out_tuple_end (uiout
);
134 ui_out_text (uiout
, "\n");
136 return num_displayed
;
139 /* The idea here is to present a source-O-centric view of a
140 function to the user. This means that things are presented
141 in source order, with (possibly) out of order assembly
142 immediately following. */
144 do_mixed_source_and_assembly (struct disassemble_info
*di
, int nlines
,
145 struct linetable_entry
*le
,
146 CORE_ADDR low
, CORE_ADDR high
,
147 struct symtab
*symtab
,
148 int how_many
, struct ui_stream
*stb
)
151 struct dis_line_entry
*mle
;
152 struct symtab_and_line sal
;
154 int out_of_order
= 0;
157 int num_displayed
= 0;
159 mle
= (struct dis_line_entry
*) alloca (nlines
160 * sizeof (struct dis_line_entry
));
162 /* Copy linetable entries for this function into our data
163 structure, creating end_pc's and setting out_of_order as
166 /* First, skip all the preceding functions. */
168 for (i
= 0; i
< nlines
- 1 && le
[i
].pc
< low
; i
++);
170 /* Now, copy all entries before the end of this function. */
172 for (; i
< nlines
- 1 && le
[i
].pc
< high
; i
++)
174 if (le
[i
].line
== le
[i
+ 1].line
&& le
[i
].pc
== le
[i
+ 1].pc
)
175 continue; /* Ignore duplicates */
177 /* Skip any end-of-function markers. */
181 mle
[newlines
].line
= le
[i
].line
;
182 if (le
[i
].line
> le
[i
+ 1].line
)
184 mle
[newlines
].start_pc
= le
[i
].pc
;
185 mle
[newlines
].end_pc
= le
[i
+ 1].pc
;
189 /* If we're on the last line, and it's part of the function,
190 then we need to get the end pc in a special way. */
192 if (i
== nlines
- 1 && le
[i
].pc
< high
)
194 mle
[newlines
].line
= le
[i
].line
;
195 mle
[newlines
].start_pc
= le
[i
].pc
;
196 sal
= find_pc_line (le
[i
].pc
, 0);
197 mle
[newlines
].end_pc
= sal
.end
;
201 /* Now, sort mle by line #s (and, then by addresses within
205 qsort (mle
, newlines
, sizeof (struct dis_line_entry
), compare_lines
);
207 /* Now, for each line entry, emit the specified lines (unless
208 they have been emitted before), followed by the assembly code
211 ui_out_list_begin (uiout
, "asm_insns");
213 for (i
= 0; i
< newlines
; i
++)
216 /* Print out everything from next_line to the current line. */
217 if (mle
[i
].line
>= next_line
)
221 /* Just one line to print. */
222 if (next_line
== mle
[i
].line
)
224 ui_out_tuple_begin (uiout
, "src_and_asm_line");
225 print_source_lines (symtab
, next_line
, mle
[i
].line
+ 1, 0);
229 /* Several source lines w/o asm instructions associated. */
230 for (; next_line
< mle
[i
].line
; next_line
++)
232 ui_out_tuple_begin (uiout
, "src_and_asm_line");
233 print_source_lines (symtab
, next_line
, next_line
+ 1,
235 ui_out_list_begin (uiout
, "line_asm_insn");
236 ui_out_list_end (uiout
);
237 ui_out_tuple_end (uiout
);
239 /* Print the last line and leave list open for
240 asm instructions to be added. */
241 ui_out_tuple_begin (uiout
, "src_and_asm_line");
242 print_source_lines (symtab
, next_line
, mle
[i
].line
+ 1, 0);
247 ui_out_tuple_begin (uiout
, "src_and_asm_line");
248 print_source_lines (symtab
, mle
[i
].line
, mle
[i
].line
+ 1, 0);
251 next_line
= mle
[i
].line
+ 1;
252 ui_out_list_begin (uiout
, "line_asm_insn");
253 /* Don't close the list if the lines are not in order. */
254 if (i
< (newlines
- 1) && mle
[i
+ 1].line
<= mle
[i
].line
)
258 num_displayed
+= dump_insns (di
, mle
[i
].start_pc
, mle
[i
].end_pc
,
262 ui_out_list_end (uiout
);
263 ui_out_tuple_end (uiout
);
264 ui_out_text (uiout
, "\n");
268 if (num_displayed
>= how_many
)
271 ui_out_list_end (uiout
);
276 do_assembly_only (disassemble_info
* di
, CORE_ADDR low
,
277 CORE_ADDR high
, int how_many
, struct ui_stream
*stb
)
279 int num_displayed
= 0;
281 ui_out_list_begin (uiout
, "asm_insns");
283 num_displayed
= dump_insns (di
, low
, high
, how_many
, stb
);
285 ui_out_list_end (uiout
);
289 do_disassembly (char *file_string
,
291 int mixed_source_and_assembly
,
292 int how_many
, CORE_ADDR low
, CORE_ADDR high
)
294 static disassemble_info di
;
295 static int di_initialized
;
296 /* To collect the instruction outputted from opcodes. */
297 static struct ui_stream
*stb
= NULL
;
298 struct symtab
*symtab
= NULL
;
299 struct linetable_entry
*le
= NULL
;
304 /* We don't add a cleanup for this, because the allocation of
305 the stream is done once only for each gdb run, and we need to
306 keep it around until the end. Hopefully there won't be any
307 errors in the init code below, that make this function bail
309 stb
= ui_out_stream_new (uiout
);
310 INIT_DISASSEMBLE_INFO_NO_ARCH (di
, stb
->stream
,
311 (fprintf_ftype
) fprintf_unfiltered
);
312 di
.flavour
= bfd_target_unknown_flavour
;
313 di
.memory_error_func
= dis_asm_memory_error
;
314 di
.print_address_func
= dis_asm_print_address
;
318 di
.mach
= TARGET_PRINT_INSN_INFO
->mach
;
319 if (TARGET_BYTE_ORDER
== BFD_ENDIAN_BIG
)
320 di
.endian
= BFD_ENDIAN_BIG
;
322 di
.endian
= BFD_ENDIAN_LITTLE
;
324 /* If gdb_disassemble_from_exec == -1, then we use the following heuristic to
325 determine whether or not to do disassembly from target memory or from the
328 If we're debugging a local process, read target memory, instead of the
329 exec file. This makes disassembly of functions in shared libs work
330 correctly. Also, read target memory if we are debugging native threads.
332 Else, we're debugging a remote process, and should disassemble from the
333 exec file for speed. However, this is no good if the target modifies its
334 code (for relocation, or whatever). */
336 if (gdb_disassemble_from_exec
== -1)
338 if (strcmp (target_shortname
, "child") == 0
339 || strcmp (target_shortname
, "procfs") == 0
340 || strcmp (target_shortname
, "vxprocess") == 0
341 || strstr (target_shortname
, "-threads") != NULL
)
342 gdb_disassemble_from_exec
= 0; /* It's a child process, read inferior mem */
344 gdb_disassemble_from_exec
= 1; /* It's remote, read the exec file */
347 if (gdb_disassemble_from_exec
)
348 di
.read_memory_func
= gdb_dis_asm_read_memory
;
350 di
.read_memory_func
= dis_asm_read_memory
;
352 /* Assume symtab is valid for whole PC range */
353 symtab
= find_pc_symtab (low
);
355 if (symtab
!= NULL
&& symtab
->linetable
!= NULL
)
357 /* Convert the linetable to a bunch of my_line_entry's. */
358 le
= symtab
->linetable
->item
;
359 nlines
= symtab
->linetable
->nitems
;
362 if (!mixed_source_and_assembly
|| nlines
<= 0
363 || symtab
== NULL
|| symtab
->linetable
== NULL
)
364 do_assembly_only (&di
, low
, high
, how_many
, stb
);
366 else if (mixed_source_and_assembly
)
367 do_mixed_source_and_assembly (&di
, nlines
, le
, low
,
368 high
, symtab
, how_many
, stb
);
370 gdb_flush (gdb_stdout
);
375 /* The arguments to be passed on the command line and parsed here are:
379 START-ADDRESS: address to start the disassembly at.
380 END-ADDRESS: address to end the disassembly at.
384 FILENAME: The name of the file where we want disassemble from.
385 LINE: The line around which we want to disassemble. It will
386 disassemble the function that contins that line.
387 HOW_MANY: Number of disassembly lines to display. In mixed mode, it
388 is the number of disassembly lines only, not counting the source
393 MODE: 0 or 1 for disassembly only, or mixed source and disassembly,
396 mi_cmd_disassemble (char *command
, char **argv
, int argc
)
398 enum mi_cmd_result retval
;
401 int mixed_source_and_assembly
;
404 /* Which options have we processed ... */
411 /* ... and their corresponding value. */
412 char *file_string
= NULL
;
418 /* Options processing stuff. */
423 FILE_OPT
, LINE_OPT
, NUM_OPT
, START_OPT
, END_OPT
425 static struct mi_opt opts
[] = {
434 /* Get the options with their arguments. Keep track of what we
438 int opt
= mi_getopt ("mi_cmd_disassemble", argc
, argv
, opts
,
442 switch ((enum opt
) opt
)
445 file_string
= xstrdup (optarg
);
449 line_num
= atoi (optarg
);
453 how_many
= atoi (optarg
);
457 low
= parse_and_eval_address (optarg
);
461 high
= parse_and_eval_address (optarg
);
469 /* Allow only filename + linenum (with how_many which is not
470 required) OR start_addr + and_addr */
472 if (!((line_seen
&& file_seen
&& num_seen
&& !start_seen
&& !end_seen
)
473 || (line_seen
&& file_seen
&& !num_seen
&& !start_seen
&& !end_seen
)
474 || (!line_seen
&& !file_seen
&& !num_seen
&& start_seen
&& end_seen
)))
476 ("mi_cmd_disassemble: Usage: ( [-f filename -l linenum [-n howmany]] | [-s startaddr -e endaddr]) [--] mixed_mode.");
480 ("mi_cmd_disassemble: Usage: [-f filename -l linenum [-n howmany]] [-s startaddr -e endaddr] [--] mixed_mode.");
482 mixed_source_and_assembly
= atoi (argv
[0]);
483 if ((mixed_source_and_assembly
!= 0) && (mixed_source_and_assembly
!= 1))
484 error ("mi_cmd_disassemble: Mixed_mode argument must be 0 or 1.");
487 /* We must get the function beginning and end where line_num is
490 if (line_seen
&& file_seen
)
492 s
= lookup_symtab (file_string
);
494 error ("mi_cmd_disassemble: Invalid filename.");
495 if (!find_line_pc (s
, line_num
, &start
))
496 error ("mi_cmd_disassemble: Invalid line number");
497 if (find_pc_partial_function (start
, NULL
, &low
, &high
) == 0)
498 error ("mi_cmd_disassemble: No function contains specified address");
501 retval
= do_disassembly (file_string
,
503 mixed_source_and_assembly
, how_many
, low
, high
);