#include "defs.h"
#include "target.h"
#include "value.h"
#include "mi-cmds.h"
#include "mi-getopt.h"
#include "gdb_string.h"
#include "ui-out.h"
#include "disasm.h"
static void mi_cmd_disassemble_usage (const char *message)
{
const char *const usage =
"[-P peeklimit]"
" ("
" [-f filename -l linenum [-n howmany] [-p startprev]]"
" | [-s startaddr [-n howmany] [-p startprev]]"
" | [-s startaddr -e endaddr]"
" )"
" [--] mixed_mode.";
error ("mi_cmd_disassemble: %s Usage: %s", message, usage);
}
enum mi_cmd_result
mi_cmd_disassemble (char *command, char **argv, int argc)
{
int mixed_source_and_assembly;
struct symtab *s;
int file_seen = 0;
int line_seen = 0;
int start_seen = 0;
int end_seen = 0;
int num_seen = 0;
int prev_seen = 0;
int peeklimit_seen = 0;
char *file_string = NULL;
int line_num = -1;
int how_many = -1;
CORE_ADDR low = 0;
CORE_ADDR high = 0;
CORE_ADDR start = 0;
int prev = 0;
int peeklimit = -1;
int optind = 0;
char *optarg;
enum opt
{
FILE_OPT, LINE_OPT, NUM_OPT, START_OPT, END_OPT, PREV_OPT, PEEKLIMIT_OPT
};
static struct mi_opt opts[] = {
{"f", FILE_OPT, 1},
{"l", LINE_OPT, 1},
{"n", NUM_OPT, 1},
{"s", START_OPT, 1},
{"e", END_OPT, 1},
{"p", PREV_OPT, 1},
{"P", PEEKLIMIT_OPT, 1},
{0}
};
while (1)
{
int opt = mi_getopt ("mi_cmd_disassemble", argc, argv, opts,
&optind, &optarg);
if (opt < 0)
break;
switch ((enum opt) opt)
{
case FILE_OPT:
file_string = xstrdup (optarg);
file_seen = 1;
break;
case LINE_OPT:
line_num = atoi (optarg);
line_seen = 1;
break;
case NUM_OPT:
how_many = atoi (optarg);
num_seen = 1;
break;
case START_OPT:
start = parse_and_eval_address (optarg);
start_seen = 1;
break;
case END_OPT:
high = parse_and_eval_address (optarg);
end_seen = 1;
break;
case PREV_OPT:
prev = atoi (optarg);
prev_seen = 1;
break;
case PEEKLIMIT_OPT:
peeklimit = atoi (optarg);
peeklimit_seen = 1;
break;
}
}
argv += optind;
argc -= optind;
if (argc < 1)
mi_cmd_disassemble_usage ("Must specify mixed mode argument.");
if (argc > 1)
mi_cmd_disassemble_usage ("Extra arguments present.");
if ((argv[0][0] == '\0') || (argv[0][1] != '\0'))
mi_cmd_disassemble_usage ("Mixed mode argument must be 0 or 1.");
if ((argv[0][0] != '0') && (argv[0][0] != '1'))
mi_cmd_disassemble_usage ("Mixed mode argument must be 0 or 1.");
mixed_source_and_assembly = (argv[0][0] == '1');
if (start_seen && line_seen)
mi_cmd_disassemble_usage ("May not specify both a line number and a start address.");
if ((line_seen && !file_seen) || (file_seen && !line_seen))
mi_cmd_disassemble_usage ("File and line number must be specified together.");
if (line_seen && file_seen)
{
s = lookup_symtab (file_string);
if (s == NULL)
error ("mi_cmd_disassemble: Invalid filename.");
if (! find_line_pc (s, line_num, &start))
error ("mi_cmd_disassemble: Invalid line number.");
}
else if (! start_seen)
mi_cmd_disassemble_usage ("No starting point specified.");
if (end_seen)
{
if (num_seen || prev_seen)
mi_cmd_disassemble_usage ("May not specify both an ending address and -n or -p.");
gdb_disassembly (uiout, start, high, mixed_source_and_assembly, how_many);
return MI_CMD_DONE;
}
if (find_pc_partial_function (start, NULL, &low, &high) == 0)
error ("mi_cmd_disassemble: No function contains the specified address.");
if (! num_seen)
{
gdb_disassembly (uiout, low, high, mixed_source_and_assembly, how_many);
return MI_CMD_DONE;
}
if (prev_seen)
{
CORE_ADDR tmp;
int ret;
ret = find_pc_offset (start, &tmp, -prev, 1, peeklimit);
if (tmp != INVALID_ADDRESS)
start = tmp;
}
gdb_disassembly (uiout, start, high, mixed_source_and_assembly, how_many);
return MI_CMD_DONE;
}