The second part is easily explained (as correctly stated by Flortify): GDB shows the original contents of the memory, not the breakpoint "bytes". In default mode, it even removes breakpoints when the debugger pauses and reinserts them before continuing. Typically, users want to see their code, rather than the weird modified instructions used for breakpoints.
With C code, you missed a breakpoint for several bytes. GDB sets a breakpoint after the function prolog , since the function prolog is usually not what gdb users want to see. Thus, if you put break on foo, the actual breakpoint will usually be located after a few bytes (it depends on the prolog code itself, which depends on the function, since it may or may not contain a stack pointer, frame pointer, etc.). But this is easy to verify. I used this code:
#include <stdio.h> int main() { int i,j; unsigned char *p = (unsigned char*)main; for (j=0; j<4; j++) { printf("%p: ",p); for (i=0; i<16; i++) printf("%.2x ", *p++); printf("\n"); } return 0; }
If we run this program ourselves, it prints:
0x40057d: 55 48 89 e5 48 83 ec 10 48 c7 45 f8 7d 05 40 00
0x40058d: c7 45 f4 00 00 00 00 eb 5a 48 8b 45 f8 48 89 c6
0x40059d: bf 84 06 40 00 b8 00 00 00 00 e8 b4 fe ff ff c7
0x4005ad: 45 f0 00 00 00 00 eb 27 48 8b 45 f8 48 8d 50 01
Now we run it in gdb (the output is reformatted for SO).
(gdb) break main
Breakpoint 1 at 0x400585: file ../bp.c, line 6.
(gdb) info break
Num Type Disp Enb Address What
1 breakpoint keep y 0x0000000000400585 in main at ../bp.c:6
(gdb) disas / r main, + 32
Dump of assembler code from 0x40057d to 0x40059d:
0x000000000040057d (main + 0): 55 push% rbp
0x000000000040057e (main + 1): 48 89 e5 mov% rsp,% rbp
0x0000000000400581 (main + 4): 48 83 ec 10 sub $ 0x10,% rsp
0x0000000000400585 (main + 8): 48 c7 45 f8 7d 05 40 00 movq $ 0x40057d, -0x8 (% rbp)
0x000000000040058d (main + 16): c7 45 f4 00 00 00 00 movl $ 0x0, -0xc (% rbp)
0x0000000000400594 (main + 23): eb 5a jmp 0x4005f0
0x0000000000400596 (main + 25): 48 8b 45 f8 mov -0x8 (% rbp),% rax
0x000000000040059a (main + 29): 48 89 c6 mov% rax,% rsi
End of assembler dump.
At the same time, we checked that the program prints the correct bytes. But it also shows that the breakpoint was inserted at 0x400585 (that is, after the prologue of the function), and not at the beginning of the function instruction. If we now run the program under gdb (with launch) and then continue after the breakpoint has been deleted, we get this result:
(gdb) cont
Continuing
0x40057d: 55 48 89 e5 48 83 ec 10 cc c7 45 f8 7d 05 40 00
0x40058d: c7 45 f4 00 00 00 00 eb 5a 48 8b 45 f8 48 89 c6
0x40059d: bf 84 06 40 00 b8 00 00 00 00 e8 b4 fe ff ff c7
0x4005ad: 45 f0 00 00 00 00 eb 27 48 8b 45 f8 48 8d 50 01
Now this shows that 0xcc is printed for the address of 9 bytes in main.