Source-Level Debugging of Compiler-Optimised Code: Ill-Posed, but Not Impossible, https://dl.acm.org/doi/10.1145/3689492.3690047. There's almost no research in this area so it's good to see someone thinking about some of the challenges. I'd like to have seen a discussion of undefined behavior, specifically, since there's a paradox where C programmers are most likely to use debuggers exactly in cases where UB is present, which poses fundamental challenges to source-level debugging.

@pervognsen When writing C/C++, I mostly find myself using a debugger when things go wrong and I'm likely in UB territory. At this point, I'm mostly looking at the disassembly and all of the source/variable mapping of the debugger is a mere convenience, and it's understandable why some things don't work.

When I see people (mostly from or inspired by the Windows gamedev world) talk about continuous usage of debuggers, I do wonder a bit what they're doing with it. Is it a nice interface for getting traces of execution? Do they just want to set a breakpoint in a function for an input doing something they don't understand then step through it until they do understand? Do they actually want to execute newly compiled code from the debugger like a REPL?

@zwarich @pervognsen In my experience, it’s mostly to test a hypothesis. Games have mountains of hidden state and extremely branch-heavy logic, and engines only sometimes invest in in-process inspection or tracing. So the hypothesis-reproduce-check loop can be the local maxima for exploring the configuration space.

@jc @pervognsen In a low-level language, it's not really possible for the toolchain to provide a uniform tracing solution (because there's no runtime to manage the trace buffer).

However, operating systems provide debugger interfaces, which allow external programs to interpose at the userspace/kernel boundary, which barring the use of binary instrumentation (the other solution @pervognsen mentioned with a different set of tradeoffs) is the only way to provide universal tracing. Or at least almost universal tracing, because ptrace() and friends have all sorts of bugs/quirks that prevent them from working completely reliable, but you're unlikely to create an alternative with higher reliability for uncooperative programs.

This would be my main use for debugging (rather than e.g. actually executing new code with side effects in a debugger context), so given a slightly greener field perhaps it would be better to target this directly?