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.