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

📄 syscall.c

📁 linux进程跟踪的工具和源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
/* * Copyright (c) 1991, 1992 Paul Kranenburg <pk@cs.few.eur.nl> * Copyright (c) 1993 Branko Lankester <branko@hacktic.nl> * Copyright (c) 1993, 1994, 1995, 1996 Rick Sladkey <jrs@world.std.com> * Copyright (c) 1996-1999 Wichert Akkerman <wichert@cistron.nl> * Copyright (c) 1999 IBM Deutschland Entwicklung GmbH, IBM Corporation *                     Linux for s390 port by D.J. Barrow *                    <barrow_dj@mail.yahoo.com,djbarrow@de.ibm.com> * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright *    notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright *    notice, this list of conditions and the following disclaimer in the *    documentation and/or other materials provided with the distribution. * 3. The name of the author may not be used to endorse or promote products *    derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * *	$Id: syscall.c,v 1.30 2001/03/28 20:29:17 wichert Exp $ */#include "defs.h"#include <signal.h>#include <time.h>#include <errno.h>#include <sys/user.h>#include <sys/syscall.h>#include <sys/param.h>#if HAVE_ASM_REG_H#ifdef SPARC#  define fpq kernel_fpq#  define fq kernel_fq#  define fpu kernel_fpu#endif#include <asm/reg.h>#ifdef SPARC#  undef fpq#  undef fq#  undef fpu #endif#endif#ifdef HAVE_SYS_REG_H#include <sys/reg.h>#ifndef PTRACE_PEEKUSR# define PTRACE_PEEKUSR PTRACE_PEEKUSER#endif#elif defined(HAVE_LINUX_PTRACE_H)#undef PTRACE_SYSCALL#include <linux/ptrace.h>#endif#if defined(LINUX) && defined(IA64)# include <asm/ptrace_offsets.h># include <asm/rse.h>#endif#ifndef SYS_ERRLIST_DECLAREDextern int sys_nerr;extern char *sys_errlist[];#endif /* SYS_ERRLIST_DECLARED */#define NR_SYSCALL_BASE 0#ifdef LINUX#ifndef ERESTARTSYS#define ERESTARTSYS	512#endif#ifndef ERESTARTNOINTR#define ERESTARTNOINTR	513#endif#ifndef ERESTARTNOHAND#define ERESTARTNOHAND	514	/* restart if no handler.. */#endif#ifndef ENOIOCTLCMD#define ENOIOCTLCMD	515	/* No ioctl command */#endif#ifndef NSIG#define NSIG 32#endif#ifdef ARM#undef NSIG#define NSIG 32#undef NR_SYSCALL_BASE#define NR_SYSCALL_BASE __NR_SYSCALL_BASE#endif#endif /* LINUX */#include "syscall.h"/* Define these shorthand notations to simplify the syscallent files. */#define TF TRACE_FILE#define TI TRACE_IPC#define TN TRACE_NETWORK#define TP TRACE_PROCESS#define TS TRACE_SIGNALstruct sysent sysent0[] = {#include "syscallent.h"};int nsyscalls0 = sizeof sysent0 / sizeof sysent0[0];#if SUPPORTED_PERSONALITIES >= 2struct sysent sysent1[] = {#include "syscallent1.h"};int nsyscalls1 = sizeof sysent1 / sizeof sysent1[0];#endif /* SUPPORTED_PERSONALITIES >= 2 */#if SUPPORTED_PERSONALITIES >= 3struct sysent sysent2[] = {#include "syscallent2.h"};int nsyscalls2 = sizeof sysent2 / sizeof sysent2[0];#endif /* SUPPORTED_PERSONALITIES >= 3 */struct sysent *sysent;int nsyscalls;/* Now undef them since short defines cause wicked namespace pollution. */#undef TF#undef TI#undef TN#undef TP#undef TSchar *errnoent0[] = {#include "errnoent.h"};int nerrnos0 = sizeof errnoent0 / sizeof errnoent0[0];#if SUPPORTED_PERSONALITIES >= 2char *errnoent1[] = {#include "errnoent1.h"};int nerrnos1 = sizeof errnoent1 / sizeof errnoent1[0];#endif /* SUPPORTED_PERSONALITIES >= 2 */#if SUPPORTED_PERSONALITIES >= 3char *errnoent2[] = {#include "errnoent2.h"};int nerrnos2 = sizeof errnoent2 / sizeof errnoent2[0];#endif /* SUPPORTED_PERSONALITIES >= 3 */char **errnoent;int nerrnos;int current_personality;intset_personality(personality)int personality;{	switch (personality) {	case 0:		errnoent = errnoent0;		nerrnos = nerrnos0;		sysent = sysent0;		nsyscalls = nsyscalls0;		ioctlent = ioctlent0;		nioctlents = nioctlents0;		signalent = signalent0;		nsignals = nsignals0;		break;#if SUPPORTED_PERSONALITIES >= 2	case 1:		errnoent = errnoent1;		nerrnos = nerrnos1;		sysent = sysent1;		nsyscalls = nsyscalls1;		ioctlent = ioctlent1;		nioctlents = nioctlents1;		signalent = signalent1;		nsignals = nsignals1;		break;#endif /* SUPPORTED_PERSONALITIES >= 2 */#if SUPPORTED_PERSONALITIES >= 3	case 2:		errnoent = errnoent2;		nerrnos = nerrnos2;		sysent = sysent2;		nsyscalls = nsyscalls2;		ioctlent = ioctlent2;		nioctlents = nioctlents2;		signalent = signalent2;		nsignals = nsignals2;		break;#endif /* SUPPORTED_PERSONALITIES >= 3 */	default:		return -1;	}	current_personality = personality;	return 0;}int qual_flags[MAX_QUALS];static int call_count[MAX_QUALS];static int error_count[MAX_QUALS];static struct timeval tv_count[MAX_QUALS];static int sorted_count[MAX_QUALS];static struct timeval shortest = { 1000000, 0 };static int lookup_syscall(), lookup_signal(), lookup_fault(), lookup_desc();static struct qual_options {	int bitflag;	char *option_name;	int (*lookup)();	char *argument_name;} qual_options[] = {	{ QUAL_TRACE,	"trace",	lookup_syscall,	"system call"	},	{ QUAL_TRACE,	"t",		lookup_syscall,	"system call"	},	{ QUAL_ABBREV,	"abbrev",	lookup_syscall,	"system call"	},	{ QUAL_ABBREV,	"a",		lookup_syscall,	"system call"	},	{ QUAL_VERBOSE,	"verbose",	lookup_syscall,	"system call"	},	{ QUAL_VERBOSE,	"v",		lookup_syscall,	"system call"	},	{ QUAL_RAW,	"raw",		lookup_syscall,	"system call"	},	{ QUAL_RAW,	"x",		lookup_syscall,	"system call"	},	{ QUAL_SIGNAL,	"signal",	lookup_signal,	"signal"	},	{ QUAL_SIGNAL,	"signals",	lookup_signal,	"signal"	},	{ QUAL_SIGNAL,	"s",		lookup_signal,	"signal"	},	{ QUAL_FAULT,	"fault",	lookup_fault,	"fault"		},	{ QUAL_FAULT,	"faults",	lookup_fault,	"fault"		},	{ QUAL_FAULT,	"m",		lookup_fault,	"fault"		},	{ QUAL_READ,	"read",		lookup_desc,	"descriptor"	},	{ QUAL_READ,	"reads",	lookup_desc,	"descriptor"	},	{ QUAL_READ,	"r",		lookup_desc,	"descriptor"	},	{ QUAL_WRITE,	"write",	lookup_desc,	"descriptor"	},	{ QUAL_WRITE,	"writes",	lookup_desc,	"descriptor"	},	{ QUAL_WRITE,	"w",		lookup_desc,	"descriptor"	},	{ 0,		NULL,		NULL,		NULL		},};static intlookup_syscall(s)char *s;{	int i;	for (i = 0; i < nsyscalls; i++) {		if (strcmp(s, sysent[i].sys_name) == 0)			return i;	}	return -1;}static intlookup_signal(s)char *s;{	int i;	char buf[32];	if (s && *s && isdigit((unsigned char)*s))		return atoi(s);	strcpy(buf, s);	s = buf;	for (i = 0; s[i]; i++)		s[i] = toupper((unsigned char)(s[i]));	if (strncmp(s, "SIG", 3) == 0)		s += 3;	for (i = 0; i <= NSIG; i++) {		if (strcmp(s, signame(i) + 3) == 0)			return i;	}	return -1;}static intlookup_fault(s)char *s;{	return -1;}static intlookup_desc(s)char *s;{	if (s && *s && isdigit((unsigned char)*s))		return atoi(s);	return -1;}static intlookup_class(s)char *s;{	if (strcmp(s, "file") == 0)		return TRACE_FILE;	if (strcmp(s, "ipc") == 0)		return TRACE_IPC;	if (strcmp(s, "network") == 0)		return TRACE_NETWORK;	if (strcmp(s, "process") == 0)		return TRACE_PROCESS;	if (strcmp(s, "signal") == 0)		return TRACE_SIGNAL;	return -1;}voidqualify(s)char *s;{	struct qual_options *opt;	int not;	char *p;	int i, n;	opt = &qual_options[0];	for (i = 0; (p = qual_options[i].option_name); i++) {		n = strlen(p);		if (strncmp(s, p, n) == 0 && s[n] == '=') {			opt = &qual_options[i];			s += n + 1;			break;		}	}	not = 0;	if (*s == '!') {		not = 1;		s++;	}	if (strcmp(s, "none") == 0) {		not = 1 - not;		s = "all";	}	if (strcmp(s, "all") == 0) {		for (i = 0; i < MAX_QUALS; i++) {			if (not)				qual_flags[i] &= ~opt->bitflag;			else				qual_flags[i] |= opt->bitflag;		}		return;	}	for (i = 0; i < MAX_QUALS; i++) {		if (not)			qual_flags[i] |= opt->bitflag;		else			qual_flags[i] &= ~opt->bitflag;	}	for (p = strtok(s, ","); p; p = strtok(NULL, ",")) {		if (opt->bitflag == QUAL_TRACE && (n = lookup_class(p)) > 0) {			for (i = 0; i < MAX_QUALS; i++) {				if (sysent[i].sys_flags & n) {					if (not)						qual_flags[i] &= ~opt->bitflag;					else						qual_flags[i] |= opt->bitflag;				}			}			continue;		}		if ((n = (*opt->lookup)(p)) < 0) {			fprintf(stderr, "strace: invalid %s `%s'\n",				opt->argument_name, p);			exit(1);		}		if (not)			qual_flags[n] &= ~opt->bitflag;		else			qual_flags[n] |= opt->bitflag;	}	return;}static voiddumpio(tcp)struct tcb *tcp;{	if (syserror(tcp))		return;	if (tcp->u_arg[0] < 0 || tcp->u_arg[0] >= MAX_QUALS)		return;	switch (tcp->scno + NR_SYSCALL_BASE) {	case SYS_read:#ifdef SYS_recv	case SYS_recv:#endif#ifdef SYS_recvfrom	case SYS_recvfrom:#endif		if (qual_flags[tcp->u_arg[0]] & QUAL_READ)			dumpstr(tcp, tcp->u_arg[1], tcp->u_rval);		break;	case SYS_write:#ifdef SYS_send	case SYS_send:#endif#ifdef SYS_sendto	case SYS_sendto:#endif		if (qual_flags[tcp->u_arg[0]] & QUAL_WRITE)			dumpstr(tcp, tcp->u_arg[1], tcp->u_arg[2]);		break;	}}#ifndef FREEBSDenum subcall_style { shift_style, deref_style, mask_style, door_style };#else /* FREEBSD */enum subcall_style { shift_style, deref_style, mask_style, door_style, table_style };struct subcall {  int call;  int nsubcalls;  int subcalls[5];};const struct subcall subcalls_table[] = {  { SYS_shmsys, 5, { SYS_shmat, SYS_shmctl, SYS_shmdt, SYS_shmget, SYS_shmctl } },#ifdef SYS_semconfig  { SYS_semsys, 4, { SYS___semctl, SYS_semget, SYS_semop, SYS_semconfig } },#else  { SYS_semsys, 3, { SYS___semctl, SYS_semget, SYS_semop } },#endif  { SYS_msgsys, 4, { SYS_msgctl, SYS_msgget, SYS_msgsnd, SYS_msgrcv } },};#endif /* FREEBSD */#if !(defined(LINUX) && ( defined(ALPHA) || defined(IA64) || defined(MIPS) ))const int socket_map [] = {	       /* SYS_SOCKET      */ 97,	       /* SYS_BIND        */ 104,	       /* SYS_CONNECT     */ 98,	       /* SYS_LISTEN      */ 106,	       /* SYS_ACCEPT      */ 99,	       /* SYS_GETSOCKNAME */ 150,	       /* SYS_GETPEERNAME */ 141,	       /* SYS_SOCKETPAIR  */ 135,	       /* SYS_SEND        */ 101,	       /* SYS_RECV        */ 102,	       /* SYS_SENDTO      */ 133,	       /* SYS_RECVFROM    */ 125,	       /* SYS_SHUTDOWN    */ 134,	       /* SYS_SETSOCKOPT  */ 105,	       /* SYS_GETSOCKOPT  */ 118,	       /* SYS_SENDMSG     */ 114,	       /* SYS_RECVMSG     */ 113};voidsparc_socket_decode (tcp)struct tcb *tcp;{	volatile long addr;	volatile int i, n;	if (tcp->u_arg [0] < 1 || tcp->u_arg [0] > sizeof(socket_map)/sizeof(int)+1){		return;	}	tcp->scno = socket_map [tcp->u_arg [0]-1];	n = tcp->u_nargs = sysent [tcp->scno].nargs;	addr = tcp->u_arg [1];	for (i = 0; i < n; i++){	        int arg;		if (umoven (tcp, addr, sizeof (arg), (void *) &arg) < 0)			arg = 0;		tcp->u_arg [i] = arg;		addr += sizeof (arg);	}}static voiddecode_subcall(tcp, subcall, nsubcalls, style)struct tcb *tcp;int subcall;int nsubcalls;enum subcall_style style;{	int i, addr, mask, arg;	switch (style) {	case shift_style:		if (tcp->u_arg[0] < 0 || tcp->u_arg[0] >= nsubcalls)			return;		tcp->scno = subcall + tcp->u_arg[0];		if (sysent[tcp->scno].nargs != -1)			tcp->u_nargs = sysent[tcp->scno].nargs;		else			tcp->u_nargs--;		for (i = 0; i < tcp->u_nargs; i++)			tcp->u_arg[i] = tcp->u_arg[i + 1];		break;	case deref_style:		if (tcp->u_arg[0] < 0 || tcp->u_arg[0] >= nsubcalls)			return;		tcp->scno = subcall + tcp->u_arg[0];		addr = tcp->u_arg[1];		for (i = 0; i < sysent[tcp->scno].nargs; i++) {			if (umove(tcp, addr, &arg) < 0)				arg = 0;			tcp->u_arg[i] = arg;			addr += sizeof(arg);		}		tcp->u_nargs = sysent[tcp->scno].nargs;		break;	case mask_style:		mask = (tcp->u_arg[0] >> 8) & 0xff;		for (i = 0; mask; i++)			mask >>= 1;		if (i >= nsubcalls)			return;		tcp->u_arg[0] &= 0xff;		tcp->scno = subcall + i;		if (sysent[tcp->scno].nargs != -1)			tcp->u_nargs = sysent[tcp->scno].nargs;		break;	case door_style:		/*		 * Oh, yuck.  The call code is the *sixth* argument.		 * (don't you mean the *last* argument? - JH)		 */		if (tcp->u_arg[5] < 0 || tcp->u_arg[5] >= nsubcalls)			return;		tcp->scno = subcall + tcp->u_arg[5];		if (sysent[tcp->scno].nargs != -1)			tcp->u_nargs = sysent[tcp->scno].nargs;		else			tcp->u_nargs--;		break;#ifdef FREEBSD	case table_style:		for (i = 0; i < sizeof(subcalls_table) / sizeof(struct subcall); i++)			if (subcalls_table[i].call == tcp->scno) break;		if (i < sizeof(subcalls_table) / sizeof(struct subcall) &&		    tcp->u_arg[0] >= 0 && tcp->u_arg[0] < subcalls_table[i].nsubcalls) {			tcp->scno = subcalls_table[i].subcalls[tcp->u_arg[0]];			for (i = 0; i < tcp->u_nargs; i++)				tcp->u_arg[i] = tcp->u_arg[i + 1];		}		break;#endif /* FREEBSD */	}}#endifstruct tcb *tcp_last = NULL;static intinternal_syscall(tcp)struct tcb *tcp;{	/*	 * We must always trace a few critical system calls in order to	 * correctly support following forks in the presence of tracing	 * qualifiers.	 */	switch (tcp->scno + NR_SYSCALL_BASE) {#ifdef SYS_fork	case SYS_fork:#endif#ifdef SYS_vfork	case SYS_vfork:#endif		internal_fork(tcp);		break;#ifdef SYS_clone	case SYS_clone:		internal_clone(tcp);		break;#endif#ifdef SYS_execv	case SYS_execv:#endif#ifdef SYS_execve	case SYS_execve:#endif		internal_exec(tcp);		break;#ifdef SYS_wait	case SYS_wait:#endif#ifdef SYS_wait4	case SYS_wait4:#endif#ifdef SYS_waitpid	case SYS_waitpid:#endif#ifdef SYS_waitsys	case SYS_waitsys:#endif		internal_wait(tcp);		break;#ifdef SYS_exit	case SYS_exit:#endif		internal_exit(tcp);		break;	}	return 0;}#ifdef LINUX#if defined (I386)	static long eax;#elif defined (IA64)	long r8, r10, psr;	long ia32 = 0;#elif defined (POWERPC)	static long result,flags;

⌨️ 快捷键说明

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