diff --git a/arch/x86/kernel/syscall.c b/arch/x86/kernel/syscall.c index 6afde263..03b8e301 100644 --- a/arch/x86/kernel/syscall.c +++ b/arch/x86/kernel/syscall.c @@ -195,6 +195,45 @@ do_setpgid(int pid, int pgid) } } +void +pokeuser(struct process *proc, void *regs0) +{ + struct x86_regs *regs = regs0; + + if(regs == NULL){ + asm("movq %%gs:132, %0" : "=r" (regs)); + --regs; + } + asm("mov %0, %%db0" ::"r" (proc->userp->u_debugreg[0])); + asm("mov %0, %%db1" ::"r" (proc->userp->u_debugreg[1])); + asm("mov %0, %%db2" ::"r" (proc->userp->u_debugreg[2])); + asm("mov %0, %%db3" ::"r" (proc->userp->u_debugreg[3])); +// asm("mov %0, %%db4" ::"r" (proc->userp->u_debugreg[4])); +// asm("mov %0, %%db5" ::"r" (proc->userp->u_debugreg[5])); + asm("mov %0, %%db6" ::"r" (proc->userp->u_debugreg[6])); + asm("mov %0, %%db7" ::"r" (proc->userp->u_debugreg[7])); + regs->r15 = proc->userp->regs.r15; + regs->r14 = proc->userp->regs.r14; + regs->r13 = proc->userp->regs.r13; + regs->r12 = proc->userp->regs.r12; + regs->rbp = proc->userp->regs.rbp; + regs->rbx = proc->userp->regs.rbx; + regs->r11 = proc->userp->regs.r11; + regs->r10 = proc->userp->regs.r10; + regs->r9 = proc->userp->regs.r9; + regs->r8 = proc->userp->regs.r8; + regs->rax = proc->userp->regs.rax; + regs->rcx = proc->userp->regs.rcx; + regs->rdx = proc->userp->regs.rdx; + regs->rsi = proc->userp->regs.rsi; + regs->rdi = proc->userp->regs.rdi; + regs->rip = proc->userp->regs.rip; + regs->cs = proc->userp->regs.cs; + regs->rflags = proc->userp->regs.eflags; + regs->rsp = proc->userp->regs.rsp; + regs->ss = proc->userp->regs.ss; +} + void peekuser(struct process *proc, void *regs0) { diff --git a/kernel/syscall.c b/kernel/syscall.c index d7ad798f..e0070d32 100644 --- a/kernel/syscall.c +++ b/kernel/syscall.c @@ -2378,6 +2378,27 @@ out: return error; } +static long ptrace_pokeuser(int pid, long addr, long data) +{ + long rc = -EIO; + struct process *child; + ihk_spinlock_t *savelock; + unsigned long irqstate; + + if(addr > sizeof(struct user) - 8 || addr < 0) + return -EFAULT; + child = findthread_and_lock(pid, -1, &savelock, &irqstate); + if (!child) + return -ESRCH; + if(child->status == PS_TRACED){ + memcpy((char *)child->userp + addr, &data, 8); + rc = 0; + } + ihk_mc_spinlock_unlock(savelock, irqstate); + + return rc; +} + static long ptrace_peekuser(int pid, long addr) { long rc = -EIO; @@ -2385,7 +2406,7 @@ static long ptrace_peekuser(int pid, long addr) ihk_spinlock_t *savelock; unsigned long irqstate; - if(addr > sizeof(struct user) || addr < 0) + if(addr > sizeof(struct user) - 8|| addr < 0) return -EFAULT; child = findthread_and_lock(pid, -1, &savelock, &irqstate); if (!child) @@ -2397,6 +2418,28 @@ static long ptrace_peekuser(int pid, long addr) return rc; } +static long ptrace_getregs(int pid, long data) +{ + struct user_regs_struct *regs = (struct user_regs_struct *)data; + long rc = -EIO; + struct process *child; + ihk_spinlock_t *savelock; + unsigned long irqstate; + + child = findthread_and_lock(pid, -1, &savelock, &irqstate); + if (!child) + return -ESRCH; + if(child->status == PS_TRACED){ + if(copy_to_user(child, regs, child->userp, sizeof(struct user_regs_struct))) + rc = -EFAULT; + else + rc = 0; + } + ihk_mc_spinlock_unlock(savelock, irqstate); + + return rc; +} + SYSCALL_DECLARE(ptrace) { const long request = (long)ihk_mc_syscall_arg0(ctx); @@ -2415,10 +2458,18 @@ SYSCALL_DECLARE(ptrace) dkprintf("ptrace: PTRACE_KILL/CONT\n"); error = ptrace_wakeup_sig(pid, request, data); break; + case PTRACE_GETREGS: + error = ptrace_getregs(pid, data); + dkprintf("PTRACE_GETREGS: data=%p return=%p\n", data, error); + break; case PTRACE_PEEKUSER: error = ptrace_peekuser(pid, addr); dkprintf("PTRACE_PEEKUSER: addr=%p return=%p\n", addr, error); break; + case PTRACE_POKEUSER: + error = ptrace_pokeuser(pid, addr, data); + dkprintf("PTRACE_POKEUSER: addr=%p data=%p return=%p\n", addr, data, error); + break; default: dkprintf("ptrace: unimplemented ptrace called.\n"); break;