[BACK]Return to kvm.c CVS log [TXT][DIR] Up to [cvs.NetBSD.org] / src / lib / libkvm

Annotation of src/lib/libkvm/kvm.c, Revision 1.87

1.87    ! yamt        1: /*     $NetBSD: kvm.c,v 1.86 2006/03/21 23:47:51 christos Exp $        */
1.42      thorpej     2:
1.1       cgd         3: /*-
1.35      cgd         4:  * Copyright (c) 1989, 1992, 1993
                      5:  *     The Regents of the University of California.  All rights reserved.
                      6:  *
                      7:  * This code is derived from software developed by the Computer Systems
                      8:  * Engineering group at Lawrence Berkeley Laboratory under DARPA contract
                      9:  * BG 91-66 and contributed to Berkeley.
1.1       cgd        10:  *
                     11:  * Redistribution and use in source and binary forms, with or without
                     12:  * modification, are permitted provided that the following conditions
                     13:  * are met:
                     14:  * 1. Redistributions of source code must retain the above copyright
                     15:  *    notice, this list of conditions and the following disclaimer.
                     16:  * 2. Redistributions in binary form must reproduce the above copyright
                     17:  *    notice, this list of conditions and the following disclaimer in the
                     18:  *    documentation and/or other materials provided with the distribution.
1.81      agc        19:  * 3. Neither the name of the University nor the names of its contributors
1.1       cgd        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:
1.53      mikel      36: #include <sys/cdefs.h>
1.1       cgd        37: #if defined(LIBC_SCCS) && !defined(lint)
1.42      thorpej    38: #if 0
1.35      cgd        39: static char sccsid[] = "@(#)kvm.c      8.2 (Berkeley) 2/13/94";
1.42      thorpej    40: #else
1.87    ! yamt       41: __RCSID("$NetBSD: kvm.c,v 1.86 2006/03/21 23:47:51 christos Exp $");
1.42      thorpej    42: #endif
1.1       cgd        43: #endif /* LIBC_SCCS and not lint */
                     44:
                     45: #include <sys/param.h>
                     46: #include <sys/user.h>
1.79      thorpej    47: #include <sys/lwp.h>
1.1       cgd        48: #include <sys/proc.h>
                     49: #include <sys/ioctl.h>
1.35      cgd        50: #include <sys/stat.h>
                     51: #include <sys/sysctl.h>
                     52:
1.40      leo        53: #include <sys/core.h>
                     54: #include <sys/exec_aout.h>
                     55: #include <sys/kcore.h>
1.80      ragge      56: #include <sys/ksyms.h>
1.40      leo        57:
1.67      mrg        58: #include <uvm/uvm_extern.h>
1.35      cgd        59:
1.76      atatat     60: #include <machine/cpu.h>
                     61:
1.35      cgd        62: #include <ctype.h>
1.87    ! yamt       63: #include <errno.h>
1.1       cgd        64: #include <fcntl.h>
                     65: #include <limits.h>
1.35      cgd        66: #include <nlist.h>
1.1       cgd        67: #include <paths.h>
1.71      wiz        68: #include <stdarg.h>
1.1       cgd        69: #include <stdio.h>
1.35      cgd        70: #include <stdlib.h>
1.1       cgd        71: #include <string.h>
1.35      cgd        72: #include <unistd.h>
1.41      leo        73: #include <kvm.h>
1.1       cgd        74:
1.35      cgd        75: #include "kvm_private.h"
1.1       cgd        76:
1.40      leo        77: static int     _kvm_get_header __P((kvm_t *));
1.39      cgd        78: static kvm_t   *_kvm_open __P((kvm_t *, const char *, const char *,
                     79:                    const char *, int, char *));
1.40      leo        80: static int     clear_gap __P((kvm_t *, FILE *, int));
1.73      christos   81: static int     open_cloexec  __P((const char *, int, int));
1.40      leo        82: static off_t   Lseek __P((kvm_t *, int, off_t, int));
1.58      thorpej    83: static ssize_t Pread __P((kvm_t *, int, void *, size_t, off_t));
1.19      mycroft    84:
1.35      cgd        85: char *
                     86: kvm_geterr(kd)
                     87:        kvm_t *kd;
                     88: {
                     89:        return (kd->errbuf);
                     90: }
1.1       cgd        91:
1.35      cgd        92: /*
                     93:  * Report an error using printf style arguments.  "program" is kd->program
                     94:  * on hard errors, and 0 on soft errors, so that under sun error emulation,
                     95:  * only hard errors are printed out (otherwise, programs like gdb will
                     96:  * generate tons of error messages when trying to access bogus pointers).
                     97:  */
                     98: void
                     99: _kvm_err(kvm_t *kd, const char *program, const char *fmt, ...)
                    100: {
                    101:        va_list ap;
1.27      phil      102:
1.35      cgd       103:        va_start(ap, fmt);
                    104:        if (program != NULL) {
                    105:                (void)fprintf(stderr, "%s: ", program);
                    106:                (void)vfprintf(stderr, fmt, ap);
                    107:                (void)fputc('\n', stderr);
                    108:        } else
                    109:                (void)vsnprintf(kd->errbuf,
1.60      thorpej   110:                    sizeof(kd->errbuf), fmt, ap);
1.26      pk        111:
1.35      cgd       112:        va_end(ap);
                    113: }
1.26      pk        114:
1.35      cgd       115: void
                    116: _kvm_syserr(kvm_t *kd, const char *program, const char *fmt, ...)
                    117: {
                    118:        va_list ap;
1.60      thorpej   119:        size_t n;
1.26      pk        120:
1.35      cgd       121:        va_start(ap, fmt);
                    122:        if (program != NULL) {
                    123:                (void)fprintf(stderr, "%s: ", program);
                    124:                (void)vfprintf(stderr, fmt, ap);
                    125:                (void)fprintf(stderr, ": %s\n", strerror(errno));
                    126:        } else {
1.55      perry     127:                char *cp = kd->errbuf;
1.26      pk        128:
1.60      thorpej   129:                (void)vsnprintf(cp, sizeof(kd->errbuf), fmt, ap);
1.35      cgd       130:                n = strlen(cp);
                    131:                (void)snprintf(&cp[n], sizeof(kd->errbuf) - n, ": %s",
                    132:                    strerror(errno));
                    133:        }
                    134:        va_end(ap);
                    135: }
1.1       cgd       136:
1.35      cgd       137: void *
                    138: _kvm_malloc(kd, n)
1.55      perry     139:        kvm_t *kd;
                    140:        size_t n;
1.35      cgd       141: {
                    142:        void *p;
                    143:
                    144:        if ((p = malloc(n)) == NULL)
1.68      sommerfe  145:                _kvm_err(kd, kd->program, "%s", strerror(errno));
1.35      cgd       146:        return (p);
                    147: }
                    148:
1.40      leo       149: /*
1.73      christos  150:  * Open a file setting the close on exec bit.
                    151:  */
                    152: static int
                    153: open_cloexec(fname, flags, mode)
                    154:        const char *fname;
                    155:        int flags, mode;
                    156: {
                    157:        int fd;
                    158:
                    159:        if ((fd = open(fname, flags, mode)) == -1)
                    160:                return fd;
1.77      christos  161:        if (fcntl(fd, F_SETFD, FD_CLOEXEC) == -1)
1.73      christos  162:                goto error;
                    163:
                    164:        return fd;
                    165: error:
                    166:        flags = errno;
                    167:        (void)close(fd);
                    168:        errno = flags;
                    169:        return -1;
                    170: }
                    171:
                    172: /*
1.58      thorpej   173:  * Wrapper around the lseek(2) system call; calls _kvm_syserr() for us
                    174:  * in the event of emergency.
1.40      leo       175:  */
                    176: static off_t
                    177: Lseek(kd, fd, offset, whence)
1.58      thorpej   178:        kvm_t *kd;
                    179:        int fd;
                    180:        off_t offset;
                    181:        int whence;
1.40      leo       182: {
1.58      thorpej   183:        off_t off;
1.40      leo       184:
                    185:        errno = 0;
1.58      thorpej   186:
1.40      leo       187:        if ((off = lseek(fd, offset, whence)) == -1 && errno != 0) {
                    188:                _kvm_syserr(kd, kd->program, "Lseek");
1.58      thorpej   189:                return ((off_t)-1);
1.40      leo       190:        }
                    191:        return (off);
                    192: }
                    193:
1.58      thorpej   194: /*
                    195:  * Wrapper around the pread(2) system call; calls _kvm_syserr() for us
                    196:  * in the event of emergency.
                    197:  */
1.40      leo       198: static ssize_t
1.58      thorpej   199: Pread(kd, fd, buf, nbytes, offset)
                    200:        kvm_t *kd;
                    201:        int fd;
                    202:        void *buf;
                    203:        size_t nbytes;
                    204:        off_t offset;
1.40      leo       205: {
1.58      thorpej   206:        ssize_t rv;
1.40      leo       207:
                    208:        errno = 0;
                    209:
1.58      thorpej   210:        if ((rv = pread(fd, buf, nbytes, offset)) != nbytes &&
                    211:            errno != 0)
                    212:                _kvm_syserr(kd, kd->program, "Pread");
1.40      leo       213:        return (rv);
                    214: }
                    215:
1.35      cgd       216: static kvm_t *
                    217: _kvm_open(kd, uf, mf, sf, flag, errout)
1.55      perry     218:        kvm_t *kd;
1.35      cgd       219:        const char *uf;
                    220:        const char *mf;
                    221:        const char *sf;
                    222:        int flag;
                    223:        char *errout;
                    224: {
                    225:        struct stat st;
1.48      cgd       226:        int ufgiven;
1.35      cgd       227:
1.37      mycroft   228:        kd->pmfd = -1;
1.35      cgd       229:        kd->vmfd = -1;
                    230:        kd->swfd = -1;
                    231:        kd->nlfd = -1;
1.65      simonb    232:        kd->alive = KVM_ALIVE_DEAD;
1.85      christos  233:        kd->procbase = NULL;
                    234:        kd->procbase_len = 0;
                    235:        kd->procbase2 = NULL;
                    236:        kd->procbase2_len = 0;
                    237:        kd->lwpbase = NULL;
                    238:        kd->lwpbase_len = 0;
1.36      mycroft   239:        kd->nbpg = getpagesize();
1.85      christos  240:        kd->swapspc = NULL;
                    241:        kd->argspc = NULL;
                    242:        kd->argspc_len = 0;
                    243:        kd->argbuf = NULL;
                    244:        kd->argv = NULL;
                    245:        kd->vmst = NULL;
                    246:        kd->vm_page_buckets = NULL;
                    247:        kd->kcore_hdr = NULL;
1.43      gwr       248:        kd->cpu_dsize = 0;
1.85      christos  249:        kd->cpu_data = NULL;
1.40      leo       250:        kd->dump_off = 0;
1.52      gwr       251:
1.65      simonb    252:        if (flag & KVM_NO_FILES) {
                    253:                kd->alive = KVM_ALIVE_SYSCTL;
                    254:                return(kd);
                    255:        }
                    256:
1.52      gwr       257:        /*
                    258:         * Call the MD open hook.  This sets:
                    259:         *      usrstack, min_uva, max_uva
                    260:         */
                    261:        if (_kvm_mdopen(kd)) {
                    262:                _kvm_err(kd, kd->program, "md init failed");
                    263:                goto failed;
                    264:        }
1.35      cgd       265:
1.48      cgd       266:        ufgiven = (uf != NULL);
1.76      atatat    267:        if (!ufgiven) {
                    268: #ifdef CPU_BOOTED_KERNEL
                    269:                /* 130 is 128 + '/' + '\0' */
                    270:                static char booted_kernel[130];
                    271:                int mib[2], rc;
                    272:                size_t len;
                    273:
                    274:                mib[0] = CTL_MACHDEP;
                    275:                mib[1] = CPU_BOOTED_KERNEL;
                    276:                booted_kernel[0] = '/';
                    277:                booted_kernel[1] = '\0';
                    278:                len = sizeof(booted_kernel) - 2;
                    279:                rc = sysctl(&mib[0], 2, &booted_kernel[1], &len, NULL, 0);
                    280:                booted_kernel[sizeof(booted_kernel) - 1] = '\0';
                    281:                uf = (booted_kernel[1] == '/') ?
                    282:                    &booted_kernel[1] : &booted_kernel[0];
                    283:                if (rc != -1)
                    284:                        rc = stat(uf, &st);
                    285:                if (rc != -1 && !S_ISREG(st.st_mode))
                    286:                        rc = -1;
                    287:                if (rc == -1)
                    288: #endif /* CPU_BOOTED_KERNEL */
                    289:                        uf = _PATH_UNIX;
                    290:        }
1.35      cgd       291:        else if (strlen(uf) >= MAXPATHLEN) {
                    292:                _kvm_err(kd, kd->program, "exec file name too long");
1.1       cgd       293:                goto failed;
                    294:        }
1.35      cgd       295:        if (flag & ~O_RDWR) {
                    296:                _kvm_err(kd, kd->program, "bad flags arg");
1.1       cgd       297:                goto failed;
                    298:        }
1.35      cgd       299:        if (mf == 0)
                    300:                mf = _PATH_MEM;
                    301:        if (sf == 0)
                    302:                sf = _PATH_DRUM;
                    303:
1.73      christos  304:        if ((kd->pmfd = open_cloexec(mf, flag, 0)) < 0) {
1.35      cgd       305:                _kvm_syserr(kd, kd->program, "%s", mf);
                    306:                goto failed;
1.1       cgd       307:        }
1.35      cgd       308:        if (fstat(kd->pmfd, &st) < 0) {
                    309:                _kvm_syserr(kd, kd->program, "%s", mf);
1.1       cgd       310:                goto failed;
                    311:        }
1.35      cgd       312:        if (S_ISCHR(st.st_mode)) {
1.1       cgd       313:                /*
1.35      cgd       314:                 * If this is a character special device, then check that
                    315:                 * it's /dev/mem.  If so, open kmem too.  (Maybe we should
                    316:                 * make it work for either /dev/mem or /dev/kmem -- in either
                    317:                 * case you're working with a live kernel.)
1.1       cgd       318:                 */
1.35      cgd       319:                if (strcmp(mf, _PATH_MEM) != 0) {       /* XXX */
                    320:                        _kvm_err(kd, kd->program,
                    321:                                 "%s: not physical memory device", mf);
                    322:                        goto failed;
1.1       cgd       323:                }
1.73      christos  324:                if ((kd->vmfd = open_cloexec(_PATH_KMEM, flag, 0)) < 0) {
1.35      cgd       325:                        _kvm_syserr(kd, kd->program, "%s", _PATH_KMEM);
                    326:                        goto failed;
1.1       cgd       327:                }
1.65      simonb    328:                kd->alive = KVM_ALIVE_FILES;
1.73      christos  329:                if ((kd->swfd = open_cloexec(sf, flag, 0)) < 0) {
1.84      yamt      330:                        if (errno != ENXIO) {
                    331:                                _kvm_syserr(kd, kd->program, "%s", sf);
                    332:                                goto failed;
                    333:                        }
                    334:                        /* swap is not configured?  not fatal */
1.1       cgd       335:                }
                    336:                /*
1.80      ragge     337:                 * Open the kernel namelist.  If /dev/ksyms doesn't
                    338:                 * exist, open the current kernel.
1.1       cgd       339:                 */
1.80      ragge     340:                if (ufgiven == 0)
                    341:                        kd->nlfd = open_cloexec(_PATH_KSYMS, O_RDONLY, 0);
                    342:                if (kd->nlfd < 0) {
                    343:                        if ((kd->nlfd = open_cloexec(uf, O_RDONLY, 0)) < 0) {
                    344:                                _kvm_syserr(kd, kd->program, "%s", uf);
                    345:                                goto failed;
                    346:                        }
1.82      cube      347:                } else {
                    348:                        /*
                    349:                         * We're here because /dev/ksyms was opened
                    350:                         * successfully.  However, we don't want to keep it
                    351:                         * open, so we close it now.  Later, we will open
                    352:                         * it again, since it will be the only case where
                    353:                         * kd->nlfd is negative.
                    354:                         */
                    355:                        close(kd->nlfd);
                    356:                        kd->nlfd = -1;
1.3       cgd       357:                }
1.35      cgd       358:        } else {
1.3       cgd       359:                /*
1.35      cgd       360:                 * This is a crash dump.
1.70      wiz       361:                 * Initialize the virtual address translation machinery,
1.35      cgd       362:                 * but first setup the namelist fd.
1.3       cgd       363:                 */
1.73      christos  364:                if ((kd->nlfd = open_cloexec(uf, O_RDONLY, 0)) < 0) {
1.35      cgd       365:                        _kvm_syserr(kd, kd->program, "%s", uf);
                    366:                        goto failed;
1.3       cgd       367:                }
1.40      leo       368:
                    369:                /*
                    370:                 * If there is no valid core header, fail silently here.
1.64      simonb    371:                 * The address translations however will fail without
1.40      leo       372:                 * header. Things can be made to run by calling
                    373:                 * kvm_dump_mkheader() before doing any translation.
                    374:                 */
                    375:                if (_kvm_get_header(kd) == 0) {
                    376:                        if (_kvm_initvtop(kd) < 0)
                    377:                                goto failed;
                    378:                }
1.3       cgd       379:        }
1.35      cgd       380:        return (kd);
                    381: failed:
1.1       cgd       382:        /*
1.35      cgd       383:         * Copy out the error if doing sane error semantics.
1.1       cgd       384:         */
1.35      cgd       385:        if (errout != 0)
1.78      itojun    386:                (void)strlcpy(errout, kd->errbuf, _POSIX2_LINE_MAX);
1.35      cgd       387:        (void)kvm_close(kd);
                    388:        return (0);
1.1       cgd       389: }
                    390:
1.43      gwr       391: /*
                    392:  * The kernel dump file (from savecore) contains:
                    393:  *    kcore_hdr_t kcore_hdr;
                    394:  *    kcore_seg_t cpu_hdr;
                    395:  *    (opaque)    cpu_data; (size is cpu_hdr.c_size)
                    396:  *       kcore_seg_t mem_hdr;
                    397:  *    (memory)    mem_data; (size is mem_hdr.c_size)
1.64      simonb    398:  *
1.43      gwr       399:  * Note: khdr is padded to khdr.c_hdrsize;
                    400:  * cpu_hdr and mem_hdr are padded to khdr.c_seghdrsize
                    401:  */
1.40      leo       402: static int
                    403: _kvm_get_header(kd)
1.43      gwr       404:        kvm_t   *kd;
1.40      leo       405: {
1.43      gwr       406:        kcore_hdr_t     kcore_hdr;
                    407:        kcore_seg_t     cpu_hdr;
                    408:        kcore_seg_t     mem_hdr;
                    409:        size_t          offset;
                    410:        ssize_t         sz;
1.40      leo       411:
1.43      gwr       412:        /*
                    413:         * Read the kcore_hdr_t
                    414:         */
1.58      thorpej   415:        sz = Pread(kd, kd->pmfd, &kcore_hdr, sizeof(kcore_hdr), (off_t)0);
1.43      gwr       416:        if (sz != sizeof(kcore_hdr))
1.40      leo       417:                return (-1);
                    418:
                    419:        /*
                    420:         * Currently, we only support dump-files made by the current
                    421:         * architecture...
                    422:         */
1.43      gwr       423:        if ((CORE_GETMAGIC(kcore_hdr) != KCORE_MAGIC) ||
                    424:            (CORE_GETMID(kcore_hdr) != MID_MACHINE))
                    425:                return (-1);
1.40      leo       426:
                    427:        /*
                    428:         * Currently, we only support exactly 2 segments: cpu-segment
                    429:         * and data-segment in exactly that order.
                    430:         */
1.43      gwr       431:        if (kcore_hdr.c_nseg != 2)
1.40      leo       432:                return (-1);
                    433:
                    434:        /*
1.43      gwr       435:         * Save away the kcore_hdr.  All errors after this
                    436:         * should do a to "goto fail" to deallocate things.
                    437:         */
                    438:        kd->kcore_hdr = _kvm_malloc(kd, sizeof(kcore_hdr));
                    439:        memcpy(kd->kcore_hdr, &kcore_hdr, sizeof(kcore_hdr));
                    440:        offset = kcore_hdr.c_hdrsize;
                    441:
                    442:        /*
                    443:         * Read the CPU segment header
1.40      leo       444:         */
1.58      thorpej   445:        sz = Pread(kd, kd->pmfd, &cpu_hdr, sizeof(cpu_hdr), (off_t)offset);
1.43      gwr       446:        if (sz != sizeof(cpu_hdr))
                    447:                goto fail;
                    448:        if ((CORE_GETMAGIC(cpu_hdr) != KCORESEG_MAGIC) ||
                    449:            (CORE_GETFLAG(cpu_hdr) != CORE_CPU))
                    450:                goto fail;
                    451:        offset += kcore_hdr.c_seghdrsize;
                    452:
                    453:        /*
                    454:         * Read the CPU segment DATA.
                    455:         */
                    456:        kd->cpu_dsize = cpu_hdr.c_size;
                    457:        kd->cpu_data = _kvm_malloc(kd, cpu_hdr.c_size);
                    458:        if (kd->cpu_data == NULL)
                    459:                goto fail;
1.58      thorpej   460:        sz = Pread(kd, kd->pmfd, kd->cpu_data, cpu_hdr.c_size, (off_t)offset);
1.43      gwr       461:        if (sz != cpu_hdr.c_size)
                    462:                goto fail;
                    463:        offset += cpu_hdr.c_size;
1.40      leo       464:
                    465:        /*
                    466:         * Read the next segment header: data segment
                    467:         */
1.58      thorpej   468:        sz = Pread(kd, kd->pmfd, &mem_hdr, sizeof(mem_hdr), (off_t)offset);
1.43      gwr       469:        if (sz != sizeof(mem_hdr))
                    470:                goto fail;
                    471:        offset += kcore_hdr.c_seghdrsize;
                    472:
                    473:        if ((CORE_GETMAGIC(mem_hdr) != KCORESEG_MAGIC) ||
                    474:            (CORE_GETFLAG(mem_hdr) != CORE_DATA))
                    475:                goto fail;
1.40      leo       476:
1.43      gwr       477:        kd->dump_off = offset;
                    478:        return (0);
1.40      leo       479:
1.43      gwr       480: fail:
                    481:        if (kd->kcore_hdr != NULL) {
                    482:                free(kd->kcore_hdr);
1.40      leo       483:                kd->kcore_hdr = NULL;
1.43      gwr       484:        }
                    485:        if (kd->cpu_data != NULL) {
                    486:                free(kd->cpu_data);
                    487:                kd->cpu_data = NULL;
                    488:                kd->cpu_dsize = 0;
1.40      leo       489:        }
1.54      mrg       490:        return (-1);
1.40      leo       491: }
                    492:
                    493: /*
1.43      gwr       494:  * The format while on the dump device is: (new format)
1.47      cgd       495:  *     kcore_seg_t cpu_hdr;
                    496:  *     (opaque)    cpu_data; (size is cpu_hdr.c_size)
                    497:  *     kcore_seg_t mem_hdr;
                    498:  *     (memory)    mem_data; (size is mem_hdr.c_size)
1.40      leo       499:  */
                    500: int
1.41      leo       501: kvm_dump_mkheader(kd, dump_off)
                    502: kvm_t  *kd;
1.40      leo       503: off_t  dump_off;
                    504: {
1.43      gwr       505:        kcore_seg_t     cpu_hdr;
1.60      thorpej   506:        size_t hdr_size;
                    507:        ssize_t sz;
1.40      leo       508:
1.41      leo       509:        if (kd->kcore_hdr != NULL) {
                    510:            _kvm_err(kd, kd->program, "already has a dump header");
1.40      leo       511:            return (-1);
                    512:        }
1.41      leo       513:        if (ISALIVE(kd)) {
                    514:                _kvm_err(kd, kd->program, "don't use on live kernel");
1.40      leo       515:                return (-1);
                    516:        }
                    517:
                    518:        /*
1.43      gwr       519:         * Validate new format crash dump
1.40      leo       520:         */
1.58      thorpej   521:        sz = Pread(kd, kd->pmfd, &cpu_hdr, sizeof(cpu_hdr), dump_off);
1.43      gwr       522:        if (sz != sizeof(cpu_hdr))
                    523:                return (-1);
1.44      leo       524:        if ((CORE_GETMAGIC(cpu_hdr) != KCORE_MAGIC)
                    525:                || (CORE_GETMID(cpu_hdr) != MID_MACHINE)) {
                    526:                _kvm_err(kd, 0, "invalid magic in cpu_hdr");
1.45      leo       527:                return (0);
1.44      leo       528:        }
1.43      gwr       529:        hdr_size = ALIGN(sizeof(cpu_hdr));
                    530:
                    531:        /*
                    532:         * Read the CPU segment.
                    533:         */
                    534:        kd->cpu_dsize = cpu_hdr.c_size;
                    535:        kd->cpu_data = _kvm_malloc(kd, kd->cpu_dsize);
                    536:        if (kd->cpu_data == NULL)
                    537:                goto fail;
1.58      thorpej   538:        sz = Pread(kd, kd->pmfd, kd->cpu_data, cpu_hdr.c_size,
                    539:            dump_off + hdr_size);
1.43      gwr       540:        if (sz != cpu_hdr.c_size)
                    541:                goto fail;
                    542:        hdr_size += kd->cpu_dsize;
                    543:
                    544:        /*
                    545:         * Leave phys mem pointer at beginning of memory data
                    546:         */
                    547:        kd->dump_off = dump_off + hdr_size;
                    548:        if (Lseek(kd, kd->pmfd, kd->dump_off, SEEK_SET) == -1)
                    549:                goto fail;
1.40      leo       550:
                    551:        /*
                    552:         * Create a kcore_hdr.
                    553:         */
1.43      gwr       554:        kd->kcore_hdr = _kvm_malloc(kd, sizeof(kcore_hdr_t));
                    555:        if (kd->kcore_hdr == NULL)
                    556:                goto fail;
1.40      leo       557:
1.41      leo       558:        kd->kcore_hdr->c_hdrsize    = ALIGN(sizeof(kcore_hdr_t));
                    559:        kd->kcore_hdr->c_seghdrsize = ALIGN(sizeof(kcore_seg_t));
                    560:        kd->kcore_hdr->c_nseg       = 2;
                    561:        CORE_SETMAGIC(*(kd->kcore_hdr), KCORE_MAGIC, MID_MACHINE,0);
1.40      leo       562:
                    563:        /*
                    564:         * Now that we have a valid header, enable translations.
                    565:         */
1.49      pk        566:        if (_kvm_initvtop(kd) == 0)
                    567:                /* Success */
                    568:                return (hdr_size);
1.43      gwr       569:
                    570: fail:
                    571:        if (kd->kcore_hdr != NULL) {
                    572:                free(kd->kcore_hdr);
                    573:                kd->kcore_hdr = NULL;
                    574:        }
                    575:        if (kd->cpu_data != NULL) {
                    576:                free(kd->cpu_data);
                    577:                kd->cpu_data = NULL;
                    578:                kd->cpu_dsize = 0;
                    579:        }
                    580:        return (-1);
1.40      leo       581: }
                    582:
                    583: static int
                    584: clear_gap(kd, fp, size)
                    585: kvm_t  *kd;
                    586: FILE   *fp;
                    587: int    size;
                    588: {
                    589:        if (size <= 0) /* XXX - < 0 should never happen */
                    590:                return (0);
                    591:        while (size-- > 0) {
                    592:                if (fputc(0, fp) == EOF) {
                    593:                        _kvm_syserr(kd, kd->program, "clear_gap");
                    594:                        return (-1);
                    595:                }
                    596:        }
                    597:        return (0);
                    598: }
                    599:
                    600: /*
                    601:  * Write the dump header info to 'fp'. Note that we can't use fseek(3) here
                    602:  * because 'fp' might be a file pointer obtained by zopen().
                    603:  */
                    604: int
                    605: kvm_dump_wrtheader(kd, fp, dumpsize)
                    606: kvm_t  *kd;
                    607: FILE   *fp;
                    608: int    dumpsize;
                    609: {
                    610:        kcore_seg_t     seghdr;
                    611:        long            offset;
                    612:        int             gap;
                    613:
1.43      gwr       614:        if (kd->kcore_hdr == NULL || kd->cpu_data == NULL) {
1.40      leo       615:                _kvm_err(kd, kd->program, "no valid dump header(s)");
                    616:                return (-1);
                    617:        }
                    618:
                    619:        /*
                    620:         * Write the generic header
                    621:         */
                    622:        offset = 0;
1.60      thorpej   623:        if (fwrite((void*)kd->kcore_hdr, sizeof(kcore_hdr_t), 1, fp) == 0) {
1.40      leo       624:                _kvm_syserr(kd, kd->program, "kvm_dump_wrtheader");
                    625:                return (-1);
                    626:        }
                    627:        offset += kd->kcore_hdr->c_hdrsize;
                    628:        gap     = kd->kcore_hdr->c_hdrsize - sizeof(kcore_hdr_t);
                    629:        if (clear_gap(kd, fp, gap) == -1)
                    630:                return (-1);
                    631:
                    632:        /*
1.83      wiz       633:         * Write the CPU header
1.40      leo       634:         */
                    635:        CORE_SETMAGIC(seghdr, KCORESEG_MAGIC, 0, CORE_CPU);
1.43      gwr       636:        seghdr.c_size = ALIGN(kd->cpu_dsize);
1.60      thorpej   637:        if (fwrite((void*)&seghdr, sizeof(seghdr), 1, fp) == 0) {
1.40      leo       638:                _kvm_syserr(kd, kd->program, "kvm_dump_wrtheader");
                    639:                return (-1);
                    640:        }
                    641:        offset += kd->kcore_hdr->c_seghdrsize;
                    642:        gap     = kd->kcore_hdr->c_seghdrsize - sizeof(seghdr);
                    643:        if (clear_gap(kd, fp, gap) == -1)
                    644:                return (-1);
                    645:
1.60      thorpej   646:        if (fwrite((void*)kd->cpu_data, kd->cpu_dsize, 1, fp) == 0) {
1.40      leo       647:                _kvm_syserr(kd, kd->program, "kvm_dump_wrtheader");
                    648:                return (-1);
                    649:        }
                    650:        offset += seghdr.c_size;
1.43      gwr       651:        gap     = seghdr.c_size - kd->cpu_dsize;
1.40      leo       652:        if (clear_gap(kd, fp, gap) == -1)
                    653:                return (-1);
                    654:
                    655:        /*
                    656:         * Write the actual dump data segment header
                    657:         */
                    658:        CORE_SETMAGIC(seghdr, KCORESEG_MAGIC, 0, CORE_DATA);
                    659:        seghdr.c_size = dumpsize;
1.60      thorpej   660:        if (fwrite((void*)&seghdr, sizeof(seghdr), 1, fp) == 0) {
1.40      leo       661:                _kvm_syserr(kd, kd->program, "kvm_dump_wrtheader");
                    662:                return (-1);
                    663:        }
                    664:        offset += kd->kcore_hdr->c_seghdrsize;
                    665:        gap     = kd->kcore_hdr->c_seghdrsize - sizeof(seghdr);
                    666:        if (clear_gap(kd, fp, gap) == -1)
                    667:                return (-1);
                    668:
1.62      christos  669:        return (int)offset;
1.40      leo       670: }
                    671:
1.35      cgd       672: kvm_t *
                    673: kvm_openfiles(uf, mf, sf, flag, errout)
                    674:        const char *uf;
                    675:        const char *mf;
                    676:        const char *sf;
                    677:        int flag;
                    678:        char *errout;
                    679: {
1.55      perry     680:        kvm_t *kd;
1.35      cgd       681:
                    682:        if ((kd = malloc(sizeof(*kd))) == NULL) {
1.78      itojun    683:                (void)strlcpy(errout, strerror(errno), _POSIX2_LINE_MAX);
1.35      cgd       684:                return (0);
                    685:        }
                    686:        kd->program = 0;
                    687:        return (_kvm_open(kd, uf, mf, sf, flag, errout));
                    688: }
                    689:
                    690: kvm_t *
                    691: kvm_open(uf, mf, sf, flag, program)
                    692:        const char *uf;
                    693:        const char *mf;
                    694:        const char *sf;
                    695:        int flag;
                    696:        const char *program;
                    697: {
1.55      perry     698:        kvm_t *kd;
1.35      cgd       699:
1.86      christos  700:        if ((kd = malloc(sizeof(*kd))) == NULL) {
                    701:                (void)fprintf(stderr, "%s: %s\n",
                    702:                    program ? program : getprogname(), strerror(errno));
1.35      cgd       703:                return (0);
1.19      mycroft   704:        }
1.35      cgd       705:        kd->program = program;
                    706:        return (_kvm_open(kd, uf, mf, sf, flag, NULL));
1.8       cgd       707: }
                    708:
                    709: int
1.35      cgd       710: kvm_close(kd)
                    711:        kvm_t *kd;
1.1       cgd       712: {
1.55      perry     713:        int error = 0;
1.24      mycroft   714:
1.35      cgd       715:        if (kd->pmfd >= 0)
                    716:                error |= close(kd->pmfd);
                    717:        if (kd->vmfd >= 0)
                    718:                error |= close(kd->vmfd);
                    719:        if (kd->nlfd >= 0)
                    720:                error |= close(kd->nlfd);
                    721:        if (kd->swfd >= 0)
                    722:                error |= close(kd->swfd);
                    723:        if (kd->vmst)
                    724:                _kvm_freevtop(kd);
1.43      gwr       725:        kd->cpu_dsize = 0;
                    726:        if (kd->cpu_data != NULL)
                    727:                free((void *)kd->cpu_data);
1.40      leo       728:        if (kd->kcore_hdr != NULL)
                    729:                free((void *)kd->kcore_hdr);
1.35      cgd       730:        if (kd->procbase != 0)
                    731:                free((void *)kd->procbase);
1.65      simonb    732:        if (kd->procbase2 != 0)
                    733:                free((void *)kd->procbase2);
1.79      thorpej   734:        if (kd->lwpbase != 0)
                    735:                free((void *)kd->lwpbase);
1.36      mycroft   736:        if (kd->swapspc != 0)
                    737:                free((void *)kd->swapspc);
                    738:        if (kd->argspc != 0)
                    739:                free((void *)kd->argspc);
1.38      mycroft   740:        if (kd->argbuf != 0)
                    741:                free((void *)kd->argbuf);
1.35      cgd       742:        if (kd->argv != 0)
                    743:                free((void *)kd->argv);
                    744:        free((void *)kd);
1.19      mycroft   745:
1.1       cgd       746:        return (0);
                    747: }
                    748:
1.18      mycroft   749: int
1.35      cgd       750: kvm_nlist(kd, nl)
                    751:        kvm_t *kd;
                    752:        struct nlist *nl;
1.18      mycroft   753: {
1.82      cube      754:        int rv, nlfd;
                    755:
                    756:        /*
                    757:         * kd->nlfd might be negative when we get here, and in that
                    758:         * case that means that we're using /dev/ksyms.
                    759:         * So open it again, just for the time we retrieve the list.
                    760:         */
                    761:        if (kd->nlfd < 0) {
                    762:                nlfd = open_cloexec(_PATH_KSYMS, O_RDONLY, 0);
                    763:                if (nlfd < 0) {
                    764:                        _kvm_err(kd, 0, "failed to open %s", _PATH_KSYMS);
                    765:                        return (nlfd);
                    766:                }
                    767:        } else
                    768:                nlfd = kd->nlfd;
1.3       cgd       769:
1.35      cgd       770:        /*
1.80      ragge     771:         * Call the nlist(3) routines to retrieve the given namelist.
1.35      cgd       772:         */
1.82      cube      773:        rv = __fdnlist(nlfd, nl);
                    774:
1.80      ragge     775:        if (rv == -1)
                    776:                _kvm_err(kd, 0, "bad namelist");
1.82      cube      777:
                    778:        if (kd->nlfd < 0)
                    779:                close(nlfd);
                    780:
1.80      ragge     781:        return (rv);
1.18      mycroft   782: }
1.3       cgd       783:
1.40      leo       784: int kvm_dump_inval(kd)
                    785: kvm_t  *kd;
                    786: {
1.60      thorpej   787:        struct nlist    nl[2];
1.57      thorpej   788:        u_long          pa, val;
1.40      leo       789:
                    790:        if (ISALIVE(kd)) {
                    791:                _kvm_err(kd, kd->program, "clearing dump on live kernel");
                    792:                return (-1);
                    793:        }
1.60      thorpej   794:        nl[0].n_name = "_dumpmag";
                    795:        nl[1].n_name = NULL;
1.40      leo       796:
1.60      thorpej   797:        if (kvm_nlist(kd, nl) == -1) {
1.40      leo       798:                _kvm_err(kd, 0, "bad namelist");
                    799:                return (-1);
                    800:        }
1.60      thorpej   801:        if (_kvm_kvatop(kd, (u_long)nl[0].n_value, &pa) == 0)
1.40      leo       802:                return (-1);
                    803:
                    804:        errno = 0;
1.57      thorpej   805:        val = 0;
1.77      christos  806:        if (pwrite(kd->pmfd, (void *)&val, sizeof(val),
1.62      christos  807:            _kvm_pa2off(kd, pa)) == -1) {
1.57      thorpej   808:                _kvm_syserr(kd, 0, "cannot invalidate dump - pwrite");
1.40      leo       809:                return (-1);
                    810:        }
                    811:        return (0);
                    812: }
                    813:
1.35      cgd       814: ssize_t
                    815: kvm_read(kd, kva, buf, len)
                    816:        kvm_t *kd;
1.55      perry     817:        u_long kva;
                    818:        void *buf;
                    819:        size_t len;
1.3       cgd       820: {
1.55      perry     821:        int cc;
                    822:        void *cp;
1.3       cgd       823:
1.65      simonb    824:        if (ISKMEM(kd)) {
1.35      cgd       825:                /*
                    826:                 * We're using /dev/kmem.  Just read straight from the
                    827:                 * device and let the active kernel do the address translation.
                    828:                 */
                    829:                errno = 0;
1.57      thorpej   830:                cc = pread(kd->vmfd, buf, len, (off_t)kva);
1.35      cgd       831:                if (cc < 0) {
                    832:                        _kvm_syserr(kd, 0, "kvm_read");
1.56      msaitoh   833:                        return (-1);
1.35      cgd       834:                } else if (cc < len)
                    835:                        _kvm_err(kd, kd->program, "short read");
                    836:                return (cc);
1.65      simonb    837:        } else if (ISSYSCTL(kd)) {
                    838:                _kvm_err(kd, kd->program, "kvm_open called with KVM_NO_FILES, "
                    839:                    "can't use kvm_read");
                    840:                return (-1);
1.35      cgd       841:        } else {
1.43      gwr       842:                if ((kd->kcore_hdr == NULL) || (kd->cpu_data == NULL)) {
1.40      leo       843:                        _kvm_err(kd, kd->program, "no valid dump header");
1.56      msaitoh   844:                        return (-1);
1.40      leo       845:                }
1.35      cgd       846:                cp = buf;
                    847:                while (len > 0) {
1.40      leo       848:                        u_long  pa;
                    849:                        off_t   foff;
1.64      simonb    850:
1.35      cgd       851:                        cc = _kvm_kvatop(kd, kva, &pa);
                    852:                        if (cc == 0)
1.56      msaitoh   853:                                return (-1);
1.35      cgd       854:                        if (cc > len)
                    855:                                cc = len;
1.40      leo       856:                        foff = _kvm_pa2off(kd, pa);
1.35      cgd       857:                        errno = 0;
1.62      christos  858:                        cc = pread(kd->pmfd, cp, (size_t)cc, foff);
1.35      cgd       859:                        if (cc < 0) {
                    860:                                _kvm_syserr(kd, kd->program, "kvm_read");
                    861:                                break;
                    862:                        }
                    863:                        /*
                    864:                         * If kvm_kvatop returns a bogus value or our core
                    865:                         * file is truncated, we might wind up seeking beyond
                    866:                         * the end of the core file in which case the read will
                    867:                         * return 0 (EOF).
                    868:                         */
                    869:                        if (cc == 0)
                    870:                                break;
1.39      cgd       871:                        cp = (char *)cp + cc;
1.35      cgd       872:                        kva += cc;
                    873:                        len -= cc;
1.3       cgd       874:                }
1.35      cgd       875:                return ((char *)cp - (char *)buf);
1.3       cgd       876:        }
1.35      cgd       877:        /* NOTREACHED */
1.3       cgd       878: }
                    879:
1.35      cgd       880: ssize_t
                    881: kvm_write(kd, kva, buf, len)
                    882:        kvm_t *kd;
1.55      perry     883:        u_long kva;
                    884:        const void *buf;
                    885:        size_t len;
1.35      cgd       886: {
1.55      perry     887:        int cc;
1.26      pk        888:
1.65      simonb    889:        if (ISKMEM(kd)) {
1.35      cgd       890:                /*
                    891:                 * Just like kvm_read, only we write.
                    892:                 */
                    893:                errno = 0;
1.57      thorpej   894:                cc = pwrite(kd->vmfd, buf, len, (off_t)kva);
1.35      cgd       895:                if (cc < 0) {
                    896:                        _kvm_syserr(kd, 0, "kvm_write");
1.56      msaitoh   897:                        return (-1);
1.35      cgd       898:                } else if (cc < len)
                    899:                        _kvm_err(kd, kd->program, "short write");
                    900:                return (cc);
1.65      simonb    901:        } else if (ISSYSCTL(kd)) {
                    902:                _kvm_err(kd, kd->program, "kvm_open called with KVM_NO_FILES, "
                    903:                    "can't use kvm_write");
                    904:                return (-1);
1.35      cgd       905:        } else {
                    906:                _kvm_err(kd, kd->program,
                    907:                    "kvm_write not implemented for dead kernels");
1.56      msaitoh   908:                return (-1);
1.26      pk        909:        }
1.35      cgd       910:        /* NOTREACHED */
1.1       cgd       911: }

CVSweb <webmaster@jp.NetBSD.org>