linux/arch/x86/um/ptrace_64.c
<<
>>
Prefs
   1/*
   2 * Copyright 2003 PathScale, Inc.
   3 * Copyright (C) 2003 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
   4 *
   5 * Licensed under the GPL
   6 */
   7
   8#include <linux/mm.h>
   9#include <linux/sched.h>
  10#include <linux/errno.h>
  11#define __FRAME_OFFSETS
  12#include <asm/ptrace.h>
  13#include <asm/uaccess.h>
  14
  15/*
  16 * determines which flags the user has access to.
  17 * 1 = access 0 = no access
  18 */
  19#define FLAG_MASK 0x44dd5UL
  20
  21static const int reg_offsets[] =
  22{
  23        [R8 >> 3] = HOST_R8,
  24        [R9 >> 3] = HOST_R9,
  25        [R10 >> 3] = HOST_R10,
  26        [R11 >> 3] = HOST_R11,
  27        [R12 >> 3] = HOST_R12,
  28        [R13 >> 3] = HOST_R13,
  29        [R14 >> 3] = HOST_R14,
  30        [R15 >> 3] = HOST_R15,
  31        [RIP >> 3] = HOST_IP,
  32        [RSP >> 3] = HOST_SP,
  33        [RAX >> 3] = HOST_AX,
  34        [RBX >> 3] = HOST_BX,
  35        [RCX >> 3] = HOST_CX,
  36        [RDX >> 3] = HOST_DX,
  37        [RSI >> 3] = HOST_SI,
  38        [RDI >> 3] = HOST_DI,
  39        [RBP >> 3] = HOST_BP,
  40        [CS >> 3] = HOST_CS,
  41        [SS >> 3] = HOST_SS,
  42        [FS_BASE >> 3] = HOST_FS_BASE,
  43        [GS_BASE >> 3] = HOST_GS_BASE,
  44        [DS >> 3] = HOST_DS,
  45        [ES >> 3] = HOST_ES,
  46        [FS >> 3] = HOST_FS,
  47        [GS >> 3] = HOST_GS,
  48        [EFLAGS >> 3] = HOST_EFLAGS,
  49        [ORIG_RAX >> 3] = HOST_ORIG_AX,
  50};
  51
  52int putreg(struct task_struct *child, int regno, unsigned long value)
  53{
  54#ifdef TIF_IA32
  55        /*
  56         * Some code in the 64bit emulation may not be 64bit clean.
  57         * Don't take any chances.
  58         */
  59        if (test_tsk_thread_flag(child, TIF_IA32))
  60                value &= 0xffffffff;
  61#endif
  62        switch (regno) {
  63        case R8:
  64        case R9:
  65        case R10:
  66        case R11:
  67        case R12:
  68        case R13:
  69        case R14:
  70        case R15:
  71        case RIP:
  72        case RSP:
  73        case RAX:
  74        case RBX:
  75        case RCX:
  76        case RDX:
  77        case RSI:
  78        case RDI:
  79        case RBP:
  80        case ORIG_RAX:
  81                break;
  82
  83        case FS:
  84        case GS:
  85        case DS:
  86        case ES:
  87        case SS:
  88        case CS:
  89                if (value && (value & 3) != 3)
  90                        return -EIO;
  91                value &= 0xffff;
  92                break;
  93
  94        case FS_BASE:
  95        case GS_BASE:
  96                if (!((value >> 48) == 0 || (value >> 48) == 0xffff))
  97                        return -EIO;
  98                break;
  99
 100        case EFLAGS:
 101                value &= FLAG_MASK;
 102                child->thread.regs.regs.gp[HOST_EFLAGS] |= value;
 103                return 0;
 104
 105        default:
 106                panic("Bad register in putreg(): %d\n", regno);
 107        }
 108
 109        child->thread.regs.regs.gp[reg_offsets[regno >> 3]] = value;
 110        return 0;
 111}
 112
 113int poke_user(struct task_struct *child, long addr, long data)
 114{
 115        if ((addr & 3) || addr < 0)
 116                return -EIO;
 117
 118        if (addr < MAX_REG_OFFSET)
 119                return putreg(child, addr, data);
 120        else if ((addr >= offsetof(struct user, u_debugreg[0])) &&
 121                (addr <= offsetof(struct user, u_debugreg[7]))) {
 122                addr -= offsetof(struct user, u_debugreg[0]);
 123                addr = addr >> 2;
 124                if ((addr == 4) || (addr == 5))
 125                        return -EIO;
 126                child->thread.arch.debugregs[addr] = data;
 127                return 0;
 128        }
 129        return -EIO;
 130}
 131
 132unsigned long getreg(struct task_struct *child, int regno)
 133{
 134        unsigned long mask = ~0UL;
 135#ifdef TIF_IA32
 136        if (test_tsk_thread_flag(child, TIF_IA32))
 137                mask = 0xffffffff;
 138#endif
 139        switch (regno) {
 140        case R8:
 141        case R9:
 142        case R10:
 143        case R11:
 144        case R12:
 145        case R13:
 146        case R14:
 147        case R15:
 148        case RIP:
 149        case RSP:
 150        case RAX:
 151        case RBX:
 152        case RCX:
 153        case RDX:
 154        case RSI:
 155        case RDI:
 156        case RBP:
 157        case ORIG_RAX:
 158        case EFLAGS:
 159        case FS_BASE:
 160        case GS_BASE:
 161                break;
 162        case FS:
 163        case GS:
 164        case DS:
 165        case ES:
 166        case SS:
 167        case CS:
 168                mask = 0xffff;
 169                break;
 170        default:
 171                panic("Bad register in getreg: %d\n", regno);
 172        }
 173        return mask & child->thread.regs.regs.gp[reg_offsets[regno >> 3]];
 174}
 175
 176int peek_user(struct task_struct *child, long addr, long data)
 177{
 178        /* read the word at location addr in the USER area. */
 179        unsigned long tmp;
 180
 181        if ((addr & 3) || addr < 0)
 182                return -EIO;
 183
 184        tmp = 0;  /* Default return condition */
 185        if (addr < MAX_REG_OFFSET)
 186                tmp = getreg(child, addr);
 187        else if ((addr >= offsetof(struct user, u_debugreg[0])) &&
 188                (addr <= offsetof(struct user, u_debugreg[7]))) {
 189                addr -= offsetof(struct user, u_debugreg[0]);
 190                addr = addr >> 2;
 191                tmp = child->thread.arch.debugregs[addr];
 192        }
 193        return put_user(tmp, (unsigned long *) data);
 194}
 195
 196/* XXX Mostly copied from sys-i386 */
 197int is_syscall(unsigned long addr)
 198{
 199        unsigned short instr;
 200        int n;
 201
 202        n = copy_from_user(&instr, (void __user *) addr, sizeof(instr));
 203        if (n) {
 204                /*
 205                 * access_process_vm() grants access to vsyscall and stub,
 206                 * while copy_from_user doesn't. Maybe access_process_vm is
 207                 * slow, but that doesn't matter, since it will be called only
 208                 * in case of singlestepping, if copy_from_user failed.
 209                 */
 210                n = access_process_vm(current, addr, &instr, sizeof(instr), 0);
 211                if (n != sizeof(instr)) {
 212                        printk("is_syscall : failed to read instruction from "
 213                               "0x%lx\n", addr);
 214                        return 1;
 215                }
 216        }
 217        /* sysenter */
 218        return instr == 0x050f;
 219}
 220
 221static int get_fpregs(struct user_i387_struct __user *buf, struct task_struct *child)
 222{
 223        int err, n, cpu = ((struct thread_info *) child->stack)->cpu;
 224        long fpregs[HOST_FP_SIZE];
 225
 226        BUG_ON(sizeof(*buf) != sizeof(fpregs));
 227        err = save_fp_registers(userspace_pid[cpu], fpregs);
 228        if (err)
 229                return err;
 230
 231        n = copy_to_user(buf, fpregs, sizeof(fpregs));
 232        if (n > 0)
 233                return -EFAULT;
 234
 235        return n;
 236}
 237
 238static int set_fpregs(struct user_i387_struct __user *buf, struct task_struct *child)
 239{
 240        int n, cpu = ((struct thread_info *) child->stack)->cpu;
 241        long fpregs[HOST_FP_SIZE];
 242
 243        BUG_ON(sizeof(*buf) != sizeof(fpregs));
 244        n = copy_from_user(fpregs, buf, sizeof(fpregs));
 245        if (n > 0)
 246                return -EFAULT;
 247
 248        return restore_fp_registers(userspace_pid[cpu], fpregs);
 249}
 250
 251long subarch_ptrace(struct task_struct *child, long request,
 252                    unsigned long addr, unsigned long data)
 253{
 254        int ret = -EIO;
 255        void __user *datap = (void __user *) data;
 256
 257        switch (request) {
 258        case PTRACE_GETFPREGS: /* Get the child FPU state. */
 259                ret = get_fpregs(datap, child);
 260                break;
 261        case PTRACE_SETFPREGS: /* Set the child FPU state. */
 262                ret = set_fpregs(datap, child);
 263                break;
 264        case PTRACE_ARCH_PRCTL:
 265                /* XXX Calls ptrace on the host - needs some SMP thinking */
 266                ret = arch_prctl(child, data, (void __user *) addr);
 267                break;
 268        }
 269
 270        return ret;
 271}
 272