xref: /haiku/docs/develop/kernel/boot/Debugging_Bootloaders_GEF.rst (revision a127b88ecbfab58f64944c98aa47722a18e363b2)
1Bootloader debugging with GEF
2=============================
3
4When Haiku’s early boot process is experiencing unknown crashes or
5faults, it can be extremely difficult to troubleshoot (especially when
6serial, video, or other i/o devices are non-functional)
7
8It **is** possible to step through the boot of any architecture of Haiku
9in a debugger if the system boots and the issue can be reproduced in
10qemu.
11
12   This works for any architecture and is *extremely* helpful to trouble
13   early platforms. Linux or Mac OS are requirements. You need a full
14   POSIX environment.
15
16Building Haiku
17--------------
18
19On most non-x86 platforms, you will need a “kernel” (haiku_loader) and
20an “initrd” (haiku_floppyboot).
21
22For arm/arm64: ``jam -q @minimum-mmc``
23
24Launching Haiku in QEMU
25-----------------------
26
27In the example below, we will prepare Haiku arm in QEMU for debugging.
28
29::
30
31   qemu-system-arm -M raspi2 -kernel haiku_loader.u-boot -initrd haiku-floppyboot.tgz.u-boot -serial stdio -m 2G -dtb rpi2.dtb -s -S
32
33**Key Flags:**
34
35-  **-s**
36
37   -  Shorthand for -gdb tcp::1234, i.e. open a gdbserver on TCP port
38      1234.
39
40-  **-S**
41
42   -  Do not start CPU at startup (you must type ‘c’ in the monitor).
43
44These simple flags will make qemu listen for a debugger connection on
45localhost:1234 and have the VM not start until you tell it to.
46
47   In the example above, we are Emulating a Raspberry Pi 2, and using
48   our Raspberry Pi 2 dtb. If you don’t have a dtb for the machine
49   you’re emulating, you can dump qemu’s internal dtb by adding
50   ``-M dumpdtb=myboard.dtb`` to the end of your qemu command.
51
52Attaching GEF
53-------------
54
55`GEF <https://github.com/hugsy/gef>`__ is an enhanced debugger which
56works extremely well for debugging code running in virtual machines. It
57piggy-backs on gdb and offers a lot of valueable insight at a glance
58without requiring to know every gdb command.
59
60Once GEF is installed, we can step through the process to attach gdb to
61qemu.
62
63Open gdb with our symbols.
64~~~~~~~~~~~~~~~~~~~~~~~~~~
65
66First we run gdb pointed at our boot loader. We use the native ELF
67binary as that seems to give gdb/gef the most accurate knowledge of our
68symbols. (the haiku_loader.u-boot is wrapped by u-boot’s mkimage, your
69milage may vary based on platform)
70
71``gdb objects/haiku/arm/release/system/boot/u-boot/boot_loader_u-boot``
72
73Set the architecture
74~~~~~~~~~~~~~~~~~~~~
75
76This may not be required, but re-enforces to gef/gdb that we’re working
77on arm.
78
79``set architecture arm``
80
81Connect to QEMU
82~~~~~~~~~~~~~~~
83
84Now we tell gdb/gef about out running (but paused) QEMU instance.
85
86``gef-remote -q localhost:1234``
87
88A successful connection should occur.
89
90Step into debugging
91~~~~~~~~~~~~~~~~~~~
92
93Before you begin execution, it’s handy to set a *breakpoint*. A
94*breakpoint* tells gdb/gef where it should pause execution to begin the
95debugging process. All of our bootloaders start in a ``start_gen``
96function, so this is a good place to start.
97
98``breakpoint start_gen``
99
100Now that a breakpoint is defined, lets run the virtual machine.
101
102In gef, type ``continue``.
103
104If everything is working as expected, you should now be “paused” at the
105``start_gen`` function (hopefully showing the C/C++ code).
106
107Now, you have a few commands to leverage:
108
109-  **step**
110
111   -  Take a single step forward and execute the code listed.
112   -  Does **not** step “into” functions, just over them getting the
113      return from the code.
114   -  Alias: s
115
116-  **stepi**
117
118   -  step forward “into” the next code.
119   -  If you’re on a function it will enter the function and show the
120      code executed.
121
122-  **break**
123
124   -  add additional “breakpoints” where you can step through the code
125      execution.
126
127-  **continue**
128
129   -  Resume execution.
130   -  If you have no additional breakpoints the code will “go do what
131      it’s supposed to”
132   -  Alias: c
133
134-  **next**
135
136   - Resume execution until it reaches the next line of code.
137   - Useful for example to run until a loop is completed, and stop at the first line after that loop.
138