From f562a28284d5c45f9b67359dd50cb823be484302 Mon Sep 17 00:00:00 2001 From: Joel Brobecker Date: Mon, 11 Nov 2013 09:21:44 +0400 Subject: [PATCH] GDB/MI: Add new "--language LANG" command option. Frontend sometimes need to evaluate expressions that are language-specific. For instance, Eclipse uses the following expression to determine the size of an address on the target: -data-evaluate-expression "sizeof (void*)" Unfortunately, if the main of the program being debugged is not C, this may not work. For instance, if the main is in Ada, you get... -data-evaluate-expression "sizeof (void*)" ^error,msg="No definition of \"sizeof\" in current context." ... and apparently decides to stop the debugging session as a result. The recommendation sent was to specifically set the language to C before trying to evaluate the expression. Something such as: 1. save current language 2. set language c 3. -data-evaluate-expression "sizeof (void*)" 4. Restore language This has the same disadvantages as the ones outlined in the "Context Management" section of the GDB/MI documentation regarding setting the current thread or the current frame, thus recommending the use of general command-line switches such as --frame, or --thread instead. This patch follows the same steps for the language, adding a similar new command option: --language LANG. Example of use: -data-evaluate-expression --language c "sizeof (void*)" ^done,value="4" gdb/ChangeLog: * mi/mi-parse.h (struct mi_parse) [language]: New field. * mi/mi-main.c (mi_cmd_execute): Temporarily set language to PARSE->LANGUAGE during command execution, if set. * mi/mi-parse.c: Add "language.h" #include. (mi_parse): Add parsing of "--language" command option. * NEWS: Add entry mentioning the new "--language" command option. gdb/testsuite/ChangeLog: * gdb.mi/mi-language.exp: New file. gdb/doc/ChangeLog: * gdb.texinfo (Show): Add xref anchor for "show language" command. (Context management): Place current subsection text into its own subsubsection. Add new subsubsection describing the "--language" command option. --- gdb/NEWS | 2 ++ gdb/doc/gdb.texinfo | 22 +++++++++++++ gdb/mi/mi-main.c | 7 ++++ gdb/mi/mi-parse.c | 25 ++++++++++++++- gdb/mi/mi-parse.h | 4 +++ gdb/testsuite/gdb.mi/mi-language.exp | 62 ++++++++++++++++++++++++++++++++++++ 6 files changed, 121 insertions(+), 1 deletion(-) create mode 100644 gdb/testsuite/gdb.mi/mi-language.exp diff --git a/gdb/NEWS b/gdb/NEWS index 6c3c272..cc7ae1b 100644 --- a/gdb/NEWS +++ b/gdb/NEWS @@ -145,6 +145,8 @@ show startup-with-shell * MI changes + ** All MI commands now accept an optional "--language" option. + ** The -trace-save MI command can optionally save trace buffer in Common Trace Format now. diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo index 9731bbf..37c313d 100644 --- a/gdb/doc/gdb.texinfo +++ b/gdb/doc/gdb.texinfo @@ -13340,6 +13340,7 @@ working language, and also what language source files were written in. @table @code @item show language +@anchor{show language} @kindex show language Display the current working language. This is the language you can use with commands such as @code{print} to @@ -28706,6 +28707,8 @@ the user interface. @node Context management @subsection Context management +@subsubsection Threads and Frames + In most cases when @value{GDBN} accesses the target, this access is done in context of a specific thread and frame (@pxref{Frames}). Often, even when accessing global data, the target requires that a thread @@ -28756,6 +28759,25 @@ all subsequent commands. No frontend is known to do this exactly right, so it is suggested to just always pass the @samp{--thread} and @samp{--frame} options. +@subsubsection Language + +The execution of several commands depends on which language is selected. +By default, the current language (@pxref{show language}) is used. +But for commands known to be language-sensitive, it is recommended +to use the @samp{--language} option. This option takes one argument, +which is the name of the language to use while executing the command. +For instance: + +@smallexample +-data-evaluate-expression --language c "sizeof (void*)" +^done,value="4" +(gdb) +@end smallexample + +The valid language names are the same names accepted by the +@samp{set language} command (@pxref{Manually}), excluding @samp{auto}, +@samp{local} or @samp{unknown}. + @node Asynchronous and non-stop modes @subsection Asynchronous command execution and non-stop mode diff --git a/gdb/mi/mi-main.c b/gdb/mi/mi-main.c index 8ff7f27..35573af 100644 --- a/gdb/mi/mi-main.c +++ b/gdb/mi/mi-main.c @@ -2123,6 +2123,7 @@ static void mi_cmd_execute (struct mi_parse *parse) { struct cleanup *cleanup; + enum language saved_language; cleanup = prepare_execute_command (); @@ -2184,6 +2185,12 @@ mi_cmd_execute (struct mi_parse *parse) error (_("Invalid frame id: %d"), frame); } + if (parse->language != language_unknown) + { + make_cleanup_restore_current_language (); + set_language (parse->language); + } + current_context = parse; if (parse->cmd->suppress_notification != NULL) diff --git a/gdb/mi/mi-parse.c b/gdb/mi/mi-parse.c index a3c1849..9994307 100644 --- a/gdb/mi/mi-parse.c +++ b/gdb/mi/mi-parse.c @@ -27,6 +27,7 @@ #include #include "gdb_string.h" #include "cli/cli-utils.h" +#include "language.h" static const char mi_no_values[] = "--no-values"; static const char mi_simple_values[] = "--simple-values"; @@ -244,6 +245,7 @@ mi_parse (const char *cmd, char **token) parse->thread_group = -1; parse->thread = -1; parse->frame = -1; + parse->language = language_unknown; cleanup = make_cleanup (mi_parse_cleanup, parse); @@ -292,7 +294,10 @@ mi_parse (const char *cmd, char **token) some important commands, like '-break-*' are implemented by forwarding to the CLI layer directly. We want to parse --thread and --frame here, so as not to leave those option in the string - that will be passed to CLI. */ + that will be passed to CLI. + + Same for the --language option. */ + for (;;) { const char *option; @@ -300,6 +305,7 @@ mi_parse (const char *cmd, char **token) size_t tgs = sizeof ("--thread-group ") - 1; size_t ts = sizeof ("--thread ") - 1; size_t fs = sizeof ("--frame ") - 1; + size_t ls = sizeof ("--language ") - 1; if (strncmp (chp, "--all ", as) == 0) { @@ -348,6 +354,23 @@ mi_parse (const char *cmd, char **token) parse->frame = strtol (chp, &endp, 10); chp = endp; } + else if (strncmp (chp, "--language ", ls) == 0) + { + char *lang_name; + struct cleanup *old_chain; + + option = "--language"; + chp += ls; + lang_name = extract_arg_const (&chp); + old_chain = make_cleanup (xfree, lang_name); + + parse->language = language_enum (lang_name); + if (parse->language == language_unknown + || parse->language == language_auto) + error (_("Invalid --language argument: %s"), lang_name); + + do_cleanups (old_chain); + } else break; diff --git a/gdb/mi/mi-parse.h b/gdb/mi/mi-parse.h index b20a389..325c1e1 100644 --- a/gdb/mi/mi-parse.h +++ b/gdb/mi/mi-parse.h @@ -50,6 +50,10 @@ struct mi_parse int thread_group; /* At present, the same as inferior number. */ int thread; int frame; + + /* The language that should be used to evaluate the MI command. + Ignored if set to language_unknown. */ + enum language language; }; /* Attempts to parse CMD returning a ``struct mi_parse''. If CMD is diff --git a/gdb/testsuite/gdb.mi/mi-language.exp b/gdb/testsuite/gdb.mi/mi-language.exp new file mode 100644 index 0000000..550beec --- /dev/null +++ b/gdb/testsuite/gdb.mi/mi-language.exp @@ -0,0 +1,62 @@ +# Copyright 2013 Free Software Foundation, Inc. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +load_lib mi-support.exp +set MIFLAGS "-i=mi" + +gdb_exit +if [mi_gdb_start] { + continue +} + +mi_gdb_test "set lang ada" \ + ".*=cmd-param-changed,param=\"language\",value=\"ada\".*" \ + "set lang ada" + +# Evaluate an expression that the Ada language is unable to parse. +mi_gdb_test "-data-evaluate-expression \"sizeof (void*)\"" \ + "\\^error,.*" \ + "sizeof expression using current language" + +# Now, ask for the same expression to be parsed, but using the C +# language. +mi_gdb_test "-data-evaluate-expression --language c \"sizeof (void*)\"" \ + "\\^done,value=\"$decimal\"" \ + "sizeof expression using C language" + +# Double-check that the current language has not changed. +mi_gdb_test "show lang ada" \ + ".*The current source language is \\\\\"ada\\\\\".*" \ + "set lang ada" + +# Test what happens when specifying an invalid language name... +mi_gdb_test "-data-evaluate-expression --language invlang \"sizeof (void*)\"" \ + "\\^error,msg=\"Invalid --language argument: invlang\"" \ + "data-evaluate-expression with invalid language name" + +# Make sure that "--language auto" is also rejected. +mi_gdb_test "-data-evaluate-expression --language auto \"sizeof (void*)\"" \ + "\\^error,msg=\"Invalid --language argument: auto\"" \ + "data-evaluate-expression with language auto" + +# Make sure that "--language local" is also rejected. +mi_gdb_test "-data-evaluate-expression --language local \"sizeof (void*)\"" \ + "\\^error,msg=\"Invalid --language argument: local\"" \ + "data-evaluate-expression with language local" + +# Make sure that "--language unknown" is also rejected. +mi_gdb_test "-data-evaluate-expression --language unknown \"sizeof (void*)\"" \ + "\\^error,msg=\"Invalid --language argument: unknown\"" \ + "data-evaluate-expression with language unknown" -- 1.8.1.2