diff options
author | Niklas Hallqvist <niklas@cvs.openbsd.org> | 1996-03-19 23:15:57 +0000 |
---|---|---|
committer | Niklas Hallqvist <niklas@cvs.openbsd.org> | 1996-03-19 23:15:57 +0000 |
commit | e46701f3ba417eb809e480d2383217567bd8a0d3 (patch) | |
tree | 6418b00c595e11941ebeb3d312e0136cfb1621b8 /lib/libkvm | |
parent | 169c29d1b708c51bbae3f546e0adfe0d433b5b7b (diff) |
From NetBSD: merge of 960317
Diffstat (limited to 'lib/libkvm')
-rw-r--r-- | lib/libkvm/kvm.c | 395 | ||||
-rw-r--r-- | lib/libkvm/kvm_i386.c | 46 | ||||
-rw-r--r-- | lib/libkvm/kvm_m68k.c | 76 | ||||
-rw-r--r-- | lib/libkvm/kvm_private.h | 15 |
4 files changed, 455 insertions, 77 deletions
diff --git a/lib/libkvm/kvm.c b/lib/libkvm/kvm.c index db1e91320b2..0126e54a178 100644 --- a/lib/libkvm/kvm.c +++ b/lib/libkvm/kvm.c @@ -1,3 +1,5 @@ +/* $OpenBSD: kvm.c,v 1.2 1996/03/19 23:15:22 niklas Exp $ */ + /*- * Copyright (c) 1989, 1992, 1993 * The Regents of the University of California. All rights reserved. @@ -46,11 +48,16 @@ static char sccsid[] = "@(#)kvm.c 8.2 (Berkeley) 2/13/94"; #include <sys/stat.h> #include <sys/sysctl.h> +#include <sys/core.h> +#include <sys/exec_aout.h> +#include <sys/kcore.h> + #include <vm/vm.h> #include <vm/vm_param.h> #include <vm/swap_pager.h> #include <machine/vmparam.h> +#include <machine/kcore.h> #include <ctype.h> #include <db.h> @@ -67,8 +74,12 @@ static char sccsid[] = "@(#)kvm.c 8.2 (Berkeley) 2/13/94"; #include "kvm_private.h" static int kvm_dbopen __P((kvm_t *, const char *)); +static int _kvm_get_header __P((kvm_t *)); static kvm_t *_kvm_open __P((kvm_t *, const char *, const char *, const char *, int, char *)); +static int clear_gap __P((kvm_t *, FILE *, int)); +static off_t Lseek __P((kvm_t *, int, off_t, int)); +static ssize_t Read __P(( kvm_t *, int, void *, size_t)); char * kvm_geterr(kd) @@ -162,6 +173,42 @@ _kvm_malloc(kd, n) return (p); } +/* + * Wrappers for Lseek/Read system calls. They check for errors and + * call _kvm_syserr() if appropriate. + */ +static off_t +Lseek(kd, fd, offset, whence) + kvm_t *kd; + int fd, whence; + off_t offset; +{ + off_t off; + + errno = 0; + if ((off = lseek(fd, offset, whence)) == -1 && errno != 0) { + _kvm_syserr(kd, kd->program, "Lseek"); + return (-1); + } + return (off); +} + +static ssize_t +Read(kd, fd, buf, nbytes) + kvm_t *kd; + int fd; + void *buf; + size_t nbytes; +{ + ssize_t rv; + + errno = 0; + + if ((rv = read(fd, buf, nbytes)) != nbytes && errno != 0) + _kvm_syserr(kd, kd->program, "Read"); + return (rv); +} + static kvm_t * _kvm_open(kd, uf, mf, sf, flag, errout) register kvm_t *kd; @@ -186,6 +233,9 @@ _kvm_open(kd, uf, mf, sf, flag, errout) kd->argv = 0; kd->vmst = 0; kd->vm_page_buckets = 0; + kd->kcore_hdr = 0; + kd->cpu_hdr = 0; + kd->dump_off = 0; if (uf == 0) uf = _PATH_UNIX; @@ -253,8 +303,17 @@ _kvm_open(kd, uf, mf, sf, flag, errout) _kvm_syserr(kd, kd->program, "%s", uf); goto failed; } - if (_kvm_initvtop(kd) < 0) - goto failed; + + /* + * If there is no valid core header, fail silently here. + * The address translations however will fail without + * header. Things can be made to run by calling + * kvm_dump_mkheader() before doing any translation. + */ + if (_kvm_get_header(kd) == 0) { + if (_kvm_initvtop(kd) < 0) + goto failed; + } } return (kd); failed: @@ -267,6 +326,277 @@ failed: return (0); } +static int +_kvm_get_header(kd) +kvm_t *kd; +{ + cpu_kcore_hdr_t ckhdr; + kcore_hdr_t khdr; + kcore_seg_t seghdr; + off_t offset; + + if (Lseek(kd, kd->pmfd, (off_t)0, SEEK_SET) == -1) + return (-1); + + if (Read(kd, kd->pmfd, &khdr, sizeof(khdr)) != sizeof(khdr)) + return (-1); + offset = khdr.c_hdrsize; + + /* + * Currently, we only support dump-files made by the current + * architecture... + */ + if ((CORE_GETMAGIC(khdr) != KCORE_MAGIC) + || ((CORE_GETMID(khdr) != MID_MACHINE))) + return (-1); + + /* + * Currently, we only support exactly 2 segments: cpu-segment + * and data-segment in exactly that order. + */ + if (khdr.c_nseg != 2) + return (-1); + + /* + * Read the next segment header: cpu segment + */ + if (Lseek(kd, kd->pmfd, (off_t)offset, SEEK_SET) == -1) + return (-1); + if (Read(kd, kd->pmfd, &seghdr, sizeof(seghdr)) != sizeof(seghdr)) + return (-1); + if (CORE_GETMAGIC(seghdr) != KCORESEG_MAGIC + || CORE_GETFLAG(seghdr) != CORE_CPU) + return (-1); + offset += khdr.c_seghdrsize; + if (Lseek(kd, kd->pmfd, (off_t)offset, SEEK_SET) == -1) + return (-1); + if (Read(kd, kd->pmfd, &ckhdr, sizeof(ckhdr)) != sizeof(ckhdr)) + return (-1); + offset += seghdr.c_size; + + /* + * Read the next segment header: data segment + */ + if (Lseek(kd, kd->pmfd, (off_t)offset, SEEK_SET) == -1) + return (-1); + if (Read(kd, kd->pmfd, &seghdr, sizeof(seghdr)) != sizeof(seghdr)) + return (-1); + offset += khdr.c_seghdrsize; + + if (CORE_GETMAGIC(seghdr) != KCORESEG_MAGIC + || CORE_GETFLAG(seghdr) != CORE_DATA) + return (-1); + + kd->kcore_hdr = (kcore_hdr_t *)_kvm_malloc(kd, sizeof(*kd->kcore_hdr)); + if (kd->kcore_hdr == NULL) + return (-1); + kd->cpu_hdr = (cpu_kcore_hdr_t *)_kvm_malloc(kd, sizeof(*kd->cpu_hdr)); + if (kd->cpu_hdr == NULL) { + free((void *)kd->kcore_hdr); + kd->kcore_hdr = NULL; + return (-1); + } + + *kd->kcore_hdr = khdr; + *kd->cpu_hdr = ckhdr; + kd->dump_off = offset; + return (0); +} + +/* + * Translate a physical address to a file-offset in the crash-dump. + */ +off_t +_kvm_pa2off(kd, pa) + kvm_t *kd; + u_long pa; +{ + off_t off; + phys_ram_seg_t *rsp; + + off = 0; + for (rsp = kd->cpu_hdr->ram_segs; rsp->size; rsp++) { + if (pa >= rsp->start && pa < rsp->start + rsp->size) { + pa -= rsp->start; + break; + } + off += rsp->size; + } + return(pa + off + kd->dump_off); +} + +int +kvm_dump_mkheader(kd_live, kd_dump, dump_off) +kvm_t *kd_live, *kd_dump; +off_t dump_off; +{ + kcore_hdr_t kch; + kcore_seg_t kseg; + cpu_kcore_hdr_t ckhdr; + int hdr_size; + + hdr_size = 0; + if (kd_dump->kcore_hdr != NULL) { + _kvm_err(kd_dump, kd_dump->program, "already has a dump header"); + return (-1); + } + if (!ISALIVE(kd_live) || ISALIVE(kd_dump)) { + _kvm_err(kd_live, kd_live->program, "wrong arguments"); + return (-1); + } + + /* + * Check for new format crash dump + */ + if (Lseek(kd_dump, kd_dump->pmfd, dump_off, SEEK_SET) == -1) + return (-1); + if (Read(kd_dump, kd_dump->pmfd, &kseg, sizeof(kseg)) != sizeof(kseg)) + return (-1); + if ((CORE_GETMAGIC(kseg) == KCORE_MAGIC) + && ((CORE_GETMID(kseg) == MID_MACHINE))) { + hdr_size += ALIGN(sizeof(kcore_seg_t)); + if (Lseek(kd_dump, kd_dump->pmfd, dump_off+hdr_size, SEEK_SET) + == -1) + return (-1); + if (Read(kd_dump, kd_dump->pmfd, &ckhdr, sizeof(ckhdr)) + != sizeof(ckhdr)) + return (-1); + hdr_size += kseg.c_size; + if (Lseek(kd_dump, kd_dump->pmfd, dump_off+hdr_size, SEEK_SET) + == -1) + return (-1); + kd_dump->cpu_hdr = (cpu_kcore_hdr_t *) + _kvm_malloc(kd_dump, sizeof(cpu_kcore_hdr_t)); + *kd_dump->cpu_hdr = ckhdr; + } + + /* + * Create a kcore_hdr. + */ + kd_dump->kcore_hdr = (kcore_hdr_t *) + _kvm_malloc(kd_dump, sizeof(kcore_hdr_t)); + if (kd_dump->kcore_hdr == NULL) { + if (kd_dump->cpu_hdr != NULL) { + free((void *)kd_dump->cpu_hdr); + kd_dump->cpu_hdr = NULL; + } + return (-1); + } + + kd_dump->kcore_hdr->c_hdrsize = ALIGN(sizeof(kcore_hdr_t)); + kd_dump->kcore_hdr->c_seghdrsize = ALIGN(sizeof(kcore_seg_t)); + kd_dump->kcore_hdr->c_nseg = 2; + CORE_SETMAGIC(*(kd_dump->kcore_hdr), KCORE_MAGIC, MID_MACHINE,0); + + /* + * If there is no cpu_hdr at this point, we probably have an + * old format crash dump.....bail out + */ + if (kd_dump->cpu_hdr == NULL) { + free((void *)kd_dump->kcore_hdr); + kd_dump->kcore_hdr = NULL; + _kvm_err(kd_dump, kd_dump->program, "invalid dump"); + } + + kd_dump->dump_off = dump_off + hdr_size; + + /* + * Now that we have a valid header, enable translations. + */ + _kvm_initvtop(kd_dump); + + return(hdr_size); +} + +static int +clear_gap(kd, fp, size) +kvm_t *kd; +FILE *fp; +int size; +{ + if (size <= 0) /* XXX - < 0 should never happen */ + return (0); + while (size-- > 0) { + if (fputc(0, fp) == EOF) { + _kvm_syserr(kd, kd->program, "clear_gap"); + return (-1); + } + } + return (0); +} + +/* + * Write the dump header info to 'fp'. Note that we can't use fseek(3) here + * because 'fp' might be a file pointer obtained by zopen(). + */ +int +kvm_dump_wrtheader(kd, fp, dumpsize) +kvm_t *kd; +FILE *fp; +int dumpsize; +{ + kcore_seg_t seghdr; + long offset; + int gap; + + if (kd->kcore_hdr == NULL || kd->cpu_hdr == NULL) { + _kvm_err(kd, kd->program, "no valid dump header(s)"); + return (-1); + } + + /* + * Write the generic header + */ + offset = 0; + if (fwrite((void*)kd->kcore_hdr, sizeof(kcore_hdr_t), 1, fp) <= 0) { + _kvm_syserr(kd, kd->program, "kvm_dump_wrtheader"); + return (-1); + } + offset += kd->kcore_hdr->c_hdrsize; + gap = kd->kcore_hdr->c_hdrsize - sizeof(kcore_hdr_t); + if (clear_gap(kd, fp, gap) == -1) + return (-1); + + /* + * Write the cpu header + */ + CORE_SETMAGIC(seghdr, KCORESEG_MAGIC, 0, CORE_CPU); + seghdr.c_size = ALIGN(sizeof(cpu_kcore_hdr_t)); + if (fwrite((void*)&seghdr, sizeof(seghdr), 1, fp) <= 0) { + _kvm_syserr(kd, kd->program, "kvm_dump_wrtheader"); + return (-1); + } + offset += kd->kcore_hdr->c_seghdrsize; + gap = kd->kcore_hdr->c_seghdrsize - sizeof(seghdr); + if (clear_gap(kd, fp, gap) == -1) + return (-1); + + if (fwrite((void*)kd->cpu_hdr, sizeof(cpu_kcore_hdr_t), 1, fp) <= 0) { + _kvm_syserr(kd, kd->program, "kvm_dump_wrtheader"); + return (-1); + } + offset += seghdr.c_size; + gap = seghdr.c_size - sizeof(cpu_kcore_hdr_t); + if (clear_gap(kd, fp, gap) == -1) + return (-1); + + /* + * Write the actual dump data segment header + */ + CORE_SETMAGIC(seghdr, KCORESEG_MAGIC, 0, CORE_DATA); + seghdr.c_size = dumpsize; + if (fwrite((void*)&seghdr, sizeof(seghdr), 1, fp) <= 0) { + _kvm_syserr(kd, kd->program, "kvm_dump_wrtheader"); + return (-1); + } + offset += kd->kcore_hdr->c_seghdrsize; + gap = kd->kcore_hdr->c_seghdrsize - sizeof(seghdr); + if (clear_gap(kd, fp, gap) == -1) + return (-1); + + return (offset); +} + kvm_t * kvm_openfiles(uf, mf, sf, flag, errout) const char *uf; @@ -321,6 +651,10 @@ kvm_close(kd) error |= (kd->db->close)(kd->db); if (kd->vmst) _kvm_freevtop(kd); + if (kd->cpu_hdr != NULL) + free((void *)kd->cpu_hdr); + if (kd->kcore_hdr != NULL) + free((void *)kd->kcore_hdr); if (kd->procbase != 0) free((void *)kd->procbase); if (kd->swapspc != 0) @@ -433,6 +767,12 @@ kvm_nlist(kd, nl) } rec.data = p->n_name; rec.size = len; + + /* + * Make sure that n_value = 0 when the symbol isn't found + */ + p->n_value = 0; + if ((kd->db->get)(kd->db, (DBT *)&rec, (DBT *)&rec, 0)) continue; if (rec.data == 0 || rec.size != sizeof(struct nlist)) @@ -454,6 +794,40 @@ kvm_nlist(kd, nl) return ((p - nl) - nvalid); } +int kvm_dump_inval(kd) +kvm_t *kd; +{ + struct nlist nlist[2]; + u_long pa; + + if (ISALIVE(kd)) { + _kvm_err(kd, kd->program, "clearing dump on live kernel"); + return (-1); + } + nlist[0].n_name = "_dumpmag"; + nlist[1].n_name = NULL; + + if (kvm_nlist(kd, nlist) == -1) { + _kvm_err(kd, 0, "bad namelist"); + return (-1); + } + if (_kvm_kvatop(kd, (u_long)nlist[0].n_value, &pa) == 0) + return (-1); + + errno = 0; + if (lseek(kd->pmfd, _kvm_pa2off(kd, pa), SEEK_SET) == -1 + && errno != 0) { + _kvm_err(kd, 0, "cannot invalidate dump - lseek"); + return (-1); + } + pa = 0; + if (write(kd->pmfd, &pa, sizeof(pa)) != sizeof(pa)) { + _kvm_err(kd, 0, "cannot invalidate dump - write"); + return (-1); + } + return (0); +} + ssize_t kvm_read(kd, kva, buf, len) kvm_t *kd; @@ -470,7 +844,8 @@ kvm_read(kd, kva, buf, len) * device and let the active kernel do the address translation. */ errno = 0; - if (lseek(kd->vmfd, (off_t)kva, 0) == -1 && errno != 0) { + if (lseek(kd->vmfd, (off_t)kva, SEEK_SET) == -1 + && errno != 0) { _kvm_err(kd, 0, "invalid address (%x)", kva); return (0); } @@ -482,17 +857,24 @@ kvm_read(kd, kva, buf, len) _kvm_err(kd, kd->program, "short read"); return (cc); } else { + if ((kd->kcore_hdr == NULL) || (kd->cpu_hdr == NULL)) { + _kvm_err(kd, kd->program, "no valid dump header"); + return (0); + } cp = buf; while (len > 0) { - u_long pa; + u_long pa; + off_t foff; cc = _kvm_kvatop(kd, kva, &pa); if (cc == 0) return (0); if (cc > len) cc = len; + foff = _kvm_pa2off(kd, pa); errno = 0; - if (lseek(kd->pmfd, (off_t)pa, 0) == -1 && errno != 0) { + if (lseek(kd->pmfd, foff, SEEK_SET) == -1 + && errno != 0) { _kvm_syserr(kd, 0, _PATH_MEM); break; } @@ -532,7 +914,8 @@ kvm_write(kd, kva, buf, len) * Just like kvm_read, only we write. */ errno = 0; - if (lseek(kd->vmfd, (off_t)kva, 0) == -1 && errno != 0) { + if (lseek(kd->vmfd, (off_t)kva, SEEK_SET) == -1 + && errno != 0) { _kvm_err(kd, 0, "invalid address (%x)", kva); return (0); } diff --git a/lib/libkvm/kvm_i386.c b/lib/libkvm/kvm_i386.c index 3ded232157f..b79a6804bac 100644 --- a/lib/libkvm/kvm_i386.c +++ b/lib/libkvm/kvm_i386.c @@ -1,3 +1,5 @@ +/* $OpenBSD: kvm_i386.c,v 1.2 1996/03/19 23:15:23 niklas Exp $ */ + /*- * Copyright (c) 1989, 1992, 1993 * The Regents of the University of California. All rights reserved. @@ -37,7 +39,7 @@ #if defined(LIBC_SCCS) && !defined(lint) /* from: static char sccsid[] = "@(#)kvm_hp300.c 8.1 (Berkeley) 6/4/93"; */ -static char *rcsid = "$Id: kvm_i386.c,v 1.1 1995/10/18 08:42:44 deraadt Exp $"; +static char *rcsid = "$OpenBSD: kvm_i386.c,v 1.2 1996/03/19 23:15:23 niklas Exp $"; #endif /* LIBC_SCCS and not lint */ /* @@ -70,13 +72,9 @@ static char *rcsid = "$Id: kvm_i386.c,v 1.1 1995/10/18 08:42:44 deraadt Exp $"; #endif struct vmstate { - pd_entry_t **PTDpaddr; pd_entry_t *PTD; }; -#define KREAD(kd, addr, p)\ - (kvm_read(kd, addr, (char *)(p), sizeof(*(p))) != sizeof(*(p))) - void _kvm_freevtop(kd) kvm_t *kd; @@ -95,7 +93,7 @@ _kvm_initvtop(kd) { struct vmstate *vm; struct nlist nlist[2]; - pt_entry_t *tmpPTD; + u_long pa; vm = (struct vmstate *)_kvm_malloc(kd, sizeof(*vm)); if (vm == 0) @@ -110,21 +108,35 @@ _kvm_initvtop(kd) return (-1); } - vm->PTDpaddr = 0; vm->PTD = 0; - if (KREAD(kd, (u_long)nlist[0].n_value - KERNBASE, &vm->PTDpaddr)) { - _kvm_err(kd, kd->program, "cannot read PTDpaddr"); - return (-1); + + if (lseek(kd->pmfd, (off_t)(nlist[0].n_value - KERNBASE), 0) == -1 && + errno != 0) { + _kvm_syserr(kd, kd->program, "kvm_lseek"); + goto invalid; + } + if (read(kd->pmfd, &pa, sizeof pa) != sizeof pa) { + _kvm_syserr(kd, kd->program, "kvm_read"); + goto invalid; } - tmpPTD = (pd_entry_t *)_kvm_malloc(kd, NBPG); - if ((kvm_read(kd, (u_long)vm->PTDpaddr, tmpPTD, NBPG)) != NBPG) { - free(tmpPTD); - _kvm_err(kd, kd->program, "cannot read PTD"); - return (-1); + vm->PTD = (pd_entry_t *)_kvm_malloc(kd, NBPG); + + if (lseek(kd->pmfd, (off_t)pa, 0) == -1 && errno != 0) { + _kvm_syserr(kd, kd->program, "kvm_lseek"); + goto invalid; + } + if (read(kd->pmfd, vm->PTD, NBPG) != NBPG) { + _kvm_syserr(kd, kd->program, "kvm_read"); + goto invalid; } - vm->PTD = tmpPTD; + return (0); + +invalid: + if (vm->PTD != 0) + free(vm->PTD); + return (-1); } /* @@ -165,7 +177,7 @@ _kvm_kvatop(kd, va, pa) /* XXX READ PHYSICAL XXX */ { if (lseek(kd->pmfd, (off_t)pte_pa, 0) == -1 && errno != 0) { - _kvm_syserr(kd, 0, "kvm_lseek"); + _kvm_syserr(kd, kd->program, "kvm_lseek"); goto invalid; } if (read(kd->pmfd, &pte, sizeof pte) != sizeof pte) { diff --git a/lib/libkvm/kvm_m68k.c b/lib/libkvm/kvm_m68k.c index 58d964809c9..dbea9864055 100644 --- a/lib/libkvm/kvm_m68k.c +++ b/lib/libkvm/kvm_m68k.c @@ -1,3 +1,5 @@ +/* $OpenBSD: kvm_m68k.c,v 1.2 1996/03/19 23:15:24 niklas Exp $ */ + /*- * Copyright (c) 1989, 1992, 1993 * The Regents of the University of California. All rights reserved. @@ -37,7 +39,7 @@ #if defined(LIBC_SCCS) && !defined(lint) /* from: static char sccsid[] = "@(#)kvm_hp300.c 8.1 (Berkeley) 6/4/93"; */ -static char *rcsid = "$Id: kvm_m68k.c,v 1.1 1995/10/18 08:42:44 deraadt Exp $"; +static char *rcsid = "$OpenBSD: kvm_m68k.c,v 1.2 1996/03/19 23:15:24 niklas Exp $"; #endif /* LIBC_SCCS and not lint */ /* @@ -49,31 +51,31 @@ static char *rcsid = "$Id: kvm_m68k.c,v 1.1 1995/10/18 08:42:44 deraadt Exp $"; #include <sys/user.h> #include <sys/proc.h> #include <sys/stat.h> + +#include <sys/core.h> +#include <sys/exec_aout.h> +#include <sys/kcore.h> + #include <unistd.h> +#include <limits.h> #include <nlist.h> #include <kvm.h> #include <vm/vm.h> #include <vm/vm_param.h> -#include <limits.h> #include <db.h> #include "kvm_private.h" #include <machine/pte.h> +#include <machine/kcore.h> #ifndef btop #define btop(x) (((unsigned)(x)) >> PGSHIFT) /* XXX */ #define ptob(x) ((caddr_t)((x) << PGSHIFT)) /* XXX */ #endif -struct vmstate { - u_long lowram; - int mmutype; - st_entry_t *Sysseg; -}; - #define KREAD(kd, addr, p)\ (kvm_read(kd, addr, (char *)(p), sizeof(*(p))) != sizeof(*(p))) @@ -89,36 +91,6 @@ int _kvm_initvtop(kd) kvm_t *kd; { - struct vmstate *vm; - struct nlist nlist[4]; - - vm = (struct vmstate *)_kvm_malloc(kd, sizeof(*vm)); - if (vm == 0) - return (-1); - kd->vmst = vm; - - nlist[0].n_name = "_lowram"; - nlist[1].n_name = "_mmutype"; - nlist[2].n_name = "_Sysseg"; - nlist[3].n_name = 0; - - if (kvm_nlist(kd, nlist) != 0) { - _kvm_err(kd, kd->program, "bad namelist"); - return (-1); - } - vm->Sysseg = 0; - if (KREAD(kd, (u_long)nlist[0].n_value, &vm->lowram)) { - _kvm_err(kd, kd->program, "cannot read lowram"); - return (-1); - } - if (KREAD(kd, (u_long)nlist[1].n_value, &vm->mmutype)) { - _kvm_err(kd, kd->program, "cannot read mmutype"); - return (-1); - } - if (KREAD(kd, (u_long)nlist[2].n_value, &vm->Sysseg)) { - _kvm_err(kd, kd->program, "cannot read segment table"); - return (-1); - } return (0); } @@ -129,8 +101,7 @@ _kvm_vatop(kd, sta, va, pa) u_long va; u_long *pa; { - register struct vmstate *vm; - register u_long lowram; + register cpu_kcore_hdr_t *cpu_kh; register u_long addr; int p, ste, pte; int offset; @@ -139,18 +110,17 @@ _kvm_vatop(kd, sta, va, pa) _kvm_err(kd, 0, "vatop called in live kernel!"); return((off_t)0); } - vm = kd->vmst; offset = va & PGOFSET; + cpu_kh = kd->cpu_hdr; /* * If we are initializing (kernel segment table pointer not yet set) * then return pa == va to avoid infinite recursion. */ - if (vm->Sysseg == 0) { - *pa = va; + if (cpu_kh->sysseg_pa == 0) { + *pa = va + cpu_kh->kernel_pa; return (NBPG - offset); } - lowram = vm->lowram; - if (vm->mmutype == -2) { + if (cpu_kh->mmutype == -2) { st_entry_t *sta2; addr = (u_long)&sta[va >> SG4_SHIFT1]; @@ -158,8 +128,8 @@ _kvm_vatop(kd, sta, va, pa) * Can't use KREAD to read kernel segment table entries. * Fortunately it is 1-to-1 mapped so we don't have to. */ - if (sta == vm->Sysseg) { - if (lseek(kd->pmfd, (off_t)addr, 0) == -1 || + if (sta == cpu_kh->sysseg_pa) { + if (lseek(kd->pmfd, _kvm_pa2off(kd, addr), 0) == -1 || read(kd->pmfd, (char *)&ste, sizeof(ste)) < 0) goto invalid; } else if (KREAD(kd, addr, &ste)) @@ -175,7 +145,7 @@ _kvm_vatop(kd, sta, va, pa) * Address from level 1 STE is a physical address, * so don't use kvm_read. */ - if (lseek(kd->pmfd, (off_t)(addr - lowram), 0) == -1 || + if (lseek(kd->pmfd, _kvm_pa2off(kd, addr), 0) == -1 || read(kd->pmfd, (char *)&ste, sizeof(ste)) < 0) goto invalid; if ((ste & SG_V) == 0) { @@ -191,8 +161,8 @@ _kvm_vatop(kd, sta, va, pa) * Can't use KREAD to read kernel segment table entries. * Fortunately it is 1-to-1 mapped so we don't have to. */ - if (sta == vm->Sysseg) { - if (lseek(kd->pmfd, (off_t)addr, 0) == -1 || + if (sta == cpu_kh->sysseg_pa) { + if (lseek(kd->pmfd, _kvm_pa2off(kd, addr), 0) == -1 || read(kd->pmfd, (char *)&ste, sizeof(ste)) < 0) goto invalid; } else if (KREAD(kd, addr, &ste)) @@ -207,7 +177,7 @@ _kvm_vatop(kd, sta, va, pa) /* * Address from STE is a physical address so don't use kvm_read. */ - if (lseek(kd->pmfd, (off_t)(addr - lowram), 0) == -1 || + if (lseek(kd->pmfd, _kvm_pa2off(kd, addr), 0) == -1 || read(kd->pmfd, (char *)&pte, sizeof(pte)) < 0) goto invalid; addr = pte & PG_FRAME; @@ -215,7 +185,7 @@ _kvm_vatop(kd, sta, va, pa) _kvm_err(kd, 0, "page not valid"); return (0); } - *pa = addr - lowram + offset; + *pa = addr + offset; return (NBPG - offset); invalid: @@ -229,5 +199,5 @@ _kvm_kvatop(kd, va, pa) u_long va; u_long *pa; { - return (_kvm_vatop(kd, (u_long)kd->vmst->Sysseg, va, pa)); + return (_kvm_vatop(kd, (u_long)kd->cpu_hdr->sysseg_pa, va, pa)); } diff --git a/lib/libkvm/kvm_private.h b/lib/libkvm/kvm_private.h index a6eb9b7bf0c..d1b2583f559 100644 --- a/lib/libkvm/kvm_private.h +++ b/lib/libkvm/kvm_private.h @@ -1,3 +1,5 @@ +/* $OpenBSD: kvm_private.h,v 1.2 1996/03/19 23:15:25 niklas Exp $ */ + /*- * Copyright (c) 1992, 1993 * The Regents of the University of California. All rights reserved. @@ -59,13 +61,22 @@ struct __kvm { int arglen; /* length of the above */ char **argv; /* (dynamic) storage for argv pointers */ int argc; /* length of above (not actual # present) */ + + /* + * Header structures for kernel dumps. Only gets filled in for + * dead kernels. + */ + struct kcore_hdr *kcore_hdr; + struct cpu_kcore_hdr *cpu_hdr; + off_t dump_off; /* Where the actual dump starts */ + /* * Kernel virtual address translation state. This only gets filled * in for dead kernels; otherwise, the running kernel (i.e. kmem) * will do the translations for us. It could be big, so we * only allocate it if necessary. */ - struct vmstate *vmst; + struct vmstate *vmst; /* XXX: should become obsoleted */ /* * These kernel variables are used for looking up user addresses, * and are cached for efficiency. @@ -78,11 +89,13 @@ struct __kvm { * Functions used internally by kvm, but across kvm modules. */ void _kvm_err __P((kvm_t *kd, const char *program, const char *fmt, ...)); +int _kvm_dump_mkheader __P((kvm_t *kd_live, kvm_t *kd_dump)); void _kvm_freeprocs __P((kvm_t *kd)); void _kvm_freevtop __P((kvm_t *)); int _kvm_initvtop __P((kvm_t *)); int _kvm_kvatop __P((kvm_t *, u_long, u_long *)); void *_kvm_malloc __P((kvm_t *kd, size_t)); +off_t _kvm_pa2off __P((kvm_t *, u_long)); void *_kvm_realloc __P((kvm_t *kd, void *, size_t)); void _kvm_syserr __P((kvm_t *kd, const char *program, const char *fmt, ...)); |