Tracing BSD System Calls by Sean Eric Fagan Example 1: garth% truss echo "Hello, World" returns 0x0 (0) SYSCALL fstat 0x1 0xefbfd7ec returns 0x0 (0) SYSCALL readlink 0x6cac 0xefbfd7d8 0x3f errno 2 'No such file or directory' SYSCALL __syscall 0xc5 0x0 0x0 0x1000 0x3 0x1002 0xffffffff 0x0 returns 0x8009000 (134254592) SYSCALL break 0xc000 returns 0x0 (0) SYSCALL break 0xe000 returns 0x0 (0) SYSCALL write 0x1 0xc000 0xd Hello, World returns 0xd (13) SYSCALL exit 0x0 process exit, rval = 0 Listing One /* stopevent() * Stop a process because of a procfs event; stay stopped until p->p_step is * cleared (cleared by PIOCCONT in procfs). */ void stopevent(struct proc *p, unsigned int event, unsigned int val) { p->p_step = 1; do { p->p_xstat = val; p->p_stype = event; /* Which event caused the stop? */ wakeup(&p->p_stype); /* Wake up any PIOCWAIT'ing procs */ tsleep(&p->p_step, PWAIT, "stopevent", 0); } while (p->p_step); } Listing Two /* New file sys/pioctl.h */ #include #if 0 struct procfs_status { int state; /* 0 for running, 1 for stopped */ int why; /* what event, if any, proc stopped on */ unsigned int val; /* Any extra data */ }; #else struct procfs_status { int state; /* Running, stopped, something else? */ int flags; /* Any flags */ unsigned long events; /* Events to stop on */ int why; /* What event, if any, proc stopped on */ unsigned long val; /* Any extra data */ }; #endif #define PIOCBIS _IOW('p', 1, unsigned int) /* Set event flag */ #define PIOCBIC _IOW('p', 2, unsigned int) /* Clear event flag */ #define PIOCSFL _IOR('p', 3, unsigned int) /* Set flags */ /* wait for proc to stop */ #define PIOCWAIT _IOR('p', 4, struct procfs_status) #define PIOCCONT _IOW('p', 5, int) /* Continue a process */ /* Get proc status */ #define PIOCSTATUS _IOW('p', 6, struct procfs_status) #define S_EXEC 0x00000001 /* stop-on-exec */ #define S_SIG 0x00000002 /* stop-on-signal */ #define S_SCE 0x00000004 /* stop on syscall entry */ #define S_SCX 0x00000008 /* stop on syscall exit */ #define S_CORE 0x00000010 /* stop on coredump */ #define S_EXIT 0x00000020 /* stop on exit */ Listing Three /* Part of procfs_vnops.c */ procfs_ioctl(ap) struct vop_ioctl_args *ap; { struct pfsnode *pfs = VTOPFS(ap->a_vp); struct proc *procp; int error; int signo; struct procfs_status *psp; procp = pfind(pfs->pfs_pid); if (procp == NULL) { return ENOTTY; } switch (ap->a_command) { case PIOCBIS: procp->p_stops |= *(unsigned int*)ap->a_data; break; case PIOCBIC: procp->p_stops &= ~*(unsigned int*)ap->a_data; break; case PIOCSFL: procp->p_pfsflags = (unsigned char)*(unsigned int*)ap->a_data; *(unsigned int*)ap->a_data = procp->p_stops; break; case PIOCSTATUS: psp = (struct procfs_status *)ap->a_data; psp->state = (procp->p_step == 0); psp->flags = procp->p_pfsflags; psp->events = procp->p_stops; if (procp->p_step) { psp->why = procp->p_stype; psp->val = procp->p_xstat; } else { psp->why = psp->val = 0; /* Not defined values */ } break; case PIOCWAIT: psp = (struct procfs_status *)ap->a_data; if (procp->p_step == 0) { error = tsleep(&procp->p_stype, PWAIT | PCATCH, "piocwait", 0); if (error) return error; } psp->state = 1; /* It stopped */ psp->flags = procp->p_pfsflags; psp->events = procp->p_stops; psp->why = procp->p_stype; /* why it stopped */ psp->val = procp->p_xstat; /* any extra info */ break; case PIOCCONT: /* Restart a proc */ if (procp->p_step == 0) return EINVAL; /* Can only start a stopped process */ if (ap->a_data && (signo = *(int*)ap->a_data)) { if (signo >= NSIG || signo <= 0) return EINVAL; if (error = psignal(procp, signo)) return error; } procp->p_step = 0; wakeup(&procp->p_step); break; default: return (ENOTTY); } return 0; } 4