xref: /openbsd/usr.bin/kdump/kdump.c (revision 17df1aa7)
1 /*	$OpenBSD: kdump.c,v 1.41 2009/10/27 23:59:39 deraadt Exp $	*/
2 
3 /*-
4  * Copyright (c) 1988, 1993
5  *	The Regents of the University of California.  All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  * 3. Neither the name of the University nor the names of its contributors
16  *    may be used to endorse or promote products derived from this software
17  *    without specific prior written permission.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
20  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
23  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29  * SUCH DAMAGE.
30  */
31 
32 #include <sys/param.h>
33 #include <sys/time.h>
34 #include <sys/uio.h>
35 #include <sys/ktrace.h>
36 #include <sys/ioctl.h>
37 #include <sys/ptrace.h>
38 #include <sys/sysctl.h>
39 #define _KERNEL
40 #include <sys/errno.h>
41 #undef _KERNEL
42 
43 #include <ctype.h>
44 #include <err.h>
45 #include <signal.h>
46 #include <stdio.h>
47 #include <stdlib.h>
48 #include <string.h>
49 #include <unistd.h>
50 #include <vis.h>
51 
52 #include "ktrace.h"
53 #include "kdump.h"
54 #include "extern.h"
55 
56 int timestamp, decimal, iohex, fancy = 1, tail, maxdata;
57 char *tracefile = DEF_TRACEFILE;
58 struct ktr_header ktr_header;
59 pid_t pid = -1;
60 
61 #define eqs(s1, s2)	(strcmp((s1), (s2)) == 0)
62 
63 #include <sys/syscall.h>
64 
65 #include <compat/bsdos/bsdos_syscall.h>
66 #include <compat/freebsd/freebsd_syscall.h>
67 #if defined(__hppa__) || defined(__m68k__)
68 #include <compat/hpux/hpux_syscall.h>
69 #endif
70 #include <compat/ibcs2/ibcs2_syscall.h>
71 #include <compat/linux/linux_syscall.h>
72 #include <compat/osf1/osf1_syscall.h>
73 #include <compat/sunos/sunos_syscall.h>
74 #include <compat/svr4/svr4_syscall.h>
75 #include <compat/ultrix/ultrix_syscall.h>
76 
77 #define KTRACE
78 #define PTRACE
79 #define NFSCLIENT
80 #define NFSSERVER
81 #define SYSVSEM
82 #define SYSVMSG
83 #define SYSVSHM
84 #define LFS
85 #define RTHREADS
86 #include <kern/syscalls.c>
87 
88 #include <compat/bsdos/bsdos_syscalls.c>
89 #include <compat/freebsd/freebsd_syscalls.c>
90 #if defined(__hppa__) || defined(__m68k__)
91 #include <compat/hpux/hpux_syscalls.c>
92 #endif
93 #include <compat/ibcs2/ibcs2_syscalls.c>
94 #include <compat/linux/linux_syscalls.c>
95 #include <compat/osf1/osf1_syscalls.c>
96 #include <compat/sunos/sunos_syscalls.c>
97 #include <compat/svr4/svr4_syscalls.c>
98 #include <compat/ultrix/ultrix_syscalls.c>
99 #undef KTRACE
100 #undef PTRACE
101 #undef NFSCLIENT
102 #undef NFSSERVER
103 #undef SYSVSEM
104 #undef SYSVMSG
105 #undef SYSVSHM
106 #undef LFS
107 #undef RTHREADS
108 
109 struct emulation {
110 	char *name;		/* Emulation name */
111 	char **sysnames;	/* Array of system call names */
112 	int  nsysnames;		/* Number of */
113 };
114 
115 static struct emulation emulations[] = {
116 	{ "native",	syscallnames,		SYS_MAXSYSCALL },
117 #if defined(__hppa__) || defined(__m68k__)
118 	{ "hpux",	hpux_syscallnames,	HPUX_SYS_MAXSYSCALL },
119 #endif
120 	{ "ibcs2",	ibcs2_syscallnames,	IBCS2_SYS_MAXSYSCALL },
121 	{ "linux",	linux_syscallnames,	LINUX_SYS_MAXSYSCALL },
122 	{ "osf1",	osf1_syscallnames,	OSF1_SYS_MAXSYSCALL },
123 	{ "sunos",	sunos_syscallnames,	SUNOS_SYS_MAXSYSCALL },
124 	{ "svr4",	svr4_syscallnames,	SVR4_SYS_MAXSYSCALL },
125 	{ "ultrix",	ultrix_syscallnames,	ULTRIX_SYS_MAXSYSCALL },
126 	{ "bsdos",	bsdos_syscallnames,	BSDOS_SYS_MAXSYSCALL },
127 	{ "freebsd",	freebsd_syscallnames,	FREEBSD_SYS_MAXSYSCALL },
128 	{ NULL,		NULL,			NULL }
129 };
130 
131 struct emulation *current;
132 
133 
134 static char *ptrace_ops[] = {
135 	"PT_TRACE_ME",	"PT_READ_I",	"PT_READ_D",	"PT_READ_U",
136 	"PT_WRITE_I",	"PT_WRITE_D",	"PT_WRITE_U",	"PT_CONTINUE",
137 	"PT_KILL",	"PT_ATTACH",	"PT_DETACH",	"PT_IO",
138 };
139 
140 static int fread_tail(void *, size_t, size_t);
141 static void dumpheader(struct ktr_header *);
142 static void ktrcsw(struct ktr_csw *);
143 static void ktremul(char *, size_t);
144 static void ktrgenio(struct ktr_genio *, size_t);
145 static void ktrnamei(const char *, size_t);
146 static void ktrpsig(struct ktr_psig *);
147 static void ktrsyscall(struct ktr_syscall *);
148 static void ktrsysret(struct ktr_sysret *);
149 static void setemul(const char *);
150 static void usage(void);
151 
152 int
153 main(int argc, char *argv[])
154 {
155 	int ch, silent;
156 	size_t ktrlen, size;
157 	int trpoints = ALL_POINTS;
158 	void *m;
159 
160 	current = &emulations[0];	/* native */
161 
162 	while ((ch = getopt(argc, argv, "e:f:dlm:nRp:Tt:xX")) != -1)
163 		switch (ch) {
164 		case 'e':
165 			setemul(optarg);
166 			break;
167 		case 'f':
168 			tracefile = optarg;
169 			break;
170 		case 'd':
171 			decimal = 1;
172 			break;
173 		case 'l':
174 			tail = 1;
175 			break;
176 		case 'm':
177 			maxdata = atoi(optarg);
178 			break;
179 		case 'n':
180 			fancy = 0;
181 			break;
182 		case 'p':
183 			pid = atoi(optarg);
184 			break;
185 		case 'R':
186 			timestamp = 2;	/* relative timestamp */
187 			break;
188 		case 'T':
189 			timestamp = 1;
190 			break;
191 		case 't':
192 			trpoints = getpoints(optarg);
193 			if (trpoints < 0)
194 				errx(1, "unknown trace point in %s", optarg);
195 			break;
196 		case 'x':
197 			iohex = 1;
198 			break;
199 		case 'X':
200 			iohex = 2;
201 			break;
202 		default:
203 			usage();
204 		}
205 	if (argc > optind)
206 		usage();
207 
208 	m = malloc(size = 1025);
209 	if (m == NULL)
210 		err(1, NULL);
211 	if (!freopen(tracefile, "r", stdin))
212 		err(1, "%s", tracefile);
213 	while (fread_tail(&ktr_header, sizeof(struct ktr_header), 1)) {
214 		silent = 0;
215 		if (pid != -1 && pid != ktr_header.ktr_pid)
216 			silent = 1;
217 		if (silent == 0 && trpoints & (1<<ktr_header.ktr_type))
218 			dumpheader(&ktr_header);
219 		ktrlen = ktr_header.ktr_len;
220 		if (ktrlen > size) {
221 			void *newm;
222 
223 			newm = realloc(m, ktrlen+1);
224 			if (newm == NULL)
225 				err(1, NULL);
226 			m = newm;
227 			size = ktrlen;
228 		}
229 		if (ktrlen && fread_tail(m, ktrlen, 1) == 0)
230 			errx(1, "data too short");
231 		if (silent)
232 			continue;
233 		if ((trpoints & (1<<ktr_header.ktr_type)) == 0)
234 			continue;
235 		switch (ktr_header.ktr_type) {
236 		case KTR_SYSCALL:
237 			ktrsyscall((struct ktr_syscall *)m);
238 			break;
239 		case KTR_SYSRET:
240 			ktrsysret((struct ktr_sysret *)m);
241 			break;
242 		case KTR_NAMEI:
243 			ktrnamei(m, ktrlen);
244 			break;
245 		case KTR_GENIO:
246 			ktrgenio((struct ktr_genio *)m, ktrlen);
247 			break;
248 		case KTR_PSIG:
249 			ktrpsig((struct ktr_psig *)m);
250 			break;
251 		case KTR_CSW:
252 			ktrcsw((struct ktr_csw *)m);
253 			break;
254 		case KTR_EMUL:
255 			ktremul(m, ktrlen);
256 			break;
257 		}
258 		if (tail)
259 			(void)fflush(stdout);
260 	}
261 	exit(0);
262 }
263 
264 static int
265 fread_tail(void *buf, size_t size, size_t num)
266 {
267 	int i;
268 
269 	while ((i = fread(buf, size, num, stdin)) == 0 && tail) {
270 		(void)sleep(1);
271 		clearerr(stdin);
272 	}
273 	return (i);
274 }
275 
276 static void
277 dumpheader(struct ktr_header *kth)
278 {
279 	static struct timeval prevtime;
280 	char unknown[64], *type;
281 	struct timeval temp;
282 
283 	switch (kth->ktr_type) {
284 	case KTR_SYSCALL:
285 		type = "CALL";
286 		break;
287 	case KTR_SYSRET:
288 		type = "RET ";
289 		break;
290 	case KTR_NAMEI:
291 		type = "NAMI";
292 		break;
293 	case KTR_GENIO:
294 		type = "GIO ";
295 		break;
296 	case KTR_PSIG:
297 		type = "PSIG";
298 		break;
299 	case KTR_CSW:
300 		type = "CSW";
301 		break;
302 	case KTR_EMUL:
303 		type = "EMUL";
304 		break;
305 	default:
306 		(void)snprintf(unknown, sizeof unknown, "UNKNOWN(%d)",
307 		    kth->ktr_type);
308 		type = unknown;
309 	}
310 
311 	(void)printf("%6ld %-8.*s ", (long)kth->ktr_pid, MAXCOMLEN,
312 	    kth->ktr_comm);
313 	if (timestamp) {
314 		if (timestamp == 2) {
315 			timersub(&kth->ktr_time, &prevtime, &temp);
316 			prevtime = kth->ktr_time;
317 		} else
318 			temp = kth->ktr_time;
319 		(void)printf("%ld.%06ld ", temp.tv_sec, temp.tv_usec);
320 	}
321 	(void)printf("%s  ", type);
322 }
323 
324 static void
325 ioctldecode(u_long cmd)
326 {
327 	char dirbuf[4], *dir = dirbuf;
328 
329 	if (cmd & IOC_IN)
330 		*dir++ = 'W';
331 	if (cmd & IOC_OUT)
332 		*dir++ = 'R';
333 	*dir = '\0';
334 
335 	printf(decimal ? ",_IO%s('%c',%lu" : ",_IO%s('%c',%#lx",
336 	    dirbuf, (int)((cmd >> 8) & 0xff), cmd & 0xff);
337 	if ((cmd & IOC_VOID) == 0)
338 		printf(decimal ? ",%lu)" : ",%#lx)", (cmd >> 16) & 0xff);
339 	else
340 		printf(")");
341 }
342 
343 static void
344 ktrsyscall(struct ktr_syscall *ktr)
345 {
346 	int argsize = ktr->ktr_argsize;
347 	register_t *ap;
348 
349 	if (ktr->ktr_code >= current->nsysnames || ktr->ktr_code < 0)
350 		(void)printf("[%d]", ktr->ktr_code);
351 	else
352 		(void)printf("%s", current->sysnames[ktr->ktr_code]);
353 	ap = (register_t *)((char *)ktr + sizeof(struct ktr_syscall));
354 	(void)putchar('(');
355 	if (argsize) {
356 		char c = '\0';
357 		if (fancy) {
358 			if (ktr->ktr_code == SYS_ioctl) {
359 				const char *cp;
360 
361 				if (decimal)
362 					(void)printf("%ld", (long)*ap);
363 				else
364 					(void)printf("%#lx", (long)*ap);
365 				ap++;
366 				argsize -= sizeof(register_t);
367 				if ((cp = ioctlname(*ap)) != NULL)
368 					(void)printf(",%s", cp);
369 				else
370 					ioctldecode(*ap);
371 				c = ',';
372 				ap++;
373 				argsize -= sizeof(register_t);
374 			} else if (ktr->ktr_code == SYS___sysctl) {
375 				int *np, n;
376 
377 				n = ap[1];
378 				if (n > CTL_MAXNAME)
379 					n = CTL_MAXNAME;
380 				np = (int *)(ap + 6);
381 				for (; n--; np++) {
382 					if (c)
383 						putchar(c);
384 					printf("%d", *np);
385 					c = '.';
386 				}
387 
388 				c = ',';
389 				ap += 2;
390 				argsize -= 2 * sizeof(register_t);
391 			} else if (ktr->ktr_code == SYS_ptrace) {
392 				if (*ap >= 0 && *ap <
393 				    sizeof(ptrace_ops) / sizeof(ptrace_ops[0]))
394 					(void)printf("%s", ptrace_ops[*ap]);
395 				else switch(*ap) {
396 #ifdef PT_GETFPREGS
397 				case PT_GETFPREGS:
398 					(void)printf("PT_GETFPREGS");
399 					break;
400 #endif
401 				case PT_GETREGS:
402 					(void)printf("PT_GETREGS");
403 					break;
404 #ifdef PT_SETFPREGS
405 				case PT_SETFPREGS:
406 					(void)printf("PT_SETFPREGS");
407 					break;
408 #endif
409 				case PT_SETREGS:
410 					(void)printf("PT_SETREGS");
411 					break;
412 #ifdef PT_STEP
413 				case PT_STEP:
414 					(void)printf("PT_STEP");
415 					break;
416 #endif
417 #ifdef PT_WCOOKIE
418 				case PT_WCOOKIE:
419 					(void)printf("PT_WCOOKIE");
420 					break;
421 #endif
422 				default:
423 					(void)printf("%ld", (long)*ap);
424 					break;
425 				}
426 				c = ',';
427 				ap++;
428 				argsize -= sizeof(register_t);
429 			}
430 		}
431 		while (argsize) {
432 			if (c)
433 				putchar(c);
434 			if (decimal)
435 				(void)printf("%ld", (long)*ap);
436 			else
437 				(void)printf("%#lx", (long)*ap);
438 			c = ',';
439 			ap++;
440 			argsize -= sizeof(register_t);
441 		}
442 	}
443 	(void)printf(")\n");
444 }
445 
446 static void
447 ktrsysret(struct ktr_sysret *ktr)
448 {
449 	int ret = ktr->ktr_retval;
450 	int error = ktr->ktr_error;
451 	int code = ktr->ktr_code;
452 
453 	if (code >= current->nsysnames || code < 0)
454 		(void)printf("[%d] ", code);
455 	else
456 		(void)printf("%s ", current->sysnames[code]);
457 
458 	if (error == 0) {
459 		if (fancy) {
460 			(void)printf("%d", ret);
461 			if (ret < 0 || ret > 9)
462 				(void)printf("/%#x", ret);
463 		} else {
464 			if (decimal)
465 				(void)printf("%d", ret);
466 			else
467 				(void)printf("%#x", ret);
468 		}
469 	} else if (error == ERESTART)
470 		(void)printf("RESTART");
471 	else if (error == EJUSTRETURN)
472 		(void)printf("JUSTRETURN");
473 	else {
474 		(void)printf("-1 errno %d", ktr->ktr_error);
475 		if (fancy)
476 			(void)printf(" %s", strerror(ktr->ktr_error));
477 	}
478 	(void)putchar('\n');
479 }
480 
481 static void
482 ktrnamei(const char *cp, size_t len)
483 {
484 	(void)printf("\"%.*s\"\n", (int)len, cp);
485 }
486 
487 static void
488 ktremul(char *cp, size_t len)
489 {
490 	char name[1024];
491 
492 	if (len >= sizeof(name))
493 		errx(1, "Emulation name too long");
494 
495 	strncpy(name, cp, len);
496 	name[len] = '\0';
497 	(void)printf("\"%s\"\n", name);
498 
499 	setemul(name);
500 }
501 
502 static void
503 ktrgenio(struct ktr_genio *ktr, size_t len)
504 {
505 	unsigned char *dp = (unsigned char *)ktr + sizeof(struct ktr_genio);
506 	int i, j;
507 	size_t datalen = len - sizeof(struct ktr_genio);
508 	static int screenwidth = 0;
509 	int col = 0, width, bpl;
510 	unsigned char visbuf[5], *cp, c;
511 
512 	if (screenwidth == 0) {
513 		struct winsize ws;
514 
515 		if (fancy && ioctl(fileno(stderr), TIOCGWINSZ, &ws) != -1 &&
516 		    ws.ws_col > 8)
517 			screenwidth = ws.ws_col;
518 		else
519 			screenwidth = 80;
520 	}
521 	printf("fd %d %s %zu bytes\n", ktr->ktr_fd,
522 		ktr->ktr_rw == UIO_READ ? "read" : "wrote", datalen);
523 	if (maxdata && datalen > maxdata)
524 		datalen = maxdata;
525 	if (iohex && !datalen)
526 		return;
527 	if (iohex == 1) {
528 		putchar('\t');
529 		col = 8;
530 		for (i = 0; i < datalen; i++) {
531 			printf("%02x", dp[i]);
532 			col += 3;
533 			if (i < datalen - 1) {
534 				if (col + 3 > screenwidth) {
535 					printf("\n\t");
536 					col = 8;
537 				} else
538 					putchar(' ');
539 			}
540 		}
541 		putchar('\n');
542 		return;
543 	}
544 	if (iohex == 2) {
545 		bpl = (screenwidth - 13)/4;
546 		if (bpl <= 0)
547 			bpl = 1;
548 		for (i = 0; i < datalen; i += bpl) {
549 			printf("   %04x:  ", i);
550 			for (j = 0; j < bpl; j++) {
551 				if (i+j >= datalen)
552 					printf("   ");
553 				else
554 					printf("%02x ", dp[i+j]);
555 			}
556 			putchar(' ');
557 			for (j = 0; j < bpl; j++) {
558 				if (i+j >= datalen)
559 					break;
560 				c = dp[i+j];
561 				if (!isprint(c))
562 					c = '.';
563 				putchar(c);
564 			}
565 			putchar('\n');
566 		}
567 		return;
568 	}
569 	(void)printf("       \"");
570 	col = 8;
571 	for (; datalen > 0; datalen--, dp++) {
572 		(void)vis(visbuf, *dp, VIS_CSTYLE, *(dp+1));
573 		cp = visbuf;
574 
575 		/*
576 		 * Keep track of printables and
577 		 * space chars (like fold(1)).
578 		 */
579 		if (col == 0) {
580 			(void)putchar('\t');
581 			col = 8;
582 		}
583 		switch (*cp) {
584 		case '\n':
585 			col = 0;
586 			(void)putchar('\n');
587 			continue;
588 		case '\t':
589 			width = 8 - (col&07);
590 			break;
591 		default:
592 			width = strlen(cp);
593 		}
594 		if (col + width > (screenwidth-2)) {
595 			(void)printf("\\\n\t");
596 			col = 8;
597 		}
598 		col += width;
599 		do {
600 			(void)putchar(*cp++);
601 		} while (*cp);
602 	}
603 	if (col == 0)
604 		(void)printf("       ");
605 	(void)printf("\"\n");
606 }
607 
608 static void
609 ktrpsig(struct ktr_psig *psig)
610 {
611 	(void)printf("SIG%s ", sys_signame[psig->signo]);
612 	if (psig->action == SIG_DFL)
613 		(void)printf("SIG_DFL code %d", psig->code);
614 	else
615 		(void)printf("caught handler=0x%lx mask=0x%x",
616 		    (u_long)psig->action, psig->mask);
617 	switch (psig->signo) {
618 	case SIGSEGV:
619 	case SIGILL:
620 	case SIGBUS:
621 	case SIGFPE:
622 		printf(" addr=%p trapno=%d", psig->si.si_addr,
623 		    psig->si.si_trapno);
624 		break;
625 	default:
626 		break;
627 	}
628 	printf("\n");
629 }
630 
631 static void
632 ktrcsw(struct ktr_csw *cs)
633 {
634 	(void)printf("%s %s\n", cs->out ? "stop" : "resume",
635 	    cs->user ? "user" : "kernel");
636 }
637 
638 static void
639 usage(void)
640 {
641 
642 	extern char *__progname;
643 	fprintf(stderr, "usage: %s "
644 	    "[-dlnRTXx] [-e emulation] [-f file] [-m maxdata] [-p pid]\n"
645 	    "%*s[-t [ceinsw]]\n",
646 	    __progname, sizeof("usage: ") + strlen(__progname), "");
647 	exit(1);
648 }
649 
650 static void
651 setemul(const char *name)
652 {
653 	int i;
654 
655 	for (i = 0; emulations[i].name != NULL; i++)
656 		if (strcmp(emulations[i].name, name) == 0) {
657 			current = &emulations[i];
658 			return;
659 		}
660 	warnx("Emulation `%s' unknown", name);
661 }
662