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