Something nice to think about: why should the breakpoint interrupt instruction be exactly 1 byte long?
Something nice to think about: why should the breakpoint interrupt instruction be exactly 1 byte long?
However, their really is no reason to use more space than necessary. If you can encode an instruction with 1 byte, it doesn't make any sense to encode it using any more bytes then what you need. Every byte that gets updated when a break point is set needs to be backed up and restored once the breakpoint is hit. Using extra bytes will hurt runtime performance.
This is particularly true given the "ptrace" interface on Linux. It only supports reading or writing a single word (2 bytes) of memory in the target process at a time. Backing up and restoring any more than 2 bytes would require extra calls into the kernel, plus extra memory barriers to ensure caches get updated. Using a scheme that did that more than once would just waste CPU cycles.
In ptrace:
> The size of a "word" is determined by the OS variant (e.g., for 32-bit Linux it's 32 bits, etc.).
Taken from http://linux.die.net/man/2/ptrace
> The size of a "word" is determined by the OS variant (e.g., for 32-bit Linux it's 32 bits, etc.).
Taken from http://linux.die.net/man/2/ptrace
Consider the following code:
jmp foo
push ax // 50
foo: int 21h // CD 21
So now we want to set a breakpoint on the "push ax". If we do it using more than a single byte, it will overwrite the int 21h instruction and the code will mess up and likely crash.That's why 1 byte is used for breakpoints.
Not quite. Some processors, including X86, have hardware support for breakpoints (http://en.wikipedia.org/wiki/X86_debug_register). It may also be possible to (mis)use virtual memory hardware for setting breakpoints. Also [pedantic], one overwrites a byte, not an instruction.
Using a single byte is necessary because the program could jump to (address+1). If that address contained part of the breakpoint code, program semantics could change. O, and jumping to (address+1) could even be useful if address contains a multi-byte instruction.
0041301E 33 D2 xor edx, edx
00413020 83 E8 02 sub eax, 2
00413023 74 01 jz loc_00413026
00413025 4A dec edx
00413026 ...
Without a single-byte int 3, a break on dec edx will mess up everything if that branch is not taken. mov eax,[x]
or eax,eax
jz foo
dec eax
foo call bar
The instruction "dec eax" is one byte in size. If you want to place a breakpoint there, and you used the two byte form of "int 3", then when the code did the "jz foo" (jump if the previous result was zero to location foo) the "call bar" instruction would be partially overwritten and form a new instruction. If the condition leading the breakpoint isn't taken, you now have some other instruction (it ends up being an "add" instruction) which is bad.That's why there's a one byte version of "int 3", because there are one byte instructions.
Just thought you're referring to something else. Thanks for clearing this up; I hope you don't mind if I use your example in the next part of the series. :-)