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