Cross Arch Remote Debugging with GDB and gdbserver
To further debug a problem in my little initramfs system I recently added gdbserver to the build scripts. And since I have never done that before I might as well document how this works.
gdbserver which runs on the target basically just provides the ‘debugging backend’ and makes it available to a normal host gdb. This has the advantage that gdbserver is relatively easy to build for your embedded system of choice, it doesn’t provide a user interface and therefore doesn’t require readline/curses libraries.
So we cross compile gdbserver whose source can be found in the gdb tarball under gdb/gdbserver like this (replace $ARCH with your target architecture in my case it was armv4tl-unknown-linux-gnueabi):
cd gdb/gdbserver
./configure --build=`./config.guess`
--target=$ARCH
--host=$ARCH
--prefix=/usr
--program-prefix="" &&
make &&
make DESTDIR=$SOMEDIR install
Then you will need a host gdb which understands the instructions of your
target architecture. Your distribution probably only enabled support for
your native architecture which means you will have to build your host
gdb from source. Note that this time we only set --target
and build
from the top level directory.
./configure --host=`./config.guess`
--build=`./config.guess`
--target=$ARCH &&
make &&
make DESTDIR=$SOMEDIR install
Now we can start our debugging session. On the target execute gdbserver and specify a port and your executable.
gdbserver :$SOME_PORT /path/to/file/you/want/to/debug
Back on the host connect to the listening gdbserver instance with your host gdb:
$ARCH-gdb
file /path/to/file/you/want/to/debug
target remote $IP_OF_TARGET:$SOME_PORT
set solib-absolute-prefix $ROOT_DIR
continue
The solib-absolute-prefix should point to the root directory of the
target on your host. Confused? Well you probably have cross compiled all
your stuff for the target and installed it into a directory on your host
and this is what I mean with “the root directory of the target on your
host”. gdb will use the solib-absolute-prefix whenever it needs to load
a shared library. What this means is that if the app you are debugging
depends on a library gdb will load the library symbols from
$ROOT_DIR/lib/libfoo.so
instead of /lib/libfoo.so
from the host
system where it either has the wrong architecture or doesn’t exists at
all.
Hope this is useful for someone out there. At the very least I now know where to look should I have to do it again in the future when I have already forgotten how it actually works.
Marc