15796c8dcSSimon Schubert /* MI Command Set - disassemble commands.
2*ef5ccd6cSJohn Marino Copyright (C) 2000-2013 Free Software Foundation, Inc.
35796c8dcSSimon Schubert Contributed by Cygnus Solutions (a Red Hat company).
45796c8dcSSimon Schubert
55796c8dcSSimon Schubert This file is part of GDB.
65796c8dcSSimon Schubert
75796c8dcSSimon Schubert This program is free software; you can redistribute it and/or modify
85796c8dcSSimon Schubert it under the terms of the GNU General Public License as published by
95796c8dcSSimon Schubert the Free Software Foundation; either version 3 of the License, or
105796c8dcSSimon Schubert (at your option) any later version.
115796c8dcSSimon Schubert
125796c8dcSSimon Schubert This program is distributed in the hope that it will be useful,
135796c8dcSSimon Schubert but WITHOUT ANY WARRANTY; without even the implied warranty of
145796c8dcSSimon Schubert MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
155796c8dcSSimon Schubert GNU General Public License for more details.
165796c8dcSSimon Schubert
175796c8dcSSimon Schubert You should have received a copy of the GNU General Public License
185796c8dcSSimon Schubert along with this program. If not, see <http://www.gnu.org/licenses/>. */
195796c8dcSSimon Schubert
205796c8dcSSimon Schubert #include "defs.h"
215796c8dcSSimon Schubert #include "arch-utils.h"
225796c8dcSSimon Schubert #include "target.h"
235796c8dcSSimon Schubert #include "value.h"
245796c8dcSSimon Schubert #include "mi-cmds.h"
255796c8dcSSimon Schubert #include "mi-getopt.h"
265796c8dcSSimon Schubert #include "gdb_string.h"
275796c8dcSSimon Schubert #include "ui-out.h"
285796c8dcSSimon Schubert #include "disasm.h"
295796c8dcSSimon Schubert
30*ef5ccd6cSJohn Marino /* The arguments to be passed on the command line and parsed here are
315796c8dcSSimon Schubert either:
325796c8dcSSimon Schubert
335796c8dcSSimon Schubert START-ADDRESS: address to start the disassembly at.
345796c8dcSSimon Schubert END-ADDRESS: address to end the disassembly at.
355796c8dcSSimon Schubert
365796c8dcSSimon Schubert or:
375796c8dcSSimon Schubert
385796c8dcSSimon Schubert FILENAME: The name of the file where we want disassemble from.
395796c8dcSSimon Schubert LINE: The line around which we want to disassemble. It will
405796c8dcSSimon Schubert disassemble the function that contins that line.
41c50c785cSJohn Marino HOW_MANY: Number of disassembly lines to display. With source, it
425796c8dcSSimon Schubert is the number of disassembly lines only, not counting the source
435796c8dcSSimon Schubert lines.
445796c8dcSSimon Schubert
455796c8dcSSimon Schubert always required:
465796c8dcSSimon Schubert
47c50c785cSJohn Marino MODE: 0 -- disassembly.
48c50c785cSJohn Marino 1 -- disassembly and source.
49c50c785cSJohn Marino 2 -- disassembly and opcodes.
50c50c785cSJohn Marino 3 -- disassembly, source and opcodes.
51c50c785cSJohn Marino */
52*ef5ccd6cSJohn Marino
535796c8dcSSimon Schubert void
mi_cmd_disassemble(char * command,char ** argv,int argc)545796c8dcSSimon Schubert mi_cmd_disassemble (char *command, char **argv, int argc)
555796c8dcSSimon Schubert {
565796c8dcSSimon Schubert struct gdbarch *gdbarch = get_current_arch ();
57a45ae5f8SJohn Marino struct ui_out *uiout = current_uiout;
585796c8dcSSimon Schubert CORE_ADDR start;
595796c8dcSSimon Schubert
60c50c785cSJohn Marino int mode, disasm_flags;
615796c8dcSSimon Schubert struct symtab *s;
625796c8dcSSimon Schubert
635796c8dcSSimon Schubert /* Which options have we processed ... */
645796c8dcSSimon Schubert int file_seen = 0;
655796c8dcSSimon Schubert int line_seen = 0;
665796c8dcSSimon Schubert int num_seen = 0;
675796c8dcSSimon Schubert int start_seen = 0;
685796c8dcSSimon Schubert int end_seen = 0;
695796c8dcSSimon Schubert
705796c8dcSSimon Schubert /* ... and their corresponding value. */
715796c8dcSSimon Schubert char *file_string = NULL;
725796c8dcSSimon Schubert int line_num = -1;
735796c8dcSSimon Schubert int how_many = -1;
745796c8dcSSimon Schubert CORE_ADDR low = 0;
755796c8dcSSimon Schubert CORE_ADDR high = 0;
76c50c785cSJohn Marino struct cleanup *cleanups = make_cleanup (null_cleanup, NULL);
775796c8dcSSimon Schubert
785796c8dcSSimon Schubert /* Options processing stuff. */
79*ef5ccd6cSJohn Marino int oind = 0;
80*ef5ccd6cSJohn Marino char *oarg;
815796c8dcSSimon Schubert enum opt
825796c8dcSSimon Schubert {
835796c8dcSSimon Schubert FILE_OPT, LINE_OPT, NUM_OPT, START_OPT, END_OPT
845796c8dcSSimon Schubert };
85*ef5ccd6cSJohn Marino static const struct mi_opt opts[] =
86*ef5ccd6cSJohn Marino {
875796c8dcSSimon Schubert {"f", FILE_OPT, 1},
885796c8dcSSimon Schubert {"l", LINE_OPT, 1},
895796c8dcSSimon Schubert {"n", NUM_OPT, 1},
905796c8dcSSimon Schubert {"s", START_OPT, 1},
915796c8dcSSimon Schubert {"e", END_OPT, 1},
925796c8dcSSimon Schubert { 0, 0, 0 }
935796c8dcSSimon Schubert };
945796c8dcSSimon Schubert
955796c8dcSSimon Schubert /* Get the options with their arguments. Keep track of what we
965796c8dcSSimon Schubert encountered. */
975796c8dcSSimon Schubert while (1)
985796c8dcSSimon Schubert {
99c50c785cSJohn Marino int opt = mi_getopt ("-data-disassemble", argc, argv, opts,
100*ef5ccd6cSJohn Marino &oind, &oarg);
1015796c8dcSSimon Schubert if (opt < 0)
1025796c8dcSSimon Schubert break;
1035796c8dcSSimon Schubert switch ((enum opt) opt)
1045796c8dcSSimon Schubert {
1055796c8dcSSimon Schubert case FILE_OPT:
106*ef5ccd6cSJohn Marino file_string = xstrdup (oarg);
1075796c8dcSSimon Schubert file_seen = 1;
108c50c785cSJohn Marino make_cleanup (xfree, file_string);
1095796c8dcSSimon Schubert break;
1105796c8dcSSimon Schubert case LINE_OPT:
111*ef5ccd6cSJohn Marino line_num = atoi (oarg);
1125796c8dcSSimon Schubert line_seen = 1;
1135796c8dcSSimon Schubert break;
1145796c8dcSSimon Schubert case NUM_OPT:
115*ef5ccd6cSJohn Marino how_many = atoi (oarg);
1165796c8dcSSimon Schubert num_seen = 1;
1175796c8dcSSimon Schubert break;
1185796c8dcSSimon Schubert case START_OPT:
119*ef5ccd6cSJohn Marino low = parse_and_eval_address (oarg);
1205796c8dcSSimon Schubert start_seen = 1;
1215796c8dcSSimon Schubert break;
1225796c8dcSSimon Schubert case END_OPT:
123*ef5ccd6cSJohn Marino high = parse_and_eval_address (oarg);
1245796c8dcSSimon Schubert end_seen = 1;
1255796c8dcSSimon Schubert break;
1265796c8dcSSimon Schubert }
1275796c8dcSSimon Schubert }
128*ef5ccd6cSJohn Marino argv += oind;
129*ef5ccd6cSJohn Marino argc -= oind;
1305796c8dcSSimon Schubert
1315796c8dcSSimon Schubert /* Allow only filename + linenum (with how_many which is not
132*ef5ccd6cSJohn Marino required) OR start_addr + end_addr. */
1335796c8dcSSimon Schubert
1345796c8dcSSimon Schubert if (!((line_seen && file_seen && num_seen && !start_seen && !end_seen)
1355796c8dcSSimon Schubert || (line_seen && file_seen && !num_seen && !start_seen && !end_seen)
1365796c8dcSSimon Schubert || (!line_seen && !file_seen && !num_seen && start_seen && end_seen)))
137c50c785cSJohn Marino error (_("-data-disassemble: Usage: ( [-f filename -l linenum [-n "
138c50c785cSJohn Marino "howmany]] | [-s startaddr -e endaddr]) [--] mode."));
1395796c8dcSSimon Schubert
1405796c8dcSSimon Schubert if (argc != 1)
141c50c785cSJohn Marino error (_("-data-disassemble: Usage: [-f filename -l linenum "
142c50c785cSJohn Marino "[-n howmany]] [-s startaddr -e endaddr] [--] mode."));
1435796c8dcSSimon Schubert
144c50c785cSJohn Marino mode = atoi (argv[0]);
145c50c785cSJohn Marino if (mode < 0 || mode > 3)
146c50c785cSJohn Marino error (_("-data-disassemble: Mode argument must be 0, 1, 2, or 3."));
1475796c8dcSSimon Schubert
148*ef5ccd6cSJohn Marino /* Convert the mode into a set of disassembly flags. */
149c50c785cSJohn Marino
150c50c785cSJohn Marino disasm_flags = 0;
151c50c785cSJohn Marino if (mode & 0x1)
152c50c785cSJohn Marino disasm_flags |= DISASSEMBLY_SOURCE;
153c50c785cSJohn Marino if (mode & 0x2)
154c50c785cSJohn Marino disasm_flags |= DISASSEMBLY_RAW_INSN;
1555796c8dcSSimon Schubert
1565796c8dcSSimon Schubert /* We must get the function beginning and end where line_num is
1575796c8dcSSimon Schubert contained. */
1585796c8dcSSimon Schubert
1595796c8dcSSimon Schubert if (line_seen && file_seen)
1605796c8dcSSimon Schubert {
1615796c8dcSSimon Schubert s = lookup_symtab (file_string);
1625796c8dcSSimon Schubert if (s == NULL)
163c50c785cSJohn Marino error (_("-data-disassemble: Invalid filename."));
1645796c8dcSSimon Schubert if (!find_line_pc (s, line_num, &start))
165c50c785cSJohn Marino error (_("-data-disassemble: Invalid line number"));
1665796c8dcSSimon Schubert if (find_pc_partial_function (start, NULL, &low, &high) == 0)
167c50c785cSJohn Marino error (_("-data-disassemble: "
168c50c785cSJohn Marino "No function contains specified address"));
1695796c8dcSSimon Schubert }
1705796c8dcSSimon Schubert
1715796c8dcSSimon Schubert gdb_disassembly (gdbarch, uiout,
1725796c8dcSSimon Schubert file_string,
173c50c785cSJohn Marino disasm_flags,
1745796c8dcSSimon Schubert how_many, low, high);
175c50c785cSJohn Marino
176c50c785cSJohn Marino do_cleanups (cleanups);
1775796c8dcSSimon Schubert }
178