Is it possible to "jump"/"skip" in GDB debugger?
Is it possible to jump to some location/address in the code/executable while debugging in GDB ?
Let say I have something similar to the following
int main()
{
caller_f1() {
f1(); // breakpoint
f2() } // want to skip f2() and jump
caller_f2() { // jump to this this location ??
f1();
f2(); }
}
To resume execution at a new address, use jump
(short form: j
):
jump LINENUM
jump *ADDRESS
The GDB manual suggests using tbreak
(temporary breakpoint) before jumping.
The linenum can be any linespec
expression, like +1
for the next line.
See @gospes's answer on a related question for a handy skip
macro that does exactly that.
Using jump
is only "safe" in un-optimized code (-O0
), and even then only within the current function. It only modifies the program counter; it doesn't change any other registers or memory.
Only gcc -O0
compiles each source statement (or line?) into an independent block of instructions that loads variable values from memory and stores results. This lets you modify variable values with a debugger at any breakpoint, and makes jump
ing between lines in the machine code work like jumping between lines in the C source.
This is part of why -O0
makes such slow code: not only does the compiler not spend time optimizing, it is required to make slow code that spills/reloads everything after every statement to support asynchronous modification of variables and even program-counter. (Store/reload latency is about 5 cycles on a typical x86, so a 1 cycle add
takes 6 cycles in -O0
builds).
gcc's manual suggests using -Og
for the usual edit-compile-debug cycle, but even that light level of optimization will break jump
and async modification of variables. If you don't want to do that while debugging, it's a good choice, especially for projects where -O0
runs so slowly that it's a problem.
To set program-counter / instruction-pointer to a new address without resuming, you can also use this:
set $pc = 0x4005a5
Copy/paste addresses from the disassembly window (layout asm
/ layout reg
).
This is equivalent to tbreak
+ jump
, but you can't use line numbers, only instruction addresses. (And you don't get a warning + confirmation-request for jumping outside the current function).
Then you can stepi
from there. $pc
is a generic gdb name for whatever the register is really called in the target architecture. e.g. RIP in x86-64. (See also the bottom of the x86 tag wiki for asm debugging tips for gdb.)
There seems to be a jump command which is exactly what you are looking for:
http://idlebox.net/2010/apidocs/gdb-7.0.zip/gdb_18.html#SEC163
Updated link: http://web.archive.org/web/20140101193811/http://idlebox.net/2010/apidocs/gdb-7.0.zip/gdb_18.html#SEC163