]> git.ipfire.org Git - thirdparty/ipxe.git/commitdiff
[libc] Rewrite setjmp() and longjmp()
authorMichael Brown <mcb30@ipxe.org>
Mon, 2 Mar 2015 15:21:38 +0000 (15:21 +0000)
committerMichael Brown <mcb30@ipxe.org>
Mon, 2 Mar 2015 16:35:37 +0000 (16:35 +0000)
Signed-off-by: Michael Brown <mcb30@ipxe.org>
src/arch/i386/core/setjmp.S
src/arch/i386/include/setjmp.h

index 03727148cab6a9c5173f6952da448137fb186891..68277b990d590ee1ff18268e6c4b94cdd54ea7ee 100644 (file)
@@ -1,42 +1,64 @@
-/* setjmp and longjmp. Use of these functions is deprecated. */
-
-FILE_LICENCE ( GPL2_OR_LATER )
+FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL )
 
        .text
        .arch i386
        .code32
-       
-/**************************************************************************
-SETJMP - Save stack context for non-local goto
-**************************************************************************/
+
+       /* Must match jmp_buf structure layout */
+       .struct 0
+env_retaddr:   .long   0
+env_stack:     .long   0
+env_ebx:       .long   0
+env_esi:       .long   0
+env_edi:       .long   0
+env_ebp:       .long   0
+       .previous
+
+/*
+ * Save stack context for non-local goto
+ */
        .globl  setjmp
 setjmp:
-       movl    4(%esp),%ecx            /* jmpbuf */
-       movl    0(%esp),%edx            /* return address */
-       movl    %edx,0(%ecx)
-       movl    %ebx,4(%ecx)
-       movl    %esp,8(%ecx)
-       movl    %ebp,12(%ecx)
-       movl    %esi,16(%ecx)
-       movl    %edi,20(%ecx)
-       movl    $0,%eax
+       /* Get jmp_buf pointer in %edx */
+       movl    4(%esp),%edx
+       /* Save return address */
+       movl    0(%esp),%eax
+       movl    %eax, env_retaddr(%edx)
+       /* Save stack pointer */
+       movl    %esp, env_stack(%edx)
+       /* Save other registers */
+       movl    %ebx, env_ebx(%edx)
+       movl    %esi, env_esi(%edx)
+       movl    %edi, env_edi(%edx)
+       movl    %ebp, env_ebp(%edx)
+       /* Return 0 when returning as setjmp() */
+       xorl    %eax, %eax
        ret
+       .size   setjmp, . - setjmp
 
-/**************************************************************************
-LONGJMP - Non-local jump to a saved stack context
-**************************************************************************/
+/*
+ * Non-local jump to a saved stack context
+ */
        .globl  longjmp
 longjmp:
-       movl    4(%esp),%edx            /* jumpbuf */
-       movl    8(%esp),%eax            /* result */
-       movl    0(%edx),%ecx
-       movl    4(%edx),%ebx
-       movl    8(%edx),%esp
-       movl    12(%edx),%ebp
-       movl    16(%edx),%esi
-       movl    20(%edx),%edi
-       cmpl    $0,%eax
-       jne     1f
-       movl    $1,%eax
-1:     movl    %ecx,0(%esp)
+       /* Get jmp_buf pointer in %edx */
+       movl    4(%esp),%edx
+       /* Get result in %eax */
+       movl    8(%esp),%eax
+       /* Force result to non-zero */
+       testl   %eax, %eax
+       jnz     1f
+       incl    %eax
+1:     /* Restore stack pointer */
+       movl    env_stack(%edx), %esp
+       /* Restore other registers */
+       movl    env_ebx(%edx), %esp
+       movl    env_esi(%edx), %esp
+       movl    env_edi(%edx), %esp
+       movl    env_ebp(%edx), %ebp
+       /* Replace return address on the new stack */
+       popl    %ecx    /* discard */
+       pushl   env_retaddr(%edx)
+       /* Return to setjmp() caller */
        ret
+       .size   longjmp, . - longjmp
index 5d3c11b69b086995dedd8eed6d83d178f7781eae..fe1a9ef4d8dcdb7d163a04242564e502408a1296 100644 (file)
@@ -1,40 +1,50 @@
-#ifndef ETHERBOOT_SETJMP_H
-#define ETHERBOOT_SETJMP_H
+#ifndef _SETJMP_H
+#define _SETJMP_H
 
-FILE_LICENCE ( GPL2_OR_LATER );
+FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
 
 #include <stdint.h>
 #include <realmode.h>
 
 /** A jump buffer */
 typedef struct {
+       /** Saved return address */
        uint32_t retaddr;
+       /** Saved stack pointer */
+       uint32_t stack;
+       /** Saved %ebx */
        uint32_t ebx;
-       uint32_t esp;
-       uint32_t ebp;
+       /** Saved %esi */
        uint32_t esi;
+       /** Saved %edi */
        uint32_t edi;
+       /** Saved %ebp */
+       uint32_t ebp;
 } jmp_buf[1];
 
 /** A real-mode-extended jump buffer */
 typedef struct {
+       /** Jump buffer */
        jmp_buf env;
-       uint16_t rm_ss;
-       uint16_t rm_sp;
+       /** Real-mode stack pointer */
+       segoff_t rm_stack;
 } rmjmp_buf[1];
 
-extern int __asmcall setjmp ( jmp_buf env );
-extern void __asmcall longjmp ( jmp_buf env, int val );
+extern int __asmcall __attribute__ (( returns_twice ))
+setjmp ( jmp_buf env );
+
+extern void __asmcall __attribute__ (( noreturn ))
+longjmp ( jmp_buf env, int val );
 
-#define rmsetjmp( _env ) ( {                   \
-       (_env)->rm_ss = rm_ss;                  \
-       (_env)->rm_sp = rm_sp;                  \
-       setjmp ( (_env)->env ); } )             \
+#define rmsetjmp( _env ) ( {                                   \
+       (_env)->rm_stack.segment = rm_ss;                       \
+       (_env)->rm_stack.offset = rm_sp;                        \
+       setjmp ( (_env)->env ); } )                             \
 
-#define rmlongjmp( _env, _val ) do {           \
-       rm_ss = (_env)->rm_ss;                  \
-       rm_sp = (_env)->rm_sp;                  \
-       longjmp ( (_env)->env, (_val) );        \
+#define rmlongjmp( _env, _val ) do {                           \
+       rm_ss = (_env)->rm_stack.segment;                       \
+       rm_sp = (_env)->rm_stack.offset;                        \
+       longjmp ( (_env)->env, (_val) );                        \
        } while ( 0 )
 
-#endif /* ETHERBOOT_SETJMP_H */
+#endif /* _SETJMP_H */