The Soul of a New Debugger
This blog post is a follow-up to A Future for Rust Debugging
Why developers are reluctant to use interactive debuggers and prefer
This is a question that has been perplexing me, and while it’s not possible to have a definite answer, we can make some educated guesses.
Interactive debuggers solve these problems: you can take an existing program that was compiled in the debug mode and probe it to your liking, setting up conditional breakpoints, looking up current values of variables, and doing a lot of other useful things. However, in my view, the widely-used interactive debuggers have a set of problems of their own:
A lot of them were designed in a different era. At that time, we didn’t have always-on Internet connections, high-resolution multi-colour displays, and devices with many gigabytes of memory. While the fundamental principles remain the same, the modern needs have changed and so do modern means.
Many existing debuggers are general-purpose. While there is some support for scripting and language-specific extensions, it’s harder to use them for specific domains and it’s harder to integrate them with your dev environment. In practical terms, this means you have to use other tools in addition to debuggers to observe the behaviour of your software, and oftentimes it’s just easier & faster to move along with
I also see more general problems with regards to debuggers. They are perceived mostly as a tool to help you find and fix bugs in your code, but not as much as a tool of discovery and exploration. It’s been 8 years since Bret Victor published his “Learnable Programming”, and these ideas are as relevant today as ever. Debuggers should strive to be a good learning tool too.
Lastly, interactive debuggers rely on underlying principles that are quite similar to profilers, dynamic tracers like DTrace and eBPF, memory leak detectors, and other developer tools. Ideas and code can – and should – be shared across this ecosystem, but it seems like whilst one type of tools gets a lot of attention, the others may still lack support for important features.
So what can we do to try solving these problems?
Elements of a modern debugger
In my previous article, I argued for a case of extending the existing debuggers to provide better support for Rust. However, after some more research and thinking, I feel that we should consider the idea of creating a new debugger framework from scratch, taking inspiration from other great projects. Not-invented-here syndrome aside, I think there are some valid reasons for going in this direction.
Another project to take inspiration from is Delve, a Go debugger. It’s built with modern tools and has several features important for Go developers, but I want to highlight the JSON-RPC API it provides. This API addresses the important problem of integration with the development environment, and by using a well-defined protocol we can create an ecosystem for debuggers that’s similar to the one that’s flourished around the language server protocol. With an HTTP-based API, we can build custom debugger front-ends using HTML and WebAssembly and run them in web browsers. With the rich front-end tools & frameworks, it opens up lots of interesting options for data representation and visualisation. Integration doesn’t have to be one-sided, too: language servers can be reused for debugging purposes, and integrating a Rust-specific debugger with the Rust compiler would allow us to utilise the full power of the existing language syntax parser and other compiler components.
Overall, I believe this is a project worth building. While we’re seeing a lot of innovation in compilers and language design, debuggers are somewhat neglected, even though debugging is no less important; as Kernighan’s law postulates, it’s twice as hard as writing the code in the first place.
Creating a new debugger is an insurmountable task and a very long journey. But it can have a modest start: if we cover only a few popular operating systems and a few simple cases first, we can quickly achieve small wins that can save us a lot of time and frustration.
This post outlines the initial project plan for Headcrab, a Rust debugger library. I will be publishing more code and documentation in the coming weeks. If you are interested in updates, please follow me on Twitter. Progress updates will be also published on this blog.
- You can find a more detailed roadmap in the project repository.