Skip to content

Commit 84f8f9b

Browse files
grisumbraslouistatta
authored andcommitted
Dmitry's 2024 Q3 report
1 parent 77231ff commit 84f8f9b

File tree

1 file changed

+102
-0
lines changed

1 file changed

+102
-0
lines changed
Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
---
2+
layout: post
3+
nav-class: dark
4+
categories: dmitry
5+
title: How to Get More Utility from the Debugger in CI
6+
author-id: dmitry
7+
author-name: Dmitry Arkhipov
8+
---
9+
10+
While some of my work in the third quarter of this year was dedicated to more
11+
work on Boost.JSON and Docca, the most interesting thing was definitely
12+
[pretty_printers](https://github.com/cppalliance/pretty_printers), a collection
13+
of utilities and build scripts which help dealing with debugger pretty printers
14+
and visualisers. Although currently it only supports
15+
[GDB](https://www.sourceware.org/gdb/), I'm planning to research
16+
[LLDB](https://lldb.llvm.org/) and
17+
[Natvis](https://learn.microsoft.com/en-us/visualstudio/debugger/create-custom-views-of-native-objects?view=vs-2022)
18+
integration too.
19+
20+
The module naturally emerged from my work on GDB pretty printers for
21+
Boost.JSON. Even if you don't know what pretty printers are, you can probably
22+
guess just by their name: they are helpers that tell the debugger how to output
23+
objects of a particular type. These days standard libraries come with such
24+
helpers, and so when we try printing a container, we get useful information
25+
instead of unintelligible gibberish. If we provide similar helpers for our
26+
libraries we can significantly improve debugging experience for our users.
27+
28+
But writing the helpers is only one half of the task. The other half is getting
29+
the debugger to actually load them. Let's look at the options GDB provides us
30+
for this.
31+
32+
1. The user can manually load an extension that contains our helpers from the
33+
initialisation file.
34+
2. The debugger can automatically load the extension that matches the name of a
35+
binary that it loads (either a program or a shared library).
36+
3. The debugger can load the extension from a special section in the loaded
37+
binary itself.
38+
39+
Option 1 is the most straightforward, and is also the least exciting. Option 2
40+
is actually the one standard libraries go for. But there is a fundamental
41+
problem with it: it doesn't work for static libraries let alone header-only
42+
ones. A static library is never a binary loaded by the debugger, and the
43+
extension file name has to match the name of a loaded binary. Header-only
44+
libraries don't have a corresponding binary at all. The reason it works so well
45+
for standard libraries is that people very rarely link to them statically when
46+
they are actually working on their code, which is when they use a debugger.
47+
48+
This leaves option 3: putting the extension into the binary. GDB documentation
49+
[explains how to do it](https://sourceware.org/gdb/current/onlinedocs/gdb.html/dotdebug_005fgdb_005fscripts-section.html).
50+
The catch is that the extension file needs to be preprocessed to effectively
51+
become an assembler command. This can be automated, though. In August Niall
52+
Douglas [posted on the Boost developers' mailing list](https://lists.boost.org/Archives/boost/2024/08/257480.php)
53+
about his and Braden Ganetsky's work on a script that does such preprocessing
54+
of a GDB extension file for his library. At that point I have experimented a
55+
little bit with such embedding and concluded that this is as good as it gets
56+
with pretty printers deployment. So, the first component of `pretty_printers`
57+
is a script that takes a GDB Python extension file and produces a C file
58+
suitable for embedding into a binary.
59+
60+
But that's not all. In the same mailing list post Niall mentions that the
61+
reason Braden has collaborated with him was bugs he found in the embedding.
62+
This leads us to testing. Boost.JSON is quite rigorously tested. This has been
63+
made possible largely thanks to the C++ Alliance Drone instance. After I
64+
initially wrote GDB pretty printers for Boost.JSON I immediately started
65+
looking for a way to test them. The aforementioned mailing list post shows that
66+
my concern wasn't a purely theoretical one.
67+
68+
After some research I discovered that with certain flags GDB can be run as a
69+
Python interpreter. Hence my original idea for testing pretty printers: a C++
70+
program that sets up objects to print, and an accompanying Python script that
71+
tells GDB where to set breakpoints and what expressions to print, and compares
72+
the output with the expected strings. But I realised that keeping the two files
73+
in sync becomes rather unwieldy very quickly. That led to take 2: put the tests
74+
in the comments of the C++ test program, and generate a corresponding Python
75+
script from it. Not only it resulted in the tests immediately following the
76+
lines creating the objects used in those tests, it also allowed the support for
77+
putting tests in functions, loops, and spreading them across multiple files.
78+
The utility that generates such Python script is the second component of
79+
`pretty_printers`.
80+
81+
This concludes the story of the two utilities contained in `pretty_printers`.
82+
The other important component of this module is the support for CMake and B2
83+
build systems. The support doesn't simply include some boilerplate. The testing
84+
function also tells GDB to whitelist the directory where the tested binary is
85+
located, so that the extensions are loaded. Otherwise the user would have to do
86+
it manually, which is particularly annoying in CI.
87+
88+
After I finished the work on the module, I decided that other libraries could
89+
benefit from it. It was suggested to me that I should submit the module for
90+
review to the Boost community. Previously there hasn't been any Boost tool
91+
reviews, but the Boost community was positive to the idea. I find this to be
92+
a very exciting development.
93+
94+
Another exciting idea I had is to research other potential debugger helpers,
95+
unrelated to pretty printing and visualisation. For example, GDB allows
96+
extensions to register custom commands. There's also the possibility of
97+
orchestrating GDB to analyse a specific situation. E.g. put a breakpoint on
98+
this line, but only after another line was hit. While locally this is easily
99+
done manually, such functionality can be useful when the error only manifests
100+
on a platform you only have access to in CI. Such ideas hint that
101+
`pretty_printers` is a misnomer, and the module should be called something
102+
different. Maybe `debugger_utils`?

0 commit comments

Comments
 (0)