Time to learn some debugging tricks

Look at recent QEMU updates - one of them is
compiling ML with debug information. So far I have only used it for translating code addresses from ML code into source code lines (addr2line). Let's see if we can enable source code debugging in GDB, so we can run the code step by step, as we would with a PC program.
Notes:
- This is the first time I'm trying this trick. I have used source code debugging in IDA + QEMU before, but that was based on decompiled code (and the free version can't do debugging if I'm not mistaken). Here I want to run ML step by step, on the original source code.
- I want the QEMU updates in the mainline, as there are some APIs for debugging ML as well (there's a PR open), which means you can merge "qemu" in your EOSM2 branch. Or, simply experiment there, and once the debugging session is over, move the changes to the "clean" branch (this is what I usually do if I need the dm-spy-experiments branch).
Enough chit-chat, let's try it:
# from ML directory
hg update qemu -C
cd platform/EOSM2.103
make clean; make
# mount the SD image
make install
Next, we have to set up a breakpoint in our code (autoexec.bin); we can do that from debugmsg.gdb.
Without debugging symbols, we would do it like this and debug the assembly code (which is not very easy):
# breakpoint on autoexec.bin
b *0x800000
To use debugging symbols in gdb, we'll have to use symbol-file (to load the symbols from an elf file). The .o files that appear when compiling ML are elf files. Also, the files without extension, "autoexec" and "magiclantern", are elf files. The first one refers to reboot.c (look it up in Makefile.src) and gets loaded where Canon's bootloader loads autoexec.bin (at AUTOEXEC_BASE = 0x800000), while the second refers to the regular ML code (starting in boot-hack.c), that gets loaded into its final location (RESTARTSTART).
Why all this trouble? Because our binary can't stay at 0x800000. How comes? Well, autoexec.bin (which is a file loaded in Canon code, probably for debugging or development purposes) wasn't meant (read: designed by Canon) to be a program to run alongside Canon's main firmware; therefore DryOS is free to use the addresses near 0x800000 (where we are loaded). So, we have to move somewhere else. More on that later.
Back to our debugging session: the issue is in reboot.c (that's where this message is printed from), so we are going to run "autoexec.bin" as a plain binary (machine code), and use "autoexec" (elf) for the debugging symbols. Add this to debugmsg.gdb:
# breakpoint on autoexec.bin (cstart)
symbol-file ../magic-lantern/platform/EOSM2.103/autoexec
b cstart
You can keep both breakpoints, as there are some other things that execute before cstart (such as checking the integrity of the binary file, to avoid executing random code when loading from a corrupted filesystem). Without further ado, let's dive in:
# from QEMU directory (assuming default paths and bash)
. ./export_ml_syms.sh EOSM2.103
./run_canon_fw.sh EOSM2,firmware="boot=1" -s -S & arm-none-eabi-gdb -x EOSM2/debugmsg.gdb
We'll hit the first breakpoint first:
Now jump to AUTOEXEC.BIN!!
...
Breakpoint 3, 0x00800000 in _start ()
=> 0x00800000 <_start+0>: 0c 40 8f e2 add r4, pc, #12
Type "continue" ("c") to reach cstart:
Breakpoint 4, cstart () at ../../src/reboot.c:215
215 int s = compute_signature((int*)SIG_START, SIG_LEN);
Type "layout src". Now you are debugging on the original source code.
Tip: you can set breakpoints like this:
b reboot.c:216
Refer to GDB manual for the
stepping commands, or use a GDB GUI.
Let's try nemiver:
. ./export_ml_syms.sh EOSM2.103
./run_canon_fw.sh EOSM2,firmware="boot=1" -s -S & nemiver --gdb-binary=$(which arm-none-eabi-gdb) --remote="localhost:1234" ../magic-lantern/platform/EOSM2.103/autoexec

For some reason, I'm unable to step. Too bad, as it seems to be working for
these guys. Maybe someone else can figure it out?
Let's try
gdbgui:
. ./export_ml_syms.sh EOSM2.103
./run_canon_fw.sh EOSM2,firmware="boot=1" -s -S & gdbgui -g "arm-none-eabi-gdb"
Make sure you view its GUI with Google Chrome and enter this at the gdb prompt:
source EOSM2/debugmsg.gdb

This one appears to work a little better, you can run the program step by step using the GUI, but still gives a bunch of errors. Go figure.
cgdb is a terminal-based GUI, but doesn't like QEMU printing debug messages on the same window. Fortunately, nkls provided a script to split the terminal window in two - splitgdb.sh. Replace its contents with something like this:
#!/usr/bin/env bash
. ./export_ml_syms.sh $1.$2
tmux new-session -d "./run_canon_fw.sh $1,firmware='boot=1' -s -S"
tmux split-window -h "cgdb -d arm-none-eabi-gdb -x $1/debugmsg.gdb"
tmux attach-session -d
./splitgdb.sh EOSM2 103

The user interface seems to be very rough though, and it doesn't like our colored debug messages either...
Let's try the "classic" ddd:
. ./export_ml_syms.sh EOSM2.103
./run_canon_fw.sh EOSM2,firmware="boot=1" -s -S & ddd --debugger "arm-none-eabi-gdb -x EOSM2/debugmsg.gdb"
This works. The interface is not pretty, but at least it works.
(I've ran EOSM ML on EOSM2 ROM, in case you are wondering)

Other suggestions?