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:
Code Block |
---|
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.
...
Code Block |
---|
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 |
---|
Note: For all the following steps the SDK environment has to be sourced. |
...
If necessary, stop the automatically started demo application. This can be done from the development host with ssh:
Code Block |
---|
$ ssh root@172.20.55.89 'systemctl stop seco-show-demo' |
Start the gdbserver on the device (again from the host through ssh):
Code Block |
---|
$ ssh root@172.20.55.89 'gdbserver :2345 /tmp/myapp' & |
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:
Code Block |
---|
$ arm-guf-linux-gnueabi-gdb `find /opt/seconorth-wayland/kirkstone-7.0/sysroots/cortexa9t2hf-neon-seconorth-linux-gnueabi/usr/src/debug -type d -printf '-d %p '` -d $PWD myapp |
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.
...
The execution is halted at the _start entry point before main. Set a breakpoint to main and let the debugger continue execution:
...
The following examples demonstrate the most basic use cases applyd to the myapp example:
Show call stack:
Code Block |
---|
(gdb) bt #0 main (argc=1, argv=0x7efffe14) at main.cpp:7 |
...