⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ptrace.c

📁 Linux内核源代码 为压缩文件 是<<Linux内核>>一书中的源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
/* ptrace.c: Sparc process tracing support. * * Copyright (C) 1996 David S. Miller (davem@caipfs.rutgers.edu) * * Based upon code written by Ross Biro, Linus Torvalds, Bob Manson, * and David Mosberger. * * Added Linux support -miguel (wierd, eh?, the orignal code was meant * to emulate SunOS). */#include <linux/kernel.h>#include <linux/sched.h>#include <linux/mm.h>#include <linux/errno.h>#include <linux/ptrace.h>#include <linux/user.h>#include <linux/smp.h>#include <linux/smp_lock.h>#include <asm/pgtable.h>#include <asm/system.h>#include <asm/uaccess.h>#define MAGIC_CONSTANT 0x80000000/* Returning from ptrace is a bit tricky because the syscall return * low level code assumes any value returned which is negative and * is a valid errno will mean setting the condition codes to indicate * an error return.  This doesn't work, so we have this hook. */static inline void pt_error_return(struct pt_regs *regs, unsigned long error){	regs->u_regs[UREG_I0] = error;	regs->psr |= PSR_C;	regs->pc = regs->npc;	regs->npc += 4;}static inline void pt_succ_return(struct pt_regs *regs, unsigned long value){	regs->u_regs[UREG_I0] = value;	regs->psr &= ~PSR_C;	regs->pc = regs->npc;	regs->npc += 4;}static voidpt_succ_return_linux(struct pt_regs *regs, unsigned long value, long *addr){	if(put_user(value, addr))		return pt_error_return(regs, EFAULT);	regs->u_regs[UREG_I0] = 0;	regs->psr &= ~PSR_C;	regs->pc = regs->npc;	regs->npc += 4;}static voidpt_os_succ_return (struct pt_regs *regs, unsigned long val, long *addr){	if (current->personality == PER_SUNOS)		pt_succ_return (regs, val);	else		pt_succ_return_linux (regs, val, addr);}/* Fuck me gently with a chainsaw... */static inline void read_sunos_user(struct pt_regs *regs, unsigned long offset,				   struct task_struct *tsk, long *addr){	struct pt_regs *cregs = tsk->thread.kregs;	struct thread_struct *t = &tsk->thread;	int v;		if(offset >= 1024)		offset -= 1024; /* whee... */	if(offset & ((sizeof(unsigned long) - 1))) {		pt_error_return(regs, EIO);		return;	}	if(offset >= 16 && offset < 784) {		offset -= 16; offset >>= 2;		pt_os_succ_return(regs, *(((unsigned long *)(&t->reg_window[0]))+offset), addr);		return;	}	if(offset >= 784 && offset < 832) {		offset -= 784; offset >>= 2;		pt_os_succ_return(regs, *(((unsigned long *)(&t->rwbuf_stkptrs[0]))+offset), addr);		return;	}	switch(offset) {	case 0:		v = t->ksp;		break;	case 4:		v = t->kpc;		break;	case 8:		v = t->kpsr;		break;	case 12:		v = t->uwinmask;		break;	case 832:		v = t->w_saved;		break;	case 896:		v = cregs->u_regs[UREG_I0];		break;	case 900:		v = cregs->u_regs[UREG_I1];		break;	case 904:		v = cregs->u_regs[UREG_I2];		break;	case 908:		v = cregs->u_regs[UREG_I3];		break;	case 912:		v = cregs->u_regs[UREG_I4];		break;	case 916:		v = cregs->u_regs[UREG_I5];		break;	case 920:		v = cregs->u_regs[UREG_I6];		break;	case 924:		if(tsk->thread.flags & MAGIC_CONSTANT)			v = cregs->u_regs[UREG_G1];		else			v = 0;		break;	case 940:		v = cregs->u_regs[UREG_I0];		break;	case 944:		v = cregs->u_regs[UREG_I1];		break;	case 948:		/* Isn't binary compatibility _fun_??? */		if(cregs->psr & PSR_C)			v = cregs->u_regs[UREG_I0] << 24;		else			v = 0;		break;		/* Rest of them are completely unsupported. */	default:		printk("%s [%d]: Wants to read user offset %ld\n",		       current->comm, current->pid, offset);		pt_error_return(regs, EIO);		return;	}	if (current->personality == PER_SUNOS)		pt_succ_return (regs, v);	else		pt_succ_return_linux (regs, v, addr);	return;}static inline void write_sunos_user(struct pt_regs *regs, unsigned long offset,				    struct task_struct *tsk){	struct pt_regs *cregs = tsk->thread.kregs;	struct thread_struct *t = &tsk->thread;	unsigned long value = regs->u_regs[UREG_I3];	if(offset >= 1024)		offset -= 1024; /* whee... */	if(offset & ((sizeof(unsigned long) - 1)))		goto failure;	if(offset >= 16 && offset < 784) {		offset -= 16; offset >>= 2;		*(((unsigned long *)(&t->reg_window[0]))+offset) = value;		goto success;	}	if(offset >= 784 && offset < 832) {		offset -= 784; offset >>= 2;		*(((unsigned long *)(&t->rwbuf_stkptrs[0]))+offset) = value;		goto success;	}	switch(offset) {	case 896:		cregs->u_regs[UREG_I0] = value;		break;	case 900:		cregs->u_regs[UREG_I1] = value;		break;	case 904:		cregs->u_regs[UREG_I2] = value;		break;	case 908:		cregs->u_regs[UREG_I3] = value;		break;	case 912:		cregs->u_regs[UREG_I4] = value;		break;	case 916:		cregs->u_regs[UREG_I5] = value;		break;	case 920:		cregs->u_regs[UREG_I6] = value;		break;	case 924:		cregs->u_regs[UREG_I7] = value;		break;	case 940:		cregs->u_regs[UREG_I0] = value;		break;	case 944:		cregs->u_regs[UREG_I1] = value;		break;		/* Rest of them are completely unsupported or "no-touch". */	default:		printk("%s [%d]: Wants to write user offset %ld\n",		       current->comm, current->pid, offset);		goto failure;	}success:	pt_succ_return(regs, 0);	return;failure:	pt_error_return(regs, EIO);	return;}/* #define ALLOW_INIT_TRACING *//* #define DEBUG_PTRACE */#ifdef DEBUG_PTRACEchar *pt_rq [] = {"TRACEME","PEEKTEXT","PEEKDATA","PEEKUSR","POKETEXT","POKEDATA","POKEUSR","CONT","KILL","SINGLESTEP","SUNATTACH","SUNDETACH","GETREGS","SETREGS","GETFPREGS","SETFPREGS","READDATA","WRITEDATA","READTEXT","WRITETEXT","GETFPAREGS","SETFPAREGS",""};#endifasmlinkage void do_ptrace(struct pt_regs *regs){	unsigned long request = regs->u_regs[UREG_I0];	unsigned long pid = regs->u_regs[UREG_I1];	unsigned long addr = regs->u_regs[UREG_I2];	unsigned long data = regs->u_regs[UREG_I3];	unsigned long addr2 = regs->u_regs[UREG_I4];	struct task_struct *child;	lock_kernel();#ifdef DEBUG_PTRACE	{		char *s;		if ((request > 0) && (request < 21))			s = pt_rq [request];		else			s = "unknown";		if (request == PTRACE_POKEDATA && data == 0x91d02001){			printk ("do_ptrace: breakpoint pid=%d, addr=%08lx addr2=%08lx\n",				pid, addr, addr2);		} else 			printk("do_ptrace: rq=%s(%d) pid=%d addr=%08lx data=%08lx addr2=%08lx\n",			       s, (int) request, (int) pid, addr, data, addr2);	}#endif	if(request == PTRACE_TRACEME) {		/* are we already being traced? */		if (current->ptrace & PT_PTRACED) {			pt_error_return(regs, EPERM);			goto out;		}		/* set the ptrace bit in the process flags. */		current->ptrace |= PT_PTRACED;		pt_succ_return(regs, 0);		goto out;	}#ifndef ALLOW_INIT_TRACING	if(pid == 1) {		/* Can't dork with init. */		pt_error_return(regs, EPERM);		goto out;	}#endif	if(!(child = find_task_by_pid(pid))) {		pt_error_return(regs, ESRCH);		goto out;	}	if ((current->personality == PER_SUNOS && request == PTRACE_SUNATTACH)	    || (current->personality != PER_SUNOS && request == PTRACE_ATTACH)) {		unsigned long flags;		if(child == current) {			/* Try this under SunOS/Solaris, bwa haha			 * You'll never be able to kill the process. ;-)			 */			pt_error_return(regs, EPERM);			goto out;		}		if((!child->dumpable ||		    (current->uid != child->euid) ||		    (current->uid != child->uid) ||		    (current->uid != child->suid) ||		    (current->gid != child->egid) ||		    (current->gid != child->sgid) || 

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -