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

📄 proxy.c

📁 linux-2.6.15.6
💻 C
字号:
/**********************************************************************proxy.cCopyright (C) 1999 Lars Brinkhoff.  See the file COPYING for licensingterms and conditions.Jeff Dike (jdike@karaya.com) : Modified for integration into uml**********************************************************************//* XXX This file shouldn't refer to CONFIG_* */#include <errno.h>#include <stdio.h>#include <stdlib.h>#include <unistd.h>#include <signal.h>#include <string.h>#include <termios.h>#include <sys/wait.h>#include <sys/types.h>#include <sys/ioctl.h>#include <asm/unistd.h>#include "ptrace_user.h"#include "ptproxy.h"#include "sysdep.h"#include "wait.h"#include "user_util.h"#include "user.h"#include "os.h"#include "tempfile.h"static int debugger_wait(debugger_state *debugger, int *status, int options,			 int (*syscall)(debugger_state *debugger, pid_t child),			 int (*normal_return)(debugger_state *debugger, 					      pid_t unused),			 int (*wait_return)(debugger_state *debugger, 					    pid_t unused)){	if(debugger->real_wait){		debugger->handle_trace = normal_return;		syscall_continue(debugger->pid);		debugger->real_wait = 0;		return(1);	}	debugger->wait_status_ptr = status;	debugger->wait_options = options;	if((debugger->debugee != NULL) && debugger->debugee->event){		syscall_continue(debugger->pid);		wait_for_stop(debugger->pid, SIGTRAP, PTRACE_SYSCALL,			      NULL);		(*wait_return)(debugger, -1);		return(0);	}	else if(debugger->wait_options & WNOHANG){		syscall_cancel(debugger->pid, 0);		debugger->handle_trace = syscall;		return(0);	}	else {		syscall_pause(debugger->pid);		debugger->handle_trace = wait_return;		debugger->waiting = 1;	}	return(1);}/* * Handle debugger trap, i.e. syscall. */int debugger_syscall(debugger_state *debugger, pid_t child){	long arg1, arg2, arg3, arg4, arg5, result;	int syscall, ret = 0;	syscall = get_syscall(debugger->pid, &arg1, &arg2, &arg3, &arg4, 			      &arg5);	switch(syscall){	case __NR_execve:		/* execve never returns */		debugger->handle_trace = debugger_syscall; 		break;	case __NR_ptrace:		if(debugger->debugee->pid != 0) arg2 = debugger->debugee->pid;		if(!debugger->debugee->in_context) 			child = debugger->debugee->pid;		result = proxy_ptrace(debugger, arg1, arg2, arg3, arg4, child,				      &ret);		syscall_cancel(debugger->pid, result);		debugger->handle_trace = debugger_syscall;		return(ret);#ifdef __NR_waitpid	case __NR_waitpid:#endif	case __NR_wait4:		if(!debugger_wait(debugger, (int *) arg2, arg3, 				  debugger_syscall, debugger_normal_return, 				  proxy_wait_return))			return(0);		break;	case __NR_kill:		if(!debugger->debugee->in_context) 			child = debugger->debugee->pid;		if(arg1 == debugger->debugee->pid){			result = kill(child, arg2);			syscall_cancel(debugger->pid, result);			debugger->handle_trace = debugger_syscall;			return(0);		}		else debugger->handle_trace = debugger_normal_return;		break;	default:		debugger->handle_trace = debugger_normal_return;	}	syscall_continue(debugger->pid);	return(0);}/* Used by the tracing thread */static debugger_state parent;static int parent_syscall(debugger_state *debugger, int pid);int init_parent_proxy(int pid){	parent = ((debugger_state) { .pid 		= pid,				     .wait_options 	= 0,				     .wait_status_ptr 	= NULL,				     .waiting 		= 0,				     .real_wait 	= 0,				     .expecting_child 	= 0,				     .handle_trace  	= parent_syscall,				     .debugee 		= NULL } );	return(0);}int parent_normal_return(debugger_state *debugger, pid_t unused){	debugger->handle_trace = parent_syscall;	syscall_continue(debugger->pid);	return(0);}static int parent_syscall(debugger_state *debugger, int pid){	long arg1, arg2, arg3, arg4, arg5;	int syscall;	syscall = get_syscall(pid, &arg1, &arg2, &arg3, &arg4, &arg5);			if((syscall == __NR_wait4)#ifdef __NR_waitpid	   || (syscall == __NR_waitpid)#endif	){		debugger_wait(&parent, (int *) arg2, arg3, parent_syscall,			      parent_normal_return, parent_wait_return);	}	else ptrace(PTRACE_SYSCALL, pid, 0, 0);	return(0);}int debugger_normal_return(debugger_state *debugger, pid_t unused){	debugger->handle_trace = debugger_syscall;	syscall_continue(debugger->pid);	return(0);}void debugger_cancelled_return(debugger_state *debugger, int result){	debugger->handle_trace = debugger_syscall;	syscall_set_result(debugger->pid, result);	syscall_continue(debugger->pid);}/* Used by the tracing thread */static debugger_state debugger;static debugee_state debugee;void init_proxy (pid_t debugger_pid, int stopped, int status){	debugger.pid = debugger_pid;	debugger.handle_trace = debugger_syscall;	debugger.debugee = &debugee;	debugger.waiting = 0;	debugger.real_wait = 0;	debugger.expecting_child = 0;	debugee.pid = 0;	debugee.traced = 0;	debugee.stopped = stopped;	debugee.event = 0;	debugee.zombie = 0;	debugee.died = 0;	debugee.wait_status = status;	debugee.in_context = 1;}int debugger_proxy(int status, int pid){	int ret = 0, sig;	if(WIFSTOPPED(status)){		sig = WSTOPSIG(status);		if (sig == SIGTRAP)			ret = (*debugger.handle_trace)(&debugger, pid);						       		else if(sig == SIGCHLD){			if(debugger.expecting_child){				ptrace(PTRACE_SYSCALL, debugger.pid, 0, sig);				debugger.expecting_child = 0;			}			else if(debugger.waiting)				real_wait_return(&debugger);			else {				ptrace(PTRACE_SYSCALL, debugger.pid, 0, sig);				debugger.real_wait = 1;			}		}		else ptrace(PTRACE_SYSCALL, debugger.pid, 0, sig);	}	else if(WIFEXITED(status)){		tracer_panic("debugger (pid %d) exited with status %d", 			     debugger.pid, WEXITSTATUS(status));	}	else if(WIFSIGNALED(status)){		tracer_panic("debugger (pid %d) exited with signal %d", 			     debugger.pid, WTERMSIG(status));	}	else {		tracer_panic("proxy got unknown status (0x%x) on debugger "			     "(pid %d)", status, debugger.pid);	}	return(ret);}void child_proxy(pid_t pid, int status){	debugee.event = 1;	debugee.wait_status = status;	if(WIFSTOPPED(status)){		debugee.stopped = 1;		debugger.expecting_child = 1;		kill(debugger.pid, SIGCHLD);	}	else if(WIFEXITED(status) || WIFSIGNALED(status)){		debugee.zombie = 1;		debugger.expecting_child = 1;		kill(debugger.pid, SIGCHLD);	}	else panic("proxy got unknown status (0x%x) on child (pid %d)", 		   status, pid);}void debugger_parent_signal(int status, int pid){	int sig;	if(WIFSTOPPED(status)){		sig = WSTOPSIG(status);		if(sig == SIGTRAP) (*parent.handle_trace)(&parent, pid);		else ptrace(PTRACE_SYSCALL, pid, 0, sig);	}}void fake_child_exit(void){	int status, pid;	child_proxy(1, W_EXITCODE(0, 0));	while(debugger.waiting == 1){		CATCH_EINTR(pid = waitpid(debugger.pid, &status, WUNTRACED));		if(pid != debugger.pid){			printk("fake_child_exit - waitpid failed, "			       "errno = %d\n", errno);			return;		}		debugger_proxy(status, debugger.pid);	}	CATCH_EINTR(pid = waitpid(debugger.pid, &status, WUNTRACED));	if(pid != debugger.pid){		printk("fake_child_exit - waitpid failed, "		       "errno = %d\n", errno);		return;	}	if(ptrace(PTRACE_DETACH, debugger.pid, 0, SIGCONT) < 0)		printk("fake_child_exit - PTRACE_DETACH failed, errno = %d\n",		       errno);}char gdb_init_string[] = "att 1 \n\b panic \n\b stop \n\handle SIGWINCH nostop noprint pass \n\";int start_debugger(char *prog, int startup, int stop, int *fd_out){	int slave, child;	slave = open_gdb_chan();	child = fork();	if(child == 0){		char *tempname = NULL;		int fd;	        if(setsid() < 0) perror("setsid");		if((dup2(slave, 0) < 0) || (dup2(slave, 1) < 0) || 		   (dup2(slave, 2) < 0)){			printk("start_debugger : dup2 failed, errno = %d\n",			       errno);			exit(1);		}		if(ioctl(0, TIOCSCTTY, 0) < 0){			printk("start_debugger : TIOCSCTTY failed, "			       "errno = %d\n", errno);			exit(1);		}		if(tcsetpgrp (1, os_getpid()) < 0){			printk("start_debugger : tcsetpgrp failed, "			       "errno = %d\n", errno);#ifdef notdef			exit(1);#endif		}		fd = make_tempfile("/tmp/gdb_init-XXXXXX", &tempname, 0);		if(fd < 0){			printk("start_debugger : make_tempfile failed,"			       "err = %d\n", -fd);			exit(1);		}		os_write_file(fd, gdb_init_string, sizeof(gdb_init_string) - 1);		if(startup){			if(stop){				os_write_file(fd, "b start_kernel\n",				      strlen("b start_kernel\n"));			}			os_write_file(fd, "c\n", strlen("c\n"));		}		if(ptrace(PTRACE_TRACEME, 0, 0, 0) < 0){			printk("start_debugger :  PTRACE_TRACEME failed, "			       "errno = %d\n", errno);			exit(1);		}		execlp("gdb", "gdb", "--command", tempname, prog, NULL);		printk("start_debugger : exec of gdb failed, errno = %d\n",		       errno);	}	if(child < 0){		printk("start_debugger : fork for gdb failed, errno = %d\n",		       errno);		return(-1);	}	*fd_out = slave;	return(child);}/* * Overrides for Emacs so that we follow Linus's tabbing style. * Emacs will notice this stuff at the end of the file and automatically * adjust the settings for this buffer only.  This must remain at the end * of the file. * --------------------------------------------------------------------------- * Local variables: * c-file-style: "linux" * End: */

⌨️ 快捷键说明

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