#include <linux/errno.h>
#include <linux/ptrace.h>
#include <linux/user.h>
-#include <linux/config.h>
+#include <linux/signal.h>
#include <asm/uaccess.h>
#include <asm/page.h>
h8300_disable_trace(child);
}
-asmlinkage int sys_ptrace(long request, long pid, long addr, long data)
+long arch_ptrace(struct task_struct *child, long request, long addr, long data)
{
- struct task_struct *child;
int ret;
- lock_kernel();
- ret = -EPERM;
- if (request == PTRACE_TRACEME) {
- /* are we already being traced? */
- if (current->ptrace & PT_PTRACED)
- goto out;
- /* set the ptrace bit in the process flags. */
- current->ptrace |= PT_PTRACED;
- ret = 0;
- goto out;
- }
- ret = -ESRCH;
- read_lock(&tasklist_lock);
- child = find_task_by_pid(pid);
- if (child)
- get_task_struct(child);
- read_unlock(&tasklist_lock);
- if (!child)
- goto out;
- if (!vx_check(vx_task_xid(child), VX_WATCH|VX_IDENT))
- goto out_tsk;
-
- ret = -EPERM;
- if (pid == 1) /* you may not mess with init */
- goto out_tsk;
-
- if (request == PTRACE_ATTACH) {
- ret = ptrace_attach(child);
- goto out_tsk;
- }
- ret = -ESRCH;
- if (!(child->ptrace & PT_PTRACED))
- goto out_tsk;
- if (child->state != TASK_STOPPED) {
- if (request != PTRACE_KILL)
- goto out_tsk;
- }
- ret = ptrace_check_attach(child, request == PTRACE_KILL);
- if (ret < 0)
- goto out_tsk;
-
switch (request) {
case PTRACE_PEEKTEXT: /* read word at location addr. */
case PTRACE_PEEKDATA: {
/* read the word at location addr in the USER area. */
case PTRACE_PEEKUSR: {
- unsigned long tmp;
+ unsigned long tmp = 0;
- if ((addr & 3) || addr < 0 || addr >= sizeof(struct user))
+ if ((addr & 3) || addr < 0 || addr >= sizeof(struct user)) {
ret = -EIO;
+ break ;
+ }
- tmp = 0; /* Default return condition */
+ ret = 0; /* Default return condition */
addr = addr >> 2; /* temporary hack. */
+
if (addr < H8300_REGS_NO)
tmp = h8300_get_reg(child, addr);
else {
- ret = -EIO;
- break ;
+ switch(addr) {
+ case 49:
+ tmp = child->mm->start_code;
+ break ;
+ case 50:
+ tmp = child->mm->start_data;
+ break ;
+ case 51:
+ tmp = child->mm->end_code;
+ break ;
+ case 52:
+ tmp = child->mm->end_data;
+ break ;
+ default:
+ ret = -EIO;
+ }
}
- ret = put_user(tmp,(unsigned long *) data);
+ if (!ret)
+ ret = put_user(tmp,(unsigned long *) data);
break ;
}
case PTRACE_SYSCALL: /* continue and stop at next (return from) syscall */
case PTRACE_CONT: { /* restart after signal. */
ret = -EIO;
- if ((unsigned long) data >= _NSIG)
+ if (!valid_signal(data))
break ;
if (request == PTRACE_SYSCALL)
set_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
case PTRACE_KILL: {
ret = 0;
- if (child->state == TASK_ZOMBIE) /* already dead */
+ if (child->exit_state == EXIT_ZOMBIE) /* already dead */
break;
child->exit_code = SIGKILL;
h8300_disable_trace(child);
case PTRACE_SINGLESTEP: { /* set the trap flag. */
ret = -EIO;
- if ((unsigned long) data > _NSIG)
+ if (!valid_signal(data))
break;
clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
child->exit_code = data;
ret = -EIO;
break;
}
-out_tsk:
- put_task_struct(child);
-out:
- unlock_kernel();
return ret;
}
return;
if (!(current->ptrace & PT_PTRACED))
return;
- current->exit_code = SIGTRAP;
- current->state = TASK_STOPPED;
- notify_parent(current, SIGCHLD);
- schedule();
+ ptrace_notify(SIGTRAP | ((current->ptrace & PT_TRACESYSGOOD)
+ ? 0x80 : 0));
/*
* this isn't the same as continuing with a signal, but it will do
* for normal use. strace only continues with a signal if the