wile_e8
wile_e8

Reputation: 347

How to step through a longjmp in gdb

I'm trying to fix a bug in code someone else wrote, and I'm trying to step though it in gdb to figure out what is going on. But one of the lines I hit is a call to longjmp(), and after hitting "next" on that line gdb continues regular execution rather than breaking on the next source line being executed. Similar continue occurs if I try "step" on the longjmp() line. Is there any gdb command I can use to break on the next source line being executed after longjmp()?

Upvotes: 2

Views: 1557

Answers (3)

Tom Tromey
Tom Tromey

Reputation: 22549

It's worth noting that gdb's behavior is system-dependent.

On Linux, next over a longjmp or throw works approximately as you would expect: if the target of the non-local jump is at or above the current frame, execution will stop there.

This is implemented using debugging hooks in the implementations of longjmp and throw. For throw this is done both with a helper function (the older approach) and with so-called SystemTap probes (aka "sdt probes"). For longjmp this is done only with sdt probes in glibc.

For this to work the probe support must be compiled into the libraries in question. You can check with readelf -n. At least Fedora does this properly.

It's possible in theory to implement support for longjmp for other platforms in gdb. However, it may be non-trivial.

You can try to decode the jmp_buf, as mentioned in other comments. Note however that on some systems, such as Linux, the target PC in the jmp_buf is encoded, for security reasons. So you will have to figure out how to decode it.

Another way to approach this is to simply single-step through longjmp itself. Set a breakpoint there, like break longjmp; use disassemble to view the assembly; and then si until you step through the instruction that transfers execution to the target.

Upvotes: 6

John Bollinger
John Bollinger

Reputation: 180978

Is there any gdb command I can use to break on the next source line being executed after longjmp()?

Not as far as I know, no. You'll need to trace the origin of the jmp_buf back up the call stack to find the setjmp() by which it was filled. If setjmp() calls in the source are few, you might consider setting a breakpoint after each. Otherwise, you might just step through the program, setting a breakpoint after each setjmp() you pass.

Note also that you indeed should find the relevant setjmp() in one of the functions in the call stack when the corresponding longjmp() is reached, for otherwise the jmp_buf is invalid.

You can use the bt command to get a call stack, and the frame command to switch to and inspect any frame on the stack.

Upvotes: 1

dbush
dbush

Reputation: 224377

You need to set a breakpoint at the line following a non-zero return code by setjmp.

For example:

#include <stdio.h>
#include <setjmp.h>

jmp_buf jb;

void f1()
{
    printf("jumping\n");
    longjmp(jb, 1);
    printf("what???\n");
}

int main()
{
    if (!setjmp(jb)) {
        printf("calling f1\n");
        f1();
    } else {
        printf("jumped!!\n");    // line 19
    }
    return 0;
}

After calling longjmp, the next line to be executed is line 19 (see comment). So in this case run break 19 at the gdb prompt and you'll stop at that line after the call to longjmp.

gdb output:

(gdb) break 19
Breakpoint 2 at 0x40056d: file /tmp/x1.c, line 19.
(gdb) start
Temporary breakpoint 3 at 0x400549: file /tmp/x1.c, line 15.
Starting program: /tmp/x1
warning: no loadable sections found in added symbol-file system-supplied DSO at 0x2aaaaaaab000

Temporary breakpoint 3, main () at /tmp/x1.c:15
15          if (!setjmp(jb)) {
(gdb) step
16              printf("calling f1\n");
(gdb)
calling f1
17              f1();
(gdb)
f1 () at /tmp/x1.c:8
8           printf("jumping\n");
(gdb)
jumping
9           longjmp(jb, 1);
(gdb)

Breakpoint 2, main () at /tmp/x1.c:19
19              printf("jumped!!\n");
(gdb)
jumped!!
21          return 0;
(gdb)
22      }
(gdb)
0x0000003fa441d9f4 in __libc_start_main () from /lib64/libc.so.6
(gdb)

Upvotes: 1

Related Questions