This week was busy.
I helped co-teach an improv rehearsal while my coach was away, spontaneously went to see a movie with friends, finished some good books (Debugging by David Agans and How to Read A Book by Mortimer J. Adler), and wrote the entirety of a rough program in a day that converted numbers between base 2, 10, and 16, or as their familiar names are called, binary, decimal, and hexadecimal. I wrote it for the purpose of re-familiarizing myself with the Forth language, since I haven’t written a program with Forth in a while. About a quarter of the way through, the program turned out to be a funny talk-show-like system with cheesy jokes and puns. You can check it out on GitHub. Forth is an awesome interactive language, you can check it out here with the official online book by Leo Brodie, Starting Forth. I’ll write a bigger post on Forth later, today I’m sharing my debugging issues and talking about a system emulator called QEMU.
Once I finished my Forth conversion program, I took a break, but eventually gravitated towards finishing an old assembly program I wrote a while back that converted an array of fahrenheit values to celsius. I had finished it, but unfortunately, lost all my work when I accidentally wiped the contents of my computer (which is a story for another time). I used QEMU to debug it at the time, but I lost my debugging log along with the wipe, sadly.
QEMU is a downloadable, open source, full system emulator. You can use it to emulate types of processor cores/CPUs, machines, or OSs all without having to own the actual device. It’s handy when you don’t have the money to buy an actual microcontroller, and you can run it straight from your terminal.
I finished rewriting my program in ARM assembly and geared up to debug my messy, night-time written code, until the qemu commands I had recovered suddenly failed. I was executing:
qemu-system-arm -machine raspi2 -cpu cortex-m3 -s -S -nographic -kernel -gdb tcp::1234 f-c2.elf
First I got the error:
qemu-system-arm: -kernel -gdb: Unknown protocol 'tcp'
WARNING: Image format was not specified for 'f-c2.elf' and probing guessed raw.
Automatically detecting the format is dangerous for raw images, write operations on block 0 will be restricted.
Specify the 'raw' format explicitly to remove the restrictions.
qemu: could not load kernel '-gdb'
I added -raw
, but all I got back with that command was a terminal prompt. I consulted my friend uelen (way-len) who knows more about QEMU than I do (something I hope to change in the future).
He shared that -s
did the same thing as -gdb tcp::1234
so that was all redundant. I ended up deleting -raw
as well.
I reformulated my qemu execution to end up with:
qemu-system-arm -machine raspi2 -cpu cortex-m3 -s -S -nographic -kernel f-c2.elf
And it worked!
I ran that in a terminal, and in another, I connected the trusty GDB debugger to my emulated system with target remote localhost:1234
.
GDB has been a bit of a stinker since then, and I haven’t been able to debug my code because it’s been sending random addresses to the program counter and jumping to pieces of code that don’t even exist (I guess this code exists, though, must’ve come from the 4th dimension or something). I spent most of today working on it, but only got so far with hardly any leads.
Somehow my program’s first instruction, mov r0, #16
, loads #12
into the link register, and random addresses are put into the program counter. I made sure that there were no addresses in r0
when the program started, so there’s no way I could somehow be moving anything into the PC or LR. I made sure it failed like that multiple times so I can accurately state that. But as David Agans says in his amazing book, Debugging, even “that” can happen, when you know it can’t.
All that to say, debugging is long and challenging, especially with things you’re not horribly familiar with yet. After spending much of my day attempting to find out gdb’s mysteries, I am retiring to my happy place, reading books and working with some Forth.
But before I leave, TIL! (Today I Learned)
TIL to really apply the concepts I learned in Debugging by David Agans, from changing one thing at a time, to keeping an audit trail, to quit thinking and just looking (I think I used that rule the most).
I learned that when you get an error for the 504th time, it’s not the end of the world.
TIL that sharing source code is really fun and really freaky at the same time, because on one end you’re thinking, “oh my goodness griefcious they’re totally going to judge my code and think I’m stupid for writing it this way instead of that way!” while on the other hand, you’re thinking “LOOK AT THIS LITTLE BABY PROGRAM I MADE ISN’T IT GREAT?” When in reality no one intensively looks at it and only tries to help figure out your problem. (those who do judge your code are either trying to help you but are unintentionally coming off as stand-offish, or they are just deciding to be turd blossoms.)
I learned that sometimes, it’s okay to pause from figuring out a problem to eat some chips and fruit while you ponder your existence and if it’s really worth it to figure this problem out.
I learned that it’s good to ask for help when you have no idea where to start looking to find out why your system emulator is being finicky (QEMU User Documentation, I’m looking at you).
And finally, TIL that making sure you recompile your altered code before running it again is a really good idea.
Until next time, folks!