Simple command line application debugging

We will take the C++ Hello World application myapp from the chapter [Simple command-line application] here to show how to set up a remote debugging session with GDB using the Yocto SDK.

Though, most of the readers are interested in using a debugger GUI this chapter is essential since most debugger GUIs for Linux, including Eclipse CDT and QtCreator, are frontends to GDB and the setup requires an understanding of how GDB works in the background

Modify the Makefile as follows:

myapp: main.cpp # $(CXX) ${CXXFLAGS} -o $@ $< $(CXX) ${CXXFLAGS} -O0 -o $@ $< # $(STRIP) $@ clean: rm -f myapp *.o *~ *.bak

Since the code is debugged with -O2 optimization, the debugger can’t cleanly relate object code to high-level source lines. That will result in problems with high-level language (C/C++ in this case) stepping (the cursor will jump around) as already discussed in [Important hints]. We add -O0 to allow proper stepping.

Further, we do not strip the debug symbols, since they are needed for debugging. This topic was also already discussed in [Important hints].

Now, we have to assure that the development host and the target device are connected to the same IP network. Check the IP address of the target device:

root@seco-mx6:/# ifconfig eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500 inet 172.20.55.89 netmask 255.255.255.0 broadcast 192.168.1.255 inet6 fde6:43f0:3520:0:3082:bc6:62be:7dcc prefixlen 64 scopeid 0x0<global> inet6 fde6:43f0:3520::729 prefixlen 128 scopeid 0x0<global> inet6 fe80::2ed7:ac9b:9049:11e1 prefixlen 64 scopeid 0x20<link> ether 00:07:8e:32:f6:72 txqueuelen 1000 (Ethernet) RX packets 2421 bytes 267143 (260.8 KiB) RX errors 0 dropped 0 overruns 0 frame 0 TX packets 185 bytes 32337 (31.5 KiB) TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0 ...

In this case 172.20.55.89 is used.

Now, recompile myapp and transfer it to the target (with scp in this case):

Note: For all the following steps the SDK environment has to be sourced.

$ source /opt/seconorth-wayland/kirkstone-7.0/environment-setup-cortexa9t2hf-neon-seconorth-linux-gnueabi $ make

If necessary, stop the automatically started demo application. This can be done from the development host with ssh:

Start the gdbserver on the device (again from the host through ssh):

Now, the gdbserver is waiting for the remote debugger to connect on the specified port 2345. The output should look like this:

Start the remote debugger out of the myapp source directory:

The embedded find command assures that the debugger can access all SDK source codes that are eventually accessed by the debug session (e.g. setpping into a library call). Every source path found in the specified directory is passed to GDB with the -p option. The source pathes inside the ELF debug information may be relative or absolute. This depends how they are passed to the compiler. So this is the only way to assure that every source path of the whole Yocto BSP is known by the debugger and every source file is found when referenced.

After executing GDB with the above command the GDB shell is entered.

Set the sysroot for the debugger, where it can find the linker and the system libraries:

Connect to the target device:

The output from the debugger should look like this:

The execution is halted at the _start entry point before main. Set a breakpoint to main and let the debugger continue execution:

The debugger will continue and the breakpoint will be hit. This should look like this:

From now on debugging is almost like using a dgb natively on the target.

The following examples demonstrate the most basic use cases applyd to the myapp example:

Show call stack:

Show the contents of a variable or more complex data type:

Step over:

List code:

Command to stop the gdbserver on the target from the host remotely, if needed:

For more information consult the GDB documentation.