Pernosco Blog

Shrink Your Compile Times With Split DWARF

What if you could reduce the time it takes to link your program by 25%, reduce the memory it takes to link your program by 40%, and reduce the size of the binary by 50%, all by changing a compiler flag? That's the power of "split DWARF", a compiler and debugger feature that uses a new format for the DWARF debugging information that's specifically designed to reduce the work the linker is required to do. Let's dive into how it works and what is required for you to benefit from it.


Automatic Downcasting: How Does It Work?

Many programming languages include mechanisms for dynamic polymorphism. These pose challenges for debuggers, because viewing only fields from the declared type of a variable may not be particularly useful. Automatically deducing the most-"derived" type and downcasting to it presents the entire object to developers and makes debugging code that uses dynamic polymorphism much more pleasant. Our Pernosco Omniscient Debugger automatically downcasts types that use dynamic polymorphism in supported languages (C++, Rust, and Ada). You might also be familiar with this technique in gdb via the set print object on command. But how is it actually implemented?


Making Debuggers Sad: C++ Identifier Canonicalization


Where Should the Debugger Set a Breakpoint?

When you search for executions of a function in Pernosco (or set a breakpoint in a more traditional debugger), how does the debugger decide where to stop? You might think it just stops at the first instruction in a function, but that's not true in general.

Debuggers actually stop immediately after the function's "prologue", and for good reason. At -O0, compilers generally do not produce accurate debug information for the function prologue, and stopping any earlier would lead to the debugger seeing incorrect parameter values. That, in turn, would produce the wrong results when evaluating conditional breakpoints. Finding the end of a function's prologue can be surprisingly difficult though. In this article I'll go through why this is an issue, and some of the heuristics involved in determining where to place a breakpoint.


Implementing Pernosco Support For Github Actions

Pernosco supports debugging failures in Github Actions tests. When a test fails, you get a link that takes you directly to debug that failure:

(If you want Pernosco debugging for the Github Actions of your open-source project, contact us.)

Implementing this required reimplementing (some of) Github Actions workflow execution. We have just published our gha-runner implementation of Github Actions (as a Rust library). You can use gha-runner to run Github Actions workflows locally, and it has extension points to let projects like Pernosco modify how workflows are executed. gha-runner contains an example that lets you run Github Actions steps locally under strace, e.g.:

Older Posts →