Annotation of src/usr.bin/kdump/kdump.c, Revision 1.1
1.1 ! deraadt 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:
! 34: #ifndef lint
! 35: static char copyright[] =
! 36: "@(#) Copyright (c) 1988, 1993\n\
! 37: The Regents of the University of California. All rights reserved.\n";
! 38: #endif /* not lint */
! 39:
! 40: #ifndef lint
! 41: #if 0
! 42: static char sccsid[] = "@(#)kdump.c 8.4 (Berkeley) 4/28/95";
! 43: #endif
! 44: static char *rcsid = "$NetBSD: kdump.c,v 1.12 1995/08/31 23:18:33 jtc Exp $";
! 45: #endif /* not lint */
! 46:
! 47: #include <sys/param.h>
! 48: #include <sys/errno.h>
! 49: #include <sys/time.h>
! 50: #include <sys/uio.h>
! 51: #include <sys/ktrace.h>
! 52: #include <sys/ioctl.h>
! 53: #include <sys/ptrace.h>
! 54: #define _KERNEL
! 55: #include <sys/errno.h>
! 56: #undef _KERNEL
! 57:
! 58: #include <err.h>
! 59: #include <signal.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:
! 68: int timestamp, decimal, fancy = 1, tail, maxdata;
! 69: char *tracefile = DEF_TRACEFILE;
! 70: struct ktr_header ktr_header;
! 71:
! 72: #define eqs(s1, s2) (strcmp((s1), (s2)) == 0)
! 73:
! 74: #include <sys/syscall.h>
! 75:
! 76: #include "../../sys/compat/hpux/hpux_syscall.h"
! 77: #include "../../sys/compat/ibcs2/ibcs2_syscall.h"
! 78: #include "../../sys/compat/linux/linux_syscall.h"
! 79: #include "../../sys/compat/osf1/osf1_syscall.h"
! 80: #include "../../sys/compat/sunos/sunos_syscall.h"
! 81: #include "../../sys/compat/svr4/svr4_syscall.h"
! 82: #include "../../sys/compat/ultrix/ultrix_syscall.h"
! 83:
! 84: #define KTRACE
! 85: #include "../../sys/kern/syscalls.c"
! 86:
! 87: #include "../../sys/compat/hpux/hpux_syscalls.c"
! 88: #include "../../sys/compat/ibcs2/ibcs2_syscalls.c"
! 89: #include "../../sys/compat/linux/linux_syscalls.c"
! 90: #include "../../sys/compat/osf1/osf1_syscalls.c"
! 91: #include "../../sys/compat/sunos/sunos_syscalls.c"
! 92: #include "../../sys/compat/svr4/svr4_syscalls.c"
! 93: #include "../../sys/compat/ultrix/ultrix_syscalls.c"
! 94: #undef KTRACE
! 95:
! 96: struct emulation {
! 97: char *name; /* Emulation name */
! 98: char **sysnames; /* Array of system call names */
! 99: int nsysnames; /* Number of */
! 100: };
! 101:
! 102: static struct emulation emulations[] = {
! 103: { "netbsd", syscallnames, SYS_MAXSYSCALL },
! 104: { "hpux", hpux_syscallnames, HPUX_SYS_MAXSYSCALL },
! 105: { "ibcs2", ibcs2_syscallnames, IBCS2_SYS_MAXSYSCALL },
! 106: { "linux", linux_syscallnames, LINUX_SYS_MAXSYSCALL },
! 107: { "osf1", osf1_syscallnames, OSF1_SYS_MAXSYSCALL },
! 108: { "sunos", sunos_syscallnames, SUNOS_SYS_MAXSYSCALL },
! 109: { "svr4", svr4_syscallnames, SVR4_SYS_MAXSYSCALL },
! 110: { "ultrix", ultrix_syscallnames, ULTRIX_SYS_MAXSYSCALL },
! 111: { NULL, NULL, NULL }
! 112: };
! 113:
! 114: struct emulation *current;
! 115:
! 116:
! 117: static char *ptrace_ops[] = {
! 118: "PT_TRACE_ME", "PT_READ_I", "PT_READ_D", "PT_READ_U",
! 119: "PT_WRITE_I", "PT_WRITE_D", "PT_WRITE_U", "PT_CONTINUE",
! 120: "PT_KILL", "PT_ATTACH", "PT_DETACH",
! 121: };
! 122:
! 123: int
! 124: main(argc, argv)
! 125: int argc;
! 126: char *argv[];
! 127: {
! 128: int ch, ktrlen, size;
! 129: register void *m;
! 130: int trpoints = ALL_POINTS;
! 131:
! 132: current = &emulations[0]; /* NetBSD */
! 133:
! 134: while ((ch = getopt(argc, argv, "e:f:dlm:nRTt:")) != -1)
! 135: switch (ch) {
! 136: case 'e':
! 137: setemul(optarg);
! 138: break;
! 139: case 'f':
! 140: tracefile = optarg;
! 141: break;
! 142: case 'd':
! 143: decimal = 1;
! 144: break;
! 145: case 'l':
! 146: tail = 1;
! 147: break;
! 148: case 'm':
! 149: maxdata = atoi(optarg);
! 150: break;
! 151: case 'n':
! 152: fancy = 0;
! 153: break;
! 154: case 'R':
! 155: timestamp = 2; /* relative timestamp */
! 156: break;
! 157: case 'T':
! 158: timestamp = 1;
! 159: break;
! 160: case 't':
! 161: trpoints = getpoints(optarg);
! 162: if (trpoints < 0)
! 163: errx(1, "unknown trace point in %s", optarg);
! 164: break;
! 165: default:
! 166: usage();
! 167: }
! 168: argv += optind;
! 169: argc -= optind;
! 170:
! 171: if (argc > 1)
! 172: usage();
! 173:
! 174: m = (void *)malloc(size = 1025);
! 175: if (m == NULL)
! 176: errx(1, "%s", strerror(ENOMEM));
! 177: if (!freopen(tracefile, "r", stdin))
! 178: err(1, "%s", tracefile);
! 179: while (fread_tail(&ktr_header, sizeof(struct ktr_header), 1)) {
! 180: if (trpoints & (1<<ktr_header.ktr_type))
! 181: dumpheader(&ktr_header);
! 182: if ((ktrlen = ktr_header.ktr_len) < 0)
! 183: errx(1, "bogus length 0x%x", ktrlen);
! 184: if (ktrlen > size) {
! 185: m = (void *)realloc(m, ktrlen+1);
! 186: if (m == NULL)
! 187: errx(1, "%s", strerror(ENOMEM));
! 188: size = ktrlen;
! 189: }
! 190: if (ktrlen && fread_tail(m, ktrlen, 1) == 0)
! 191: errx(1, "data too short");
! 192: if ((trpoints & (1<<ktr_header.ktr_type)) == 0)
! 193: continue;
! 194: switch (ktr_header.ktr_type) {
! 195: case KTR_SYSCALL:
! 196: ktrsyscall((struct ktr_syscall *)m);
! 197: break;
! 198: case KTR_SYSRET:
! 199: ktrsysret((struct ktr_sysret *)m);
! 200: break;
! 201: case KTR_NAMEI:
! 202: ktrnamei(m, ktrlen);
! 203: break;
! 204: case KTR_GENIO:
! 205: ktrgenio((struct ktr_genio *)m, ktrlen);
! 206: break;
! 207: case KTR_PSIG:
! 208: ktrpsig((struct ktr_psig *)m);
! 209: break;
! 210: case KTR_CSW:
! 211: ktrcsw((struct ktr_csw *)m);
! 212: break;
! 213: case KTR_EMUL:
! 214: ktremul(m, ktrlen);
! 215: break;
! 216: }
! 217: if (tail)
! 218: (void)fflush(stdout);
! 219: }
! 220: }
! 221:
! 222: fread_tail(buf, size, num)
! 223: char *buf;
! 224: int num, size;
! 225: {
! 226: int i;
! 227:
! 228: while ((i = fread(buf, size, num, stdin)) == 0 && tail) {
! 229: (void)sleep(1);
! 230: clearerr(stdin);
! 231: }
! 232: return (i);
! 233: }
! 234:
! 235: dumpheader(kth)
! 236: struct ktr_header *kth;
! 237: {
! 238: char unknown[64], *type;
! 239: static struct timeval prevtime;
! 240: struct timeval temp;
! 241:
! 242: switch (kth->ktr_type) {
! 243: case KTR_SYSCALL:
! 244: type = "CALL";
! 245: break;
! 246: case KTR_SYSRET:
! 247: type = "RET ";
! 248: break;
! 249: case KTR_NAMEI:
! 250: type = "NAMI";
! 251: break;
! 252: case KTR_GENIO:
! 253: type = "GIO ";
! 254: break;
! 255: case KTR_PSIG:
! 256: type = "PSIG";
! 257: break;
! 258: case KTR_CSW:
! 259: type = "CSW";
! 260: break;
! 261: case KTR_EMUL:
! 262: type = "EMUL";
! 263: break;
! 264: default:
! 265: (void)sprintf(unknown, "UNKNOWN(%d)", kth->ktr_type);
! 266: type = unknown;
! 267: }
! 268:
! 269: (void)printf("%6d %-8.*s ", kth->ktr_pid, MAXCOMLEN, kth->ktr_comm);
! 270: if (timestamp) {
! 271: if (timestamp == 2) {
! 272: timersub(&kth->ktr_time, &prevtime, &temp);
! 273: prevtime = kth->ktr_time;
! 274: } else
! 275: temp = kth->ktr_time;
! 276: (void)printf("%ld.%06ld ", temp.tv_sec, temp.tv_usec);
! 277: }
! 278: (void)printf("%s ", type);
! 279: }
! 280:
! 281:
! 282: ktrsyscall(ktr)
! 283: register struct ktr_syscall *ktr;
! 284: {
! 285: register argsize = ktr->ktr_argsize;
! 286: register register_t *ap;
! 287: char *ioctlname();
! 288:
! 289: if (ktr->ktr_code >= current->nsysnames || ktr->ktr_code < 0)
! 290: (void)printf("[%d]", ktr->ktr_code);
! 291: else
! 292: (void)printf("%s", current->sysnames[ktr->ktr_code]);
! 293: ap = (register_t *)((char *)ktr + sizeof(struct ktr_syscall));
! 294: if (argsize) {
! 295: char c = '(';
! 296: if (fancy) {
! 297: if (ktr->ktr_code == SYS_ioctl) {
! 298: char *cp;
! 299: if (decimal)
! 300: (void)printf("(%ld", (long)*ap);
! 301: else
! 302: (void)printf("(%#lx", (long)*ap);
! 303: ap++;
! 304: argsize -= sizeof(register_t);
! 305: if ((cp = ioctlname(*ap)) != NULL)
! 306: (void)printf(",%s", cp);
! 307: else {
! 308: if (decimal)
! 309: (void)printf(",%ld",
! 310: (long)*ap);
! 311: else
! 312: (void)printf(",%#lx ",
! 313: (long)*ap);
! 314: }
! 315: c = ',';
! 316: ap++;
! 317: argsize -= sizeof(register_t);
! 318: } else if (ktr->ktr_code == SYS_ptrace) {
! 319: if (*ap >= 0 && *ap <=
! 320: sizeof(ptrace_ops) / sizeof(ptrace_ops[0]))
! 321: (void)printf("(%s", ptrace_ops[*ap]);
! 322: else
! 323: (void)printf("(%ld", (long)*ap);
! 324: c = ',';
! 325: ap++;
! 326: argsize -= sizeof(register_t);
! 327: }
! 328: }
! 329: while (argsize) {
! 330: if (decimal)
! 331: (void)printf("%c%ld", c, (long)*ap);
! 332: else
! 333: (void)printf("%c%#lx", c, (long)*ap);
! 334: c = ',';
! 335: ap++;
! 336: argsize -= sizeof(register_t);
! 337: }
! 338: (void)putchar(')');
! 339: }
! 340: (void)putchar('\n');
! 341: }
! 342:
! 343: ktrsysret(ktr)
! 344: struct ktr_sysret *ktr;
! 345: {
! 346: register int ret = ktr->ktr_retval;
! 347: register int error = ktr->ktr_error;
! 348: register int code = ktr->ktr_code;
! 349:
! 350: if (code >= current->nsysnames || code < 0)
! 351: (void)printf("[%d] ", code);
! 352: else
! 353: (void)printf("%s ", current->sysnames[code]);
! 354:
! 355: if (error == 0) {
! 356: if (fancy) {
! 357: (void)printf("%d", ret);
! 358: if (ret < 0 || ret > 9)
! 359: (void)printf("/%#x", ret);
! 360: } else {
! 361: if (decimal)
! 362: (void)printf("%d", ret);
! 363: else
! 364: (void)printf("%#x", ret);
! 365: }
! 366: } else if (error == ERESTART)
! 367: (void)printf("RESTART");
! 368: else if (error == EJUSTRETURN)
! 369: (void)printf("JUSTRETURN");
! 370: else {
! 371: (void)printf("-1 errno %d", ktr->ktr_error);
! 372: if (fancy)
! 373: (void)printf(" %s", strerror(ktr->ktr_error));
! 374: }
! 375: (void)putchar('\n');
! 376: }
! 377:
! 378: ktrnamei(cp, len)
! 379: char *cp;
! 380: {
! 381: (void)printf("\"%.*s\"\n", len, cp);
! 382: }
! 383:
! 384: ktremul(cp, len)
! 385: char *cp;
! 386: {
! 387: char name[1024];
! 388:
! 389: if (len >= sizeof(name))
! 390: errx(1, "Emulation name too long");
! 391:
! 392: strncpy(name, cp, len);
! 393: name[len] = '\0';
! 394: (void)printf("\"%s\"\n", name);
! 395:
! 396: setemul(name);
! 397: }
! 398:
! 399: ktrgenio(ktr, len)
! 400: struct ktr_genio *ktr;
! 401: {
! 402: register int datalen = len - sizeof (struct ktr_genio);
! 403: register char *dp = (char *)ktr + sizeof (struct ktr_genio);
! 404: register char *cp;
! 405: register int col = 0;
! 406: register width;
! 407: char visbuf[5];
! 408: static screenwidth = 0;
! 409:
! 410: if (screenwidth == 0) {
! 411: struct winsize ws;
! 412:
! 413: if (fancy && ioctl(fileno(stderr), TIOCGWINSZ, &ws) != -1 &&
! 414: ws.ws_col > 8)
! 415: screenwidth = ws.ws_col;
! 416: else
! 417: screenwidth = 80;
! 418: }
! 419: printf("fd %d %s %d bytes\n", ktr->ktr_fd,
! 420: ktr->ktr_rw == UIO_READ ? "read" : "wrote", datalen);
! 421: if (maxdata && datalen > maxdata)
! 422: datalen = maxdata;
! 423: (void)printf(" \"");
! 424: col = 8;
! 425: for (; datalen > 0; datalen--, dp++) {
! 426: (void) vis(visbuf, *dp, VIS_CSTYLE, *(dp+1));
! 427: cp = visbuf;
! 428: /*
! 429: * Keep track of printables and
! 430: * space chars (like fold(1)).
! 431: */
! 432: if (col == 0) {
! 433: (void)putchar('\t');
! 434: col = 8;
! 435: }
! 436: switch(*cp) {
! 437: case '\n':
! 438: col = 0;
! 439: (void)putchar('\n');
! 440: continue;
! 441: case '\t':
! 442: width = 8 - (col&07);
! 443: break;
! 444: default:
! 445: width = strlen(cp);
! 446: }
! 447: if (col + width > (screenwidth-2)) {
! 448: (void)printf("\\\n\t");
! 449: col = 8;
! 450: }
! 451: col += width;
! 452: do {
! 453: (void)putchar(*cp++);
! 454: } while (*cp);
! 455: }
! 456: if (col == 0)
! 457: (void)printf(" ");
! 458: (void)printf("\"\n");
! 459: }
! 460:
! 461: ktrpsig(psig)
! 462: struct ktr_psig *psig;
! 463: {
! 464: (void)printf("SIG%s ", sys_signame[psig->signo]);
! 465: if (psig->action == SIG_DFL)
! 466: (void)printf("SIG_DFL\n");
! 467: else
! 468: (void)printf("caught handler=0x%lx mask=0x%x code=0x%x\n",
! 469: (u_long)psig->action, psig->mask, psig->code);
! 470: }
! 471:
! 472: ktrcsw(cs)
! 473: struct ktr_csw *cs;
! 474: {
! 475: (void)printf("%s %s\n", cs->out ? "stop" : "resume",
! 476: cs->user ? "user" : "kernel");
! 477: }
! 478:
! 479: usage()
! 480: {
! 481:
! 482: (void)fprintf(stderr,
! 483: "usage: kdump [-dnlRT] [-e emulation] [-f trfile] [-m maxdata] [-t [cnis]]\n");
! 484: exit(1);
! 485: }
! 486:
! 487: setemul(name)
! 488: char *name;
! 489: {
! 490: int i;
! 491: for (i = 0; emulations[i].name != NULL; i++)
! 492: if (strcmp(emulations[i].name, name) == 0) {
! 493: current = &emulations[i];
! 494: return;
! 495: }
! 496: warnx("Emulation `%s' unknown", name);
! 497: }