--- /dev/null
+= GDB
+
+== Overview
+
+Of course, gdb is the debugger to use for some programs compiled with gcc (the GNU Compiler Collection). Support is best for
+C and C++, and only C concerns us for FreeRADIUS.
+
+When a test fails you'll see something like this in the output, a command line showing how to run the test (with -xx for added debugging output):
+
+[source,shell]
+----
+./build/make/jlibtool --silent --timeout=300 --mode=execute ./build/bin/local/unit_test_attribute -F ./src/tests/fuzzer-corpus -D share/dictionary -d ./src/tests/unit -r "build/tests/units/data_types.txt" src/tests/unit/data_types.txt -xx
+----
+
+To run the test under gdb, tell jlibtool to run gdb, which in turn will run and pass options on to `unit_test_attribute`. Keep the `-xx` if you wish, but definitely omit the `--timeout=300`.
+
+[source,shell]
+----
+TZ=GMT build/make/jlibtool --silent --mode=execute gdb --args ./build/bin/local/unit_test_attribute -F ./src/tests/fuzzer-corpus -D ./share/dictionary -d ./src/tests/unit -r "build/tests/unit/data_types.txt" src/tests/unit/data_types.txt
+----
+
+Like lldb, gdb provides access to Python. One can define a class that adds a command to gdb. Here's the schema:
+
+[source,python]
+----
+import gdb
+
+# Python source code that must include a class definition like this:
+
+class newCmd (gdb.Command):
+ """comment that will be displayed if the user types "help <command name>""""
+
+ def __init__ (self):
+ # Kicks it upstairs. The first parameter is the command name
+ # We intend the user to type this command, hence the choice
+ # of second parameter.
+ super (DD, self).__init__ ("newcmd", gdb.COMMAND_USER)
+
+ def invoke (self, arg, from_tty):
+ # Code that actually performs the new command.
+ # from_tty is Boolean, true iff the user entered it at a terminal
+
+newCmd () # Actually create an instance
+----
+
+invoke will typically include calls to methods like `gdb.parse_and_eval(),` which takes a Python string, parses it as appropriate for the source language, and evaluates it, returning a corresponding gdb.Value, from which you can get information like its type. (lldb classes for Python extensions tend to have a member indicating validity, so the methods always return a value of the expected type,
+and set that validity member to indicate whether the invocation succeeded. gdb throws exceptions instead.)
+
+For our immediate purpose, calling existing FreeRADIUS functions to display data structures in a consistent fashion, we build up the command and use the gdb `run` command, because the functions themselves write to stderr.
+
+Before using the new command, gdb will have to execute the commmand
+
+[source]
+----
+source <path of file containing the class definition>
+----
+
+One can autoload Python scripts, and we may wish to do that.
+
+After that, you can type `newcmd foo` and the command will run.
+
+==References
+
+* https://sourceware.org/gdb/current/onlinedocs/gdb.html/Python.html#Python [The "Extending GDB using Python" section of Debugging with GDB]
+* https://interrupt.memfault.com/blog/automate-debugging-with-gdb-python-api ["Automate Debugging with GDB Python API" from Interrupt by Memfault] The first section is about writing prettypriters, which isn't of interest to us. Later they get into adding custom gdb commands with Python, our current interest.