mirror of
https://github.com/ipxe/ipxe
synced 2025-12-25 17:12:40 +03:00
[libc] Rewrite setjmp() and longjmp()
Signed-off-by: Michael Brown <mcb30@ipxe.org>
This commit is contained in:
@@ -1,42 +1,64 @@
|
|||||||
/* setjmp and longjmp. Use of these functions is deprecated. */
|
FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL )
|
||||||
|
|
||||||
FILE_LICENCE ( GPL2_OR_LATER )
|
|
||||||
|
|
||||||
.text
|
.text
|
||||||
.arch i386
|
.arch i386
|
||||||
.code32
|
.code32
|
||||||
|
|
||||||
/**************************************************************************
|
/* Must match jmp_buf structure layout */
|
||||||
SETJMP - Save stack context for non-local goto
|
.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
|
.globl setjmp
|
||||||
setjmp:
|
setjmp:
|
||||||
movl 4(%esp),%ecx /* jmpbuf */
|
/* Get jmp_buf pointer in %edx */
|
||||||
movl 0(%esp),%edx /* return address */
|
movl 4(%esp),%edx
|
||||||
movl %edx,0(%ecx)
|
/* Save return address */
|
||||||
movl %ebx,4(%ecx)
|
movl 0(%esp),%eax
|
||||||
movl %esp,8(%ecx)
|
movl %eax, env_retaddr(%edx)
|
||||||
movl %ebp,12(%ecx)
|
/* Save stack pointer */
|
||||||
movl %esi,16(%ecx)
|
movl %esp, env_stack(%edx)
|
||||||
movl %edi,20(%ecx)
|
/* Save other registers */
|
||||||
movl $0,%eax
|
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
|
ret
|
||||||
|
.size setjmp, . - setjmp
|
||||||
|
|
||||||
/**************************************************************************
|
/*
|
||||||
LONGJMP - Non-local jump to a saved stack context
|
* Non-local jump to a saved stack context
|
||||||
**************************************************************************/
|
*/
|
||||||
.globl longjmp
|
.globl longjmp
|
||||||
longjmp:
|
longjmp:
|
||||||
movl 4(%esp),%edx /* jumpbuf */
|
/* Get jmp_buf pointer in %edx */
|
||||||
movl 8(%esp),%eax /* result */
|
movl 4(%esp),%edx
|
||||||
movl 0(%edx),%ecx
|
/* Get result in %eax */
|
||||||
movl 4(%edx),%ebx
|
movl 8(%esp),%eax
|
||||||
movl 8(%edx),%esp
|
/* Force result to non-zero */
|
||||||
movl 12(%edx),%ebp
|
testl %eax, %eax
|
||||||
movl 16(%edx),%esi
|
jnz 1f
|
||||||
movl 20(%edx),%edi
|
incl %eax
|
||||||
cmpl $0,%eax
|
1: /* Restore stack pointer */
|
||||||
jne 1f
|
movl env_stack(%edx), %esp
|
||||||
movl $1,%eax
|
/* Restore other registers */
|
||||||
1: movl %ecx,0(%esp)
|
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
|
ret
|
||||||
|
.size longjmp, . - longjmp
|
||||||
|
|||||||
@@ -1,40 +1,50 @@
|
|||||||
#ifndef ETHERBOOT_SETJMP_H
|
#ifndef _SETJMP_H
|
||||||
#define ETHERBOOT_SETJMP_H
|
#define _SETJMP_H
|
||||||
|
|
||||||
FILE_LICENCE ( GPL2_OR_LATER );
|
FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <realmode.h>
|
#include <realmode.h>
|
||||||
|
|
||||||
/** A jump buffer */
|
/** A jump buffer */
|
||||||
typedef struct {
|
typedef struct {
|
||||||
|
/** Saved return address */
|
||||||
uint32_t retaddr;
|
uint32_t retaddr;
|
||||||
|
/** Saved stack pointer */
|
||||||
|
uint32_t stack;
|
||||||
|
/** Saved %ebx */
|
||||||
uint32_t ebx;
|
uint32_t ebx;
|
||||||
uint32_t esp;
|
/** Saved %esi */
|
||||||
uint32_t ebp;
|
|
||||||
uint32_t esi;
|
uint32_t esi;
|
||||||
|
/** Saved %edi */
|
||||||
uint32_t edi;
|
uint32_t edi;
|
||||||
|
/** Saved %ebp */
|
||||||
|
uint32_t ebp;
|
||||||
} jmp_buf[1];
|
} jmp_buf[1];
|
||||||
|
|
||||||
/** A real-mode-extended jump buffer */
|
/** A real-mode-extended jump buffer */
|
||||||
typedef struct {
|
typedef struct {
|
||||||
|
/** Jump buffer */
|
||||||
jmp_buf env;
|
jmp_buf env;
|
||||||
uint16_t rm_ss;
|
/** Real-mode stack pointer */
|
||||||
uint16_t rm_sp;
|
segoff_t rm_stack;
|
||||||
} rmjmp_buf[1];
|
} rmjmp_buf[1];
|
||||||
|
|
||||||
extern int __asmcall setjmp ( jmp_buf env );
|
extern int __asmcall __attribute__ (( returns_twice ))
|
||||||
extern void __asmcall longjmp ( jmp_buf env, int val );
|
setjmp ( jmp_buf env );
|
||||||
|
|
||||||
#define rmsetjmp( _env ) ( { \
|
extern void __asmcall __attribute__ (( noreturn ))
|
||||||
(_env)->rm_ss = rm_ss; \
|
longjmp ( jmp_buf env, int val );
|
||||||
(_env)->rm_sp = rm_sp; \
|
|
||||||
setjmp ( (_env)->env ); } ) \
|
|
||||||
|
|
||||||
#define rmlongjmp( _env, _val ) do { \
|
#define rmsetjmp( _env ) ( { \
|
||||||
rm_ss = (_env)->rm_ss; \
|
(_env)->rm_stack.segment = rm_ss; \
|
||||||
rm_sp = (_env)->rm_sp; \
|
(_env)->rm_stack.offset = rm_sp; \
|
||||||
longjmp ( (_env)->env, (_val) ); \
|
setjmp ( (_env)->env ); } ) \
|
||||||
|
|
||||||
|
#define rmlongjmp( _env, _val ) do { \
|
||||||
|
rm_ss = (_env)->rm_stack.segment; \
|
||||||
|
rm_sp = (_env)->rm_stack.offset; \
|
||||||
|
longjmp ( (_env)->env, (_val) ); \
|
||||||
} while ( 0 )
|
} while ( 0 )
|
||||||
|
|
||||||
#endif /* ETHERBOOT_SETJMP_H */
|
#endif /* _SETJMP_H */
|
||||||
|
|||||||
Reference in New Issue
Block a user