
Debugging Firmware with GDB - fra
https://interrupt.memfault.com/blog/gdb-for-firmware-1
======
AdmiralAsshat
I used to work on a legacy piece of business software, written mostly in C.
One recurring issue we noticed about GDB was that compiling a "debug" version
of the binary to be able to GDB it often fixed whatever problem the program
was having, such that we were no longer able to reproduce the issue. So it
wasn't uncommon for me to have this conversation with my manager:

Me: Customer is having their program X hit a SEGFAULT when they run it.

Manager: Did you transfer over a GDB version to backtrace the core dump?

Me: Yep.

Manager: What did it say?

Me: Well, when I run the same series of steps through the GDB version, it
doesn't segfault, so I have nothing to backtrace.

Manager: Huh...

Me: What would you like me to do?

Manager: Move the production binary aside, drop in the GDB version. Leave it
there.

~~~
dbcurtis
You have uninitialized variables.

If you run debug builds, the compiler fetches an uninitialized variable out of
memory that the OS nicely zeroed before it gave it to the process. If you run
even the simplest optimizer, it will say: "Well, obviously, no one cares what
this variable starts with, because they didn't initialize it. So let's just
use the garbage value left over in this free-at-the-moment register." Expunge
your uninitialized variables, and _then_ show me the disassembly code that the
compiler got wrong. (Once upon a time I managed a piece of the validation for
a C/C++/FORTRAN compiler suite. I have had this conversation more than once.
:)

Exception: Real-time code with timing-specific hardware interactions. But that
isn't an optimizer bug, that's a design issue.

~~~
monocasa
There's all sorts of other things that can hard fault a release build and not
a debug build.

~~~
dbcurtis
Yes, yes. Very true, optimizers can break in interesting ways. And yet, 99.9%
of the time when some whiner says: “The optimzer broke my software!” it is an
uninitialized variable.

The other 0.1% of failures kept my team busy enough. But I never allocated any
time to your problem until you proved that you had no uninitialized variables.

------
equalunique

      In this post, we’ll walk through setting up GDB for the following environment:
    
          A Nordic nRF52840 development kit
    

Hoping this guide will be a useful reference for diving into the QMK[0] port
to nRF52840 by Sekigon[1]. Scratch-built keyboards are my hobby and it would
be nice to have something beefier than an atmega32u4 handling both the
keymap/layout and bluetooth.

[0] [https://docs.qmk.fm/](https://docs.qmk.fm/)

[1] [https://github.com/sekigon-
gonnoc/qmk_firmware](https://github.com/sekigon-gonnoc/qmk_firmware)

~~~
fra
Good luck! I'm a big fan of the nRF52840! It's a great fit for a BT+USB
keyboard. Hit us up in the blog post comments if you struggle with following
Mohammad's instructions.

------
tyhoff
What I want, and what I think GDB really needs for people to use its Python
API's more frequently, is a way to easily manage, share, install, and
collaborate with other people's .gdbinit and GDB Python scripts.

I've written a number of these at my previous companies, which all get loaded
by default when any developer was debugging (basically wrapping gdb in a 'make
gdb' style call). That works for internal development at a company where
everyone is using the same flow, but that's nearly impossible in the real
world as every one has a different setup.

I'm assuming numerous companies have written a Linked List GDB Printer (such
as [https://github.com/chrisc11/debug-
tips/blob/master/gdb/pytho...](https://github.com/chrisc11/debug-
tips/blob/master/gdb/python-linked-list.md)) or a script that prints useful
information from the global variables particular to the RTOS running. These
are all great, but they are a pain to install.

Is there really no better way to share these across the Internet other than
"Copy / Paste this text into your .gdbinit"? I'm thinking it would be possible
and relatively painless to share these scripts through PyPi, require them, and
load them like a normal package, but I haven't seen this approach taken.

------
scoutt
With modern JTAG probes and available software (like GDB or OpenOCD) it's
unthinkable going back to debugging with SW emulators, in-circuit emulators or
with bare LEDs or a serial port (sometimes you have none).

Being able to debug firmware is very important to me, up to the point that the
fact a chip (or family) is supported by OpenOCD becomes a determining factor
when choosing a component for a new project. Specially if the project is (or
could be) open sourced.

I don't like proprietary debuggers. If a chip requires or forces me or my
company to purchase Segger XYZ probe or a custom IDE, then it's not discarded
right away, but back to the bottom of the pile.

When there is no alternative, I find myself writing OpenOCD flash drivers even
before starting any FW development.

------
Circuits
who needs GDB when you have the good old fashion print statement... O.o

~~~
emidln
At my first job, we didn't have GDB or a console, but you could set a test
point high. In the worst case, you attached an LED. In the best case, you
maybe had a scope handy to log the data.

~~~
danbolt
In the games industry, I worked with an older programmer that developed games
on the Sega Genesis back in the 90s. He said often changing the background
colour[1] was the "simplest" way of debugging state or branches.

[1]
[https://segaretro.org/Sega_Mega_Drive/Palettes_and_CRAM#Back...](https://segaretro.org/Sega_Mega_Drive/Palettes_and_CRAM#Background_colour)

~~~
unwind
In my youth, us Amiga demoscene coders used this method too. You could
basically measure CPU consumption by some sub-routine by setting a particular
color on entry, then resetting on exit. Basically "raster lines" became a
measure of time.

Pretty sure I optimized by putting a piece of tape at the exit line on the TV,
then trying to make the color bar more narrow. :)

