? o Index: kvm.c =================================================================== RCS file: /cvsroot/src/lib/libkvm/kvm.c,v retrieving revision 1.105 diff -u -p -u -r1.105 kvm.c --- kvm.c 8 Mar 2020 00:06:42 -0000 1.105 +++ kvm.c 27 Apr 2020 23:34:50 -0000 @@ -48,6 +48,7 @@ __RCSID("$NetBSD: kvm.c,v 1.105 2020/03/ #include #include #include +#include #include #include @@ -205,6 +206,19 @@ _kvm_pread(kvm_t *kd, int fd, void *buf, return size; } +static ssize_t +_kvm_pwrite(kvm_t *kd, const void *buf, size_t size, off_t off) +{ + char *mem = kd->dump_mem; + + if (size + off > kd->dump_size) { + errno = EINVAL; + return -1; + } + memcpy(mem + off, buf, size); + return size; +} + /* * Wrapper around the pread(2) system call; calls _kvm_syserr() for us * in the event of emergency. @@ -256,6 +270,8 @@ _kvm_open(kvm_t *kd, const char *uf, con kd->iobuf = NULL; kd->iobufsz = 0; kd->errbuf[0] = '\0'; + kd->dump_mem = MAP_FAILED; + kd->dump_size = 0; if (flag & KVM_NO_FILES) { kd->alive = KVM_ALIVE_SYSCTL; @@ -371,6 +387,11 @@ _kvm_open(kvm_t *kd, const char *uf, con if (_kvm_initvtop(kd) < 0) goto failed; } + kd->dump_size = (size_t)st.st_size; + kd->dump_mem = mmap(NULL, kd->dump_size, PROT_READ|PROT_WRITE, + MAP_FILE|MAP_PRIVATE, kd->pmfd, 0); + if (kd->dump_mem == MAP_FAILED) + goto failed; } return (kd); failed: @@ -758,6 +779,8 @@ kvm_close(kvm_t *kd) free(kd->argv); if (kd->iobuf != 0) free(kd->iobuf); + if (kd->dump_mem != MAP_FAILED) + munmap(kd->dump_mem, kd->dump_size); free(kd); return (error); @@ -891,6 +914,7 @@ ssize_t kvm_write(kvm_t *kd, u_long kva, const void *buf, size_t len) { int cc; + const void *cp; if (ISKMEM(kd)) { /* @@ -909,9 +933,43 @@ kvm_write(kvm_t *kd, u_long kva, const v "can't use kvm_write"); return (-1); } else { - _kvm_err(kd, kd->program, - "kvm_write not implemented for dead kernels"); - return (-1); + if (kd->dump_mem == MAP_FAILED) { + _kvm_err(kd, kd->program, + "kvm_write not implemented for dead kernels"); + return (-1); + } + cp = buf; + while (len > 0) { + paddr_t pa; + off_t foff; + + cc = _kvm_kvatop(kd, (vaddr_t)kva, &pa); + if (cc == 0) { + _kvm_err(kd, kd->program, "_kvm_kvatop(%lx)", kva); + return (-1); + } + if (cc > len) + cc = len; + foff = _kvm_pa2off(kd, pa); + errno = 0; + cc = _kvm_pwrite(kd, cp, (size_t)cc, foff); + if (cc < 0) { + _kvm_syserr(kd, kd->program, "kvm_pwrite"); + break; + } + /* + * If kvm_kvatop returns a bogus value or our core + * file is truncated, we might wind up seeking beyond + * the end of the core file in which case the read will + * return 0 (EOF). + */ + if (cc == 0) + break; + cp = (const char *)cp + cc; + kva += cc; + len -= cc; + } + return ((const char *)cp - (const char *)buf); } /* NOTREACHED */ } Index: kvm_private.h =================================================================== RCS file: /cvsroot/src/lib/libkvm/kvm_private.h,v retrieving revision 1.20 diff -u -p -u -r1.20 kvm_private.h --- kvm_private.h 12 Sep 2011 21:11:32 -0000 1.20 +++ kvm_private.h 27 Apr 2020 23:34:50 -0000 @@ -72,6 +72,8 @@ struct __kvm { size_t cpu_dsize; void *cpu_data; off_t dump_off; /* Where the actual dump starts */ + void *dump_mem; + size_t dump_size; /* * Kernel virtual address translation state. This only gets filled