support ptrace(PTRACE_PEEKUSER, ...)

This commit is contained in:
Tomoki Shirasawa
2014-10-08 14:56:28 +09:00
parent a101aa0534
commit 4b46330624
3 changed files with 144 additions and 4 deletions

View File

@@ -195,6 +195,52 @@ do_setpgid(int pid, int pgid)
}
}
void
peekuser(struct process *proc, void *regs0)
{
struct x86_regs *regs = regs0;
if(regs == NULL){
asm("movq %%gs:132, %0" : "=r" (regs));
--regs;
}
if(proc->userp == NULL){
proc->userp = kmalloc(sizeof(struct user), IHK_MC_AP_NOWAIT);
memset(proc->userp, '\0', sizeof(struct user));
}
asm("mov %%db0, %0" :"=r" (proc->userp->u_debugreg[0]));
asm("mov %%db1, %0" :"=r" (proc->userp->u_debugreg[1]));
asm("mov %%db2, %0" :"=r" (proc->userp->u_debugreg[2]));
asm("mov %%db3, %0" :"=r" (proc->userp->u_debugreg[3]));
// asm("mov %%db4, %0" :"=r" (proc->userp->u_debugreg[4]));
// asm("mov %%db5, %0" :"=r" (proc->userp->u_debugreg[5]));
asm("mov %%db6, %0" :"=r" (proc->userp->u_debugreg[6]));
asm("mov %%db7, %0" :"=r" (proc->userp->u_debugreg[7]));
proc->userp->regs.r15 = regs->r15;
proc->userp->regs.r14 = regs->r14;
proc->userp->regs.r13 = regs->r13;
proc->userp->regs.r12 = regs->r12;
proc->userp->regs.rbp = regs->rbp;
proc->userp->regs.rbx = regs->rbx;
proc->userp->regs.r11 = regs->r11;
proc->userp->regs.r10 = regs->r10;
proc->userp->regs.r9 = regs->r9;
proc->userp->regs.r8 = regs->r8;
proc->userp->regs.rax = regs->rax;
proc->userp->regs.rcx = regs->rcx;
proc->userp->regs.rdx = regs->rdx;
proc->userp->regs.rsi = regs->rsi;
proc->userp->regs.rdi = regs->rdi;
proc->userp->regs.rip = regs->rip;
proc->userp->regs.cs = regs->cs;
proc->userp->regs.eflags = regs->rflags;
proc->userp->regs.rsp = regs->rsp;
proc->userp->regs.ss = regs->ss;
asm("mov %%es, %0" :"=r" (proc->userp->regs.es));
asm("mov %%fs, %0" :"=r" (proc->userp->regs.fs));
asm("mov %%gs, %0" :"=r" (proc->userp->regs.gs));
}
extern void coredump(struct process *proc, void *regs);
void
@@ -358,7 +404,7 @@ do_signal(unsigned long rc, void *regs0, struct process *proc, struct sig_pendin
}
}
static int ptrace_report_signal(struct process *proc, struct sig_pending *pending)
static int ptrace_report_signal(struct process *proc, struct x86_regs *regs, struct sig_pending *pending)
{
int sig;
__sigset_t w;
@@ -395,6 +441,7 @@ static int ptrace_report_signal(struct process *proc, struct sig_pending *pendin
waitq_wakeup(&proc->ftn->parent->waitpid_q);
}
peekuser(proc, regs);
dkprintf("ptrace_report_signal,sleeping\n");
/* Sleep */
proc->status = PS_TRACED;
@@ -464,7 +511,7 @@ check_signal(unsigned long rc, void *regs0)
for(sig_bv = pending->sigmask.__val[0], sig = 0; sig_bv; sig++, sig_bv >>= 1);
if((proc->ftn->ptrace & PT_TRACED) && sig != SIGKILL) {
sig = ptrace_report_signal(proc, pending);
sig = ptrace_report_signal(proc, regs, pending);
/* TODO: Tracing process could overwrite signal, so handle the case here. */
}

View File

@@ -143,6 +143,71 @@
#include <futex.h>
#include <rlimit.h>
struct user_fpregs_struct
{
unsigned short cwd;
unsigned short swd;
unsigned short ftw;
unsigned short fop;
unsigned long rip;
unsigned long rdp;
unsigned int mxcsr;
unsigned int mxcr_mask;
unsigned int st_space[32];
unsigned int xmm_space[64];
unsigned int padding[24];
};
struct user_regs_struct
{
unsigned long r15;
unsigned long r14;
unsigned long r13;
unsigned long r12;
unsigned long rbp;
unsigned long rbx;
unsigned long r11;
unsigned long r10;
unsigned long r9;
unsigned long r8;
unsigned long rax;
unsigned long rcx;
unsigned long rdx;
unsigned long rsi;
unsigned long rdi;
unsigned long orig_rax;
unsigned long rip;
unsigned long cs;
unsigned long eflags;
unsigned long rsp;
unsigned long ss;
unsigned long fs_base;
unsigned long gs_base;
unsigned long ds;
unsigned long es;
unsigned long fs;
unsigned long gs;
};
struct user
{
struct user_regs_struct regs;
int u_fpvalid;
struct user_fpregs_struct i387;
unsigned long int u_tsize;
unsigned long int u_dsize;
unsigned long int u_ssize;
unsigned long start_code;
unsigned long start_stack;
long int signal;
int reserved;
struct user_regs_struct* u_ar0;
struct user_fpregs_struct* u_fpstate;
unsigned long int magic;
char u_comm [32];
unsigned long int u_debugreg [8];
};
#define AUXV_LEN 14
struct vm_range {
@@ -273,6 +338,8 @@ struct process {
cpu_set_t cpu_set;
unsigned long saved_auxv[AUXV_LEN];
int pgid; /* process group id */
struct user *userp;
};
struct process_vm {

View File

@@ -1379,6 +1379,8 @@ SYSCALL_DECLARE(arch_prctl)
ihk_mc_syscall_arg1(ctx));
}
extern void peekuser(struct process *proc, void *regs);
static int ptrace_report_exec(struct process *proc)
{
dkprintf("ptrace_report_exec,enter\n");
@@ -1429,7 +1431,8 @@ static int ptrace_report_exec(struct process *proc)
/* Wake parent (if sleeping in wait4()) */
waitq_wakeup(&proc->ftn->parent->waitpid_q);
}
peekuser(proc, NULL);
/* Sleep */
dkprintf("ptrace_report_exec,sleeping\n");
proc->status = PS_TRACED;
@@ -2375,13 +2378,32 @@ out:
return error;
}
static long ptrace_peekuser(int pid, long addr)
{
long rc = -EIO;
struct process *child;
ihk_spinlock_t *savelock;
unsigned long irqstate;
if(addr > sizeof(struct user) || addr < 0)
return -EFAULT;
child = findthread_and_lock(pid, -1, &savelock, &irqstate);
if (!child)
return -ESRCH;
if(child->status == PS_TRACED)
memcpy(&rc, (char *)child->userp + addr, 8);
ihk_mc_spinlock_unlock(savelock, irqstate);
return rc;
}
SYSCALL_DECLARE(ptrace)
{
const long request = (long)ihk_mc_syscall_arg0(ctx);
const int pid = (int)ihk_mc_syscall_arg1(ctx);
const long addr = (long)ihk_mc_syscall_arg2(ctx);
const long data = (long)ihk_mc_syscall_arg3(ctx);
int error;
long error = -EOPNOTSUPP;
switch(request) {
case PTRACE_TRACEME:
@@ -2393,6 +2415,10 @@ SYSCALL_DECLARE(ptrace)
dkprintf("ptrace: PTRACE_KILL/CONT\n");
error = ptrace_wakeup_sig(pid, request, data);
break;
case PTRACE_PEEKUSER:
error = ptrace_peekuser(pid, addr);
dkprintf("PTRACE_PEEKUSER: addr=%p return=%p\n", addr, error);
break;
default:
dkprintf("ptrace: unimplemented ptrace called.\n");
break;