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