Normal call instructions are encoded as call rel32
, with a relative displacement instead of absolute. As always, check the instruction-set reference manual entry to learn how instructions are encoded.
To get GDB's built-in disassembly to include the raw machine-code bytes, use disas /r
. (Not sure how to get that behaviour for the asm window in layout asm
/ layout reg
.) objdump
includes the machine code (in hex) by default. I use alias disas='objdump -drwC -Mintel'
in my .bashrc.
In GDB, you don't need to modify the relative displacement encoded in the machine instruction: you could just stepi
into the call
and them use a jump *0x1234567
GDB command to continue execution somewhere else. Or set $pc = 0x1234567
to change EIP / RIP without also doing a "continue".
See Is it possible to "jump"/"skip" in GDB debugger?
So you let the call instruction push a return address and jump, but then jump somewhere else to pretend like you jumped there in the first place. This might only work if the original target of the call
was accessible; I'm not sure if x86 faults just from setting RIP to non-executable memory, or of it won't fault until it tries to run the first instruction.