Many users need to debug code from source level. This blog describes how to use Arm Development Studio (Arm DS) to debug the Arm Trust Firmware (ATF), U-boot, and Linux Kernel on the Juno-r2 platform at the source level.
In this blog post, we assume that the Trust Firmware, U-boot, and Linux kernel images are already uploaded to the SD-card storage on the Juno-r2 board, as the following figure shows:
The primary CPU after reset is Cortex-A53_0. Other cores 2 Cortex-A72, 3 Cortex-A53 are in powerdown state, as the following figure shows:
The version of Arm DS is 2023.0. In Arm DS, to set up the Juno-r2 connection, click the Connect Only option like the following figure shows:
This blog post describes the debug skills in the following topics:
When the debugger connects to the target and stops the CPU running, it halts at ATF BL1 at EL3. If you want to debug the BL1, you must add the symbol file, bl1.elf, to the debugger like the following figure shows:
If the debugger and the source code are on different Host machines you must set up a path mapping for the debugger to locate the source code. This blog post describes the example where the Arm DS runs on a Windows system, but the source code is on a Ubuntu system. Therefore, you must set up a mapping Z: disk to access the source code by using Samba service, as the figure shows:
The following figure shows you the source code on the Arm DS Window View. You can debug the code from source level.
Make sure that the Symbol Loading EL and the Code running EL are at the same address space. For example, when the CPU is stopped at EL3 and you want to add the BL2 Symbol file to the debugger, you must add an offset EL1S:0x0 with the EL1S: prefix:
The EL1S: prefix is added because the BL2 runs at EL1S. If you do not add the EL1S: prefix, the debugger loads the symbol file at the current EL address space, EL3.
The offset EL3:0x0 is needed when loading the BL31 symbol file, because BL31 runs at EL3 while BL2 runs at EL1S.
If you want to debug the U-boot that runs at EL2N address space, you do not need to add the prefix offset when the CPU is stopped at EL2, as the figure shows:
During the U-boot execution, the U-boot does the relocation of code section and data section. Therefore, you must reload the symbol file to the debugger with the correct offset that U-boot is going to use.
On the Juno-r2 platform, you can see the offset value 0x000000001ef6e000 with the U-boot command bdinfo as the following figure shows:
Therefore, you add the Symbol file u-boot with the offset value EL2N:0x1ef6e000.
Running the U-boot command printenv shows you the kernel load address is 0x80080000. The kernel entry address is 0xffffff8010080000, and you must add the symbol file, vmliux, with the offset 0x80700000000, 0x80080000-0xffffff8010080000. The figure shows this:
The following figure shows you can view and debug from the assembly code at EL2N address space now.
There is an EL switch from EL2 to EL1, so you must add the symbol file again with the same offset value after the kernel is switched to EL1.
As shown in the following figure, you can view and debug from the assembly code at EL1N address space.
There is an MMU mapping from physical address space to virtual address space. Therefore, you must add the symbol file again without the offset value after the MMU is enabled.
As shown in the following figure, you can view and debug the code from source level at EL1N address space.
For more information about debugging the Armv8-A Linux Kernel with DS-5, see the blog Debugging the Armv8-A Linux Kernel with DS-5.
There are some differences between Arm DS debugging on the Juno-r2 hardware platform and debugging on the FVP: