Deleted Added
sdiff udiff text old ( 286914 ) new ( 286938 )
full compact
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.

--- 17 unchanged lines hidden (view full) ---

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#ifndef lint
33static const char rcsid[] =
34 "$FreeBSD: head/usr.bin/truss/syscalls.c 286938 2015-08-19 20:02:03Z jhb $";
35#endif /* not lint */
36
37/*
38 * This file has routines used to print out system calls and their
39 * arguments.
40 */
41
42#include <sys/types.h>

--- 575 unchanged lines hidden (view full) ---

618
619static const char *
620xlookup(struct xlat *xlat, int val)
621{
622
623 return (lookup(xlat, val, 16));
624}
625
626/*
627 * Searches an xlat array containing bitfield values. Remaining bits
628 * set after removing the known ones are printed at the end:
629 * IN|0x400.
630 */
631static char *
632xlookup_bits(struct xlat *xlat, int val)
633{
634 int len, rem;
635 static char str[512];
636
637 len = 0;
638 rem = val;
639 for (; xlat->str != NULL; xlat++) {
640 if ((xlat->val & rem) == xlat->val) {
641 /*
642 * Don't print the "all-bits-zero" string unless all
643 * bits are really zero.
644 */
645 if (xlat->val == 0 && val != 0)
646 continue;
647 len += sprintf(str + len, "%s|", xlat->str);
648 rem &= ~(xlat->val);
649 }
650 }
651
652 /*
653 * If we have leftover bits or didn't match anything, print
654 * the remainder.
655 */
656 if (rem || len == 0)
657 len += sprintf(str + len, "0x%x", rem);
658 if (len && str[len - 1] == '|')
659 len--;
660 str[len] = 0;
661 return (str);
662}
663
664/*
665 * If/when the list gets big, it might be desirable to do it
666 * as a hash table or binary search.
667 */
668struct syscall *
669get_syscall(const char *name)
670{
671 struct syscall *sc;
672
673 sc = syscalls;
674 if (name == NULL)
675 return (NULL);
676 while (sc->name) {
677 if (strcmp(name, sc->name) == 0)
678 return (sc);
679 sc++;
680 }
681 return (NULL);
682}
683
684/*
685 * Copy a fixed amount of bytes from the process.
686 */
687static int
688get_struct(pid_t pid, void *offset, void *buf, int len)
689{
690 struct ptrace_io_desc iorequest;
691
692 iorequest.piod_op = PIOD_READ_D;
693 iorequest.piod_offs = offset;
694 iorequest.piod_addr = buf;
695 iorequest.piod_len = len;
696 if (ptrace(PT_IO, pid, (caddr_t)&iorequest, 0) < 0)
697 return (-1);
698 return (0);
699}
700
701#define MAXSIZE 4096
702
703/*
704 * Copy a string from the process. Note that it is
705 * expected to be a C string, but if max is set, it will
706 * only get that much.
707 */
708static char *
709get_string(pid_t pid, void *addr, int max)
710{
711 struct ptrace_io_desc iorequest;

--- 111 unchanged lines hidden (view full) ---

823 }
824 default:
825 fprintf(fp, "%#x", ke->fflags);
826 }
827 fprintf(fp, ",%p,%p", (void *)ke->data, (void *)ke->udata);
828}
829
830/*
831 * Converts a syscall argument into a string. Said string is
832 * allocated via malloc(), so needs to be free()'d. sc is
833 * a pointer to the syscall description (see above); args is
834 * an array of all of the system call arguments.
835 */
836char *
837print_arg(struct syscall_args *sc, unsigned long *args, long retval,
838 struct trussinfo *trussinfo)
839{
840 FILE *fp;
841 char *tmp;
842 size_t tmplen;
843 pid_t pid;

--- 14 unchanged lines hidden (view full) ---

858 fprintf(fp, "0x%lx", args[sc->offset]);
859 break;
860 case Long:
861 fprintf(fp, "%ld", args[sc->offset]);
862 break;
863 case Name: {
864 /* NULL-terminated string. */
865 char *tmp2;
866
867 tmp2 = get_string(pid, (void*)args[sc->offset], 0);
868 fprintf(fp, "\"%s\"", tmp2);
869 free(tmp2);
870 break;
871 }
872 case BinString: {
873 /*
874 * Binary block of data that might have printable characters.
875 * XXX If type|OUT, assume that the length is the syscall's
876 * return value. Otherwise, assume that the length of the block
877 * is in the next syscall argument.
878 */
879 int max_string = trussinfo->strsize;
880 char tmp2[max_string + 1], *tmp3;
881 int len;
882 int truncated = 0;
883
884 if (sc->type & OUT)
885 len = retval;
886 else
887 len = args[sc->offset + 1];
888
889 /*
890 * Don't print more than max_string characters, to avoid word
891 * wrap. If we have to truncate put some ... after the string.
892 */
893 if (len > max_string) {
894 len = max_string;
895 truncated = 1;
896 }
897 if (len && get_struct(pid, (void*)args[sc->offset], &tmp2, len)
898 != -1) {
899 tmp3 = malloc(len * 4 + 1);
900 while (len) {

--- 46 unchanged lines hidden (view full) ---

947 }
948#ifdef __LP64__
949 case Quad:
950 fprintf(fp, "0x%lx", args[sc->offset]);
951 break;
952#else
953 case Quad: {
954 unsigned long long ll;
955
956 ll = *(unsigned long long *)(args + sc->offset);
957 fprintf(fp, "0x%llx", ll);
958 break;
959 }
960#endif
961 case Ptr:
962 fprintf(fp, "0x%lx", args[sc->offset]);
963 break;
964 case Readlinkres: {
965 char *tmp2;
966
967 if (retval == -1)
968 break;
969 tmp2 = get_string(pid, (void*)args[sc->offset], retval);
970 fprintf(fp, "\"%s\"", tmp2);
971 free(tmp2);
972 break;
973 }
974 case Ioctl: {
975 const char *temp;
976 unsigned long cmd;
977
978 cmd = args[sc->offset];
979 temp = ioctlname(cmd);
980 if (temp)
981 fputs(temp, fp);
982 else {
983 fprintf(fp, "0x%lx { IO%s%s 0x%lx('%c'), %lu, %lu }",
984 cmd, cmd & IOC_OUT ? "R" : "",
985 cmd & IOC_IN ? "W" : "", IOCGROUP(cmd),
986 isprint(IOCGROUP(cmd)) ? (char)IOCGROUP(cmd) : '?',
987 cmd & 0xFF, IOCPARM_LEN(cmd));
988 }
989 break;
990 }
991 case Timespec: {
992 struct timespec ts;
993
994 if (get_struct(pid, (void *)args[sc->offset], &ts,
995 sizeof(ts)) != -1)
996 fprintf(fp, "{ %ld.%09ld }", (long)ts.tv_sec,
997 ts.tv_nsec);
998 else
999 fprintf(fp, "0x%lx", args[sc->offset]);
1000 break;
1001 }

--- 24 unchanged lines hidden (view full) ---

1026 }
1027 fputs(" }", fp);
1028 } else
1029 fprintf(fp, "0x%lx", args[sc->offset]);
1030 break;
1031 }
1032 case Timeval: {
1033 struct timeval tv;
1034
1035 if (get_struct(pid, (void *)args[sc->offset], &tv, sizeof(tv))
1036 != -1)
1037 fprintf(fp, "{ %ld.%06ld }", (long)tv.tv_sec,
1038 tv.tv_usec);
1039 else
1040 fprintf(fp, "0x%lx", args[sc->offset]);
1041 break;
1042 }
1043 case Timeval2: {
1044 struct timeval tv[2];
1045
1046 if (get_struct(pid, (void *)args[sc->offset], &tv, sizeof(tv))
1047 != -1)
1048 fprintf(fp, "{ %ld.%06ld, %ld.%06ld }",
1049 (long)tv[0].tv_sec, tv[0].tv_usec,
1050 (long)tv[1].tv_sec, tv[1].tv_usec);
1051 else
1052 fprintf(fp, "0x%lx", args[sc->offset]);
1053 break;
1054 }
1055 case Itimerval: {
1056 struct itimerval itv;
1057
1058 if (get_struct(pid, (void *)args[sc->offset], &itv,
1059 sizeof(itv)) != -1)
1060 fprintf(fp, "{ %ld.%06ld, %ld.%06ld }",
1061 (long)itv.it_interval.tv_sec,
1062 itv.it_interval.tv_usec,
1063 (long)itv.it_value.tv_sec,
1064 itv.it_value.tv_usec);
1065 else
1066 fprintf(fp, "0x%lx", args[sc->offset]);
1067 break;
1068 }
1069 case LinuxSockArgs:
1070 {
1071 struct linux_socketcall_args largs;
1072
1073 if (get_struct(pid, (void *)args[sc->offset], (void *)&largs,
1074 sizeof(largs)) != -1)
1075 fprintf(fp, "{ %s, 0x%lx }",
1076 lookup(linux_socketcall_ops, largs.what, 10),
1077 (long unsigned int)largs.args);
1078 else
1079 fprintf(fp, "0x%lx", args[sc->offset]);
1080 break;

--- 81 unchanged lines hidden (view full) ---

1162 fputc('}', fp);
1163 break;
1164 }
1165 case Sigprocmask: {
1166 fputs(xlookup(sigprocmask_ops, args[sc->offset]), fp);
1167 break;
1168 }
1169 case Fcntlflag: {
1170 /* XXX: Output depends on the value of the previous argument. */
1171 switch (args[sc->offset - 1]) {
1172 case F_SETFD:
1173 fputs(xlookup_bits(fcntlfd_arg, args[sc->offset]), fp);
1174 break;
1175 case F_SETFL:
1176 fputs(xlookup_bits(fcntlfl_arg, args[sc->offset]), fp);
1177 break;
1178 case F_GETFD:
1179 case F_GETFL:

--- 115 unchanged lines hidden (view full) ---

1295 ss.ss_len) == -1) {
1296 fprintf(fp, "0x%lx", args[sc->offset]);
1297 break;
1298 }
1299
1300 switch (ss.ss_family) {
1301 case AF_INET:
1302 lsin = (struct sockaddr_in *)&ss;
1303 inet_ntop(AF_INET, &lsin->sin_addr, addr, sizeof(addr));
1304 fprintf(fp, "{ AF_INET %s:%d }", addr,
1305 htons(lsin->sin_port));
1306 break;
1307 case AF_INET6:
1308 lsin6 = (struct sockaddr_in6 *)&ss;
1309 inet_ntop(AF_INET6, &lsin6->sin6_addr, addr,
1310 sizeof(addr));
1311 fprintf(fp, "{ AF_INET6 [%s]:%d }", addr,
1312 htons(lsin6->sin6_port));
1313 break;
1314 case AF_UNIX:
1315 sun = (struct sockaddr_un *)&ss;
1316 fprintf(fp, "{ AF_UNIX \"%s\" }", sun->sun_path);
1317 break;
1318 default:

--- 25 unchanged lines hidden (view full) ---

1344 fprintf(fp, " %s ss_t }",
1345 xlookup_bits(sigaction_flags, sa.sa_flags));
1346 } else
1347 fprintf(fp, "0x%lx", args[sc->offset]);
1348 break;
1349 }
1350 case Kevent: {
1351 /*
1352 * XXX XXX: The size of the array is determined by either the
1353 * next syscall argument, or by the syscall return value,
1354 * depending on which argument number we are. This matches the
1355 * kevent syscall, but luckily that's the only syscall that uses
1356 * them.
1357 */
1358 struct kevent *ke;
1359 int numevents = -1;
1360 size_t bytes;
1361 int i;

--- 22 unchanged lines hidden (view full) ---

1384 } else {
1385 fprintf(fp, "0x%lx", args[sc->offset]);
1386 }
1387 free(ke);
1388 break;
1389 }
1390 case Stat: {
1391 struct stat st;
1392
1393 if (get_struct(pid, (void *)args[sc->offset], &st, sizeof(st))
1394 != -1) {
1395 char mode[12];
1396
1397 strmode(st.st_mode, mode);
1398 fprintf(fp,
1399 "{ mode=%s,inode=%jd,size=%jd,blksize=%ld }", mode,
1400 (intmax_t)st.st_ino, (intmax_t)st.st_size,
1401 (long)st.st_blksize);
1402 } else {
1403 fprintf(fp, "0x%lx", args[sc->offset]);
1404 }
1405 break;
1406 }
1407 case Rusage: {
1408 struct rusage ru;
1409
1410 if (get_struct(pid, (void *)args[sc->offset], &ru, sizeof(ru))
1411 != -1) {
1412 fprintf(fp,
1413 "{ u=%ld.%06ld,s=%ld.%06ld,in=%ld,out=%ld }",
1414 (long)ru.ru_utime.tv_sec, ru.ru_utime.tv_usec,
1415 (long)ru.ru_stime.tv_sec, ru.ru_stime.tv_usec,
1416 ru.ru_inblock, ru.ru_oublock);
1417 } else
1418 fprintf(fp, "0x%lx", args[sc->offset]);
1419 break;
1420 }
1421 case Rlimit: {
1422 struct rlimit rl;
1423
1424 if (get_struct(pid, (void *)args[sc->offset], &rl, sizeof(rl))
1425 != -1) {
1426 fprintf(fp, "{ cur=%ju,max=%ju }",
1427 rl.rlim_cur, rl.rlim_max);
1428 } else
1429 fprintf(fp, "0x%lx", args[sc->offset]);
1430 break;
1431 }

--- 53 unchanged lines hidden (view full) ---

1485 default:
1486 errx(1, "Invalid argument type %d\n", sc->type & ARG_MASK);
1487 }
1488 fclose(fp);
1489 return (tmp);
1490}
1491
1492/*
1493 * Print (to outfile) the system call and its arguments. Note that
1494 * nargs is the number of arguments (not the number of words; this is
1495 * potentially confusing, I know).
1496 */
1497void
1498print_syscall(struct trussinfo *trussinfo, const char *name, int nargs,
1499 char **s_args)
1500{
1501 struct timespec timediff;
1502 int i, len;
1503
1504 len = 0;

--- 97 unchanged lines hidden ---