Browse Source

[libc] Rewrite setjmp() and longjmp()

Signed-off-by: Michael Brown <mcb30@ipxe.org>
tags/v1.20.1
Michael Brown 9 years ago
parent
commit
8ab4b00442
2 changed files with 81 additions and 49 deletions
  1. 53
    31
      src/arch/i386/core/setjmp.S
  2. 28
    18
      src/arch/i386/include/setjmp.h

+ 53
- 31
src/arch/i386/core/setjmp.S View File

@@ -1,42 +1,64 @@
1
-/* setjmp and longjmp. Use of these functions is deprecated. */
2
-
3
-FILE_LICENCE ( GPL2_OR_LATER )
1
+FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL )
4 2
 
5 3
 	.text
6 4
 	.arch i386
7 5
 	.code32
8
-	
9
-/**************************************************************************
10
-SETJMP - Save stack context for non-local goto
11
-**************************************************************************/
6
+
7
+	/* Must match jmp_buf structure layout */
8
+	.struct	0
9
+env_retaddr:	.long	0
10
+env_stack:	.long	0
11
+env_ebx:	.long	0
12
+env_esi:	.long	0
13
+env_edi:	.long	0
14
+env_ebp:	.long	0
15
+	.previous
16
+
17
+/*
18
+ * Save stack context for non-local goto
19
+ */
12 20
 	.globl	setjmp
13 21
 setjmp:
14
-	movl	4(%esp),%ecx		/* jmpbuf */
15
-	movl	0(%esp),%edx		/* return address */
16
-	movl	%edx,0(%ecx)
17
-	movl	%ebx,4(%ecx)
18
-	movl	%esp,8(%ecx)
19
-	movl	%ebp,12(%ecx)
20
-	movl	%esi,16(%ecx)
21
-	movl	%edi,20(%ecx)
22
-	movl	$0,%eax
22
+	/* Get jmp_buf pointer in %edx */
23
+	movl	4(%esp),%edx
24
+	/* Save return address */
25
+	movl	0(%esp),%eax
26
+	movl	%eax, env_retaddr(%edx)
27
+	/* Save stack pointer */
28
+	movl	%esp, env_stack(%edx)
29
+	/* Save other registers */
30
+	movl	%ebx, env_ebx(%edx)
31
+	movl	%esi, env_esi(%edx)
32
+	movl	%edi, env_edi(%edx)
33
+	movl	%ebp, env_ebp(%edx)
34
+	/* Return 0 when returning as setjmp() */
35
+	xorl	%eax, %eax
23 36
 	ret
37
+	.size	setjmp, . - setjmp
24 38
 
25
-/**************************************************************************
26
-LONGJMP - Non-local jump to a saved stack context
27
-**************************************************************************/
39
+/*
40
+ * Non-local jump to a saved stack context
41
+ */
28 42
 	.globl	longjmp
29 43
 longjmp:
30
-	movl	4(%esp),%edx		/* jumpbuf */
31
-	movl	8(%esp),%eax		/* result */
32
-	movl	0(%edx),%ecx
33
-	movl	4(%edx),%ebx
34
-	movl	8(%edx),%esp
35
-	movl	12(%edx),%ebp
36
-	movl	16(%edx),%esi
37
-	movl	20(%edx),%edi
38
-	cmpl	$0,%eax
39
-	jne	1f
40
-	movl	$1,%eax
41
-1:	movl	%ecx,0(%esp)
44
+	/* Get jmp_buf pointer in %edx */
45
+	movl	4(%esp),%edx
46
+	/* Get result in %eax */
47
+	movl	8(%esp),%eax
48
+	/* Force result to non-zero */
49
+	testl	%eax, %eax
50
+	jnz	1f
51
+	incl	%eax
52
+1:	/* Restore stack pointer */
53
+	movl	env_stack(%edx), %esp
54
+	/* Restore other registers */
55
+	movl	env_ebx(%edx), %esp
56
+	movl	env_esi(%edx), %esp
57
+	movl	env_edi(%edx), %esp
58
+	movl	env_ebp(%edx), %ebp
59
+	/* Replace return address on the new stack */
60
+	popl	%ecx	/* discard */
61
+	pushl	env_retaddr(%edx)
62
+	/* Return to setjmp() caller */
42 63
 	ret
64
+	.size	longjmp, . - longjmp

+ 28
- 18
src/arch/i386/include/setjmp.h View File

@@ -1,40 +1,50 @@
1
-#ifndef ETHERBOOT_SETJMP_H
2
-#define ETHERBOOT_SETJMP_H
1
+#ifndef _SETJMP_H
2
+#define _SETJMP_H
3 3
 
4
-FILE_LICENCE ( GPL2_OR_LATER );
4
+FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
5 5
 
6 6
 #include <stdint.h>
7 7
 #include <realmode.h>
8 8
 
9 9
 /** A jump buffer */
10 10
 typedef struct {
11
+	/** Saved return address */
11 12
 	uint32_t retaddr;
13
+	/** Saved stack pointer */
14
+	uint32_t stack;
15
+	/** Saved %ebx */
12 16
 	uint32_t ebx;
13
-	uint32_t esp;
14
-	uint32_t ebp;
17
+	/** Saved %esi */
15 18
 	uint32_t esi;
19
+	/** Saved %edi */
16 20
 	uint32_t edi;
21
+	/** Saved %ebp */
22
+	uint32_t ebp;
17 23
 } jmp_buf[1];
18 24
 
19 25
 /** A real-mode-extended jump buffer */
20 26
 typedef struct {
27
+	/** Jump buffer */
21 28
 	jmp_buf env;
22
-	uint16_t rm_ss;
23
-	uint16_t rm_sp;
29
+	/** Real-mode stack pointer */
30
+	segoff_t rm_stack;
24 31
 } rmjmp_buf[1];
25 32
 
26
-extern int __asmcall setjmp ( jmp_buf env );
27
-extern void __asmcall longjmp ( jmp_buf env, int val );
33
+extern int __asmcall __attribute__ (( returns_twice ))
34
+setjmp ( jmp_buf env );
35
+
36
+extern void __asmcall __attribute__ (( noreturn ))
37
+longjmp ( jmp_buf env, int val );
28 38
 
29
-#define rmsetjmp( _env ) ( {			\
30
-	(_env)->rm_ss = rm_ss;			\
31
-	(_env)->rm_sp = rm_sp;			\
32
-	setjmp ( (_env)->env ); } )		\
39
+#define rmsetjmp( _env ) ( {					\
40
+	(_env)->rm_stack.segment = rm_ss;			\
41
+	(_env)->rm_stack.offset = rm_sp;			\
42
+	setjmp ( (_env)->env ); } )				\
33 43
 
34
-#define rmlongjmp( _env, _val ) do {		\
35
-	rm_ss = (_env)->rm_ss;			\
36
-	rm_sp = (_env)->rm_sp;			\
37
-	longjmp ( (_env)->env, (_val) );	\
44
+#define rmlongjmp( _env, _val ) do {				\
45
+	rm_ss = (_env)->rm_stack.segment;			\
46
+	rm_sp = (_env)->rm_stack.offset;			\
47
+	longjmp ( (_env)->env, (_val) );			\
38 48
 	} while ( 0 )
39 49
 
40
-#endif /* ETHERBOOT_SETJMP_H */
50
+#endif /* _SETJMP_H */

Loading…
Cancel
Save