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