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]

Some proposed changes in GDB



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