GUF-Yocto-jethro-9.0-r7707-0
i.MX6
User Manual
11
Debugging
11.1
Important hints
Before starting debugging several important topics have to be discussed.
11.1.1 The debugger needs access to the debug symbols
When the debugger is instructed to set a breakpoint on e.g. a function
foo
, it needs to look up which address
corrsponds to that
symbol
. This and some further informmation is encoded into the compile output artifact, no
matter if it is an executable, a shared library/object, the Linux kernel or a kernel module.
The compiler can be instructed to add debug info by adding the compile flag
-g
or even better for debugging with
GDB with
-ggdb
that adds some more GDB specific debug info.
Further, the debug info doesn’t need to be included to just execute the above stated artifacts without debugging.
Moreover, for Linux BSPs, it’s a common practice to compile the whole BSP with
-g
first and then remove that
symbols before installation on the target system to reduce memory footprint drastically while keeping a untouched
copy inside the BSP and/or the SDK on the development host for debugging purposes. Otherwise, the debug
symbols consume a lot of disk space on the target device. This process is known as
stripping
and it is done
by a tool called
<compiler-prefix>-strip
. So it’s reasonable, that native debugging on the target device is not
possible without further steps to make the symbols available to the debugger.
11.1.2 The debugger needs access to the source files
Apart from the symbols, the debugger needs to have access to the source code belonging to the components
beeing debugged. This is needed to step through the various source lines as they were in your code editor.
Likewise, it wouldn’t make sense to istall source code on the target device, since it is not needed for normal
operation and would consume a lot of disk space.
11.1.3 Optimization compiler flags destroy high level language code stepping
Optimization prevents the debugger from relating the high level lines of code to their assembler counterparts
because optimization e.g. eliminates duplicated assembler sequences and instead, introduces jumps and returns
to already existing ones. The one to one relation between C/C++ source to assembler code gets lost.
To be able to step properly through high level code lines it’s necessary to compile the code to be degugged with
-O0
optimization.
This is an easy task for code compiled outside the BSP with the SDK such as a custom application. But almost
all of the already built BSP components are compiled with
-O2
. That means, if a library function such as
printf
is
called from the custom application and the developer wants to step into printf with the debugger, she/he will find
the debuger jumping on weird C/C++ code lines inside
printf
function though it’s own application is compiled with
-O0
.
The only way to overcome this issue is to compile the BSP by yourself and set
-O0
compilation on the component
recipes of interest. This is beyond the scope of this manual and not recommended to do by yourself until she/he
is familar with Yocto BSP devlopment.
The same issue applies to the Linux kernel and external compiled modules. The kernel can’t be compiled entirely
with
-O0
since some parts relay on optimization. Instead, the developer has to set the optimization flag for the
driver/subsystem of intersest in the submakefile.
11.1.4 The symbol files have to originate from the same compile run as their installed stripped counter-
parts on the target system
This is obvious but a common mistake. If a binary is recompiled and we need a stripped and a unstripped copy
the unstripped counterparts have to be reinstalled on the target.
66