aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gdb/ChangeLog9
-rw-r--r--gdb/mi/mi-main.c40
-rw-r--r--gdb/mi/mi-parse.c43
-rw-r--r--gdb/mi/mi-parse.h14
-rw-r--r--gdb/testsuite/ChangeLog4
-rw-r--r--gdb/testsuite/gdb.base/interp.exp11
6 files changed, 82 insertions, 39 deletions
diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index 3bf2bef..7663dd7 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,5 +1,14 @@
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:
* thread.c (clear_thread_inferior_resources): Call
delete_longjmp_breakpoint.
diff --git a/gdb/mi/mi-main.c b/gdb/mi/mi-main.c
index 3343c03..48e907f 100644
--- a/gdb/mi/mi-main.c
+++ b/gdb/mi/mi-main.c
@@ -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);
}
diff --git a/gdb/mi/mi-parse.c b/gdb/mi/mi-parse.c
index 4541b66..774d368 100644
--- a/gdb/mi/mi-parse.c
+++ b/gdb/mi/mi-parse.c
@@ -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;
diff --git a/gdb/mi/mi-parse.h b/gdb/mi/mi-parse.h
index 3c6cd9a..6d0f53c 100644
--- a/gdb/mi/mi-parse.h
+++ b/gdb/mi/mi-parse.h
@@ -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. */
diff --git a/gdb/testsuite/ChangeLog b/gdb/testsuite/ChangeLog
index 6ed7ab3..d60aa7c 100644
--- a/gdb/testsuite/ChangeLog
+++ b/gdb/testsuite/ChangeLog
@@ -1,5 +1,9 @@
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.
* gdb.java/jnpe.exp: New file.
* gdb.cp/nextoverthrow.exp: New file.
diff --git a/gdb/testsuite/gdb.base/interp.exp b/gdb/testsuite/gdb.base/interp.exp
index ece2552..a923f1a 100644
--- a/gdb/testsuite/gdb.base/interp.exp
+++ b/gdb/testsuite/gdb.base/interp.exp
@@ -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