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

📄 syscall.c

📁 linux进程跟踪的工具和源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
		if (tcp->scno >= 0 && tcp->scno < nsyscalls && sysent[tcp->scno].nargs != -1)			tcp->u_nargs = sysent[tcp->scno].nargs;		else      	        	tcp->u_nargs = MAX_ARGS;		for (i = 0; i < tcp->u_nargs; i++)			tcp->u_arg[i] = *((&regs.r_o0) + i);	}#elif defined (HPPA)	{		int i;		if (tcp->scno >= 0 && tcp->scno < nsyscalls && sysent[tcp->scno].nargs != -1)			tcp->u_nargs = sysent[tcp->scno].nargs;		else      	        	tcp->u_nargs = MAX_ARGS;		for (i = 0; i < tcp->u_nargs; i++) {			if (upeek(pid, PT_GR26-4*i, &tcp->u_arg[i]) < 0)				return -1;		}	}#else /* Other architecture (like i386) (32bits specific) */	{		int i;		if (tcp->scno >= 0 && tcp->scno < nsyscalls && sysent[tcp->scno].nargs != -1)			tcp->u_nargs = sysent[tcp->scno].nargs;		else      	        	tcp->u_nargs = MAX_ARGS;		for (i = 0; i < tcp->u_nargs; i++) {			if (upeek(pid, i*4, &tcp->u_arg[i]) < 0)				return -1;		}	}#endif #endif /* LINUX */#ifdef SUNOS4	{		int i;		if (tcp->scno >= 0 && tcp->scno < nsyscalls && sysent[tcp->scno].nargs != -1)			tcp->u_nargs = sysent[tcp->scno].nargs;		else      	        	tcp->u_nargs = MAX_ARGS;		for (i = 0; i < tcp->u_nargs; i++) {			struct user *u;			if (upeek(pid, uoff(u_arg[0]) +			    (i*sizeof(u->u_arg[0])), &tcp->u_arg[i]) < 0)				return -1;		}	}#endif /* SUNOS4 */#ifdef SVR4#ifdef MIPS	/*	 * SGI is broken: even though it has pr_sysarg, it doesn't	 * set them on system call entry.  Get a clue.	 */	if (tcp->scno >= 0 && tcp->scno < nsyscalls && sysent[tcp->scno].nargs != -1)		tcp->u_nargs = sysent[tcp->scno].nargs;	else		tcp->u_nargs = tcp->status.pr_nsysarg;	if (tcp->u_nargs > 4) {		memcpy(tcp->u_arg, &tcp->status.pr_reg[CTX_A0],			4*sizeof(tcp->u_arg[0]));		umoven(tcp, tcp->status.pr_reg[CTX_SP] + 16,			(tcp->u_nargs - 4)*sizeof(tcp->u_arg[0]), (char *) (tcp->u_arg + 4));	}	else {		memcpy(tcp->u_arg, &tcp->status.pr_reg[CTX_A0],			tcp->u_nargs*sizeof(tcp->u_arg[0]));	}#elif UNIXWARE >= 2	/*	 * Like SGI, UnixWare doesn't set pr_sysarg until system call exit	 */	if (tcp->scno >= 0 && tcp->scno < nsyscalls && sysent[tcp->scno].nargs != -1)		tcp->u_nargs = sysent[tcp->scno].nargs;	else		tcp->u_nargs = tcp->status.pr_lwp.pr_nsysarg;	umoven(tcp, tcp->status.PR_REG[UESP] + 4,		tcp->u_nargs*sizeof(tcp->u_arg[0]), (char *) tcp->u_arg);#elif defined (HAVE_PR_SYSCALL)	if (tcp->scno >= 0 && tcp->scno < nsyscalls && sysent[tcp->scno].nargs != -1)		tcp->u_nargs = sysent[tcp->scno].nargs;	else		tcp->u_nargs = tcp->status.pr_nsysarg;	{		int i;		for (i = 0; i < tcp->u_nargs; i++)			tcp->u_arg[i] = tcp->status.pr_sysarg[i];	}#elif defined (I386)	if (tcp->scno >= 0 && tcp->scno < nsyscalls && sysent[tcp->scno].nargs != -1)		tcp->u_nargs = sysent[tcp->scno].nargs;	else		tcp->u_nargs = 5;	umoven(tcp, tcp->status.PR_REG[UESP] + 4,		tcp->u_nargs*sizeof(tcp->u_arg[0]), (char *) tcp->u_arg);#else	I DONT KNOW WHAT TO DO#endif /* !HAVE_PR_SYSCALL */#endif /* SVR4 */#ifdef FREEBSD	if (tcp->scno >= 0 && tcp->scno < nsyscalls &&	    sysent[tcp->scno].nargs > tcp->status.val)		tcp->u_nargs = sysent[tcp->scno].nargs;	else 	  	tcp->u_nargs = tcp->status.val;	if (tcp->u_nargs < 0)		tcp->u_nargs = 0;	if (tcp->u_nargs > MAX_ARGS)		tcp->u_nargs = MAX_ARGS;	switch(regs.r_eax) {	case SYS___syscall:		pread(tcp->pfd, &tcp->u_arg, tcp->u_nargs * sizeof(unsigned long),		      regs.r_esp + sizeof(int) + sizeof(quad_t));	  break;        case SYS_syscall:		pread(tcp->pfd, &tcp->u_arg, tcp->u_nargs * sizeof(unsigned long),		      regs.r_esp + 2 * sizeof(int));	  break;        default:		pread(tcp->pfd, &tcp->u_arg, tcp->u_nargs * sizeof(unsigned long),		      regs.r_esp + sizeof(int));	  break;	}#endif /* FREEBSD */	return 1;}inttrace_syscall(tcp)struct tcb *tcp;{	int sys_res;	struct timeval tv;	int res;	/* Measure the exit time as early as possible to avoid errors. */	if (dtime && (tcp->flags & TCB_INSYSCALL))		gettimeofday(&tv, NULL);	res = get_scno(tcp);	if (res != 1)		return res;	res = syscall_fixup(tcp);	if (res != 1)		return res;	if (tcp->flags & TCB_INSYSCALL) {		long u_error;		res = get_error(tcp);		if (res != 1)			return res;		u_error = tcp->u_error;		internal_syscall(tcp);		if (tcp->scno >= 0 && tcp->scno < nsyscalls &&		    !(qual_flags[tcp->scno] & QUAL_TRACE)) {			tcp->flags &= ~TCB_INSYSCALL;			return 0;		}		if (tcp->flags & TCB_REPRINT) {			printleader(tcp);			tprintf("<... ");			if (tcp->scno >= nsyscalls || tcp->scno < 0)				tprintf("syscall_%lu", tcp->scno);			else				tprintf("%s", sysent[tcp->scno].sys_name);			tprintf(" resumed> ");		}		if (cflag && tcp->scno < nsyscalls && tcp->scno >= 0) {			call_count[tcp->scno]++;			if (tcp->u_error)				error_count[tcp->scno]++;			tv_sub(&tv, &tv, &tcp->etime);#ifdef LINUX			if (tv_cmp(&tv, &tcp->dtime) > 0) {				static struct timeval one_tick =					{ 0, 1000000 / HZ };				if (tv_nz(&tcp->dtime))					tv = tcp->dtime;				else if (tv_cmp(&tv, &one_tick) > 0) {					if (tv_cmp(&shortest, &one_tick) < 0)						tv = shortest;					else						tv = one_tick;				}			}#endif /* LINUX */			if (tv_cmp(&tv, &shortest) < 0)				shortest = tv;			tv_add(&tv_count[tcp->scno],				&tv_count[tcp->scno], &tv);			tcp->flags &= ~TCB_INSYSCALL;			return 0;		}		if (tcp->scno >= nsyscalls || tcp->scno < 0		    || (qual_flags[tcp->scno] & QUAL_RAW))			sys_res = printargs(tcp);		else			sys_res = (*sysent[tcp->scno].sys_func)(tcp);		u_error = tcp->u_error;		tprintf(") ");		tabto(acolumn);		if (tcp->scno >= nsyscalls || tcp->scno < 0 ||		    qual_flags[tcp->scno] & QUAL_RAW) {			if (u_error)				tprintf("= -1 (errno %ld)", u_error);			else				tprintf("= %#lx", tcp->u_rval);		}		else if (!(sys_res & RVAL_NONE) && u_error) {			switch (u_error) {#ifdef LINUX			case ERESTARTSYS:				tprintf("= ? ERESTARTSYS (To be restarted)");				break;			case ERESTARTNOINTR:				tprintf("= ? ERESTARTNOINTR (To be restarted)");				break;			case ERESTARTNOHAND:				tprintf("= ? ERESTARTNOHAND (To be restarted)");				break;#endif /* LINUX */			default:				tprintf("= -1 ");				if (u_error < nerrnos && u_error < sys_nerr)					tprintf("%s (%s)", errnoent[u_error],						sys_errlist[u_error]);				else if (u_error < nerrnos)					tprintf("%s (errno %ld)",						errnoent[u_error], u_error);				else if (u_error < sys_nerr)					tprintf("ERRNO_%ld (%s)", u_error,						sys_errlist[u_error]);				else					tprintf("E??? (errno %ld)", u_error);				break;			}		}		else {			if (sys_res & RVAL_NONE)				tprintf("= ?");			else {				switch (sys_res & RVAL_MASK) {				case RVAL_HEX:					tprintf("= %#lx", tcp->u_rval);					break;				case RVAL_OCTAL:					tprintf("= %#lo", tcp->u_rval);					break;				case RVAL_UDECIMAL:					tprintf("= %lu", tcp->u_rval);					break;				case RVAL_DECIMAL:					tprintf("= %ld", tcp->u_rval);					break;#ifdef HAVE_LONG_LONG				case RVAL_LHEX:					tprintf("= %#llx", tcp->u_lrval);					break;				case RVAL_LOCTAL:					tprintf("= %#llo", tcp->u_lrval);					break;				case RVAL_LUDECIMAL:					tprintf("= %llu", tcp->u_lrval);					break;				case RVAL_LDECIMAL:					tprintf("= %lld", tcp->u_lrval);					break;#endif				default:					fprintf(stderr,						"invalid rval format\n");					break;				}			}			if ((sys_res & RVAL_STR) && tcp->auxstr)				tprintf(" (%s)", tcp->auxstr);		}		if (dtime) {			tv_sub(&tv, &tv, &tcp->etime);			tprintf(" <%ld.%06ld>",				(long) tv.tv_sec, (long) tv.tv_usec);		}		printtrailer(tcp);		dumpio(tcp);		if (fflush(tcp->outf) == EOF)			return -1;		tcp->flags &= ~TCB_INSYSCALL;		return 0;	}	/* Entering system call */	res = syscall_enter(tcp);	if (res != 1)		return res;	switch (tcp->scno + NR_SYSCALL_BASE) {#ifdef LINUX#if !defined (ALPHA) && !defined(IA64) && !defined(SPARC) && !defined(MIPS) && !defined(HPPA)	case SYS_socketcall:		decode_subcall(tcp, SYS_socket_subcall,			SYS_socket_nsubcalls, deref_style);		break;	case SYS_ipc:		decode_subcall(tcp, SYS_ipc_subcall,			SYS_ipc_nsubcalls, shift_style);		break;#endif /* !ALPHA && !IA64 && !MIPS && !SPARC */#ifdef SPARC	case SYS_socketcall:		sparc_socket_decode (tcp);		break;#endif#endif /* LINUX */#ifdef SVR4#ifdef SYS_pgrpsys_subcall	case SYS_pgrpsys:		decode_subcall(tcp, SYS_pgrpsys_subcall,			SYS_pgrpsys_nsubcalls, shift_style);		break;#endif /* SYS_pgrpsys_subcall */#ifdef SYS_sigcall_subcall	case SYS_sigcall:		decode_subcall(tcp, SYS_sigcall_subcall,			SYS_sigcall_nsubcalls, mask_style);		break;#endif /* SYS_sigcall_subcall */	case SYS_msgsys:		decode_subcall(tcp, SYS_msgsys_subcall,			SYS_msgsys_nsubcalls, shift_style);		break;	case SYS_shmsys:		decode_subcall(tcp, SYS_shmsys_subcall,			SYS_shmsys_nsubcalls, shift_style);		break;	case SYS_semsys:		decode_subcall(tcp, SYS_semsys_subcall,			SYS_semsys_nsubcalls, shift_style);		break;#if 0 /* broken */	case SYS_utssys:		decode_subcall(tcp, SYS_utssys_subcall,			SYS_utssys_nsubcalls, shift_style);		break;#endif	case SYS_sysfs:		decode_subcall(tcp, SYS_sysfs_subcall,			SYS_sysfs_nsubcalls, shift_style);		break;	case SYS_spcall:		decode_subcall(tcp, SYS_spcall_subcall,			SYS_spcall_nsubcalls, shift_style);		break;#ifdef SYS_context_subcall	case SYS_context:		decode_subcall(tcp, SYS_context_subcall,			SYS_context_nsubcalls, shift_style);		break;#endif /* SYS_context_subcall */#ifdef SYS_door_subcall	case SYS_door:		decode_subcall(tcp, SYS_door_subcall,			SYS_door_nsubcalls, door_style);		break;#endif /* SYS_door_subcall */#ifdef SYS_kaio_subcall	case SYS_kaio:		decode_subcall(tcp, SYS_kaio_subcall,			SYS_kaio_nsubcalls, shift_style);		break;#endif	#endif /* SVR4 */#ifdef FREEBSD	case SYS_msgsys:	case SYS_shmsys:	case SYS_semsys:		decode_subcall(tcp, 0, 0, table_style);		break;#endif		#ifdef SUNOS4	case SYS_semsys:		decode_subcall(tcp, SYS_semsys_subcall,			SYS_semsys_nsubcalls, shift_style);		break;	case SYS_msgsys:		decode_subcall(tcp, SYS_msgsys_subcall,			SYS_msgsys_nsubcalls, shift_style);		break;	case SYS_shmsys:		decode_subcall(tcp, SYS_shmsys_subcall,			SYS_shmsys_nsubcalls, shift_style);		break;#endif	}	internal_syscall(tcp);	if (tcp->scno >=0 && tcp->scno < nsyscalls && !(qual_flags[tcp->scno] & QUAL_TRACE)) {		tcp->flags |= TCB_INSYSCALL;		return 0;	}	if (cflag) {		gettimeofday(&tcp->etime, NULL);		tcp->flags |= TCB_INSYSCALL;		return 0;	}	printleader(tcp);	tcp->flags &= ~TCB_REPRINT;	tcp_last = tcp;	if (tcp->scno >= nsyscalls || tcp->scno < 0)		tprintf("syscall_%lu(", tcp->scno);	else		tprintf("%s(", sysent[tcp->scno].sys_name);	if (tcp->scno >= nsyscalls || tcp->scno < 0 || 	    ((qual_flags[tcp->scno] & QUAL_RAW) && tcp->scno != SYS_exit))		sys_res = printargs(tcp);	else		sys_res = (*sysent[tcp->scno].sys_func)(tcp);	if (fflush(tcp->outf) == EOF)		return -1;	tcp->flags |= TCB_INSYSCALL;	/* Measure the entrance time as late as possible to avoid errors. */	if (dtime)		gettimeofday(&tcp->etime, NULL);	return sys_res;}intprintargs(tcp)struct tcb *tcp;{	if (entering(tcp)) {		int i;		for (i = 0; i < tcp->u_nargs; i++)			tprintf("%s%#lx", i ? ", " : "", tcp->u_arg[i]);	}	return 0;}longgetrval2(tcp)struct tcb *tcp;{	long val = -1;#ifdef LINUX#ifdef SPARC	struct regs regs;	if (ptrace(PTRACE_GETREGS,tcp->pid,(char *)&regs,0) < 0)		return -1;	val = regs.r_o1;#endif /* SPARC */#endif /* LINUX */#ifdef SUNOS4	if (upeek(tcp->pid, uoff(u_rval2), &val) < 0)		return -1;#endif /* SUNOS4 */#ifdef SVR4#ifdef SPARC	val = tcp->status.PR_REG[R_O1];#endif /* SPARC */#ifdef I386	val = tcp->status.PR_REG[EDX];#endif /* I386 */#ifdef MIPS	val = tcp->status.PR_REG[CTX_V1];#endif /* MIPS */#endif /* SVR4 */#ifdef FREEBSD	struct reg regs;	pread(tcp->pfd_reg, &regs, sizeof(regs), 0);	val = regs.r_edx;#endif		return val;}/* * Apparently, indirect system calls have already be converted by ptrace(2), * so if you see "indir" this program has gone astray. */intsys_indir(tcp)struct tcb *tcp;{	int i, scno, nargs;	if (entering(tcp)) {		if ((scno = tcp->u_arg[0]) > nsyscalls) {			fprintf(stderr, "Bogus syscall: %u\n", scno);			return 0;		}		nargs = sysent[scno].nargs;		tprintf("%s", sysent[scno].sys_name);		for (i = 0; i < nargs; i++)			tprintf(", %#lx", tcp->u_arg[i+1]);	}	return 0;}static inttime_cmp(a, b)void *a;void *b;{	return -tv_cmp(&tv_count[*((int *) a)], &tv_count[*((int *) b)]);}static intsyscall_cmp(a, b)void *a;void *b;{	return strcmp(sysent[*((int *) a)].sys_name,		sysent[*((int *) b)].sys_name);}static intcount_cmp(a, b)void *a;void *b;{	int m = call_count[*((int *) a)], n = call_count[*((int *) b)];	return (m < n) ? 1 : (m > n) ? -1 : 0;}static int (*sortfun)();static struct timeval overhead = { -1, -1 };voidset_sortby(sortby)char *sortby;{	if (strcmp(sortby, "time") == 0)		sortfun = time_cmp;	else if (strcmp(sortby, "calls") == 0)		sortfun = count_cmp;	else if (strcmp(sortby, "name") == 0)		sortfun = syscall_cmp;	else if (strcmp(sortby, "nothing") == 0)		sortfun = NULL;	else {		fprintf(stderr, "invalid sortby: `%s'\n", sortby);		exit(1);	}}void set_overhead(n)int n;{	overhead.tv_sec = n / 1000000;	overhead.tv_usec = n % 1000000;}voidcall_summary(outf)FILE *outf;{	int i, j;	int call_cum, error_cum;	struct timeval tv_cum, dtv;	double percent;	char *dashes = "-------------------------";	char error_str[16];	call_cum = error_cum = tv_cum.tv_sec = tv_cum.tv_usec = 0;	if (overhead.tv_sec == -1) {		tv_mul(&overhead, &shortest, 8);		tv_div(&overhead, &overhead, 10);	}	for (i = 0; i < nsyscalls; i++) {		sorted_count[i] = i;		if (call_count[i] == 0)			continue;		tv_mul(&dtv, &overhead, call_count[i]);		tv_sub(&tv_count[i], &tv_count[i], &dtv);		call_cum += call_count[i];		error_cum += error_count[i];		tv_add(&tv_cum, &tv_cum, &tv_count[i]);	}	if (sortfun)		qsort((void *) sorted_count, nsyscalls, sizeof(int), sortfun);	fprintf(outf, "%6.6s %11.11s %11.11s %9.9s %9.9s %s\n",		"% time", "seconds", "usecs/call",		"calls", "errors", "syscall");	fprintf(outf, "%6.6s %11.11s %11.11s %9.9s %9.9s %-16.16s\n",		dashes, dashes, dashes, dashes, dashes, dashes);	for (i = 0; i < nsyscalls; i++) {		j = sorted_count[i];		if (call_count[j] == 0)			continue;		tv_div(&dtv, &tv_count[j], call_count[j]);		if (error_count[j])			sprintf(error_str, "%d", error_count[j]);		else			error_str[0] = '\0';		percent = 100.0*tv_float(&tv_count[j])/tv_float(&tv_cum);		fprintf(outf, "%6.2f %4ld.%06ld %11ld %9d %9.9s %s\n",			percent, (long) tv_count[j].tv_sec,			(long) tv_count[j].tv_usec,			(long) 1000000 * dtv.tv_sec + dtv.tv_usec,			call_count[j], error_str, sysent[j].sys_name);	}	fprintf(outf, "%6.6s %11.11s %11.11s %9.9s %9.9s %-16.16s\n",		dashes, dashes, dashes, dashes, dashes, dashes);	if (error_cum)		sprintf(error_str, "%d", error_cum);	else		error_str[0] = '\0';	fprintf(outf, "%6.6s %4ld.%06ld %11.11s %9d %9.9s %s\n",		"100.00", (long) tv_cum.tv_sec, (long) tv_cum.tv_usec, "",		call_cum, error_str, "total");}

⌨️ 快捷键说明

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