diff options
Diffstat (limited to 'arch/um/sys-i386/ptrace.c')
-rw-r--r-- | arch/um/sys-i386/ptrace.c | 109 |
1 files changed, 47 insertions, 62 deletions
diff --git a/arch/um/sys-i386/ptrace.c b/arch/um/sys-i386/ptrace.c index dcf0c6b310c8..178f894384f4 100644 --- a/arch/um/sys-i386/ptrace.c +++ b/arch/um/sys-i386/ptrace.c | |||
@@ -1,18 +1,11 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com) | 2 | * Copyright (C) 2000 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) |
3 | * Licensed under the GPL | 3 | * Licensed under the GPL |
4 | */ | 4 | */ |
5 | 5 | ||
6 | #include <linux/compiler.h> | ||
7 | #include "linux/sched.h" | ||
8 | #include "linux/mm.h" | 6 | #include "linux/mm.h" |
9 | #include "asm/elf.h" | 7 | #include "linux/sched.h" |
10 | #include "asm/ptrace.h" | ||
11 | #include "asm/uaccess.h" | 8 | #include "asm/uaccess.h" |
12 | #include "asm/unistd.h" | ||
13 | #include "sysdep/ptrace.h" | ||
14 | #include "sysdep/sigcontext.h" | ||
15 | #include "sysdep/sc.h" | ||
16 | 9 | ||
17 | extern int arch_switch_tls(struct task_struct *from, struct task_struct *to); | 10 | extern int arch_switch_tls(struct task_struct *from, struct task_struct *to); |
18 | 11 | ||
@@ -23,7 +16,8 @@ void arch_switch_to(struct task_struct *from, struct task_struct *to) | |||
23 | return; | 16 | return; |
24 | 17 | ||
25 | if (err != -EINVAL) | 18 | if (err != -EINVAL) |
26 | printk(KERN_WARNING "arch_switch_tls failed, errno %d, not EINVAL\n", -err); | 19 | printk(KERN_WARNING "arch_switch_tls failed, errno %d, " |
20 | "not EINVAL\n", -err); | ||
27 | else | 21 | else |
28 | printk(KERN_WARNING "arch_switch_tls failed, errno = EINVAL\n"); | 22 | printk(KERN_WARNING "arch_switch_tls failed, errno = EINVAL\n"); |
29 | } | 23 | } |
@@ -34,21 +28,21 @@ int is_syscall(unsigned long addr) | |||
34 | int n; | 28 | int n; |
35 | 29 | ||
36 | n = copy_from_user(&instr, (void __user *) addr, sizeof(instr)); | 30 | n = copy_from_user(&instr, (void __user *) addr, sizeof(instr)); |
37 | if(n){ | 31 | if (n) { |
38 | /* access_process_vm() grants access to vsyscall and stub, | 32 | /* access_process_vm() grants access to vsyscall and stub, |
39 | * while copy_from_user doesn't. Maybe access_process_vm is | 33 | * while copy_from_user doesn't. Maybe access_process_vm is |
40 | * slow, but that doesn't matter, since it will be called only | 34 | * slow, but that doesn't matter, since it will be called only |
41 | * in case of singlestepping, if copy_from_user failed. | 35 | * in case of singlestepping, if copy_from_user failed. |
42 | */ | 36 | */ |
43 | n = access_process_vm(current, addr, &instr, sizeof(instr), 0); | 37 | n = access_process_vm(current, addr, &instr, sizeof(instr), 0); |
44 | if(n != sizeof(instr)) { | 38 | if (n != sizeof(instr)) { |
45 | printk("is_syscall : failed to read instruction from " | 39 | printk(KERN_ERR "is_syscall : failed to read " |
46 | "0x%lx\n", addr); | 40 | "instruction from 0x%lx\n", addr); |
47 | return(1); | 41 | return 1; |
48 | } | 42 | } |
49 | } | 43 | } |
50 | /* int 0x80 or sysenter */ | 44 | /* int 0x80 or sysenter */ |
51 | return((instr == 0x80cd) || (instr == 0x340f)); | 45 | return (instr == 0x80cd) || (instr == 0x340f); |
52 | } | 46 | } |
53 | 47 | ||
54 | /* determines which flags the user has access to. */ | 48 | /* determines which flags the user has access to. */ |
@@ -92,21 +86,21 @@ int putreg(struct task_struct *child, int regno, unsigned long value) | |||
92 | 86 | ||
93 | int poke_user(struct task_struct *child, long addr, long data) | 87 | int poke_user(struct task_struct *child, long addr, long data) |
94 | { | 88 | { |
95 | if ((addr & 3) || addr < 0) | 89 | if ((addr & 3) || addr < 0) |
96 | return -EIO; | 90 | return -EIO; |
97 | 91 | ||
98 | if (addr < MAX_REG_OFFSET) | 92 | if (addr < MAX_REG_OFFSET) |
99 | return putreg(child, addr, data); | 93 | return putreg(child, addr, data); |
100 | 94 | else if ((addr >= offsetof(struct user, u_debugreg[0])) && | |
101 | else if((addr >= offsetof(struct user, u_debugreg[0])) && | 95 | (addr <= offsetof(struct user, u_debugreg[7]))) { |
102 | (addr <= offsetof(struct user, u_debugreg[7]))){ | 96 | addr -= offsetof(struct user, u_debugreg[0]); |
103 | addr -= offsetof(struct user, u_debugreg[0]); | 97 | addr = addr >> 2; |
104 | addr = addr >> 2; | 98 | if ((addr == 4) || (addr == 5)) |
105 | if((addr == 4) || (addr == 5)) return -EIO; | 99 | return -EIO; |
106 | child->thread.arch.debugregs[addr] = data; | 100 | child->thread.arch.debugregs[addr] = data; |
107 | return 0; | 101 | return 0; |
108 | } | 102 | } |
109 | return -EIO; | 103 | return -EIO; |
110 | } | 104 | } |
111 | 105 | ||
112 | unsigned long getreg(struct task_struct *child, int regno) | 106 | unsigned long getreg(struct task_struct *child, int regno) |
@@ -129,20 +123,20 @@ unsigned long getreg(struct task_struct *child, int regno) | |||
129 | return retval; | 123 | return retval; |
130 | } | 124 | } |
131 | 125 | ||
126 | /* read the word at location addr in the USER area. */ | ||
132 | int peek_user(struct task_struct *child, long addr, long data) | 127 | int peek_user(struct task_struct *child, long addr, long data) |
133 | { | 128 | { |
134 | /* read the word at location addr in the USER area. */ | ||
135 | unsigned long tmp; | 129 | unsigned long tmp; |
136 | 130 | ||
137 | if ((addr & 3) || addr < 0) | 131 | if ((addr & 3) || addr < 0) |
138 | return -EIO; | 132 | return -EIO; |
139 | 133 | ||
140 | tmp = 0; /* Default return condition */ | 134 | tmp = 0; /* Default return condition */ |
141 | if(addr < MAX_REG_OFFSET){ | 135 | if (addr < MAX_REG_OFFSET) { |
142 | tmp = getreg(child, addr); | 136 | tmp = getreg(child, addr); |
143 | } | 137 | } |
144 | else if((addr >= offsetof(struct user, u_debugreg[0])) && | 138 | else if ((addr >= offsetof(struct user, u_debugreg[0])) && |
145 | (addr <= offsetof(struct user, u_debugreg[7]))){ | 139 | (addr <= offsetof(struct user, u_debugreg[7]))) { |
146 | addr -= offsetof(struct user, u_debugreg[0]); | 140 | addr -= offsetof(struct user, u_debugreg[0]); |
147 | addr = addr >> 2; | 141 | addr = addr >> 2; |
148 | tmp = child->thread.arch.debugregs[addr]; | 142 | tmp = child->thread.arch.debugregs[addr]; |
@@ -173,15 +167,15 @@ struct i387_fxsave_struct { | |||
173 | static inline unsigned short twd_i387_to_fxsr( unsigned short twd ) | 167 | static inline unsigned short twd_i387_to_fxsr( unsigned short twd ) |
174 | { | 168 | { |
175 | unsigned int tmp; /* to avoid 16 bit prefixes in the code */ | 169 | unsigned int tmp; /* to avoid 16 bit prefixes in the code */ |
176 | 170 | ||
177 | /* Transform each pair of bits into 01 (valid) or 00 (empty) */ | 171 | /* Transform each pair of bits into 01 (valid) or 00 (empty) */ |
178 | tmp = ~twd; | 172 | tmp = ~twd; |
179 | tmp = (tmp | (tmp>>1)) & 0x5555; /* 0V0V0V0V0V0V0V0V */ | 173 | tmp = (tmp | (tmp>>1)) & 0x5555; /* 0V0V0V0V0V0V0V0V */ |
180 | /* and move the valid bits to the lower byte. */ | 174 | /* and move the valid bits to the lower byte. */ |
181 | tmp = (tmp | (tmp >> 1)) & 0x3333; /* 00VV00VV00VV00VV */ | 175 | tmp = (tmp | (tmp >> 1)) & 0x3333; /* 00VV00VV00VV00VV */ |
182 | tmp = (tmp | (tmp >> 2)) & 0x0f0f; /* 0000VVVV0000VVVV */ | 176 | tmp = (tmp | (tmp >> 2)) & 0x0f0f; /* 0000VVVV0000VVVV */ |
183 | tmp = (tmp | (tmp >> 4)) & 0x00ff; /* 00000000VVVVVVVV */ | 177 | tmp = (tmp | (tmp >> 4)) & 0x00ff; /* 00000000VVVVVVVV */ |
184 | return tmp; | 178 | return tmp; |
185 | } | 179 | } |
186 | 180 | ||
187 | static inline unsigned long twd_fxsr_to_i387( struct i387_fxsave_struct *fxsave ) | 181 | static inline unsigned long twd_fxsr_to_i387( struct i387_fxsave_struct *fxsave ) |
@@ -235,7 +229,7 @@ static inline int convert_fxsr_to_user(struct _fpstate __user *buf, | |||
235 | return 0; | 229 | return 0; |
236 | } | 230 | } |
237 | 231 | ||
238 | static inline int convert_fxsr_from_user(struct pt_regs *regs, | 232 | static inline int convert_fxsr_from_user(struct pt_regs *regs, |
239 | struct _fpstate __user *buf) | 233 | struct _fpstate __user *buf) |
240 | { | 234 | { |
241 | return 0; | 235 | return 0; |
@@ -247,18 +241,20 @@ int get_fpregs(unsigned long buf, struct task_struct *child) | |||
247 | 241 | ||
248 | err = convert_fxsr_to_user((struct _fpstate __user *) buf, | 242 | err = convert_fxsr_to_user((struct _fpstate __user *) buf, |
249 | &child->thread.regs); | 243 | &child->thread.regs); |
250 | if(err) return(-EFAULT); | 244 | if (err) |
251 | else return(0); | 245 | return -EFAULT; |
246 | return 0; | ||
252 | } | 247 | } |
253 | 248 | ||
254 | int set_fpregs(unsigned long buf, struct task_struct *child) | 249 | int set_fpregs(unsigned long buf, struct task_struct *child) |
255 | { | 250 | { |
256 | int err; | 251 | int err; |
257 | 252 | ||
258 | err = convert_fxsr_from_user(&child->thread.regs, | 253 | err = convert_fxsr_from_user(&child->thread.regs, |
259 | (struct _fpstate __user *) buf); | 254 | (struct _fpstate __user *) buf); |
260 | if(err) return(-EFAULT); | 255 | if (err) |
261 | else return(0); | 256 | return -EFAULT; |
257 | return 0; | ||
262 | } | 258 | } |
263 | 259 | ||
264 | int get_fpxregs(unsigned long buf, struct task_struct *tsk) | 260 | int get_fpxregs(unsigned long buf, struct task_struct *tsk) |
@@ -284,7 +280,7 @@ int dump_fpu(struct pt_regs *regs, elf_fpregset_t *fpu) | |||
284 | fpu->fos = 0; | 280 | fpu->fos = 0; |
285 | memcpy(fpu->st_space, (void *) SC_FP_ST(PT_REGS_SC(regs)), | 281 | memcpy(fpu->st_space, (void *) SC_FP_ST(PT_REGS_SC(regs)), |
286 | sizeof(fpu->st_space)); | 282 | sizeof(fpu->st_space)); |
287 | return(1); | 283 | return 1; |
288 | } | 284 | } |
289 | #endif | 285 | #endif |
290 | 286 | ||
@@ -292,14 +288,3 @@ int dump_fpu(struct pt_regs *regs, elf_fpregset_t *fpu ) | |||
292 | { | 288 | { |
293 | return 1; | 289 | return 1; |
294 | } | 290 | } |
295 | |||
296 | /* | ||
297 | * Overrides for Emacs so that we follow Linus's tabbing style. | ||
298 | * Emacs will notice this stuff at the end of the file and automatically | ||
299 | * adjust the settings for this buffer only. This must remain at the end | ||
300 | * of the file. | ||
301 | * --------------------------------------------------------------------------- | ||
302 | * Local variables: | ||
303 | * c-file-style: "linux" | ||
304 | * End: | ||
305 | */ | ||