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 5858f0484fSRodney W. Grimes #include <machine/vmparam.h> 5958f0484fSRodney W. Grimes 6058f0484fSRodney W. Grimes #include <ctype.h> 6158f0484fSRodney W. Grimes #include <fcntl.h> 6258f0484fSRodney W. Grimes #include <kvm.h> 6358f0484fSRodney W. Grimes #include <limits.h> 6458f0484fSRodney W. Grimes #include <nlist.h> 6558f0484fSRodney W. Grimes #include <paths.h> 6658f0484fSRodney W. Grimes #include <stdio.h> 6758f0484fSRodney W. Grimes #include <stdlib.h> 6858f0484fSRodney W. Grimes #include <string.h> 6958f0484fSRodney W. Grimes #include <unistd.h> 7058f0484fSRodney W. Grimes 7158f0484fSRodney W. Grimes #include "kvm_private.h" 7258f0484fSRodney W. Grimes 73b7875890SDavid E. O'Brien /* from src/lib/libc/gen/nlist.c */ 7469160b1eSDavid E. O'Brien int __fdnlist(int, struct nlist *); 75b7875890SDavid E. O'Brien 7658f0484fSRodney W. Grimes char * 7758f0484fSRodney W. Grimes kvm_geterr(kd) 7858f0484fSRodney W. Grimes kvm_t *kd; 7958f0484fSRodney W. Grimes { 8058f0484fSRodney W. Grimes return (kd->errbuf); 8158f0484fSRodney W. Grimes } 8258f0484fSRodney W. Grimes 8358f0484fSRodney W. Grimes #include <stdarg.h> 8458f0484fSRodney W. Grimes 8558f0484fSRodney W. Grimes /* 8658f0484fSRodney W. Grimes * Report an error using printf style arguments. "program" is kd->program 8758f0484fSRodney W. Grimes * on hard errors, and 0 on soft errors, so that under sun error emulation, 8858f0484fSRodney W. Grimes * only hard errors are printed out (otherwise, programs like gdb will 8958f0484fSRodney W. Grimes * generate tons of error messages when trying to access bogus pointers). 9058f0484fSRodney W. Grimes */ 9158f0484fSRodney W. Grimes void 9258f0484fSRodney W. Grimes _kvm_err(kvm_t *kd, const char *program, const char *fmt, ...) 9358f0484fSRodney W. Grimes { 9458f0484fSRodney W. Grimes va_list ap; 9558f0484fSRodney W. Grimes 9658f0484fSRodney W. Grimes va_start(ap, fmt); 9758f0484fSRodney W. Grimes if (program != NULL) { 9858f0484fSRodney W. Grimes (void)fprintf(stderr, "%s: ", program); 9958f0484fSRodney W. Grimes (void)vfprintf(stderr, fmt, ap); 10058f0484fSRodney W. Grimes (void)fputc('\n', stderr); 10158f0484fSRodney W. Grimes } else 10258f0484fSRodney W. Grimes (void)vsnprintf(kd->errbuf, 10358f0484fSRodney W. Grimes sizeof(kd->errbuf), (char *)fmt, ap); 10458f0484fSRodney W. Grimes 10558f0484fSRodney W. Grimes va_end(ap); 10658f0484fSRodney W. Grimes } 10758f0484fSRodney W. Grimes 10858f0484fSRodney W. Grimes void 10958f0484fSRodney W. Grimes _kvm_syserr(kvm_t *kd, const char *program, const char *fmt, ...) 11058f0484fSRodney W. Grimes { 11158f0484fSRodney W. Grimes va_list ap; 112be04b6d1SDavid E. O'Brien int n; 11358f0484fSRodney W. Grimes 11458f0484fSRodney W. Grimes va_start(ap, fmt); 11558f0484fSRodney W. Grimes if (program != NULL) { 11658f0484fSRodney W. Grimes (void)fprintf(stderr, "%s: ", program); 11758f0484fSRodney W. Grimes (void)vfprintf(stderr, fmt, ap); 11858f0484fSRodney W. Grimes (void)fprintf(stderr, ": %s\n", strerror(errno)); 11958f0484fSRodney W. Grimes } else { 120be04b6d1SDavid E. O'Brien char *cp = kd->errbuf; 12158f0484fSRodney W. Grimes 12258f0484fSRodney W. Grimes (void)vsnprintf(cp, sizeof(kd->errbuf), (char *)fmt, ap); 12358f0484fSRodney W. Grimes n = strlen(cp); 12458f0484fSRodney W. Grimes (void)snprintf(&cp[n], sizeof(kd->errbuf) - n, ": %s", 12558f0484fSRodney W. Grimes strerror(errno)); 12658f0484fSRodney W. Grimes } 12758f0484fSRodney W. Grimes va_end(ap); 12858f0484fSRodney W. Grimes } 12958f0484fSRodney W. Grimes 13058f0484fSRodney W. Grimes void * 13158f0484fSRodney W. Grimes _kvm_malloc(kd, n) 132be04b6d1SDavid E. O'Brien kvm_t *kd; 133be04b6d1SDavid E. O'Brien size_t n; 13458f0484fSRodney W. Grimes { 13558f0484fSRodney W. Grimes void *p; 13658f0484fSRodney W. Grimes 137d7b100f9SAndrey A. Chernov if ((p = calloc(n, sizeof(char))) == NULL) 138d7b100f9SAndrey A. Chernov _kvm_err(kd, kd->program, "can't allocate %u bytes: %s", 139d7b100f9SAndrey A. Chernov n, strerror(errno)); 14058f0484fSRodney W. Grimes return (p); 14158f0484fSRodney W. Grimes } 14258f0484fSRodney W. Grimes 14358f0484fSRodney W. Grimes static kvm_t * 1448771870cSPeter Wemm _kvm_open(kd, uf, mf, flag, errout) 145be04b6d1SDavid E. O'Brien kvm_t *kd; 14658f0484fSRodney W. Grimes const char *uf; 14758f0484fSRodney W. Grimes const char *mf; 14858f0484fSRodney W. Grimes int flag; 14958f0484fSRodney W. Grimes char *errout; 15058f0484fSRodney W. Grimes { 15158f0484fSRodney W. Grimes struct stat st; 15258f0484fSRodney W. Grimes 15358f0484fSRodney W. Grimes kd->vmfd = -1; 15458f0484fSRodney W. Grimes kd->pmfd = -1; 15558f0484fSRodney W. Grimes kd->nlfd = -1; 15658f0484fSRodney W. Grimes kd->vmst = 0; 15758f0484fSRodney W. Grimes kd->procbase = 0; 15858f0484fSRodney W. Grimes kd->argspc = 0; 15958f0484fSRodney W. Grimes kd->argv = 0; 16058f0484fSRodney W. Grimes 16158f0484fSRodney W. Grimes if (uf == 0) 1624be4929cSGarrett Wollman uf = getbootfile(); 16358f0484fSRodney W. Grimes else if (strlen(uf) >= MAXPATHLEN) { 16458f0484fSRodney W. Grimes _kvm_err(kd, kd->program, "exec file name too long"); 16558f0484fSRodney W. Grimes goto failed; 16658f0484fSRodney W. Grimes } 16758f0484fSRodney W. Grimes if (flag & ~O_RDWR) { 16858f0484fSRodney W. Grimes _kvm_err(kd, kd->program, "bad flags arg"); 16958f0484fSRodney W. Grimes goto failed; 17058f0484fSRodney W. Grimes } 17158f0484fSRodney W. Grimes if (mf == 0) 17258f0484fSRodney W. Grimes mf = _PATH_MEM; 17358f0484fSRodney W. Grimes 17458f0484fSRodney W. Grimes if ((kd->pmfd = open(mf, flag, 0)) < 0) { 17558f0484fSRodney W. Grimes _kvm_syserr(kd, kd->program, "%s", mf); 17658f0484fSRodney W. Grimes goto failed; 17758f0484fSRodney W. Grimes } 17858f0484fSRodney W. Grimes if (fstat(kd->pmfd, &st) < 0) { 17958f0484fSRodney W. Grimes _kvm_syserr(kd, kd->program, "%s", mf); 18058f0484fSRodney W. Grimes goto failed; 18158f0484fSRodney W. Grimes } 182f76b74d6SJacques Vidrine if (fcntl(kd->pmfd, F_SETFD, FD_CLOEXEC) < 0) { 183f76b74d6SJacques Vidrine _kvm_syserr(kd, kd->program, "%s", mf); 184f76b74d6SJacques Vidrine goto failed; 185f76b74d6SJacques Vidrine } 18658f0484fSRodney W. Grimes if (S_ISCHR(st.st_mode)) { 18758f0484fSRodney W. Grimes /* 18858f0484fSRodney W. Grimes * If this is a character special device, then check that 18958f0484fSRodney W. Grimes * it's /dev/mem. If so, open kmem too. (Maybe we should 19058f0484fSRodney W. Grimes * make it work for either /dev/mem or /dev/kmem -- in either 19158f0484fSRodney W. Grimes * case you're working with a live kernel.) 19258f0484fSRodney W. Grimes */ 19335e6b695SPoul-Henning Kamp if (strcmp(mf, _PATH_DEVNULL) == 0) { 19435e6b695SPoul-Henning Kamp kd->vmfd = open(_PATH_DEVNULL, O_RDONLY); 1957928124aSHidetoshi Shimokawa return (kd); 1967928124aSHidetoshi Shimokawa } else if (strcmp(mf, _PATH_MEM) == 0) { 19758f0484fSRodney W. Grimes if ((kd->vmfd = open(_PATH_KMEM, flag)) < 0) { 19858f0484fSRodney W. Grimes _kvm_syserr(kd, kd->program, "%s", _PATH_KMEM); 19958f0484fSRodney W. Grimes goto failed; 20058f0484fSRodney W. Grimes } 201f76b74d6SJacques Vidrine if (fcntl(kd->vmfd, F_SETFD, FD_CLOEXEC) < 0) { 202f76b74d6SJacques Vidrine _kvm_syserr(kd, kd->program, "%s", _PATH_KMEM); 203f76b74d6SJacques Vidrine goto failed; 204f76b74d6SJacques Vidrine } 2057928124aSHidetoshi Shimokawa return (kd); 20635e6b695SPoul-Henning Kamp } 2077928124aSHidetoshi Shimokawa } 20858f0484fSRodney W. Grimes /* 20958f0484fSRodney W. Grimes * This is a crash dump. 21035e6b695SPoul-Henning Kamp * Initialize the virtual address translation machinery, 21158f0484fSRodney W. Grimes * but first setup the namelist fd. 21258f0484fSRodney W. Grimes */ 21358f0484fSRodney W. Grimes if ((kd->nlfd = open(uf, O_RDONLY, 0)) < 0) { 21458f0484fSRodney W. Grimes _kvm_syserr(kd, kd->program, "%s", uf); 21558f0484fSRodney W. Grimes goto failed; 21658f0484fSRodney W. Grimes } 217f76b74d6SJacques Vidrine if (fcntl(kd->nlfd, F_SETFD, FD_CLOEXEC) < 0) { 218f76b74d6SJacques Vidrine _kvm_syserr(kd, kd->program, "%s", uf); 219f76b74d6SJacques Vidrine goto failed; 220f76b74d6SJacques Vidrine } 22158f0484fSRodney W. Grimes if (_kvm_initvtop(kd) < 0) 22258f0484fSRodney W. Grimes goto failed; 22358f0484fSRodney W. Grimes return (kd); 22458f0484fSRodney W. Grimes failed: 22558f0484fSRodney W. Grimes /* 22658f0484fSRodney W. Grimes * Copy out the error if doing sane error semantics. 22758f0484fSRodney W. Grimes */ 22858f0484fSRodney W. Grimes if (errout != 0) 229ba3c0383SKris Kennaway strlcpy(errout, kd->errbuf, _POSIX2_LINE_MAX); 23058f0484fSRodney W. Grimes (void)kvm_close(kd); 23158f0484fSRodney W. Grimes return (0); 23258f0484fSRodney W. Grimes } 23358f0484fSRodney W. Grimes 23458f0484fSRodney W. Grimes kvm_t * 23558f0484fSRodney W. Grimes kvm_openfiles(uf, mf, sf, flag, errout) 23658f0484fSRodney W. Grimes const char *uf; 23758f0484fSRodney W. Grimes const char *mf; 238fe42e96eSRuslan Ermilov const char *sf __unused; 23958f0484fSRodney W. Grimes int flag; 24058f0484fSRodney W. Grimes char *errout; 24158f0484fSRodney W. Grimes { 242be04b6d1SDavid E. O'Brien kvm_t *kd; 24358f0484fSRodney W. Grimes 24458f0484fSRodney W. Grimes if ((kd = malloc(sizeof(*kd))) == NULL) { 245ba3c0383SKris Kennaway (void)strlcpy(errout, strerror(errno), _POSIX2_LINE_MAX); 24658f0484fSRodney W. Grimes return (0); 24758f0484fSRodney W. Grimes } 248a52219bbSPeter Wemm memset(kd, 0, sizeof(*kd)); 24958f0484fSRodney W. Grimes kd->program = 0; 2508771870cSPeter Wemm return (_kvm_open(kd, uf, mf, flag, errout)); 25158f0484fSRodney W. Grimes } 25258f0484fSRodney W. Grimes 25358f0484fSRodney W. Grimes kvm_t * 25412eaa3d5SPoul-Henning Kamp kvm_open(uf, mf, sf, flag, errstr) 25558f0484fSRodney W. Grimes const char *uf; 25658f0484fSRodney W. Grimes const char *mf; 257fe42e96eSRuslan Ermilov const char *sf __unused; 25858f0484fSRodney W. Grimes int flag; 25912eaa3d5SPoul-Henning Kamp const char *errstr; 26058f0484fSRodney W. Grimes { 261be04b6d1SDavid E. O'Brien kvm_t *kd; 26258f0484fSRodney W. Grimes 26312eaa3d5SPoul-Henning Kamp if ((kd = malloc(sizeof(*kd))) == NULL) { 26464f14011SBruce Evans if (errstr != NULL) 26512eaa3d5SPoul-Henning Kamp (void)fprintf(stderr, "%s: %s\n", 26664f14011SBruce Evans errstr, strerror(errno)); 26758f0484fSRodney W. Grimes return (0); 26858f0484fSRodney W. Grimes } 269a52219bbSPeter Wemm memset(kd, 0, sizeof(*kd)); 27012eaa3d5SPoul-Henning Kamp kd->program = errstr; 2718771870cSPeter Wemm return (_kvm_open(kd, uf, mf, flag, NULL)); 27258f0484fSRodney W. Grimes } 27358f0484fSRodney W. Grimes 27458f0484fSRodney W. Grimes int 27558f0484fSRodney W. Grimes kvm_close(kd) 27658f0484fSRodney W. Grimes kvm_t *kd; 27758f0484fSRodney W. Grimes { 278be04b6d1SDavid E. O'Brien int error = 0; 27958f0484fSRodney W. Grimes 28058f0484fSRodney W. Grimes if (kd->pmfd >= 0) 28158f0484fSRodney W. Grimes error |= close(kd->pmfd); 28258f0484fSRodney W. Grimes if (kd->vmfd >= 0) 28358f0484fSRodney W. Grimes error |= close(kd->vmfd); 28458f0484fSRodney W. Grimes if (kd->nlfd >= 0) 28558f0484fSRodney W. Grimes error |= close(kd->nlfd); 28658f0484fSRodney W. Grimes if (kd->vmst) 28758f0484fSRodney W. Grimes _kvm_freevtop(kd); 28858f0484fSRodney W. Grimes if (kd->procbase != 0) 28958f0484fSRodney W. Grimes free((void *)kd->procbase); 29058f0484fSRodney W. Grimes if (kd->argv != 0) 29158f0484fSRodney W. Grimes free((void *)kd->argv); 29258f0484fSRodney W. Grimes free((void *)kd); 29358f0484fSRodney W. Grimes 29458f0484fSRodney W. Grimes return (0); 29558f0484fSRodney W. Grimes } 29658f0484fSRodney W. Grimes 29758f0484fSRodney W. Grimes int 29858f0484fSRodney W. Grimes kvm_nlist(kd, nl) 29958f0484fSRodney W. Grimes kvm_t *kd; 30058f0484fSRodney W. Grimes struct nlist *nl; 30158f0484fSRodney W. Grimes { 302be04b6d1SDavid E. O'Brien struct nlist *p; 303be04b6d1SDavid E. O'Brien int nvalid; 304c4a7cdb3SPeter Wemm struct kld_sym_lookup lookup; 30558f0484fSRodney W. Grimes 30658f0484fSRodney W. Grimes /* 307c4a7cdb3SPeter Wemm * If we can't use the kld symbol lookup, revert to the 30858f0484fSRodney W. Grimes * slow library call. 30958f0484fSRodney W. Grimes */ 310c4a7cdb3SPeter Wemm if (!ISALIVE(kd)) 31158f0484fSRodney W. Grimes return (__fdnlist(kd->nlfd, nl)); 31258f0484fSRodney W. Grimes 31358f0484fSRodney W. Grimes /* 314c4a7cdb3SPeter Wemm * We can use the kld lookup syscall. Go through each nlist entry 315c4a7cdb3SPeter Wemm * and look it up with a kldsym(2) syscall. 31658f0484fSRodney W. Grimes */ 31758f0484fSRodney W. Grimes nvalid = 0; 31858f0484fSRodney W. Grimes for (p = nl; p->n_name && p->n_name[0]; ++p) { 319c4a7cdb3SPeter Wemm lookup.version = sizeof(lookup); 320c4a7cdb3SPeter Wemm lookup.symname = p->n_name; 321c4a7cdb3SPeter Wemm lookup.symvalue = 0; 322c4a7cdb3SPeter Wemm lookup.symsize = 0; 32358f0484fSRodney W. Grimes 324c4a7cdb3SPeter Wemm if (lookup.symname[0] == '_') 325c4a7cdb3SPeter Wemm lookup.symname++; 326c4a7cdb3SPeter Wemm 327c4a7cdb3SPeter Wemm if (kldsym(0, KLDSYM_LOOKUP, &lookup) != -1) { 328c4a7cdb3SPeter Wemm p->n_type = N_TEXT; 329c4a7cdb3SPeter Wemm p->n_other = 0; 330c4a7cdb3SPeter Wemm p->n_desc = 0; 331c4a7cdb3SPeter Wemm p->n_value = lookup.symvalue; 33258f0484fSRodney W. Grimes ++nvalid; 333c4a7cdb3SPeter Wemm /* lookup.symsize */ 334c4a7cdb3SPeter Wemm } 33558f0484fSRodney W. Grimes } 33658f0484fSRodney W. Grimes /* 33758f0484fSRodney W. Grimes * Return the number of entries that weren't found. 33858f0484fSRodney W. Grimes */ 33958f0484fSRodney W. Grimes return ((p - nl) - nvalid); 34058f0484fSRodney W. Grimes } 34158f0484fSRodney W. Grimes 34258f0484fSRodney W. Grimes ssize_t 34358f0484fSRodney W. Grimes kvm_read(kd, kva, buf, len) 34458f0484fSRodney W. Grimes kvm_t *kd; 345be04b6d1SDavid E. O'Brien u_long kva; 346be04b6d1SDavid E. O'Brien void *buf; 347be04b6d1SDavid E. O'Brien size_t len; 34858f0484fSRodney W. Grimes { 349be04b6d1SDavid E. O'Brien int cc; 3501a5ff928SStefan Farfeleder char *cp; 35158f0484fSRodney W. Grimes 35258f0484fSRodney W. Grimes if (ISALIVE(kd)) { 35358f0484fSRodney W. Grimes /* 35458f0484fSRodney W. Grimes * We're using /dev/kmem. Just read straight from the 35558f0484fSRodney W. Grimes * device and let the active kernel do the address translation. 35658f0484fSRodney W. Grimes */ 35758f0484fSRodney W. Grimes errno = 0; 35858f0484fSRodney W. Grimes if (lseek(kd->vmfd, (off_t)kva, 0) == -1 && errno != 0) { 35958f0484fSRodney W. Grimes _kvm_err(kd, 0, "invalid address (%x)", kva); 36091a594d8SJacques Vidrine return (-1); 36158f0484fSRodney W. Grimes } 36258f0484fSRodney W. Grimes cc = read(kd->vmfd, buf, len); 36358f0484fSRodney W. Grimes if (cc < 0) { 36458f0484fSRodney W. Grimes _kvm_syserr(kd, 0, "kvm_read"); 36591a594d8SJacques Vidrine return (-1); 36658f0484fSRodney W. Grimes } else if (cc < len) 36758f0484fSRodney W. Grimes _kvm_err(kd, kd->program, "short read"); 36858f0484fSRodney W. Grimes return (cc); 36958f0484fSRodney W. Grimes } else { 37058f0484fSRodney W. Grimes cp = buf; 37158f0484fSRodney W. Grimes while (len > 0) { 372e55a0cd8SPeter Wemm off_t pa; 37358f0484fSRodney W. Grimes 37458f0484fSRodney W. Grimes cc = _kvm_kvatop(kd, kva, &pa); 37558f0484fSRodney W. Grimes if (cc == 0) 37691a594d8SJacques Vidrine return (-1); 37758f0484fSRodney W. Grimes if (cc > len) 37858f0484fSRodney W. Grimes cc = len; 37958f0484fSRodney W. Grimes errno = 0; 380e55a0cd8SPeter Wemm if (lseek(kd->pmfd, pa, 0) == -1 && errno != 0) { 38158f0484fSRodney W. Grimes _kvm_syserr(kd, 0, _PATH_MEM); 38258f0484fSRodney W. Grimes break; 38358f0484fSRodney W. Grimes } 38458f0484fSRodney W. Grimes cc = read(kd->pmfd, cp, cc); 38558f0484fSRodney W. Grimes if (cc < 0) { 38658f0484fSRodney W. Grimes _kvm_syserr(kd, kd->program, "kvm_read"); 38758f0484fSRodney W. Grimes break; 38858f0484fSRodney W. Grimes } 38958f0484fSRodney W. Grimes /* 39058f0484fSRodney W. Grimes * If kvm_kvatop returns a bogus value or our core 39158f0484fSRodney W. Grimes * file is truncated, we might wind up seeking beyond 39258f0484fSRodney W. Grimes * the end of the core file in which case the read will 39358f0484fSRodney W. Grimes * return 0 (EOF). 39458f0484fSRodney W. Grimes */ 39558f0484fSRodney W. Grimes if (cc == 0) 39658f0484fSRodney W. Grimes break; 3971a5ff928SStefan Farfeleder cp += cc; 39858f0484fSRodney W. Grimes kva += cc; 39958f0484fSRodney W. Grimes len -= cc; 40058f0484fSRodney W. Grimes } 4011a5ff928SStefan Farfeleder return (cp - (char *)buf); 40258f0484fSRodney W. Grimes } 40358f0484fSRodney W. Grimes /* NOTREACHED */ 40458f0484fSRodney W. Grimes } 40558f0484fSRodney W. Grimes 40658f0484fSRodney W. Grimes ssize_t 40758f0484fSRodney W. Grimes kvm_write(kd, kva, buf, len) 40858f0484fSRodney W. Grimes kvm_t *kd; 409be04b6d1SDavid E. O'Brien u_long kva; 410be04b6d1SDavid E. O'Brien const void *buf; 411be04b6d1SDavid E. O'Brien size_t len; 41258f0484fSRodney W. Grimes { 413be04b6d1SDavid E. O'Brien int cc; 41458f0484fSRodney W. Grimes 41558f0484fSRodney W. Grimes if (ISALIVE(kd)) { 41658f0484fSRodney W. Grimes /* 41758f0484fSRodney W. Grimes * Just like kvm_read, only we write. 41858f0484fSRodney W. Grimes */ 41958f0484fSRodney W. Grimes errno = 0; 42058f0484fSRodney W. Grimes if (lseek(kd->vmfd, (off_t)kva, 0) == -1 && errno != 0) { 42158f0484fSRodney W. Grimes _kvm_err(kd, 0, "invalid address (%x)", kva); 42291a594d8SJacques Vidrine return (-1); 42358f0484fSRodney W. Grimes } 42458f0484fSRodney W. Grimes cc = write(kd->vmfd, buf, len); 42558f0484fSRodney W. Grimes if (cc < 0) { 42658f0484fSRodney W. Grimes _kvm_syserr(kd, 0, "kvm_write"); 42791a594d8SJacques Vidrine return (-1); 42858f0484fSRodney W. Grimes } else if (cc < len) 42958f0484fSRodney W. Grimes _kvm_err(kd, kd->program, "short write"); 43058f0484fSRodney W. Grimes return (cc); 43158f0484fSRodney W. Grimes } else { 43258f0484fSRodney W. Grimes _kvm_err(kd, kd->program, 43358f0484fSRodney W. Grimes "kvm_write not implemented for dead kernels"); 43491a594d8SJacques Vidrine return (-1); 43558f0484fSRodney W. Grimes } 43658f0484fSRodney W. Grimes /* NOTREACHED */ 43758f0484fSRodney W. Grimes } 438