📄 syscall.c
字号:
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] = *((®s.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 *)®s,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, ®s, 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 + -