Future Plans
Internally, GDB has changed much over the years. A quick study of Cygnus' source repository shows that of the approximately
90,000 lines of code present in 1991, only about 30,000 lines remain unchanged, and 310,000 new lines have been added.
Despite all of the new code, most of the original design persists unchanged, and is now in need of updating. Most of the work
described below is presently underway; we expect that the rest of it will happen over the next year or two. Cygnus is leading the
development, and is also getting help from the net community, especially with testing and support for particular targets of
interest to volunteers.
Dynamic Choice of Architecture
The original approach to GCC and GDB portability was to make symbolic links to machine-specific include files. So for
instance, GDB's main include file defs.h includes the lines
#include "xm.h"
#include "tm.h"
even though there are no files xm.h or tm.h to be found in the sources. How does this work?
Suppose we want to build Windows cross PowerPC EABI tools. Then, running on Windows, we say (to the Cygwin port of the
shell program bash):
% ./configure --target=powerpc-eabi
The configure script's main activity is to construct makefiles from Makefile.in files, filling in variables and adding dependencies
for machine-specific files, such as the SDS protocol backend.
But it also makes symbolic links:
xm.h -> config/i386/xm-cygwin.h
tm.h -> config/powerpc/tm-ppc-eabi.h
These include files contain the C macros defining the host and target architectures, as described earlier.
For GCC, this has been an efficient approach. It is possible to use #ifdefs to choose the compiler algorithms best suited to the
target processor, thus not slowing down the compiler by making it choose while trying to get to the business of generating
code.
However, for GDB, this doesn't work nearly so well. GDB sits at the end of the tool "food chain", and must always be prepared
to deal with various object files, different compilation options, and different versions of the hardware. In addition, it does not
have the same sort of performance issues. (There are really only two key performance issues for GDB: the speed of reading
symbol files, and the efficiency of the remote debugging protocol.)
As noted previously, this general idea of dispatching at runtime is already in use for symbol readers and debugging protocols,
and has been successful there. We are changing GDB to do the same kind of thing for target architecture definition.
Ultimately, it will be possible to have a "universal" GDB that has support for all possible processors. Although this is a nice
idea, it won't matter to most shops, since they typically use only one or two different architectures. Of more practical interest
will be the ability to handle different architecture variants; for instance, all the processors in the MIPS family, or all the versions
of Hitachi SH. (GDB handles some of the variants now, but only by kludgery.)
Another interesting possibility will be the ability to have dynamically loaded architecture descriptions. Mentor/Microtec's
description of their Xray debugger mentions this as a capability, although without supplying much detail. In GDB's case the
documentation for how to do this will be publicly available along with the sources.
Event-driven behavior and asynchronous debugging
GDB's execution control, as described above, does not actually work well in an event-oriented environment. For example, the
Insight GUI requires a certain amount of trickery in order to keep the interface working while wait_for_inferior is quietly waiting
for the target.
GDB's new design is to break up the infinite loops. Instead, each GUI or command interpreter, as well as each target
connection, will register itself as a generator of "events". Then GDB's waiting will consist of waiting for any event, and either
dispatching it to an interface, or to a target vector.
This requires a complete reorganization of wait_for_inferior, a daunting task because of its complexities that were described earlier.
One big benefit will be the ability to do asynchronous debugging, which means interacting with the target while it is running. To
use the command line as an example, the prompt will come back right away and allow typing of commands before the
programs stops again:
(gdb) continue
(gdb)
Computing away! [output from the program]
(gdb) print avar
avar = 45
More computing going on! [ more output]
(gdb) print avar
avar = 46 [program is modifying avar]
Program stopped at foo()
(gdb) print avar
avar = 46
(gdb)
GUIs will be able to work similarly, so while right now the variable display window will be disabled while the program is
running, with asynchronous debug all the data displays can remain active and usable.
Parallel debugging
Another vestige of the old GDB is the one-process assumption. While multi-thread support has been in GDB since 1994, GDB
can still only reasonably handle a single executable program in a single address space. Modern embedded systems will
require the removal of this limitation; new designs include multiple CPUs (such as ARM and DSP), multiple copies of a
processor on a single die, and multiple CPUs executing from a partially shared memory.
Changes will include the encapsulation of global data about the program into objects. The event-driven architecture will help
considerably here, and there will be additional work to develop an interface that will manage the multiple processors without
unduly taxing the user.
|