[BACK]Return to kdump.c CVS log [TXT][DIR] Up to [local] / src / usr.bin / kdump

Annotation of src/usr.bin/kdump/kdump.c, Revision 1.11

1.11    ! deraadt     1: /*     $OpenBSD: kdump.c,v 1.10 1999/09/25 19:35:47 kstailey Exp $     */
1.4       deraadt     2:
1.1       deraadt     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. All advertising materials mentioning features or use of this software
                     16:  *    must display the following acknowledgement:
                     17:  *     This product includes software developed by the University of
                     18:  *     California, Berkeley and its contributors.
                     19:  * 4. Neither the name of the University nor the names of its contributors
                     20:  *    may be used to endorse or promote products derived from this software
                     21:  *    without specific prior written permission.
                     22:  *
                     23:  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
                     24:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
                     25:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
                     26:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
                     27:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
                     28:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
                     29:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
                     30:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
                     31:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
                     32:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
                     33:  * SUCH DAMAGE.
                     34:  */
                     35:
                     36: #ifndef lint
                     37: static char copyright[] =
                     38: "@(#) Copyright (c) 1988, 1993\n\
                     39:        The Regents of the University of California.  All rights reserved.\n";
                     40: #endif /* not lint */
                     41:
                     42: #ifndef lint
                     43: #if 0
                     44: static char sccsid[] = "@(#)kdump.c    8.4 (Berkeley) 4/28/95";
                     45: #endif
1.11    ! deraadt    46: static char *rcsid = "$OpenBSD: kdump.c,v 1.10 1999/09/25 19:35:47 kstailey Exp $";
1.1       deraadt    47: #endif /* not lint */
                     48:
                     49: #include <sys/param.h>
                     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: #define _KERNEL
                     56: #include <sys/errno.h>
                     57: #undef _KERNEL
                     58:
                     59: #include <err.h>
                     60: #include <signal.h>
                     61: #include <stdio.h>
                     62: #include <stdlib.h>
                     63: #include <string.h>
                     64: #include <unistd.h>
                     65: #include <vis.h>
                     66:
                     67: #include "ktrace.h"
                     68:
                     69: int timestamp, decimal, fancy = 1, tail, maxdata;
                     70: char *tracefile = DEF_TRACEFILE;
                     71: struct ktr_header ktr_header;
                     72:
                     73: #define eqs(s1, s2)    (strcmp((s1), (s2)) == 0)
                     74:
                     75: #include <sys/syscall.h>
                     76:
1.9       deraadt    77: #include "../../sys/compat/bsdos/bsdos_syscall.h"
                     78: #include "../../sys/compat/freebsd/freebsd_syscall.h"
1.10      kstailey   79: #include "../../sys/compat/netbsd/netbsd_syscall.h"
1.1       deraadt    80: #include "../../sys/compat/hpux/hpux_syscall.h"
                     81: #include "../../sys/compat/ibcs2/ibcs2_syscall.h"
                     82: #include "../../sys/compat/linux/linux_syscall.h"
                     83: #include "../../sys/compat/osf1/osf1_syscall.h"
                     84: #include "../../sys/compat/sunos/sunos_syscall.h"
                     85: #include "../../sys/compat/svr4/svr4_syscall.h"
                     86: #include "../../sys/compat/ultrix/ultrix_syscall.h"
                     87:
                     88: #define KTRACE
1.7       deraadt    89: #define NFSCLIENT
                     90: #define NFSSERVER
                     91: #define SYSVSEM
                     92: #define SYSVMSG
                     93: #define SYSVSHM
                     94: #define LFS
                     95: #define NTP
1.1       deraadt    96: #include "../../sys/kern/syscalls.c"
                     97:
1.9       deraadt    98: #include "../../sys/compat/bsdos/bsdos_syscalls.c"
                     99: #include "../../sys/compat/freebsd/freebsd_syscalls.c"
1.10      kstailey  100: #include "../../sys/compat/netbsd/netbsd_syscalls.c"
1.1       deraadt   101: #include "../../sys/compat/hpux/hpux_syscalls.c"
                    102: #include "../../sys/compat/ibcs2/ibcs2_syscalls.c"
                    103: #include "../../sys/compat/linux/linux_syscalls.c"
                    104: #include "../../sys/compat/osf1/osf1_syscalls.c"
                    105: #include "../../sys/compat/sunos/sunos_syscalls.c"
                    106: #include "../../sys/compat/svr4/svr4_syscalls.c"
                    107: #include "../../sys/compat/ultrix/ultrix_syscalls.c"
                    108: #undef KTRACE
1.7       deraadt   109: #undef NFSCLIENT
                    110: #undef NFSSERVER
                    111: #undef SYSVSEM
                    112: #undef SYSVMSG
                    113: #undef SYSVSHM
                    114: #undef LFS
                    115: #undef NTP
1.1       deraadt   116:
                    117: struct emulation {
                    118:        char *name;             /* Emulation name */
                    119:        char **sysnames;        /* Array of system call names */
                    120:        int  nsysnames;         /* Number of */
                    121: };
                    122:
                    123: static struct emulation emulations[] = {
1.9       deraadt   124:        { "native",     syscallnames,           SYS_MAXSYSCALL },
                    125:        { "hpux",       hpux_syscallnames,      HPUX_SYS_MAXSYSCALL },
                    126:        { "ibcs2",      ibcs2_syscallnames,     IBCS2_SYS_MAXSYSCALL },
                    127:        { "linux",      linux_syscallnames,     LINUX_SYS_MAXSYSCALL },
                    128:        { "osf1",       osf1_syscallnames,      OSF1_SYS_MAXSYSCALL },
                    129:        { "sunos",      sunos_syscallnames,     SUNOS_SYS_MAXSYSCALL },
                    130:        { "svr4",       svr4_syscallnames,      SVR4_SYS_MAXSYSCALL },
                    131:        { "ultrix",     ultrix_syscallnames,    ULTRIX_SYS_MAXSYSCALL },
                    132:        { "bsdos",      bsdos_syscallnames,     BSDOS_SYS_MAXSYSCALL },
                    133:        { "freebsd",    freebsd_syscallnames,   FREEBSD_SYS_MAXSYSCALL },
1.10      kstailey  134:        { "netbsd",     netbsd_syscallnames,    NETBSD_SYS_MAXSYSCALL },
1.9       deraadt   135:        { NULL,         NULL,                   NULL }
1.1       deraadt   136: };
                    137:
                    138: struct emulation *current;
                    139:
                    140:
                    141: static char *ptrace_ops[] = {
                    142:        "PT_TRACE_ME",  "PT_READ_I",    "PT_READ_D",    "PT_READ_U",
                    143:        "PT_WRITE_I",   "PT_WRITE_D",   "PT_WRITE_U",   "PT_CONTINUE",
                    144:        "PT_KILL",      "PT_ATTACH",    "PT_DETACH",
                    145: };
                    146:
                    147: int
                    148: main(argc, argv)
                    149:        int argc;
                    150:        char *argv[];
                    151: {
                    152:        int ch, ktrlen, size;
                    153:        register void *m;
                    154:        int trpoints = ALL_POINTS;
                    155:
1.3       deraadt   156:        current = &emulations[0];       /* native */
1.1       deraadt   157:
                    158:        while ((ch = getopt(argc, argv, "e:f:dlm:nRTt:")) != -1)
                    159:                switch (ch) {
                    160:                case 'e':
                    161:                        setemul(optarg);
                    162:                        break;
                    163:                case 'f':
                    164:                        tracefile = optarg;
                    165:                        break;
                    166:                case 'd':
                    167:                        decimal = 1;
                    168:                        break;
                    169:                case 'l':
                    170:                        tail = 1;
                    171:                        break;
                    172:                case 'm':
                    173:                        maxdata = atoi(optarg);
                    174:                        break;
                    175:                case 'n':
                    176:                        fancy = 0;
                    177:                        break;
                    178:                case 'R':
                    179:                        timestamp = 2;  /* relative timestamp */
                    180:                        break;
                    181:                case 'T':
                    182:                        timestamp = 1;
                    183:                        break;
                    184:                case 't':
                    185:                        trpoints = getpoints(optarg);
                    186:                        if (trpoints < 0)
                    187:                                errx(1, "unknown trace point in %s", optarg);
                    188:                        break;
                    189:                default:
                    190:                        usage();
                    191:                }
1.5       deraadt   192:        if (argc > optind)
1.1       deraadt   193:                usage();
                    194:
                    195:        m = (void *)malloc(size = 1025);
                    196:        if (m == NULL)
                    197:                errx(1, "%s", strerror(ENOMEM));
                    198:        if (!freopen(tracefile, "r", stdin))
                    199:                err(1, "%s", tracefile);
                    200:        while (fread_tail(&ktr_header, sizeof(struct ktr_header), 1)) {
                    201:                if (trpoints & (1<<ktr_header.ktr_type))
                    202:                        dumpheader(&ktr_header);
                    203:                if ((ktrlen = ktr_header.ktr_len) < 0)
                    204:                        errx(1, "bogus length 0x%x", ktrlen);
                    205:                if (ktrlen > size) {
                    206:                        m = (void *)realloc(m, ktrlen+1);
                    207:                        if (m == NULL)
                    208:                                errx(1, "%s", strerror(ENOMEM));
                    209:                        size = ktrlen;
                    210:                }
                    211:                if (ktrlen && fread_tail(m, ktrlen, 1) == 0)
                    212:                        errx(1, "data too short");
                    213:                if ((trpoints & (1<<ktr_header.ktr_type)) == 0)
                    214:                        continue;
                    215:                switch (ktr_header.ktr_type) {
                    216:                case KTR_SYSCALL:
                    217:                        ktrsyscall((struct ktr_syscall *)m);
                    218:                        break;
                    219:                case KTR_SYSRET:
                    220:                        ktrsysret((struct ktr_sysret *)m);
                    221:                        break;
                    222:                case KTR_NAMEI:
                    223:                        ktrnamei(m, ktrlen);
                    224:                        break;
                    225:                case KTR_GENIO:
                    226:                        ktrgenio((struct ktr_genio *)m, ktrlen);
                    227:                        break;
                    228:                case KTR_PSIG:
                    229:                        ktrpsig((struct ktr_psig *)m);
                    230:                        break;
                    231:                case KTR_CSW:
                    232:                        ktrcsw((struct ktr_csw *)m);
                    233:                        break;
                    234:                case KTR_EMUL:
                    235:                        ktremul(m, ktrlen);
                    236:                        break;
                    237:                }
                    238:                if (tail)
                    239:                        (void)fflush(stdout);
                    240:        }
                    241: }
                    242:
1.11    ! deraadt   243: int
1.1       deraadt   244: fread_tail(buf, size, num)
                    245:        char *buf;
                    246:        int num, size;
                    247: {
                    248:        int i;
                    249:
                    250:        while ((i = fread(buf, size, num, stdin)) == 0 && tail) {
                    251:                (void)sleep(1);
                    252:                clearerr(stdin);
                    253:        }
                    254:        return (i);
                    255: }
                    256:
1.11    ! deraadt   257: void
1.1       deraadt   258: dumpheader(kth)
                    259:        struct ktr_header *kth;
                    260: {
                    261:        char unknown[64], *type;
                    262:        static struct timeval prevtime;
                    263:        struct timeval temp;
                    264:
                    265:        switch (kth->ktr_type) {
                    266:        case KTR_SYSCALL:
                    267:                type = "CALL";
                    268:                break;
                    269:        case KTR_SYSRET:
                    270:                type = "RET ";
                    271:                break;
                    272:        case KTR_NAMEI:
                    273:                type = "NAMI";
                    274:                break;
                    275:        case KTR_GENIO:
                    276:                type = "GIO ";
                    277:                break;
                    278:        case KTR_PSIG:
                    279:                type = "PSIG";
                    280:                break;
                    281:        case KTR_CSW:
                    282:                type = "CSW";
                    283:                break;
                    284:        case KTR_EMUL:
                    285:                type = "EMUL";
                    286:                break;
                    287:        default:
                    288:                (void)sprintf(unknown, "UNKNOWN(%d)", kth->ktr_type);
                    289:                type = unknown;
                    290:        }
                    291:
                    292:        (void)printf("%6d %-8.*s ", kth->ktr_pid, MAXCOMLEN, kth->ktr_comm);
                    293:        if (timestamp) {
                    294:                if (timestamp == 2) {
                    295:                        timersub(&kth->ktr_time, &prevtime, &temp);
                    296:                        prevtime = kth->ktr_time;
                    297:                } else
                    298:                        temp = kth->ktr_time;
                    299:                (void)printf("%ld.%06ld ", temp.tv_sec, temp.tv_usec);
                    300:        }
                    301:        (void)printf("%s  ", type);
                    302: }
                    303:
1.2       deraadt   304: void
                    305: ioctldecode(cmd)
                    306:        u_long cmd;
                    307: {
                    308:        char dirbuf[4], *dir = dirbuf;
                    309:
1.6       deraadt   310:        if (cmd & IOC_IN)
                    311:                *dir++ = 'W';
1.2       deraadt   312:        if (cmd & IOC_OUT)
                    313:                *dir++ = 'R';
                    314:        *dir = '\0';
                    315:
                    316:        printf(decimal ? ",_IO%s('%c',%ld" : ",_IO%s('%c',%#lx",
                    317:            dirbuf, (cmd >> 8) & 0xff, cmd & 0xff);
                    318:        if ((cmd & IOC_VOID) == 0)
                    319:                printf(decimal ? ",%ld)" : ",%#lx)", (cmd >> 16) & 0xff);
                    320:        else
                    321:                printf(")");
                    322: }
1.1       deraadt   323:
1.11    ! deraadt   324: void
1.1       deraadt   325: ktrsyscall(ktr)
                    326:        register struct ktr_syscall *ktr;
                    327: {
                    328:        register argsize = ktr->ktr_argsize;
                    329:        register register_t *ap;
                    330:        char *ioctlname();
                    331:
                    332:        if (ktr->ktr_code >= current->nsysnames || ktr->ktr_code < 0)
                    333:                (void)printf("[%d]", ktr->ktr_code);
                    334:        else
                    335:                (void)printf("%s", current->sysnames[ktr->ktr_code]);
                    336:        ap = (register_t *)((char *)ktr + sizeof(struct ktr_syscall));
                    337:        if (argsize) {
                    338:                char c = '(';
                    339:                if (fancy) {
                    340:                        if (ktr->ktr_code == SYS_ioctl) {
                    341:                                char *cp;
                    342:                                if (decimal)
                    343:                                        (void)printf("(%ld", (long)*ap);
                    344:                                else
                    345:                                        (void)printf("(%#lx", (long)*ap);
                    346:                                ap++;
                    347:                                argsize -= sizeof(register_t);
                    348:                                if ((cp = ioctlname(*ap)) != NULL)
                    349:                                        (void)printf(",%s", cp);
1.2       deraadt   350:                                else
                    351:                                        ioctldecode(*ap);
1.1       deraadt   352:                                c = ',';
                    353:                                ap++;
                    354:                                argsize -= sizeof(register_t);
                    355:                        } else if (ktr->ktr_code == SYS_ptrace) {
                    356:                                if (*ap >= 0 && *ap <=
                    357:                                    sizeof(ptrace_ops) / sizeof(ptrace_ops[0]))
                    358:                                        (void)printf("(%s", ptrace_ops[*ap]);
                    359:                                else
                    360:                                        (void)printf("(%ld", (long)*ap);
                    361:                                c = ',';
                    362:                                ap++;
                    363:                                argsize -= sizeof(register_t);
                    364:                        }
                    365:                }
                    366:                while (argsize) {
                    367:                        if (decimal)
                    368:                                (void)printf("%c%ld", c, (long)*ap);
                    369:                        else
                    370:                                (void)printf("%c%#lx", c, (long)*ap);
                    371:                        c = ',';
                    372:                        ap++;
                    373:                        argsize -= sizeof(register_t);
                    374:                }
                    375:                (void)putchar(')');
                    376:        }
                    377:        (void)putchar('\n');
                    378: }
                    379:
                    380: ktrsysret(ktr)
                    381:        struct ktr_sysret *ktr;
                    382: {
                    383:        register int ret = ktr->ktr_retval;
                    384:        register int error = ktr->ktr_error;
                    385:        register int code = ktr->ktr_code;
                    386:
                    387:        if (code >= current->nsysnames || code < 0)
                    388:                (void)printf("[%d] ", code);
                    389:        else
                    390:                (void)printf("%s ", current->sysnames[code]);
                    391:
                    392:        if (error == 0) {
                    393:                if (fancy) {
                    394:                        (void)printf("%d", ret);
                    395:                        if (ret < 0 || ret > 9)
                    396:                                (void)printf("/%#x", ret);
                    397:                } else {
                    398:                        if (decimal)
                    399:                                (void)printf("%d", ret);
                    400:                        else
                    401:                                (void)printf("%#x", ret);
                    402:                }
                    403:        } else if (error == ERESTART)
                    404:                (void)printf("RESTART");
                    405:        else if (error == EJUSTRETURN)
                    406:                (void)printf("JUSTRETURN");
                    407:        else {
                    408:                (void)printf("-1 errno %d", ktr->ktr_error);
                    409:                if (fancy)
                    410:                        (void)printf(" %s", strerror(ktr->ktr_error));
                    411:        }
                    412:        (void)putchar('\n');
                    413: }
                    414:
                    415: ktrnamei(cp, len)
                    416:        char *cp;
                    417: {
                    418:        (void)printf("\"%.*s\"\n", len, cp);
                    419: }
                    420:
                    421: ktremul(cp, len)
                    422:        char *cp;
                    423: {
                    424:        char name[1024];
                    425:
                    426:        if (len >= sizeof(name))
                    427:                errx(1, "Emulation name too long");
                    428:
                    429:        strncpy(name, cp, len);
                    430:        name[len] = '\0';
                    431:        (void)printf("\"%s\"\n", name);
                    432:
                    433:        setemul(name);
                    434: }
                    435:
                    436: ktrgenio(ktr, len)
                    437:        struct ktr_genio *ktr;
                    438: {
                    439:        register int datalen = len - sizeof (struct ktr_genio);
                    440:        register char *dp = (char *)ktr + sizeof (struct ktr_genio);
                    441:        register char *cp;
                    442:        register int col = 0;
                    443:        register width;
                    444:        char visbuf[5];
                    445:        static screenwidth = 0;
                    446:
                    447:        if (screenwidth == 0) {
                    448:                struct winsize ws;
                    449:
                    450:                if (fancy && ioctl(fileno(stderr), TIOCGWINSZ, &ws) != -1 &&
                    451:                    ws.ws_col > 8)
                    452:                        screenwidth = ws.ws_col;
                    453:                else
                    454:                        screenwidth = 80;
                    455:        }
                    456:        printf("fd %d %s %d bytes\n", ktr->ktr_fd,
                    457:                ktr->ktr_rw == UIO_READ ? "read" : "wrote", datalen);
                    458:        if (maxdata && datalen > maxdata)
                    459:                datalen = maxdata;
                    460:        (void)printf("       \"");
                    461:        col = 8;
                    462:        for (; datalen > 0; datalen--, dp++) {
                    463:                (void) vis(visbuf, *dp, VIS_CSTYLE, *(dp+1));
                    464:                cp = visbuf;
                    465:                /*
                    466:                 * Keep track of printables and
                    467:                 * space chars (like fold(1)).
                    468:                 */
                    469:                if (col == 0) {
                    470:                        (void)putchar('\t');
                    471:                        col = 8;
                    472:                }
                    473:                switch(*cp) {
                    474:                case '\n':
                    475:                        col = 0;
                    476:                        (void)putchar('\n');
                    477:                        continue;
                    478:                case '\t':
                    479:                        width = 8 - (col&07);
                    480:                        break;
                    481:                default:
                    482:                        width = strlen(cp);
                    483:                }
                    484:                if (col + width > (screenwidth-2)) {
                    485:                        (void)printf("\\\n\t");
                    486:                        col = 8;
                    487:                }
                    488:                col += width;
                    489:                do {
                    490:                        (void)putchar(*cp++);
                    491:                } while (*cp);
                    492:        }
                    493:        if (col == 0)
                    494:                (void)printf("       ");
                    495:        (void)printf("\"\n");
                    496: }
                    497:
1.11    ! deraadt   498: void
1.1       deraadt   499: ktrpsig(psig)
                    500:        struct ktr_psig *psig;
                    501: {
                    502:        (void)printf("SIG%s ", sys_signame[psig->signo]);
                    503:        if (psig->action == SIG_DFL)
                    504:                (void)printf("SIG_DFL\n");
                    505:        else
                    506:                (void)printf("caught handler=0x%lx mask=0x%x code=0x%x\n",
                    507:                    (u_long)psig->action, psig->mask, psig->code);
                    508: }
                    509:
1.11    ! deraadt   510: void
1.1       deraadt   511: ktrcsw(cs)
                    512:        struct ktr_csw *cs;
                    513: {
                    514:        (void)printf("%s %s\n", cs->out ? "stop" : "resume",
                    515:            cs->user ? "user" : "kernel");
                    516: }
                    517:
1.11    ! deraadt   518: void
1.1       deraadt   519: usage()
                    520: {
                    521:
                    522:        (void)fprintf(stderr,
                    523: "usage: kdump [-dnlRT] [-e emulation] [-f trfile] [-m maxdata] [-t [cnis]]\n");
                    524:        exit(1);
                    525: }
                    526:
1.11    ! deraadt   527: void
1.1       deraadt   528: setemul(name)
                    529:        char *name;
                    530: {
                    531:        int i;
                    532:        for (i = 0; emulations[i].name != NULL; i++)
                    533:                if (strcmp(emulations[i].name, name) == 0) {
                    534:                        current = &emulations[i];
                    535:                        return;
                    536:                }
                    537:        warnx("Emulation `%s' unknown", name);
                    538: }