How DWARF Works: Table of Contents and Introduction

Sep 25, 2024

Table of Contents

Part One: Parsing Debug Info
Part Two: Using Debug Info at Runtime
  • Inspecting a Child Process
  • Stack Unwinding
  • Finding Variable Values
Appendix

Introduction

Welcome to the series on parsing and using DWARF debug info!

Its purpose is to provide a user-friendly starting point for learning about how debug information and debuggers work on Linux. It's written from the perspective of a debugger author, not a compiler author.

Non-goals include being a 100% comprehensive guide, providing details on specific languages or compilers, or giving details on other platforms.

If you want to learn more beyond what's contained in these posts, I highly recommend reading all relevant versions of the source documentation as well as other reference implementations that are pretty decent (links below).

If you have questions, comments, or corrections, please don't hesitate to reach out via email to jim at this domain dot com. I love hearing from you.

Thanks for reading!

Why Are You Writing This?

I feel strongly that the state of the art in debuggers needs to be improved on Linux. We have gdb and lldb (plus about a million graphical front ends, none of which are good). All of these tools take a long time to learn, are slow to use, and they don't make the data you need readily apparent.

There's also rr and Pernosco, which are astounding technical achievements, but suffer the same issues of taking a long time to get from "bug" to "not bug" (especially for simple issues). They do a great job of helping solve some of the hardest bugs much faster, but they're not tools I use every day.

Comparatively, Windows has Visual Studio, WinDbg, RemedyBG, and the RAD Debugger. Each of these tools do the job of making the information I need about my program available at my fingertips as fast as possible, but unfortunately, they all are Windows-only. Despite its incredible bloat, it's awesome to be able to just press F5 in Visual Studio and have a ton of helpful information at your disposal.

Graphical debuggers are hands-down better than terminal based ones because debugging is fundamentally a problem of visualization. I want to see lots of relevant information all at once every time I step, and the terminal doesn't facilitate that nearly as well as a purpose-built GUI.

Additionally, terminal based debuggers are inherently worse than graphical ones because they dont allow me to get at the information I need quickly. Starting a debugging session by writing a .gdbinit file and using the REPL is much slower than using Visual Studio, where you just press F5.

I find that most people simply don't use gdb and instead reach for printf-debugging since it's quicker and easier for the vast majority of use-cases. As a practitioner, that's the correct choice, because what is the point of a debugger that doesn't save you time? However, it leaves a ton of power on the table and is a local maximum that we must push through.

I am certain this situation can be improved. The tools to write a robust grapical debugger for Linux already exist; it's just a long, hard road to actually get it done.

Given that Linux is the most widely deployed operating system on the planet1, 2, further investment in tooling in this area is a no-brainer. Hopefully this series can contribute towards a bright future of Linux development tools in some small way.

Further Reading

All of the code I link to is non-GPL.

Useful Tools