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 relationship between the 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 debugged 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 debugger jumping on weird C/C++ code lines inside the printf function through its 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 familiar with Yocto BSP development.
The same issue applies to the Linux kernel and external compiled modules. The kernel can’t be compiled entirely with -O0 since some parts rely on optimization. Instead, the developer has to set the optimization flag for the driver/subsystem of interest in the sub make file.