summaryrefslogtreecommitdiff
path: root/lib/libkvm
diff options
context:
space:
mode:
authorNiklas Hallqvist <niklas@cvs.openbsd.org>1996-03-19 23:15:57 +0000
committerNiklas Hallqvist <niklas@cvs.openbsd.org>1996-03-19 23:15:57 +0000
commite46701f3ba417eb809e480d2383217567bd8a0d3 (patch)
tree6418b00c595e11941ebeb3d312e0136cfb1621b8 /lib/libkvm
parent169c29d1b708c51bbae3f546e0adfe0d433b5b7b (diff)
From NetBSD: merge of 960317
Diffstat (limited to 'lib/libkvm')
-rw-r--r--lib/libkvm/kvm.c395
-rw-r--r--lib/libkvm/kvm_i386.c46
-rw-r--r--lib/libkvm/kvm_m68k.c76
-rw-r--r--lib/libkvm/kvm_private.h15
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, ...));