198944Sobrien/* MI Command Set - disassemble commands.
298944Sobrien   Copyright 2000, 2001, 2002 Free Software Foundation, Inc.
398944Sobrien   Contributed by Cygnus Solutions (a Red Hat company).
498944Sobrien
598944Sobrien   This file is part of GDB.
698944Sobrien
798944Sobrien   This program is free software; you can redistribute it and/or modify
898944Sobrien   it under the terms of the GNU General Public License as published by
998944Sobrien   the Free Software Foundation; either version 2 of the License, or
1098944Sobrien   (at your option) any later version.
1198944Sobrien
1298944Sobrien   This program is distributed in the hope that it will be useful,
1398944Sobrien   but WITHOUT ANY WARRANTY; without even the implied warranty of
1498944Sobrien   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
1598944Sobrien   GNU General Public License for more details.
1698944Sobrien
1798944Sobrien   You should have received a copy of the GNU General Public License
1898944Sobrien   along with this program; if not, write to the Free Software
1998944Sobrien   Foundation, Inc., 59 Temple Place - Suite 330,
2098944Sobrien   Boston, MA 02111-1307, USA.  */
2198944Sobrien
2298944Sobrien#include "defs.h"
2398944Sobrien#include "target.h"
2498944Sobrien#include "value.h"
2598944Sobrien#include "mi-cmds.h"
2698944Sobrien#include "mi-getopt.h"
27130803Smarcel#include "gdb_string.h"
2898944Sobrien#include "ui-out.h"
29130803Smarcel#include "disasm.h"
3098944Sobrien
3198944Sobrien/* The arguments to be passed on the command line and parsed here are:
3298944Sobrien
3398944Sobrien   either:
3498944Sobrien
3598944Sobrien   START-ADDRESS: address to start the disassembly at.
3698944Sobrien   END-ADDRESS: address to end the disassembly at.
3798944Sobrien
3898944Sobrien   or:
3998944Sobrien
4098944Sobrien   FILENAME: The name of the file where we want disassemble from.
4198944Sobrien   LINE: The line around which we want to disassemble. It will
4298944Sobrien   disassemble the function that contins that line.
4398944Sobrien   HOW_MANY: Number of disassembly lines to display. In mixed mode, it
4498944Sobrien   is the number of disassembly lines only, not counting the source
4598944Sobrien   lines.
4698944Sobrien
4798944Sobrien   always required:
4898944Sobrien
4998944Sobrien   MODE: 0 or 1 for disassembly only, or mixed source and disassembly,
5098944Sobrien   respectively. */
5198944Sobrienenum mi_cmd_result
5298944Sobrienmi_cmd_disassemble (char *command, char **argv, int argc)
5398944Sobrien{
54130803Smarcel  enum mi_cmd_result retval;
5598944Sobrien  CORE_ADDR start;
5698944Sobrien
5798944Sobrien  int mixed_source_and_assembly;
5898944Sobrien  struct symtab *s;
5998944Sobrien
6098944Sobrien  /* Which options have we processed ... */
6198944Sobrien  int file_seen = 0;
6298944Sobrien  int line_seen = 0;
6398944Sobrien  int num_seen = 0;
6498944Sobrien  int start_seen = 0;
6598944Sobrien  int end_seen = 0;
6698944Sobrien
6798944Sobrien  /* ... and their corresponding value. */
6898944Sobrien  char *file_string = NULL;
6998944Sobrien  int line_num = -1;
7098944Sobrien  int how_many = -1;
7198944Sobrien  CORE_ADDR low = 0;
7298944Sobrien  CORE_ADDR high = 0;
7398944Sobrien
7498944Sobrien  /* Options processing stuff. */
7598944Sobrien  int optind = 0;
7698944Sobrien  char *optarg;
7798944Sobrien  enum opt
7898944Sobrien  {
79130803Smarcel    FILE_OPT, LINE_OPT, NUM_OPT, START_OPT, END_OPT
80130803Smarcel  };
81130803Smarcel  static struct mi_opt opts[] = {
8298944Sobrien    {"f", FILE_OPT, 1},
8398944Sobrien    {"l", LINE_OPT, 1},
8498944Sobrien    {"n", NUM_OPT, 1},
8598944Sobrien    {"s", START_OPT, 1},
8698944Sobrien    {"e", END_OPT, 1},
8798944Sobrien    0
8898944Sobrien  };
8998944Sobrien
9098944Sobrien  /* Get the options with their arguments. Keep track of what we
9198944Sobrien     encountered. */
9298944Sobrien  while (1)
9398944Sobrien    {
9498944Sobrien      int opt = mi_getopt ("mi_cmd_disassemble", argc, argv, opts,
9598944Sobrien			   &optind, &optarg);
9698944Sobrien      if (opt < 0)
9798944Sobrien	break;
9898944Sobrien      switch ((enum opt) opt)
9998944Sobrien	{
10098944Sobrien	case FILE_OPT:
10198944Sobrien	  file_string = xstrdup (optarg);
10298944Sobrien	  file_seen = 1;
10398944Sobrien	  break;
10498944Sobrien	case LINE_OPT:
10598944Sobrien	  line_num = atoi (optarg);
10698944Sobrien	  line_seen = 1;
10798944Sobrien	  break;
10898944Sobrien	case NUM_OPT:
10998944Sobrien	  how_many = atoi (optarg);
11098944Sobrien	  num_seen = 1;
11198944Sobrien	  break;
11298944Sobrien	case START_OPT:
11398944Sobrien	  low = parse_and_eval_address (optarg);
11498944Sobrien	  start_seen = 1;
11598944Sobrien	  break;
11698944Sobrien	case END_OPT:
11798944Sobrien	  high = parse_and_eval_address (optarg);
11898944Sobrien	  end_seen = 1;
11998944Sobrien	  break;
12098944Sobrien	}
12198944Sobrien    }
12298944Sobrien  argv += optind;
12398944Sobrien  argc -= optind;
12498944Sobrien
12598944Sobrien  /* Allow only filename + linenum (with how_many which is not
12698944Sobrien     required) OR start_addr + and_addr */
12798944Sobrien
12898944Sobrien  if (!((line_seen && file_seen && num_seen && !start_seen && !end_seen)
12998944Sobrien	|| (line_seen && file_seen && !num_seen && !start_seen && !end_seen)
130130803Smarcel	|| (!line_seen && !file_seen && !num_seen && start_seen && end_seen)))
131130803Smarcel    error
132130803Smarcel      ("mi_cmd_disassemble: Usage: ( [-f filename -l linenum [-n howmany]] | [-s startaddr -e endaddr]) [--] mixed_mode.");
13398944Sobrien
13498944Sobrien  if (argc != 1)
135130803Smarcel    error
136130803Smarcel      ("mi_cmd_disassemble: Usage: [-f filename -l linenum [-n howmany]] [-s startaddr -e endaddr] [--] mixed_mode.");
13798944Sobrien
13898944Sobrien  mixed_source_and_assembly = atoi (argv[0]);
13998944Sobrien  if ((mixed_source_and_assembly != 0) && (mixed_source_and_assembly != 1))
14098944Sobrien    error ("mi_cmd_disassemble: Mixed_mode argument must be 0 or 1.");
14198944Sobrien
142130803Smarcel
14398944Sobrien  /* We must get the function beginning and end where line_num is
14498944Sobrien     contained. */
14598944Sobrien
14698944Sobrien  if (line_seen && file_seen)
14798944Sobrien    {
14898944Sobrien      s = lookup_symtab (file_string);
14998944Sobrien      if (s == NULL)
15098944Sobrien	error ("mi_cmd_disassemble: Invalid filename.");
15198944Sobrien      if (!find_line_pc (s, line_num, &start))
15298944Sobrien	error ("mi_cmd_disassemble: Invalid line number");
15398944Sobrien      if (find_pc_partial_function (start, NULL, &low, &high) == 0)
15498944Sobrien	error ("mi_cmd_disassemble: No function contains specified address");
15598944Sobrien    }
15698944Sobrien
157130803Smarcel  gdb_disassembly (uiout,
158130803Smarcel  		   file_string,
159130803Smarcel		   line_num,
160130803Smarcel		   mixed_source_and_assembly, how_many, low, high);
16198944Sobrien
16298944Sobrien  return MI_CMD_DONE;
16398944Sobrien}
164