Remote debugging using gdbserver

The key component for remote debugging is the debug agent, gdbserver, which runs on the target and controls execution of the program being debugged. Gdbserver connects to a copy of GDB running on the host machine via a network connection or an RS-232 serial interface.

Debugging through gdbserver is almost, but not quite, the same as debugging natively. The differences are mostly centered around the fact that there are two computers involved and they have to be in the right state for debugging to take place. Here are some things to look out for:

  • At the start of a debug session you need to load the program you want to debug on the target using gdbserver and then separately load GDB from your cross toolchain on the host.
  • GDB and gdbserver need to connect to each other before a debug session can begin.
  • GDB, running onto the host, needs to be told where to look for debug symbols and source code, especially for shared libraries.
  • The GDB run command does not work as expected.
  • gdbserver will terminate when the debug session ends and you will need to restart it if you want another debug session.
  • You need debug symbols and source code for the binaries you want to debug on the host, but not necessarily on the target. Often there is not enough storage space for them on the target and they will need to be stripped before deploying to the target.
  • The GDB/gdbserver combination does not have all the features of GDB running natively: for example, gdbserver cannot follow the child after fork() whereas native GDB can.
  • Odd things can happen if GDB and gdbserver are different versions or are the same version but configured differently. Ideally they should be built from the same source using your favorite build tool.

Debug symbols increase the size of executables dramatically, sometimes by a factor of 10. As mentioned in Chapter 5, Building a Root Filesystem, it can be useful to remove debug symbols without recompiling everything. The tool for the job is strip from your cross toolchain. You can control the aggressiveness of the strip with these switches:

  • --strip-all: (default) removes all symbols
  • --strip-unneeded: removes symbols not needed for relocation processing
  • --strip-debug: removes only debug symbols

    Tip

    For applications and shared libraries, --strip-all (the default) is fine, but when it comes to kernel modules you will find that it will stop the module loading. Use --strip-unneeded instead. I am still working on a use case for –strip-debug.

With that in mind, let's look at the specifics involved in debugging with the Yocto Project and Buildroot.

Setting up the Yocto Project

The Yocto Project builds a cross GDB for the host as part of the SDK, but you will have to make changes to your target configuration to include gdbserver in the target image. You can add the package explicitly, for example by adding this to conf/local.conf, noting once again that there must be a leading space at the start of this string:

IMAGE_INSTALL_append = " gdbserver"

Or, you can add tools-debug to EXTRA_IMAGE_FEATURES, which will add both gdbserver and strace to the target image (I will talk about strace in the next chapter):

EXTRA_IMAGE_FEATURES = "debug-tweaks tools-debug"

Setting up Buildroot

With Buildroot, you need to enable options both to build the cross GDB for the host (assuming that you are using the Buildroot internal toolchain) and to build gdbserver for the target. Specifically you need to enable:

  • BR2_PACKAGE_HOST_GDB, in the menu Toolchain | Build cross gdb for the host
  • BR2_PACKAGE_GDB, in the menu Target packages | Debugging, profiling and benchmark | gdb
  • BR2_PACKAGE_GDB_SERVER in the menu Target packages | Debugging, profiling and benchmark | gdbserver
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.149.232.152