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