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