docs/develop: Import oco's article on profiling applications

- Create a new "debugging" section and move two other articles there as
  well
This commit is contained in:
Adrien Destugues
2025-02-27 13:31:53 +01:00
parent b20e1e7e6a
commit e1bdecd0d7
10 changed files with 104 additions and 2 deletions
@@ -1,137 +0,0 @@
Bootloader debugging with GEF
=============================
When Haikus early boot process is experiencing unknown crashes or
faults, it can be extremely difficult to troubleshoot (especially when
serial, video, or other i/o devices are non-functional)
It **is** possible to step through the boot of any architecture of Haiku
in a debugger if the system boots and the issue can be reproduced in
qemu.
This works for any architecture and is *extremely* helpful to trouble
early platforms. Linux or Mac OS are requirements. You need a full
POSIX environment.
Building Haiku
--------------
On most non-x86 platforms, you will need a “kernel” (haiku_loader) and
an “initrd” (haiku_floppyboot).
For arm/arm64: ``jam -q @minimum-mmc``
Launching Haiku in QEMU
-----------------------
In the example below, we will prepare Haiku arm in QEMU for debugging.
::
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
**Key Flags:**
- **-s**
- Shorthand for -gdb tcp::1234, i.e. open a gdbserver on TCP port
1234.
- **-S**
- Do not start CPU at startup (you must type c in the monitor).
These simple flags will make qemu listen for a debugger connection on
localhost:1234 and have the VM not start until you tell it to.
In the example above, we are Emulating a Raspberry Pi 2, and using
our Raspberry Pi 2 dtb. If you dont have a dtb for the machine
youre emulating, you can dump qemus internal dtb by adding
``-M dumpdtb=myboard.dtb`` to the end of your qemu command.
Attaching GEF
-------------
`GEF <https://github.com/hugsy/gef>`__ is an enhanced debugger which
works extremely well for debugging code running in virtual machines. It
piggy-backs on gdb and offers a lot of valueable insight at a glance
without requiring to know every gdb command.
Once GEF is installed, we can step through the process to attach gdb to
qemu.
Open gdb with our symbols.
~~~~~~~~~~~~~~~~~~~~~~~~~~
First we run gdb pointed at our boot loader. We use the native ELF
binary as that seems to give gdb/gef the most accurate knowledge of our
symbols. (the haiku_loader.u-boot is wrapped by u-boots mkimage, your
milage may vary based on platform)
``gdb objects/haiku/arm/release/system/boot/u-boot/boot_loader_u-boot``
Set the architecture
~~~~~~~~~~~~~~~~~~~~
This may not be required, but re-enforces to gef/gdb that were working
on arm.
``set architecture arm``
Connect to QEMU
~~~~~~~~~~~~~~~
Now we tell gdb/gef about out running (but paused) QEMU instance.
``gef-remote -q localhost:1234``
A successful connection should occur.
Step into debugging
~~~~~~~~~~~~~~~~~~~
Before you begin execution, its handy to set a *breakpoint*. A
*breakpoint* tells gdb/gef where it should pause execution to begin the
debugging process. All of our bootloaders start in a ``start_gen``
function, so this is a good place to start.
``breakpoint start_gen``
Now that a breakpoint is defined, lets run the virtual machine.
In gef, type ``continue``.
If everything is working as expected, you should now be “paused” at the
``start_gen`` function (hopefully showing the C/C++ code).
Now, you have a few commands to leverage:
- **step**
- Take a single step forward and execute the code listed.
- Does **not** step “into” functions, just over them getting the
return from the code.
- Alias: s
- **stepi**
- step forward “into” the next code.
- If youre on a function it will enter the function and show the
code executed.
- **break**
- add additional “breakpoints” where you can step through the code
execution.
- **continue**
- Resume execution.
- If you have no additional breakpoints the code will “go do what
its supposed to”
- Alias: c
- **next**
- Resume execution until it reaches the next line of code.
- Useful for example to run until a loop is completed, and stop at the first line after that loop.
-2
View File
@@ -10,5 +10,3 @@ Kernel
/kernel/vm/swap_file_support
/kernel/arch/index
/kernel/boot/boot_process_specs.rst
/kernel/boot/Debugging_Bootloaders_GEF
/kernel/pci_serial_debug
-68
View File
@@ -1,68 +0,0 @@
Using PCI serial ports for debugging
====================================
Modern systems usually don't come with a built-in serial port anymore. This
is unconvenient for low level debugging, since the serial port allows access
to early boot log as well as kernel debugger, even when the display or keyboard
are not working.
It is fortunately possible to add a serial port over the PCI bus on machines
which have appropriate expansion ports. This can be done using expresscard,
mini-PCI, or PCI express ports.
Devices known to work
---------------------
Dexlan XMT01A (https://www.accessoires-informatiques.com/Prix/EXPRESSCARD-PCIE-POUR-PORTABLE-23842.html)
Uses MOSCHIP 9922 controller
Devices to be tested
--------------------
https://smile.amazon.com/Industrial-Desktop-Bracket-Moschip-MCS9922/dp/B003D3MFHM/
Configuring
-----------
- Install the card in your computer
- Boot Haiku and look in the syslog for the PCI bus scan for the device:
.. code-block:: text
KERN: PCI: [dom 0, bus 5] bus 5, device 0, function 0: vendor 9710, device 9922, revision 00
KERN: PCI: class_base 07, class_function 00, class_api 02
KERN: PCI: vendor 9710: MosChip Semiconductor Technology Ltd.
KERN: PCI: device 9922: MCS9922 PCIe Multi-I/O Controller
KERN: PCI: info: Communication controller (Serial controller, 16550)
KERN: PCI: line_size 10, latency 00, header_type 80, BIST 00
KERN: PCI: ROM base host 00000000, pci 00000000, size 00000000
KERN: PCI: cardbus_CIS 00000000, subsystem_id 1000, subsystem_vendor_id a000
KERN: PCI: interrupt_line 0b, interrupt_pin 01, min_grant 00, max_latency 00
KERN: PCI: base reg 0: host 00004000, pci 0000KERN: 4000, size 00000008, flags 01
KERN: PCI: base reg 1: host f1c01000, pci f1c01000, size 00001000, flags 00
KERN: PCI: base reg 2: host 00000000, pci 00000000, size 00000000, flags 00
KERN: PCI: base reg 3: host 00000000, pci 00000000, size 00000000, flags 00
KERN: PCI: base reg 4: host 00000000, pci 00000000, size 00000000, flags 00
KERN: PCI: base reg 5: host f1c00000, pci f1c00000, size 00001000, flags 00
KERN: PCI: Capabilities: MSI, PM, PCIe
KERN: PCI: Extended capabilities: Virtual Channel, Advanced Error Reporting
Write down the address of "base reg 0", this is where the serial port registers
are mapped (it is probably possible to get this information from lspci on Linux
as well?)
Configure serial debug in config/settings/kernel/drivers/kernel:
.. code-block:: text
serial_debug_output true
serial_debug_speed 115200
serial_debug_port 0x4000
Now your kernel is configured to send its output to the serial port. You can
connect another machine to it (using an USB to serial adapter and a NULL modem
cable, for example) and use SerialConnect or a similar tool to see the output
and access the KDL prompt.
Happy debugging!