Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/lib/libkvm Implement kvm_write() for dump files. We map the ...



details:   https://anonhg.NetBSD.org/src/rev/b281e4a774fc
branches:  trunk
changeset: 1009597:b281e4a774fc
user:      christos <christos%NetBSD.org@localhost>
date:      Tue Apr 28 00:12:01 2020 +0000

description:
Implement kvm_write() for dump files. We map the file privately so that
changes don't get propagated back, and then write to the private buffer.
This is not useful yes, but it is simple enough to make pread use the buffer
if it is available.

diffstat:

 lib/libkvm/kvm.c         |  68 ++++++++++++++++++++++++++++++++++++++++++++---
 lib/libkvm/kvm_private.h |   4 ++-
 2 files changed, 66 insertions(+), 6 deletions(-)

diffs (149 lines):

diff -r 183443bffbf1 -r b281e4a774fc lib/libkvm/kvm.c
--- a/lib/libkvm/kvm.c  Mon Apr 27 23:54:43 2020 +0000
+++ b/lib/libkvm/kvm.c  Tue Apr 28 00:12:01 2020 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: kvm.c,v 1.105 2020/03/08 00:06:42 chs Exp $    */
+/*     $NetBSD: kvm.c,v 1.106 2020/04/28 00:12:01 christos Exp $       */
 
 /*-
  * Copyright (c) 1989, 1992, 1993
@@ -38,7 +38,7 @@
 #if 0
 static char sccsid[] = "@(#)kvm.c      8.2 (Berkeley) 2/13/94";
 #else
-__RCSID("$NetBSD: kvm.c,v 1.105 2020/03/08 00:06:42 chs Exp $");
+__RCSID("$NetBSD: kvm.c,v 1.106 2020/04/28 00:12:01 christos Exp $");
 #endif
 #endif /* LIBC_SCCS and not lint */
 
@@ -48,6 +48,7 @@
 #include <sys/ioctl.h>
 #include <sys/stat.h>
 #include <sys/sysctl.h>
+#include <sys/mman.h>
 
 #include <sys/core.h>
 #include <sys/exec.h>
@@ -205,6 +206,19 @@
        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 @@
        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 @@
                        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 @@
                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 @@
 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 @@
                    "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 */
 }
diff -r 183443bffbf1 -r b281e4a774fc lib/libkvm/kvm_private.h
--- a/lib/libkvm/kvm_private.h  Mon Apr 27 23:54:43 2020 +0000
+++ b/lib/libkvm/kvm_private.h  Tue Apr 28 00:12:01 2020 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: kvm_private.h,v 1.20 2011/09/12 21:11:32 christos Exp $        */
+/*     $NetBSD: kvm_private.h,v 1.21 2020/04/28 00:12:01 christos Exp $        */
 
 /*-
  * Copyright (c) 1992, 1993
@@ -72,6 +72,8 @@
        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



Home | Main Index | Thread Index | Old Index