This is the mail archive of the gdb@sourceware.cygnus.com mailing list for the GDB project. See the GDB home page for more information.
Index Nav: | [Date Index] [Subject Index] [Author Index] [Thread Index] | |
---|---|---|
Message Nav: | [Date Prev] [Date Next] | [Thread Prev] [Thread Next] |
Folks, here is a description of some proposed changes to GDB. Enjoy. I am planning to include in GDB an event loop, in files event*.[ch]. This is the first step towards the implementation of GDB as an asynchronous debugger. This means that after the project is completed, GDB's interface will be responsive to user input while the target program is executing. GDB will launch target execution and it will later be able to detect when the target has stopped, and notify the user accordingly. This first group of changes sets in place the infrastructure necessary to achieve the above goal. At this stage, the event loop machinery has been integrated with the readline library and GDB's command line interface. This new behavior is still not the default execution path, and it is triggered only if gdb is invoked with the -nw and --async options. Target execution is still as it usually is, i.e. blocking. In the near future we plan to make the event loop be the default engine for GDB). After that, we'll start converting each of the gdb targets to be asynchronous. An event loop listens for events from multiple event sources. When an event arrives, it is queued and processed by the event loop which calls the appropriate event handler and then listens for more events. An event loop completes when there are no event sources to listen on. External event sources can be plugged into the loop. Event handlers are often associated with event sources and/or events. An event handler analyzes the event and may take some action based on the event. Event sources for gdb are currently the UI and the target. Gdb communicates with the command line user interface via the readline library and usually communicates with remote targets via a serial port. Serial ports are represented in GDB as file descriptors and select/poll calls. For native targets instead, the communication consists of calls to ptrace and waits (via signals) or calls to poll/select (via file descriptors). In the current gdb, the code handling events related to the target resides in the wait_for_inferior function and in various target specific files (*-tdep.c). As mentioned above, all the new event-* files are part of the event loop. Such event loop was partially modeled around the notion of a notifier which is also used in the Tcl/Tk event loop. A notifier is a module that queues the detected events and processes them, in an infinite loop. An event is represented by a procedure to be invoked in order to process the event. Such events are queued in the notifier as they occur and then processed, while the queue is scanned head to tail. Events are detected in two main fashions, depending on the nature of the corresponding event source. If the event of interest is a change of state in a file descriptor, then a call to poll or select will be made to detect it. If the events generate signals, they are also queued by special functions that are invoked through traditional signal handlers. The actions to be taken is response to such events will also be executed when the queue is scanned, the next time thought the infinite loop. The whole mechanism can be described as having two main components. The first one is to detect the occurrence of events and queue them, the second is to process the queued events. Corollary tasks are the creation and deletion of event sources. In this set of changes involving only the command line interface, there is just one event source: the file descriptor for the input stream. While the event loop code is relatively simple and self-explanatory, a few words should be spent describing how the core of GDB has been so far modified, and how the readline library inter-operates with the new event driven GDB. Readline offers an alternate interface, via callback functions. These are all included in the file callback.c in the readline distribution. This file provides (mainly) a function, which the event loop uses as callback (i.e. event handler) whenever an event is detected on the standard input file descriptor. readline_callback_read_char is called (by the GDB event loop) whenever there is a new character ready on the input stream. This function incrementally builds a buffer internal to readline where it accumulates the line read up to the point of invocation. In the special case in which the character read is newline, the function invokes a GDB supplied callback routine, which does the processing of a full command line. This latter routine is the asynchronous analog of the old command_line_input in gdb. Instead of invoking (and waiting for) readline to read the command line and pass it back to command_loop for processing, the new command_line_handler function has the command line already available as its parameter. The usual gdb calling sequence is as follow: main --> command_loop --> command_line_input --> readline now we have (only partial sequence showed here): readline_callback_read_char --> command_line_handler --> command_handler The sequence is basically reversed. Handling of signals has also changed, as previously mentioned. New functions handle_sig* have been introduced, one for each of the signals GDB cares about. Specifically: SIGINT, SIGFPE, SIGQUIT, SIGTSTP, SIGHUP, SIGWINCH. These functions are the actual signal handlers associated to the signals via calls to signal(). The only job for these functions is to enqueue the appropriate event/procedure with the event loop. Such procedures are the old signal handlers. The event loop will take care of invoking the queued procedures to perform the usual tasks associated with the reception of the signal. Another change is related to the gdb prompt. When gdb is invoked with the --async option, the prompt is stored in a prompt stack. The prompt that gdb displays is always the top of the stack. This mechanism provides the infrastructure that will be used once code that requires further user input is converted to the new scheme. This will be the case for the 'commands' command which currently displays a prompt of '>' and uses readline (in synchronous, blocking mode) to read user input. Another example of this is the 'actions' command. In these two cases, gdb will need to invoke the readline callback function from the event loop, but it will need to remember its state (hence the stack) as being reading auxiliary input instead of high level commands. The state will be represented by having a stack with two prompts, '>' as the top, and '(gdb)' below it. When the auxiliary input is finished, the stack will be popped. Of course in these circumstances, another piece of information will be necessary: the callback function provided to readline, to be called after a complete line of input has been entered. This second part of the mechanism is however still not in place. A second change related to prompts is due to the different form of the prompt when the annotation level is 2. In this case, the prompt is actually composed of 3 parts: a prefix, the prompt itself and a suffix. Accordingly, each element on the prompt stack is a record composed of three parts. This was necessary because the 'set prompt' command operates only on the middle portion of the prompt, leaving prefix and suffix unchanged. This allows to deal consistently with changing the prompt independently of the current annotation level. The code will be available in the next week or so. When it is ready, I'll post a message to this list, with the proposed patches. Elena Zannoni Cygnus Solutions