Re: GDB Focus Group at the 2008 GCC Summit

Jason Molenda
2008-06-23T21:46:44Z

On Jun 19, 2008, at 12:09 PM, Joel Brobecker wrote:

> |
> | * Fix and continue:
> |
> | Perhaps try to implement this feature through the use of Python.
> | For instance, use python to build a return value, and return
> that.

As Jim mentioned, we did this to gdb here at Apple four or five years
back. I started my work on F&C by reading through HP's gdb changes
(in "wdb", their version of gdb). Their implementation is very gdb-
centric and may be a better place to start looking - if I remember
correctly gdb rebuilds the .o file itself as a part of the "fix"
command, for instance.

With our F&C system, we start by compiling a PIC library from the .o
file (a "bundle" on Mac OS X). We've modified gcc to pad the
prologues of functions with a few nop instructions and we've also
changed the compiler to use indirect references to static objects
within the compilation unit. Normally a function accessing a file-
static variable, would use a pic-based reference once it had been
finished with the linker. But we want to map these all to the
original static/globals that we started with so we need the
indirection. (you don't want a global to have a value of 10, fix in a
file and then one compilation unit thinks it has a value of 0 while
the rest of the program is still pointing to the one with a 10.)

Before we load the newly built code, we try to look over the types in
the .o file and ensure that arguments haven't been added to functions,
structure sizes haven't been changed, etc. Again, half of the program
thinking that a function takes 2 arguments and another part thinking
it takes 3 will work poorly.

Once the new .o file has been loaded into memory, we rewrite the nop's
in the prologues of all earlier versions of the functions to point to
the newest versions. So if someone has a pointer to one of the
original functions, they'll still end up calling the new one. We
update the indirection table for file statics so any references to
globals/statics in the just-loaded .o file will go to the original
versions, if they exist.

The IDE is responsible for removing & reinserting breakpoints at the
correct line numbers. If you had a breakpoint on main.c:35 and you
added a couple of lines of code earlier in the file, that breakpoint
needs to be moved to main.c:37.

If you're stopped in a function that was just updated, the IDE tells
gdb to re-set to the corresponding line number in the newly loaded
file. This obviously has no chance of working except at -O0. And
with i386/ppc code, most functions that reference static/global data
load $pc into a register so they can load objects pc-relative. You
need to find that setup in the new function, compute what that picbase
register should hold and set it ahead of time.

gdb then marks the psymtab/symtab of the just-replaced file as
'obsolete' so when we are doing a symbol-to-addr lookup we don't find
them. At the same time, if you're doing an addr-to-symbol lookup you
want to find the old, obsoleted files -- you might have a function on
the stack still or something like that.

As you can tell from the above, at Apple I offload some of the work to
the compiler and some to the IDE. You get the impression that the wdb
folks did it all by themselves - they have all sorts of chicanery to
squeeze the jump instruction into functions regardless of how long
they are, or if you're stopped in the middle of the code it wants to
rewrite.

All that being said, it's a pretty fragile mechanism. C/C++ weren't
designed for this kind of thing. It works fine on trivial examples
and makes great demoware but it's very easy to crash your program when
you're trying to use this on real programs/real problems. I've heard
some success stories from people who are doing specific narrow things,
or where re-starting their debug session and getting back to the
problem spot are so expensive that they're willing to take a risk.
But IMO, in practice, it's less useful than any of us would have liked.

wdb and Apple's gdb implementations are GPL'ed of course so for more
details it's probably best to just browse the sources.

J