Debugging with GDB or LLDB¶
Some of the facilities described here are only available in builds from April 11, 2013 or later.
On macOS, we recommend using lldb to debug rather than gdb.
Which compiler backend are you using?¶
If you are using the C backend, then the information discussed here will be useful for debugging. We use the C backend on 64 bit Linux, 64 bit FreeBSD and all macOS versions.
If you’re using the HARP backend (32 bit Linux or 32 bit FreeBSD), then you’ll be limited to getting stack traces.
Debugging with the C backend¶
Debugging with the C backend is not a perfect experience but it is improving.
Finding the generated C files¶
The C files generated by the compiler will be found under the
_build/build directory with a directory in there for each
library that was built as part of the project.
Finding the corresponding Dylan code¶
The generated C files contain the file name and line number of the corresponding Dylan source. However, this may be confusing in the presence of inlined functions and macro expansions.
Understanding name mangling¶
Fill this in, particularly with a link to the Hacker’s Guide!
Understanding stack traces¶
Let’s look at part of a representative stack trace:
#0 0x92b41b06 in read$NOCANCEL$UNIX2003 () #1 0x0042c509 in Kunix_readYio_internalsVioI () #2 0x000bc8e7 in xep_4 () #3 0x0042ba99 in Kaccessor_read_intoXYstreams_internalsVioMM0I () #4 0x000c0805 in key_mep_6 () #5 0x000c43a4 in implicit_keyed_single_method_engine_4 () #6 0x000c1dd5 in gf_optional_xep_4 () #7 0x004139fb in Kload_bufferYstreams_internalsVioI () #8 0x0041334a in Kdo_next_input_bufferYstreamsVioMM1I () #9 0x000c04ab in key_mep_4 () #10 0x000c3eaf in implicit_keyed_single_method_engine_1 () #11 0x0040520f in Kread_lineYstreamsVioMM0I () #12 0x000c0321 in key_mep_3 () #13 0x000c3eaf in implicit_keyed_single_method_engine_1 () #14 0x0079dcf6 in Kcommand_line_loopYcommand_linesVenvironment_commandsMM0I () #15 0x000bf6b3 in rest_key_xep_5 () #16 0x00007abe in Kdo_execute_commandVcommandsMdylan_compilerM0I () #17 0x000bb9bb in primitive_engine_node_apply_with_optionals () #18 0x0002b9ba in Khandle_missed_dispatchVKgI () #19 0x0002aaef in KPgf_dispatch_absentVKgI () #20 0x000c25e8 in general_engine_node_n_engine () #21 0x004b19a8 in Kexecute_commandVcommandsMM0I () #22 0x000bb9bb in primitive_engine_node_apply_with_optionals () #23 0x0002b9ba in Khandle_missed_dispatchVKgI () #24 0x0002aaef in KPgf_dispatch_absentVKgI () #25 0x000c25e8 in general_engine_node_n_engine () #26 0x000c11ab in gf_xep_1 () #27 0x0000aa9e in KmainYconsole_environmentVdylan_compilerI () #28 0x0000abb3 in _Init_dylan_compiler__X_start_for_user ()
Some things to notice:
- Method dispatch takes up the bulk of the stack frames with function calls
implicit_keyed_single_method_engine_1and so on.
- Methods representing Dylan code are mangled as discussed in a section above.
- It may seem alarming to see methods like
Khandle_missed_dispatchVKgI(where did dispatch go?!?). These function calls indicate that the dispatch data for a method hadn’t been set up yet as this is the first invocation of that method. The method dispatch data is set up lazily, so this is normal and expected.
- There isn’t any information on arguments or what file and line number contains the corresponding code. This means that you don’t have the debug data for the compiler around. An easy way to address this is to build your own copy of the compiler.
Breaking on main¶
Unfortunately, you can’t simply set a breakpoint on
main. This is because
the generated code runs from shared library constructor functions so the
entire Dylan application runs and exits prior to
main being invoked.
A reasonable alternative is to determine the C name of your entry point function and set a breakpoint on that instead.
Inspecting Dylan objects in LLDB¶
In LLDB, you may import our Dylan support library:
command script import /path/to/opendylan/share/opendylan/lldb/dylan
Do not import the scripts under that directory directly as that will not work. Once this has been done, variables that are representing Dylan values will automatically be shown with additional data about their actual values.
Inspecting Dylan objects in GDB¶
We do not yet have support for Dylan in GDB as we do for LLDB.
The C runtime contains a number of helper functions specifically for improving the debugging process. These can be invoked from gdb or lldb and will assist you in analyzing values.
Returns the class instance for the given instance object.
Tests whether instance is
Tests whether instance is a
floatdata stored in the instance.
doubledata stored in the instance.
Returns the string form of the given symbol.
Tests whether instance is an empty list.
Returns the C string data stored in the given instance.
Tests whether instance is a
Returns the format string stored in the given
Returns the format string arguments stored in the given
<string>object containing the function’s name. Note that we do not store the name for all function objects.
Print some information about the given object to
Debugging with the HARP backend¶
As mentioned previously, this is largely limited to getting stack
traces. If you try to run a Dylan application built with the
HARP backend under the debugger, you may need to adjust your
debugger’s signal handling as the Memory Pool System GC that is
used employs the
To do this on Linux and FreeBSD in gdb, use this command:
handle SIGSEGV pass nostop noprint
Add more notes about this later.