What are setjmp and longjmp ?
setjmp and longjmp are C library functions intended for exception handling.
setjmp saves the current execution state into a structure of type jmp_buf. Later, a longjmp call can transfer control to the point immediately after the call to previous setjmp. The return value from setjmp indicates whether control reached that point normally or from a call to longjmp:
- jmp_buf state;
- if( setjmp(state) == 0 ) // save the current state , returns 0 first time.
- {
- // ...
- // on error
- longjmp(state,-1); // this returns -1 at line 2
- // ...
- }else{
- }
Implementation
The prototypes for the functions are defined in setjmp.h:
int setjmp(jmp_buf env);
void longjmp(jmp_buf env, int val);
void longjmp(jmp_buf env, int val);
Let us typedef the jump_buf to hold the x86 register state. Note that the struct _jmp_buf has to be typedefd to an array to comply with the C standard.
typedef struct _jmp_buf {
unsigned ebx,ecx,edx,esi,edi,ebp,esp,eip;
int ret;
} jmp_buf[1];
unsigned ebx,ecx,edx,esi,edi,ebp,esp,eip;
int ret;
} jmp_buf[1];
Implementation of the routines in X86 assembly ( gcc AT&T syntax):
.text
.globl setjmp
.type setjmp,@function
setjmp:
movl 4(%esp),%eax ;
movl %ebx,0(%eax) ;
movl %ecx,4(%eax) ;
movl %edx,8(%eax) ;
movl %esi,12(%eax) ;
movl %edi,16(%eax) ;
movl %ebp,20(%eax) ;
popl %edx ;
movl %esp,24(%eax) ;
movl %edx,28(%eax) ;
xorl %eax,%eax ;
pushl %edx ;
ret;
.text
.globl longjmp
.type longjmp,@function
longjmp:
; process parameters
movl 4(%esp),%eax ; jmp_buf
movl 8(%esp),%ebx ; ret val
; fix the ret val if it 0
test %ebx,%ebx ;
jnz 0f ;
incl %ebx ;
0:
movl %ebx,32(%eax) ; save retval
; restore registers
movl 0(%eax),%ebx ;
movl 4(%eax),%ecx ;
movl 8(%eax),%edx ;
movl 12(%eax),%esi ;
movl 16(%eax),%edi ;
movl 20(%eax),%ebp ;
movl 24(%eax),%esp ;
pushl 28(%eax) ;
movl 32(%eax),%eax ; ret val
ret ;
.globl setjmp
.type setjmp,@function
setjmp:
movl 4(%esp),%eax ;
movl %ebx,0(%eax) ;
movl %ecx,4(%eax) ;
movl %edx,8(%eax) ;
movl %esi,12(%eax) ;
movl %edi,16(%eax) ;
movl %ebp,20(%eax) ;
popl %edx ;
movl %esp,24(%eax) ;
movl %edx,28(%eax) ;
xorl %eax,%eax ;
pushl %edx ;
ret;
.text
.globl longjmp
.type longjmp,@function
longjmp:
; process parameters
movl 4(%esp),%eax ; jmp_buf
movl 8(%esp),%ebx ; ret val
; fix the ret val if it 0
test %ebx,%ebx ;
jnz 0f ;
incl %ebx ;
0:
movl %ebx,32(%eax) ; save retval
; restore registers
movl 0(%eax),%ebx ;
movl 4(%eax),%ecx ;
movl 8(%eax),%edx ;
movl 12(%eax),%esi ;
movl 16(%eax),%edi ;
movl 20(%eax),%ebp ;
movl 24(%eax),%esp ;
pushl 28(%eax) ;
movl 32(%eax),%eax ; ret val
ret ;