gdb
* mi/mi-parse.h (mi_parse): Update. * mi/mi-parse.c (mi_parse_cleanup): New function. (mi_parse): Add 'token' argument. Throw exception on error. * mi/mi-main.c (mi_print_exception): New function. (mi_execute_command): Use mi_print_exception. Catch exceptions from mi_parse. gdb/testsuite * gdb.base/interp.exp: Add regression test.
This commit is contained in:
parent
90ecf1736c
commit
305aeedc41
@ -1,3 +1,12 @@
|
||||
2010-12-09 Tom Tromey <tromey@redhat.com>
|
||||
|
||||
* mi/mi-parse.h (mi_parse): Update.
|
||||
* mi/mi-parse.c (mi_parse_cleanup): New function.
|
||||
(mi_parse): Add 'token' argument. Throw exception on error.
|
||||
* mi/mi-main.c (mi_print_exception): New function.
|
||||
(mi_execute_command): Use mi_print_exception. Catch exceptions
|
||||
from mi_parse.
|
||||
|
||||
2010-12-09 Tom Tromey <tromey@redhat.com>
|
||||
|
||||
PR c++/9593:
|
||||
|
@ -1865,11 +1865,26 @@ captured_mi_execute_command (struct ui_out *uiout, void *data)
|
||||
return;
|
||||
}
|
||||
|
||||
/* Print a gdb exception to the MI output stream. */
|
||||
|
||||
static void
|
||||
mi_print_exception (const char *token, struct gdb_exception exception)
|
||||
{
|
||||
fputs_unfiltered (token, raw_stdout);
|
||||
fputs_unfiltered ("^error,msg=\"", raw_stdout);
|
||||
if (exception.message == NULL)
|
||||
fputs_unfiltered ("unknown error", raw_stdout);
|
||||
else
|
||||
fputstr_unfiltered (exception.message, '"', raw_stdout);
|
||||
fputs_unfiltered ("\"\n", raw_stdout);
|
||||
}
|
||||
|
||||
void
|
||||
mi_execute_command (char *cmd, int from_tty)
|
||||
{
|
||||
struct mi_parse *command;
|
||||
char *token;
|
||||
struct mi_parse *command = NULL;
|
||||
volatile struct gdb_exception exception;
|
||||
|
||||
/* This is to handle EOF (^D). We just quit gdb. */
|
||||
/* FIXME: we should call some API function here. */
|
||||
@ -1878,13 +1893,22 @@ mi_execute_command (char *cmd, int from_tty)
|
||||
|
||||
target_log_command (cmd);
|
||||
|
||||
command = mi_parse (cmd);
|
||||
|
||||
if (command != NULL)
|
||||
TRY_CATCH (exception, RETURN_MASK_ALL)
|
||||
{
|
||||
command = mi_parse (cmd, &token);
|
||||
}
|
||||
if (exception.reason < 0)
|
||||
{
|
||||
mi_print_exception (token, exception);
|
||||
xfree (token);
|
||||
}
|
||||
else
|
||||
{
|
||||
struct gdb_exception result;
|
||||
ptid_t previous_ptid = inferior_ptid;
|
||||
|
||||
command->token = token;
|
||||
|
||||
if (do_timings)
|
||||
{
|
||||
command->cmd_start = (struct mi_timestamp *)
|
||||
@ -1898,13 +1922,7 @@ mi_execute_command (char *cmd, int from_tty)
|
||||
{
|
||||
/* The command execution failed and error() was called
|
||||
somewhere. */
|
||||
fputs_unfiltered (command->token, raw_stdout);
|
||||
fputs_unfiltered ("^error,msg=\"", raw_stdout);
|
||||
if (result.message == NULL)
|
||||
fputs_unfiltered ("unknown error", raw_stdout);
|
||||
else
|
||||
fputstr_unfiltered (result.message, '"', raw_stdout);
|
||||
fputs_unfiltered ("\"\n", raw_stdout);
|
||||
mi_print_exception (command->token, result);
|
||||
mi_out_rewind (uiout);
|
||||
}
|
||||
|
||||
|
@ -223,12 +223,20 @@ mi_parse_free (struct mi_parse *parse)
|
||||
xfree (parse);
|
||||
}
|
||||
|
||||
/* A cleanup that calls mi_parse_free. */
|
||||
|
||||
static void
|
||||
mi_parse_cleanup (void *arg)
|
||||
{
|
||||
mi_parse_free (arg);
|
||||
}
|
||||
|
||||
struct mi_parse *
|
||||
mi_parse (char *cmd)
|
||||
mi_parse (char *cmd, char **token)
|
||||
{
|
||||
char *chp;
|
||||
struct mi_parse *parse = XMALLOC (struct mi_parse);
|
||||
struct cleanup *cleanup;
|
||||
|
||||
memset (parse, 0, sizeof (*parse));
|
||||
parse->all = 0;
|
||||
@ -236,6 +244,8 @@ mi_parse (char *cmd)
|
||||
parse->thread = -1;
|
||||
parse->frame = -1;
|
||||
|
||||
cleanup = make_cleanup (mi_parse_cleanup, parse);
|
||||
|
||||
/* Before starting, skip leading white space. */
|
||||
while (isspace (*cmd))
|
||||
cmd++;
|
||||
@ -243,9 +253,9 @@ mi_parse (char *cmd)
|
||||
/* Find/skip any token and then extract it. */
|
||||
for (chp = cmd; *chp >= '0' && *chp <= '9'; chp++)
|
||||
;
|
||||
parse->token = xmalloc ((chp - cmd + 1) * sizeof (char *));
|
||||
memcpy (parse->token, cmd, (chp - cmd));
|
||||
parse->token[chp - cmd] = '\0';
|
||||
*token = xmalloc ((chp - cmd + 1) * sizeof (char *));
|
||||
memcpy (*token, cmd, (chp - cmd));
|
||||
(*token)[chp - cmd] = '\0';
|
||||
|
||||
/* This wasn't a real MI command. Return it as a CLI_COMMAND. */
|
||||
if (*chp != '-')
|
||||
@ -254,6 +264,9 @@ mi_parse (char *cmd)
|
||||
chp++;
|
||||
parse->command = xstrdup (chp);
|
||||
parse->op = CLI_COMMAND;
|
||||
|
||||
discard_cleanups (cleanup);
|
||||
|
||||
return parse;
|
||||
}
|
||||
|
||||
@ -271,15 +284,7 @@ mi_parse (char *cmd)
|
||||
/* Find the command in the MI table. */
|
||||
parse->cmd = mi_lookup (parse->command);
|
||||
if (parse->cmd == NULL)
|
||||
{
|
||||
/* FIXME: This should be a function call. */
|
||||
fprintf_unfiltered
|
||||
(raw_stdout,
|
||||
"%s^error,msg=\"Undefined MI command: %s\"\n",
|
||||
parse->token, parse->command);
|
||||
mi_parse_free (parse);
|
||||
return NULL;
|
||||
}
|
||||
error (_("Undefined MI command: %s"), parse->command);
|
||||
|
||||
/* Skip white space following the command. */
|
||||
while (isspace (*chp))
|
||||
@ -349,15 +354,7 @@ mi_parse (char *cmd)
|
||||
{
|
||||
mi_parse_argv (chp, parse);
|
||||
if (parse->argv == NULL)
|
||||
{
|
||||
/* FIXME: This should be a function call. */
|
||||
fprintf_unfiltered
|
||||
(raw_stdout,
|
||||
"%s^error,msg=\"Problem parsing arguments: %s %s\"\n",
|
||||
parse->token, parse->command, chp);
|
||||
mi_parse_free (parse);
|
||||
return NULL;
|
||||
}
|
||||
error (_("Problem parsing arguments: %s %s"), parse->command, chp);
|
||||
}
|
||||
|
||||
/* FIXME: DELETE THIS */
|
||||
@ -366,6 +363,8 @@ mi_parse (char *cmd)
|
||||
if (parse->cmd->cli.cmd != NULL)
|
||||
parse->args = xstrdup (chp);
|
||||
|
||||
discard_cleanups (cleanup);
|
||||
|
||||
/* Fully parsed. */
|
||||
parse->op = MI_COMMAND;
|
||||
return parse;
|
||||
|
@ -52,13 +52,15 @@ struct mi_parse
|
||||
int frame;
|
||||
};
|
||||
|
||||
/* Attempts to parse CMD returning a ``struct mi_command''. If CMD is
|
||||
invalid, an error mesage is reported (MI format) and NULL is
|
||||
returned. For a CLI_COMMAND, COMMAND, TOKEN and OP are initialized.
|
||||
For an MI_COMMAND COMMAND, TOKEN, ARGS and OP are
|
||||
initialized. Un-initialized fields are zero. */
|
||||
/* Attempts to parse CMD returning a ``struct mi_parse''. If CMD is
|
||||
invalid, an exception is thrown. For an MI_COMMAND COMMAND, ARGS
|
||||
and OP are initialized. Un-initialized fields are zero. *TOKEN is
|
||||
set to the token, even if an exception is thrown. It is allocated
|
||||
with xmalloc; it must either be freed with xfree, or assigned to
|
||||
the TOKEN field of the resultant mi_parse object, to be freed by
|
||||
mi_parse_free. */
|
||||
|
||||
extern struct mi_parse *mi_parse (char *cmd);
|
||||
extern struct mi_parse *mi_parse (char *cmd, char **token);
|
||||
|
||||
/* Free a command returned by mi_parse_command. */
|
||||
|
||||
|
@ -1,3 +1,7 @@
|
||||
2010-12-09 Tom Tromey <tromey@redhat.com>
|
||||
|
||||
* gdb.base/interp.exp: Add regression test.
|
||||
|
||||
2010-12-09 Tom Tromey <tromey@redhat.com>
|
||||
|
||||
* gdb.java/jnpe.java: New file.
|
||||
|
@ -33,4 +33,15 @@ gdb_test_multiple $cmd $cmd {
|
||||
}
|
||||
gdb_test "interpreter-exec console \"show version\"" "GNU gdb .*"
|
||||
|
||||
# Regression test for crash when an exception occurs in mi_parse.
|
||||
gdb_test_multiple "interpreter-exec mi \"-break-insert --thread a\"" \
|
||||
"regression test for mi_parse crash" {
|
||||
-re ".error,msg=.Invalid value for the '--thread' option.\r\n$gdb_prompt " {
|
||||
pass "$cmd"
|
||||
gdb_expect 1 {
|
||||
-re "\r\n$gdb_prompt $" { }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
gdb_exit
|
||||
|
Loading…
Reference in New Issue
Block a user