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