-/* $OpenBSD: kvm.c,v 1.3 1996/05/05 14:56:42 deraadt Exp $ */
-/* $NetBSD: kvm.c,v 1.42 1996/03/18 22:33:13 thorpej Exp $ */
+/* $OpenBSD: kvm.c,v 1.4 1996/05/10 12:58:30 deraadt Exp $ */
+/* $NetBSD: kvm.c,v 1.43 1996/05/05 04:31:59 gwr Exp $ */
/*-
* Copyright (c) 1989, 1992, 1993
#if 0
static char sccsid[] = "@(#)kvm.c 8.2 (Berkeley) 2/13/94";
#else
-static char *rcsid = "$OpenBSD: kvm.c,v 1.3 1996/05/05 14:56:42 deraadt Exp $";
+static char *rcsid = "$OpenBSD: kvm.c,v 1.4 1996/05/10 12:58:30 deraadt Exp $";
#endif
#endif /* LIBC_SCCS and not lint */
#include <vm/vm_param.h>
#include <vm/swap_pager.h>
-#include <machine/vmparam.h>
-#include <machine/kcore.h>
-
#include <ctype.h>
#include <db.h>
#include <fcntl.h>
kd->vmst = 0;
kd->vm_page_buckets = 0;
kd->kcore_hdr = 0;
- kd->cpu_hdr = 0;
+ kd->cpu_dsize = 0;
+ kd->cpu_data = 0;
kd->dump_off = 0;
if (uf == 0)
return (0);
}
+/*
+ * The kernel dump file (from savecore) contains:
+ * kcore_hdr_t kcore_hdr;
+ * kcore_seg_t cpu_hdr;
+ * (opaque) cpu_data; (size is cpu_hdr.c_size)
+ * kcore_seg_t mem_hdr;
+ * (memory) mem_data; (size is mem_hdr.c_size)
+ *
+ * Note: khdr is padded to khdr.c_hdrsize;
+ * cpu_hdr and mem_hdr are padded to khdr.c_seghdrsize
+ */
static int
_kvm_get_header(kd)
-kvm_t *kd;
+ kvm_t *kd;
{
- cpu_kcore_hdr_t ckhdr;
- kcore_hdr_t khdr;
- kcore_seg_t seghdr;
- off_t offset;
+ kcore_hdr_t kcore_hdr;
+ kcore_seg_t cpu_hdr;
+ kcore_seg_t mem_hdr;
+ size_t offset;
+ ssize_t sz;
+ /*
+ * Read the kcore_hdr_t
+ */
if (Lseek(kd, kd->pmfd, (off_t)0, SEEK_SET) == -1)
return (-1);
-
- if (Read(kd, kd->pmfd, &khdr, sizeof(khdr)) != sizeof(khdr))
+ sz = Read(kd, kd->pmfd, &kcore_hdr, sizeof(kcore_hdr));
+ if (sz != sizeof(kcore_hdr))
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);
+ if ((CORE_GETMAGIC(kcore_hdr) != KCORE_MAGIC) ||
+ (CORE_GETMID(kcore_hdr) != 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)
+ if (kcore_hdr.c_nseg != 2)
return (-1);
/*
- * Read the next segment header: cpu segment
+ * Save away the kcore_hdr. All errors after this
+ * should do a to "goto fail" to deallocate things.
+ */
+ kd->kcore_hdr = _kvm_malloc(kd, sizeof(kcore_hdr));
+ memcpy(kd->kcore_hdr, &kcore_hdr, sizeof(kcore_hdr));
+ offset = kcore_hdr.c_hdrsize;
+
+ /*
+ * Read the CPU segment header
*/
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;
+ goto fail;
+ sz = Read(kd, kd->pmfd, &cpu_hdr, sizeof(cpu_hdr));
+ if (sz != sizeof(cpu_hdr))
+ goto fail;
+ if ((CORE_GETMAGIC(cpu_hdr) != KCORESEG_MAGIC) ||
+ (CORE_GETFLAG(cpu_hdr) != CORE_CPU))
+ goto fail;
+ offset += kcore_hdr.c_seghdrsize;
+
+ /*
+ * Read the CPU segment DATA.
+ */
+ kd->cpu_dsize = cpu_hdr.c_size;
+ kd->cpu_data = _kvm_malloc(kd, cpu_hdr.c_size);
+ if (kd->cpu_data == NULL)
+ goto fail;
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;
+ goto fail;
+ sz = Read(kd, kd->pmfd, kd->cpu_data, cpu_hdr.c_size);
+ if (sz != cpu_hdr.c_size)
+ goto fail;
+ offset += cpu_hdr.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;
+ goto fail;
+ sz = Read(kd, kd->pmfd, &mem_hdr, sizeof(mem_hdr));
+ if (sz != sizeof(mem_hdr))
+ goto fail;
+ offset += kcore_hdr.c_seghdrsize;
- if (CORE_GETMAGIC(seghdr) != KCORESEG_MAGIC
- || CORE_GETFLAG(seghdr) != CORE_DATA)
- return (-1);
+ if ((CORE_GETMAGIC(mem_hdr) != KCORESEG_MAGIC) ||
+ (CORE_GETFLAG(mem_hdr) != CORE_DATA))
+ goto fail;
- 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->dump_off = offset;
+ return (0);
+
+fail:
+ if (kd->kcore_hdr != NULL) {
+ free(kd->kcore_hdr);
kd->kcore_hdr = NULL;
- return (-1);
+ }
+ if (kd->cpu_data != NULL) {
+ free(kd->cpu_data);
+ kd->cpu_data = NULL;
+ kd->cpu_dsize = 0;
}
- *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.
+ * The format while on the dump device is: (new format)
+ * kcore_seg_t cpu_hdr;
+ * (opaque) cpu_data; (size is cpu_hdr.c_size)
+ * kcore_seg_t mem_hdr;
+ * (memory) mem_data; (size is mem_hdr.c_size)
*/
-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, dump_off)
kvm_t *kd;
off_t dump_off;
{
- kcore_hdr_t kch;
- kcore_seg_t kseg;
- cpu_kcore_hdr_t ckhdr;
- int hdr_size;
+ kcore_seg_t cpu_hdr;
+ int hdr_size, sz;
- hdr_size = 0;
if (kd->kcore_hdr != NULL) {
_kvm_err(kd, kd->program, "already has a dump header");
return (-1);
}
/*
- * Check for new format crash dump
+ * Validate new format crash dump
*/
if (Lseek(kd, kd->pmfd, dump_off, SEEK_SET) == -1)
return (-1);
- if (Read(kd, kd->pmfd, &kseg, sizeof(kseg)) != sizeof(kseg))
+ sz = Read(kd, kd->pmfd, &cpu_hdr, sizeof(cpu_hdr));
+ if (sz != sizeof(cpu_hdr))
return (-1);
- if ((CORE_GETMAGIC(kseg) == KCORE_MAGIC)
- && ((CORE_GETMID(kseg) == MID_MACHINE))) {
- hdr_size += ALIGN(sizeof(kcore_seg_t));
- if (Lseek(kd, kd->pmfd, dump_off+hdr_size, SEEK_SET) == -1)
- return (-1);
- if (Read(kd, kd->pmfd, &ckhdr, sizeof(ckhdr)) != sizeof(ckhdr))
- return (-1);
- hdr_size += kseg.c_size;
- if (Lseek(kd, kd->pmfd, dump_off+hdr_size, SEEK_SET) == -1)
- return (-1);
- kd->cpu_hdr = (cpu_kcore_hdr_t *)
- _kvm_malloc(kd, sizeof(cpu_kcore_hdr_t));
- *kd->cpu_hdr = ckhdr;
- }
+ if (CORE_GETMAGIC(cpu_hdr) != KCORE_MAGIC)
+ return (-1);
+ if (CORE_GETMID(cpu_hdr) != MID_MACHINE)
+ return (-1);
+ hdr_size = ALIGN(sizeof(cpu_hdr));
+
+ /*
+ * Read the CPU segment.
+ */
+ kd->cpu_dsize = cpu_hdr.c_size;
+ kd->cpu_data = _kvm_malloc(kd, kd->cpu_dsize);
+ if (kd->cpu_data == NULL)
+ goto fail;
+ if (Lseek(kd, kd->pmfd, dump_off+hdr_size, SEEK_SET) == -1)
+ goto fail;
+ sz = Read(kd, kd->pmfd, kd->cpu_data, cpu_hdr.c_size);
+ if (sz != cpu_hdr.c_size)
+ goto fail;
+ hdr_size += kd->cpu_dsize;
+
+ /*
+ * Leave phys mem pointer at beginning of memory data
+ */
+ kd->dump_off = dump_off + hdr_size;
+ if (Lseek(kd, kd->pmfd, kd->dump_off, SEEK_SET) == -1)
+ goto fail;
/*
* Create a kcore_hdr.
*/
- kd->kcore_hdr = (kcore_hdr_t *) _kvm_malloc(kd, sizeof(kcore_hdr_t));
- if (kd->kcore_hdr == NULL) {
- if (kd->cpu_hdr != NULL) {
- free((void *)kd->cpu_hdr);
- kd->cpu_hdr = NULL;
- }
- return (-1);
- }
+ kd->kcore_hdr = _kvm_malloc(kd, sizeof(kcore_hdr_t));
+ if (kd->kcore_hdr == NULL)
+ goto fail;
kd->kcore_hdr->c_hdrsize = ALIGN(sizeof(kcore_hdr_t));
kd->kcore_hdr->c_seghdrsize = ALIGN(sizeof(kcore_seg_t));
kd->kcore_hdr->c_nseg = 2;
CORE_SETMAGIC(*(kd->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->cpu_hdr == NULL) {
- free((void *)kd->kcore_hdr);
- kd->kcore_hdr = NULL;
- _kvm_err(kd, kd->program, "invalid dump");
- }
-
- kd->dump_off = dump_off + hdr_size;
-
/*
* Now that we have a valid header, enable translations.
*/
_kvm_initvtop(kd);
return(hdr_size);
+
+fail:
+ if (kd->kcore_hdr != NULL) {
+ free(kd->kcore_hdr);
+ kd->kcore_hdr = NULL;
+ }
+ if (kd->cpu_data != NULL) {
+ free(kd->cpu_data);
+ kd->cpu_data = NULL;
+ kd->cpu_dsize = 0;
+ }
+ return (-1);
}
static int
long offset;
int gap;
- if (kd->kcore_hdr == NULL || kd->cpu_hdr == NULL) {
+ if (kd->kcore_hdr == NULL || kd->cpu_data == NULL) {
_kvm_err(kd, kd->program, "no valid dump header(s)");
return (-1);
}
* Write the cpu header
*/
CORE_SETMAGIC(seghdr, KCORESEG_MAGIC, 0, CORE_CPU);
- seghdr.c_size = ALIGN(sizeof(cpu_kcore_hdr_t));
+ seghdr.c_size = ALIGN(kd->cpu_dsize);
if (fwrite((void*)&seghdr, sizeof(seghdr), 1, fp) <= 0) {
_kvm_syserr(kd, kd->program, "kvm_dump_wrtheader");
return (-1);
if (clear_gap(kd, fp, gap) == -1)
return (-1);
- if (fwrite((void*)kd->cpu_hdr, sizeof(cpu_kcore_hdr_t), 1, fp) <= 0) {
+ if (fwrite((void*)kd->cpu_data, kd->cpu_dsize, 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);
+ gap = seghdr.c_size - kd->cpu_dsize;
if (clear_gap(kd, fp, gap) == -1)
return (-1);
error |= (kd->db->close)(kd->db);
if (kd->vmst)
_kvm_freevtop(kd);
- if (kd->cpu_hdr != NULL)
- free((void *)kd->cpu_hdr);
+ kd->cpu_dsize = 0;
+ if (kd->cpu_data != NULL)
+ free((void *)kd->cpu_data);
if (kd->kcore_hdr != NULL)
free((void *)kd->kcore_hdr);
if (kd->procbase != 0)
_kvm_err(kd, kd->program, "short read");
return (cc);
} else {
- if ((kd->kcore_hdr == NULL) || (kd->cpu_hdr == NULL)) {
+ if ((kd->kcore_hdr == NULL) || (kd->cpu_data == NULL)) {
_kvm_err(kd, kd->program, "no valid dump header");
return (0);
}
-/* $OpenBSD: kvm_sun3.c,v 1.2 1996/05/05 14:57:53 deraadt Exp $ */
-/* $NetBSD: kvm_sun3.c,v 1.3 1996/03/18 22:34:04 thorpej Exp $ */
+/* $OpenBSD: kvm_sun3.c,v 1.3 1996/05/10 12:58:33 deraadt Exp $ */
+/* $NetBSD: kvm_sun3.c,v 1.4 1996/05/05 04:32:18 gwr Exp $ */
/*-
* Copyright (c) 1992, 1993
* SUCH DAMAGE.
*/
+#if defined(LIBC_SCCS) && !defined(lint)
+#if 0
+static char sccsid[] = "@(#)kvm_sparc.c 8.1 (Berkeley) 6/4/93";
+#else
+static char *rcsid = "$NetBSD: kvm_sun3.c,v 1.4 1996/05/05 04:32:18 gwr Exp $";
+#endif
+#endif /* LIBC_SCCS and not lint */
+
/*
- * Sun3 machine dependent routines for kvm. Hopefully, the forthcoming
- * vm code will one day obsolete this module. Furthermore, I hope it
- * gets here soon, because this basically is an error stub! (sorry)
+ * Sun3 machine dependent routines for kvm.
*/
#include <sys/param.h>
#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 <db.h>
#include <vm/vm.h>
#include <vm/vm_param.h>
-#include <limits.h>
-#include <db.h>
+#include <machine/kcore.h>
+#include <machine/pte.h>
#include "kvm_private.h"
+#define NKSEG (NSEGMAP/8) /* kernel segmap entries */
struct vmstate {
- u_long end;
+ /* Page Map Entry Group (PMEG) */
+ int pmeg[NKSEG][NPAGSEG];
};
-void
-_kvm_freevtop(kd)
- kvm_t *kd;
-{
- if (kd->vmst != 0)
- free(kd->vmst);
-}
-
+/*
+ * Prepare for translation of kernel virtual addresses into offsets
+ * into crash dump files. We use the MMU specific goop written at the
+ * beginning of a crash dump by dumpsys()
+ * Note: sun3 MMU specific!
+ */
int
_kvm_initvtop(kd)
kvm_t *kd;
{
- register int i;
- register int off;
- register struct vmstate *vm;
- struct stat st;
- struct nlist nlist[2];
-
- vm = (struct vmstate *)_kvm_malloc(kd, sizeof(*vm));
- if (vm == 0)
- return (-1);
-
- kd->vmst = vm;
-
- if (fstat(kd->pmfd, &st) < 0)
- return (-1);
-
- /* Get end of kernel address */
- nlist[0].n_name = "_end";
- nlist[1].n_name = 0;
- if (kvm_nlist(kd, nlist) != 0) {
- _kvm_err(kd, kd->program, "pmap_stod: no such symbol");
- return (-1);
- }
- vm->end = (u_long)nlist[0].n_value;
+ register char *p;
+
+ p = kd->cpu_data;
+ p += (NBPG - sizeof(kcore_seg_t));
+ kd->vmst = (struct vmstate *)p;
return (0);
}
-#define VA_OFF(va) (va & (NBPG - 1))
+void
+_kvm_freevtop(kd)
+ kvm_t *kd;
+{
+ /* This was set by pointer arithmetic, not allocation. */
+ kd->vmst = (void*)0;
+}
/*
* Translate a kernel virtual address to a physical address using the
* physical address. This routine is used only for crashdumps.
*/
int
-_kvm_kvatop(kd, va, pa)
+_kvm_kvatop(kd, va, pap)
kvm_t *kd;
u_long va;
- u_long *pa;
+ u_long *pap;
{
- register int end;
+ register cpu_kcore_hdr_t *ckh;
+ u_int segnum, sme, ptenum;
+ int pte, offset;
+ u_long pa;
+
+ if (ISALIVE(kd)) {
+ _kvm_err(kd, 0, "vatop called in live kernel!");
+ return((off_t)0);
+ }
+ ckh = kd->cpu_data;
if (va < KERNBASE) {
- _kvm_err(kd, 0, "invalid address (%x<%x)", va, KERNBASE);
- return (0);
+ _kvm_err(kd, 0, "not a kernel address");
+ return((off_t)0);
}
- end = kd->vmst->end;
- if (va >= end) {
- _kvm_err(kd, 0, "invalid address (%x>=%x)", va, end);
+ /*
+ * Get the segmap entry (sme) from the kernel segmap.
+ * Note: only have segmap entries from KERNBASE to end.
+ */
+ segnum = VA_SEGNUM(va - KERNBASE);
+ ptenum = VA_PTE_NUM(va);
+ offset = va & PGOFSET;
+
+ /* The segmap entry selects a PMEG. */
+ sme = ckh->ksegmap[segnum];
+ pte = kd->vmst->pmeg[sme][ptenum];
+
+ if ((pte & PG_VALID) == 0) {
+ _kvm_err(kd, 0, "page not valid (VA=0x%x)", va);
return (0);
}
+ pa = PG_PA(pte) + offset;
+
+ *pap = pa;
+ return (NBPG - offset);
+}
- *pa = (va - KERNBASE);
- return (end - va);
+/*
+ * Translate a physical address to a file-offset in the crash-dump.
+ */
+off_t
+_kvm_pa2off(kd, pa)
+ kvm_t *kd;
+ u_long pa;
+{
+ return(kd->dump_off + pa);
}