X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=arch%2Fum%2Fsys-i386%2Fptrace.c;h=28bf01150323143d376ed6fdf607c6fab7933af1;hb=97bf2856c6014879bd04983a3e9dfcdac1e7fe85;hp=817ef7479d3fc1b869d9f09cad7767ac50552231;hpb=5273a3df6485dc2ad6aa7ddd441b9a21970f003b;p=linux-2.6.git diff --git a/arch/um/sys-i386/ptrace.c b/arch/um/sys-i386/ptrace.c index 817ef7479..28bf01150 100644 --- a/arch/um/sys-i386/ptrace.c +++ b/arch/um/sys-i386/ptrace.c @@ -3,17 +3,33 @@ * Licensed under the GPL */ +#include #include "linux/sched.h" +#include "linux/mm.h" #include "asm/elf.h" #include "asm/ptrace.h" #include "asm/uaccess.h" -#include "ptrace_user.h" +#include "asm/unistd.h" +#include "sysdep/ptrace.h" #include "sysdep/sigcontext.h" #include "sysdep/sc.h" -void arch_switch(void) +void arch_switch_to_tt(struct task_struct *from, struct task_struct *to) { - update_debugregs(current->thread.arch.debugregs_seq); + update_debugregs(to->thread.arch.debugregs_seq); + arch_switch_tls_tt(from, to); +} + +void arch_switch_to_skas(struct task_struct *from, struct task_struct *to) +{ + int err = arch_switch_tls_skas(from, to); + if (!err) + return; + + if (err != -EINVAL) + printk(KERN_WARNING "arch_switch_tls_skas failed, errno %d, not EINVAL\n", -err); + else + printk(KERN_WARNING "arch_switch_tls_skas failed, errno = EINVAL\n"); } int is_syscall(unsigned long addr) @@ -21,13 +37,22 @@ int is_syscall(unsigned long addr) unsigned short instr; int n; - n = copy_from_user(&instr, (void *) addr, sizeof(instr)); + n = copy_from_user(&instr, (void __user *) addr, sizeof(instr)); if(n){ - printk("is_syscall : failed to read instruction from 0x%lu\n", - addr); - return(0); + /* access_process_vm() grants access to vsyscall and stub, + * while copy_from_user doesn't. Maybe access_process_vm is + * slow, but that doesn't matter, since it will be called only + * in case of singlestepping, if copy_from_user failed. + */ + n = access_process_vm(current, addr, &instr, sizeof(instr), 0); + if(n != sizeof(instr)) { + printk("is_syscall : failed to read instruction from " + "0x%lx\n", addr); + return(1); + } } - return(instr == 0x80cd); + /* int 0x80 or sysenter */ + return((instr == 0x80cd) || (instr == 0x340f)); } /* determines which flags the user has access to. */ @@ -69,6 +94,25 @@ int putreg(struct task_struct *child, int regno, unsigned long value) return 0; } +int poke_user(struct task_struct *child, long addr, long data) +{ + if ((addr & 3) || addr < 0) + return -EIO; + + if (addr < MAX_REG_OFFSET) + return putreg(child, addr, data); + + else if((addr >= offsetof(struct user, u_debugreg[0])) && + (addr <= offsetof(struct user, u_debugreg[7]))){ + addr -= offsetof(struct user, u_debugreg[0]); + addr = addr >> 2; + if((addr == 4) || (addr == 5)) return -EIO; + child->thread.arch.debugregs[addr] = data; + return 0; + } + return -EIO; +} + unsigned long getreg(struct task_struct *child, int regno) { unsigned long retval = ~0UL; @@ -89,6 +133,27 @@ unsigned long getreg(struct task_struct *child, int regno) return retval; } +int peek_user(struct task_struct *child, long addr, long data) +{ +/* read the word at location addr in the USER area. */ + unsigned long tmp; + + if ((addr & 3) || addr < 0) + return -EIO; + + tmp = 0; /* Default return condition */ + if(addr < MAX_REG_OFFSET){ + tmp = getreg(child, addr); + } + else if((addr >= offsetof(struct user, u_debugreg[0])) && + (addr <= offsetof(struct user, u_debugreg[7]))){ + addr -= offsetof(struct user, u_debugreg[0]); + addr = addr >> 2; + tmp = child->thread.arch.debugregs[addr]; + } + return put_user(tmp, (unsigned long __user *) data); +} + struct i387_fxsave_struct { unsigned short cwd; unsigned short swd; @@ -173,12 +238,12 @@ static inline unsigned long twd_fxsr_to_i387( struct i387_fxsave_struct *fxsave */ #ifdef CONFIG_MODE_TT -static inline int convert_fxsr_to_user_tt(struct _fpstate *buf, +static inline int convert_fxsr_to_user_tt(struct _fpstate __user *buf, struct pt_regs *regs) { struct i387_fxsave_struct *fxsave = SC_FXSR_ENV(PT_REGS_SC(regs)); unsigned long env[7]; - struct _fpreg *to; + struct _fpreg __user *to; struct _fpxreg *from; int i; @@ -203,7 +268,7 @@ static inline int convert_fxsr_to_user_tt(struct _fpstate *buf, } #endif -static inline int convert_fxsr_to_user(struct _fpstate *buf, +static inline int convert_fxsr_to_user(struct _fpstate __user *buf, struct pt_regs *regs) { return(CHOOSE_MODE(convert_fxsr_to_user_tt(buf, regs), 0)); @@ -211,12 +276,12 @@ static inline int convert_fxsr_to_user(struct _fpstate *buf, #ifdef CONFIG_MODE_TT static inline int convert_fxsr_from_user_tt(struct pt_regs *regs, - struct _fpstate *buf) + struct _fpstate __user *buf) { struct i387_fxsave_struct *fxsave = SC_FXSR_ENV(PT_REGS_SC(regs)); unsigned long env[7]; struct _fpxreg *to; - struct _fpreg *from; + struct _fpreg __user *from; int i; if ( __copy_from_user( env, buf, 7 * sizeof(long) ) ) @@ -242,7 +307,7 @@ static inline int convert_fxsr_from_user_tt(struct pt_regs *regs, #endif static inline int convert_fxsr_from_user(struct pt_regs *regs, - struct _fpstate *buf) + struct _fpstate __user *buf) { return(CHOOSE_MODE(convert_fxsr_from_user_tt(regs, buf), 0)); } @@ -251,7 +316,7 @@ int get_fpregs(unsigned long buf, struct task_struct *child) { int err; - err = convert_fxsr_to_user((struct _fpstate *) buf, + err = convert_fxsr_to_user((struct _fpstate __user *) buf, &child->thread.regs); if(err) return(-EFAULT); else return(0); @@ -262,7 +327,7 @@ int set_fpregs(unsigned long buf, struct task_struct *child) int err; err = convert_fxsr_from_user(&child->thread.regs, - (struct _fpstate *) buf); + (struct _fpstate __user *) buf); if(err) return(-EFAULT); else return(0); } @@ -274,7 +339,7 @@ int get_fpxregs_tt(unsigned long buf, struct task_struct *tsk) struct i387_fxsave_struct *fxsave = SC_FXSR_ENV(PT_REGS_SC(regs)); int err; - err = __copy_to_user((void *) buf, fxsave, + err = __copy_to_user((void __user *) buf, fxsave, sizeof(struct user_fxsr_struct)); if(err) return -EFAULT; else return 0; @@ -293,7 +358,7 @@ int set_fpxregs_tt(unsigned long buf, struct task_struct *tsk) struct i387_fxsave_struct *fxsave = SC_FXSR_ENV(PT_REGS_SC(regs)); int err; - err = __copy_from_user(fxsave, (void *) buf, + err = __copy_from_user(fxsave, (void __user *) buf, sizeof(struct user_fxsr_struct) ); if(err) return -EFAULT; else return 0;