Use the generic ptrace_resume code for PTRACE_SYSCALL, PTRACE_CONT, PTRACE_KILL and PTRACE_SINGLESTEP. This implies defining arch_has_single_step in <asm/ptrace.h> and implementing the user_enable_single_step and user_disable_single_step functions, which also causes the breakpoint information to be cleared on fork, which could be considered a bug fix. Also the TIF_SYSCALL_TRACE thread flag is now cleared on PTRACE_KILL which it previously wasn't which is consistent with all architectures using the modern ptrace code. Signed-off-by: Christoph Hellwig <hch@lst.de> Cc: Oleg Nesterov <oleg@redhat.com> Cc: Roland McGrath <roland@redhat.com> Cc: Yoshinori Sato <ysato@users.sourceforge.jp> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
		
			
				
	
	
		
			84 lines
		
	
	
	
		
			2.2 KiB
			
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			84 lines
		
	
	
	
		
			2.2 KiB
			
		
	
	
	
		
			C
		
	
	
	
	
	
/*
 | 
						|
 *  linux/arch/h8300/platform/h8s/ptrace_h8s.c
 | 
						|
 *    ptrace cpu depend helper functions
 | 
						|
 *
 | 
						|
 *  Yoshinori Sato <ysato@users.sourceforge.jp>
 | 
						|
 *
 | 
						|
 * This file is subject to the terms and conditions of the GNU General
 | 
						|
 * Public License.  See the file COPYING in the main directory of
 | 
						|
 * this archive for more details.
 | 
						|
 */
 | 
						|
 | 
						|
#include <linux/linkage.h>
 | 
						|
#include <linux/sched.h>
 | 
						|
#include <linux/errno.h>
 | 
						|
#include <asm/ptrace.h>
 | 
						|
 | 
						|
#define CCR_MASK  0x6f
 | 
						|
#define EXR_TRACE 0x80
 | 
						|
 | 
						|
/* Mapping from PT_xxx to the stack offset at which the register is
 | 
						|
   saved.  Notice that usp has no stack-slot and needs to be treated
 | 
						|
   specially (see get_reg/put_reg below). */
 | 
						|
static const int h8300_register_offset[] = {
 | 
						|
	PT_REG(er1), PT_REG(er2), PT_REG(er3), PT_REG(er4),
 | 
						|
	PT_REG(er5), PT_REG(er6), PT_REG(er0), PT_REG(orig_er0),
 | 
						|
	PT_REG(ccr), PT_REG(pc),  0,           PT_REG(exr)
 | 
						|
};
 | 
						|
 | 
						|
/* read register */
 | 
						|
long h8300_get_reg(struct task_struct *task, int regno)
 | 
						|
{
 | 
						|
	switch (regno) {
 | 
						|
	case PT_USP:
 | 
						|
		return task->thread.usp + sizeof(long)*2 + 2;
 | 
						|
	case PT_CCR:
 | 
						|
	case PT_EXR:
 | 
						|
	    return *(unsigned short *)(task->thread.esp0 + h8300_register_offset[regno]);
 | 
						|
	default:
 | 
						|
	    return *(unsigned long *)(task->thread.esp0 + h8300_register_offset[regno]);
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
/* write register */
 | 
						|
int h8300_put_reg(struct task_struct *task, int regno, unsigned long data)
 | 
						|
{
 | 
						|
	unsigned short oldccr;
 | 
						|
	switch (regno) {
 | 
						|
	case PT_USP:
 | 
						|
		task->thread.usp = data - sizeof(long)*2 - 2;
 | 
						|
	case PT_CCR:
 | 
						|
		oldccr = *(unsigned short *)(task->thread.esp0 + h8300_register_offset[regno]);
 | 
						|
		oldccr &= ~CCR_MASK;
 | 
						|
		data &= CCR_MASK;
 | 
						|
		data |= oldccr;
 | 
						|
		*(unsigned short *)(task->thread.esp0 + h8300_register_offset[regno]) = data;
 | 
						|
		break;
 | 
						|
	case PT_EXR:
 | 
						|
		/* exr modify not support */
 | 
						|
		return -EIO;
 | 
						|
	default:
 | 
						|
		*(unsigned long *)(task->thread.esp0 + h8300_register_offset[regno]) = data;
 | 
						|
		break;
 | 
						|
	}
 | 
						|
	return 0;
 | 
						|
}
 | 
						|
 | 
						|
/* disable singlestep */
 | 
						|
void user_disable_single_step(struct task_struct *child)
 | 
						|
{
 | 
						|
	*(unsigned short *)(child->thread.esp0 + h8300_register_offset[PT_EXR]) &= ~EXR_TRACE;
 | 
						|
}
 | 
						|
 | 
						|
/* enable singlestep */
 | 
						|
void user_enable_single_step(struct task_struct *child)
 | 
						|
{
 | 
						|
	*(unsigned short *)(child->thread.esp0 + h8300_register_offset[PT_EXR]) |= EXR_TRACE;
 | 
						|
}
 | 
						|
 | 
						|
asmlinkage void trace_trap(unsigned long bp)
 | 
						|
{
 | 
						|
	(void)bp;
 | 
						|
	force_sig(SIGTRAP,current);
 | 
						|
}
 | 
						|
 |