Home | History | Annotate | Line # | Download | only in kdump
kdump.c revision 1.62
      1 /*	$NetBSD: kdump.c,v 1.62 2003/09/20 22:24:00 matt 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/cdefs.h>
     33 #ifndef lint
     34 __COPYRIGHT("@(#) Copyright (c) 1988, 1993\n\
     35 	The Regents of the University of California.  All rights reserved.\n");
     36 #endif /* not lint */
     37 
     38 #ifndef lint
     39 #if 0
     40 static char sccsid[] = "@(#)kdump.c	8.4 (Berkeley) 4/28/95";
     41 #else
     42 __RCSID("$NetBSD: kdump.c,v 1.62 2003/09/20 22:24:00 matt Exp $");
     43 #endif
     44 #endif /* not lint */
     45 
     46 #include <sys/param.h>
     47 #define _KERNEL
     48 #include <sys/errno.h>
     49 #undef _KERNEL
     50 #include <sys/time.h>
     51 #include <sys/uio.h>
     52 #include <sys/ktrace.h>
     53 #include <sys/ioctl.h>
     54 #include <sys/ptrace.h>
     55 
     56 #include <ctype.h>
     57 #include <err.h>
     58 #include <signal.h>
     59 #include <stddef.h>
     60 #include <stdio.h>
     61 #include <stdlib.h>
     62 #include <string.h>
     63 #include <unistd.h>
     64 #include <vis.h>
     65 
     66 #include "ktrace.h"
     67 #include "setemul.h"
     68 
     69 #include <sys/syscall.h>
     70 
     71 int timestamp, decimal, plain, tail, maxdata = -1, numeric;
     72 int hexdump;
     73 pid_t do_pid = -1;
     74 const char *tracefile = NULL;
     75 struct ktr_header ktr_header;
     76 int emul_changed = 0;
     77 
     78 #define eqs(s1, s2)	(strcmp((s1), (s2)) == 0)
     79 
     80 static const char *ptrace_ops[] = {
     81 	"PT_TRACE_ME",	"PT_READ_I",	"PT_READ_D",	"PT_READ_U",
     82 	"PT_WRITE_I",	"PT_WRITE_D",	"PT_WRITE_U",	"PT_CONTINUE",
     83 	"PT_KILL",	"PT_ATTACH",	"PT_DETACH",
     84 };
     85 
     86 static const char *linux_ptrace_ops[] = {
     87 	"PTRACE_TRACEME",
     88 	"PTRACE_PEEKTEXT", "PTRACE_PEEKDATA", "PTRACE_PEEKUSER",
     89 	"PTRACE_POKETEXT", "PTRACE_POKEDATA", "PTRACE_POKEUSER",
     90 	"PTRACE_CONT", "PTRACE_KILL", "PTRACE_SINGLESTEP",
     91 	NULL, NULL,
     92 	"PTRACE_GETREGS", "PTRACE_SETREGS", "PTRACE_GETFPREGS",
     93 	"PTRACE_SETFPREGS", "PTRACE_ATTACH", "PTRACE_DETACH",
     94 	"PTRACE_SYSCALL",
     95 };
     96 
     97 int	main __P((int, char **));
     98 int	fread_tail __P((char *, int, int));
     99 int	dumpheader __P((struct ktr_header *));
    100 void	ioctldecode __P((u_long));
    101 void	ktrsyscall __P((struct ktr_syscall *));
    102 void	ktrsysret __P((struct ktr_sysret *, int));
    103 void	ktrnamei __P((char *, int));
    104 void	ktremul __P((char *, int, int));
    105 void	ktrgenio __P((struct ktr_genio *, int));
    106 void	ktrpsig __P((void *, int));
    107 void	ktrcsw __P((struct ktr_csw *));
    108 void	ktruser __P((struct ktr_user *, int));
    109 void	ktrmmsg __P((struct ktr_mmsg *, int));
    110 void	usage __P((void));
    111 void	eprint __P((int));
    112 void	rprint __P((register_t));
    113 char	*ioctlname __P((long));
    114 static const char *signame __P((long, int));
    115 static void hexdump_buf(const void *, int);
    116 static void visdump_buf(const void *, int, int);
    117 
    118 int
    119 main(argc, argv)
    120 	int argc;
    121 	char *argv[];
    122 {
    123 	int ch, ktrlen, size;
    124 	void *m;
    125 	int trpoints = 0;
    126 	int trset = 0;
    127 	const char *emul_name = "netbsd";
    128 	int col;
    129 
    130 	while ((ch = getopt(argc, argv, "e:f:dlm:Nnp:RTt:x")) != -1)
    131 		switch (ch) {
    132 		case 'e':
    133 			emul_name = strdup(optarg); /* it's safer to copy it */
    134 			break;
    135 		case 'f':
    136 			tracefile = optarg;
    137 			break;
    138 		case 'd':
    139 			decimal = 1;
    140 			break;
    141 		case 'l':
    142 			tail = 1;
    143 			break;
    144 		case 'p':
    145 			do_pid = atoi(optarg);
    146 			break;
    147 		case 'm':
    148 			maxdata = atoi(optarg);
    149 			break;
    150 		case 'N':
    151 			numeric++;
    152 			break;
    153 		case 'n':
    154 			plain++;
    155 			break;
    156 		case 'R':
    157 			timestamp = 2;	/* relative timestamp */
    158 			break;
    159 		case 'T':
    160 			timestamp = 1;
    161 			break;
    162 		case 't':
    163 			trset = 1;
    164 			trpoints = getpoints(trpoints, optarg);
    165 			if (trpoints < 0)
    166 				errx(1, "unknown trace point in %s", optarg);
    167 			break;
    168 		case 'x':
    169 			hexdump = 1;
    170 			break;
    171 		default:
    172 			usage();
    173 		}
    174 	argv += optind;
    175 	argc -= optind;
    176 
    177 	if (!trset)
    178 		trpoints = ALL_POINTS;
    179 
    180 	if (tracefile == NULL) {
    181 		if (argc == 1) {
    182 			tracefile = argv[0];
    183 			argv++;
    184 			argc--;
    185 		}
    186 		else
    187 			tracefile = DEF_TRACEFILE;
    188 	}
    189 
    190 	if (argc > 0)
    191 		usage();
    192 
    193 	setemul(emul_name, 0, 0);
    194 	mach_lookup_emul();
    195 
    196 	m = malloc(size = 1024);
    197 	if (m == NULL)
    198 		errx(1, "malloc: %s", strerror(ENOMEM));
    199 	if (!freopen(tracefile, "r", stdin))
    200 		err(1, "%s", tracefile);
    201 	while (fread_tail((char *)&ktr_header, sizeof(struct ktr_header), 1)) {
    202 		if (trpoints & (1<<ktr_header.ktr_type)
    203 		    && (do_pid == -1 || ktr_header.ktr_pid == do_pid))
    204 			col = dumpheader(&ktr_header);
    205 		else
    206 			col = -1;
    207 		if ((ktrlen = ktr_header.ktr_len) < 0)
    208 			errx(1, "bogus length 0x%x", ktrlen);
    209 		if (ktrlen > size) {
    210 			while (ktrlen > size)
    211 				size *= 2;
    212 			m = realloc(m, size);
    213 			if (m == NULL)
    214 				errx(1, "realloc: %s", strerror(ENOMEM));
    215 		}
    216 		if (ktrlen && fread_tail(m, ktrlen, 1) == 0)
    217 			errx(1, "data too short");
    218 		if (col == -1)
    219 			continue;
    220 
    221 		/* update context to match currently processed record */
    222 		ectx_sanify(ktr_header.ktr_pid);
    223 
    224 		switch (ktr_header.ktr_type) {
    225 		case KTR_SYSCALL:
    226 			ktrsyscall(m);
    227 			break;
    228 		case KTR_SYSRET:
    229 			ktrsysret(m, ktrlen);
    230 			break;
    231 		case KTR_NAMEI:
    232 			ktrnamei(m, ktrlen);
    233 			break;
    234 		case KTR_GENIO:
    235 			ktrgenio(m, ktrlen);
    236 			break;
    237 		case KTR_PSIG:
    238 			ktrpsig(m, ktrlen);
    239 			break;
    240 		case KTR_CSW:
    241 			ktrcsw(m);
    242 			break;
    243 		case KTR_EMUL:
    244 			ktremul(m, ktrlen, size);
    245 			break;
    246 		case KTR_USER:
    247 			ktruser(m, ktrlen);
    248 			break;
    249 		case KTR_MMSG:
    250 			ktrmmsg(m, ktrlen);
    251 			break;
    252 		case KTR_EXEC_ARG:
    253 		case KTR_EXEC_ENV:
    254 			visdump_buf(m, ktrlen, col);
    255 			break;
    256 		default:
    257 			printf("\n");
    258 			hexdump_buf(m, ktrlen);
    259 		}
    260 		if (tail)
    261 			(void)fflush(stdout);
    262 	}
    263 	return (0);
    264 }
    265 
    266 int
    267 fread_tail(buf, size, num)
    268 	char *buf;
    269 	int num, size;
    270 {
    271 	int i;
    272 
    273 	while ((i = fread(buf, size, num, stdin)) == 0 && tail) {
    274 		(void)sleep(1);
    275 		clearerr(stdin);
    276 	}
    277 	return (i);
    278 }
    279 
    280 int
    281 dumpheader(kth)
    282 	struct ktr_header *kth;
    283 {
    284 	char unknown[64], *type;
    285 	static struct timeval prevtime;
    286 	struct timeval temp;
    287 	int col;
    288 
    289 	switch (kth->ktr_type) {
    290 	case KTR_SYSCALL:
    291 		type = "CALL";
    292 		break;
    293 	case KTR_SYSRET:
    294 		type = "RET ";
    295 		break;
    296 	case KTR_NAMEI:
    297 		type = "NAMI";
    298 		break;
    299 	case KTR_GENIO:
    300 		type = "GIO ";
    301 		break;
    302 	case KTR_PSIG:
    303 		type = "PSIG";
    304 		break;
    305 	case KTR_CSW:
    306 		type = "CSW ";
    307 		break;
    308 	case KTR_EMUL:
    309 		type = "EMUL";
    310 		break;
    311 	case KTR_USER:
    312 		type = "USER";
    313 		break;
    314 	case KTR_MMSG:
    315 		type = "MMSG";
    316 		break;
    317 	case KTR_EXEC_ENV:
    318 		type = "ENV";
    319 		break;
    320 	case KTR_EXEC_ARG:
    321 		type = "ARG";
    322 		break;
    323 	default:
    324 		(void)sprintf(unknown, "UNKNOWN(%d)", kth->ktr_type);
    325 		type = unknown;
    326 	}
    327 
    328 	col = printf("%6d %-8.*s ", kth->ktr_pid, MAXCOMLEN, kth->ktr_comm);
    329 	if (timestamp) {
    330 		if (timestamp == 2) {
    331 			if (prevtime.tv_sec == 0)
    332 				temp.tv_sec = temp.tv_usec = 0;
    333 			else
    334 				timersub(&kth->ktr_time, &prevtime, &temp);
    335 			prevtime = kth->ktr_time;
    336 		} else
    337 			temp = kth->ktr_time;
    338 		col += printf("%ld.%06ld ",
    339 		    (long int)temp.tv_sec, (long int)temp.tv_usec);
    340 	}
    341 	col += printf("%-4s  ", type);
    342 	return col;
    343 }
    344 
    345 void
    346 ioctldecode(cmd)
    347 	u_long cmd;
    348 {
    349 	char dirbuf[4], *dir = dirbuf;
    350 
    351 	if (cmd & IOC_IN)
    352 		*dir++ = 'W';
    353 	if (cmd & IOC_OUT)
    354 		*dir++ = 'R';
    355 	*dir = '\0';
    356 
    357 	printf(decimal ? ",_IO%s('%c',%ld" : ",_IO%s('%c',%#lx",
    358 	    dirbuf, (int) ((cmd >> 8) & 0xff), cmd & 0xff);
    359 	if ((cmd & IOC_VOID) == 0)
    360 		printf(decimal ? ",%ld)" : ",%#lx)", (cmd >> 16) & 0xff);
    361 	else
    362 		printf(")");
    363 }
    364 
    365 void
    366 ktrsyscall(ktr)
    367 	struct ktr_syscall *ktr;
    368 {
    369 	int argsize = ktr->ktr_argsize;
    370 	const struct emulation *revelant = current;
    371 	register_t *ap;
    372 
    373 	if (((ktr->ktr_code >= revelant->nsysnames || ktr->ktr_code < 0)
    374 	    && (mach_traps_dispatch(&ktr->ktr_code, &revelant) == 0)) ||
    375 	    numeric)
    376 		(void)printf("[%d]", ktr->ktr_code);
    377 	else
    378 		(void)printf("%s", revelant->sysnames[ktr->ktr_code]);
    379 	ap = (register_t *)((char *)ktr + sizeof(struct ktr_syscall));
    380 	if (argsize) {
    381 		char c = '(';
    382 		if (!plain) {
    383 			char *cp;
    384 
    385 			switch (ktr->ktr_code) {
    386 			case SYS_ioctl:
    387 				if (decimal)
    388 					(void)printf("(%ld", (long)*ap);
    389 				else
    390 					(void)printf("(%#lx", (long)*ap);
    391 				ap++;
    392 				argsize -= sizeof(register_t);
    393 				if ((cp = ioctlname(*ap)) != NULL)
    394 					(void)printf(",%s", cp);
    395 				else
    396 					ioctldecode(*ap);
    397 				c = ',';
    398 				ap++;
    399 				argsize -= sizeof(register_t);
    400 				break;
    401 
    402 			case SYS_ptrace:
    403 				if (strcmp(revelant->name, "linux") == 0) {
    404 				  if (*ap >= 0 && *ap <=
    405 				      sizeof(linux_ptrace_ops) /
    406 				      sizeof(linux_ptrace_ops[0]))
    407 					(void)printf("(%s",
    408 					    linux_ptrace_ops[*ap]);
    409 				  else
    410 					(void)printf("(%ld", (long)*ap);
    411 				} else {
    412 				  if (*ap >= 0 && *ap <=
    413 				    sizeof(ptrace_ops) / sizeof(ptrace_ops[0]))
    414 					(void)printf("(%s", ptrace_ops[*ap]);
    415 				  else
    416 					(void)printf("(%ld", (long)*ap);
    417 				}
    418 				c = ',';
    419 				ap++;
    420 				argsize -= sizeof(register_t);
    421 				break;
    422 
    423 			case SYS_kill:
    424 				if (decimal)
    425 					(void)printf("(%ld, SIG%s",
    426 					    (long)ap[0], signame(ap[1], 1));
    427 				else
    428 					(void)printf("(%#lx, SIG%s",
    429 					    (long)ap[0], signame(ap[1], 1));
    430 				ap += 2;
    431 				argsize -= 2 * sizeof(register_t);
    432 				break;
    433 
    434 			default:
    435 				/* No special handling */
    436 				break;
    437 			}
    438 		}
    439 		while (argsize) {
    440 			if (decimal)
    441 				(void)printf("%c%ld", c, (long)*ap);
    442 			else
    443 				(void)printf("%c%#lx", c, (long)*ap);
    444 			c = ',';
    445 			ap++;
    446 			argsize -= sizeof(register_t);
    447 		}
    448 		(void)putchar(')');
    449 	}
    450 	(void)putchar('\n');
    451 }
    452 
    453 void
    454 ktrsysret(ktr, len)
    455 	struct ktr_sysret *ktr;
    456 	int len;
    457 {
    458 	const struct emulation *revelant;
    459 	int error = ktr->ktr_error;
    460 	int code = ktr->ktr_code;
    461 
    462 	if (emul_changed)
    463 		revelant = previous;
    464 	else
    465 		revelant = current;
    466 	emul_changed = 0;
    467 
    468 	if ((code >= revelant->nsysnames || code < 0 || plain > 1)
    469 	    && (mach_traps_dispatch(&code, &revelant) == 0))
    470 		(void)printf("[%d] ", code);
    471 	else
    472 		(void)printf("%s ", revelant->sysnames[code]);
    473 
    474 	switch (error) {
    475 	case 0:
    476 		rprint(ktr->ktr_retval);
    477 		if (len > offsetof(struct ktr_sysret, ktr_retval_1) &&
    478 		    ktr->ktr_retval_1 != 0) {
    479 			(void)printf(", ");
    480 			rprint(ktr->ktr_retval_1);
    481 		}
    482 		break;
    483 
    484 	default:
    485 		eprint(error);
    486 		break;
    487 	}
    488 	(void)putchar('\n');
    489 }
    490 
    491 void
    492 rprint(register_t ret)
    493 {
    494 	if (!plain) {
    495 		(void)printf("%ld", (long)ret);
    496 		if (ret < 0 || ret > 9)
    497 			(void)printf("/%#lx", (long)ret);
    498 	} else {
    499 		if (decimal)
    500 			(void)printf("%ld", (long)ret);
    501 		else
    502 			(void)printf("%#lx", (long)ret);
    503 	}
    504 }
    505 
    506 /*
    507  * We print the original emulation's error numerically, but we
    508  * translate it to netbsd to print it symbolically.
    509  */
    510 void
    511 eprint(e)
    512 	int e;
    513 {
    514 	int i = e;
    515 
    516 	if (current->errnomap) {
    517 
    518 		/* No remapping for ERESTART and EJUSTRETURN */
    519 		/* Kludge for linux that has negative error numbers */
    520 		if (current->errnomap[2] > 0 && e < 0)
    521 			goto normal;
    522 
    523 		for (i = 0; i < current->nerrnomap; i++)
    524 			if (e == current->errnomap[i])
    525 				break;
    526 
    527 		if (i == current->nerrnomap) {
    528 			printf("-1 unknown errno %d", e);
    529 			return;
    530 		}
    531 	}
    532 
    533 normal:
    534 	switch (i) {
    535 	case ERESTART:
    536 		(void)printf("RESTART");
    537 		break;
    538 
    539 	case EJUSTRETURN:
    540 		(void)printf("JUSTRETURN");
    541 		break;
    542 
    543 	default:
    544 		(void)printf("-1 errno %d", e);
    545 		if (!plain)
    546 			(void)printf(" %s", strerror(i));
    547 	}
    548 }
    549 
    550 void
    551 ktrnamei(cp, len)
    552 	char *cp;
    553 	int len;
    554 {
    555 
    556 	(void)printf("\"%.*s\"\n", len, cp);
    557 }
    558 
    559 void
    560 ktremul(name, len, bufsize)
    561 	char *name;
    562 	int len, bufsize;
    563 {
    564 	if (len >= bufsize)
    565 		len = bufsize - 1;
    566 
    567 	name[len] = '\0';
    568 	setemul(name, ktr_header.ktr_pid, 1);
    569 	emul_changed = 1;
    570 
    571 	(void)printf("\"%s\"\n", name);
    572 }
    573 
    574 static void
    575 hexdump_buf(const void *vdp, int datalen)
    576 {
    577 	char chars[16];
    578 	const unsigned char *dp = vdp;
    579 	int line_end, off, l, c;
    580 	char *cp;
    581 
    582 	for (off = 0; off < datalen;) {
    583 		line_end = off + 16;
    584 		if (line_end > datalen)
    585 			line_end = datalen;
    586 		printf("\t%3.3x ", off);
    587 		for (l = 0, cp = chars; off < line_end; off++) {
    588 			c = *dp++;
    589 			if ((off & 7) == 0)
    590 				l += printf(" ");
    591 			l += printf(" %2.2x", c);
    592 			*cp++ = isgraph(c) ? c : '.';
    593 		};
    594 		printf("%*s %.*s\n", 50 - l, "", (int)(cp - chars), chars);
    595 	}
    596 }
    597 
    598 static void
    599 visdump_buf(const void *vdp, int datalen, int col)
    600 {
    601 	const unsigned char *dp = vdp;
    602 	char *cp;
    603 	int width;
    604 	char visbuf[5];
    605 	static int screenwidth = 0;
    606 
    607 	if (screenwidth == 0) {
    608 		struct winsize ws;
    609 
    610 		if (!plain && ioctl(fileno(stderr), TIOCGWINSZ, &ws) != -1 &&
    611 		    ws.ws_col > 8)
    612 			screenwidth = ws.ws_col;
    613 		else
    614 			screenwidth = 80;
    615 	}
    616 
    617 	(void)printf("\"");
    618 	col++;
    619 	for (; datalen > 0; datalen--, dp++) {
    620 		(void)svis(visbuf, *dp, VIS_CSTYLE,
    621 		    datalen > 1 ? *(dp + 1) : 0, "\"");
    622 		cp = visbuf;
    623 		/*
    624 		 * Keep track of printables and
    625 		 * space chars (like fold(1)).
    626 		 */
    627 		if (col == 0) {
    628 			(void)putchar('\t');
    629 			col = 8;
    630 		}
    631 		switch(*cp) {
    632 		case '\n':
    633 			col = 0;
    634 			(void)putchar('\n');
    635 			continue;
    636 		case '\t':
    637 			width = 8 - (col & 07);
    638 			break;
    639 		default:
    640 			width = strlen(cp);
    641 		}
    642 		if (col + width > (screenwidth - 2)) {
    643 			(void)printf("\\\n\t");
    644 			col = 8;
    645 		}
    646 		col += width;
    647 		do {
    648 			(void)putchar(*cp++);
    649 		} while (*cp);
    650 	}
    651 	if (col == 0)
    652 		(void)printf("       ");
    653 	(void)printf("\"\n");
    654 }
    655 
    656 void
    657 ktrgenio(ktr, len)
    658 	struct ktr_genio *ktr;
    659 	int len;
    660 {
    661 	int datalen = len - sizeof (struct ktr_genio);
    662 	char *dp = (char *)ktr + sizeof (struct ktr_genio);
    663 
    664 	printf("fd %d %s %d bytes\n", ktr->ktr_fd,
    665 		ktr->ktr_rw == UIO_READ ? "read" : "wrote", datalen);
    666 	if (maxdata == 0)
    667 		return;
    668 	if (maxdata > 0 && datalen > maxdata)
    669 		datalen = maxdata;
    670 	if (hexdump) {
    671 		hexdump_buf(dp, datalen);
    672 		return;
    673 	}
    674 	(void)printf("       ");
    675 	visdump_buf(dp, datalen, 7);
    676 }
    677 
    678 void
    679 ktrpsig(v, len)
    680 	void *v;
    681 	int len;
    682 {
    683 	int signo, first;
    684 	struct {
    685 		struct ktr_psig ps;
    686 		siginfo_t si;
    687 	} *psig = v;
    688 	siginfo_t *si = &psig->si;
    689 	const char *code;
    690 
    691 	(void)printf("SIG%s ", signame(psig->ps.signo, 0));
    692 	if (psig->ps.action == SIG_DFL)
    693 		(void)printf("SIG_DFL");
    694 	else {
    695 		(void)printf("caught handler=%p mask=(", psig->ps.action);
    696 		first = 1;
    697 		for (signo = 1; signo < NSIG; signo++) {
    698 			if (sigismember(&psig->ps.mask, signo)) {
    699 				if (first)
    700 					first = 0;
    701 				else
    702 					(void)printf(",");
    703 				(void)printf("%d", signo);
    704 			}
    705 		}
    706 		(void)printf(")");
    707 	}
    708 	switch (len) {
    709 	case sizeof(struct ktr_psig):
    710 		if (psig->ps.code)
    711 			printf(" code=0x%x", psig->ps.code);
    712 		printf(psig->ps.action == SIG_DFL ? "\n" : ")\n");
    713 		return;
    714 	case sizeof(*psig):
    715 		if (si->si_code == 0) {
    716 			printf(": code=SI_USER sent by pid=%d, uid=%d)\n",
    717 			    si->si_pid, si->si_uid);
    718 			return;
    719 		}
    720 
    721 		if (si->si_code < 0) {
    722 			switch (si->si_code) {
    723 			case SI_TIMER:
    724 				printf(": code=SI_TIMER sigval %p)\n",
    725 				    si->si_sigval.sival_ptr);
    726 				return;
    727 			case SI_QUEUE:
    728 				code = "SI_QUEUE";
    729 				break;
    730 			case SI_ASYNCIO:
    731 				code = "SI_ASYNCIO";
    732 				break;
    733 			case SI_MESGQ:
    734 				code = "SI_MESGQ";
    735 				break;
    736 			default:
    737 				code = NULL;
    738 				break;
    739 			}
    740 			if (code)
    741 				printf(": code=%s unimplemented)\n", code);
    742 			else
    743 				printf(": code=%d unimplemented)\n",
    744 				    si->si_code);
    745 			return;
    746 		}
    747 
    748 		code = siginfocodename(si->si_signo, si->si_code);
    749 		switch (si->si_signo) {
    750 		case SIGCHLD:
    751 			printf(": code=%s child pid=%d, uid=%d, "
    752 			    " status=%u, utime=%lu, stime=%lu)\n",
    753 			    code, si->si_pid,
    754 			    si->si_uid, si->si_status,
    755 			    (unsigned long) si->si_utime,
    756 			    (unsigned long) si->si_stime);
    757 			return;
    758 		case SIGILL:
    759 		case SIGFPE:
    760 		case SIGSEGV:
    761 		case SIGBUS:
    762 		case SIGTRAP:
    763 			printf(": code=%s, addr=%p, trap=%d)\n",
    764 			    code, si->si_addr, si->si_trap);
    765 			return;
    766 		case SIGIO:
    767 			printf(": code=%s, fd=%d, band=%lx)\n",
    768 			    code, si->si_fd, si->si_band);
    769 			return;
    770 		default:
    771 			printf(": code=%s, errno=%d)\n",
    772 			    code, si->si_errno);
    773 			return;
    774 		}
    775 		/*NOTREACHED*/
    776 	default:
    777 		warnx("Unhandled size %d for ktrpsig\n", len);
    778 		break;
    779 	}
    780 }
    781 
    782 void
    783 ktrcsw(cs)
    784 	struct ktr_csw *cs;
    785 {
    786 
    787 	(void)printf("%s %s\n", cs->out ? "stop" : "resume",
    788 	    cs->user ? "user" : "kernel");
    789 }
    790 
    791 void
    792 ktruser(usr, len)
    793 	struct ktr_user *usr;
    794 	int len;
    795 {
    796 	int i;
    797 	unsigned char *dta;
    798 
    799 	printf("\"%.*s: %d, ", KTR_USER_MAXIDLEN, usr->ktr_id, len);
    800 	dta = (unsigned char *)usr;
    801 	for(i=sizeof(struct ktr_user); i < len; i++)
    802 		printf("%02x", (unsigned int) dta[i]);
    803 	printf("\"\n");
    804 }
    805 
    806 void
    807 ktrmmsg(mmsg, len)
    808 	struct ktr_mmsg *mmsg;
    809 	int len;
    810 {
    811 	printf("id %d [0x%x -> 0x%x] flags 0x%x\n",
    812 	    mmsg->ktr_id, mmsg->ktr_local_port,
    813 	    mmsg->ktr_remote_port, mmsg->ktr_bits);
    814 
    815 	hexdump_buf(mmsg, len);
    816 }
    817 
    818 static const char *
    819 signame(long sig, int xlat)
    820 {
    821 	static char buf[64];
    822 	if (sig == 0)
    823 		return " 0";
    824 	else if (sig < 0 || sig >= NSIG) {
    825 		(void)snprintf(buf, sizeof(buf), "*unknown %ld*", sig);
    826 		return buf;
    827 	} else
    828 		return sys_signame[(xlat && current->signalmap != NULL) ?
    829 		    current->signalmap[sig] : sig];
    830 }
    831 
    832 void
    833 usage()
    834 {
    835 
    836 	(void)fprintf(stderr, "usage: kdump [-dlNnRTx] [-e emulation] "
    837 	   "[-f file] [-m maxdata] [-p pid]\n             [-t trstr] "
    838 	   "[file]\n");
    839 	exit(1);
    840 }
    841