]> CyberLeo.Net >> Repos - FreeBSD/stable/8.git/blob - usr.bin/kdump/kdump.c
MFC 232072: Pretty-print the advice constants passed to posix_fadvise(2).
[FreeBSD/stable/8.git] / usr.bin / kdump / kdump.c
1 /*-
2  * Copyright (c) 1988, 1993
3  *      The Regents of the University of California.  All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  * 3. All advertising materials mentioning features or use of this software
14  *    must display the following acknowledgement:
15  *      This product includes software developed by the University of
16  *      California, Berkeley and its contributors.
17  * 4. Neither the name of the University nor the names of its contributors
18  *    may be used to endorse or promote products derived from this software
19  *    without specific prior written permission.
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31  * SUCH DAMAGE.
32  */
33
34 #ifndef lint
35 static const char copyright[] =
36 "@(#) Copyright (c) 1988, 1993\n\
37         The Regents of the University of California.  All rights reserved.\n";
38 #endif /* not lint */
39
40 #ifndef lint
41 #if 0
42 static char sccsid[] = "@(#)kdump.c     8.1 (Berkeley) 6/6/93";
43 #endif
44 #endif /* not lint */
45 #include <sys/cdefs.h>
46 __FBSDID("$FreeBSD$");
47
48 #define _KERNEL
49 extern int errno;
50 #include <sys/errno.h>
51 #undef _KERNEL
52 #include <sys/param.h>
53 #include <sys/errno.h>
54 #define _KERNEL
55 #include <sys/time.h>
56 #undef _KERNEL
57 #include <sys/uio.h>
58 #include <sys/ktrace.h>
59 #include <sys/ioctl.h>
60 #include <sys/socket.h>
61 #include <sys/stat.h>
62 #include <sys/sysent.h>
63 #include <sys/un.h>
64 #include <sys/queue.h>
65 #ifdef IPX
66 #include <sys/types.h>
67 #include <netipx/ipx.h>
68 #endif
69 #ifdef NETATALK
70 #include <netatalk/at.h>
71 #endif
72 #include <arpa/inet.h>
73 #include <netinet/in.h>
74 #include <ctype.h>
75 #include <dlfcn.h>
76 #include <err.h>
77 #include <grp.h>
78 #include <inttypes.h>
79 #include <locale.h>
80 #include <pwd.h>
81 #include <stdio.h>
82 #include <stdlib.h>
83 #include <string.h>
84 #include <time.h>
85 #include <unistd.h>
86 #include <vis.h>
87 #include "ktrace.h"
88 #include "kdump_subr.h"
89
90 u_int abidump(struct ktr_header *);
91 int fetchprocinfo(struct ktr_header *, u_int *);
92 int fread_tail(void *, int, int);
93 void dumpheader(struct ktr_header *);
94 void ktrsyscall(struct ktr_syscall *, u_int);
95 void ktrsysret(struct ktr_sysret *, u_int);
96 void ktrnamei(char *, int);
97 void hexdump(char *, int, int);
98 void visdump(char *, int, int);
99 void ktrgenio(struct ktr_genio *, int);
100 void ktrpsig(struct ktr_psig *);
101 void ktrcsw(struct ktr_csw *);
102 void ktruser(int, unsigned char *);
103 void ktrsockaddr(struct sockaddr *);
104 void ktrstat(struct stat *);
105 void ktrstruct(char *, size_t);
106 void usage(void);
107 void sockfamilyname(int);
108 const char *ioctlname(u_long);
109
110 int timestamp, decimal, fancy = 1, suppressdata, tail, threads, maxdata,
111     resolv = 0, abiflag = 0;
112 const char *tracefile = DEF_TRACEFILE;
113 struct ktr_header ktr_header;
114
115 #define TIME_FORMAT     "%b %e %T %Y"
116 #define eqs(s1, s2)     (strcmp((s1), (s2)) == 0)
117
118 #define print_number(i,n,c) do {                \
119         if (decimal)                            \
120                 printf("%c%ld", c, (long)*i);   \
121         else                                    \
122                 printf("%c%#lx", c, (long)*i);  \
123         i++;                                    \
124         n--;                                    \
125         c = ',';                                \
126         } while (0);
127
128 #if defined(__amd64__) || defined(__i386__)
129
130 void linux_ktrsyscall(struct ktr_syscall *);
131 void linux_ktrsysret(struct ktr_sysret *);
132 extern char *linux_syscallnames[];
133 extern int nlinux_syscalls;
134
135 /*
136  * from linux.h
137  * Linux syscalls return negative errno's, we do positive and map them
138  */
139 static int bsd_to_linux_errno[ELAST + 1] = {
140         -0,  -1,  -2,  -3,  -4,  -5,  -6,  -7,  -8,  -9,
141         -10, -35, -12, -13, -14, -15, -16, -17, -18, -19,
142         -20, -21, -22, -23, -24, -25, -26, -27, -28, -29,
143         -30, -31, -32, -33, -34, -11,-115,-114, -88, -89,
144         -90, -91, -92, -93, -94, -95, -96, -97, -98, -99,
145         -100,-101,-102,-103,-104,-105,-106,-107,-108,-109,
146         -110,-111, -40, -36,-112,-113, -39, -11, -87,-122,
147         -116, -66,  -6,  -6,  -6,  -6,  -6, -37, -38,  -9,
148         -6,  -6, -43, -42, -75,-125, -84, -95, -16, -74,
149         -72, -67, -71
150 };
151 #endif
152
153 struct proc_info
154 {
155         TAILQ_ENTRY(proc_info)  info;
156         u_int                   sv_flags;
157         pid_t                   pid;
158 };
159
160 TAILQ_HEAD(trace_procs, proc_info) trace_procs;
161
162 int
163 main(int argc, char *argv[])
164 {
165         int ch, ktrlen, size;
166         void *m;
167         int trpoints = ALL_POINTS;
168         int drop_logged;
169         pid_t pid = 0;
170         u_int sv_flags;
171
172         (void) setlocale(LC_CTYPE, "");
173
174         while ((ch = getopt(argc,argv,"f:dElm:np:AHRrsTt:")) != -1)
175                 switch((char)ch) {
176                 case 'A':
177                         abiflag = 1;
178                         break;
179                 case 'f':
180                         tracefile = optarg;
181                         break;
182                 case 'd':
183                         decimal = 1;
184                         break;
185                 case 'l':
186                         tail = 1;
187                         break;
188                 case 'm':
189                         maxdata = atoi(optarg);
190                         break;
191                 case 'n':
192                         fancy = 0;
193                         break;
194                 case 'p':
195                         pid = atoi(optarg);
196                         break;
197                 case 'r':
198                         resolv = 1;
199                         break;
200                 case 's':
201                         suppressdata = 1;
202                         break;
203                 case 'E':
204                         timestamp = 3;  /* elapsed timestamp */
205                         break;
206                 case 'H':
207                         threads = 1;
208                         break;
209                 case 'R':
210                         timestamp = 2;  /* relative timestamp */
211                         break;
212                 case 'T':
213                         timestamp = 1;
214                         break;
215                 case 't':
216                         trpoints = getpoints(optarg);
217                         if (trpoints < 0)
218                                 errx(1, "unknown trace point in %s", optarg);
219                         break;
220                 default:
221                         usage();
222                 }
223
224         if (argc > optind)
225                 usage();
226
227         m = (void *)malloc(size = 1025);
228         if (m == NULL)
229                 errx(1, "%s", strerror(ENOMEM));
230         if (!freopen(tracefile, "r", stdin))
231                 err(1, "%s", tracefile);
232         TAILQ_INIT(&trace_procs);
233         drop_logged = 0;
234         while (fread_tail(&ktr_header, sizeof(struct ktr_header), 1)) {
235                 if (ktr_header.ktr_type & KTR_DROP) {
236                         ktr_header.ktr_type &= ~KTR_DROP;
237                         if (!drop_logged && threads) {
238                                 (void)printf(
239                                     "%6jd %6jd %-8.*s Events dropped.\n",
240                                     (intmax_t)ktr_header.ktr_pid,
241                                     ktr_header.ktr_tid > 0 ?
242                                     (intmax_t)ktr_header.ktr_tid : 0,
243                                     MAXCOMLEN, ktr_header.ktr_comm);
244                                 drop_logged = 1;
245                         } else if (!drop_logged) {
246                                 (void)printf("%6jd %-8.*s Events dropped.\n",
247                                     (intmax_t)ktr_header.ktr_pid, MAXCOMLEN,
248                                     ktr_header.ktr_comm);
249                                 drop_logged = 1;
250                         }
251                 }
252                 if (trpoints & (1<<ktr_header.ktr_type))
253                         if (pid == 0 || ktr_header.ktr_pid == pid)
254                                 dumpheader(&ktr_header);
255                 if ((ktrlen = ktr_header.ktr_len) < 0)
256                         errx(1, "bogus length 0x%x", ktrlen);
257                 if (ktrlen > size) {
258                         m = (void *)realloc(m, ktrlen+1);
259                         if (m == NULL)
260                                 errx(1, "%s", strerror(ENOMEM));
261                         size = ktrlen;
262                 }
263                 if (ktrlen && fread_tail(m, ktrlen, 1) == 0)
264                         errx(1, "data too short");
265                 if (fetchprocinfo(&ktr_header, (u_int *)m) != 0)
266                         continue;
267                 sv_flags = abidump(&ktr_header);
268                 if (pid && ktr_header.ktr_pid != pid)
269                         continue;
270                 if ((trpoints & (1<<ktr_header.ktr_type)) == 0)
271                         continue;
272                 drop_logged = 0;
273                 switch (ktr_header.ktr_type) {
274                 case KTR_SYSCALL:
275 #if defined(__amd64__) || defined(__i386__)
276                         if ((sv_flags & SV_ABI_MASK) == SV_ABI_LINUX)
277                                 linux_ktrsyscall((struct ktr_syscall *)m);
278                         else
279 #endif
280                                 ktrsyscall((struct ktr_syscall *)m, sv_flags);
281                         break;
282                 case KTR_SYSRET:
283 #if defined(__amd64__) || defined(__i386__)
284                         if ((sv_flags & SV_ABI_MASK) == SV_ABI_LINUX)
285                                 linux_ktrsysret((struct ktr_sysret *)m);
286                         else
287 #endif
288                                 ktrsysret((struct ktr_sysret *)m, sv_flags);
289                         break;
290                 case KTR_NAMEI:
291                 case KTR_SYSCTL:
292                         ktrnamei(m, ktrlen);
293                         break;
294                 case KTR_GENIO:
295                         ktrgenio((struct ktr_genio *)m, ktrlen);
296                         break;
297                 case KTR_PSIG:
298                         ktrpsig((struct ktr_psig *)m);
299                         break;
300                 case KTR_CSW:
301                         ktrcsw((struct ktr_csw *)m);
302                         break;
303                 case KTR_USER:
304                         ktruser(ktrlen, m);
305                         break;
306                 case KTR_STRUCT:
307                         ktrstruct(m, ktrlen);
308                         break;
309                 default:
310                         printf("\n");
311                         break;
312                 }
313                 if (tail)
314                         (void)fflush(stdout);
315         }
316         return 0;
317 }
318
319 int
320 fread_tail(void *buf, int size, int num)
321 {
322         int i;
323
324         while ((i = fread(buf, size, num, stdin)) == 0 && tail) {
325                 (void)sleep(1);
326                 clearerr(stdin);
327         }
328         return (i);
329 }
330
331 int
332 fetchprocinfo(struct ktr_header *kth, u_int *flags)
333 {
334         struct proc_info *pi;
335
336         switch (kth->ktr_type) {
337         case KTR_PROCCTOR:
338                 TAILQ_FOREACH(pi, &trace_procs, info) {
339                         if (pi->pid == kth->ktr_pid) {
340                                 TAILQ_REMOVE(&trace_procs, pi, info);
341                                 break;
342                         }
343                 }
344                 pi = malloc(sizeof(struct proc_info));
345                 if (pi == NULL)
346                         errx(1, "%s", strerror(ENOMEM));
347                 pi->sv_flags = *flags;
348                 pi->pid = kth->ktr_pid;
349                 TAILQ_INSERT_TAIL(&trace_procs, pi, info);
350                 return (1);
351
352         case KTR_PROCDTOR:
353                 TAILQ_FOREACH(pi, &trace_procs, info) {
354                         if (pi->pid == kth->ktr_pid) {
355                                 TAILQ_REMOVE(&trace_procs, pi, info);
356                                 free(pi);
357                                 break;
358                         }
359                 }
360                 return (1);
361         }
362
363         return (0);
364 }
365
366 u_int
367 abidump(struct ktr_header *kth)
368 {
369         struct proc_info *pi;
370         const char *abi;
371         const char *arch;
372         u_int flags = 0;
373
374         TAILQ_FOREACH(pi, &trace_procs, info) {
375                 if (pi->pid == kth->ktr_pid) {
376                         flags = pi->sv_flags;
377                         break;
378                 }
379         }
380
381         if (abiflag == 0)
382                 return (flags);
383
384         switch (flags & SV_ABI_MASK) {
385         case SV_ABI_LINUX:
386                 abi = "L";
387                 break;
388         case SV_ABI_FREEBSD:
389                 abi = "F";
390                 break;
391         default:
392                 abi = "U";
393                 break;
394         }
395
396         if (flags != 0) {
397                 if (flags & SV_LP64)
398                         arch = "64";
399                 else
400                         arch = "32";
401         } else
402                 arch = "00";
403
404         printf("%s%s  ", abi, arch);
405
406         return (flags);
407 }
408
409 void
410 dumpheader(struct ktr_header *kth)
411 {
412         static char unknown[64];
413         static struct timeval prevtime, temp;
414         const char *type;
415
416         switch (kth->ktr_type) {
417         case KTR_SYSCALL:
418                 type = "CALL";
419                 break;
420         case KTR_SYSRET:
421                 type = "RET ";
422                 break;
423         case KTR_NAMEI:
424                 type = "NAMI";
425                 break;
426         case KTR_GENIO:
427                 type = "GIO ";
428                 break;
429         case KTR_PSIG:
430                 type = "PSIG";
431                 break;
432         case KTR_CSW:
433                 type = "CSW ";
434                 break;
435         case KTR_USER:
436                 type = "USER";
437                 break;
438         case KTR_STRUCT:
439                 type = "STRU";
440                 break;
441         case KTR_SYSCTL:
442                 type = "SCTL";
443                 break;
444         case KTR_PROCCTOR:
445                 /* FALLTHROUGH */
446         case KTR_PROCDTOR:
447                 return;
448         default:
449                 (void)sprintf(unknown, "UNKNOWN(%d)", kth->ktr_type);
450                 type = unknown;
451         }
452
453         /*
454          * The ktr_tid field was previously the ktr_buffer field, which held
455          * the kernel pointer value for the buffer associated with data
456          * following the record header.  It now holds a threadid, but only
457          * for trace files after the change.  Older trace files still contain
458          * kernel pointers.  Detect this and suppress the results by printing
459          * negative tid's as 0.
460          */
461         if (threads)
462                 (void)printf("%6jd %6jd %-8.*s ", (intmax_t)kth->ktr_pid,
463                     kth->ktr_tid > 0 ? (intmax_t)kth->ktr_tid : 0,
464                     MAXCOMLEN, kth->ktr_comm);
465         else
466                 (void)printf("%6jd %-8.*s ", (intmax_t)kth->ktr_pid, MAXCOMLEN,
467                     kth->ktr_comm);
468         if (timestamp) {
469                 if (timestamp == 3) {
470                         if (prevtime.tv_sec == 0)
471                                 prevtime = kth->ktr_time;
472                         timevalsub(&kth->ktr_time, &prevtime);
473                 }
474                 if (timestamp == 2) {
475                         temp = kth->ktr_time;
476                         timevalsub(&kth->ktr_time, &prevtime);
477                         prevtime = temp;
478                 }
479                 (void)printf("%jd.%06ld ", (intmax_t)kth->ktr_time.tv_sec,
480                     kth->ktr_time.tv_usec);
481         }
482         (void)printf("%s  ", type);
483 }
484
485 #include <sys/syscall.h>
486 #define KTRACE
487 #include <sys/kern/syscalls.c>
488 #undef KTRACE
489 int nsyscalls = sizeof (syscallnames) / sizeof (syscallnames[0]);
490
491 void
492 ktrsyscall(struct ktr_syscall *ktr, u_int flags)
493 {
494         int narg = ktr->ktr_narg;
495         register_t *ip;
496
497         if ((flags != 0 && ((flags & SV_ABI_MASK) != SV_ABI_FREEBSD)) ||
498             (ktr->ktr_code >= nsyscalls || ktr->ktr_code < 0))
499                 (void)printf("[%d]", ktr->ktr_code);
500         else
501                 (void)printf("%s", syscallnames[ktr->ktr_code]);
502         ip = &ktr->ktr_args[0];
503         if (narg) {
504                 char c = '(';
505                 if (fancy &&
506                     (flags == 0 || (flags & SV_ABI_MASK) == SV_ABI_FREEBSD)) {
507                         if (ktr->ktr_code == SYS_ioctl) {
508                                 const char *cp;
509                                 print_number(ip,narg,c);
510                                 if ((cp = ioctlname(*ip)) != NULL)
511                                         (void)printf(",%s", cp);
512                                 else {
513                                         if (decimal)
514                                                 (void)printf(",%ld", (long)*ip);
515                                         else
516                                                 (void)printf(",%#lx ", (long)*ip);
517                                 }
518                                 c = ',';
519                                 ip++;
520                                 narg--;
521                         } else if (ktr->ktr_code == SYS_ptrace) {
522                                 (void)putchar('(');
523                                 ptraceopname ((int)*ip);
524                                 c = ',';
525                                 ip++;
526                                 narg--;
527                         } else if (ktr->ktr_code == SYS_access ||
528                                    ktr->ktr_code == SYS_eaccess) {
529                                 print_number(ip,narg,c);
530                                 (void)putchar(',');
531                                 accessmodename ((int)*ip);
532                                 ip++;
533                                 narg--;
534                         } else if (ktr->ktr_code == SYS_open) {
535                                 int     flags;
536                                 int     mode;
537                                 print_number(ip,narg,c);
538                                 flags = *ip;
539                                 mode = *++ip;
540                                 (void)putchar(',');
541                                 flagsandmodename (flags, mode, decimal);
542                                 ip++;
543                                 narg-=2;
544                         } else if (ktr->ktr_code == SYS_wait4) {
545                                 print_number(ip,narg,c);
546                                 print_number(ip,narg,c);
547                                 (void)putchar(',');
548                                 wait4optname ((int)*ip);
549                                 ip++;
550                                 narg--;
551                         } else if (ktr->ktr_code == SYS_chmod ||
552                                    ktr->ktr_code == SYS_fchmod ||
553                                    ktr->ktr_code == SYS_lchmod) {
554                                 print_number(ip,narg,c);
555                                 (void)putchar(',');
556                                 modename ((int)*ip);
557                                 ip++;
558                                 narg--;
559                         } else if (ktr->ktr_code == SYS_mknod) {
560                                 print_number(ip,narg,c);
561                                 (void)putchar(',');
562                                 modename ((int)*ip);
563                                 ip++;
564                                 narg--;
565                         } else if (ktr->ktr_code == SYS_getfsstat) {
566                                 print_number(ip,narg,c);
567                                 print_number(ip,narg,c);
568                                 (void)putchar(',');
569                                 getfsstatflagsname ((int)*ip);
570                                 ip++;
571                                 narg--;
572                         } else if (ktr->ktr_code == SYS_mount) {
573                                 print_number(ip,narg,c);
574                                 print_number(ip,narg,c);
575                                 (void)putchar(',');
576                                 mountflagsname ((int)*ip);
577                                 ip++;
578                                 narg--;
579                         } else if (ktr->ktr_code == SYS_unmount) {
580                                 print_number(ip,narg,c);
581                                 (void)putchar(',');
582                                 mountflagsname ((int)*ip);
583                                 ip++;
584                                 narg--;
585                         } else if (ktr->ktr_code == SYS_recvmsg ||
586                                    ktr->ktr_code == SYS_sendmsg) {
587                                 print_number(ip,narg,c);
588                                 print_number(ip,narg,c);
589                                 (void)putchar(',');
590                                 sendrecvflagsname ((int)*ip);
591                                 ip++;
592                                 narg--;
593                         } else if (ktr->ktr_code == SYS_recvfrom ||
594                                    ktr->ktr_code == SYS_sendto) {
595                                 print_number(ip,narg,c);
596                                 print_number(ip,narg,c);
597                                 print_number(ip,narg,c);
598                                 (void)putchar(',');
599                                 sendrecvflagsname ((int)*ip);
600                                 ip++;
601                                 narg--;
602                         } else if (ktr->ktr_code == SYS_chflags ||
603                                    ktr->ktr_code == SYS_fchflags ||
604                                    ktr->ktr_code == SYS_lchflags) {
605                                 print_number(ip,narg,c);
606                                 (void)putchar(',');
607                                 modename((int)*ip);
608                                 ip++;
609                                 narg--;
610                         } else if (ktr->ktr_code == SYS_kill) {
611                                 print_number(ip,narg,c);
612                                 (void)putchar(',');
613                                 signame((int)*ip);
614                                 ip++;
615                                 narg--;
616                         } else if (ktr->ktr_code == SYS_reboot) {
617                                 (void)putchar('(');
618                                 rebootoptname((int)*ip);
619                                 ip++;
620                                 narg--;
621                         } else if (ktr->ktr_code == SYS_umask) {
622                                 (void)putchar('(');
623                                 modename((int)*ip);
624                                 ip++;
625                                 narg--;
626                         } else if (ktr->ktr_code == SYS_msync) {
627                                 print_number(ip,narg,c);
628                                 print_number(ip,narg,c);
629                                 (void)putchar(',');
630                                 msyncflagsname((int)*ip);
631                                 ip++;
632                                 narg--;
633 #ifdef SYS_freebsd6_mmap
634                         } else if (ktr->ktr_code == SYS_freebsd6_mmap) {
635                                 print_number(ip,narg,c);
636                                 print_number(ip,narg,c);
637                                 (void)putchar(',');
638                                 mmapprotname ((int)*ip);
639                                 (void)putchar(',');
640                                 ip++;
641                                 narg--;
642                                 mmapflagsname ((int)*ip);
643                                 ip++;
644                                 narg--;
645 #endif
646                         } else if (ktr->ktr_code == SYS_mmap) {
647                                 print_number(ip,narg,c);
648                                 print_number(ip,narg,c);
649                                 (void)putchar(',');
650                                 mmapprotname ((int)*ip);
651                                 (void)putchar(',');
652                                 ip++;
653                                 narg--;
654                                 mmapflagsname ((int)*ip);
655                                 ip++;
656                                 narg--;
657                         } else if (ktr->ktr_code == SYS_mprotect) {
658                                 print_number(ip,narg,c);
659                                 print_number(ip,narg,c);
660                                 (void)putchar(',');
661                                 mmapprotname ((int)*ip);
662                                 ip++;
663                                 narg--;
664                         } else if (ktr->ktr_code == SYS_madvise) {
665                                 print_number(ip,narg,c);
666                                 print_number(ip,narg,c);
667                                 (void)putchar(',');
668                                 madvisebehavname((int)*ip);
669                                 ip++;
670                                 narg--;
671                         } else if (ktr->ktr_code == SYS_setpriority) {
672                                 print_number(ip,narg,c);
673                                 print_number(ip,narg,c);
674                                 (void)putchar(',');
675                                 prioname((int)*ip);
676                                 ip++;
677                                 narg--;
678                         } else if (ktr->ktr_code == SYS_fcntl) {
679                                 int cmd;
680                                 int arg;
681                                 print_number(ip,narg,c);
682                                 cmd = *ip;
683                                 arg = *++ip;
684                                 (void)putchar(',');
685                                 fcntlcmdname(cmd, arg, decimal);
686                                 ip++;
687                                 narg-=2;
688                         } else if (ktr->ktr_code == SYS_socket) {
689                                 int sockdomain;
690                                 (void)putchar('(');
691                                 sockdomain=(int)*ip;
692                                 sockdomainname(sockdomain);
693                                 ip++;
694                                 narg--;
695                                 (void)putchar(',');
696                                 socktypename((int)*ip);
697                                 ip++;
698                                 narg--;
699                                 if (sockdomain == PF_INET ||
700                                     sockdomain == PF_INET6) {
701                                         (void)putchar(',');
702                                         sockipprotoname((int)*ip);
703                                         ip++;
704                                         narg--;
705                                 }
706                                 c = ',';
707                         } else if (ktr->ktr_code == SYS_setsockopt ||
708                                    ktr->ktr_code == SYS_getsockopt) {
709                                 print_number(ip,narg,c);
710                                 (void)putchar(',');
711                                 sockoptlevelname((int)*ip, decimal);
712                                 if ((int)*ip == SOL_SOCKET) {
713                                         ip++;
714                                         narg--;
715                                         (void)putchar(',');
716                                         sockoptname((int)*ip);
717                                 }
718                                 ip++;
719                                 narg--;
720 #ifdef SYS_freebsd6_lseek
721                         } else if (ktr->ktr_code == SYS_freebsd6_lseek) {
722                                 print_number(ip,narg,c);
723                                 /* Hidden 'pad' argument, not in lseek(2) */
724                                 print_number(ip,narg,c);
725                                 print_number(ip,narg,c);
726                                 (void)putchar(',');
727                                 whencename ((int)*ip);
728                                 ip++;
729                                 narg--;
730 #endif
731                         } else if (ktr->ktr_code == SYS_lseek) {
732                                 print_number(ip,narg,c);
733                                 /* Hidden 'pad' argument, not in lseek(2) */
734                                 print_number(ip,narg,c);
735                                 (void)putchar(',');
736                                 whencename ((int)*ip);
737                                 ip++;
738                                 narg--;
739
740                         } else if (ktr->ktr_code == SYS_flock) {
741                                 print_number(ip,narg,c);
742                                 (void)putchar(',');
743                                 flockname((int)*ip);
744                                 ip++;
745                                 narg--;
746                         } else if (ktr->ktr_code == SYS_mkfifo ||
747                                    ktr->ktr_code == SYS_mkdir) {
748                                 print_number(ip,narg,c);
749                                 (void)putchar(',');
750                                 modename((int)*ip);
751                                 ip++;
752                                 narg--;
753                         } else if (ktr->ktr_code == SYS_shutdown) {
754                                 print_number(ip,narg,c);
755                                 (void)putchar(',');
756                                 shutdownhowname((int)*ip);
757                                 ip++;
758                                 narg--;
759                         } else if (ktr->ktr_code == SYS_socketpair) {
760                                 (void)putchar('(');
761                                 sockdomainname((int)*ip);
762                                 ip++;
763                                 narg--;
764                                 (void)putchar(',');
765                                 socktypename((int)*ip);
766                                 ip++;
767                                 narg--;
768                                 c = ',';
769                         } else if (ktr->ktr_code == SYS_getrlimit ||
770                                    ktr->ktr_code == SYS_setrlimit) {
771                                 (void)putchar('(');
772                                 rlimitname((int)*ip);
773                                 ip++;
774                                 narg--;
775                                 c = ',';
776                         } else if (ktr->ktr_code == SYS_quotactl) {
777                                 print_number(ip,narg,c);
778                                 (void)putchar(',');
779                                 quotactlname((int)*ip);
780                                 ip++;
781                                 narg--;
782                                 c = ',';
783                         } else if (ktr->ktr_code == SYS_nfssvc) {
784                                 (void)putchar('(');
785                                 nfssvcname((int)*ip);
786                                 ip++;
787                                 narg--;
788                                 c = ',';
789                         } else if (ktr->ktr_code == SYS_rtprio) {
790                                 (void)putchar('(');
791                                 rtprioname((int)*ip);
792                                 ip++;
793                                 narg--;
794                                 c = ',';
795                         } else if (ktr->ktr_code == SYS___semctl) {
796                                 print_number(ip,narg,c);
797                                 print_number(ip,narg,c);
798                                 (void)putchar(',');
799                                 semctlname((int)*ip);
800                                 ip++;
801                                 narg--;
802                         } else if (ktr->ktr_code == SYS_semget) {
803                                 print_number(ip,narg,c);
804                                 print_number(ip,narg,c);
805                                 (void)putchar(',');
806                                 semgetname((int)*ip);
807                                 ip++;
808                                 narg--;
809                         } else if (ktr->ktr_code == SYS_msgctl) {
810                                 print_number(ip,narg,c);
811                                 (void)putchar(',');
812                                 shmctlname((int)*ip);
813                                 ip++;
814                                 narg--;
815                         } else if (ktr->ktr_code == SYS_shmat) {
816                                 print_number(ip,narg,c);
817                                 print_number(ip,narg,c);
818                                 (void)putchar(',');
819                                 shmatname((int)*ip);
820                                 ip++;
821                                 narg--;
822                         } else if (ktr->ktr_code == SYS_shmctl) {
823                                 print_number(ip,narg,c);
824                                 (void)putchar(',');
825                                 shmctlname((int)*ip);
826                                 ip++;
827                                 narg--;
828                         } else if (ktr->ktr_code == SYS_minherit) {
829                                 print_number(ip,narg,c);
830                                 print_number(ip,narg,c);
831                                 (void)putchar(',');
832                                 minheritname((int)*ip);
833                                 ip++;
834                                 narg--;
835                         } else if (ktr->ktr_code == SYS_rfork) {
836                                 (void)putchar('(');
837                                 rforkname((int)*ip);
838                                 ip++;
839                                 narg--;
840                                 c = ',';
841                         } else if (ktr->ktr_code == SYS_lio_listio) {
842                                 (void)putchar('(');
843                                 lio_listioname((int)*ip);
844                                 ip++;
845                                 narg--;
846                                 c = ',';
847                         } else if (ktr->ktr_code == SYS_mlockall) {
848                                 (void)putchar('(');
849                                 mlockallname((int)*ip);
850                                 ip++;
851                                 narg--;
852                         } else if (ktr->ktr_code == SYS_sched_setscheduler) {
853                                 print_number(ip,narg,c);
854                                 (void)putchar(',');
855                                 schedpolicyname((int)*ip);
856                                 ip++;
857                                 narg--;
858                         } else if (ktr->ktr_code == SYS_sched_get_priority_max ||
859                                    ktr->ktr_code == SYS_sched_get_priority_min) {
860                                 (void)putchar('(');
861                                 schedpolicyname((int)*ip);
862                                 ip++;
863                                 narg--;
864                         } else if (ktr->ktr_code == SYS_sendfile) {
865                                 print_number(ip,narg,c);
866                                 print_number(ip,narg,c);
867                                 print_number(ip,narg,c);
868                                 print_number(ip,narg,c);
869                                 print_number(ip,narg,c);
870                                 print_number(ip,narg,c);
871                                 (void)putchar(',');
872                                 sendfileflagsname((int)*ip);
873                                 ip++;
874                                 narg--;
875                         } else if (ktr->ktr_code == SYS_kldsym) {
876                                 print_number(ip,narg,c);
877                                 (void)putchar(',');
878                                 kldsymcmdname((int)*ip);
879                                 ip++;
880                                 narg--;
881                         } else if (ktr->ktr_code == SYS_sigprocmask) {
882                                 (void)putchar('(');
883                                 sigprocmaskhowname((int)*ip);
884                                 ip++;
885                                 narg--;
886                                 c = ',';
887                         } else if (ktr->ktr_code == SYS___acl_get_file ||
888                                    ktr->ktr_code == SYS___acl_set_file ||
889                                    ktr->ktr_code == SYS___acl_get_fd ||
890                                    ktr->ktr_code == SYS___acl_set_fd ||
891                                    ktr->ktr_code == SYS___acl_delete_file ||
892                                    ktr->ktr_code == SYS___acl_delete_fd ||
893                                    ktr->ktr_code == SYS___acl_aclcheck_file ||
894                                    ktr->ktr_code == SYS___acl_aclcheck_fd ||
895                                    ktr->ktr_code == SYS___acl_get_link ||
896                                    ktr->ktr_code == SYS___acl_set_link ||
897                                    ktr->ktr_code == SYS___acl_delete_link ||
898                                    ktr->ktr_code == SYS___acl_aclcheck_link) {
899                                 print_number(ip,narg,c);
900                                 (void)putchar(',');
901                                 acltypename((int)*ip);
902                                 ip++;
903                                 narg--;
904                         } else if (ktr->ktr_code == SYS_sigaction) {
905                                 (void)putchar('(');
906                                 signame((int)*ip);
907                                 ip++;
908                                 narg--;
909                                 c = ',';
910                         } else if (ktr->ktr_code == SYS_extattrctl) {
911                                 print_number(ip,narg,c);
912                                 (void)putchar(',');
913                                 extattrctlname((int)*ip);
914                                 ip++;
915                                 narg--;
916                         } else if (ktr->ktr_code == SYS_nmount) {
917                                 print_number(ip,narg,c);
918                                 print_number(ip,narg,c);
919                                 (void)putchar(',');
920                                 mountflagsname ((int)*ip);
921                                 ip++;
922                                 narg--;
923                         } else if (ktr->ktr_code == SYS_thr_create) {
924                                 print_number(ip,narg,c);
925                                 print_number(ip,narg,c);
926                                 (void)putchar(',');
927                                 thrcreateflagsname ((int)*ip);
928                                 ip++;
929                                 narg--;
930                         } else if (ktr->ktr_code == SYS_thr_kill) {
931                                 print_number(ip,narg,c);
932                                 (void)putchar(',');
933                                 signame ((int)*ip);
934                                 ip++;
935                                 narg--;
936                         } else if (ktr->ktr_code == SYS_kldunloadf) {
937                                 print_number(ip,narg,c);
938                                 (void)putchar(',');
939                                 kldunloadfflagsname ((int)*ip);
940                                 ip++;
941                                 narg--;
942                         } else if (ktr->ktr_code == SYS_posix_fadvise) {
943                                 print_number(ip,narg,c);
944                                 print_number(ip,narg,c);
945                                 print_number(ip,narg,c);
946                                 (void)putchar(',');
947                                 fadvisebehavname((int)*ip);
948                                 ip++;
949                                 narg--;
950                         }
951                 }
952                 while (narg > 0) {
953                         print_number(ip,narg,c);
954                 }
955                 (void)putchar(')');
956         }
957         (void)putchar('\n');
958 }
959
960 void
961 ktrsysret(struct ktr_sysret *ktr, u_int flags)
962 {
963         register_t ret = ktr->ktr_retval;
964         int error = ktr->ktr_error;
965         int code = ktr->ktr_code;
966
967         if ((flags != 0 && ((flags & SV_ABI_MASK) != SV_ABI_FREEBSD)) ||
968             (code >= nsyscalls || code < 0))
969                 (void)printf("[%d] ", code);
970         else
971                 (void)printf("%s ", syscallnames[code]);
972
973         if (error == 0) {
974                 if (fancy) {
975                         (void)printf("%ld", (long)ret);
976                         if (ret < 0 || ret > 9)
977                                 (void)printf("/%#lx", (long)ret);
978                 } else {
979                         if (decimal)
980                                 (void)printf("%ld", (long)ret);
981                         else
982                                 (void)printf("%#lx", (long)ret);
983                 }
984         } else if (error == ERESTART)
985                 (void)printf("RESTART");
986         else if (error == EJUSTRETURN)
987                 (void)printf("JUSTRETURN");
988         else {
989                 (void)printf("-1 errno %d", ktr->ktr_error);
990                 if (fancy)
991                         (void)printf(" %s", strerror(ktr->ktr_error));
992         }
993         (void)putchar('\n');
994 }
995
996 void
997 ktrnamei(char *cp, int len)
998 {
999         (void)printf("\"%.*s\"\n", len, cp);
1000 }
1001
1002 void
1003 hexdump(char *p, int len, int screenwidth)
1004 {
1005         int n, i;
1006         int width;
1007
1008         width = 0;
1009         do {
1010                 width += 2;
1011                 i = 13;                 /* base offset */
1012                 i += (width / 2) + 1;   /* spaces every second byte */
1013                 i += (width * 2);       /* width of bytes */
1014                 i += 3;                 /* "  |" */
1015                 i += width;             /* each byte */
1016                 i += 1;                 /* "|" */
1017         } while (i < screenwidth);
1018         width -= 2;
1019
1020         for (n = 0; n < len; n += width) {
1021                 for (i = n; i < n + width; i++) {
1022                         if ((i % width) == 0) { /* beginning of line */
1023                                 printf("       0x%04x", i);
1024                         }
1025                         if ((i % 2) == 0) {
1026                                 printf(" ");
1027                         }
1028                         if (i < len)
1029                                 printf("%02x", p[i] & 0xff);
1030                         else
1031                                 printf("  ");
1032                 }
1033                 printf("  |");
1034                 for (i = n; i < n + width; i++) {
1035                         if (i >= len)
1036                                 break;
1037                         if (p[i] >= ' ' && p[i] <= '~')
1038                                 printf("%c", p[i]);
1039                         else
1040                                 printf(".");
1041                 }
1042                 printf("|\n");
1043         }
1044         if ((i % width) != 0)
1045                 printf("\n");
1046 }
1047
1048 void
1049 visdump(char *dp, int datalen, int screenwidth)
1050 {
1051         int col = 0;
1052         char *cp;
1053         int width;
1054         char visbuf[5];
1055
1056         (void)printf("       \"");
1057         col = 8;
1058         for (;datalen > 0; datalen--, dp++) {
1059                 (void) vis(visbuf, *dp, VIS_CSTYLE, *(dp+1));
1060                 cp = visbuf;
1061                 /*
1062                  * Keep track of printables and
1063                  * space chars (like fold(1)).
1064                  */
1065                 if (col == 0) {
1066                         (void)putchar('\t');
1067                         col = 8;
1068                 }
1069                 switch(*cp) {
1070                 case '\n':
1071                         col = 0;
1072                         (void)putchar('\n');
1073                         continue;
1074                 case '\t':
1075                         width = 8 - (col&07);
1076                         break;
1077                 default:
1078                         width = strlen(cp);
1079                 }
1080                 if (col + width > (screenwidth-2)) {
1081                         (void)printf("\\\n\t");
1082                         col = 8;
1083                 }
1084                 col += width;
1085                 do {
1086                         (void)putchar(*cp++);
1087                 } while (*cp);
1088         }
1089         if (col == 0)
1090                 (void)printf("       ");
1091         (void)printf("\"\n");
1092 }
1093
1094 void
1095 ktrgenio(struct ktr_genio *ktr, int len)
1096 {
1097         int datalen = len - sizeof (struct ktr_genio);
1098         char *dp = (char *)ktr + sizeof (struct ktr_genio);
1099         static int screenwidth = 0;
1100         int i, binary;
1101
1102         if (screenwidth == 0) {
1103                 struct winsize ws;
1104
1105                 if (fancy && ioctl(fileno(stderr), TIOCGWINSZ, &ws) != -1 &&
1106                     ws.ws_col > 8)
1107                         screenwidth = ws.ws_col;
1108                 else
1109                         screenwidth = 80;
1110         }
1111         printf("fd %d %s %d byte%s\n", ktr->ktr_fd,
1112                 ktr->ktr_rw == UIO_READ ? "read" : "wrote", datalen,
1113                 datalen == 1 ? "" : "s");
1114         if (suppressdata)
1115                 return;
1116         if (maxdata && datalen > maxdata)
1117                 datalen = maxdata;
1118
1119         for (i = 0, binary = 0; i < datalen && binary == 0; i++)  {
1120                 if (dp[i] >= 32 && dp[i] < 127)
1121                         continue;
1122                 if (dp[i] == 10 || dp[i] == 13 || dp[i] == 0 || dp[i] == 9)
1123                         continue;
1124                 binary = 1;
1125         }
1126         if (binary)
1127                 hexdump(dp, datalen, screenwidth);
1128         else
1129                 visdump(dp, datalen, screenwidth);
1130 }
1131
1132 const char *signames[] = {
1133         "NULL", "HUP", "INT", "QUIT", "ILL", "TRAP", "IOT",     /*  1 - 6  */
1134         "EMT", "FPE", "KILL", "BUS", "SEGV", "SYS",             /*  7 - 12 */
1135         "PIPE", "ALRM",  "TERM", "URG", "STOP", "TSTP",         /* 13 - 18 */
1136         "CONT", "CHLD", "TTIN", "TTOU", "IO", "XCPU",           /* 19 - 24 */
1137         "XFSZ", "VTALRM", "PROF", "WINCH", "29", "USR1",        /* 25 - 30 */
1138         "USR2", NULL,                                           /* 31 - 32 */
1139 };
1140
1141 void
1142 ktrpsig(struct ktr_psig *psig)
1143 {
1144         if (psig->signo > 0 && psig->signo < NSIG)
1145                 (void)printf("SIG%s ", signames[psig->signo]);
1146         else
1147                 (void)printf("SIG %d ", psig->signo);
1148         if (psig->action == SIG_DFL)
1149                 (void)printf("SIG_DFL code=0x%x\n", psig->code);
1150         else {
1151                 (void)printf("caught handler=0x%lx mask=0x%x code=0x%x\n",
1152                     (u_long)psig->action, psig->mask.__bits[0], psig->code);
1153         }
1154 }
1155
1156 void
1157 ktrcsw(struct ktr_csw *cs)
1158 {
1159         (void)printf("%s %s\n", cs->out ? "stop" : "resume",
1160                 cs->user ? "user" : "kernel");
1161 }
1162
1163 #define UTRACE_DLOPEN_START             1
1164 #define UTRACE_DLOPEN_STOP              2
1165 #define UTRACE_DLCLOSE_START            3
1166 #define UTRACE_DLCLOSE_STOP             4
1167 #define UTRACE_LOAD_OBJECT              5
1168 #define UTRACE_UNLOAD_OBJECT            6
1169 #define UTRACE_ADD_RUNDEP               7
1170 #define UTRACE_PRELOAD_FINISHED         8
1171 #define UTRACE_INIT_CALL                9
1172 #define UTRACE_FINI_CALL                10
1173
1174 struct utrace_rtld {
1175         char sig[4];                            /* 'RTLD' */
1176         int event;
1177         void *handle;
1178         void *mapbase;
1179         size_t mapsize;
1180         int refcnt;
1181         char name[MAXPATHLEN];
1182 };
1183
1184 void
1185 ktruser_rtld(int len, unsigned char *p)
1186 {
1187         struct utrace_rtld *ut = (struct utrace_rtld *)p;
1188         void *parent;
1189         int mode;
1190
1191         switch (ut->event) {
1192         case UTRACE_DLOPEN_START:
1193                 mode = ut->refcnt;
1194                 printf("dlopen(%s, ", ut->name);
1195                 switch (mode & RTLD_MODEMASK) {
1196                 case RTLD_NOW:
1197                         printf("RTLD_NOW");
1198                         break;
1199                 case RTLD_LAZY:
1200                         printf("RTLD_LAZY");
1201                         break;
1202                 default:
1203                         printf("%#x", mode & RTLD_MODEMASK);
1204                 }
1205                 if (mode & RTLD_GLOBAL)
1206                         printf(" | RTLD_GLOBAL");
1207                 if (mode & RTLD_TRACE)
1208                         printf(" | RTLD_TRACE");
1209                 if (mode & ~(RTLD_MODEMASK | RTLD_GLOBAL | RTLD_TRACE))
1210                         printf(" | %#x", mode &
1211                             ~(RTLD_MODEMASK | RTLD_GLOBAL | RTLD_TRACE));
1212                 printf(")\n");
1213                 break;
1214         case UTRACE_DLOPEN_STOP:
1215                 printf("%p = dlopen(%s) ref %d\n", ut->handle, ut->name,
1216                     ut->refcnt);
1217                 break;
1218         case UTRACE_DLCLOSE_START:
1219                 printf("dlclose(%p) (%s, %d)\n", ut->handle, ut->name,
1220                     ut->refcnt);
1221                 break;
1222         case UTRACE_DLCLOSE_STOP:
1223                 printf("dlclose(%p) finished\n", ut->handle);
1224                 break;
1225         case UTRACE_LOAD_OBJECT:
1226                 printf("RTLD: loaded   %p @ %p - %p (%s)\n", ut->handle,
1227                     ut->mapbase, (char *)ut->mapbase + ut->mapsize - 1,
1228                     ut->name);
1229                 break;
1230         case UTRACE_UNLOAD_OBJECT:
1231                 printf("RTLD: unloaded %p @ %p - %p (%s)\n", ut->handle,
1232                     ut->mapbase, (char *)ut->mapbase + ut->mapsize - 1,
1233                     ut->name);
1234                 break;
1235         case UTRACE_ADD_RUNDEP:
1236                 parent = ut->mapbase;
1237                 printf("RTLD: %p now depends on %p (%s, %d)\n", parent,
1238                     ut->handle, ut->name, ut->refcnt);
1239                 break;
1240         case UTRACE_PRELOAD_FINISHED:
1241                 printf("RTLD: LD_PRELOAD finished\n");
1242                 break;
1243         case UTRACE_INIT_CALL:
1244                 printf("RTLD: init %p for %p (%s)\n", ut->mapbase, ut->handle,
1245                     ut->name);
1246                 break;
1247         case UTRACE_FINI_CALL:
1248                 printf("RTLD: fini %p for %p (%s)\n", ut->mapbase, ut->handle,
1249                     ut->name);
1250                 break;
1251         default:
1252                 p += 4;
1253                 len -= 4;
1254                 printf("RTLD: %d ", len);
1255                 while (len--)
1256                         if (decimal)
1257                                 printf(" %d", *p++);
1258                         else
1259                                 printf(" %02x", *p++);
1260                 printf("\n");
1261         }
1262 }
1263
1264 struct utrace_malloc {
1265         void *p;
1266         size_t s;
1267         void *r;
1268 };
1269
1270 void
1271 ktruser_malloc(int len, unsigned char *p)
1272 {
1273         struct utrace_malloc *ut = (struct utrace_malloc *)p;
1274
1275         if (ut->p == NULL) {
1276                 if (ut->s == 0 && ut->r == NULL)
1277                         printf("malloc_init()\n");
1278                 else
1279                         printf("%p = malloc(%zu)\n", ut->r, ut->s);
1280         } else {
1281                 if (ut->s == 0)
1282                         printf("free(%p)\n", ut->p);
1283                 else
1284                         printf("%p = realloc(%p, %zu)\n", ut->r, ut->p, ut->s);
1285         }
1286 }
1287
1288 void
1289 ktruser(int len, unsigned char *p)
1290 {
1291
1292         if (len >= 8 && bcmp(p, "RTLD", 4) == 0) {
1293                 ktruser_rtld(len, p);
1294                 return;
1295         }
1296
1297         if (len == sizeof(struct utrace_malloc)) {
1298                 ktruser_malloc(len, p);
1299                 return;
1300         }
1301
1302         (void)printf("%d ", len);
1303         while (len--)
1304                 if (decimal)
1305                         (void)printf(" %d", *p++);
1306                 else
1307                         (void)printf(" %02x", *p++);
1308         (void)printf("\n");
1309 }
1310
1311 void
1312 ktrsockaddr(struct sockaddr *sa)
1313 {
1314 /*
1315  TODO: Support additional address families
1316         #include <netnatm/natm.h>
1317         struct sockaddr_natm    *natm;
1318         #include <netsmb/netbios.h>
1319         struct sockaddr_nb      *nb;
1320 */
1321         char addr[64];
1322
1323         /*
1324          * note: ktrstruct() has already verified that sa points to a
1325          * buffer at least sizeof(struct sockaddr) bytes long and exactly
1326          * sa->sa_len bytes long.
1327          */
1328         printf("struct sockaddr { ");
1329         sockfamilyname(sa->sa_family);
1330         printf(", ");
1331
1332 #define check_sockaddr_len(n)                                   \
1333         if (sa_##n->s##n##_len < sizeof(struct sockaddr_##n)) { \
1334                 printf("invalid");                              \
1335                 break;                                          \
1336         }
1337
1338         switch(sa->sa_family) {
1339         case AF_INET: {
1340                 struct sockaddr_in      *sa_in;
1341
1342                 sa_in = (struct sockaddr_in *)sa;
1343                 check_sockaddr_len(in);
1344                 inet_ntop(AF_INET, &sa_in->sin_addr, addr, sizeof addr);
1345                 printf("%s:%u", addr, ntohs(sa_in->sin_port));
1346                 break;
1347         }
1348 #ifdef NETATALK
1349         case AF_APPLETALK: {
1350                 struct sockaddr_at      *sa_at;
1351                 struct netrange         *nr;
1352
1353                 sa_at = (struct sockaddr_at *)sa;
1354                 check_sockaddr_len(at);
1355                 nr = &sa_at->sat_range.r_netrange;
1356                 printf("%d.%d, %d-%d, %d", ntohs(sa_at->sat_addr.s_net),
1357                         sa_at->sat_addr.s_node, ntohs(nr->nr_firstnet),
1358                         ntohs(nr->nr_lastnet), nr->nr_phase);
1359                 break;
1360         }
1361 #endif
1362         case AF_INET6: {
1363                 struct sockaddr_in6     *sa_in6;
1364
1365                 sa_in6 = (struct sockaddr_in6 *)sa;
1366                 check_sockaddr_len(in6);
1367                 inet_ntop(AF_INET6, &sa_in6->sin6_addr, addr, sizeof addr);
1368                 printf("[%s]:%u", addr, htons(sa_in6->sin6_port));
1369                 break;
1370         }
1371 #ifdef IPX
1372         case AF_IPX: {
1373                 struct sockaddr_ipx     *sa_ipx;
1374
1375                 sa_ipx = (struct sockaddr_ipx *)sa;
1376                 check_sockaddr_len(ipx);
1377                 /* XXX wish we had ipx_ntop */
1378                 printf("%s", ipx_ntoa(sa_ipx->sipx_addr));
1379                 break;
1380         }
1381 #endif
1382         case AF_UNIX: {
1383                 struct sockaddr_un *sa_un;
1384
1385                 sa_un = (struct sockaddr_un *)sa;
1386                 check_sockaddr_len(un);
1387                 printf("%.*s", (int)sizeof(sa_un->sun_path), sa_un->sun_path);
1388                 break;
1389         }
1390         default:
1391                 printf("unknown address family");
1392         }
1393         printf(" }\n");
1394 }
1395
1396 void
1397 ktrstat(struct stat *statp)
1398 {
1399         char mode[12], timestr[PATH_MAX + 4];
1400         struct passwd *pwd;
1401         struct group  *grp;
1402         struct tm *tm;
1403
1404         /*
1405          * note: ktrstruct() has already verified that statp points to a
1406          * buffer exactly sizeof(struct stat) bytes long.
1407          */
1408         printf("struct stat {");
1409         strmode(statp->st_mode, mode);
1410         printf("dev=%ju, ino=%ju, mode=%s, nlink=%ju, ",
1411                 (uintmax_t)statp->st_dev, (uintmax_t)statp->st_ino, mode,
1412                 (uintmax_t)statp->st_nlink);
1413         if (resolv == 0 || (pwd = getpwuid(statp->st_uid)) == NULL)
1414                 printf("uid=%ju, ", (uintmax_t)statp->st_uid);
1415         else
1416                 printf("uid=\"%s\", ", pwd->pw_name);
1417         if (resolv == 0 || (grp = getgrgid(statp->st_gid)) == NULL)
1418                 printf("gid=%ju, ", (uintmax_t)statp->st_gid);
1419         else
1420                 printf("gid=\"%s\", ", grp->gr_name);
1421         printf("rdev=%ju, ", (uintmax_t)statp->st_rdev);
1422         printf("atime=");
1423         if (resolv == 0)
1424                 printf("%jd", (intmax_t)statp->st_atimespec.tv_sec);
1425         else {
1426                 tm = localtime(&statp->st_atimespec.tv_sec);
1427                 (void)strftime(timestr, sizeof(timestr), TIME_FORMAT, tm);
1428                 printf("\"%s\"", timestr);
1429         }
1430         if (statp->st_atimespec.tv_nsec != 0)
1431                 printf(".%09ld, ", statp->st_atimespec.tv_nsec);
1432         else
1433                 printf(", ");
1434         printf("stime=");
1435         if (resolv == 0)
1436                 printf("%jd", (intmax_t)statp->st_mtimespec.tv_sec);
1437         else {
1438                 tm = localtime(&statp->st_mtimespec.tv_sec);
1439                 (void)strftime(timestr, sizeof(timestr), TIME_FORMAT, tm);
1440                 printf("\"%s\"", timestr);
1441         }
1442         if (statp->st_mtimespec.tv_nsec != 0)
1443                 printf(".%09ld, ", statp->st_mtimespec.tv_nsec);
1444         else
1445                 printf(", ");
1446         printf("ctime=");
1447         if (resolv == 0)
1448                 printf("%jd", (intmax_t)statp->st_ctimespec.tv_sec);
1449         else {
1450                 tm = localtime(&statp->st_ctimespec.tv_sec);
1451                 (void)strftime(timestr, sizeof(timestr), TIME_FORMAT, tm);
1452                 printf("\"%s\"", timestr);
1453         }
1454         if (statp->st_ctimespec.tv_nsec != 0)
1455                 printf(".%09ld, ", statp->st_ctimespec.tv_nsec);
1456         else
1457                 printf(", ");
1458         printf("birthtime=");
1459         if (resolv == 0)
1460                 printf("%jd", (intmax_t)statp->st_birthtimespec.tv_sec);
1461         else {
1462                 tm = localtime(&statp->st_birthtimespec.tv_sec);
1463                 (void)strftime(timestr, sizeof(timestr), TIME_FORMAT, tm);
1464                 printf("\"%s\"", timestr);
1465         }
1466         if (statp->st_birthtimespec.tv_nsec != 0)
1467                 printf(".%09ld, ", statp->st_birthtimespec.tv_nsec);
1468         else
1469                 printf(", ");
1470         printf("size=%jd, blksize=%ju, blocks=%jd, flags=0x%x",
1471                 (uintmax_t)statp->st_size, (uintmax_t)statp->st_blksize,
1472                 (intmax_t)statp->st_blocks, statp->st_flags);
1473         printf(" }\n");
1474 }
1475
1476 void
1477 ktrstruct(char *buf, size_t buflen)
1478 {
1479         char *name, *data;
1480         size_t namelen, datalen;
1481         int i;
1482
1483         for (name = buf, namelen = 0;
1484              namelen < buflen && name[namelen] != '\0';
1485              ++namelen)
1486                 /* nothing */;
1487         if (namelen == buflen)
1488                 goto invalid;
1489         if (name[namelen] != '\0')
1490                 goto invalid;
1491         data = buf + namelen + 1;
1492         datalen = buflen - namelen - 1;
1493         if (datalen == 0)
1494                 goto invalid;
1495         /* sanity check */
1496         for (i = 0; i < namelen; ++i)
1497                 if (!isalpha((unsigned char)name[i]))
1498                         goto invalid;
1499         if (strcmp(name, "stat") == 0) {
1500                 if (datalen != sizeof(struct stat))
1501                         goto invalid;
1502                 ktrstat((struct stat *)data);
1503         } else if (strcmp(name, "sockaddr") == 0) {
1504                 if (datalen < sizeof(struct sockaddr) ||
1505                     datalen != ((struct sockaddr *)(data))->sa_len)
1506                         goto invalid;
1507                 ktrsockaddr((struct sockaddr *)data);
1508         } else {
1509                 printf("unknown structure\n");
1510         }
1511         return;
1512 invalid:
1513         printf("invalid record\n");
1514 }
1515
1516 #if defined(__amd64__) || defined(__i386__)
1517 void
1518 linux_ktrsyscall(struct ktr_syscall *ktr)
1519 {
1520         int narg = ktr->ktr_narg;
1521         register_t *ip;
1522
1523         if (ktr->ktr_code >= nlinux_syscalls || ktr->ktr_code < 0)
1524                 printf("[%d]", ktr->ktr_code);
1525         else
1526                 printf("%s", linux_syscallnames[ktr->ktr_code]);
1527         ip = &ktr->ktr_args[0];
1528         if (narg) {
1529                 char c = '(';
1530                 while (narg > 0)
1531                         print_number(ip, narg, c);
1532                 putchar(')');
1533         }
1534         putchar('\n');
1535 }
1536
1537 void
1538 linux_ktrsysret(struct ktr_sysret *ktr)
1539 {
1540         register_t ret = ktr->ktr_retval;
1541         int error = ktr->ktr_error;
1542         int code = ktr->ktr_code;
1543
1544         if (code >= nlinux_syscalls || code < 0)
1545                 printf("[%d] ", code);
1546         else
1547                 printf("%s ", linux_syscallnames[code]);
1548
1549         if (error == 0) {
1550                 if (fancy) {
1551                         printf("%ld", (long)ret);
1552                         if (ret < 0 || ret > 9)
1553                                 printf("/%#lx", (long)ret);
1554                 } else {
1555                         if (decimal)
1556                                 printf("%ld", (long)ret);
1557                         else
1558                                 printf("%#lx", (long)ret);
1559                 }
1560         } else if (error == ERESTART)
1561                 printf("RESTART");
1562         else if (error == EJUSTRETURN)
1563                 printf("JUSTRETURN");
1564         else {
1565                 if (ktr->ktr_error <= ELAST + 1)
1566                         error = abs(bsd_to_linux_errno[ktr->ktr_error]);
1567                 else
1568                         error = 999;
1569                 printf("-1 errno %d", error);
1570                 if (fancy)
1571                         printf(" %s", strerror(ktr->ktr_error));
1572         }
1573         putchar('\n');
1574 }
1575 #endif
1576
1577 void
1578 usage(void)
1579 {
1580         fprintf(stderr, "usage: kdump [-dEnlHRrsTA] [-f trfile] "
1581             "[-m maxdata] [-p pid] [-t trstr]\n");
1582         exit(1);
1583 }