diff options
author | Al Viro <viro@ftp.linux.org.uk> | 2011-08-18 20:03:19 +0100 |
---|---|---|
committer | Richard Weinberger <richard@nod.at> | 2011-11-02 14:14:51 +0100 |
commit | 6582b7f7743da6ce3e3714e9e8b18e0e073d4acd (patch) | |
tree | 649346d2333865ccd4bb4d560ceb50c39139c5c2 /arch/um/sys-i386/ptrace.c | |
parent | 858ba94499b4f48e9eb0be7cf0092f1ea9460fef (diff) |
um: merge arch/um/sys-{i386,x86_64}
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Signed-off-by: Richard Weinberger <richard@nod.at>
Diffstat (limited to 'arch/um/sys-i386/ptrace.c')
-rw-r--r-- | arch/um/sys-i386/ptrace.c | 273 |
1 files changed, 0 insertions, 273 deletions
diff --git a/arch/um/sys-i386/ptrace.c b/arch/um/sys-i386/ptrace.c deleted file mode 100644 index a174fde2531..00000000000 --- a/arch/um/sys-i386/ptrace.c +++ /dev/null @@ -1,273 +0,0 @@ -/* - * Copyright (C) 2000 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) - * Licensed under the GPL - */ - -#include "linux/mm.h" -#include "linux/sched.h" -#include "asm/uaccess.h" -#include "skas.h" - -extern int arch_switch_tls(struct task_struct *to); - -void arch_switch_to(struct task_struct *to) -{ - int err = arch_switch_tls(to); - if (!err) - return; - - if (err != -EINVAL) - printk(KERN_WARNING "arch_switch_tls failed, errno %d, " - "not EINVAL\n", -err); - else - printk(KERN_WARNING "arch_switch_tls failed, errno = EINVAL\n"); -} - -int is_syscall(unsigned long addr) -{ - unsigned short instr; - int n; - - n = copy_from_user(&instr, (void __user *) addr, sizeof(instr)); - if (n) { - /* 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(KERN_ERR "is_syscall : failed to read " - "instruction from 0x%lx\n", addr); - return 1; - } - } - /* int 0x80 or sysenter */ - return (instr == 0x80cd) || (instr == 0x340f); -} - -/* determines which flags the user has access to. */ -/* 1 = access 0 = no access */ -#define FLAG_MASK 0x00044dd5 - -static const int reg_offsets[] = { - [EBX] = HOST_EBX, - [ECX] = HOST_ECX, - [EDX] = HOST_EDX, - [ESI] = HOST_ESI, - [EDI] = HOST_EDI, - [EBP] = HOST_EBP, - [EAX] = HOST_EAX, - [DS] = HOST_DS, - [ES] = HOST_ES, - [FS] = HOST_FS, - [GS] = HOST_GS, - [EIP] = HOST_IP, - [CS] = HOST_CS, - [EFL] = HOST_EFLAGS, - [UESP] = HOST_SP, - [SS] = HOST_SS, -}; - -int putreg(struct task_struct *child, int regno, unsigned long value) -{ - regno >>= 2; - switch (regno) { - case EBX: - case ECX: - case EDX: - case ESI: - case EDI: - case EBP: - case EAX: - case EIP: - case UESP: - break; - case FS: - if (value && (value & 3) != 3) - return -EIO; - break; - case GS: - if (value && (value & 3) != 3) - return -EIO; - break; - case DS: - case ES: - if (value && (value & 3) != 3) - return -EIO; - value &= 0xffff; - break; - case SS: - case CS: - if ((value & 3) != 3) - return -EIO; - value &= 0xffff; - break; - case EFL: - value &= FLAG_MASK; - child->thread.regs.regs.gp[HOST_EFLAGS] |= value; - return 0; - case ORIG_EAX: - child->thread.regs.regs.syscall = value; - return 0; - default : - panic("Bad register in putreg() : %d\n", regno); - } - child->thread.regs.regs.gp[reg_offsets[regno]] = 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 mask = ~0UL; - - regno >>= 2; - switch (regno) { - case ORIG_EAX: - return child->thread.regs.regs.syscall; - case FS: - case GS: - case DS: - case ES: - case SS: - case CS: - mask = 0xffff; - break; - case EIP: - case UESP: - case EAX: - case EBX: - case ECX: - case EDX: - case ESI: - case EDI: - case EBP: - case EFL: - break; - default: - panic("Bad register in getreg() : %d\n", regno); - } - return mask & child->thread.regs.regs.gp[reg_offsets[regno]]; -} - -/* read the word at location addr in the USER area. */ -int peek_user(struct task_struct *child, long addr, long data) -{ - 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); -} - -static int get_fpregs(struct user_i387_struct __user *buf, struct task_struct *child) -{ - int err, n, cpu = ((struct thread_info *) child->stack)->cpu; - struct user_i387_struct fpregs; - - err = save_fp_registers(userspace_pid[cpu], (unsigned long *) &fpregs); - if (err) - return err; - - n = copy_to_user(buf, &fpregs, sizeof(fpregs)); - if(n > 0) - return -EFAULT; - - return n; -} - -static int set_fpregs(struct user_i387_struct __user *buf, struct task_struct *child) -{ - int n, cpu = ((struct thread_info *) child->stack)->cpu; - struct user_i387_struct fpregs; - - n = copy_from_user(&fpregs, buf, sizeof(fpregs)); - if (n > 0) - return -EFAULT; - - return restore_fp_registers(userspace_pid[cpu], - (unsigned long *) &fpregs); -} - -static int get_fpxregs(struct user_fxsr_struct __user *buf, struct task_struct *child) -{ - int err, n, cpu = ((struct thread_info *) child->stack)->cpu; - struct user_fxsr_struct fpregs; - - err = save_fpx_registers(userspace_pid[cpu], (unsigned long *) &fpregs); - if (err) - return err; - - n = copy_to_user(buf, &fpregs, sizeof(fpregs)); - if(n > 0) - return -EFAULT; - - return n; -} - -static int set_fpxregs(struct user_fxsr_struct __user *buf, struct task_struct *child) -{ - int n, cpu = ((struct thread_info *) child->stack)->cpu; - struct user_fxsr_struct fpregs; - - n = copy_from_user(&fpregs, buf, sizeof(fpregs)); - if (n > 0) - return -EFAULT; - - return restore_fpx_registers(userspace_pid[cpu], - (unsigned long *) &fpregs); -} - -long subarch_ptrace(struct task_struct *child, long request, - unsigned long addr, unsigned long data) -{ - int ret = -EIO; - void __user *datap = (void __user *) data; - switch (request) { - case PTRACE_GETFPREGS: /* Get the child FPU state. */ - ret = get_fpregs(datap, child); - break; - case PTRACE_SETFPREGS: /* Set the child FPU state. */ - ret = set_fpregs(datap, child); - break; - case PTRACE_GETFPXREGS: /* Get the child FPU state. */ - ret = get_fpxregs(datap, child); - break; - case PTRACE_SETFPXREGS: /* Set the child FPU state. */ - ret = set_fpxregs(datap, child); - break; - default: - ret = -EIO; - } - return ret; -} |