News for hackers. Stuff that matters.
Re:How to build highly-debuggable C++ binaries by mark_undoio on Monday July 29, 2024 @01:17PM (#41102005)
> It’s a massive pain to have everything be marked as “optimized out” and reassemble the things you want from other variables or by using a disassembler to manually track which register the value is hiding in.

If you've got a time traveling / reversible debugger than you can (sometimes) go back to a point where the value was being written / used, at which point it'll often reappear in scope and be accessible.

I believe DWARF's built-in virtual machine should be able to recompute missing values in many cases but I don't think compilers are great at putting the relevant info in, even where it should be possible to compute the right value fairly easily.

Re:How to build highly-debuggable C++ binaries by mark_undoio on Monday July 29, 2024 @01:19PM (#41102016)
The other trick I've found really helpful for "optimized out" values is to find places where they cross boundaries that block optimizations (e.g. procedure calls to another translation unit, so long as you're not doing some kind of link-time optimisation).

e.g. if the value you're interested in is being passed to / returned from a function then inspecting it around the call / return site should have the value available.

Re:How to build highly-debuggable C++ binaries by o11c on Monday July 29, 2024 @01:44PM (#41102228)
Two particular notes around this (exact commands assuming gdb, but other debuggers should have equivalents):

Pass various arguments to `backtrace` rather than just relying the default. Chances are it will have some non-optimized-out variables, which you can use to figure out what's going on.

Use `info registers` and see what looks like a pointer, then cast it to a type you suspect it is. Note that this can be done for any stack frame.

Re:How to build highly-debuggable C++ binaries by account42 on Tuesday July 30, 2024 @07:23AM (#41107981)
Even with LTO or inside translation units, compilers are (sadly) extremely conservative about changing function boundaries.
Re:How to build highly-debuggable C++ binaries by mark_undoio on Tuesday July 30, 2024 @12:02PM (#41110573)
I've seen gcc do an enthusiastic job on `static` functions within a C compilation unit - specifically where they only have one call site and so can be fully inlined into the caller.

In that case, the code did become pretty hard to debug due to the extensive inlining and reordering it had allowed. Unfortunate because the only reason such functions exist is to make the structure of the code more apparent!

Maybe that's an exception (and / or maybe it's easier with C than for C++).

Maybe the less is that it's still always worth trying function call boundaries, in case the compiler has been conservative!

Re:How to build highly-debuggable C++ binaries by account42 on Wednesday July 31, 2024 @04:42AM (#41117402)
Yes, inlining is one exception. Function variants for constant propagation are another. But both of those have been around for a long time and if neither of them apply compilers won't even reorder arguments where that makes sense or deviate from the platform calling convention based on register pressure inside the functions or drop unused arguments or reorder arguments if that improves things. Feels like in general internal function boundaries in the code should be just a hint to and optimizing compiler but somehow there has been very little development in that area. Similar for struct/class layout, compilers won't touch that even if they can see all uses.