Back to home page

OSCL-LXR

 
 

    


0001 /*
0002  * Copyright 2003 PathScale, Inc.
0003  * Copyright (C) 2003 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
0004  *
0005  * Licensed under the GPL
0006  */
0007 
0008 #include <linux/mm.h>
0009 #include <linux/sched.h>
0010 #include <linux/errno.h>
0011 #define __FRAME_OFFSETS
0012 #include <asm/ptrace.h>
0013 #include <linux/uaccess.h>
0014 #include <registers.h>
0015 #include <asm/ptrace-abi.h>
0016 
0017 /*
0018  * determines which flags the user has access to.
0019  * 1 = access 0 = no access
0020  */
0021 #define FLAG_MASK 0x44dd5UL
0022 
0023 static const int reg_offsets[] =
0024 {
0025     [R8 >> 3] = HOST_R8,
0026     [R9 >> 3] = HOST_R9,
0027     [R10 >> 3] = HOST_R10,
0028     [R11 >> 3] = HOST_R11,
0029     [R12 >> 3] = HOST_R12,
0030     [R13 >> 3] = HOST_R13,
0031     [R14 >> 3] = HOST_R14,
0032     [R15 >> 3] = HOST_R15,
0033     [RIP >> 3] = HOST_IP,
0034     [RSP >> 3] = HOST_SP,
0035     [RAX >> 3] = HOST_AX,
0036     [RBX >> 3] = HOST_BX,
0037     [RCX >> 3] = HOST_CX,
0038     [RDX >> 3] = HOST_DX,
0039     [RSI >> 3] = HOST_SI,
0040     [RDI >> 3] = HOST_DI,
0041     [RBP >> 3] = HOST_BP,
0042     [CS >> 3] = HOST_CS,
0043     [SS >> 3] = HOST_SS,
0044     [FS_BASE >> 3] = HOST_FS_BASE,
0045     [GS_BASE >> 3] = HOST_GS_BASE,
0046     [DS >> 3] = HOST_DS,
0047     [ES >> 3] = HOST_ES,
0048     [FS >> 3] = HOST_FS,
0049     [GS >> 3] = HOST_GS,
0050     [EFLAGS >> 3] = HOST_EFLAGS,
0051     [ORIG_RAX >> 3] = HOST_ORIG_AX,
0052 };
0053 
0054 int putreg(struct task_struct *child, int regno, unsigned long value)
0055 {
0056     switch (regno) {
0057     case R8:
0058     case R9:
0059     case R10:
0060     case R11:
0061     case R12:
0062     case R13:
0063     case R14:
0064     case R15:
0065     case RIP:
0066     case RSP:
0067     case RAX:
0068     case RBX:
0069     case RCX:
0070     case RDX:
0071     case RSI:
0072     case RDI:
0073     case RBP:
0074         break;
0075 
0076     case ORIG_RAX:
0077         /* Update the syscall number. */
0078         UPT_SYSCALL_NR(&child->thread.regs.regs) = value;
0079         break;
0080 
0081     case FS:
0082     case GS:
0083     case DS:
0084     case ES:
0085     case SS:
0086     case CS:
0087         if (value && (value & 3) != 3)
0088             return -EIO;
0089         value &= 0xffff;
0090         break;
0091 
0092     case FS_BASE:
0093     case GS_BASE:
0094         if (!((value >> 48) == 0 || (value >> 48) == 0xffff))
0095             return -EIO;
0096         break;
0097 
0098     case EFLAGS:
0099         value &= FLAG_MASK;
0100         child->thread.regs.regs.gp[HOST_EFLAGS] |= value;
0101         return 0;
0102 
0103     default:
0104         panic("Bad register in putreg(): %d\n", regno);
0105     }
0106 
0107     child->thread.regs.regs.gp[reg_offsets[regno >> 3]] = value;
0108     return 0;
0109 }
0110 
0111 int poke_user(struct task_struct *child, long addr, long data)
0112 {
0113     if ((addr & 3) || addr < 0)
0114         return -EIO;
0115 
0116     if (addr < MAX_REG_OFFSET)
0117         return putreg(child, addr, data);
0118     else if ((addr >= offsetof(struct user, u_debugreg[0])) &&
0119         (addr <= offsetof(struct user, u_debugreg[7]))) {
0120         addr -= offsetof(struct user, u_debugreg[0]);
0121         addr = addr >> 3;
0122         if ((addr == 4) || (addr == 5))
0123             return -EIO;
0124         child->thread.arch.debugregs[addr] = data;
0125         return 0;
0126     }
0127     return -EIO;
0128 }
0129 
0130 unsigned long getreg(struct task_struct *child, int regno)
0131 {
0132     unsigned long mask = ~0UL;
0133 
0134     switch (regno) {
0135     case R8:
0136     case R9:
0137     case R10:
0138     case R11:
0139     case R12:
0140     case R13:
0141     case R14:
0142     case R15:
0143     case RIP:
0144     case RSP:
0145     case RAX:
0146     case RBX:
0147     case RCX:
0148     case RDX:
0149     case RSI:
0150     case RDI:
0151     case RBP:
0152     case ORIG_RAX:
0153     case EFLAGS:
0154     case FS_BASE:
0155     case GS_BASE:
0156         break;
0157     case FS:
0158     case GS:
0159     case DS:
0160     case ES:
0161     case SS:
0162     case CS:
0163         mask = 0xffff;
0164         break;
0165     default:
0166         panic("Bad register in getreg: %d\n", regno);
0167     }
0168     return mask & child->thread.regs.regs.gp[reg_offsets[regno >> 3]];
0169 }
0170 
0171 int peek_user(struct task_struct *child, long addr, long data)
0172 {
0173     /* read the word at location addr in the USER area. */
0174     unsigned long tmp;
0175 
0176     if ((addr & 3) || addr < 0)
0177         return -EIO;
0178 
0179     tmp = 0;  /* Default return condition */
0180     if (addr < MAX_REG_OFFSET)
0181         tmp = getreg(child, addr);
0182     else if ((addr >= offsetof(struct user, u_debugreg[0])) &&
0183         (addr <= offsetof(struct user, u_debugreg[7]))) {
0184         addr -= offsetof(struct user, u_debugreg[0]);
0185         addr = addr >> 2;
0186         tmp = child->thread.arch.debugregs[addr];
0187     }
0188     return put_user(tmp, (unsigned long *) data);
0189 }
0190 
0191 /* XXX Mostly copied from sys-i386 */
0192 int is_syscall(unsigned long addr)
0193 {
0194     unsigned short instr;
0195     int n;
0196 
0197     n = copy_from_user(&instr, (void __user *) addr, sizeof(instr));
0198     if (n) {
0199         /*
0200          * access_process_vm() grants access to vsyscall and stub,
0201          * while copy_from_user doesn't. Maybe access_process_vm is
0202          * slow, but that doesn't matter, since it will be called only
0203          * in case of singlestepping, if copy_from_user failed.
0204          */
0205         n = access_process_vm(current, addr, &instr, sizeof(instr),
0206                 FOLL_FORCE);
0207         if (n != sizeof(instr)) {
0208             printk("is_syscall : failed to read instruction from "
0209                    "0x%lx\n", addr);
0210             return 1;
0211         }
0212     }
0213     /* sysenter */
0214     return instr == 0x050f;
0215 }
0216 
0217 static int get_fpregs(struct user_i387_struct __user *buf, struct task_struct *child)
0218 {
0219     int err, n, cpu = ((struct thread_info *) child->stack)->cpu;
0220     struct user_i387_struct fpregs;
0221 
0222     err = save_i387_registers(userspace_pid[cpu],
0223                   (unsigned long *) &fpregs);
0224     if (err)
0225         return err;
0226 
0227     n = copy_to_user(buf, &fpregs, sizeof(fpregs));
0228     if (n > 0)
0229         return -EFAULT;
0230 
0231     return n;
0232 }
0233 
0234 static int set_fpregs(struct user_i387_struct __user *buf, struct task_struct *child)
0235 {
0236     int n, cpu = ((struct thread_info *) child->stack)->cpu;
0237     struct user_i387_struct fpregs;
0238 
0239     n = copy_from_user(&fpregs, buf, sizeof(fpregs));
0240     if (n > 0)
0241         return -EFAULT;
0242 
0243     return restore_i387_registers(userspace_pid[cpu],
0244                       (unsigned long *) &fpregs);
0245 }
0246 
0247 long subarch_ptrace(struct task_struct *child, long request,
0248             unsigned long addr, unsigned long data)
0249 {
0250     int ret = -EIO;
0251     void __user *datap = (void __user *) data;
0252 
0253     switch (request) {
0254     case PTRACE_GETFPREGS: /* Get the child FPU state. */
0255         ret = get_fpregs(datap, child);
0256         break;
0257     case PTRACE_SETFPREGS: /* Set the child FPU state. */
0258         ret = set_fpregs(datap, child);
0259         break;
0260     case PTRACE_ARCH_PRCTL:
0261         /* XXX Calls ptrace on the host - needs some SMP thinking */
0262         ret = arch_prctl(child, data, (void __user *) addr);
0263         break;
0264     }
0265 
0266     return ret;
0267 }