158f0484fSRodney W. Grimes /*- 258f0484fSRodney W. Grimes * Copyright (c) 1989, 1992, 1993 358f0484fSRodney W. Grimes * The Regents of the University of California. All rights reserved. 458f0484fSRodney W. Grimes * 558f0484fSRodney W. Grimes * This code is derived from software developed by the Computer Systems 658f0484fSRodney W. Grimes * Engineering group at Lawrence Berkeley Laboratory under DARPA contract 758f0484fSRodney W. Grimes * BG 91-66 and contributed to Berkeley. 858f0484fSRodney W. Grimes * 958f0484fSRodney W. Grimes * Redistribution and use in source and binary forms, with or without 1058f0484fSRodney W. Grimes * modification, are permitted provided that the following conditions 1158f0484fSRodney W. Grimes * are met: 1258f0484fSRodney W. Grimes * 1. Redistributions of source code must retain the above copyright 1358f0484fSRodney W. Grimes * notice, this list of conditions and the following disclaimer. 1458f0484fSRodney W. Grimes * 2. Redistributions in binary form must reproduce the above copyright 1558f0484fSRodney W. Grimes * notice, this list of conditions and the following disclaimer in the 1658f0484fSRodney W. Grimes * documentation and/or other materials provided with the distribution. 1758f0484fSRodney W. Grimes * 3. All advertising materials mentioning features or use of this software 1858f0484fSRodney W. Grimes * must display the following acknowledgement: 1958f0484fSRodney W. Grimes * This product includes software developed by the University of 2058f0484fSRodney W. Grimes * California, Berkeley and its contributors. 2158f0484fSRodney W. Grimes * 4. Neither the name of the University nor the names of its contributors 2258f0484fSRodney W. Grimes * may be used to endorse or promote products derived from this software 2358f0484fSRodney W. Grimes * without specific prior written permission. 2458f0484fSRodney W. Grimes * 2558f0484fSRodney W. Grimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 2658f0484fSRodney W. Grimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 2758f0484fSRodney W. Grimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2858f0484fSRodney W. Grimes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 2958f0484fSRodney W. Grimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 3058f0484fSRodney W. Grimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 3158f0484fSRodney W. Grimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 3258f0484fSRodney W. Grimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 3358f0484fSRodney W. Grimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 3458f0484fSRodney W. Grimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 3558f0484fSRodney W. Grimes * SUCH DAMAGE. 3658f0484fSRodney W. Grimes */ 3758f0484fSRodney W. Grimes 3858f0484fSRodney W. Grimes #if defined(LIBC_SCCS) && !defined(lint) 398771870cSPeter Wemm #if 0 4058f0484fSRodney W. Grimes static char sccsid[] = "@(#)kvm.c 8.2 (Berkeley) 2/13/94"; 418771870cSPeter Wemm #else 428771870cSPeter Wemm static const char rcsid[] = 438771870cSPeter Wemm "$FreeBSD$"; 448771870cSPeter Wemm #endif 4558f0484fSRodney W. Grimes #endif /* LIBC_SCCS and not lint */ 4658f0484fSRodney W. Grimes 4758f0484fSRodney W. Grimes #include <sys/param.h> 4858f0484fSRodney W. Grimes #include <sys/user.h> 4958f0484fSRodney W. Grimes #include <sys/proc.h> 5058f0484fSRodney W. Grimes #include <sys/ioctl.h> 5158f0484fSRodney W. Grimes #include <sys/stat.h> 5258f0484fSRodney W. Grimes #include <sys/sysctl.h> 53c4a7cdb3SPeter Wemm #include <sys/linker.h> 5458f0484fSRodney W. Grimes 5558f0484fSRodney W. Grimes #include <vm/vm.h> 5658f0484fSRodney W. Grimes #include <vm/vm_param.h> 5758f0484fSRodney W. Grimes #include <vm/swap_pager.h> 5858f0484fSRodney W. Grimes 5958f0484fSRodney W. Grimes #include <machine/vmparam.h> 6058f0484fSRodney W. Grimes 6158f0484fSRodney W. Grimes #include <ctype.h> 6258f0484fSRodney W. Grimes #include <fcntl.h> 6358f0484fSRodney W. Grimes #include <kvm.h> 6458f0484fSRodney W. Grimes #include <limits.h> 6558f0484fSRodney W. Grimes #include <nlist.h> 6658f0484fSRodney W. Grimes #include <paths.h> 6758f0484fSRodney W. Grimes #include <stdio.h> 6858f0484fSRodney W. Grimes #include <stdlib.h> 6958f0484fSRodney W. Grimes #include <string.h> 7058f0484fSRodney W. Grimes #include <unistd.h> 7158f0484fSRodney W. Grimes 7258f0484fSRodney W. Grimes #include "kvm_private.h" 7358f0484fSRodney W. Grimes 74b7875890SDavid E. O'Brien /* from src/lib/libc/gen/nlist.c */ 75b7875890SDavid E. O'Brien int __fdnlist __P((int, struct nlist *)); 76b7875890SDavid E. O'Brien 7758f0484fSRodney W. Grimes char * 7858f0484fSRodney W. Grimes kvm_geterr(kd) 7958f0484fSRodney W. Grimes kvm_t *kd; 8058f0484fSRodney W. Grimes { 8158f0484fSRodney W. Grimes return (kd->errbuf); 8258f0484fSRodney W. Grimes } 8358f0484fSRodney W. Grimes 8458f0484fSRodney W. Grimes #if __STDC__ 8558f0484fSRodney W. Grimes #include <stdarg.h> 8658f0484fSRodney W. Grimes #else 8758f0484fSRodney W. Grimes #include <varargs.h> 8858f0484fSRodney W. Grimes #endif 8958f0484fSRodney W. Grimes 9058f0484fSRodney W. Grimes /* 9158f0484fSRodney W. Grimes * Report an error using printf style arguments. "program" is kd->program 9258f0484fSRodney W. Grimes * on hard errors, and 0 on soft errors, so that under sun error emulation, 9358f0484fSRodney W. Grimes * only hard errors are printed out (otherwise, programs like gdb will 9458f0484fSRodney W. Grimes * generate tons of error messages when trying to access bogus pointers). 9558f0484fSRodney W. Grimes */ 9658f0484fSRodney W. Grimes void 9758f0484fSRodney W. Grimes #if __STDC__ 9858f0484fSRodney W. Grimes _kvm_err(kvm_t *kd, const char *program, const char *fmt, ...) 9958f0484fSRodney W. Grimes #else 10058f0484fSRodney W. Grimes _kvm_err(kd, program, fmt, va_alist) 10158f0484fSRodney W. Grimes kvm_t *kd; 10258f0484fSRodney W. Grimes char *program, *fmt; 10358f0484fSRodney W. Grimes va_dcl 10458f0484fSRodney W. Grimes #endif 10558f0484fSRodney W. Grimes { 10658f0484fSRodney W. Grimes va_list ap; 10758f0484fSRodney W. Grimes 10858f0484fSRodney W. Grimes #ifdef __STDC__ 10958f0484fSRodney W. Grimes va_start(ap, fmt); 11058f0484fSRodney W. Grimes #else 11158f0484fSRodney W. Grimes va_start(ap); 11258f0484fSRodney W. Grimes #endif 11358f0484fSRodney W. Grimes if (program != NULL) { 11458f0484fSRodney W. Grimes (void)fprintf(stderr, "%s: ", program); 11558f0484fSRodney W. Grimes (void)vfprintf(stderr, fmt, ap); 11658f0484fSRodney W. Grimes (void)fputc('\n', stderr); 11758f0484fSRodney W. Grimes } else 11858f0484fSRodney W. Grimes (void)vsnprintf(kd->errbuf, 11958f0484fSRodney W. Grimes sizeof(kd->errbuf), (char *)fmt, ap); 12058f0484fSRodney W. Grimes 12158f0484fSRodney W. Grimes va_end(ap); 12258f0484fSRodney W. Grimes } 12358f0484fSRodney W. Grimes 12458f0484fSRodney W. Grimes void 12558f0484fSRodney W. Grimes #if __STDC__ 12658f0484fSRodney W. Grimes _kvm_syserr(kvm_t *kd, const char *program, const char *fmt, ...) 12758f0484fSRodney W. Grimes #else 12858f0484fSRodney W. Grimes _kvm_syserr(kd, program, fmt, va_alist) 12958f0484fSRodney W. Grimes kvm_t *kd; 13058f0484fSRodney W. Grimes char *program, *fmt; 13158f0484fSRodney W. Grimes va_dcl 13258f0484fSRodney W. Grimes #endif 13358f0484fSRodney W. Grimes { 13458f0484fSRodney W. Grimes va_list ap; 13558f0484fSRodney W. Grimes register int n; 13658f0484fSRodney W. Grimes 13758f0484fSRodney W. Grimes #if __STDC__ 13858f0484fSRodney W. Grimes va_start(ap, fmt); 13958f0484fSRodney W. Grimes #else 14058f0484fSRodney W. Grimes va_start(ap); 14158f0484fSRodney W. Grimes #endif 14258f0484fSRodney W. Grimes if (program != NULL) { 14358f0484fSRodney W. Grimes (void)fprintf(stderr, "%s: ", program); 14458f0484fSRodney W. Grimes (void)vfprintf(stderr, fmt, ap); 14558f0484fSRodney W. Grimes (void)fprintf(stderr, ": %s\n", strerror(errno)); 14658f0484fSRodney W. Grimes } else { 14758f0484fSRodney W. Grimes register char *cp = kd->errbuf; 14858f0484fSRodney W. Grimes 14958f0484fSRodney W. Grimes (void)vsnprintf(cp, sizeof(kd->errbuf), (char *)fmt, ap); 15058f0484fSRodney W. Grimes n = strlen(cp); 15158f0484fSRodney W. Grimes (void)snprintf(&cp[n], sizeof(kd->errbuf) - n, ": %s", 15258f0484fSRodney W. Grimes strerror(errno)); 15358f0484fSRodney W. Grimes } 15458f0484fSRodney W. Grimes va_end(ap); 15558f0484fSRodney W. Grimes } 15658f0484fSRodney W. Grimes 15758f0484fSRodney W. Grimes void * 15858f0484fSRodney W. Grimes _kvm_malloc(kd, n) 15958f0484fSRodney W. Grimes register kvm_t *kd; 16058f0484fSRodney W. Grimes register size_t n; 16158f0484fSRodney W. Grimes { 16258f0484fSRodney W. Grimes void *p; 16358f0484fSRodney W. Grimes 164d7b100f9SAndrey A. Chernov if ((p = calloc(n, sizeof(char))) == NULL) 165d7b100f9SAndrey A. Chernov _kvm_err(kd, kd->program, "can't allocate %u bytes: %s", 166d7b100f9SAndrey A. Chernov n, strerror(errno)); 16758f0484fSRodney W. Grimes return (p); 16858f0484fSRodney W. Grimes } 16958f0484fSRodney W. Grimes 17058f0484fSRodney W. Grimes static kvm_t * 1718771870cSPeter Wemm _kvm_open(kd, uf, mf, flag, errout) 17258f0484fSRodney W. Grimes register kvm_t *kd; 17358f0484fSRodney W. Grimes const char *uf; 17458f0484fSRodney W. Grimes const char *mf; 17558f0484fSRodney W. Grimes int flag; 17658f0484fSRodney W. Grimes char *errout; 17758f0484fSRodney W. Grimes { 17858f0484fSRodney W. Grimes struct stat st; 17958f0484fSRodney W. Grimes 18058f0484fSRodney W. Grimes kd->vmfd = -1; 18158f0484fSRodney W. Grimes kd->pmfd = -1; 18258f0484fSRodney W. Grimes kd->nlfd = -1; 18358f0484fSRodney W. Grimes kd->vmst = 0; 18458f0484fSRodney W. Grimes kd->procbase = 0; 18558f0484fSRodney W. Grimes kd->argspc = 0; 18658f0484fSRodney W. Grimes kd->argv = 0; 18758f0484fSRodney W. Grimes 18858f0484fSRodney W. Grimes if (uf == 0) 1894be4929cSGarrett Wollman uf = getbootfile(); 19058f0484fSRodney W. Grimes else if (strlen(uf) >= MAXPATHLEN) { 19158f0484fSRodney W. Grimes _kvm_err(kd, kd->program, "exec file name too long"); 19258f0484fSRodney W. Grimes goto failed; 19358f0484fSRodney W. Grimes } 19458f0484fSRodney W. Grimes if (flag & ~O_RDWR) { 19558f0484fSRodney W. Grimes _kvm_err(kd, kd->program, "bad flags arg"); 19658f0484fSRodney W. Grimes goto failed; 19758f0484fSRodney W. Grimes } 19858f0484fSRodney W. Grimes if (mf == 0) 19958f0484fSRodney W. Grimes mf = _PATH_MEM; 20058f0484fSRodney W. Grimes 20158f0484fSRodney W. Grimes if ((kd->pmfd = open(mf, flag, 0)) < 0) { 20258f0484fSRodney W. Grimes _kvm_syserr(kd, kd->program, "%s", mf); 20358f0484fSRodney W. Grimes goto failed; 20458f0484fSRodney W. Grimes } 20558f0484fSRodney W. Grimes if (fstat(kd->pmfd, &st) < 0) { 20658f0484fSRodney W. Grimes _kvm_syserr(kd, kd->program, "%s", mf); 20758f0484fSRodney W. Grimes goto failed; 20858f0484fSRodney W. Grimes } 20958f0484fSRodney W. Grimes if (S_ISCHR(st.st_mode)) { 21058f0484fSRodney W. Grimes /* 21158f0484fSRodney W. Grimes * If this is a character special device, then check that 21258f0484fSRodney W. Grimes * it's /dev/mem. If so, open kmem too. (Maybe we should 21358f0484fSRodney W. Grimes * make it work for either /dev/mem or /dev/kmem -- in either 21458f0484fSRodney W. Grimes * case you're working with a live kernel.) 21558f0484fSRodney W. Grimes */ 21635e6b695SPoul-Henning Kamp if (strcmp(mf, _PATH_DEVNULL) == 0) { 21735e6b695SPoul-Henning Kamp kd->vmfd = open(_PATH_DEVNULL, O_RDONLY); 21835e6b695SPoul-Henning Kamp } else if (strcmp(mf, _PATH_MEM) != 0) { 21958f0484fSRodney W. Grimes _kvm_err(kd, kd->program, 22058f0484fSRodney W. Grimes "%s: not physical memory device", mf); 22158f0484fSRodney W. Grimes goto failed; 22235e6b695SPoul-Henning Kamp } else { 22358f0484fSRodney W. Grimes if ((kd->vmfd = open(_PATH_KMEM, flag)) < 0) { 22458f0484fSRodney W. Grimes _kvm_syserr(kd, kd->program, "%s", _PATH_KMEM); 22558f0484fSRodney W. Grimes goto failed; 22658f0484fSRodney W. Grimes } 22735e6b695SPoul-Henning Kamp } 22858f0484fSRodney W. Grimes } else { 22958f0484fSRodney W. Grimes /* 23058f0484fSRodney W. Grimes * This is a crash dump. 23135e6b695SPoul-Henning Kamp * Initialize the virtual address translation machinery, 23258f0484fSRodney W. Grimes * but first setup the namelist fd. 23358f0484fSRodney W. Grimes */ 23458f0484fSRodney W. Grimes if ((kd->nlfd = open(uf, O_RDONLY, 0)) < 0) { 23558f0484fSRodney W. Grimes _kvm_syserr(kd, kd->program, "%s", uf); 23658f0484fSRodney W. Grimes goto failed; 23758f0484fSRodney W. Grimes } 23858f0484fSRodney W. Grimes if (_kvm_initvtop(kd) < 0) 23958f0484fSRodney W. Grimes goto failed; 24058f0484fSRodney W. Grimes } 24158f0484fSRodney W. Grimes return (kd); 24258f0484fSRodney W. Grimes failed: 24358f0484fSRodney W. Grimes /* 24458f0484fSRodney W. Grimes * Copy out the error if doing sane error semantics. 24558f0484fSRodney W. Grimes */ 24658f0484fSRodney W. Grimes if (errout != 0) 24758f0484fSRodney W. Grimes strcpy(errout, kd->errbuf); 24858f0484fSRodney W. Grimes (void)kvm_close(kd); 24958f0484fSRodney W. Grimes return (0); 25058f0484fSRodney W. Grimes } 25158f0484fSRodney W. Grimes 25258f0484fSRodney W. Grimes kvm_t * 25358f0484fSRodney W. Grimes kvm_openfiles(uf, mf, sf, flag, errout) 25458f0484fSRodney W. Grimes const char *uf; 25558f0484fSRodney W. Grimes const char *mf; 25658f0484fSRodney W. Grimes const char *sf; 25758f0484fSRodney W. Grimes int flag; 25858f0484fSRodney W. Grimes char *errout; 25958f0484fSRodney W. Grimes { 26058f0484fSRodney W. Grimes register kvm_t *kd; 26158f0484fSRodney W. Grimes 26258f0484fSRodney W. Grimes if ((kd = malloc(sizeof(*kd))) == NULL) { 26358f0484fSRodney W. Grimes (void)strcpy(errout, strerror(errno)); 26458f0484fSRodney W. Grimes return (0); 26558f0484fSRodney W. Grimes } 266a52219bbSPeter Wemm memset(kd, 0, sizeof(*kd)); 26758f0484fSRodney W. Grimes kd->program = 0; 2688771870cSPeter Wemm return (_kvm_open(kd, uf, mf, flag, errout)); 26958f0484fSRodney W. Grimes } 27058f0484fSRodney W. Grimes 27158f0484fSRodney W. Grimes kvm_t * 27212eaa3d5SPoul-Henning Kamp kvm_open(uf, mf, sf, flag, errstr) 27358f0484fSRodney W. Grimes const char *uf; 27458f0484fSRodney W. Grimes const char *mf; 27558f0484fSRodney W. Grimes const char *sf; 27658f0484fSRodney W. Grimes int flag; 27712eaa3d5SPoul-Henning Kamp const char *errstr; 27858f0484fSRodney W. Grimes { 27958f0484fSRodney W. Grimes register kvm_t *kd; 28058f0484fSRodney W. Grimes 28112eaa3d5SPoul-Henning Kamp if ((kd = malloc(sizeof(*kd))) == NULL) { 28264f14011SBruce Evans if (errstr != NULL) 28312eaa3d5SPoul-Henning Kamp (void)fprintf(stderr, "%s: %s\n", 28464f14011SBruce Evans errstr, strerror(errno)); 28558f0484fSRodney W. Grimes return (0); 28658f0484fSRodney W. Grimes } 287a52219bbSPeter Wemm memset(kd, 0, sizeof(*kd)); 28812eaa3d5SPoul-Henning Kamp kd->program = errstr; 2898771870cSPeter Wemm return (_kvm_open(kd, uf, mf, flag, NULL)); 29058f0484fSRodney W. Grimes } 29158f0484fSRodney W. Grimes 29258f0484fSRodney W. Grimes int 29358f0484fSRodney W. Grimes kvm_close(kd) 29458f0484fSRodney W. Grimes kvm_t *kd; 29558f0484fSRodney W. Grimes { 29658f0484fSRodney W. Grimes register int error = 0; 29758f0484fSRodney W. Grimes 29858f0484fSRodney W. Grimes if (kd->pmfd >= 0) 29958f0484fSRodney W. Grimes error |= close(kd->pmfd); 30058f0484fSRodney W. Grimes if (kd->vmfd >= 0) 30158f0484fSRodney W. Grimes error |= close(kd->vmfd); 30258f0484fSRodney W. Grimes if (kd->nlfd >= 0) 30358f0484fSRodney W. Grimes error |= close(kd->nlfd); 30458f0484fSRodney W. Grimes if (kd->vmst) 30558f0484fSRodney W. Grimes _kvm_freevtop(kd); 30658f0484fSRodney W. Grimes if (kd->procbase != 0) 30758f0484fSRodney W. Grimes free((void *)kd->procbase); 30858f0484fSRodney W. Grimes if (kd->argv != 0) 30958f0484fSRodney W. Grimes free((void *)kd->argv); 31058f0484fSRodney W. Grimes free((void *)kd); 31158f0484fSRodney W. Grimes 31258f0484fSRodney W. Grimes return (0); 31358f0484fSRodney W. Grimes } 31458f0484fSRodney W. Grimes 31558f0484fSRodney W. Grimes int 31658f0484fSRodney W. Grimes kvm_nlist(kd, nl) 31758f0484fSRodney W. Grimes kvm_t *kd; 31858f0484fSRodney W. Grimes struct nlist *nl; 31958f0484fSRodney W. Grimes { 32058f0484fSRodney W. Grimes register struct nlist *p; 32158f0484fSRodney W. Grimes register int nvalid; 322c4a7cdb3SPeter Wemm struct kld_sym_lookup lookup; 32358f0484fSRodney W. Grimes 32458f0484fSRodney W. Grimes /* 325c4a7cdb3SPeter Wemm * If we can't use the kld symbol lookup, revert to the 32658f0484fSRodney W. Grimes * slow library call. 32758f0484fSRodney W. Grimes */ 328c4a7cdb3SPeter Wemm if (!ISALIVE(kd)) 32958f0484fSRodney W. Grimes return (__fdnlist(kd->nlfd, nl)); 33058f0484fSRodney W. Grimes 33158f0484fSRodney W. Grimes /* 332c4a7cdb3SPeter Wemm * We can use the kld lookup syscall. Go through each nlist entry 333c4a7cdb3SPeter Wemm * and look it up with a kldsym(2) syscall. 33458f0484fSRodney W. Grimes */ 33558f0484fSRodney W. Grimes nvalid = 0; 33658f0484fSRodney W. Grimes for (p = nl; p->n_name && p->n_name[0]; ++p) { 337c4a7cdb3SPeter Wemm lookup.version = sizeof(lookup); 338c4a7cdb3SPeter Wemm lookup.symname = p->n_name; 339c4a7cdb3SPeter Wemm lookup.symvalue = 0; 340c4a7cdb3SPeter Wemm lookup.symsize = 0; 34158f0484fSRodney W. Grimes 342c4a7cdb3SPeter Wemm if (lookup.symname[0] == '_') 343c4a7cdb3SPeter Wemm lookup.symname++; 344c4a7cdb3SPeter Wemm 345c4a7cdb3SPeter Wemm if (kldsym(0, KLDSYM_LOOKUP, &lookup) != -1) { 346c4a7cdb3SPeter Wemm p->n_type = N_TEXT; 347c4a7cdb3SPeter Wemm p->n_other = 0; 348c4a7cdb3SPeter Wemm p->n_desc = 0; 349c4a7cdb3SPeter Wemm p->n_value = lookup.symvalue; 35058f0484fSRodney W. Grimes ++nvalid; 351c4a7cdb3SPeter Wemm /* lookup.symsize */ 352c4a7cdb3SPeter Wemm } 35358f0484fSRodney W. Grimes } 35458f0484fSRodney W. Grimes /* 35558f0484fSRodney W. Grimes * Return the number of entries that weren't found. 35658f0484fSRodney W. Grimes */ 35758f0484fSRodney W. Grimes return ((p - nl) - nvalid); 35858f0484fSRodney W. Grimes } 35958f0484fSRodney W. Grimes 36058f0484fSRodney W. Grimes ssize_t 36158f0484fSRodney W. Grimes kvm_read(kd, kva, buf, len) 36258f0484fSRodney W. Grimes kvm_t *kd; 36358f0484fSRodney W. Grimes register u_long kva; 36458f0484fSRodney W. Grimes register void *buf; 36558f0484fSRodney W. Grimes register size_t len; 36658f0484fSRodney W. Grimes { 36758f0484fSRodney W. Grimes register int cc; 36858f0484fSRodney W. Grimes register void *cp; 36958f0484fSRodney W. Grimes 37058f0484fSRodney W. Grimes if (ISALIVE(kd)) { 37158f0484fSRodney W. Grimes /* 37258f0484fSRodney W. Grimes * We're using /dev/kmem. Just read straight from the 37358f0484fSRodney W. Grimes * device and let the active kernel do the address translation. 37458f0484fSRodney W. Grimes */ 37558f0484fSRodney W. Grimes errno = 0; 37658f0484fSRodney W. Grimes if (lseek(kd->vmfd, (off_t)kva, 0) == -1 && errno != 0) { 37758f0484fSRodney W. Grimes _kvm_err(kd, 0, "invalid address (%x)", kva); 37891a594d8SJacques Vidrine return (-1); 37958f0484fSRodney W. Grimes } 38058f0484fSRodney W. Grimes cc = read(kd->vmfd, buf, len); 38158f0484fSRodney W. Grimes if (cc < 0) { 38258f0484fSRodney W. Grimes _kvm_syserr(kd, 0, "kvm_read"); 38391a594d8SJacques Vidrine return (-1); 38458f0484fSRodney W. Grimes } else if (cc < len) 38558f0484fSRodney W. Grimes _kvm_err(kd, kd->program, "short read"); 38658f0484fSRodney W. Grimes return (cc); 38758f0484fSRodney W. Grimes } else { 38858f0484fSRodney W. Grimes cp = buf; 38958f0484fSRodney W. Grimes while (len > 0) { 39058f0484fSRodney W. Grimes u_long pa; 39158f0484fSRodney W. Grimes 39258f0484fSRodney W. Grimes cc = _kvm_kvatop(kd, kva, &pa); 39358f0484fSRodney W. Grimes if (cc == 0) 39491a594d8SJacques Vidrine return (-1); 39558f0484fSRodney W. Grimes if (cc > len) 39658f0484fSRodney W. Grimes cc = len; 39758f0484fSRodney W. Grimes errno = 0; 39858f0484fSRodney W. Grimes if (lseek(kd->pmfd, (off_t)pa, 0) == -1 && errno != 0) { 39958f0484fSRodney W. Grimes _kvm_syserr(kd, 0, _PATH_MEM); 40058f0484fSRodney W. Grimes break; 40158f0484fSRodney W. Grimes } 40258f0484fSRodney W. Grimes cc = read(kd->pmfd, cp, cc); 40358f0484fSRodney W. Grimes if (cc < 0) { 40458f0484fSRodney W. Grimes _kvm_syserr(kd, kd->program, "kvm_read"); 40558f0484fSRodney W. Grimes break; 40658f0484fSRodney W. Grimes } 40758f0484fSRodney W. Grimes /* 40858f0484fSRodney W. Grimes * If kvm_kvatop returns a bogus value or our core 40958f0484fSRodney W. Grimes * file is truncated, we might wind up seeking beyond 41058f0484fSRodney W. Grimes * the end of the core file in which case the read will 41158f0484fSRodney W. Grimes * return 0 (EOF). 41258f0484fSRodney W. Grimes */ 41358f0484fSRodney W. Grimes if (cc == 0) 41458f0484fSRodney W. Grimes break; 41558f0484fSRodney W. Grimes (char *)cp += cc; 41658f0484fSRodney W. Grimes kva += cc; 41758f0484fSRodney W. Grimes len -= cc; 41858f0484fSRodney W. Grimes } 41958f0484fSRodney W. Grimes return ((char *)cp - (char *)buf); 42058f0484fSRodney W. Grimes } 42158f0484fSRodney W. Grimes /* NOTREACHED */ 42258f0484fSRodney W. Grimes } 42358f0484fSRodney W. Grimes 42458f0484fSRodney W. Grimes ssize_t 42558f0484fSRodney W. Grimes kvm_write(kd, kva, buf, len) 42658f0484fSRodney W. Grimes kvm_t *kd; 42758f0484fSRodney W. Grimes register u_long kva; 42858f0484fSRodney W. Grimes register const void *buf; 42958f0484fSRodney W. Grimes register size_t len; 43058f0484fSRodney W. Grimes { 43158f0484fSRodney W. Grimes register int cc; 43258f0484fSRodney W. Grimes 43358f0484fSRodney W. Grimes if (ISALIVE(kd)) { 43458f0484fSRodney W. Grimes /* 43558f0484fSRodney W. Grimes * Just like kvm_read, only we write. 43658f0484fSRodney W. Grimes */ 43758f0484fSRodney W. Grimes errno = 0; 43858f0484fSRodney W. Grimes if (lseek(kd->vmfd, (off_t)kva, 0) == -1 && errno != 0) { 43958f0484fSRodney W. Grimes _kvm_err(kd, 0, "invalid address (%x)", kva); 44091a594d8SJacques Vidrine return (-1); 44158f0484fSRodney W. Grimes } 44258f0484fSRodney W. Grimes cc = write(kd->vmfd, buf, len); 44358f0484fSRodney W. Grimes if (cc < 0) { 44458f0484fSRodney W. Grimes _kvm_syserr(kd, 0, "kvm_write"); 44591a594d8SJacques Vidrine return (-1); 44658f0484fSRodney W. Grimes } else if (cc < len) 44758f0484fSRodney W. Grimes _kvm_err(kd, kd->program, "short write"); 44858f0484fSRodney W. Grimes return (cc); 44958f0484fSRodney W. Grimes } else { 45058f0484fSRodney W. Grimes _kvm_err(kd, kd->program, 45158f0484fSRodney W. Grimes "kvm_write not implemented for dead kernels"); 45291a594d8SJacques Vidrine return (-1); 45358f0484fSRodney W. Grimes } 45458f0484fSRodney W. Grimes /* NOTREACHED */ 45558f0484fSRodney W. Grimes } 456