7

setjmp() is supposed to save registers including "return address" and "stack pointer" into "jmp_buf". When I compile (both gcc and clang) and debug the following program under x86_64 with glibc, I cannot understand what is in the "jmp_buf" and where "return address" and "stack pointer" are located in the "jmp_buf".

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

int main()
{
    int i;

    jmp_buf env;

    i = setjmp(env);

    printf("i = %d\n", i);

    if (i != 0) return;

    longjmp(env, 2);
    printf("Does this line get printed?\n");
}   

When the program stops at a breakpoint before "printf("i = %d\n", i);", I tried gdb functionality: "p/x env"; however I cannot find the "return RIP" and "previous RSP" in this structure (env) which contains __jmpbuf and __saved_mask. Anyone knows how exactly these two functions work and what exactly they save under x86_64 with glibc (I use ubuntu 14.04)?

WindChaser
  • 960
  • 1
  • 10
  • 30
  • I saw several questions like this in stackoverflow.com, but the answers are usually "It depends on the architecture, OS, library and ABI..." or paste the standard. They are not what I would like to know. – WindChaser Jan 21 '15 at 03:20
  • 1
    Why don't you look at the implementation on your platform? It's open source. For example: https://github.com/lattera/glibc/blob/master/sysdeps/sh/____longjmp_chk.S - that's what longjmp calls into in glibc. – John Zwinck Jan 21 '15 at 03:24

1 Answers1

10

Believe it or not, the contents of jmp_buf are intentionally meaningless. If you take a look at the source to the x86_64 setjmp(), you'll note several references to PTR_MANGLE. This is an internal glibc macro which XORs a thread-local value against a register. This is used here in large part to ensure that developers do not rely on the layout of jmpbuf — it is considered an implementation detail, and may change between versions of libc.

If you want something readable, check out the ucontext interface.