[
Date Prev][
Date Next][
Thread Prev][
Thread Next][
Date Index][
Thread Index]
[
List Home]
[cdt-debug-dev] MI investigation
|
This note is a summary of the state of our MI investigation.
MI has been under development for a number of years.
The goal is a better interface for loosely coupled UIs,
with
more granular commands
a stable keyword=value response syntax
separation of the logical output streams
There is MI documentation in the GDB users manual but it is not
completely reliable. What follows describes the current state
of MI in GDB 5.1.1
OUTPUT STREAMS
The response to an MI command is an MI result and a prompt, possibly
preceded
and/or followed by asynchronous MI output intermixed with stream output.
The command can be prefixed by an (arbitrary) number, in which case
the MI output is prefixed by the same number.
MI results begin with one of ^done, ^running, ^connected,
^error, and ^exit, possibly followed by comma-separated name=value pairs.
Asynchronous MI output comes in 3 types, with different prefix characters.
'+' - asynch. updates of the status of a long-running debugger operation.
It is ignorable.
The only one defined is the "+download" response used with remote
hosts.
'=' - specified as "supplementary information that the client should handle
(e.g., a new breakpoint information)."
Currently none of these are issued.
'*' - asynch. state changes of the target. The only one of these issued
today is "*stopped". An "exec-" MI command elicits a "^running"
response first, then when/if the target stops (by hitting a
breakpoint,
watchpoint, end of stepping range etc.) the additional "*stopped"
output is generated.
Stream output also comes in 3 types, again with 3 prefix characters:
'~' - console output to be displayed in a CLI console window, containing
the response to CLI commands.
'&' - log messages from GDB's internal diagnostics
'@' - textual output from the running target
In fact, this only works for remote targets.
When debugging locally the debuggee interacts directly with
stdin/stdout/stderr. Obviously this can cause great confusion
if the program output begins with one of the prefix characters.
MI CHANGES
In the past year or so the format of MI outputs has changed, but for
backward compatibility recent GDBs support both mi0 and mi1 styles.
An example of the difference is the result from a -break-list command.
With mi0:
^done,BreakpointTable={hdr={"Num","Type","Disp","Enb","Address","What"},
bkpt={number="1",type="breakpoint",disp="keep",enabled="y",addr
="0x080485c9",
func="main",file="test.c",line="12",times="0"}}
With mi1:
^done,BreakpointTable={nr_rows="1",nr_cols="6",hdr=[{width="3",alignment="
-1",
col_name="number",colhdr="Num"},{width="14",alignment="-1",col_name="type",
colhdr="Type"},{width="4",alignment="-1",col_name="disp",colhdr="Disp"},
{width="3",alignment="-1",col_name="enabled",colhdr="Enb"},
{width="10",alignment="-1",col_name="addr",colhdr="Address"},
{width="40",alignment="2",col_name="what",colhdr="What"}],
body=[bkpt={number="1",type="breakpoint",disp="keep",enabled="y",
addr="0x080485c9",func="main",file="test.c",line="12",times="0"}]}
COMMANDS
These MI commands are documented but not implemented in GDB 5.1.1:
-display-delete
-display-disable
-display-enable
-display-insert
-display-list
-exec-abort
-exec-show-arguments
-file-list-exec-sections
-file-list-exec-source-files
-file-list-shared-libraries
-file-list-symbol-files
-stack-info-frame
-symbol-info-address
-symbol-info-file
-symbol-info-function
-symbol-info-line
-symbol-info-symbol
-symbol-list-functions
-symbol-list-types
-symbol-list-variables
-symbol-locate
-symbol-type
-target-attach
-target-compare-sections
-target-exec-status
-target-list-available-targets
-target-list-current-targets
-target-list-parameters
-thread-info
-thread-list-all-threads
These commands are implemented but not documented:
-data-write-memory
-data-write-register-values
This command only works with asynchronous targets, which does not
include local Linux debugging:
-exec-interrupt
CLI SUPPORT
The statements in the manual and GDB source warning that the CLI-in-MI
function will disappear are recognized as inadequate but there is no
clear consensus on what the eventual answer will be.
There are two parts to this issue:
1. Supplement the incomplete MI command set
2. Providing a command line interface for GUI users to access "power user"
capabilities, create and use user-defined commands, invoke scripts, etc.
The first is often done under the covers by MI, for example an MI "
-break-list"
actually executes the CLI "info break" command. The key is they
should behave like MI commands and produce MI results, which they do to
a great extent. However there are some CLI commands we use today that
do not have implemented MI equivalents, and which do not produce MI
style results
"info program" - to find process ID so we can kill it, since
-exec-interrupt doesn't work
"whatis"/"ptype" - to substitute for missing -symbol-type
"info line"/"info line *" - to convert address <-> line#
"maintenance print objfiles" - for missing -file-list-exec-source-files
"info share" - for missing -file-list-shared-libraries
"info threads" - for missing -thread-list-all-threads
"list" - produces no output at all
The second part is more difficult. For this we want to provide a high
fidelity
CLI interface, with standard CLI output in the console window.
At the same time, we need to keep the GUI up to date with any state
changes in the debugger or the target, such as new breakpoints, running
state,
or stack frame changes, preferably by notifications in the MI stream when
these things do change.
Current gdbs (up to 5.1.1) don't help with either of these problems.
MI users have to fake generating CLI-like output for console commands,
and have to query the debug state after a command to find out if anything
has changed.
However, Apple has done a lot of work in this area with a version of GDB
they use under their Project Builder IDE for OS X, and which they have
made available for integration back into the main GDB codebase.
APPLE MI EXTENSIONS
Apple's extensions address two major MI deficiencies with CLI support.
First, they have made the interpreter dynamically switchable,
and introduced an MI command -interpreter-exec interpreter "command" which
can be used to run console (CLI) commands with true CLI output.
The difference is illustrated in this example:
(gdb) info break
&"info break\n"
^done,BreakpointTable={hdr
={"Number","Type","Disposition","Enabled","Address",
"What","StackFrame","Condition","IgnoreCount","Commands"},bkpt={number="1",
type="breakpoint",disp="keep",enabled="y",addr="0x080485c9",func="main",
file="test.c",line="12",times="0"}}
(gdb) -interpreter-exec console "info break"
Number Type Disposition Enabled Address WhatStackFrame
Condition IgnoreCount Commands
1 breakpoint keep y 0x080485c9 in main at test.c :12
^done
(gdb)
Secondly, Apple has added hooks in GDB to capture state change information
when these true CLI mode console commands are run using -interpreter-exec.
The information is appended to the MI result rather than using an
asynchronous notification.
These notifications are provided:
Breakpoint delete =>
^done,MI_HOOK_RESULT=(HOOK_TYPE="breakpoint_delete",bkptno="n")
Breakpoing modify =>
^done,MI_HOOK_RESULT=(HOOK_TYPE="breakpoint_modify",bkpt=(...))
Breakpoing create =>
^done,MI_HOOK_RESULT=(HOOK_TYPE="breakpoint_create",bkpt=(...))
Frame changed =>
^done,MI_HOOK_RESULT=(HOOK_TYPE="frame_changed",frame="n")
Thread context (i.e., current thread) changed =>
^done,MI_HOOK_RESULT=(HOOK_TYPE="thread_changed",thread="n")
The information is cumulative if a complex command causes more than one
change.
They also introduced a few other hooks that also take effect
when -interpreter-exec console is being used:
1. If an -interpreter-exec CLI command asks for "(y or n)" confirmation,
always answer "y".
2. If an -interpreter-exec CLI command needs multiline input (e.g.
"define",
"document", "if", or "while), prompt with the MI async notification
=read-one-line,prompt="prompt"
3. If an -interpreter-exec CLI command steps or continues the target,
generate the notifications "^stepping" or "^continuing"
4. If an -interpreter-exec CLI command attempts to run the target,
don't do it, instead send the notification
=rerun
back to the UI
ASSESSMENT
The value that MI provides today is in
stream separation
robustly parseable output
supported interface
but with these limitations
stream separation isn't reliable
some necessary machine output is still in CLI format
some necessary output isn't available ("list")
CLI console output has to be faked
inadequate notification of state changes
The question now is whether the current MI implementation provides
enough value to target it now, given we will have to implement
workarounds for the limitations, and given that nobody believes it is
complete and so will continue to be a moving target for some time.
My view is it would it make more sense to help fix MI first,
e.g. by helping to integrate the Apple work and fix the stream
separation problem, and move to it when it is more stable and complete.
REFERENCES
Questions about GDB-MI Interface
http://sources.redhat.com/ml/gdb/2002-04/msg00394.html
Target Output Streaming in MI
http://sources.redhat.com/ml/gdb/2002-05/msg00022.html
Brian