Earlier quoted context omitted.
Yes, it is. Do you have a specific question?
I think their question was this: how is it that I can step through and see the expected changes to my variables, given that the optimiser is permitted to re-order/elide/restructure my code?
How Does a C Debugger Work? (2014)
21–30 of 32 posts
Re: How Does a C Debugger Work? (2014)
#22It writes an invalid instruction at this location. What ever this instruction, it just has to be invalid. On x86 at least, it is a valid instruction. INT3, or CC in hex. There are also the debug registers which implement breakpoints without modifying any code, although it's limited to a maximum of 4 at once. Characterising gdb as a "C debugger" is quite appropriate --- try to debug the Asm directly with it is an excr…
Author here. I will rewrite this sentence, "invalid instruction" is too limited. It should be something like "an instruction that traps, and which isn't already used for another purpose". Syscalls trap but they are already used; and INT3/CC are valid instructions.
Re: How Does a C Debugger Work? (2014)
#23What about optimizations? Isn't it possible the compiler will re-order or combine statements differently than how they are written in source?
But there's a wide "grey area" depending on optimization level where the debug information is more or less off yet the mapping is still "good enough". Debugging on optimized builds can work surprisingly well if you know what to expect (e.g. the debugging cursor might jump to unexpected places in the source code because the line mapping is off, or you can't step into a function because it has been inlined).
Re: How Does a C Debugger Work? (2014)
#24It writes an invalid instruction at this location. What ever this instruction, it just has to be invalid. On x86 at least, it is a valid instruction. INT3, or CC in hex. There are also the debug registers which implement breakpoints without modifying any code, although it's limited to a maximum of 4 at once. Characterising gdb as a "C debugger" is quite appropriate --- try to debug the Asm directly with it is an excr…
Re: How Does a C Debugger Work? (2014)
#25It writes an invalid instruction at this location. What ever this instruction, it just has to be invalid. On x86 at least, it is a valid instruction. INT3, or CC in hex. There are also the debug registers which implement breakpoints without modifying any code, although it's limited to a maximum of 4 at once. Characterising gdb as a "C debugger" is quite appropriate --- try to debug the Asm directly with it is an excr…
Yeah, it's useful to have a special-purpose 'software breakpoint' instruction. Arm actually didn't have one until v5 of the architecture, so some older systems or those wanting to maintain compatibility will still use an arbitrary undefined-instruction pattern. The advantage of an architecturally defined instruction rather than picking something invalid at random is (a) software can rely on future CPUs not deciding t…
Re: How Does a C Debugger Work? (2014)
#26Another great one that actually walks through writing a basic debugger is Eli Bendersky's series[1].
One nitpick:
> It could, and that would work (that the way valgrind memory debugger works), but that would be too slow. Valgrind slows the application 1000x down, GDB doesn't. That's also the way virtual machines like Qemu work.
This is usecase-dependent: running a program until you hit a breakpoint will be significantly faster with `int 3`, but running a piece of instrumentation on every instruction (or branch, or basic block, or ...) will be significantly faster with Valgrind (or another dynamic binary instrumentation framework). This is because Valgrind and other DBI tools can rewrite the instruction stream to sidecar instrumentation into the same process, versus converting every instruction (or other program feature) into a sequence of expensive system calls.
Re: How Does a C Debugger Work? (2014)
#27Earlier quoted context omitted.
Having come from a background of WinDbg (Windows) and DEBUG (DOS) before it, GDB feels very "unergonomic" in comparison. The general verbosity (why do you need an asterisk in front of an address when writing a breakpoint --- as the title of this site so prominently reminds?), lack of a regular hexdump command (16-byte hex+ASCII format) and the rather perplexing behaviour of the "disassemble" command ( https://stackov…
gdb) watch my_ptr what does this mean? watch when the value at the address given by my_ptr changes, or watch when the value of my_ptr changes (i.e. it is modified to point to a different location) ? gdb) watch * my_ptr Ah ... now it's clear what is meant. gdb) watch 0xfeedface hmm, now 0xfeedface is not a variable but literally an address. But wait, is it? What does this mean? Watch the value at memory location 0xfee…
Is it? I can't tell if your post has a sarcastic tone or not!
Re: How Does a C Debugger Work? (2014)
#28Earlier quoted context omitted.
Having come from a background of WinDbg (Windows) and DEBUG (DOS) before it, GDB feels very "unergonomic" in comparison. The general verbosity (why do you need an asterisk in front of an address when writing a breakpoint --- as the title of this site so prominently reminds?), lack of a regular hexdump command (16-byte hex+ASCII format) and the rather perplexing behaviour of the "disassemble" command ( https://stackov…
gdb) watch my_ptr what does this mean? watch when the value at the address given by my_ptr changes, or watch when the value of my_ptr changes (i.e. it is modified to point to a different location) ? gdb) watch * my_ptr Ah ... now it's clear what is meant. gdb) watch 0xfeedface hmm, now 0xfeedface is not a variable but literally an address. But wait, is it? What does this mean? Watch the value at memory location 0xfee…
Not the end of the world, just annoying.
Re: How Does a C Debugger Work? (2014)
#29It writes an invalid instruction at this location. What ever this instruction, it just has to be invalid. On x86 at least, it is a valid instruction. INT3, or CC in hex. There are also the debug registers which implement breakpoints without modifying any code, although it's limited to a maximum of 4 at once. Characterising gdb as a "C debugger" is quite appropriate --- try to debug the Asm directly with it is an excr…
Having recently had the pleasure of having to debug JIT-compiled code with an ABI mismatch, I can't overstate how useful `rr` ( https://github.com/mozilla/rr ) can be to debug assembly. The ability to `rsi` e.g. reverse step instruction is very powerful. One tool that I started exploring is https://pernos.co/ , the ability to do dataflow analysis is super cool. Let's you easily answer the question "How did this value…
It's really striking that it can't work on ARM though, due to an ARM architectural issue which x86 doesn't have.
Re: How Does a C Debugger Work? (2014)
#30Earlier quoted context omitted.
gdb) watch my_ptr what does this mean? watch when the value at the address given by my_ptr changes, or watch when the value of my_ptr changes (i.e. it is modified to point to a different location) ? gdb) watch * my_ptr Ah ... now it's clear what is meant. gdb) watch 0xfeedface hmm, now 0xfeedface is not a variable but literally an address. But wait, is it? What does this mean? Watch the value at memory location 0xfee…
Names of locations in assembly language are typically constants, similar to global arrays in C. There's no my_ptr, as such; there's an address, and my_ptr is its name. When you watch my_ptr, you want to monitor what's at that address - ``watch *my_ptr'', in gdb terms. Not the end of the world, just annoying.