diff options
author | Jeff Dike <jdike@addtoit.com> | 2006-09-26 02:32:59 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@g5.osdl.org> | 2006-09-26 11:49:05 -0400 |
commit | 13c06be399902c9ebda08e092edb1614bb4a3761 (patch) | |
tree | c67134cfb7efd23ab7017fde32657fa3a7e58154 /arch/um | |
parent | c5c6ba4e08ab9c9e390a0f3a7d9a5c332f5cc6ef (diff) |
[PATCH] uml: Use klibc setjmp/longjmp
This patch adds an implementation of setjmp and longjmp to UML, allowing
access to the inside of a jmpbuf without needing the access macros formerly
provided by libc.
The implementation is stolen from klibc. I copy the relevant files into
arch/um. I have another patch which avoids the copying, but requires klibc be
in the tree.
setjmp and longjmp users required some tweaking. Includes of <setjmp.h> were
removed and includes of the UML longjmp.h were added where necessary. There
are also replacements of siglongjmp with UML_LONGJMP which I somehow missed
earlier.
Signed-off-by: Jeff Dike <jdike@addtoit.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'arch/um')
-rw-r--r-- | arch/um/include/longjmp.h | 5 | ||||
-rw-r--r-- | arch/um/include/sysdep-i386/archsetjmp.h | 19 | ||||
-rw-r--r-- | arch/um/include/sysdep-x86_64/archsetjmp.h | 21 | ||||
-rw-r--r-- | arch/um/os-Linux/process.c | 1 | ||||
-rw-r--r-- | arch/um/os-Linux/skas/process.c | 3 | ||||
-rw-r--r-- | arch/um/os-Linux/sys-i386/registers.c | 10 | ||||
-rw-r--r-- | arch/um/os-Linux/sys-x86_64/registers.c | 10 | ||||
-rw-r--r-- | arch/um/os-Linux/trap.c | 1 | ||||
-rw-r--r-- | arch/um/os-Linux/uaccess.c | 3 | ||||
-rw-r--r-- | arch/um/os-Linux/util.c | 5 | ||||
-rw-r--r-- | arch/um/sys-i386/Makefile | 2 | ||||
-rw-r--r-- | arch/um/sys-i386/setjmp.S | 58 | ||||
-rw-r--r-- | arch/um/sys-x86_64/Makefile | 4 | ||||
-rw-r--r-- | arch/um/sys-x86_64/setjmp.S | 54 |
14 files changed, 173 insertions, 23 deletions
diff --git a/arch/um/include/longjmp.h b/arch/um/include/longjmp.h index 1b5c0131a12e..e93c6d3e893b 100644 --- a/arch/um/include/longjmp.h +++ b/arch/um/include/longjmp.h | |||
@@ -1,9 +1,12 @@ | |||
1 | #ifndef __UML_LONGJMP_H | 1 | #ifndef __UML_LONGJMP_H |
2 | #define __UML_LONGJMP_H | 2 | #define __UML_LONGJMP_H |
3 | 3 | ||
4 | #include <setjmp.h> | 4 | #include "sysdep/archsetjmp.h" |
5 | #include "os.h" | 5 | #include "os.h" |
6 | 6 | ||
7 | extern int setjmp(jmp_buf); | ||
8 | extern void longjmp(jmp_buf, int); | ||
9 | |||
7 | #define UML_LONGJMP(buf, val) do { \ | 10 | #define UML_LONGJMP(buf, val) do { \ |
8 | longjmp(*buf, val); \ | 11 | longjmp(*buf, val); \ |
9 | } while(0) | 12 | } while(0) |
diff --git a/arch/um/include/sysdep-i386/archsetjmp.h b/arch/um/include/sysdep-i386/archsetjmp.h new file mode 100644 index 000000000000..ea1ba3d42aee --- /dev/null +++ b/arch/um/include/sysdep-i386/archsetjmp.h | |||
@@ -0,0 +1,19 @@ | |||
1 | /* | ||
2 | * arch/i386/include/klibc/archsetjmp.h | ||
3 | */ | ||
4 | |||
5 | #ifndef _KLIBC_ARCHSETJMP_H | ||
6 | #define _KLIBC_ARCHSETJMP_H | ||
7 | |||
8 | struct __jmp_buf { | ||
9 | unsigned int __ebx; | ||
10 | unsigned int __esp; | ||
11 | unsigned int __ebp; | ||
12 | unsigned int __esi; | ||
13 | unsigned int __edi; | ||
14 | unsigned int __eip; | ||
15 | }; | ||
16 | |||
17 | typedef struct __jmp_buf jmp_buf[1]; | ||
18 | |||
19 | #endif /* _SETJMP_H */ | ||
diff --git a/arch/um/include/sysdep-x86_64/archsetjmp.h b/arch/um/include/sysdep-x86_64/archsetjmp.h new file mode 100644 index 000000000000..454fc60aff6d --- /dev/null +++ b/arch/um/include/sysdep-x86_64/archsetjmp.h | |||
@@ -0,0 +1,21 @@ | |||
1 | /* | ||
2 | * arch/x86_64/include/klibc/archsetjmp.h | ||
3 | */ | ||
4 | |||
5 | #ifndef _KLIBC_ARCHSETJMP_H | ||
6 | #define _KLIBC_ARCHSETJMP_H | ||
7 | |||
8 | struct __jmp_buf { | ||
9 | unsigned long __rbx; | ||
10 | unsigned long __rsp; | ||
11 | unsigned long __rbp; | ||
12 | unsigned long __r12; | ||
13 | unsigned long __r13; | ||
14 | unsigned long __r14; | ||
15 | unsigned long __r15; | ||
16 | unsigned long __rip; | ||
17 | }; | ||
18 | |||
19 | typedef struct __jmp_buf jmp_buf[1]; | ||
20 | |||
21 | #endif /* _SETJMP_H */ | ||
diff --git a/arch/um/os-Linux/process.c b/arch/um/os-Linux/process.c index b98d3ca2cd1b..3afde92ad2c0 100644 --- a/arch/um/os-Linux/process.c +++ b/arch/um/os-Linux/process.c | |||
@@ -7,7 +7,6 @@ | |||
7 | #include <stdio.h> | 7 | #include <stdio.h> |
8 | #include <errno.h> | 8 | #include <errno.h> |
9 | #include <signal.h> | 9 | #include <signal.h> |
10 | #include <setjmp.h> | ||
11 | #include <linux/unistd.h> | 10 | #include <linux/unistd.h> |
12 | #include <sys/mman.h> | 11 | #include <sys/mman.h> |
13 | #include <sys/wait.h> | 12 | #include <sys/wait.h> |
diff --git a/arch/um/os-Linux/skas/process.c b/arch/um/os-Linux/skas/process.c index 7baf90fda58b..50418a5e7134 100644 --- a/arch/um/os-Linux/skas/process.c +++ b/arch/um/os-Linux/skas/process.c | |||
@@ -8,7 +8,6 @@ | |||
8 | #include <unistd.h> | 8 | #include <unistd.h> |
9 | #include <errno.h> | 9 | #include <errno.h> |
10 | #include <signal.h> | 10 | #include <signal.h> |
11 | #include <setjmp.h> | ||
12 | #include <sched.h> | 11 | #include <sched.h> |
13 | #include "ptrace_user.h" | 12 | #include "ptrace_user.h" |
14 | #include <sys/wait.h> | 13 | #include <sys/wait.h> |
@@ -470,7 +469,7 @@ void thread_wait(void *sw, void *fb) | |||
470 | *switch_buf = &buf; | 469 | *switch_buf = &buf; |
471 | fork_buf = fb; | 470 | fork_buf = fb; |
472 | if(UML_SETJMP(&buf) == 0) | 471 | if(UML_SETJMP(&buf) == 0) |
473 | siglongjmp(*fork_buf, INIT_JMP_REMOVE_SIGSTACK); | 472 | UML_LONGJMP(fork_buf, INIT_JMP_REMOVE_SIGSTACK); |
474 | } | 473 | } |
475 | 474 | ||
476 | void switch_threads(void *me, void *next) | 475 | void switch_threads(void *me, void *next) |
diff --git a/arch/um/os-Linux/sys-i386/registers.c b/arch/um/os-Linux/sys-i386/registers.c index 516f66dd87e3..1f90a2d71386 100644 --- a/arch/um/os-Linux/sys-i386/registers.c +++ b/arch/um/os-Linux/sys-i386/registers.c | |||
@@ -5,12 +5,12 @@ | |||
5 | 5 | ||
6 | #include <errno.h> | 6 | #include <errno.h> |
7 | #include <string.h> | 7 | #include <string.h> |
8 | #include <setjmp.h> | ||
9 | #include "sysdep/ptrace_user.h" | 8 | #include "sysdep/ptrace_user.h" |
10 | #include "sysdep/ptrace.h" | 9 | #include "sysdep/ptrace.h" |
11 | #include "uml-config.h" | 10 | #include "uml-config.h" |
12 | #include "skas_ptregs.h" | 11 | #include "skas_ptregs.h" |
13 | #include "registers.h" | 12 | #include "registers.h" |
13 | #include "longjmp.h" | ||
14 | #include "user.h" | 14 | #include "user.h" |
15 | 15 | ||
16 | /* These are set once at boot time and not changed thereafter */ | 16 | /* These are set once at boot time and not changed thereafter */ |
@@ -132,9 +132,9 @@ void get_safe_registers(unsigned long *regs, unsigned long *fp_regs) | |||
132 | 132 | ||
133 | void get_thread_regs(union uml_pt_regs *uml_regs, void *buffer) | 133 | void get_thread_regs(union uml_pt_regs *uml_regs, void *buffer) |
134 | { | 134 | { |
135 | struct __jmp_buf_tag *jmpbuf = buffer; | 135 | struct __jmp_buf *jmpbuf = buffer; |
136 | 136 | ||
137 | UPT_SET(uml_regs, EIP, jmpbuf->__jmpbuf[JB_PC]); | 137 | UPT_SET(uml_regs, EIP, jmpbuf->__eip); |
138 | UPT_SET(uml_regs, UESP, jmpbuf->__jmpbuf[JB_SP]); | 138 | UPT_SET(uml_regs, UESP, jmpbuf->__esp); |
139 | UPT_SET(uml_regs, EBP, jmpbuf->__jmpbuf[JB_BP]); | 139 | UPT_SET(uml_regs, EBP, jmpbuf->__ebp); |
140 | } | 140 | } |
diff --git a/arch/um/os-Linux/sys-x86_64/registers.c b/arch/um/os-Linux/sys-x86_64/registers.c index becd898d9398..e730447d6c02 100644 --- a/arch/um/os-Linux/sys-x86_64/registers.c +++ b/arch/um/os-Linux/sys-x86_64/registers.c | |||
@@ -5,11 +5,11 @@ | |||
5 | 5 | ||
6 | #include <errno.h> | 6 | #include <errno.h> |
7 | #include <string.h> | 7 | #include <string.h> |
8 | #include <setjmp.h> | ||
9 | #include "ptrace_user.h" | 8 | #include "ptrace_user.h" |
10 | #include "uml-config.h" | 9 | #include "uml-config.h" |
11 | #include "skas_ptregs.h" | 10 | #include "skas_ptregs.h" |
12 | #include "registers.h" | 11 | #include "registers.h" |
12 | #include "longjmp.h" | ||
13 | #include "user.h" | 13 | #include "user.h" |
14 | 14 | ||
15 | /* These are set once at boot time and not changed thereafter */ | 15 | /* These are set once at boot time and not changed thereafter */ |
@@ -80,9 +80,9 @@ void get_safe_registers(unsigned long *regs, unsigned long *fp_regs) | |||
80 | 80 | ||
81 | void get_thread_regs(union uml_pt_regs *uml_regs, void *buffer) | 81 | void get_thread_regs(union uml_pt_regs *uml_regs, void *buffer) |
82 | { | 82 | { |
83 | struct __jmp_buf_tag *jmpbuf = buffer; | 83 | struct __jmp_buf *jmpbuf = buffer; |
84 | 84 | ||
85 | UPT_SET(uml_regs, RIP, jmpbuf->__jmpbuf[JB_PC]); | 85 | UPT_SET(uml_regs, RIP, jmpbuf->__rip); |
86 | UPT_SET(uml_regs, RSP, jmpbuf->__jmpbuf[JB_RSP]); | 86 | UPT_SET(uml_regs, RSP, jmpbuf->__rsp); |
87 | UPT_SET(uml_regs, RBP, jmpbuf->__jmpbuf[JB_RBP]); | 87 | UPT_SET(uml_regs, RBP, jmpbuf->__rbp); |
88 | } | 88 | } |
diff --git a/arch/um/os-Linux/trap.c b/arch/um/os-Linux/trap.c index 90b29ae9af46..1df231a26244 100644 --- a/arch/um/os-Linux/trap.c +++ b/arch/um/os-Linux/trap.c | |||
@@ -5,7 +5,6 @@ | |||
5 | 5 | ||
6 | #include <stdlib.h> | 6 | #include <stdlib.h> |
7 | #include <signal.h> | 7 | #include <signal.h> |
8 | #include <setjmp.h> | ||
9 | #include "kern_util.h" | 8 | #include "kern_util.h" |
10 | #include "user_util.h" | 9 | #include "user_util.h" |
11 | #include "os.h" | 10 | #include "os.h" |
diff --git a/arch/um/os-Linux/uaccess.c b/arch/um/os-Linux/uaccess.c index 865f6a6a2590..bbb73a650370 100644 --- a/arch/um/os-Linux/uaccess.c +++ b/arch/um/os-Linux/uaccess.c | |||
@@ -4,8 +4,7 @@ | |||
4 | * Licensed under the GPL | 4 | * Licensed under the GPL |
5 | */ | 5 | */ |
6 | 6 | ||
7 | #include <setjmp.h> | 7 | #include <stddef.h> |
8 | #include <string.h> | ||
9 | #include "longjmp.h" | 8 | #include "longjmp.h" |
10 | 9 | ||
11 | unsigned long __do_user_copy(void *to, const void *from, int n, | 10 | unsigned long __do_user_copy(void *to, const void *from, int n, |
diff --git a/arch/um/os-Linux/util.c b/arch/um/os-Linux/util.c index c47a2a7ce70e..3f5b1514e8a7 100644 --- a/arch/um/os-Linux/util.c +++ b/arch/um/os-Linux/util.c | |||
@@ -7,7 +7,6 @@ | |||
7 | #include <stdlib.h> | 7 | #include <stdlib.h> |
8 | #include <unistd.h> | 8 | #include <unistd.h> |
9 | #include <limits.h> | 9 | #include <limits.h> |
10 | #include <setjmp.h> | ||
11 | #include <sys/mman.h> | 10 | #include <sys/mman.h> |
12 | #include <sys/stat.h> | 11 | #include <sys/stat.h> |
13 | #include <sys/utsname.h> | 12 | #include <sys/utsname.h> |
@@ -107,11 +106,11 @@ int setjmp_wrapper(void (*proc)(void *, void *), ...) | |||
107 | jmp_buf buf; | 106 | jmp_buf buf; |
108 | int n; | 107 | int n; |
109 | 108 | ||
110 | n = sigsetjmp(buf, 1); | 109 | n = UML_SETJMP(&buf); |
111 | if(n == 0){ | 110 | if(n == 0){ |
112 | va_start(args, proc); | 111 | va_start(args, proc); |
113 | (*proc)(&buf, &args); | 112 | (*proc)(&buf, &args); |
114 | } | 113 | } |
115 | va_end(args); | 114 | va_end(args); |
116 | return(n); | 115 | return n; |
117 | } | 116 | } |
diff --git a/arch/um/sys-i386/Makefile b/arch/um/sys-i386/Makefile index 374d61a19439..59cc70275754 100644 --- a/arch/um/sys-i386/Makefile +++ b/arch/um/sys-i386/Makefile | |||
@@ -1,5 +1,5 @@ | |||
1 | obj-y = bugs.o checksum.o delay.o fault.o ksyms.o ldt.o ptrace.o \ | 1 | obj-y = bugs.o checksum.o delay.o fault.o ksyms.o ldt.o ptrace.o \ |
2 | ptrace_user.o signal.o sigcontext.o syscalls.o sysrq.o \ | 2 | ptrace_user.o setjmp.o signal.o sigcontext.o syscalls.o sysrq.o \ |
3 | sys_call_table.o tls.o | 3 | sys_call_table.o tls.o |
4 | 4 | ||
5 | obj-$(CONFIG_MODE_SKAS) += stub.o stub_segv.o | 5 | obj-$(CONFIG_MODE_SKAS) += stub.o stub_segv.o |
diff --git a/arch/um/sys-i386/setjmp.S b/arch/um/sys-i386/setjmp.S new file mode 100644 index 000000000000..b766792c9933 --- /dev/null +++ b/arch/um/sys-i386/setjmp.S | |||
@@ -0,0 +1,58 @@ | |||
1 | # | ||
2 | # arch/i386/setjmp.S | ||
3 | # | ||
4 | # setjmp/longjmp for the i386 architecture | ||
5 | # | ||
6 | |||
7 | # | ||
8 | # The jmp_buf is assumed to contain the following, in order: | ||
9 | # %ebx | ||
10 | # %esp | ||
11 | # %ebp | ||
12 | # %esi | ||
13 | # %edi | ||
14 | # <return address> | ||
15 | # | ||
16 | |||
17 | .text | ||
18 | .align 4 | ||
19 | .globl setjmp | ||
20 | .type setjmp, @function | ||
21 | setjmp: | ||
22 | #ifdef _REGPARM | ||
23 | movl %eax,%edx | ||
24 | #else | ||
25 | movl 4(%esp),%edx | ||
26 | #endif | ||
27 | popl %ecx # Return address, and adjust the stack | ||
28 | xorl %eax,%eax # Return value | ||
29 | movl %ebx,(%edx) | ||
30 | movl %esp,4(%edx) # Post-return %esp! | ||
31 | pushl %ecx # Make the call/return stack happy | ||
32 | movl %ebp,8(%edx) | ||
33 | movl %esi,12(%edx) | ||
34 | movl %edi,16(%edx) | ||
35 | movl %ecx,20(%edx) # Return address | ||
36 | ret | ||
37 | |||
38 | .size setjmp,.-setjmp | ||
39 | |||
40 | .text | ||
41 | .align 4 | ||
42 | .globl longjmp | ||
43 | .type longjmp, @function | ||
44 | longjmp: | ||
45 | #ifdef _REGPARM | ||
46 | xchgl %eax,%edx | ||
47 | #else | ||
48 | movl 4(%esp),%edx # jmp_ptr address | ||
49 | movl 8(%esp),%eax # Return value | ||
50 | #endif | ||
51 | movl (%edx),%ebx | ||
52 | movl 4(%edx),%esp | ||
53 | movl 8(%edx),%ebp | ||
54 | movl 12(%edx),%esi | ||
55 | movl 16(%edx),%edi | ||
56 | jmp *20(%edx) | ||
57 | |||
58 | .size longjmp,.-longjmp | ||
diff --git a/arch/um/sys-x86_64/Makefile b/arch/um/sys-x86_64/Makefile index c19794d435d6..f41768b8e25e 100644 --- a/arch/um/sys-x86_64/Makefile +++ b/arch/um/sys-x86_64/Makefile | |||
@@ -5,8 +5,8 @@ | |||
5 | # | 5 | # |
6 | 6 | ||
7 | obj-y = bugs.o delay.o fault.o ldt.o mem.o ptrace.o ptrace_user.o \ | 7 | obj-y = bugs.o delay.o fault.o ldt.o mem.o ptrace.o ptrace_user.o \ |
8 | sigcontext.o signal.o syscalls.o syscall_table.o sysrq.o ksyms.o \ | 8 | setjmp.o sigcontext.o signal.o syscalls.o syscall_table.o sysrq.o \ |
9 | tls.o | 9 | ksyms.o tls.o |
10 | 10 | ||
11 | obj-$(CONFIG_MODE_SKAS) += stub.o stub_segv.o | 11 | obj-$(CONFIG_MODE_SKAS) += stub.o stub_segv.o |
12 | obj-$(CONFIG_MODULES) += um_module.o | 12 | obj-$(CONFIG_MODULES) += um_module.o |
diff --git a/arch/um/sys-x86_64/setjmp.S b/arch/um/sys-x86_64/setjmp.S new file mode 100644 index 000000000000..45f547b4043e --- /dev/null +++ b/arch/um/sys-x86_64/setjmp.S | |||
@@ -0,0 +1,54 @@ | |||
1 | # | ||
2 | # arch/x86_64/setjmp.S | ||
3 | # | ||
4 | # setjmp/longjmp for the x86-64 architecture | ||
5 | # | ||
6 | |||
7 | # | ||
8 | # The jmp_buf is assumed to contain the following, in order: | ||
9 | # %rbx | ||
10 | # %rsp (post-return) | ||
11 | # %rbp | ||
12 | # %r12 | ||
13 | # %r13 | ||
14 | # %r14 | ||
15 | # %r15 | ||
16 | # <return address> | ||
17 | # | ||
18 | |||
19 | .text | ||
20 | .align 4 | ||
21 | .globl setjmp | ||
22 | .type setjmp, @function | ||
23 | setjmp: | ||
24 | pop %rsi # Return address, and adjust the stack | ||
25 | xorl %eax,%eax # Return value | ||
26 | movq %rbx,(%rdi) | ||
27 | movq %rsp,8(%rdi) # Post-return %rsp! | ||
28 | push %rsi # Make the call/return stack happy | ||
29 | movq %rbp,16(%rdi) | ||
30 | movq %r12,24(%rdi) | ||
31 | movq %r13,32(%rdi) | ||
32 | movq %r14,40(%rdi) | ||
33 | movq %r15,48(%rdi) | ||
34 | movq %rsi,56(%rdi) # Return address | ||
35 | ret | ||
36 | |||
37 | .size setjmp,.-setjmp | ||
38 | |||
39 | .text | ||
40 | .align 4 | ||
41 | .globl longjmp | ||
42 | .type longjmp, @function | ||
43 | longjmp: | ||
44 | movl %esi,%eax # Return value (int) | ||
45 | movq (%rdi),%rbx | ||
46 | movq 8(%rdi),%rsp | ||
47 | movq 16(%rdi),%rbp | ||
48 | movq 24(%rdi),%r12 | ||
49 | movq 32(%rdi),%r13 | ||
50 | movq 40(%rdi),%r14 | ||
51 | movq 48(%rdi),%r15 | ||
52 | jmp *56(%rdi) | ||
53 | |||
54 | .size longjmp,.-longjmp | ||