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 38e67f5b9fSMatthew Dillon #include <sys/cdefs.h> 39e67f5b9fSMatthew Dillon __FBSDID("$FreeBSD$"); 40e67f5b9fSMatthew Dillon 4158f0484fSRodney W. Grimes #if defined(LIBC_SCCS) && !defined(lint) 428771870cSPeter Wemm #if 0 4358f0484fSRodney W. Grimes static char sccsid[] = "@(#)kvm.c 8.2 (Berkeley) 2/13/94"; 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 */ 7569160b1eSDavid E. O'Brien int __fdnlist(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 #include <stdarg.h> 8558f0484fSRodney W. Grimes 8658f0484fSRodney W. Grimes /* 8758f0484fSRodney W. Grimes * Report an error using printf style arguments. "program" is kd->program 8858f0484fSRodney W. Grimes * on hard errors, and 0 on soft errors, so that under sun error emulation, 8958f0484fSRodney W. Grimes * only hard errors are printed out (otherwise, programs like gdb will 9058f0484fSRodney W. Grimes * generate tons of error messages when trying to access bogus pointers). 9158f0484fSRodney W. Grimes */ 9258f0484fSRodney W. Grimes void 9358f0484fSRodney W. Grimes _kvm_err(kvm_t *kd, const char *program, const char *fmt, ...) 9458f0484fSRodney W. Grimes { 9558f0484fSRodney W. Grimes va_list ap; 9658f0484fSRodney W. Grimes 9758f0484fSRodney W. Grimes va_start(ap, fmt); 9858f0484fSRodney W. Grimes if (program != NULL) { 9958f0484fSRodney W. Grimes (void)fprintf(stderr, "%s: ", program); 10058f0484fSRodney W. Grimes (void)vfprintf(stderr, fmt, ap); 10158f0484fSRodney W. Grimes (void)fputc('\n', stderr); 10258f0484fSRodney W. Grimes } else 10358f0484fSRodney W. Grimes (void)vsnprintf(kd->errbuf, 10458f0484fSRodney W. Grimes sizeof(kd->errbuf), (char *)fmt, ap); 10558f0484fSRodney W. Grimes 10658f0484fSRodney W. Grimes va_end(ap); 10758f0484fSRodney W. Grimes } 10858f0484fSRodney W. Grimes 10958f0484fSRodney W. Grimes void 11058f0484fSRodney W. Grimes _kvm_syserr(kvm_t *kd, const char *program, const char *fmt, ...) 11158f0484fSRodney W. Grimes { 11258f0484fSRodney W. Grimes va_list ap; 113be04b6d1SDavid E. O'Brien int n; 11458f0484fSRodney W. Grimes 11558f0484fSRodney W. Grimes va_start(ap, fmt); 11658f0484fSRodney W. Grimes if (program != NULL) { 11758f0484fSRodney W. Grimes (void)fprintf(stderr, "%s: ", program); 11858f0484fSRodney W. Grimes (void)vfprintf(stderr, fmt, ap); 11958f0484fSRodney W. Grimes (void)fprintf(stderr, ": %s\n", strerror(errno)); 12058f0484fSRodney W. Grimes } else { 121be04b6d1SDavid E. O'Brien char *cp = kd->errbuf; 12258f0484fSRodney W. Grimes 12358f0484fSRodney W. Grimes (void)vsnprintf(cp, sizeof(kd->errbuf), (char *)fmt, ap); 12458f0484fSRodney W. Grimes n = strlen(cp); 12558f0484fSRodney W. Grimes (void)snprintf(&cp[n], sizeof(kd->errbuf) - n, ": %s", 12658f0484fSRodney W. Grimes strerror(errno)); 12758f0484fSRodney W. Grimes } 12858f0484fSRodney W. Grimes va_end(ap); 12958f0484fSRodney W. Grimes } 13058f0484fSRodney W. Grimes 13158f0484fSRodney W. Grimes void * 13258f0484fSRodney W. Grimes _kvm_malloc(kd, n) 133be04b6d1SDavid E. O'Brien kvm_t *kd; 134be04b6d1SDavid E. O'Brien size_t n; 13558f0484fSRodney W. Grimes { 13658f0484fSRodney W. Grimes void *p; 13758f0484fSRodney W. Grimes 138d7b100f9SAndrey A. Chernov if ((p = calloc(n, sizeof(char))) == NULL) 139d7b100f9SAndrey A. Chernov _kvm_err(kd, kd->program, "can't allocate %u bytes: %s", 140d7b100f9SAndrey A. Chernov n, strerror(errno)); 14158f0484fSRodney W. Grimes return (p); 14258f0484fSRodney W. Grimes } 14358f0484fSRodney W. Grimes 14458f0484fSRodney W. Grimes static kvm_t * 1458771870cSPeter Wemm _kvm_open(kd, uf, mf, flag, errout) 146be04b6d1SDavid E. O'Brien kvm_t *kd; 14758f0484fSRodney W. Grimes const char *uf; 14858f0484fSRodney W. Grimes const char *mf; 14958f0484fSRodney W. Grimes int flag; 15058f0484fSRodney W. Grimes char *errout; 15158f0484fSRodney W. Grimes { 15258f0484fSRodney W. Grimes struct stat st; 15358f0484fSRodney W. Grimes 15458f0484fSRodney W. Grimes kd->vmfd = -1; 15558f0484fSRodney W. Grimes kd->pmfd = -1; 15658f0484fSRodney W. Grimes kd->nlfd = -1; 15758f0484fSRodney W. Grimes kd->vmst = 0; 15858f0484fSRodney W. Grimes kd->procbase = 0; 15958f0484fSRodney W. Grimes kd->argspc = 0; 16058f0484fSRodney W. Grimes kd->argv = 0; 16158f0484fSRodney W. Grimes 16258f0484fSRodney W. Grimes if (uf == 0) 1634be4929cSGarrett Wollman uf = getbootfile(); 16458f0484fSRodney W. Grimes else if (strlen(uf) >= MAXPATHLEN) { 16558f0484fSRodney W. Grimes _kvm_err(kd, kd->program, "exec file name too long"); 16658f0484fSRodney W. Grimes goto failed; 16758f0484fSRodney W. Grimes } 16858f0484fSRodney W. Grimes if (flag & ~O_RDWR) { 16958f0484fSRodney W. Grimes _kvm_err(kd, kd->program, "bad flags arg"); 17058f0484fSRodney W. Grimes goto failed; 17158f0484fSRodney W. Grimes } 17258f0484fSRodney W. Grimes if (mf == 0) 17358f0484fSRodney W. Grimes mf = _PATH_MEM; 17458f0484fSRodney W. Grimes 17558f0484fSRodney W. Grimes if ((kd->pmfd = open(mf, flag, 0)) < 0) { 17658f0484fSRodney W. Grimes _kvm_syserr(kd, kd->program, "%s", mf); 17758f0484fSRodney W. Grimes goto failed; 17858f0484fSRodney W. Grimes } 17958f0484fSRodney W. Grimes if (fstat(kd->pmfd, &st) < 0) { 18058f0484fSRodney W. Grimes _kvm_syserr(kd, kd->program, "%s", mf); 18158f0484fSRodney W. Grimes goto failed; 18258f0484fSRodney W. Grimes } 183f76b74d6SJacques Vidrine if (fcntl(kd->pmfd, F_SETFD, FD_CLOEXEC) < 0) { 184f76b74d6SJacques Vidrine _kvm_syserr(kd, kd->program, "%s", mf); 185f76b74d6SJacques Vidrine goto failed; 186f76b74d6SJacques Vidrine } 18758f0484fSRodney W. Grimes if (S_ISCHR(st.st_mode)) { 18858f0484fSRodney W. Grimes /* 18958f0484fSRodney W. Grimes * If this is a character special device, then check that 19058f0484fSRodney W. Grimes * it's /dev/mem. If so, open kmem too. (Maybe we should 19158f0484fSRodney W. Grimes * make it work for either /dev/mem or /dev/kmem -- in either 19258f0484fSRodney W. Grimes * case you're working with a live kernel.) 19358f0484fSRodney W. Grimes */ 19435e6b695SPoul-Henning Kamp if (strcmp(mf, _PATH_DEVNULL) == 0) { 19535e6b695SPoul-Henning Kamp kd->vmfd = open(_PATH_DEVNULL, O_RDONLY); 19635e6b695SPoul-Henning Kamp } else if (strcmp(mf, _PATH_MEM) != 0) { 19758f0484fSRodney W. Grimes _kvm_err(kd, kd->program, 19858f0484fSRodney W. Grimes "%s: not physical memory device", mf); 19958f0484fSRodney W. Grimes goto failed; 20035e6b695SPoul-Henning Kamp } else { 20158f0484fSRodney W. Grimes if ((kd->vmfd = open(_PATH_KMEM, flag)) < 0) { 20258f0484fSRodney W. Grimes _kvm_syserr(kd, kd->program, "%s", _PATH_KMEM); 20358f0484fSRodney W. Grimes goto failed; 20458f0484fSRodney W. Grimes } 205f76b74d6SJacques Vidrine if (fcntl(kd->vmfd, F_SETFD, FD_CLOEXEC) < 0) { 206f76b74d6SJacques Vidrine _kvm_syserr(kd, kd->program, "%s", _PATH_KMEM); 207f76b74d6SJacques Vidrine goto failed; 208f76b74d6SJacques Vidrine } 20935e6b695SPoul-Henning Kamp } 21058f0484fSRodney W. Grimes } else { 21158f0484fSRodney W. Grimes /* 21258f0484fSRodney W. Grimes * This is a crash dump. 21335e6b695SPoul-Henning Kamp * Initialize the virtual address translation machinery, 21458f0484fSRodney W. Grimes * but first setup the namelist fd. 21558f0484fSRodney W. Grimes */ 21658f0484fSRodney W. Grimes if ((kd->nlfd = open(uf, O_RDONLY, 0)) < 0) { 21758f0484fSRodney W. Grimes _kvm_syserr(kd, kd->program, "%s", uf); 21858f0484fSRodney W. Grimes goto failed; 21958f0484fSRodney W. Grimes } 220f76b74d6SJacques Vidrine if (fcntl(kd->nlfd, F_SETFD, FD_CLOEXEC) < 0) { 221f76b74d6SJacques Vidrine _kvm_syserr(kd, kd->program, "%s", uf); 222f76b74d6SJacques Vidrine goto failed; 223f76b74d6SJacques Vidrine } 22458f0484fSRodney W. Grimes if (_kvm_initvtop(kd) < 0) 22558f0484fSRodney W. Grimes goto failed; 22658f0484fSRodney W. Grimes } 22758f0484fSRodney W. Grimes return (kd); 22858f0484fSRodney W. Grimes failed: 22958f0484fSRodney W. Grimes /* 23058f0484fSRodney W. Grimes * Copy out the error if doing sane error semantics. 23158f0484fSRodney W. Grimes */ 23258f0484fSRodney W. Grimes if (errout != 0) 233ba3c0383SKris Kennaway strlcpy(errout, kd->errbuf, _POSIX2_LINE_MAX); 23458f0484fSRodney W. Grimes (void)kvm_close(kd); 23558f0484fSRodney W. Grimes return (0); 23658f0484fSRodney W. Grimes } 23758f0484fSRodney W. Grimes 23858f0484fSRodney W. Grimes kvm_t * 23958f0484fSRodney W. Grimes kvm_openfiles(uf, mf, sf, flag, errout) 24058f0484fSRodney W. Grimes const char *uf; 24158f0484fSRodney W. Grimes const char *mf; 242fe42e96eSRuslan Ermilov const char *sf __unused; 24358f0484fSRodney W. Grimes int flag; 24458f0484fSRodney W. Grimes char *errout; 24558f0484fSRodney W. Grimes { 246be04b6d1SDavid E. O'Brien kvm_t *kd; 24758f0484fSRodney W. Grimes 24858f0484fSRodney W. Grimes if ((kd = malloc(sizeof(*kd))) == NULL) { 249ba3c0383SKris Kennaway (void)strlcpy(errout, strerror(errno), _POSIX2_LINE_MAX); 25058f0484fSRodney W. Grimes return (0); 25158f0484fSRodney W. Grimes } 252a52219bbSPeter Wemm memset(kd, 0, sizeof(*kd)); 25358f0484fSRodney W. Grimes kd->program = 0; 2548771870cSPeter Wemm return (_kvm_open(kd, uf, mf, flag, errout)); 25558f0484fSRodney W. Grimes } 25658f0484fSRodney W. Grimes 25758f0484fSRodney W. Grimes kvm_t * 25812eaa3d5SPoul-Henning Kamp kvm_open(uf, mf, sf, flag, errstr) 25958f0484fSRodney W. Grimes const char *uf; 26058f0484fSRodney W. Grimes const char *mf; 261fe42e96eSRuslan Ermilov const char *sf __unused; 26258f0484fSRodney W. Grimes int flag; 26312eaa3d5SPoul-Henning Kamp const char *errstr; 26458f0484fSRodney W. Grimes { 265be04b6d1SDavid E. O'Brien kvm_t *kd; 26658f0484fSRodney W. Grimes 26712eaa3d5SPoul-Henning Kamp if ((kd = malloc(sizeof(*kd))) == NULL) { 26864f14011SBruce Evans if (errstr != NULL) 26912eaa3d5SPoul-Henning Kamp (void)fprintf(stderr, "%s: %s\n", 27064f14011SBruce Evans errstr, strerror(errno)); 27158f0484fSRodney W. Grimes return (0); 27258f0484fSRodney W. Grimes } 273a52219bbSPeter Wemm memset(kd, 0, sizeof(*kd)); 27412eaa3d5SPoul-Henning Kamp kd->program = errstr; 2758771870cSPeter Wemm return (_kvm_open(kd, uf, mf, flag, NULL)); 27658f0484fSRodney W. Grimes } 27758f0484fSRodney W. Grimes 27858f0484fSRodney W. Grimes int 27958f0484fSRodney W. Grimes kvm_close(kd) 28058f0484fSRodney W. Grimes kvm_t *kd; 28158f0484fSRodney W. Grimes { 282be04b6d1SDavid E. O'Brien int error = 0; 28358f0484fSRodney W. Grimes 28458f0484fSRodney W. Grimes if (kd->pmfd >= 0) 28558f0484fSRodney W. Grimes error |= close(kd->pmfd); 28658f0484fSRodney W. Grimes if (kd->vmfd >= 0) 28758f0484fSRodney W. Grimes error |= close(kd->vmfd); 28858f0484fSRodney W. Grimes if (kd->nlfd >= 0) 28958f0484fSRodney W. Grimes error |= close(kd->nlfd); 29058f0484fSRodney W. Grimes if (kd->vmst) 29158f0484fSRodney W. Grimes _kvm_freevtop(kd); 29258f0484fSRodney W. Grimes if (kd->procbase != 0) 29358f0484fSRodney W. Grimes free((void *)kd->procbase); 29458f0484fSRodney W. Grimes if (kd->argv != 0) 29558f0484fSRodney W. Grimes free((void *)kd->argv); 29658f0484fSRodney W. Grimes free((void *)kd); 29758f0484fSRodney W. Grimes 29858f0484fSRodney W. Grimes return (0); 29958f0484fSRodney W. Grimes } 30058f0484fSRodney W. Grimes 30158f0484fSRodney W. Grimes int 30258f0484fSRodney W. Grimes kvm_nlist(kd, nl) 30358f0484fSRodney W. Grimes kvm_t *kd; 30458f0484fSRodney W. Grimes struct nlist *nl; 30558f0484fSRodney W. Grimes { 306be04b6d1SDavid E. O'Brien struct nlist *p; 307be04b6d1SDavid E. O'Brien int nvalid; 308c4a7cdb3SPeter Wemm struct kld_sym_lookup lookup; 30958f0484fSRodney W. Grimes 31058f0484fSRodney W. Grimes /* 311c4a7cdb3SPeter Wemm * If we can't use the kld symbol lookup, revert to the 31258f0484fSRodney W. Grimes * slow library call. 31358f0484fSRodney W. Grimes */ 314c4a7cdb3SPeter Wemm if (!ISALIVE(kd)) 31558f0484fSRodney W. Grimes return (__fdnlist(kd->nlfd, nl)); 31658f0484fSRodney W. Grimes 31758f0484fSRodney W. Grimes /* 318c4a7cdb3SPeter Wemm * We can use the kld lookup syscall. Go through each nlist entry 319c4a7cdb3SPeter Wemm * and look it up with a kldsym(2) syscall. 32058f0484fSRodney W. Grimes */ 32158f0484fSRodney W. Grimes nvalid = 0; 32258f0484fSRodney W. Grimes for (p = nl; p->n_name && p->n_name[0]; ++p) { 323c4a7cdb3SPeter Wemm lookup.version = sizeof(lookup); 324c4a7cdb3SPeter Wemm lookup.symname = p->n_name; 325c4a7cdb3SPeter Wemm lookup.symvalue = 0; 326c4a7cdb3SPeter Wemm lookup.symsize = 0; 32758f0484fSRodney W. Grimes 328c4a7cdb3SPeter Wemm if (lookup.symname[0] == '_') 329c4a7cdb3SPeter Wemm lookup.symname++; 330c4a7cdb3SPeter Wemm 331c4a7cdb3SPeter Wemm if (kldsym(0, KLDSYM_LOOKUP, &lookup) != -1) { 332c4a7cdb3SPeter Wemm p->n_type = N_TEXT; 333c4a7cdb3SPeter Wemm p->n_other = 0; 334c4a7cdb3SPeter Wemm p->n_desc = 0; 335c4a7cdb3SPeter Wemm p->n_value = lookup.symvalue; 33658f0484fSRodney W. Grimes ++nvalid; 337c4a7cdb3SPeter Wemm /* lookup.symsize */ 338c4a7cdb3SPeter Wemm } 33958f0484fSRodney W. Grimes } 34058f0484fSRodney W. Grimes /* 34158f0484fSRodney W. Grimes * Return the number of entries that weren't found. 34258f0484fSRodney W. Grimes */ 34358f0484fSRodney W. Grimes return ((p - nl) - nvalid); 34458f0484fSRodney W. Grimes } 34558f0484fSRodney W. Grimes 34658f0484fSRodney W. Grimes ssize_t 34758f0484fSRodney W. Grimes kvm_read(kd, kva, buf, len) 34858f0484fSRodney W. Grimes kvm_t *kd; 349be04b6d1SDavid E. O'Brien u_long kva; 350be04b6d1SDavid E. O'Brien void *buf; 351be04b6d1SDavid E. O'Brien size_t len; 35258f0484fSRodney W. Grimes { 353be04b6d1SDavid E. O'Brien int cc; 354be04b6d1SDavid E. O'Brien void *cp; 35558f0484fSRodney W. Grimes 35658f0484fSRodney W. Grimes if (ISALIVE(kd)) { 35758f0484fSRodney W. Grimes /* 35858f0484fSRodney W. Grimes * We're using /dev/kmem. Just read straight from the 35958f0484fSRodney W. Grimes * device and let the active kernel do the address translation. 36058f0484fSRodney W. Grimes */ 36158f0484fSRodney W. Grimes errno = 0; 36258f0484fSRodney W. Grimes if (lseek(kd->vmfd, (off_t)kva, 0) == -1 && errno != 0) { 36358f0484fSRodney W. Grimes _kvm_err(kd, 0, "invalid address (%x)", kva); 36491a594d8SJacques Vidrine return (-1); 36558f0484fSRodney W. Grimes } 36658f0484fSRodney W. Grimes cc = read(kd->vmfd, buf, len); 36758f0484fSRodney W. Grimes if (cc < 0) { 36858f0484fSRodney W. Grimes _kvm_syserr(kd, 0, "kvm_read"); 36991a594d8SJacques Vidrine return (-1); 37058f0484fSRodney W. Grimes } else if (cc < len) 37158f0484fSRodney W. Grimes _kvm_err(kd, kd->program, "short read"); 37258f0484fSRodney W. Grimes return (cc); 37358f0484fSRodney W. Grimes } else { 37458f0484fSRodney W. Grimes cp = buf; 37558f0484fSRodney W. Grimes while (len > 0) { 37658f0484fSRodney W. Grimes u_long pa; 37758f0484fSRodney W. Grimes 37858f0484fSRodney W. Grimes cc = _kvm_kvatop(kd, kva, &pa); 37958f0484fSRodney W. Grimes if (cc == 0) 38091a594d8SJacques Vidrine return (-1); 38158f0484fSRodney W. Grimes if (cc > len) 38258f0484fSRodney W. Grimes cc = len; 38358f0484fSRodney W. Grimes errno = 0; 38458f0484fSRodney W. Grimes if (lseek(kd->pmfd, (off_t)pa, 0) == -1 && errno != 0) { 38558f0484fSRodney W. Grimes _kvm_syserr(kd, 0, _PATH_MEM); 38658f0484fSRodney W. Grimes break; 38758f0484fSRodney W. Grimes } 38858f0484fSRodney W. Grimes cc = read(kd->pmfd, cp, cc); 38958f0484fSRodney W. Grimes if (cc < 0) { 39058f0484fSRodney W. Grimes _kvm_syserr(kd, kd->program, "kvm_read"); 39158f0484fSRodney W. Grimes break; 39258f0484fSRodney W. Grimes } 39358f0484fSRodney W. Grimes /* 39458f0484fSRodney W. Grimes * If kvm_kvatop returns a bogus value or our core 39558f0484fSRodney W. Grimes * file is truncated, we might wind up seeking beyond 39658f0484fSRodney W. Grimes * the end of the core file in which case the read will 39758f0484fSRodney W. Grimes * return 0 (EOF). 39858f0484fSRodney W. Grimes */ 39958f0484fSRodney W. Grimes if (cc == 0) 40058f0484fSRodney W. Grimes break; 40158f0484fSRodney W. Grimes (char *)cp += cc; 40258f0484fSRodney W. Grimes kva += cc; 40358f0484fSRodney W. Grimes len -= cc; 40458f0484fSRodney W. Grimes } 40558f0484fSRodney W. Grimes return ((char *)cp - (char *)buf); 40658f0484fSRodney W. Grimes } 40758f0484fSRodney W. Grimes /* NOTREACHED */ 40858f0484fSRodney W. Grimes } 40958f0484fSRodney W. Grimes 41058f0484fSRodney W. Grimes ssize_t 41158f0484fSRodney W. Grimes kvm_write(kd, kva, buf, len) 41258f0484fSRodney W. Grimes kvm_t *kd; 413be04b6d1SDavid E. O'Brien u_long kva; 414be04b6d1SDavid E. O'Brien const void *buf; 415be04b6d1SDavid E. O'Brien size_t len; 41658f0484fSRodney W. Grimes { 417be04b6d1SDavid E. O'Brien int cc; 41858f0484fSRodney W. Grimes 41958f0484fSRodney W. Grimes if (ISALIVE(kd)) { 42058f0484fSRodney W. Grimes /* 42158f0484fSRodney W. Grimes * Just like kvm_read, only we write. 42258f0484fSRodney W. Grimes */ 42358f0484fSRodney W. Grimes errno = 0; 42458f0484fSRodney W. Grimes if (lseek(kd->vmfd, (off_t)kva, 0) == -1 && errno != 0) { 42558f0484fSRodney W. Grimes _kvm_err(kd, 0, "invalid address (%x)", kva); 42691a594d8SJacques Vidrine return (-1); 42758f0484fSRodney W. Grimes } 42858f0484fSRodney W. Grimes cc = write(kd->vmfd, buf, len); 42958f0484fSRodney W. Grimes if (cc < 0) { 43058f0484fSRodney W. Grimes _kvm_syserr(kd, 0, "kvm_write"); 43191a594d8SJacques Vidrine return (-1); 43258f0484fSRodney W. Grimes } else if (cc < len) 43358f0484fSRodney W. Grimes _kvm_err(kd, kd->program, "short write"); 43458f0484fSRodney W. Grimes return (cc); 43558f0484fSRodney W. Grimes } else { 43658f0484fSRodney W. Grimes _kvm_err(kd, kd->program, 43758f0484fSRodney W. Grimes "kvm_write not implemented for dead kernels"); 43891a594d8SJacques Vidrine return (-1); 43958f0484fSRodney W. Grimes } 44058f0484fSRodney W. Grimes /* NOTREACHED */ 44158f0484fSRodney W. Grimes } 442