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