The detour technique is much nicer on ARM64. All the instructions are 4 bytes and you have a `jump immediate` instruction so its possible to jump to the detour code using 1 instruction assuming you have an empty area close by. On X86 the smallest instruction is 1 byte and the detour jump instruction is going to be larger than 1 byte. Having to overwrite the target instruction with multiple instructions is tricky because you need to make sure that the subsequent instructions are only reachable via the target instruction. This means the simple technique of instruction overwriting is not possible for debugging some instructions. Though, usually you can always target the start of a function because the prologue will contain enough instructions to make room for a detour. Also, when using this technique you have to make the assumption the program is 'sane' and not jumping into the middle of functions from other functions because the instruction reachability analysis is usually done at the function level.
Well, if you assume “sane”, then you can do whole-function (or basic block) rewriting if the detour would overwrite other reachable instructions. More annoying for sure, but should be doable.
Are there any compilers that insert nops between real instructions in debug builds to allow inserting a jump to code to evaluate the expression? Conditional breakpoints are so slow it’s usually faster to add an if with the condition and recompile.
I'm curious how people assumed these work? Allowing step debugging already precludes a ton of possible optimizations that a compiler might otherwise be able to do. No?
If you compile for an optimized level you probably will see your debugger jump around and skip random things. It just depends on what the optimizer did to the code. Have made that mistake enough times to watch it in action.
Right, I'm assuming the places where you would notice that conditional debugs are slow are also the places where you will have trouble with step debugging, in general?
Hmm would not think so. As the IDE does not really care much about that. The backend just says 'you are near this spot in the code'. In the IDE it looks like things just 'dont exist' or the current line pointer will jump around when you compile release mode. Whereas in 'debug' (or O0) the compiler just emits the code in the most simplistic way possible so things tend to stay in order. While 'release' (or O1 to O3) can (and will) move things around to remove processor pipeline stalls, optimizations, and other intrinsics.
Conditional is going to have some overhead because it has to re-evaluate the condition on every step of the program counter if you are near the offending line or not. While line stepping is more closer to a lookup table of where in the parsed strings are you compared to the current program counter. Which is a much simpler lookup and the previous step was nearby (so probably less than logn but not quite 1). While a conditional would have at least N search (all of your break points plus the calculation of the variables for the condition). Some hardware also assists with breakpoints by popping an exception when you hit a particular program counter making it much faster in some cases. Whereas with a conditional you have to ignore the hardware and do it the 'hard way' on every virtual step of the PC.
I think you are talking past me? My point is the easy code is not where you would want to put breakpoints. It isn't a matter of the IDE, it is a matter of the likelihood that you want a breakpoint in a tight loop. And if you do, you will be working against optimizations and adding far more code to execute than a single condition.
Is like someone adding what feels like a single field to a query, not accounting for the effort that goes into a join.
Edit: I should add that "difficulty with step debugging" isn't just "won't work." I picture "having to press resume a few hundred times to get exactly where I want to be" as difficulty, there.