Adjust MI non-stop/MI3 spec

Vladimir Prus vladimir@codesourcery.com
Mon May 5 08:33:00 GMT 2008


Attached is the current version of MI non-stop/MI3 spec, in case
anybody's interested. Nothing drastic changed, except some changes
were moved to MI3, and the --thread option is no longer required 
in MI2 non-stop mode.

- Volodya

-------------- next part --------------
MI3/non-stop MI spec
==================

Legend:
(*) Behaviour to be implemented in MI3
-> Todo items

General clarifications
----------------------

(*) It is not longer required that async output record, or result
record, is followed by a prompt.  Instead, prompt is used to indicate
that gdb is ready to accept next command.  Each MI command results in 
either ^done or ^error.  The ^done response means that the previous
command is successfully executed. For commands that run the target,
^done is output immediately when the target was successfully resumed.
Any further change in the state of the target is reported via async
output records.  The prompt will be printed either immediately after
^done, if GDB can accept commands while target is running, or when
the target stops.

    Notes: A frontend can send a command without waiting for 
    the prompt, and it will be eventually processed.  However, if gdb
    has not printed a prompt after the previous command yet, it means
    that it might take a lot time until the next command will be executed.
    The frontend may use the lack of prompt to disable some commands, or 
    to show "waiting for previous command to finish"  indicator.

New notifications
-----------------

1. The *running notification is introduced, in the form:

   *running,thread-id="xxx"

It's emitted whenever a thread is resumed. "xxx" can be all if all
threads are resumed.

2. The *stopped notification will get a new field, 'stopped-threads':

   *stopped,thread-id="xxx",stopped-threads=[...]

Here, the thread-id field indicates the thread which caused the stop,
and the stopped-threads lists all threads that were stopped as result.
Typically, those are all threads in the program for all-stop mode
and the same thread as in thread-id for non-stop mode.
The value of the stopped-threads field can be either list of thread ids,
or a string "all".

Explicit thread specification
-----------------------------

All MI commands accept a new option --thread that indicates which
thread the command should operate on.  Using an MI command with
this option does not change GDB's externally visible notion of the
current thread, nor does it emit any "thread changed" notification.

The --thread option essentially allows the frontend to examine any
thread it wants without making that thread current and without depending
on GDB's current thread. Lacking this, a frontend wishing to examine
non-current thread should emit -thread-select, perform the operation
and the -thread-select back.  This is both extra commands to send,
and it creates a window where the current thread as seen in GDB console
is not the one that is expected.

-> In fact, we probably should make thread selection, internally, not
to reset the frame to 0. Otherwise, frontend can nicely messup GDB
console.

(*) MI3 might make this option required.


Async/non-stop mode notes
-------------------------

The async mode basically means that gdb can process commands even while
the target is running.  This mode is enabled whenever the target is
async-capable.

In async mode, there are two further distinctions:
  - Should we allow an exec command while some other exec command
  is already in progress?
  - Should we stop all threads whenever an event is detected in one thread?

Those issues seem independent initially, so we might try to allow
two -exec-next at one time, and then stop all threads when any -exec-next
is finished.  However, that will require user to explicitly resume the
-exec-next that is not yet finished, which does not seem very helpful --
it's not much better than sending two -exec-next sequentally.
Therefore, for now we shall have only two modes:

  - "all-stop", when all threads are stopped if any thread stops,
  and when only one exec command is allowed to be active at any given time,
  - "non-stop", where individual threads are stopped, and several
  exec commands can be active.

Except for what is said above "all-stop" and "non-stop" async modes are
identical. 

Generally, most MI commands are allowed while a target is running, with the
following exceptions:

   - An execution command that logically applies to a single thread 
   cannot be used if the thread is already running.  Global -exec-continue is
   OK, and will resume all threads that are not presently running. In all-stop
   mode an execution command cannot be started if any thread is running.

          
   - Some data access commands are also implicitly using a specific thread --
   because they are using registers, or variables in specific thread/frame,
   or because they have to call a function in the inferior. Such data access
   commands are not allowed when the necessary thread is running. Wholesale
   update operations like -var-update will plain ignore variable objects
   that need now-running threads.

   - The commands that grab global state of the target are allowed when 
   some threads are running.  It should be understood that the result may
   be inaccurate -- in particular, the memory content can change while
   we read it, and the list of threads might not be updated until some
   event from the target arrives. In addition, some targets might not   
   even allow reading memory while all threads are running -- so memory
   access commands on such targets will require that at least one thread
   is stopped.

To simplify things, if GDB is started in MI mode, no CLI command is allowed
while the target is running.  The -interpreter-exec is allowed, but
is at user's risk.

   Note: in cases when to implement a command, GDB requires that at least
   one (or all) threads are stopped, and the command is issued when this
   condition is not met, we have two choices -- issue an error, or briefly
   stop the target, perform the operation, and resume. Clearly, doing
   that in GDB (or even in the target) will be less intrusive then doing
   that in frontend.  However, it might be still too intrusive. For now,
   we'll just emit error, should a real need arise, we can always implement
   automatic interruption of the target.   

MI non-stop command changes
---------------------------

    When operating in non-stop mode, GDB does not automatically switch
    the current thread to a thread that got some event.  This is to avoid
    annoying CLI users with switches to some other thread as he's doing
    something with the current selected thread. This is also to avoid
    changing the meaning of the commands already sent/queued by the frontend,
    in case the frontend choose not to use the --thread option.

    - Break commands. The primary limitation on breakpoint commands is
    that it is not possible to insert or remove breakpoints from the
    target if all threads of the target are running. Therefore, the
    -break-insert, -break-watch, -break-delete, -break-enable and
    -break-disable commands are not allowed unless at least one
    thread is stopped.

    The -break-info, -break-list, -break-after, -break-condition commands
    are allowed.
    The -break-catch and -break-commands commands are not presently
    implemented and will not be implemented.

    If -break-insert command specifies only line number, then it implicitly
    depends on the filename of the current thread/frame. In non-stop mode,
    the frontend is required to specify thread and frame explicitly.

    - Program context commands. Those are not allowed after the program
    has started execution.

    - Thread commands.  There are no limitations.  Note that while
    the -thread-select command can be used on a thread that is currently
    running, very few of other commands will work on a running thread.
   
    - Program execution. The -exec-next, -exec-step, -exec-finish, 
    -exec-until, -exec-return, -exec-step-instruction and 
    -exec-next-instruction always resume just the thread specified
    with the --thread option, or the current thread. This is the same
    as using "scheduler-locking on" in all-stop mode.
    The -exec-continue will resume just the thread specified with the --thread
    parameter, or the current thread. To resume all threads, one must
    pass the --all option. If a specific
    thread was resumed with -exec-continue, then should that thread create
    another thread, that new thread won't be running. If case the entire
    program was resumed, then new threads will be running as well.

    - Stack commands. All are allowed. All require a thread parameter in
    non-stop mode.

    - Variable objects. The thread -var-create operands on must be stopped.
    If a variable object makes use of any local variable, the object 
    becomes bound to the
    thread where it was created.  An attempt to manipulate an
    individual variable obect when the thread it is bound to is not
    stopped results in an error. As a special exception, -var-update will
    ignore any variable object whose bound thread is not stopped.
    A variable object's expression might involve a function call.  If a
    variable object is not bound to any thread, the function call will be
    executed in any currently stopped thread.

    -> Decide/check if we can create a global varobj when all threads
    are running.
    
    - Data manipulation. All commands are supported, except for
    data-list-changed-registers, which is presently thread-unaware and seems
    inferior to using variable objects anyway. 
    The -data-evaluate-expression and -data-list-register-values requires
    that either the --thread or the --global option be provided.

    - Symbol query commands. All are supported.
    
    - File commands. The -file-exec-and-symbols and -file-exec-file cannot
    be used when any thread is running.  The -file-list-shared-libraries
    can be used while inferior is running, but the results might be
    invalidated immediately. Same for -file-list-symbol-files. Others
    can be used without limitations.

    On some targets it might not be possible to get the list of shared 
    libraries from the target while it is running. In such cases, GDB will
    report an error.

    - Target manipulation. The -target-disconnect can be used while threads
    are running. Other (currently implemented) commands can only
    be used before we have an executable.

    - File transfer. Can be always used.

    - Misc. Case-by-case, nothing interesting.


More information about the Gdb mailing list