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