mirror of
https://source.denx.de/u-boot/u-boot.git
synced 2025-12-21 17:32:09 +01:00
Our last sync with the kernel was 5.1. Even that was a partial one as some patches from 4.x kernels were already missing making the transition to a modern kbuild infeasible. We are so out of sync now, that tracking the patches and backporting them one by one makes little sense and it's going to take ages. This is an attempt to sync up Makefile[.lib/.kbuild]. Unfortunately due to sheer amount of patches this is not easy to review, but that's what we decided during a community call. One of the biggest changes is get rid of partial linking entirely and build .a archives isntead of .o. We diaviate from the kernel on that. Instead of calling a custom script to create the archive symbol table, we call ar with rcTP (isntead of rcSTP) since we want a resulting archive that's sauble with the linker. The only affected platforms are PPC ones. Unfortunately I don't have any of them around to test, but the objdump of the resulting files -- arch/powerpc/lib/built-in.[oa] looks identical. Signed-off-by: Ilias Apalodimas <ilias.apalodimas@linaro.org>
185 lines
6.6 KiB
ReStructuredText
185 lines
6.6 KiB
ReStructuredText
.. SPDX-License-Identifier: GPL-2.0+
|
|
.. Copyright (c) 2020 Heinrich Schuchardt
|
|
|
|
Analyzing crash dumps
|
|
=====================
|
|
|
|
When the CPU detects an instruction that it cannot execute it raises an
|
|
interrupt. U-Boot then writes a crash dump. This chapter describes how such
|
|
dump can be analyzed.
|
|
|
|
Creating a crash dump voluntarily
|
|
---------------------------------
|
|
|
|
For describing the analysis of a crash dump we need an example. U-Boot comes
|
|
with a command :doc:`exception <../usage/cmd/exception>` that comes in handy
|
|
here. The command is enabled by::
|
|
|
|
CONFIG_CMD_EXCEPTION=y
|
|
|
|
The example output below was recorded when running qemu\_arm64\_defconfig on
|
|
QEMU::
|
|
|
|
=> exception undefined
|
|
"Synchronous Abort" handler, esr 0x02000000
|
|
elr: 00000000000101fc lr : 00000000000214ec (reloc)
|
|
elr: 000000007ff291fc lr : 000000007ff3a4ec
|
|
x0 : 000000007ffbd7f8 x1 : 0000000000000000
|
|
x2 : 0000000000000001 x3 : 000000007eedce18
|
|
x4 : 000000007ff291fc x5 : 000000007eedce50
|
|
x6 : 0000000000000064 x7 : 000000007eedce10
|
|
x8 : 0000000000000000 x9 : 0000000000000004
|
|
x10: 6db6db6db6db6db7 x11: 000000000000000d
|
|
x12: 0000000000000006 x13: 000000000001869f
|
|
x14: 000000007edd7dc0 x15: 0000000000000002
|
|
x16: 000000007ff291fc x17: 0000000000000000
|
|
x18: 000000007eed8dc0 x19: 0000000000000000
|
|
x20: 000000007ffbd7f8 x21: 0000000000000000
|
|
x22: 000000007eedce10 x23: 0000000000000002
|
|
x24: 000000007ffd4c80 x25: 0000000000000000
|
|
x26: 0000000000000000 x27: 0000000000000000
|
|
x28: 000000007eedce70 x29: 000000007edd7b40
|
|
|
|
Code: b00003c0 912ad000 940029d6 17ffff52 (e7f7defb)
|
|
Resetting CPU ...
|
|
|
|
resetting ...
|
|
|
|
The first line provides us with the type of interrupt that occurred.
|
|
On ARMv8 a synchronous abort is an exception thrown when hitting an unallocated
|
|
instruction. The exception syndrome register ESR register contains information
|
|
describing the reason for the exception. Bit 25 set here indicates that a 32 bit
|
|
instruction led to the exception.
|
|
|
|
The second line provides the contents of the elr and the lr register after
|
|
subtracting the relocation offset. - U-Boot relocates itself after being
|
|
loaded. - The relocation offset can also be displayed using the bdinfo command.
|
|
|
|
After the contents of the registers we get a line indicating the machine
|
|
code of the instructions preceding the crash and in parentheses the instruction
|
|
leading to the dump.
|
|
|
|
Analyzing the code location
|
|
---------------------------
|
|
|
|
We can convert the instructions in the line starting with 'Code:' into mnemonics
|
|
using the objdump command. To make things easier scripts/decodecode is
|
|
supplied::
|
|
|
|
$echo 'Code: b00003c0 912ad000 940029d6 17ffff52 (e7f7defb)' | \
|
|
CROSS_COMPILE=aarch64-linux-gnu- ARCH=arm64 scripts/decodecode
|
|
Code: b00003c0 912ad000 940029d6 17ffff52 (e7f7defb)
|
|
All code
|
|
========
|
|
0: b00003c0 adrp x0, 0x79000
|
|
4: 912ad000 add x0, x0, #0xab4
|
|
8: 940029d6 bl 0xa760
|
|
c: 17ffff52 b 0xfffffffffffffd54
|
|
10:* e7f7defb .inst 0xe7f7defb ; undefined <-- trapping instruction
|
|
|
|
Code starting with the faulting instruction
|
|
===========================================
|
|
0: e7f7defb .inst 0xe7f7defb ; undefined
|
|
|
|
Now lets use the locations provided by the elr and lr registers after
|
|
subtracting the relocation offset to find out where in the code the crash
|
|
occurred and from where it was invoked.
|
|
|
|
File u-boot.map contains the memory layout of the U-Boot binary. Here we find
|
|
these lines::
|
|
|
|
.text.do_undefined
|
|
0x00000000000101fc 0xc cmd/built-in.a
|
|
.text.exception_complete
|
|
0x0000000000010208 0x90 cmd/built-in.a
|
|
...
|
|
.text.cmd_process
|
|
0x00000000000213b8 0x164 common/built-in.a
|
|
0x00000000000213b8 cmd_process
|
|
.text.cmd_process_error
|
|
0x000000000002151c 0x40 common/built-in.a
|
|
0x000000000002151c cmd_process_error
|
|
|
|
So the error occurred at the start of function do\_undefined() and this
|
|
function was invoked from somewhere inside function cmd\_process().
|
|
|
|
If we want to dive deeper, we can disassemble the U-Boot binary::
|
|
|
|
$ aarch64-linux-gnu-objdump -S -D u-boot | less
|
|
|
|
00000000000101fc <do_undefined>:
|
|
{
|
|
/*
|
|
* 0xe7f...f. is undefined in ARM mode
|
|
* 0xde.. is undefined in Thumb mode
|
|
*/
|
|
asm volatile (".word 0xe7f7defb\n");
|
|
101fc: e7f7defb .inst 0xe7f7defb ; undefined
|
|
return CMD_RET_FAILURE;
|
|
}
|
|
10200: 52800020 mov w0, #0x1 // #1
|
|
10204: d65f03c0 ret
|
|
|
|
This example is based on the ARMv8 architecture but the same procedures can be
|
|
used on other architectures as well.
|
|
|
|
Crashs in UEFI binaries
|
|
-----------------------
|
|
|
|
If UEFI images are loaded when a crash occurs, their load addresses are
|
|
displayed. If the process counter points to an address in a loaded UEFI
|
|
binary, the relative process counter position is indicated. Here is an
|
|
example executed on the U-Boot sandbox::
|
|
|
|
=> load host 0:1 $kernel_addr_r buggy.efi
|
|
5632 bytes read in 0 ms
|
|
=> bootefi $kernel_addr_r
|
|
Booting /buggy.efi
|
|
Buggy world!
|
|
|
|
Segmentation violation
|
|
pc = 0x19fc264c, pc_reloc = 0xffffaa4688b1664c
|
|
|
|
UEFI image [0x0000000019fc0000:0x0000000019fc6137] pc=0x264c '/buggy.efi'
|
|
|
|
The crash occured in UEFI binary buggy.efi at relative position 0x264c.
|
|
Disassembly may be used to find the actual source code location::
|
|
|
|
$ x86_64-linux-gnu-objdump -S -D buggy_efi.so
|
|
|
|
0000000000002640 <memset>:
|
|
2640: f3 0f 1e fa endbr64
|
|
2644: 48 89 f8 mov %rdi,%rax
|
|
2647: 48 89 f9 mov %rdi,%rcx
|
|
264a: eb 0b jmp 2657 <memset+0x17>
|
|
264c: 40 88 31 mov %sil,(%rcx)
|
|
|
|
Architecture specific details
|
|
-----------------------------
|
|
|
|
ARMv8
|
|
~~~~~
|
|
|
|
On the ARM 64-bit architecture CONFIG_ARMV8_SPL_EXCEPTION_VECTORS controls
|
|
if the exception vector tables are set up in the Secondary Program Loader (SPL).
|
|
Without initialization of the tables crash dumps cannot be shown. The feature is
|
|
disabled by default on most boards to reduce the size of the SPL.
|
|
|
|
RISC-V
|
|
~~~~~~
|
|
|
|
On the RISC-V architecture CONFIG_SHOW_REGS=y has to be specified to show
|
|
all registers in crash dumps.
|
|
|
|
Sandbox
|
|
~~~~~~~
|
|
|
|
The sandbox U-Boot binary must be invoked with parameter *-S* to display crash
|
|
dumps:
|
|
|
|
.. code-block:: bash
|
|
|
|
./u-boot -S -T
|
|
|
|
Only with CONFIG_SANDBOX_CRASH_RESET=y the sandbox reboots after a crash.
|