[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.90

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

CVSweb <webmaster@jp.NetBSD.org>