Tuesday, 19 January 2010

Debugging shared libraries

If an application crashes inside a shared library, you need source level debugging in that shared library to find the cause.

Let's assume the shared library is part of the base system. First of all, you need to build the library with debugging information. Unfortunately, MKDEBUG and MKDEBUGLIB don't help because they only affect applications and static libraries, respectively. Assuming you still have the obj tree of the last build around, the easiest way to build is by using the make wrapper it created:

$ MAKE="`echo /usr/obj/usr/src/tooldir*/bin/nbmake-amd64`"

As an alternative, you could also use normal make. This will use its own obj directory and might trip over missing dependencies as a result:

$ MAKE="make USETOOLS=no"

Now build the debugging library:

$ cd /usr/src/lib/libedit
$ $MAKE obj
$ $MAKE CFLAGS=-g distclean dependall

When loading the application into the debugger, you can use LD_LIBRARY_PATH to make sure that your debug version of the library is loaded. To run sh with our debugging version of libedit:

$ LD_LIBRARY_PATH="`$MAKE print-objdir`" gdb /bin/sh
(gdb) b el_gets
Function "el_gets" not defined.
Make breakpoint pending on future shared library load? (y or [n]) y
(gdb) r
Breakpoint 2, el_gets (el=0x7f7ffdb11800, nread=0x621b1c)
    at /usr/src/lib/libedit/eln.c:75
75  el->el_flags |= IGNORE_EXTCHARS;