📄 syscall.c
字号:
#elif defined (M68K) static int d0;#elif defined (ARM) static int r0;#elif defined (ALPHA) static long r0; static long a3;#elif defined (SPARC) static struct regs regs; static unsigned long trap;#elif defined(MIPS) static long a3; static long r2;#elif defined(S390) static long gpr2; static long pc;#elif defined(HPPA) static long r28;#endif #endif /* LINUX */#ifdef FREEBSD struct reg regs;#endif /* FREEBSD */ intget_scno(tcp)struct tcb *tcp;{ long scno = 0;#ifndef USE_PROCFS int pid = tcp->pid;#endif /* !PROCFS */ #ifdef LINUX#if defined(S390) if (upeek(tcp->pid,PT_PSWADDR,&pc) < 0) return -1; scno = ptrace(PTRACE_PEEKTEXT, tcp->pid, (char *)(pc-4),0); if (errno) return -1; scno&=0xFF;#elif defined (POWERPC) if (upeek(pid, 4*PT_R0, &scno) < 0) return -1; if (!(tcp->flags & TCB_INSYSCALL)) { /* Check if we return from execve. */ if (scno == 0 && (tcp->flags & TCB_WAITEXECVE)) { tcp->flags &= ~TCB_WAITEXECVE; return 0; } }#elif defined (I386) if (upeek(pid, 4*ORIG_EAX, &scno) < 0) return -1;#elif defined(IA64)#define IA64_PSR_IS ((long)1 << 34) if (upeek (pid, PT_CR_IPSR, &psr) >= 0) ia32 = (psr & IA64_PSR_IS); if (!(tcp->flags & TCB_INSYSCALL)) { if (ia32) { if (upeek(pid, PT_R8, &scno) < 0) return -1; } else { if (upeek (pid, PT_R15, &scno) < 0) return -1; } } else { /* syscall in progress */ if (upeek (pid, PT_R8, &r8) < 0) return -1; if (upeek (pid, PT_R10, &r10) < 0) return -1; }#elif defined (ARM) { long pc; upeek(pid, 4*15, &pc); umoven(tcp, pc-4, 4, (char *)&scno); scno &= 0x000fffff; }#elif defined (M68K) if (upeek(pid, 4*PT_ORIG_D0, &scno) < 0) return -1;#elif defined (MIPS) if (upeek(pid, REG_A3, &a3) < 0) return -1; if(!(tcp->flags & TCB_INSYSCALL)) { if (upeek(pid, REG_V0, &scno) < 0) return -1; if (scno < 0 || scno > nsyscalls) { if(a3 == 0 || a3 == -1) { if(debug) fprintf (stderr, "stray syscall exit: v0 = %ld\n", scno); return 0; } } } else { if (upeek(pid, REG_V0, &r2) < 0) return -1; }#elif defined (ALPHA) if (upeek(pid, REG_A3, &a3) < 0) return -1; if (!(tcp->flags & TCB_INSYSCALL)) { if (upeek(pid, REG_R0, &scno) < 0) return -1; /* Check if we return from execve. */ if (scno == 0 && tcp->flags & TCB_WAITEXECVE) { tcp->flags &= ~TCB_WAITEXECVE; return 0; } /* * Do some sanity checks to figure out if it's * really a syscall entry */ if (scno < 0 || scno > nsyscalls) { if (a3 == 0 || a3 == -1) { if (debug) fprintf (stderr, "stray syscall exit: r0 = %ld\n", scno); return 0; } } } else { if (upeek(pid, REG_R0, &r0) < 0) return -1; }#elif defined (SPARC) /* Everything we need is in the current register set. */ if (ptrace(PTRACE_GETREGS,pid,(char *)®s,0) < 0) return -1; /* If we are entering, then disassemble the syscall trap. */ if (!(tcp->flags & TCB_INSYSCALL)) { /* Retrieve the syscall trap instruction. */ errno = 0; trap = ptrace(PTRACE_PEEKTEXT,pid,(char *)regs.r_pc,0); if (errno) return -1; /* Disassemble the trap to see what personality to use. */ switch (trap) { case 0x91d02010: /* Linux/SPARC syscall trap. */ set_personality(0); break; case 0x91d0206d: /* Linux/SPARC64 syscall trap. */ fprintf(stderr,"syscall: Linux/SPARC64 not supported yet\n"); return -1; case 0x91d02000: /* SunOS syscall trap. (pers 1) */ fprintf(stderr,"syscall: SunOS no support\n"); return -1; case 0x91d02008: /* Solaris 2.x syscall trap. (per 2) */ set_personality(1); break; case 0x91d02009: /* NetBSD/FreeBSD syscall trap. */ fprintf(stderr,"syscall: NetBSD/FreeBSD not supported\n"); return -1; case 0x91d02027: /* Solaris 2.x gettimeofday */ set_personality(1); break; default: /* Unknown syscall trap. */ if(tcp->flags & TCB_WAITEXECVE) { tcp->flags &= ~TCB_WAITEXECVE; return 0; } fprintf(stderr,"syscall: unknown syscall trap %08x %08x\n", trap, regs.r_pc); return -1; } /* Extract the system call number from the registers. */ if (trap == 0x91d02027) scno = 156; else scno = regs.r_g1; if (scno == 0) { scno = regs.r_o0; memmove (®s.r_o0, ®s.r_o1, 7*sizeof(regs.r_o0)); } }#elif defined(HPPA) if (upeek(pid, PT_GR20, &scno) < 0) return -1; if (!(tcp->flags & TCB_INSYSCALL)) { /* Check if we return from execve. */ if ((tcp->flags & TCB_WAITEXECVE)) { tcp->flags &= ~TCB_WAITEXECVE; return 0; } }#endif #endif /* LINUX */#ifdef SUNOS4 if (upeek(pid, uoff(u_arg[7]), &scno) < 0) return -1;#endif#ifdef USE_PROCFS#ifdef HAVE_PR_SYSCALL scno = tcp->status.PR_SYSCALL;#else /* !HAVE_PR_SYSCALL */#ifndef FREEBSD scno = tcp->status.PR_WHAT;#else /* FREEBSD */ if (pread(tcp->pfd_reg, ®s, sizeof(regs), 0) < 0) { perror("pread"); return -1; } switch (regs.r_eax) { case SYS_syscall: case SYS___syscall: pread(tcp->pfd, &scno, sizeof(scno), regs.r_esp + sizeof(int)); break; default: scno = regs.r_eax; break; }#endif /* FREEBSD */#endif /* !HAVE_PR_SYSCALL */#endif /* USE_PROCFS */ if (!(tcp->flags & TCB_INSYSCALL)) tcp->scno = scno; return 1;}intsyscall_fixup(tcp)struct tcb *tcp;{#ifndef USE_PROCFS int pid = tcp->pid;#else /* USE_PROCFS */ int scno = tcp->scno; if (!(tcp->flags & TCB_INSYSCALL)) { if (tcp->status.PR_WHY != PR_SYSENTRY) { if ( scno == SYS_fork#ifdef SYS_vfork || scno == SYS_vfork#endif /* SYS_vfork */ ) { /* We are returning in the child, fake it. */ tcp->status.PR_WHY = PR_SYSENTRY; trace_syscall(tcp); tcp->status.PR_WHY = PR_SYSEXIT; } else { fprintf(stderr, "syscall: missing entry\n"); tcp->flags |= TCB_INSYSCALL; } } } else { if (tcp->status.PR_WHY != PR_SYSEXIT) { fprintf(stderr, "syscall: missing exit\n"); tcp->flags &= ~TCB_INSYSCALL; } }#endif /* USE_PROCFS */#ifdef SUNOS4 if (!(tcp->flags & TCB_INSYSCALL)) { if (scno == 0) { fprintf(stderr, "syscall: missing entry\n"); tcp->flags |= TCB_INSYSCALL; } } else { if (scno != 0) { if (debug) { /* * This happens when a signal handler * for a signal which interrupted a * a system call makes another system call. */ fprintf(stderr, "syscall: missing exit\n"); } tcp->flags &= ~TCB_INSYSCALL; } }#endif /* SUNOS4 */#ifdef LINUX#if defined (I386) if (upeek(pid, 4*EAX, &eax) < 0) return -1; if (eax != -ENOSYS && !(tcp->flags & TCB_INSYSCALL)) { if (debug) fprintf(stderr, "stray syscall exit: eax = %ld\n", eax); return 0; }#elif defined (S390) if (upeek(pid, PT_GPR2, &gpr2) < 0) return -1; if (gpr2 != -ENOSYS && !(tcp->flags & TCB_INSYSCALL)) { if (debug) fprintf(stderr, "stray syscall exit: gpr2 = %ld\n", gpr2); return 0; }#elif defined (POWERPC)# define SO_MASK 0x10000000 if (upeek(pid, 4*PT_CCR, &flags) < 0) return -1; if (upeek(pid, 4*PT_R3, &result) < 0) return -1; if (flags & SO_MASK) result = -result;#elif defined (M68K) if (upeek(pid, 4*PT_D0, &d0) < 0) return -1; if (d0 != -ENOSYS && !(tcp->flags & TCB_INSYSCALL)) { if (debug) fprintf(stderr, "stray syscall exit: d0 = %ld\n", d0); return 0; }#elif defined (ARM) if (upeek(pid, 4*0, (long *)&r0) < 0) return -1; if ( 0 && r0 != -ENOSYS && !(tcp->flags & TCB_INSYSCALL)) { if (debug) fprintf(stderr, "stray syscall exit: d0 = %ld\n", r0); return 0; }#elif defined (HPPA) if (upeek(pid, PT_GR28, &r28) < 0) return -1;#endif#endif /* LINUX */ return 1;}intget_error(tcp)struct tcb *tcp;{ int u_error = 0;#ifdef LINUX#ifdef S390 if (gpr2 && (unsigned) -gpr2 < nerrnos) { tcp->u_rval = -1; u_error = -gpr2; } else { tcp->u_rval = gpr2; u_error = 0; }#else /* !S390 */#ifdef I386 if (eax < 0 && -eax < nerrnos) { tcp->u_rval = -1; u_error = -eax; } else { tcp->u_rval = eax; u_error = 0; }#else /* !I386 */#ifdef IA64 if (ia32) { int err; err = (int)r8; if (err < 0 && -err < nerrnos) { tcp->u_rval = -1; u_error = -err; } else { tcp->u_rval = err; u_error = 0; } } else { if (r10) { tcp->u_rval = -1; u_error = r8; } else { tcp->u_rval = r8; u_error = 0; } }#else /* !IA64 */#ifdef MIPS if (a3) { tcp->u_rval = -1; u_error = r2; } else { tcp->u_rval = r2; u_error = 0; }#else#ifdef POWERPC if (result && (unsigned) -result < nerrnos) { tcp->u_rval = -1; u_error = -result; } else { tcp->u_rval = result; u_error = 0; }#else /* !POWERPC */#ifdef M68K if (d0 && (unsigned) -d0 < nerrnos) { tcp->u_rval = -1; u_error = -d0; } else { tcp->u_rval = d0; u_error = 0; }#else /* !M68K */#ifdef ARM if (r0 && (unsigned) -r0 < nerrnos) { tcp->u_rval = -1; u_error = -r0; } else { tcp->u_rval = r0; u_error = 0; }#else /* !ARM */#ifdef ALPHA if (a3) { tcp->u_rval = -1; u_error = r0; } else { tcp->u_rval = r0; u_error = 0; }#else /* !ALPHA */#ifdef SPARC if (regs.r_psr & PSR_C) { tcp->u_rval = -1; u_error = regs.r_o0; } else { tcp->u_rval = regs.r_o0; u_error = 0; }#else /* !SPARC */#ifdef HPPA if (r28 && (unsigned) -r28 < nerrnos) { tcp->u_rval = -1; u_error = -r28; } else { tcp->u_rval = r28; u_error = 0; }#endif /* HPPA */#endif /* SPARC */#endif /* ALPHA */#endif /* ARM */#endif /* M68K */#endif /* POWERPC */#endif /* MIPS */#endif /* IA64 */#endif /* I386 */#endif /* S390 */#endif /* LINUX */#ifdef SUNOS4 /* get error code from user struct */ if (upeek(pid, uoff(u_error), &u_error) < 0) return -1; u_error >>= 24; /* u_error is a char */ /* get system call return value */ if (upeek(pid, uoff(u_rval1), &tcp->u_rval) < 0) return -1;#endif /* SUNOS4 */#ifdef SVR4#ifdef SPARC /* Judicious guessing goes a long way. */ if (tcp->status.pr_reg[R_PSR] & 0x100000) { tcp->u_rval = -1; u_error = tcp->status.pr_reg[R_O0]; } else { tcp->u_rval = tcp->status.pr_reg[R_O0]; u_error = 0; }#endif /* SPARC */#ifdef I386 /* Wanna know how to kill an hour single-stepping? */ if (tcp->status.PR_REG[EFL] & 0x1) { tcp->u_rval = -1; u_error = tcp->status.PR_REG[EAX]; } else { tcp->u_rval = tcp->status.PR_REG[EAX];#ifdef HAVE_LONG_LONG tcp->u_lrval = ((unsigned long long) tcp->status.PR_REG[EDX] << 32) + tcp->status.PR_REG[EAX];#endif u_error = 0; }#endif /* I386 */#ifdef MIPS if (tcp->status.pr_reg[CTX_A3]) { tcp->u_rval = -1; u_error = tcp->status.pr_reg[CTX_V0]; } else { tcp->u_rval = tcp->status.pr_reg[CTX_V0]; u_error = 0; }#endif /* MIPS */#endif /* SVR4 */#ifdef FREEBSD if (regs.r_eflags & PSL_C) { tcp->u_rval = -1; u_error = regs.r_eax; } else { tcp->u_rval = regs.r_eax; tcp->u_lrval = ((unsigned long long) regs.r_edx << 32) + regs.r_eax; u_error = 0; }#endif /* FREEBSD */ tcp->u_error = u_error; return 1;}int syscall_enter(tcp)struct tcb *tcp;{#ifndef USE_PROCFS int pid = tcp->pid;#endif /* !USE_PROCFS */ #ifdef LINUX#if defined(S390) { 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==0 ? PT_ORIGGPR2:PT_GPR2+(i<<2), &tcp->u_arg[i]) < 0) return -1; } }#elif defined (ALPHA) { 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++) { /* WTA: if scno is out-of-bounds this will bomb. Add range-check * for scno somewhere above here! */ if (upeek(pid, REG_A0+i, &tcp->u_arg[i]) < 0) return -1; } }#elif defined (IA64) { unsigned long *bsp, cfm, i; if (upeek(pid, PT_AR_BSP, (long *) &bsp) < 0) return -1; if (upeek(pid, PT_CFM, (long *) &cfm) < 0) return -1; bsp = ia64_rse_skip_regs(bsp, -(cfm & 0x7f)); 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 (umoven(tcp, (unsigned long) ia64_rse_skip_regs(bsp, i), sizeof(long), (char *) &tcp->u_arg[i]) < 0) return -1; } }#elif defined (MIPS) { long sp; int i, nargs; if (tcp->scno >= 0 && tcp->scno < nsyscalls && sysent[tcp->scno].nargs != -1) nargs = tcp->u_nargs = sysent[tcp->scno].nargs; else nargs = tcp->u_nargs = MAX_ARGS; if(nargs > 4) { if(upeek(pid, REG_SP, &sp) < 0) return -1; for(i = 0; i < 4; i++) { if (upeek(pid, REG_A0 + i, &tcp->u_arg[i])<0) return -1; } umoven(tcp, sp+16, (nargs-4) * sizeof(tcp->u_arg[0]), (char *)(tcp->u_arg + 4)); } else { for(i = 0; i < nargs; i++) { if (upeek(pid, REG_A0 + i, &tcp->u_arg[i]) < 0) return -1; } } }#elif defined (POWERPC) { 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==0) ? (4*PT_ORIG_R3) : ((i+PT_R3)*4), &tcp->u_arg[i]) < 0) return -1; } }#elif defined (SPARC) { int i;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -