Changeset View
Changeset View
Standalone View
Standalone View
usr.bin/truss/syscalls.c
Show All 23 Lines | |||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | ||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | ||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | ||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | * 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 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | ||||
* SUCH DAMAGE. | * SUCH DAMAGE. | ||||
*/ | */ | ||||
#ifndef lint | #include <sys/cdefs.h> | ||||
static const char rcsid[] = | __FBSDID("$FreeBSD$"); | ||||
"$FreeBSD$"; | |||||
#endif /* not lint */ | |||||
/* | /* | ||||
* This file has routines used to print out system calls and their | * This file has routines used to print out system calls and their | ||||
* arguments. | * arguments. | ||||
*/ | */ | ||||
#include <sys/types.h> | #include <sys/types.h> | ||||
#include <sys/event.h> | |||||
#include <sys/ioccom.h> | |||||
#include <sys/mman.h> | #include <sys/mman.h> | ||||
#include <sys/procctl.h> | #include <sys/procctl.h> | ||||
#include <sys/ptrace.h> | #include <sys/ptrace.h> | ||||
#include <sys/resource.h> | |||||
#include <sys/socket.h> | #include <sys/socket.h> | ||||
#include <sys/time.h> | #include <sys/stat.h> | ||||
#include <sys/umtx.h> | |||||
#include <sys/un.h> | #include <sys/un.h> | ||||
#include <sys/wait.h> | #include <sys/wait.h> | ||||
#include <machine/sysarch.h> | |||||
#include <netinet/in.h> | #include <netinet/in.h> | ||||
#include <arpa/inet.h> | #include <arpa/inet.h> | ||||
#include <sys/ioccom.h> | |||||
#include <machine/atomic.h> | |||||
#include <errno.h> | |||||
#include <sys/umtx.h> | |||||
#include <sys/event.h> | |||||
#include <sys/stat.h> | |||||
#include <sys/resource.h> | |||||
#include <machine/sysarch.h> | |||||
#include <ctype.h> | #include <ctype.h> | ||||
#include <err.h> | #include <err.h> | ||||
#include <fcntl.h> | #include <fcntl.h> | ||||
#include <poll.h> | #include <poll.h> | ||||
#include <signal.h> | #include <signal.h> | ||||
#include <stdint.h> | #include <stdint.h> | ||||
#include <stdio.h> | #include <stdio.h> | ||||
▲ Show 20 Lines • Show All 52 Lines • ▼ Show 20 Lines | static struct syscall syscalls[] = { | ||||
{ .name = "readlinkat", .ret_type = 1, .nargs = 4, | { .name = "readlinkat", .ret_type = 1, .nargs = 4, | ||||
.args = { { Atfd, 0 }, { Name, 1 }, { Readlinkres | OUT, 2 }, | .args = { { Atfd, 0 }, { Name, 1 }, { Readlinkres | OUT, 2 }, | ||||
{ Int, 3 } } }, | { Int, 3 } } }, | ||||
{ .name = "lseek", .ret_type = 2, .nargs = 3, | { .name = "lseek", .ret_type = 2, .nargs = 3, | ||||
.args = { { Int, 0 }, { Quad, 1 + QUAD_ALIGN }, | .args = { { Int, 0 }, { Quad, 1 + QUAD_ALIGN }, | ||||
{ Whence, 1 + QUAD_SLOTS + QUAD_ALIGN } } }, | { Whence, 1 + QUAD_SLOTS + QUAD_ALIGN } } }, | ||||
{ .name = "linux_lseek", .ret_type = 2, .nargs = 3, | { .name = "linux_lseek", .ret_type = 2, .nargs = 3, | ||||
.args = { { Int, 0 }, { Int, 1 }, { Whence, 2 } } }, | .args = { { Int, 0 }, { Int, 1 }, { Whence, 2 } } }, | ||||
{ .name = "mmap", .ret_type = 2, .nargs = 6, | { .name = "mmap", .ret_type = 1, .nargs = 6, | ||||
.args = { { Ptr, 0 }, { Int, 1 }, { Mprot, 2 }, { Mmapflags, 3 }, | .args = { { Ptr, 0 }, { Int, 1 }, { Mprot, 2 }, { Mmapflags, 3 }, | ||||
{ Int, 4 }, { Quad, 5 + QUAD_ALIGN } } }, | { Int, 4 }, { Quad, 5 + QUAD_ALIGN } } }, | ||||
{ .name = "linux_mkdir", .ret_type = 1, .nargs = 2, | { .name = "linux_mkdir", .ret_type = 1, .nargs = 2, | ||||
.args = { { Name | IN, 0 }, { Int, 1 } } }, | .args = { { Name | IN, 0 }, { Int, 1 } } }, | ||||
{ .name = "mprotect", .ret_type = 1, .nargs = 3, | { .name = "mprotect", .ret_type = 1, .nargs = 3, | ||||
.args = { { Ptr, 0 }, { Int, 1 }, { Mprot, 2 } } }, | .args = { { Ptr, 0 }, { Int, 1 }, { Mprot, 2 } } }, | ||||
{ .name = "open", .ret_type = 1, .nargs = 3, | { .name = "open", .ret_type = 1, .nargs = 3, | ||||
.args = { { Name | IN, 0 }, { Open, 1 }, { Octal, 2 } } }, | .args = { { Name | IN, 0 }, { Open, 1 }, { Octal, 2 } } }, | ||||
{ .name = "openat", .ret_type = 1, .nargs = 4, | { .name = "openat", .ret_type = 1, .nargs = 4, | ||||
.args = { { Atfd, 0 }, { Name | IN, 1 }, { Open, 2 }, | .args = { { Atfd, 0 }, { Name | IN, 1 }, { Open, 2 }, | ||||
{ Octal, 3 } } }, | { Octal, 3 } } }, | ||||
{ .name = "mkdir", .ret_type = 1, .nargs = 2, | { .name = "mkdir", .ret_type = 1, .nargs = 2, | ||||
.args = { { Name, 0 }, { Octal, 1 } } }, | .args = { { Name, 0 }, { Octal, 1 } } }, | ||||
{ .name = "mkdirat", .ret_type = 1, .nargs = 3, | { .name = "mkdirat", .ret_type = 1, .nargs = 3, | ||||
.args = { { Atfd, 0 }, { Name, 1 }, { Octal, 2 } } }, | .args = { { Atfd, 0 }, { Name, 1 }, { Octal, 2 } } }, | ||||
{ .name = "linux_open", .ret_type = 1, .nargs = 3, | { .name = "linux_open", .ret_type = 1, .nargs = 3, | ||||
.args = { { Name, 0 }, { Hex, 1 }, { Octal, 2 } } }, | .args = { { Name, 0 }, { Hex, 1 }, { Octal, 2 } } }, | ||||
{ .name = "close", .ret_type = 1, .nargs = 1, | { .name = "close", .ret_type = 1, .nargs = 1, | ||||
.args = { { Int, 0 } } }, | .args = { { Int, 0 } } }, | ||||
{ .name = "link", .ret_type = 0, .nargs = 2, | { .name = "link", .ret_type = 1, .nargs = 2, | ||||
.args = { { Name, 0 }, { Name, 1 } } }, | .args = { { Name, 0 }, { Name, 1 } } }, | ||||
{ .name = "linkat", .ret_type = 0, .nargs = 5, | { .name = "linkat", .ret_type = 1, .nargs = 5, | ||||
.args = { { Atfd, 0 }, { Name, 1 }, { Atfd, 2 }, { Name, 3 }, | .args = { { Atfd, 0 }, { Name, 1 }, { Atfd, 2 }, { Name, 3 }, | ||||
{ Atflags, 4 } } }, | { Atflags, 4 } } }, | ||||
{ .name = "unlink", .ret_type = 0, .nargs = 1, | { .name = "unlink", .ret_type = 1, .nargs = 1, | ||||
.args = { { Name, 0 } } }, | .args = { { Name, 0 } } }, | ||||
{ .name = "unlinkat", .ret_type = 0, .nargs = 3, | { .name = "unlinkat", .ret_type = 1, .nargs = 3, | ||||
.args = { { Atfd, 0 }, { Name, 1 }, { Atflags, 2 } } }, | .args = { { Atfd, 0 }, { Name, 1 }, { Atflags, 2 } } }, | ||||
{ .name = "chdir", .ret_type = 0, .nargs = 1, | { .name = "chdir", .ret_type = 1, .nargs = 1, | ||||
.args = { { Name, 0 } } }, | .args = { { Name, 0 } } }, | ||||
{ .name = "chroot", .ret_type = 0, .nargs = 1, | { .name = "chroot", .ret_type = 1, .nargs = 1, | ||||
.args = { { Name, 0 } } }, | .args = { { Name, 0 } } }, | ||||
{ .name = "mkfifo", .ret_type = 0, .nargs = 2, | { .name = "mkfifo", .ret_type = 1, .nargs = 2, | ||||
.args = { { Name, 0 }, { Octal, 1 } } }, | .args = { { Name, 0 }, { Octal, 1 } } }, | ||||
{ .name = "mkfifoat", .ret_type = 0, .nargs = 3, | { .name = "mkfifoat", .ret_type = 1, .nargs = 3, | ||||
.args = { { Atfd, 0 }, { Name, 1 }, { Octal, 2 } } }, | .args = { { Atfd, 0 }, { Name, 1 }, { Octal, 2 } } }, | ||||
{ .name = "mknod", .ret_type = 0, .nargs = 3, | { .name = "mknod", .ret_type = 1, .nargs = 3, | ||||
.args = { { Name, 0 }, { Octal, 1 }, { Int, 2 } } }, | .args = { { Name, 0 }, { Octal, 1 }, { Int, 2 } } }, | ||||
{ .name = "mknodat", .ret_type = 0, .nargs = 4, | { .name = "mknodat", .ret_type = 1, .nargs = 4, | ||||
.args = { { Atfd, 0 }, { Name, 1 }, { Octal, 2 }, { Int, 3 } } }, | .args = { { Atfd, 0 }, { Name, 1 }, { Octal, 2 }, { Int, 3 } } }, | ||||
{ .name = "chmod", .ret_type = 0, .nargs = 2, | { .name = "chmod", .ret_type = 1, .nargs = 2, | ||||
.args = { { Name, 0 }, { Octal, 1 } } }, | .args = { { Name, 0 }, { Octal, 1 } } }, | ||||
{ .name = "fchmod", .ret_type = 0, .nargs = 2, | { .name = "fchmod", .ret_type = 1, .nargs = 2, | ||||
.args = { { Int, 0 }, { Octal, 1 } } }, | .args = { { Int, 0 }, { Octal, 1 } } }, | ||||
{ .name = "lchmod", .ret_type = 0, .nargs = 2, | { .name = "lchmod", .ret_type = 1, .nargs = 2, | ||||
.args = { { Name, 0 }, { Octal, 1 } } }, | .args = { { Name, 0 }, { Octal, 1 } } }, | ||||
{ .name = "fchmodat", .ret_type = 0, .nargs = 4, | { .name = "fchmodat", .ret_type = 1, .nargs = 4, | ||||
.args = { { Atfd, 0 }, { Name, 1 }, { Octal, 2 }, { Atflags, 3 } } }, | .args = { { Atfd, 0 }, { Name, 1 }, { Octal, 2 }, { Atflags, 3 } } }, | ||||
{ .name = "chown", .ret_type = 0, .nargs = 3, | { .name = "chown", .ret_type = 1, .nargs = 3, | ||||
.args = { { Name, 0 }, { Int, 1 }, { Int, 2 } } }, | .args = { { Name, 0 }, { Int, 1 }, { Int, 2 } } }, | ||||
{ .name = "fchown", .ret_type = 0, .nargs = 3, | { .name = "fchown", .ret_type = 1, .nargs = 3, | ||||
.args = { { Int, 0 }, { Int, 1 }, { Int, 2 } } }, | .args = { { Int, 0 }, { Int, 1 }, { Int, 2 } } }, | ||||
{ .name = "lchown", .ret_type = 0, .nargs = 3, | { .name = "lchown", .ret_type = 1, .nargs = 3, | ||||
.args = { { Name, 0 }, { Int, 1 }, { Int, 2 } } }, | .args = { { Name, 0 }, { Int, 1 }, { Int, 2 } } }, | ||||
{ .name = "fchownat", .ret_type = 0, .nargs = 5, | { .name = "fchownat", .ret_type = 1, .nargs = 5, | ||||
.args = { { Atfd, 0 }, { Name, 1 }, { Int, 2 }, { Int, 3 }, | .args = { { Atfd, 0 }, { Name, 1 }, { Int, 2 }, { Int, 3 }, | ||||
{ Atflags, 4 } } }, | { Atflags, 4 } } }, | ||||
{ .name = "linux_stat64", .ret_type = 1, .nargs = 3, | { .name = "linux_stat64", .ret_type = 1, .nargs = 3, | ||||
.args = { { Name | IN, 0 }, { Ptr | OUT, 1 }, { Ptr | IN, 1 } } }, | .args = { { Name | IN, 0 }, { Ptr | OUT, 1 }, { Ptr | IN, 1 } } }, | ||||
{ .name = "mount", .ret_type = 0, .nargs = 4, | { .name = "mount", .ret_type = 1, .nargs = 4, | ||||
.args = { { Name, 0 }, { Name, 1 }, { Int, 2 }, { Ptr, 3 } } }, | .args = { { Name, 0 }, { Name, 1 }, { Int, 2 }, { Ptr, 3 } } }, | ||||
{ .name = "umount", .ret_type = 0, .nargs = 2, | { .name = "umount", .ret_type = 1, .nargs = 2, | ||||
.args = { { Name, 0 }, { Int, 2 } } }, | .args = { { Name, 0 }, { Int, 2 } } }, | ||||
{ .name = "fstat", .ret_type = 1, .nargs = 2, | { .name = "fstat", .ret_type = 1, .nargs = 2, | ||||
.args = { { Int, 0 }, { Stat | OUT, 1 } } }, | .args = { { Int, 0 }, { Stat | OUT, 1 } } }, | ||||
{ .name = "fstatat", .ret_type = 1, .nargs = 4, | { .name = "fstatat", .ret_type = 1, .nargs = 4, | ||||
.args = { { Atfd, 0 }, { Name | IN, 1 }, { Stat | OUT, 2 }, | .args = { { Atfd, 0 }, { Name | IN, 1 }, { Stat | OUT, 2 }, | ||||
{ Atflags, 3 } } }, | { Atflags, 3 } } }, | ||||
{ .name = "stat", .ret_type = 1, .nargs = 2, | { .name = "stat", .ret_type = 1, .nargs = 2, | ||||
.args = { { Name | IN, 0 }, { Stat | OUT, 1 } } }, | .args = { { Name | IN, 0 }, { Stat | OUT, 1 } } }, | ||||
▲ Show 20 Lines • Show All 46 Lines • ▼ Show 20 Lines | static struct syscall syscalls[] = { | ||||
.args = { { Int, 0 }, { BinString | IN, 1 }, { Int, 2 }, { Hex, 3 }, | .args = { { Int, 0 }, { BinString | IN, 1 }, { Int, 2 }, { Hex, 3 }, | ||||
{ Sockaddr | IN, 4 }, { Ptr | IN, 5 } } }, | { Sockaddr | IN, 4 }, { Ptr | IN, 5 } } }, | ||||
{ .name = "execve", .ret_type = 1, .nargs = 3, | { .name = "execve", .ret_type = 1, .nargs = 3, | ||||
.args = { { Name | IN, 0 }, { ExecArgs | IN, 1 }, | .args = { { Name | IN, 0 }, { ExecArgs | IN, 1 }, | ||||
{ ExecEnv | IN, 2 } } }, | { ExecEnv | IN, 2 } } }, | ||||
{ .name = "linux_execve", .ret_type = 1, .nargs = 3, | { .name = "linux_execve", .ret_type = 1, .nargs = 3, | ||||
.args = { { Name | IN, 0 }, { ExecArgs | IN, 1 }, | .args = { { Name | IN, 0 }, { ExecArgs | IN, 1 }, | ||||
{ ExecEnv | IN, 2 } } }, | { ExecEnv | IN, 2 } } }, | ||||
{ .name = "kldload", .ret_type = 0, .nargs = 1, | { .name = "kldload", .ret_type = 1, .nargs = 1, | ||||
.args = { { Name | IN, 0 } } }, | .args = { { Name | IN, 0 } } }, | ||||
{ .name = "kldunload", .ret_type = 0, .nargs = 1, | { .name = "kldunload", .ret_type = 1, .nargs = 1, | ||||
.args = { { Int, 0 } } }, | .args = { { Int, 0 } } }, | ||||
{ .name = "kldfind", .ret_type = 0, .nargs = 1, | { .name = "kldfind", .ret_type = 1, .nargs = 1, | ||||
.args = { { Name | IN, 0 } } }, | .args = { { Name | IN, 0 } } }, | ||||
{ .name = "kldnext", .ret_type = 0, .nargs = 1, | { .name = "kldnext", .ret_type = 1, .nargs = 1, | ||||
.args = { { Int, 0 } } }, | .args = { { Int, 0 } } }, | ||||
{ .name = "kldstat", .ret_type = 0, .nargs = 2, | { .name = "kldstat", .ret_type = 1, .nargs = 2, | ||||
.args = { { Int, 0 }, { Ptr, 1 } } }, | .args = { { Int, 0 }, { Ptr, 1 } } }, | ||||
{ .name = "kldfirstmod", .ret_type = 0, .nargs = 1, | { .name = "kldfirstmod", .ret_type = 1, .nargs = 1, | ||||
.args = { { Int, 0 } } }, | .args = { { Int, 0 } } }, | ||||
{ .name = "nanosleep", .ret_type = 0, .nargs = 1, | { .name = "nanosleep", .ret_type = 1, .nargs = 1, | ||||
.args = { { Timespec, 0 } } }, | .args = { { Timespec, 0 } } }, | ||||
{ .name = "select", .ret_type = 1, .nargs = 5, | { .name = "select", .ret_type = 1, .nargs = 5, | ||||
.args = { { Int, 0 }, { Fd_set, 1 }, { Fd_set, 2 }, { Fd_set, 3 }, | .args = { { Int, 0 }, { Fd_set, 1 }, { Fd_set, 2 }, { Fd_set, 3 }, | ||||
{ Timeval, 4 } } }, | { Timeval, 4 } } }, | ||||
{ .name = "poll", .ret_type = 1, .nargs = 3, | { .name = "poll", .ret_type = 1, .nargs = 3, | ||||
.args = { { Pollfd, 0 }, { Int, 1 }, { Int, 2 } } }, | .args = { { Pollfd, 0 }, { Int, 1 }, { Int, 2 } } }, | ||||
{ .name = "gettimeofday", .ret_type = 1, .nargs = 2, | { .name = "gettimeofday", .ret_type = 1, .nargs = 2, | ||||
.args = { { Timeval | OUT, 0 }, { Ptr, 1 } } }, | .args = { { Timeval | OUT, 0 }, { Ptr, 1 } } }, | ||||
{ .name = "clock_gettime", .ret_type = 1, .nargs = 2, | { .name = "clock_gettime", .ret_type = 1, .nargs = 2, | ||||
.args = { { Int, 0 }, { Timespec | OUT, 1 } } }, | .args = { { Int, 0 }, { Timespec | OUT, 1 } } }, | ||||
{ .name = "getitimer", .ret_type = 1, .nargs = 2, | { .name = "getitimer", .ret_type = 1, .nargs = 2, | ||||
.args = { { Int, 0 }, { Itimerval | OUT, 2 } } }, | .args = { { Int, 0 }, { Itimerval | OUT, 2 } } }, | ||||
{ .name = "setitimer", .ret_type = 1, .nargs = 3, | { .name = "setitimer", .ret_type = 1, .nargs = 3, | ||||
.args = { { Int, 0 }, { Itimerval, 1 }, { Itimerval | OUT, 2 } } }, | .args = { { Int, 0 }, { Itimerval, 1 }, { Itimerval | OUT, 2 } } }, | ||||
{ .name = "kse_release", .ret_type = 0, .nargs = 1, | { .name = "kse_release", .ret_type = 0, .nargs = 1, | ||||
.args = { { Timespec, 0 } } }, | .args = { { Timespec, 0 } } }, | ||||
{ .name = "kevent", .ret_type = 0, .nargs = 6, | { .name = "kevent", .ret_type = 1, .nargs = 6, | ||||
.args = { { Int, 0 }, { Kevent, 1 }, { Int, 2 }, { Kevent | OUT, 3 }, | .args = { { Int, 0 }, { Kevent, 1 }, { Int, 2 }, { Kevent | OUT, 3 }, | ||||
{ Int, 4 }, { Timespec, 5 } } }, | { Int, 4 }, { Timespec, 5 } } }, | ||||
{ .name = "sigpending", .ret_type = 0, .nargs = 1, | { .name = "sigpending", .ret_type = 1, .nargs = 1, | ||||
.args = { { Sigset | OUT, 0 } } }, | .args = { { Sigset | OUT, 0 } } }, | ||||
{ .name = "sigprocmask", .ret_type = 0, .nargs = 3, | { .name = "sigprocmask", .ret_type = 1, .nargs = 3, | ||||
.args = { { Sigprocmask, 0 }, { Sigset, 1 }, { Sigset | OUT, 2 } } }, | .args = { { Sigprocmask, 0 }, { Sigset, 1 }, { Sigset | OUT, 2 } } }, | ||||
{ .name = "sigqueue", .ret_type = 0, .nargs = 3, | { .name = "sigqueue", .ret_type = 1, .nargs = 3, | ||||
.args = { { Int, 0 }, { Signal, 1 }, { LongHex, 2 } } }, | .args = { { Int, 0 }, { Signal, 1 }, { LongHex, 2 } } }, | ||||
{ .name = "sigreturn", .ret_type = 0, .nargs = 1, | { .name = "sigreturn", .ret_type = 1, .nargs = 1, | ||||
.args = { { Ptr, 0 } } }, | .args = { { Ptr, 0 } } }, | ||||
{ .name = "sigsuspend", .ret_type = 0, .nargs = 1, | { .name = "sigsuspend", .ret_type = 1, .nargs = 1, | ||||
.args = { { Sigset | IN, 0 } } }, | .args = { { Sigset | IN, 0 } } }, | ||||
{ .name = "sigtimedwait", .ret_type = 1, .nargs = 3, | { .name = "sigtimedwait", .ret_type = 1, .nargs = 3, | ||||
.args = { { Sigset | IN, 0 }, { Ptr, 1 }, { Timespec | IN, 2 } } }, | .args = { { Sigset | IN, 0 }, { Ptr, 1 }, { Timespec | IN, 2 } } }, | ||||
{ .name = "sigwait", .ret_type = 1, .nargs = 2, | { .name = "sigwait", .ret_type = 1, .nargs = 2, | ||||
.args = { { Sigset | IN, 0 }, { Ptr, 1 } } }, | .args = { { Sigset | IN, 0 }, { Ptr, 1 } } }, | ||||
{ .name = "sigwaitinfo", .ret_type = 1, .nargs = 2, | { .name = "sigwaitinfo", .ret_type = 1, .nargs = 2, | ||||
.args = { { Sigset | IN, 0 }, { Ptr, 1 } } }, | .args = { { Sigset | IN, 0 }, { Ptr, 1 } } }, | ||||
{ .name = "unmount", .ret_type = 1, .nargs = 2, | { .name = "unmount", .ret_type = 1, .nargs = 2, | ||||
Show All 25 Lines | .args = { { Atfd, 0 }, { Name | IN, 1 }, { Timespec2 | IN, 2 }, | ||||
{ Atflags, 3 } } }, | { Atflags, 3 } } }, | ||||
{ .name = "chflags", .ret_type = 1, .nargs = 2, | { .name = "chflags", .ret_type = 1, .nargs = 2, | ||||
.args = { { Name | IN, 0 }, { Hex, 1 } } }, | .args = { { Name | IN, 0 }, { Hex, 1 } } }, | ||||
{ .name = "lchflags", .ret_type = 1, .nargs = 2, | { .name = "lchflags", .ret_type = 1, .nargs = 2, | ||||
.args = { { Name | IN, 0 }, { Hex, 1 } } }, | .args = { { Name | IN, 0 }, { Hex, 1 } } }, | ||||
{ .name = "pathconf", .ret_type = 1, .nargs = 2, | { .name = "pathconf", .ret_type = 1, .nargs = 2, | ||||
.args = { { Name | IN, 0 }, { Pathconf, 1 } } }, | .args = { { Name | IN, 0 }, { Pathconf, 1 } } }, | ||||
{ .name = "pipe", .ret_type = 1, .nargs = 1, | { .name = "pipe", .ret_type = 1, .nargs = 1, | ||||
.args = { { Ptr, 0 } } }, | .args = { { PipeFds | OUT, 0 } } }, | ||||
{ .name = "pipe2", .ret_type = 1, .nargs = 2, | { .name = "pipe2", .ret_type = 1, .nargs = 2, | ||||
.args = { { Ptr, 0 }, { Open, 1 } } }, | .args = { { Ptr, 0 }, { Open, 1 } } }, | ||||
{ .name = "truncate", .ret_type = 1, .nargs = 3, | { .name = "truncate", .ret_type = 1, .nargs = 3, | ||||
.args = { { Name | IN, 0 }, { Int | IN, 1 }, { Quad | IN, 2 } } }, | .args = { { Name | IN, 0 }, { Int | IN, 1 }, { Quad | IN, 2 } } }, | ||||
{ .name = "ftruncate", .ret_type = 1, .nargs = 3, | { .name = "ftruncate", .ret_type = 1, .nargs = 3, | ||||
.args = { { Int | IN, 0 }, { Int | IN, 1 }, { Quad | IN, 2 } } }, | .args = { { Int | IN, 0 }, { Int | IN, 1 }, { Quad | IN, 2 } } }, | ||||
{ .name = "kill", .ret_type = 1, .nargs = 2, | { .name = "kill", .ret_type = 1, .nargs = 2, | ||||
.args = { { Int | IN, 0 }, { Signal | IN, 1 } } }, | .args = { { Int | IN, 0 }, { Signal | IN, 1 } } }, | ||||
Show All 19 Lines | .args = { { Idtype, 0 }, { Int, 1 }, { ExitStatus | OUT, 2 }, | ||||
{ Waitoptions, 3 }, { Rusage | OUT, 4 }, { Ptr, 5 } } }, | { Waitoptions, 3 }, { Rusage | OUT, 4 }, { Ptr, 5 } } }, | ||||
{ .name = "procctl", .ret_type = 1, .nargs = 4, | { .name = "procctl", .ret_type = 1, .nargs = 4, | ||||
.args = { { Idtype, 0 }, { Int, 1 }, { Procctl, 2 }, { Ptr, 3 } } }, | .args = { { Idtype, 0 }, { Int, 1 }, { Procctl, 2 }, { Ptr, 3 } } }, | ||||
{ .name = "sysarch", .ret_type = 1, .nargs = 2, | { .name = "sysarch", .ret_type = 1, .nargs = 2, | ||||
.args = { { Sysarch, 0 }, { Ptr, 1 } } }, | .args = { { Sysarch, 0 }, { Ptr, 1 } } }, | ||||
{ .name = "_umtx_op", .ret_type = 1, .nargs = 5, | { .name = "_umtx_op", .ret_type = 1, .nargs = 5, | ||||
.args = { { Ptr, 0 }, { Umtxop, 1 }, { LongHex, 2 }, { Ptr, 3 }, | .args = { { Ptr, 0 }, { Umtxop, 1 }, { LongHex, 2 }, { Ptr, 3 }, | ||||
{ Ptr, 4 } } }, | { Ptr, 4 } } }, | ||||
{ .name = "thr_kill", .ret_type = 0, .nargs = 2, | { .name = "thr_kill", .ret_type = 1, .nargs = 2, | ||||
.args = { { Long, 0 }, { Signal, 1 } } }, | .args = { { Long, 0 }, { Signal, 1 } } }, | ||||
{ .name = "thr_self", .ret_type = 0, .nargs = 1, | { .name = "thr_self", .ret_type = 1, .nargs = 1, | ||||
.args = { { Ptr, 0 } } }, | .args = { { Ptr, 0 } } }, | ||||
{ .name = 0 }, | { .name = 0 }, | ||||
}; | }; | ||||
/* Xlat idea taken from strace */ | /* Xlat idea taken from strace */ | ||||
struct xlat { | struct xlat { | ||||
int val; | int val; | ||||
const char *str; | const char *str; | ||||
▲ Show 20 Lines • Show All 147 Lines • ▼ Show 20 Lines | |||||
static struct xlat idtype_arg[] = { | static struct xlat idtype_arg[] = { | ||||
X(P_PID) X(P_PPID) X(P_PGID) X(P_SID) X(P_CID) X(P_UID) X(P_GID) | X(P_PID) X(P_PPID) X(P_PGID) X(P_SID) X(P_CID) X(P_UID) X(P_GID) | ||||
X(P_ALL) X(P_LWPID) X(P_TASKID) X(P_PROJID) X(P_POOLID) X(P_JAILID) | X(P_ALL) X(P_LWPID) X(P_TASKID) X(P_PROJID) X(P_POOLID) X(P_JAILID) | ||||
X(P_CTID) X(P_CPUID) X(P_PSETID) XEND | X(P_CTID) X(P_CPUID) X(P_PSETID) XEND | ||||
}; | }; | ||||
static struct xlat procctl_arg[] = { | static struct xlat procctl_arg[] = { | ||||
X(PROC_SPROTECT) XEND | X(PROC_SPROTECT) X(PROC_REAP_ACQUIRE) X(PROC_REAP_RELEASE) | ||||
X(PROC_REAP_STATUS) X(PROC_REAP_GETPIDS) X(PROC_REAP_KILL) | |||||
X(PROC_TRACE_CTL) X(PROC_TRACE_STATUS) XEND | |||||
}; | }; | ||||
static struct xlat umtx_ops[] = { | static struct xlat umtx_ops[] = { | ||||
X(UMTX_OP_RESERVED0) X(UMTX_OP_RESERVED1) X(UMTX_OP_WAIT) | X(UMTX_OP_RESERVED0) X(UMTX_OP_RESERVED1) X(UMTX_OP_WAIT) | ||||
X(UMTX_OP_WAKE) X(UMTX_OP_MUTEX_TRYLOCK) X(UMTX_OP_MUTEX_LOCK) | X(UMTX_OP_WAKE) X(UMTX_OP_MUTEX_TRYLOCK) X(UMTX_OP_MUTEX_LOCK) | ||||
X(UMTX_OP_MUTEX_UNLOCK) X(UMTX_OP_SET_CEILING) X(UMTX_OP_CV_WAIT) | X(UMTX_OP_MUTEX_UNLOCK) X(UMTX_OP_SET_CEILING) X(UMTX_OP_CV_WAIT) | ||||
X(UMTX_OP_CV_SIGNAL) X(UMTX_OP_CV_BROADCAST) X(UMTX_OP_WAIT_UINT) | X(UMTX_OP_CV_SIGNAL) X(UMTX_OP_CV_BROADCAST) X(UMTX_OP_WAIT_UINT) | ||||
X(UMTX_OP_RW_RDLOCK) X(UMTX_OP_RW_WRLOCK) X(UMTX_OP_RW_UNLOCK) | X(UMTX_OP_RW_RDLOCK) X(UMTX_OP_RW_WRLOCK) X(UMTX_OP_RW_UNLOCK) | ||||
▲ Show 20 Lines • Show All 258 Lines • ▼ Show 20 Lines | case EVFILT_PROCDESC: | ||||
break; | break; | ||||
case EVFILT_TIMER: | case EVFILT_TIMER: | ||||
fputs(xlookup_bits(kevent_timer_fflags, ke->fflags), fp); | fputs(xlookup_bits(kevent_timer_fflags, ke->fflags), fp); | ||||
break; | break; | ||||
case EVFILT_USER: { | case EVFILT_USER: { | ||||
int ctrl, data; | int ctrl, data; | ||||
ctrl = ke->fflags & NOTE_FFCTRLMASK; | ctrl = ke->fflags & NOTE_FFCTRLMASK; | ||||
data = ke->fflags & NOTE_FFLAGSMASK; | data = ke->fflags & NOTE_FFLAGSMASK; | ||||
if (input) { | if (input) { | ||||
fputs(xlookup(kevent_user_ffctrl, ctrl), fp); | fputs(xlookup(kevent_user_ffctrl, ctrl), fp); | ||||
if (ke->fflags & NOTE_TRIGGER) | if (ke->fflags & NOTE_TRIGGER) | ||||
fputs("|NOTE_TRIGGER", fp); | fputs("|NOTE_TRIGGER", fp); | ||||
if (data != 0) | if (data != 0) | ||||
fprintf(fp, "|%#x", data); | fprintf(fp, "|%#x", data); | ||||
} else { | } else { | ||||
fprintf(fp, "%#x", data); | fprintf(fp, "%#x", data); | ||||
} | } | ||||
break; | break; | ||||
} | } | ||||
default: | default: | ||||
fprintf(fp, "%#x", ke->fflags); | fprintf(fp, "%#x", ke->fflags); | ||||
} | } | ||||
fprintf(fp, ",%p,%p", (void *)ke->data, (void *)ke->udata); | fprintf(fp, ",%p,%p", (void *)ke->data, (void *)ke->udata); | ||||
} | } | ||||
/* | /* | ||||
* Converts a syscall argument into a string. Said string is | * Converts a syscall argument into a string. Said string is | ||||
* allocated via malloc(), so needs to be free()'d. sc is | * allocated via malloc(), so needs to be free()'d. sc is | ||||
* a pointer to the syscall description (see above); args is | * a pointer to the syscall description (see above); args is | ||||
* an array of all of the system call arguments. | * an array of all of the system call arguments. | ||||
*/ | */ | ||||
char * | char * | ||||
print_arg(struct syscall_args *sc, unsigned long *args, long retval, | print_arg(struct syscall_args *sc, unsigned long *args, long *retval, | ||||
struct trussinfo *trussinfo) | struct trussinfo *trussinfo) | ||||
{ | { | ||||
FILE *fp; | FILE *fp; | ||||
char *tmp; | char *tmp; | ||||
size_t tmplen; | size_t tmplen; | ||||
pid_t pid; | pid_t pid; | ||||
fp = open_memstream(&tmp, &tmplen); | fp = open_memstream(&tmp, &tmplen); | ||||
pid = trussinfo->pid; | pid = trussinfo->curthread->proc->pid; | ||||
switch (sc->type & ARG_MASK) { | switch (sc->type & ARG_MASK) { | ||||
case Hex: | case Hex: | ||||
fprintf(fp, "0x%x", (int)args[sc->offset]); | fprintf(fp, "0x%x", (int)args[sc->offset]); | ||||
break; | break; | ||||
case Octal: | case Octal: | ||||
fprintf(fp, "0%o", (int)args[sc->offset]); | fprintf(fp, "0%o", (int)args[sc->offset]); | ||||
break; | break; | ||||
case Int: | case Int: | ||||
Show All 22 Lines | case BinString: { | ||||
* is in the next syscall argument. | * is in the next syscall argument. | ||||
*/ | */ | ||||
int max_string = trussinfo->strsize; | int max_string = trussinfo->strsize; | ||||
char tmp2[max_string + 1], *tmp3; | char tmp2[max_string + 1], *tmp3; | ||||
int len; | int len; | ||||
int truncated = 0; | int truncated = 0; | ||||
if (sc->type & OUT) | if (sc->type & OUT) | ||||
len = retval; | len = retval[0]; | ||||
else | else | ||||
len = args[sc->offset + 1]; | len = args[sc->offset + 1]; | ||||
/* | /* | ||||
* Don't print more than max_string characters, to avoid word | * Don't print more than max_string characters, to avoid word | ||||
* wrap. If we have to truncate put some ... after the string. | * wrap. If we have to truncate put some ... after the string. | ||||
*/ | */ | ||||
if (len > max_string) { | if (len > max_string) { | ||||
Show All 36 Lines | case StringArray: { | ||||
*/ | */ | ||||
if (((sc->type & ARG_MASK) == ExecArgs && | if (((sc->type & ARG_MASK) == ExecArgs && | ||||
(trussinfo->flags & EXECVEARGS) == 0) || | (trussinfo->flags & EXECVEARGS) == 0) || | ||||
((sc->type & ARG_MASK) == ExecEnv && | ((sc->type & ARG_MASK) == ExecEnv && | ||||
(trussinfo->flags & EXECVEENVS) == 0)) { | (trussinfo->flags & EXECVEENVS) == 0)) { | ||||
fprintf(fp, "0x%lx", args[sc->offset]); | fprintf(fp, "0x%lx", args[sc->offset]); | ||||
break; | break; | ||||
} | } | ||||
/* | /* | ||||
* Read a page of pointers at a time. Punt if the top-level | * Read a page of pointers at a time. Punt if the top-level | ||||
* pointer is not aligned. Note that the first read is of | * pointer is not aligned. Note that the first read is of | ||||
* a partial page. | * a partial page. | ||||
*/ | */ | ||||
addr = args[sc->offset]; | addr = args[sc->offset]; | ||||
if (addr % sizeof(char *) != 0) { | if (addr % sizeof(char *) != 0) { | ||||
fprintf(fp, "0x%lx", args[sc->offset]); | fprintf(fp, "0x%lx", args[sc->offset]); | ||||
▲ Show 20 Lines • Show All 44 Lines • ▼ Show 20 Lines | #else | ||||
} | } | ||||
#endif | #endif | ||||
case Ptr: | case Ptr: | ||||
fprintf(fp, "0x%lx", args[sc->offset]); | fprintf(fp, "0x%lx", args[sc->offset]); | ||||
break; | break; | ||||
case Readlinkres: { | case Readlinkres: { | ||||
char *tmp2; | char *tmp2; | ||||
if (retval == -1) | if (retval[0] == -1) | ||||
break; | break; | ||||
tmp2 = get_string(pid, (void*)args[sc->offset], retval); | tmp2 = get_string(pid, (void*)args[sc->offset], retval[0]); | ||||
fprintf(fp, "\"%s\"", tmp2); | fprintf(fp, "\"%s\"", tmp2); | ||||
free(tmp2); | free(tmp2); | ||||
break; | break; | ||||
} | } | ||||
case Ioctl: { | case Ioctl: { | ||||
const char *temp; | const char *temp; | ||||
unsigned long cmd; | unsigned long cmd; | ||||
▲ Show 20 Lines • Show All 380 Lines • ▼ Show 20 Lines | case Kevent: { | ||||
*/ | */ | ||||
struct kevent *ke; | struct kevent *ke; | ||||
int numevents = -1; | int numevents = -1; | ||||
size_t bytes; | size_t bytes; | ||||
int i; | int i; | ||||
if (sc->offset == 1) | if (sc->offset == 1) | ||||
numevents = args[sc->offset+1]; | numevents = args[sc->offset+1]; | ||||
else if (sc->offset == 3 && retval != -1) | else if (sc->offset == 3 && retval[0] != -1) | ||||
numevents = retval; | numevents = retval[0]; | ||||
if (numevents >= 0) { | if (numevents >= 0) { | ||||
bytes = sizeof(struct kevent) * numevents; | bytes = sizeof(struct kevent) * numevents; | ||||
if ((ke = malloc(bytes)) == NULL) | if ((ke = malloc(bytes)) == NULL) | ||||
err(1, | err(1, | ||||
"Cannot malloc %zu bytes for kevent array", | "Cannot malloc %zu bytes for kevent array", | ||||
bytes); | bytes); | ||||
} else | } else | ||||
▲ Show 20 Lines • Show All 102 Lines • ▼ Show 20 Lines | case Accessmode: | ||||
if (args[sc->offset] == F_OK) | if (args[sc->offset] == F_OK) | ||||
fputs("F_OK", fp); | fputs("F_OK", fp); | ||||
else | else | ||||
fputs(xlookup_bits(access_modes, args[sc->offset]), fp); | fputs(xlookup_bits(access_modes, args[sc->offset]), fp); | ||||
break; | break; | ||||
case Sysarch: | case Sysarch: | ||||
fputs(xlookup(sysarch_ops, args[sc->offset]), fp); | fputs(xlookup(sysarch_ops, args[sc->offset]), fp); | ||||
break; | break; | ||||
case PipeFds: | |||||
/* | |||||
* The pipe() system call in the kernel returns its | |||||
* two file descriptors via return values. However, | |||||
* the interface exposed by libc is that pipe() | |||||
* accepts a pointer to an array of descriptors. | |||||
* Format the output to match the libc API by printing | |||||
* the returned file descriptors as a fake argument. | |||||
* | |||||
* Overwrite the first retval to signal a successful | |||||
* return as well. | |||||
*/ | |||||
fprintf(fp, "{ %ld, %ld }", retval[0], retval[1]); | |||||
retval[0] = 0; | |||||
break; | |||||
default: | default: | ||||
errx(1, "Invalid argument type %d\n", sc->type & ARG_MASK); | errx(1, "Invalid argument type %d\n", sc->type & ARG_MASK); | ||||
} | } | ||||
fclose(fp); | fclose(fp); | ||||
return (tmp); | return (tmp); | ||||
} | } | ||||
/* | /* | ||||
* Print (to outfile) the system call and its arguments. Note that | * Print (to outfile) the system call and its arguments. Note that | ||||
* nargs is the number of arguments (not the number of words; this is | * nargs is the number of arguments (not the number of words; this is | ||||
* potentially confusing, I know). | * potentially confusing, I know). | ||||
*/ | */ | ||||
void | void | ||||
print_syscall(struct trussinfo *trussinfo, const char *name, int nargs, | print_syscall(struct trussinfo *trussinfo, const char *name, int nargs, | ||||
char **s_args) | char **s_args) | ||||
{ | { | ||||
struct timespec timediff; | struct timespec timediff; | ||||
int i, len; | int i, len; | ||||
len = 0; | len = 0; | ||||
if (trussinfo->flags & FOLLOWFORKS) | if (trussinfo->flags & FOLLOWFORKS) | ||||
len += fprintf(trussinfo->outfile, "%5d: ", trussinfo->pid); | len += fprintf(trussinfo->outfile, "%5d: ", | ||||
trussinfo->curthread->proc->pid); | |||||
if (name != NULL && (strcmp(name, "execve") == 0 || | if (name != NULL && (strcmp(name, "execve") == 0 || | ||||
strcmp(name, "exit") == 0)) { | strcmp(name, "exit") == 0)) { | ||||
clock_gettime(CLOCK_REALTIME, &trussinfo->curthread->after); | clock_gettime(CLOCK_REALTIME, &trussinfo->curthread->after); | ||||
} | } | ||||
if (trussinfo->flags & ABSOLUTETIMESTAMPS) { | if (trussinfo->flags & ABSOLUTETIMESTAMPS) { | ||||
timespecsubt(&trussinfo->curthread->after, | timespecsubt(&trussinfo->curthread->after, | ||||
Show All 22 Lines | print_syscall(struct trussinfo *trussinfo, const char *name, int nargs, | ||||
} | } | ||||
len += fprintf(trussinfo->outfile, ")"); | len += fprintf(trussinfo->outfile, ")"); | ||||
for (i = 0; i < 6 - (len / 8); i++) | for (i = 0; i < 6 - (len / 8); i++) | ||||
fprintf(trussinfo->outfile, "\t"); | fprintf(trussinfo->outfile, "\t"); | ||||
} | } | ||||
void | void | ||||
print_syscall_ret(struct trussinfo *trussinfo, const char *name, int nargs, | print_syscall_ret(struct trussinfo *trussinfo, const char *name, int nargs, | ||||
char **s_args, int errorp, long retval, struct syscall *sc) | char **s_args, int errorp, long *retval, struct syscall *sc) | ||||
{ | { | ||||
struct timespec timediff; | struct timespec timediff; | ||||
if (trussinfo->flags & COUNTONLY) { | if (trussinfo->flags & COUNTONLY) { | ||||
if (!sc) | if (!sc) | ||||
return; | return; | ||||
clock_gettime(CLOCK_REALTIME, &trussinfo->curthread->after); | clock_gettime(CLOCK_REALTIME, &trussinfo->curthread->after); | ||||
timespecsubt(&trussinfo->curthread->after, | timespecsubt(&trussinfo->curthread->after, | ||||
&trussinfo->curthread->before, &timediff); | &trussinfo->curthread->before, &timediff); | ||||
timespecadd(&sc->time, &timediff, &sc->time); | timespecadd(&sc->time, &timediff, &sc->time); | ||||
sc->ncalls++; | sc->ncalls++; | ||||
if (errorp) | if (errorp) | ||||
sc->nerror++; | sc->nerror++; | ||||
return; | return; | ||||
} | } | ||||
print_syscall(trussinfo, name, nargs, s_args); | print_syscall(trussinfo, name, nargs, s_args); | ||||
fflush(trussinfo->outfile); | fflush(trussinfo->outfile); | ||||
if (errorp) | if (errorp) | ||||
fprintf(trussinfo->outfile, " ERR#%ld '%s'\n", retval, | fprintf(trussinfo->outfile, " ERR#%ld '%s'\n", retval[0], | ||||
strerror(retval)); | strerror(retval[0])); | ||||
else { | #ifndef __LP64__ | ||||
/* | else if (sc != NULL && sc->ret_type == 2) { | ||||
* Because pipe(2) has a special assembly glue to provide the | off_t off; | ||||
* libc API, we have to adjust retval. | |||||
*/ | #if _BYTE_ORDER == _LITTLE_ENDIAN | ||||
if (name != NULL && strcmp(name, "pipe") == 0) | off = (off_t)retval[1] << 32 | retval[0]; | ||||
retval = 0; | #else | ||||
fprintf(trussinfo->outfile, " = %ld (0x%lx)\n", retval, retval); | off = (off_t)retval[0] << 32 | retval[1]; | ||||
#endif | |||||
fprintf(trussinfo->outfile, " = %jd (0x%jx)\n", (intmax_t)off, | |||||
(intmax_t)off); | |||||
} | } | ||||
#endif | |||||
else | |||||
fprintf(trussinfo->outfile, " = %ld (0x%lx)\n", retval[0], | |||||
retval[0]); | |||||
} | } | ||||
void | void | ||||
print_summary(struct trussinfo *trussinfo) | print_summary(struct trussinfo *trussinfo) | ||||
{ | { | ||||
struct timespec total = {0, 0}; | struct timespec total = {0, 0}; | ||||
struct syscall *sc; | struct syscall *sc; | ||||
int ncall, nerror; | int ncall, nerror; | ||||
Show All 18 Lines |