1/* 2 * Copyright 1997 Sean Eric Fagan 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions 6 * are met: 7 * 1. Redistributions of source code must retain the above copyright 8 * notice, this list of conditions and the following disclaimer. --- 16 unchanged lines hidden (view full) --- 25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 29 * SUCH DAMAGE. 30 */ 31 32#include <sys/cdefs.h> |
33__FBSDID("$FreeBSD: head/usr.bin/truss/syscalls.c 288832 2015-10-05 18:08:35Z bdrewery $"); |
34 35/* 36 * This file has routines used to print out system calls and their 37 * arguments. 38 */ 39 40#include <sys/types.h> 41#include <sys/event.h> --- 42 unchanged lines hidden (view full) --- 84#define QUAD_SLOTS 1 85#else 86#define QUAD_SLOTS 2 87#endif 88 89/* 90 * This should probably be in its own file, sorted alphabetically. 91 */ |
92static struct syscall decoded_syscalls[] = { |
93 { .name = "fcntl", .ret_type = 1, .nargs = 3, 94 .args = { { Int, 0 }, { Fcntl, 1 }, { Fcntlflag, 2 } } }, 95 { .name = "rfork", .ret_type = 1, .nargs = 1, 96 .args = { { Rforkflags, 0 } } }, 97 { .name = "linux_readlink", .ret_type = 1, .nargs = 3, 98 .args = { { Name, 0 }, { Name | OUT, 1 }, { Int, 2 } } }, 99 { .name = "linux_socketcall", .ret_type = 1, .nargs = 2, 100 .args = { { Int, 0 }, { LinuxSockArgs, 1 } } }, --- 264 unchanged lines hidden (view full) --- 365 .args = { { Ptr, 0 }, { Umtxop, 1 }, { LongHex, 2 }, { Ptr, 3 }, 366 { Ptr, 4 } } }, 367 { .name = "thr_kill", .ret_type = 1, .nargs = 2, 368 .args = { { Long, 0 }, { Signal, 1 } } }, 369 { .name = "thr_self", .ret_type = 1, .nargs = 1, 370 .args = { { Ptr, 0 } } }, 371 { .name = 0 }, 372}; |
373static STAILQ_HEAD(, syscall) syscalls; |
374 375/* Xlat idea taken from strace */ 376struct xlat { 377 int val; 378 const char *str; 379}; 380 381#define X(a) { a, #a }, --- 273 unchanged lines hidden (view full) --- 655 if (rem || len == 0) 656 len += sprintf(str + len, "0x%x", rem); 657 if (len && str[len - 1] == '|') 658 len--; 659 str[len] = 0; 660 return (str); 661} 662 |
663void 664init_syscalls(void) 665{ 666 struct syscall *sc; 667 668 STAILQ_INIT(&syscalls); 669 for (sc = decoded_syscalls; sc->name != NULL; sc++) 670 STAILQ_INSERT_HEAD(&syscalls, sc, entries); 671} |
672/* 673 * If/when the list gets big, it might be desirable to do it 674 * as a hash table or binary search. 675 */ 676struct syscall * |
677get_syscall(const char *name, int nargs) |
678{ 679 struct syscall *sc; |
680 int i; |
681 |
682 if (name == NULL) 683 return (NULL); |
684 STAILQ_FOREACH(sc, &syscalls, entries) |
685 if (strcmp(name, sc->name) == 0) 686 return (sc); |
687 688 /* It is unknown. Add it into the list. */ 689#if DEBUG 690 fprintf(stderr, "unknown syscall %s -- setting args to %d\n", name, 691 nargs); 692#endif 693 694 sc = calloc(1, sizeof(struct syscall)); 695 sc->name = strdup(name); 696 sc->ret_type = 1; 697 sc->nargs = nargs; 698 for (i = 0; i < nargs; i++) { 699 sc->args[i].offset = i; 700 /* Treat all unknown arguments as LongHex. */ 701 sc->args[i].type = LongHex; |
702 } |
703 STAILQ_INSERT_HEAD(&syscalls, sc, entries); 704 705 return (sc); |
706} 707 708/* 709 * Copy a fixed amount of bytes from the process. 710 */ 711static int 712get_struct(pid_t pid, void *offset, void *buf, int len) 713{ --- 939 unchanged lines hidden (view full) --- 1653 1654void 1655print_syscall_ret(struct trussinfo *trussinfo, const char *name, int nargs, 1656 char **s_args, int errorp, long *retval, struct syscall *sc) 1657{ 1658 struct timespec timediff; 1659 1660 if (trussinfo->flags & COUNTONLY) { |
1661 clock_gettime(CLOCK_REALTIME, &trussinfo->curthread->after); 1662 timespecsubt(&trussinfo->curthread->after, 1663 &trussinfo->curthread->before, &timediff); 1664 timespecadd(&sc->time, &timediff, &sc->time); 1665 sc->ncalls++; 1666 if (errorp) 1667 sc->nerror++; 1668 return; 1669 } 1670 1671 print_syscall(trussinfo, name, nargs, s_args); 1672 fflush(trussinfo->outfile); 1673 if (errorp) 1674 fprintf(trussinfo->outfile, " ERR#%ld '%s'\n", retval[0], 1675 strerror(retval[0])); 1676#ifndef __LP64__ |
1677 else if (sc->ret_type == 2) { |
1678 off_t off; 1679 1680#if _BYTE_ORDER == _LITTLE_ENDIAN 1681 off = (off_t)retval[1] << 32 | retval[0]; 1682#else 1683 off = (off_t)retval[0] << 32 | retval[1]; 1684#endif 1685 fprintf(trussinfo->outfile, " = %jd (0x%jx)\n", (intmax_t)off, --- 10 unchanged lines hidden (view full) --- 1696{ 1697 struct timespec total = {0, 0}; 1698 struct syscall *sc; 1699 int ncall, nerror; 1700 1701 fprintf(trussinfo->outfile, "%-20s%15s%8s%8s\n", 1702 "syscall", "seconds", "calls", "errors"); 1703 ncall = nerror = 0; |
1704 STAILQ_FOREACH(sc, &syscalls, entries) |
1705 if (sc->ncalls) { 1706 fprintf(trussinfo->outfile, "%-20s%5jd.%09ld%8d%8d\n", 1707 sc->name, (intmax_t)sc->time.tv_sec, 1708 sc->time.tv_nsec, sc->ncalls, sc->nerror); 1709 timespecadd(&total, &sc->time, &total); 1710 ncall += sc->ncalls; 1711 nerror += sc->nerror; 1712 } 1713 fprintf(trussinfo->outfile, "%20s%15s%8s%8s\n", 1714 "", "-------------", "-------", "-------"); 1715 fprintf(trussinfo->outfile, "%-20s%5jd.%09ld%8d%8d\n", 1716 "", (intmax_t)total.tv_sec, total.tv_nsec, ncall, nerror); 1717} |