xref: /freebsd/usr.bin/kdump/kdump.c (revision f856af0466c076beef4ea9b15d088e1119a945b8)
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/ptrace.h>
61 #include <sys/socket.h>
62 #include <err.h>
63 #include <locale.h>
64 #include <stdio.h>
65 #include <stdlib.h>
66 #include <string.h>
67 #include <unistd.h>
68 #include <vis.h>
69 #include "ktrace.h"
70 #include "kdump_subr.h"
71 
72 int fread_tail(void *, int, int);
73 void dumpheader(struct ktr_header *);
74 void ktrsyscall(struct ktr_syscall *);
75 void ktrsysret(struct ktr_sysret *);
76 void ktrnamei(char *, int);
77 void hexdump(char *, int, int);
78 void visdump(char *, int, int);
79 void ktrgenio(struct ktr_genio *, int);
80 void ktrpsig(struct ktr_psig *);
81 void ktrcsw(struct ktr_csw *);
82 void ktruser(int, unsigned char *);
83 void usage(void);
84 const char *ioctlname(u_long);
85 
86 int timestamp, decimal, fancy = 1, suppressdata, tail, threads, maxdata;
87 const char *tracefile = DEF_TRACEFILE;
88 struct ktr_header ktr_header;
89 
90 #define eqs(s1, s2)	(strcmp((s1), (s2)) == 0)
91 
92 int
93 main(int argc, char *argv[])
94 {
95 	int ch, ktrlen, size;
96 	void *m;
97 	int trpoints = ALL_POINTS;
98 	int drop_logged;
99 	pid_t pid = 0;
100 
101 	(void) setlocale(LC_CTYPE, "");
102 
103 	while ((ch = getopt(argc,argv,"f:dElm:np:HRsTt:")) != -1)
104 		switch((char)ch) {
105 		case 'f':
106 			tracefile = optarg;
107 			break;
108 		case 'd':
109 			decimal = 1;
110 			break;
111 		case 'l':
112 			tail = 1;
113 			break;
114 		case 'm':
115 			maxdata = atoi(optarg);
116 			break;
117 		case 'n':
118 			fancy = 0;
119 			break;
120 		case 'p':
121 			pid = atoi(optarg);
122 			break;
123 		case 's':
124 			suppressdata = 1;
125 			break;
126 		case 'E':
127 			timestamp = 3;	/* elapsed timestamp */
128 			break;
129 		case 'H':
130 			threads = 1;
131 			break;
132 		case 'R':
133 			timestamp = 2;	/* relative timestamp */
134 			break;
135 		case 'T':
136 			timestamp = 1;
137 			break;
138 		case 't':
139 			trpoints = getpoints(optarg);
140 			if (trpoints < 0)
141 				errx(1, "unknown trace point in %s", optarg);
142 			break;
143 		default:
144 			usage();
145 		}
146 
147 	if (argc > optind)
148 		usage();
149 
150 	m = (void *)malloc(size = 1025);
151 	if (m == NULL)
152 		errx(1, "%s", strerror(ENOMEM));
153 	if (!freopen(tracefile, "r", stdin))
154 		err(1, "%s", tracefile);
155 	drop_logged = 0;
156 	while (fread_tail(&ktr_header, sizeof(struct ktr_header), 1)) {
157 		if (ktr_header.ktr_type & KTR_DROP) {
158 			ktr_header.ktr_type &= ~KTR_DROP;
159 			if (!drop_logged && threads) {
160 				(void)printf("%6d %6d %-8.*s Events dropped.\n",
161 				    ktr_header.ktr_pid, ktr_header.ktr_tid >
162 				    0 ? ktr_header.ktr_tid : 0, MAXCOMLEN,
163 				    ktr_header.ktr_comm);
164 				drop_logged = 1;
165 			} else if (!drop_logged) {
166 				(void)printf("%6d %-8.*s Events dropped.\n",
167 				    ktr_header.ktr_pid, MAXCOMLEN,
168 				    ktr_header.ktr_comm);
169 				drop_logged = 1;
170 			}
171 		}
172 		if (trpoints & (1<<ktr_header.ktr_type))
173 			if (pid == 0 || ktr_header.ktr_pid == pid)
174 				dumpheader(&ktr_header);
175 		if ((ktrlen = ktr_header.ktr_len) < 0)
176 			errx(1, "bogus length 0x%x", ktrlen);
177 		if (ktrlen > size) {
178 			m = (void *)realloc(m, ktrlen+1);
179 			if (m == NULL)
180 				errx(1, "%s", strerror(ENOMEM));
181 			size = ktrlen;
182 		}
183 		if (ktrlen && fread_tail(m, ktrlen, 1) == 0)
184 			errx(1, "data too short");
185 		if (pid && ktr_header.ktr_pid != pid)
186 			continue;
187 		if ((trpoints & (1<<ktr_header.ktr_type)) == 0)
188 			continue;
189 		drop_logged = 0;
190 		switch (ktr_header.ktr_type) {
191 		case KTR_SYSCALL:
192 			ktrsyscall((struct ktr_syscall *)m);
193 			break;
194 		case KTR_SYSRET:
195 			ktrsysret((struct ktr_sysret *)m);
196 			break;
197 		case KTR_NAMEI:
198 			ktrnamei(m, ktrlen);
199 			break;
200 		case KTR_GENIO:
201 			ktrgenio((struct ktr_genio *)m, ktrlen);
202 			break;
203 		case KTR_PSIG:
204 			ktrpsig((struct ktr_psig *)m);
205 			break;
206 		case KTR_CSW:
207 			ktrcsw((struct ktr_csw *)m);
208 			break;
209 		case KTR_USER:
210 			ktruser(ktrlen, m);
211 			break;
212 		default:
213 			printf("\n");
214 			break;
215 		}
216 		if (tail)
217 			(void)fflush(stdout);
218 	}
219 	return 0;
220 }
221 
222 int
223 fread_tail(void *buf, int size, int num)
224 {
225 	int i;
226 
227 	while ((i = fread(buf, size, num, stdin)) == 0 && tail) {
228 		(void)sleep(1);
229 		clearerr(stdin);
230 	}
231 	return (i);
232 }
233 
234 void
235 dumpheader(struct ktr_header *kth)
236 {
237 	static char unknown[64];
238 	static struct timeval prevtime, temp;
239 	const char *type;
240 
241 	switch (kth->ktr_type) {
242 	case KTR_SYSCALL:
243 		type = "CALL";
244 		break;
245 	case KTR_SYSRET:
246 		type = "RET ";
247 		break;
248 	case KTR_NAMEI:
249 		type = "NAMI";
250 		break;
251 	case KTR_GENIO:
252 		type = "GIO ";
253 		break;
254 	case KTR_PSIG:
255 		type = "PSIG";
256 		break;
257 	case KTR_CSW:
258 		type = "CSW";
259 		break;
260 	case KTR_USER:
261 		type = "USER";
262 		break;
263 	default:
264 		(void)sprintf(unknown, "UNKNOWN(%d)", kth->ktr_type);
265 		type = unknown;
266 	}
267 
268 	/*
269 	 * The ktr_tid field was previously the ktr_buffer field, which held
270 	 * the kernel pointer value for the buffer associated with data
271 	 * following the record header.  It now holds a threadid, but only
272 	 * for trace files after the change.  Older trace files still contain
273 	 * kernel pointers.  Detect this and suppress the results by printing
274 	 * negative tid's as 0.
275 	 */
276 	if (threads)
277 		(void)printf("%6d %6d %-8.*s ", kth->ktr_pid, kth->ktr_tid >
278 		    0 ? kth->ktr_tid : 0, MAXCOMLEN, kth->ktr_comm);
279 	else
280 		(void)printf("%6d %-8.*s ", kth->ktr_pid, MAXCOMLEN,
281 		    kth->ktr_comm);
282 	if (timestamp) {
283 		if (timestamp == 3) {
284 			if (prevtime.tv_sec == 0)
285 				prevtime = kth->ktr_time;
286 			timevalsub(&kth->ktr_time, &prevtime);
287 		}
288 		if (timestamp == 2) {
289 			temp = kth->ktr_time;
290 			timevalsub(&kth->ktr_time, &prevtime);
291 			prevtime = temp;
292 		}
293 		(void)printf("%ld.%06ld ",
294 		    kth->ktr_time.tv_sec, kth->ktr_time.tv_usec);
295 	}
296 	(void)printf("%s  ", type);
297 }
298 
299 #include <sys/syscall.h>
300 #define KTRACE
301 #include <sys/kern/syscalls.c>
302 #undef KTRACE
303 int nsyscalls = sizeof (syscallnames) / sizeof (syscallnames[0]);
304 
305 static const char *ptrace_ops[] = {
306 	"PT_TRACE_ME",	"PT_READ_I",	"PT_READ_D",	"PT_READ_U",
307 	"PT_WRITE_I",	"PT_WRITE_D",	"PT_WRITE_U",	"PT_CONTINUE",
308 	"PT_KILL",	"PT_STEP",	"PT_ATTACH",	"PT_DETACH",
309 };
310 
311 void
312 ktrsyscall(struct ktr_syscall *ktr)
313 {
314 	int narg = ktr->ktr_narg;
315 	register_t *ip;
316 
317 	if (ktr->ktr_code >= nsyscalls || ktr->ktr_code < 0)
318 		(void)printf("[%d]", ktr->ktr_code);
319 	else
320 		(void)printf("%s", syscallnames[ktr->ktr_code]);
321 	ip = &ktr->ktr_args[0];
322 	if (narg) {
323 		char c = '(';
324 		if (fancy) {
325 
326 #define print_number(i,n,c) do {                      \
327 	if (decimal)                                  \
328 		(void)printf("%c%ld", c, (long)*i);   \
329 	else                                          \
330 		(void)printf("%c%#lx", c, (long)*i);  \
331 	i++;                                          \
332 	n--;                                          \
333 	c = ',';                                      \
334 	} while (0);
335 
336 			if (ktr->ktr_code == SYS_ioctl) {
337 				const char *cp;
338 				print_number(ip,narg,c);
339 				if ((cp = ioctlname(*ip)) != NULL)
340 					(void)printf(",%s", cp);
341 				else {
342 					if (decimal)
343 						(void)printf(",%ld", (long)*ip);
344 					else
345 						(void)printf(",%#lx ", (long)*ip);
346 				}
347 				c = ',';
348 				ip++;
349 				narg--;
350 			} else if (ktr->ktr_code == SYS_ptrace) {
351 				if ((size_t)*ip < sizeof(ptrace_ops) /
352 				    sizeof(ptrace_ops[0]) && *ip >= 0)
353 					(void)printf("(%s", ptrace_ops[*ip]);
354 #ifdef PT_GETREGS
355 				else if (*ip == PT_GETREGS)
356 					(void)printf("(%s", "PT_GETREGS");
357 #endif
358 #ifdef PT_SETREGS
359 				else if (*ip == PT_SETREGS)
360 					(void)printf("(%s", "PT_SETREGS");
361 #endif
362 #ifdef PT_GETFPREGS
363 				else if (*ip == PT_GETFPREGS)
364 					(void)printf("(%s", "PT_GETFPREGS");
365 #endif
366 #ifdef PT_SETFPREGS
367 				else if (*ip == PT_SETFPREGS)
368 					(void)printf("(%s", "PT_SETFPREGS");
369 #endif
370 #ifdef PT_GETDBREGS
371 				else if (*ip == PT_GETDBREGS)
372 					(void)printf("(%s", "PT_GETDBREGS");
373 #endif
374 #ifdef PT_SETDBREGS
375 				else if (*ip == PT_SETDBREGS)
376 					(void)printf("(%s", "PT_SETDBREGS");
377 #endif
378 				else
379 					(void)printf("(%ld", (long)*ip);
380 				c = ',';
381 				ip++;
382 				narg--;
383 			} else if (ktr->ktr_code == SYS_access ||
384 				   ktr->ktr_code == SYS_eaccess) {
385 				print_number(ip,narg,c);
386 				(void)putchar(',');
387 				accessmodename ((int)*ip);
388 				ip++;
389 				narg--;
390 			} else if (ktr->ktr_code == SYS_open) {
391 				int	flags;
392 				int	mode;
393 				print_number(ip,narg,c);
394 				flags = *ip;
395 				mode = *++ip;
396 				(void)putchar(',');
397 				flagsandmodename (flags, mode, decimal);
398 				ip++;
399 				narg-=2;
400 			} else if (ktr->ktr_code == SYS_wait4) {
401 				print_number(ip,narg,c);
402 				print_number(ip,narg,c);
403 				(void)putchar(',');
404 				wait4optname ((int)*ip);
405 				ip++;
406 				narg--;
407 			} else if (ktr->ktr_code == SYS_chmod ||
408 				   ktr->ktr_code == SYS_fchmod ||
409 				   ktr->ktr_code == SYS_lchmod) {
410 				print_number(ip,narg,c);
411 				(void)putchar(',');
412 				modename ((int)*ip);
413 				ip++;
414 				narg--;
415 			} else if (ktr->ktr_code == SYS_mknod) {
416 				print_number(ip,narg,c);
417 				(void)putchar(',');
418 				modename ((int)*ip);
419 				ip++;
420 				narg--;
421 			} else if (ktr->ktr_code == SYS_getfsstat) {
422 				print_number(ip,narg,c);
423 				print_number(ip,narg,c);
424 				(void)putchar(',');
425 				getfsstatflagsname ((int)*ip);
426 				ip++;
427 				narg--;
428 			} else if (ktr->ktr_code == SYS_mount) {
429 				print_number(ip,narg,c);
430 				print_number(ip,narg,c);
431 				(void)putchar(',');
432 				mountflagsname ((int)*ip);
433 				ip++;
434 				narg--;
435 			} else if (ktr->ktr_code == SYS_unmount) {
436 				print_number(ip,narg,c);
437 				(void)putchar(',');
438 				mountflagsname ((int)*ip);
439 				ip++;
440 				narg--;
441 			} else if (ktr->ktr_code == SYS_recvmsg ||
442 				   ktr->ktr_code == SYS_sendmsg) {
443 				print_number(ip,narg,c);
444 				print_number(ip,narg,c);
445 				(void)putchar(',');
446 				sendrecvflagsname ((int)*ip);
447 				ip++;
448 				narg--;
449 			} else if (ktr->ktr_code == SYS_recvfrom ||
450 				   ktr->ktr_code == SYS_sendto) {
451 				print_number(ip,narg,c);
452 				print_number(ip,narg,c);
453 				print_number(ip,narg,c);
454 				(void)putchar(',');
455 				sendrecvflagsname ((int)*ip);
456 				ip++;
457 				narg--;
458 			} else if (ktr->ktr_code == SYS_chflags ||
459 				   ktr->ktr_code == SYS_fchflags ||
460 				   ktr->ktr_code == SYS_lchflags) {
461 				print_number(ip,narg,c);
462 				(void)putchar(',');
463 				modename((int)*ip);
464 				ip++;
465 				narg--;
466 			} else if (ktr->ktr_code == SYS_kill) {
467 				print_number(ip,narg,c);
468 				(void)putchar(',');
469 				signame((int)*ip);
470 				ip++;
471 				narg--;
472 			} else if (ktr->ktr_code == SYS_reboot) {
473 				(void)putchar('(');
474 				rebootoptname((int)*ip);
475 				ip++;
476 				narg--;
477 			} else if (ktr->ktr_code == SYS_umask) {
478 				(void)putchar('(');
479 				modename((int)*ip);
480 				ip++;
481 				narg--;
482 			} else if (ktr->ktr_code == SYS_msync) {
483 				print_number(ip,narg,c);
484 				print_number(ip,narg,c);
485 				(void)putchar(',');
486 				msyncflagsname((int)*ip);
487 				ip++;
488 				narg--;
489 			} else if (ktr->ktr_code == SYS_mmap) {
490 				print_number(ip,narg,c);
491 				print_number(ip,narg,c);
492 				(void)putchar(',');
493 				mmapprotname ((int)*ip);
494 				(void)putchar(',');
495 				ip++;
496 				narg--;
497 				mmapflagsname ((int)*ip);
498 				ip++;
499 				narg--;
500 			} else if (ktr->ktr_code == SYS_mprotect) {
501 				print_number(ip,narg,c);
502 				print_number(ip,narg,c);
503 				(void)putchar(',');
504 				mmapprotname ((int)*ip);
505 				ip++;
506 				narg--;
507 			} else if (ktr->ktr_code == SYS_madvise) {
508 				print_number(ip,narg,c);
509 				print_number(ip,narg,c);
510 				(void)putchar(',');
511 				madvisebehavname((int)*ip);
512 				ip++;
513 				narg--;
514 			} else if (ktr->ktr_code == SYS_setpriority) {
515 				print_number(ip,narg,c);
516 				print_number(ip,narg,c);
517 				(void)putchar(',');
518 				prioname((int)*ip);
519 				ip++;
520 				narg--;
521 			} else if (ktr->ktr_code == SYS_fcntl) {
522 				int cmd;
523 				int arg;
524 				print_number(ip,narg,c);
525 				cmd = *ip;
526 				arg = *++ip;
527 				(void)putchar(',');
528 				fcntlcmdname(cmd, arg, decimal);
529 				ip++;
530 				narg-=2;
531 			} else if (ktr->ktr_code == SYS_socket) {
532 				int sockdomain;
533 				(void)putchar('(');
534 				sockdomain=(int)*ip;
535 				sockdomainname(sockdomain);
536 				ip++;
537 				narg--;
538 				(void)putchar(',');
539 				socktypename((int)*ip);
540 				ip++;
541 				narg--;
542 				if (sockdomain == PF_INET ||
543 				    sockdomain == PF_INET6) {
544 					(void)putchar(',');
545 					sockipprotoname((int)*ip);
546 					ip++;
547 					narg--;
548 				}
549 				c = ',';
550 			} else if (ktr->ktr_code == SYS_setsockopt ||
551 				   ktr->ktr_code == SYS_getsockopt) {
552 				print_number(ip,narg,c);
553 				(void)putchar(',');
554 				sockoptlevelname((int)*ip, decimal);
555 				ip++;
556 				narg--;
557 				(void)putchar(',');
558 				sockoptname((int)*ip);
559 				ip++;
560 				narg--;
561 			} else if (ktr->ktr_code == SYS_lseek) {
562 				print_number(ip,narg,c);
563 				/* Hidden 'pad' argument, not in lseek(2) */
564 				print_number(ip,narg,c);
565 				print_number(ip,narg,c);
566 				(void)putchar(',');
567 				whencename ((int)*ip);
568 				ip++;
569 				narg--;
570 			} else if (ktr->ktr_code == SYS_flock) {
571 				print_number(ip,narg,c);
572 				(void)putchar(',');
573 				flockname((int)*ip);
574 				ip++;
575 				narg--;
576 			} else if (ktr->ktr_code == SYS_mkfifo ||
577 				   ktr->ktr_code == SYS_mkdir) {
578 				print_number(ip,narg,c);
579 				(void)putchar(',');
580 				modename((int)*ip);
581 				ip++;
582 				narg--;
583 			} else if (ktr->ktr_code == SYS_shutdown) {
584 				print_number(ip,narg,c);
585 				(void)putchar(',');
586 				shutdownhowname((int)*ip);
587 				ip++;
588 				narg--;
589 			} else if (ktr->ktr_code == SYS_socketpair) {
590 				(void)putchar('(');
591 				sockdomainname((int)*ip);
592 				ip++;
593 				narg--;
594 				(void)putchar(',');
595 				socktypename((int)*ip);
596 				ip++;
597 				narg--;
598 				c = ',';
599 			} else if (ktr->ktr_code == SYS_getrlimit ||
600 				   ktr->ktr_code == SYS_setrlimit) {
601 				(void)putchar('(');
602 				rlimitname((int)*ip);
603 				ip++;
604 				narg--;
605 				c = ',';
606 			} else if (ktr->ktr_code == SYS_quotactl) {
607 				print_number(ip,narg,c);
608 				quotactlname((int)*ip);
609 				ip++;
610 				narg--;
611 				c = ',';
612 			} else if (ktr->ktr_code == SYS_nfssvc) {
613 				(void)putchar('(');
614 				nfssvcname((int)*ip);
615 				ip++;
616 				narg--;
617 				c = ',';
618 			} else if (ktr->ktr_code == SYS_rtprio) {
619 				(void)putchar('(');
620 				rtprioname((int)*ip);
621 				ip++;
622 				narg--;
623 				c = ',';
624 			} else if (ktr->ktr_code == SYS___semctl) {
625 				print_number(ip,narg,c);
626 				print_number(ip,narg,c);
627 				semctlname((int)*ip);
628 				ip++;
629 				narg--;
630 			} else if (ktr->ktr_code == SYS_semget) {
631 				print_number(ip,narg,c);
632 				print_number(ip,narg,c);
633 				semgetname((int)*ip);
634 				ip++;
635 				narg--;
636 			} else if (ktr->ktr_code == SYS_msgctl) {
637 				print_number(ip,narg,c);
638 				shmctlname((int)*ip);
639 				ip++;
640 				narg--;
641 			} else if (ktr->ktr_code == SYS_shmat) {
642 				print_number(ip,narg,c);
643 				print_number(ip,narg,c);
644 				shmatname((int)*ip);
645 				ip++;
646 				narg--;
647 			} else if (ktr->ktr_code == SYS_shmctl) {
648 				print_number(ip,narg,c);
649 				shmctlname((int)*ip);
650 				ip++;
651 				narg--;
652 			} else if (ktr->ktr_code == SYS_minherit) {
653 				print_number(ip,narg,c);
654 				print_number(ip,narg,c);
655 				minheritname((int)*ip);
656 				ip++;
657 				narg--;
658 			} else if (ktr->ktr_code == SYS_rfork) {
659 				(void)putchar('(');
660 				rforkname((int)*ip);
661 				ip++;
662 				narg--;
663 				c = ',';
664 			} else if (ktr->ktr_code == SYS_lio_listio) {
665 				(void)putchar('(');
666 				lio_listioname((int)*ip);
667 				ip++;
668 				narg--;
669 				c = ',';
670 			} else if (ktr->ktr_code == SYS_mlockall) {
671 				(void)putchar('(');
672 				mlockallname((int)*ip);
673 				ip++;
674 				narg--;
675 			} else if (ktr->ktr_code == SYS_sched_setscheduler) {
676 				print_number(ip,narg,c);
677 				schedpolicyname((int)*ip);
678 				ip++;
679 				narg--;
680 			} else if (ktr->ktr_code == SYS_sched_get_priority_max ||
681 				   ktr->ktr_code == SYS_sched_get_priority_min) {
682 				(void)putchar('(');
683 				schedpolicyname((int)*ip);
684 				ip++;
685 				narg--;
686 			} else if (ktr->ktr_code == SYS_sendfile) {
687 				print_number(ip,narg,c);
688 				print_number(ip,narg,c);
689 				print_number(ip,narg,c);
690 				print_number(ip,narg,c);
691 				print_number(ip,narg,c);
692 				print_number(ip,narg,c);
693 				sendfileflagsname((int)*ip);
694 				ip++;
695 				narg--;
696 			} else if (ktr->ktr_code == SYS_kldsym) {
697 				print_number(ip,narg,c);
698 				kldsymcmdname((int)*ip);
699 				ip++;
700 				narg--;
701 			} else if (ktr->ktr_code == SYS_sigprocmask) {
702 				(void)putchar('(');
703 				sigprocmaskhowname((int)*ip);
704 				ip++;
705 				narg--;
706 				c = ',';
707 			} else if (ktr->ktr_code == SYS___acl_get_file ||
708 				   ktr->ktr_code == SYS___acl_set_file ||
709 				   ktr->ktr_code == SYS___acl_get_fd ||
710 				   ktr->ktr_code == SYS___acl_set_fd ||
711 				   ktr->ktr_code == SYS___acl_delete_file ||
712 				   ktr->ktr_code == SYS___acl_delete_fd ||
713 				   ktr->ktr_code == SYS___acl_aclcheck_file ||
714 				   ktr->ktr_code == SYS___acl_aclcheck_fd ||
715 				   ktr->ktr_code == SYS___acl_get_link ||
716 				   ktr->ktr_code == SYS___acl_set_link ||
717 				   ktr->ktr_code == SYS___acl_delete_link ||
718 				   ktr->ktr_code == SYS___acl_aclcheck_link) {
719 				print_number(ip,narg,c);
720 				acltypename((int)*ip);
721 				ip++;
722 				narg--;
723 			} else if (ktr->ktr_code == SYS_sigaction) {
724 				(void)putchar('(');
725 				signame((int)*ip);
726 				ip++;
727 				narg--;
728 				c = ',';
729 			} else if (ktr->ktr_code == SYS_extattrctl) {
730 				print_number(ip,narg,c);
731 				extattrctlname((int)*ip);
732 				ip++;
733 				narg--;
734 			} else if (ktr->ktr_code == SYS_nmount) {
735 				print_number(ip,narg,c);
736 				print_number(ip,narg,c);
737 				(void)putchar(',');
738 				mountflagsname ((int)*ip);
739 				ip++;
740 				narg--;
741 			} else if (ktr->ktr_code == SYS_kse_thr_interrupt) {
742 				print_number(ip,narg,c);
743 				(void)putchar(',');
744 				ksethrcmdname ((int)*ip);
745 				ip++;
746 				narg--;
747 			} else if (ktr->ktr_code == SYS_thr_create) {
748 				print_number(ip,narg,c);
749 				print_number(ip,narg,c);
750 				(void)putchar(',');
751 				thrcreateflagsname ((int)*ip);
752 				ip++;
753 				narg--;
754 			} else if (ktr->ktr_code == SYS_thr_kill) {
755 				print_number(ip,narg,c);
756 				(void)putchar(',');
757 				signame ((int)*ip);
758 				ip++;
759 				narg--;
760 			} else if (ktr->ktr_code == SYS_kldunloadf) {
761 				print_number(ip,narg,c);
762 				(void)putchar(',');
763 				kldunloadfflagsname ((int)*ip);
764 				ip++;
765 				narg--;
766 			}
767 		}
768 		while (narg) {
769 			print_number(ip,narg,c);
770 		}
771 		(void)putchar(')');
772 	}
773 	(void)putchar('\n');
774 }
775 
776 void
777 ktrsysret(struct ktr_sysret *ktr)
778 {
779 	register_t ret = ktr->ktr_retval;
780 	int error = ktr->ktr_error;
781 	int code = ktr->ktr_code;
782 
783 	if (code >= nsyscalls || code < 0)
784 		(void)printf("[%d] ", code);
785 	else
786 		(void)printf("%s ", syscallnames[code]);
787 
788 	if (error == 0) {
789 		if (fancy) {
790 			(void)printf("%d", ret);
791 			if (ret < 0 || ret > 9)
792 				(void)printf("/%#lx", (long)ret);
793 		} else {
794 			if (decimal)
795 				(void)printf("%ld", (long)ret);
796 			else
797 				(void)printf("%#lx", (long)ret);
798 		}
799 	} else if (error == ERESTART)
800 		(void)printf("RESTART");
801 	else if (error == EJUSTRETURN)
802 		(void)printf("JUSTRETURN");
803 	else {
804 		(void)printf("-1 errno %d", ktr->ktr_error);
805 		if (fancy)
806 			(void)printf(" %s", strerror(ktr->ktr_error));
807 	}
808 	(void)putchar('\n');
809 }
810 
811 void
812 ktrnamei(char *cp, int len)
813 {
814 	(void)printf("\"%.*s\"\n", len, cp);
815 }
816 
817 void
818 hexdump(char *p, int len, int screenwidth)
819 {
820 	int n, i;
821 	int width;
822 
823 	width = 0;
824 	do {
825 		width += 2;
826 		i = 13;			/* base offset */
827 		i += (width / 2) + 1;	/* spaces every second byte */
828 		i += (width * 2);	/* width of bytes */
829 		i += 3;			/* "  |" */
830 		i += width;		/* each byte */
831 		i += 1;			/* "|" */
832 	} while (i < screenwidth);
833 	width -= 2;
834 
835 	for (n = 0; n < len; n += width) {
836 		for (i = n; i < n + width; i++) {
837 			if ((i % width) == 0) {	/* beginning of line */
838 				printf("       0x%04x", i);
839 			}
840 			if ((i % 2) == 0) {
841 				printf(" ");
842 			}
843 			if (i < len)
844 				printf("%02x", p[i] & 0xff);
845 			else
846 				printf("  ");
847 		}
848 		printf("  |");
849 		for (i = n; i < n + width; i++) {
850 			if (i >= len)
851 				break;
852 			if (p[i] >= ' ' && p[i] <= '~')
853 				printf("%c", p[i]);
854 			else
855 				printf(".");
856 		}
857 		printf("|\n");
858 	}
859 	if ((i % width) != 0)
860 		printf("\n");
861 }
862 
863 void
864 visdump(char *dp, int datalen, int screenwidth)
865 {
866 	int col = 0;
867 	char *cp;
868 	int width;
869 	char visbuf[5];
870 
871 	(void)printf("       \"");
872 	col = 8;
873 	for (;datalen > 0; datalen--, dp++) {
874 		(void) vis(visbuf, *dp, VIS_CSTYLE, *(dp+1));
875 		cp = visbuf;
876 		/*
877 		 * Keep track of printables and
878 		 * space chars (like fold(1)).
879 		 */
880 		if (col == 0) {
881 			(void)putchar('\t');
882 			col = 8;
883 		}
884 		switch(*cp) {
885 		case '\n':
886 			col = 0;
887 			(void)putchar('\n');
888 			continue;
889 		case '\t':
890 			width = 8 - (col&07);
891 			break;
892 		default:
893 			width = strlen(cp);
894 		}
895 		if (col + width > (screenwidth-2)) {
896 			(void)printf("\\\n\t");
897 			col = 8;
898 		}
899 		col += width;
900 		do {
901 			(void)putchar(*cp++);
902 		} while (*cp);
903 	}
904 	if (col == 0)
905 		(void)printf("       ");
906 	(void)printf("\"\n");
907 }
908 
909 void
910 ktrgenio(struct ktr_genio *ktr, int len)
911 {
912 	int datalen = len - sizeof (struct ktr_genio);
913 	char *dp = (char *)ktr + sizeof (struct ktr_genio);
914 	static int screenwidth = 0;
915 	int i, binary;
916 
917 	if (screenwidth == 0) {
918 		struct winsize ws;
919 
920 		if (fancy && ioctl(fileno(stderr), TIOCGWINSZ, &ws) != -1 &&
921 		    ws.ws_col > 8)
922 			screenwidth = ws.ws_col;
923 		else
924 			screenwidth = 80;
925 	}
926 	printf("fd %d %s %d byte%s\n", ktr->ktr_fd,
927 		ktr->ktr_rw == UIO_READ ? "read" : "wrote", datalen,
928 		datalen == 1 ? "" : "s");
929 	if (suppressdata)
930 		return;
931 	if (maxdata && datalen > maxdata)
932 		datalen = maxdata;
933 
934 	for (i = 0, binary = 0; i < datalen && binary == 0; i++)  {
935 		if (dp[i] >= 32 && dp[i] < 127)
936 			continue;
937 		if (dp[i] == 10 || dp[i] == 13 || dp[i] == 0 || dp[i] == 9)
938 			continue;
939 		binary = 1;
940 	}
941 	if (binary)
942 		hexdump(dp, datalen, screenwidth);
943 	else
944 		visdump(dp, datalen, screenwidth);
945 }
946 
947 const char *signames[] = {
948 	"NULL", "HUP", "INT", "QUIT", "ILL", "TRAP", "IOT",	/*  1 - 6  */
949 	"EMT", "FPE", "KILL", "BUS", "SEGV", "SYS",		/*  7 - 12 */
950 	"PIPE", "ALRM",  "TERM", "URG", "STOP", "TSTP",		/* 13 - 18 */
951 	"CONT", "CHLD", "TTIN", "TTOU", "IO", "XCPU",		/* 19 - 24 */
952 	"XFSZ", "VTALRM", "PROF", "WINCH", "29", "USR1",	/* 25 - 30 */
953 	"USR2", NULL,						/* 31 - 32 */
954 };
955 
956 void
957 ktrpsig(struct ktr_psig *psig)
958 {
959 	if (psig->signo > 0 && psig->signo < NSIG)
960 		(void)printf("SIG%s ", signames[psig->signo]);
961 	else
962 		(void)printf("SIG %d ", psig->signo);
963 	if (psig->action == SIG_DFL)
964 		(void)printf("SIG_DFL\n");
965 	else {
966 		(void)printf("caught handler=0x%lx mask=0x%x code=0x%x\n",
967 		    (u_long)psig->action, psig->mask.__bits[0], psig->code);
968 	}
969 }
970 
971 void
972 ktrcsw(struct ktr_csw *cs)
973 {
974 	(void)printf("%s %s\n", cs->out ? "stop" : "resume",
975 		cs->user ? "user" : "kernel");
976 }
977 
978 struct utrace_malloc {
979 	void *p;
980 	size_t s;
981 	void *r;
982 };
983 
984 void
985 ktruser_malloc(int len, unsigned char *p)
986 {
987 	struct utrace_malloc *ut = (struct utrace_malloc *)p;
988 
989 	if (ut->p == NULL) {
990 		if (ut->s == 0 && ut->r == NULL)
991 			printf("malloc_init()\n");
992 		else
993 			printf("%p = malloc(%zu)\n", ut->r, ut->s);
994 	} else {
995 		if (ut->s == 0)
996 			printf("free(%p)\n", ut->p);
997 		else
998 			printf("%p = realloc(%p, %zu)\n", ut->r, ut->p, ut->s);
999 	}
1000 }
1001 
1002 void
1003 ktruser(int len, unsigned char *p)
1004 {
1005 
1006 	if (len == sizeof(struct utrace_malloc)) {
1007 		ktruser_malloc(len, p);
1008 		return;
1009 	}
1010 
1011 	(void)printf("%d ", len);
1012 	while (len--)
1013 		if (decimal)
1014 			(void)printf(" %d", *p++);
1015 		else
1016 			(void)printf(" %02x", *p++);
1017 	(void)printf("\n");
1018 }
1019 
1020 void
1021 usage(void)
1022 {
1023 	(void)fprintf(stderr,
1024   "usage: kdump [-dEnlHRsT] [-f trfile] [-m maxdata] [-p pid] [-t [cnisuw]]\n");
1025 	exit(1);
1026 }
1027