Vladimir Prus


Monday, November 26, 2007

Breakpoints in constructors

Presently, no release of GDB properly handles breakpoints in contructors. This summer, I've worked on fixing that, and while it took longer than expected, it was eventually done, just in time for Sourcery G++ Fall release. The patches were also submitted for GDB FSF, missed the window for 6.7, but will be present in 6.8 release.

The underlying problem with breakpoints in constructors was that gcc generates two distinct function bodies for a constructor. One is a regular one that constructs the entire object, including all bases. Another one constructs everything except for virtual base classes. As it happens, gcc emits both constructors even for classes that have no virtual bases at all. GDB was not prepared that a given function name or source line corresponds to several addresses in program, so it picks one. And usually it picked the wrong one.

Constructor is the most common case, but is not the only one. If you set a breakpoint in a function template, you can have multiple template instantiations that correspond to a source line. An inline function can be inlined in multiple places, and lead to exactly the same problem.

The solution, obviously, is to teach GDB that a breakpoint can correspond to several addresses, and then create multiple-location breakpoints when needed. Now, whenever a user creates a breakpoint that resolves to a source line, GDB traverses line tables for all modules, and if it finds another address for the same line, that address is added to breakpoint. For a template or inline function, you can end up with quite a lot of locations, so you can review list of locations, and disable the unwanted ones.

The nicest bit of this is interaction with shared libraries. Say, you've set a breakpoint inside function template. If you load a new shared library, and it contains an instantiation of that function template, a new location will be added to the breakpoint, transparently. If a library is unloaded, the location will become 'pending', until you load the library back.

The side effect of this work was a serious improvement in the way breakpoints in shared libraries work, but that's a topic for another post.


Matthias Kretz said...

Yay! Can't wait for the new gdb. Awesome work!

Michael Pyne said...

You're like my hero for the whole month now. Just want you to know that. :)

Kevin Kofler said...

The patch has been backported to the GDB in Rawhide (future Fedora 9) on November 3.

Jens said...

That's like kinda wow! :D

Unless I'm mistaken, this has been a problem for GDB since GCC 3.0. Fantastic news!

zwabel said...

Really great! Does this maybe also solve some of the general problems while debugging within constructors? For example, it seems like gdb sometimes is not aware of local variables within constructors.

Vladimir Prus said...

David, I don't think any other bugs with debugging constructors were fixed, at least intentionally. In fact, I don't know any other problem specific to constructors, in GDB. Can you give some more details?

William said...

i don't know if you'll get this message, but here is an excellent bug report of exactly the problem i believe zwabel was referring to.

I am also having this problem in a constructor that is very complicated and long. Hard to debug with no info about local variables.

check this link

roland.puntaier said...

Great. That would have spared me a lot of workarounds. I use MinGW GDB 6.6. So I will change to 6.8 as soon as possible and do a lot of cleanup. Thanks very much.