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 * 4. Neither the name of the University nor the names of its contributors 1858f0484fSRodney W. Grimes * may be used to endorse or promote products derived from this software 1958f0484fSRodney W. Grimes * without specific prior written permission. 2058f0484fSRodney W. Grimes * 2158f0484fSRodney W. Grimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 2258f0484fSRodney W. Grimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 2358f0484fSRodney W. Grimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2458f0484fSRodney W. Grimes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 2558f0484fSRodney W. Grimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2658f0484fSRodney W. Grimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2758f0484fSRodney W. Grimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2858f0484fSRodney W. Grimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2958f0484fSRodney W. Grimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 3058f0484fSRodney W. Grimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 3158f0484fSRodney W. Grimes * SUCH DAMAGE. 3258f0484fSRodney W. Grimes */ 3358f0484fSRodney W. Grimes 34e67f5b9fSMatthew Dillon #include <sys/cdefs.h> 35e67f5b9fSMatthew Dillon __FBSDID("$FreeBSD$"); 36e67f5b9fSMatthew Dillon 3758f0484fSRodney W. Grimes #if defined(LIBC_SCCS) && !defined(lint) 388771870cSPeter Wemm #if 0 3958f0484fSRodney W. Grimes static char sccsid[] = "@(#)kvm.c 8.2 (Berkeley) 2/13/94"; 408771870cSPeter Wemm #endif 4158f0484fSRodney W. Grimes #endif /* LIBC_SCCS and not lint */ 4258f0484fSRodney W. Grimes 4358f0484fSRodney W. Grimes #include <sys/param.h> 4458f0484fSRodney W. Grimes #include <sys/user.h> 4558f0484fSRodney W. Grimes #include <sys/proc.h> 4658f0484fSRodney W. Grimes #include <sys/ioctl.h> 4758f0484fSRodney W. Grimes #include <sys/stat.h> 4858f0484fSRodney W. Grimes #include <sys/sysctl.h> 49c4a7cdb3SPeter Wemm #include <sys/linker.h> 5058f0484fSRodney W. Grimes 5158f0484fSRodney W. Grimes #include <vm/vm.h> 5258f0484fSRodney W. Grimes #include <vm/vm_param.h> 5358f0484fSRodney W. Grimes 5458f0484fSRodney W. Grimes #include <machine/vmparam.h> 5558f0484fSRodney W. Grimes 5658f0484fSRodney W. Grimes #include <ctype.h> 5758f0484fSRodney W. Grimes #include <fcntl.h> 5858f0484fSRodney W. Grimes #include <kvm.h> 5958f0484fSRodney W. Grimes #include <limits.h> 6058f0484fSRodney W. Grimes #include <nlist.h> 6158f0484fSRodney W. Grimes #include <paths.h> 6258f0484fSRodney W. Grimes #include <stdio.h> 6358f0484fSRodney W. Grimes #include <stdlib.h> 6458f0484fSRodney W. Grimes #include <string.h> 6558f0484fSRodney W. Grimes #include <unistd.h> 6658f0484fSRodney W. Grimes 6758f0484fSRodney W. Grimes #include "kvm_private.h" 6858f0484fSRodney W. Grimes 69b7875890SDavid E. O'Brien /* from src/lib/libc/gen/nlist.c */ 7069160b1eSDavid E. O'Brien int __fdnlist(int, struct nlist *); 71b7875890SDavid E. O'Brien 7258f0484fSRodney W. Grimes char * 7358f0484fSRodney W. Grimes kvm_geterr(kd) 7458f0484fSRodney W. Grimes kvm_t *kd; 7558f0484fSRodney W. Grimes { 7658f0484fSRodney W. Grimes return (kd->errbuf); 7758f0484fSRodney W. Grimes } 7858f0484fSRodney W. Grimes 7958f0484fSRodney W. Grimes #include <stdarg.h> 8058f0484fSRodney W. Grimes 8158f0484fSRodney W. Grimes /* 8258f0484fSRodney W. Grimes * Report an error using printf style arguments. "program" is kd->program 8358f0484fSRodney W. Grimes * on hard errors, and 0 on soft errors, so that under sun error emulation, 8458f0484fSRodney W. Grimes * only hard errors are printed out (otherwise, programs like gdb will 8558f0484fSRodney W. Grimes * generate tons of error messages when trying to access bogus pointers). 8658f0484fSRodney W. Grimes */ 8758f0484fSRodney W. Grimes void 8858f0484fSRodney W. Grimes _kvm_err(kvm_t *kd, const char *program, const char *fmt, ...) 8958f0484fSRodney W. Grimes { 9058f0484fSRodney W. Grimes va_list ap; 9158f0484fSRodney W. Grimes 9258f0484fSRodney W. Grimes va_start(ap, fmt); 9358f0484fSRodney W. Grimes if (program != NULL) { 9458f0484fSRodney W. Grimes (void)fprintf(stderr, "%s: ", program); 9558f0484fSRodney W. Grimes (void)vfprintf(stderr, fmt, ap); 9658f0484fSRodney W. Grimes (void)fputc('\n', stderr); 9758f0484fSRodney W. Grimes } else 9858f0484fSRodney W. Grimes (void)vsnprintf(kd->errbuf, 9958f0484fSRodney W. Grimes sizeof(kd->errbuf), (char *)fmt, ap); 10058f0484fSRodney W. Grimes 10158f0484fSRodney W. Grimes va_end(ap); 10258f0484fSRodney W. Grimes } 10358f0484fSRodney W. Grimes 10458f0484fSRodney W. Grimes void 10558f0484fSRodney W. Grimes _kvm_syserr(kvm_t *kd, const char *program, const char *fmt, ...) 10658f0484fSRodney W. Grimes { 10758f0484fSRodney W. Grimes va_list ap; 108be04b6d1SDavid E. O'Brien int n; 10958f0484fSRodney W. Grimes 11058f0484fSRodney W. Grimes va_start(ap, fmt); 11158f0484fSRodney W. Grimes if (program != NULL) { 11258f0484fSRodney W. Grimes (void)fprintf(stderr, "%s: ", program); 11358f0484fSRodney W. Grimes (void)vfprintf(stderr, fmt, ap); 11458f0484fSRodney W. Grimes (void)fprintf(stderr, ": %s\n", strerror(errno)); 11558f0484fSRodney W. Grimes } else { 116be04b6d1SDavid E. O'Brien char *cp = kd->errbuf; 11758f0484fSRodney W. Grimes 11858f0484fSRodney W. Grimes (void)vsnprintf(cp, sizeof(kd->errbuf), (char *)fmt, ap); 11958f0484fSRodney W. Grimes n = strlen(cp); 12058f0484fSRodney W. Grimes (void)snprintf(&cp[n], sizeof(kd->errbuf) - n, ": %s", 12158f0484fSRodney W. Grimes strerror(errno)); 12258f0484fSRodney W. Grimes } 12358f0484fSRodney W. Grimes va_end(ap); 12458f0484fSRodney W. Grimes } 12558f0484fSRodney W. Grimes 12658f0484fSRodney W. Grimes void * 12758f0484fSRodney W. Grimes _kvm_malloc(kd, n) 128be04b6d1SDavid E. O'Brien kvm_t *kd; 129be04b6d1SDavid E. O'Brien size_t n; 13058f0484fSRodney W. Grimes { 13158f0484fSRodney W. Grimes void *p; 13258f0484fSRodney W. Grimes 133d7b100f9SAndrey A. Chernov if ((p = calloc(n, sizeof(char))) == NULL) 134d7b100f9SAndrey A. Chernov _kvm_err(kd, kd->program, "can't allocate %u bytes: %s", 135d7b100f9SAndrey A. Chernov n, strerror(errno)); 13658f0484fSRodney W. Grimes return (p); 13758f0484fSRodney W. Grimes } 13858f0484fSRodney W. Grimes 13958f0484fSRodney W. Grimes static kvm_t * 1408771870cSPeter Wemm _kvm_open(kd, uf, mf, flag, errout) 141be04b6d1SDavid E. O'Brien kvm_t *kd; 14258f0484fSRodney W. Grimes const char *uf; 14358f0484fSRodney W. Grimes const char *mf; 14458f0484fSRodney W. Grimes int flag; 14558f0484fSRodney W. Grimes char *errout; 14658f0484fSRodney W. Grimes { 14758f0484fSRodney W. Grimes struct stat st; 14858f0484fSRodney W. Grimes 14958f0484fSRodney W. Grimes kd->vmfd = -1; 15058f0484fSRodney W. Grimes kd->pmfd = -1; 15158f0484fSRodney W. Grimes kd->nlfd = -1; 15258f0484fSRodney W. Grimes kd->vmst = 0; 15358f0484fSRodney W. Grimes kd->procbase = 0; 15458f0484fSRodney W. Grimes kd->argspc = 0; 15558f0484fSRodney W. Grimes kd->argv = 0; 15658f0484fSRodney W. Grimes 15758f0484fSRodney W. Grimes if (uf == 0) 1584be4929cSGarrett Wollman uf = getbootfile(); 15958f0484fSRodney W. Grimes else if (strlen(uf) >= MAXPATHLEN) { 16058f0484fSRodney W. Grimes _kvm_err(kd, kd->program, "exec file name too long"); 16158f0484fSRodney W. Grimes goto failed; 16258f0484fSRodney W. Grimes } 16358f0484fSRodney W. Grimes if (flag & ~O_RDWR) { 16458f0484fSRodney W. Grimes _kvm_err(kd, kd->program, "bad flags arg"); 16558f0484fSRodney W. Grimes goto failed; 16658f0484fSRodney W. Grimes } 16758f0484fSRodney W. Grimes if (mf == 0) 16858f0484fSRodney W. Grimes mf = _PATH_MEM; 16958f0484fSRodney W. Grimes 17058f0484fSRodney W. Grimes if ((kd->pmfd = open(mf, flag, 0)) < 0) { 17158f0484fSRodney W. Grimes _kvm_syserr(kd, kd->program, "%s", mf); 17258f0484fSRodney W. Grimes goto failed; 17358f0484fSRodney W. Grimes } 17458f0484fSRodney W. Grimes if (fstat(kd->pmfd, &st) < 0) { 17558f0484fSRodney W. Grimes _kvm_syserr(kd, kd->program, "%s", mf); 17658f0484fSRodney W. Grimes goto failed; 17758f0484fSRodney W. Grimes } 17865efc5eeSChristian S.J. Peron if (S_ISREG(st.st_mode) && st.st_size <= 0) { 17965efc5eeSChristian S.J. Peron errno = EINVAL; 18065efc5eeSChristian S.J. Peron _kvm_syserr(kd, kd->program, "empty file"); 18165efc5eeSChristian S.J. Peron goto failed; 18265efc5eeSChristian S.J. Peron } 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); 1967928124aSHidetoshi Shimokawa return (kd); 1977928124aSHidetoshi Shimokawa } else if (strcmp(mf, _PATH_MEM) == 0) { 19858f0484fSRodney W. Grimes if ((kd->vmfd = open(_PATH_KMEM, flag)) < 0) { 19958f0484fSRodney W. Grimes _kvm_syserr(kd, kd->program, "%s", _PATH_KMEM); 20058f0484fSRodney W. Grimes goto failed; 20158f0484fSRodney W. Grimes } 202f76b74d6SJacques Vidrine if (fcntl(kd->vmfd, F_SETFD, FD_CLOEXEC) < 0) { 203f76b74d6SJacques Vidrine _kvm_syserr(kd, kd->program, "%s", _PATH_KMEM); 204f76b74d6SJacques Vidrine goto failed; 205f76b74d6SJacques Vidrine } 2067928124aSHidetoshi Shimokawa return (kd); 20735e6b695SPoul-Henning Kamp } 2087928124aSHidetoshi Shimokawa } 20958f0484fSRodney W. Grimes /* 21058f0484fSRodney W. Grimes * This is a crash dump. 21135e6b695SPoul-Henning Kamp * Initialize the virtual address translation machinery, 21258f0484fSRodney W. Grimes * but first setup the namelist fd. 21358f0484fSRodney W. Grimes */ 21458f0484fSRodney W. Grimes if ((kd->nlfd = open(uf, O_RDONLY, 0)) < 0) { 21558f0484fSRodney W. Grimes _kvm_syserr(kd, kd->program, "%s", uf); 21658f0484fSRodney W. Grimes goto failed; 21758f0484fSRodney W. Grimes } 218f76b74d6SJacques Vidrine if (fcntl(kd->nlfd, F_SETFD, FD_CLOEXEC) < 0) { 219f76b74d6SJacques Vidrine _kvm_syserr(kd, kd->program, "%s", uf); 220f76b74d6SJacques Vidrine goto failed; 221f76b74d6SJacques Vidrine } 222d7dc9f76SHidetoshi Shimokawa if (strncmp(mf, _PATH_FWMEM, strlen(_PATH_FWMEM)) == 0) 223d7dc9f76SHidetoshi Shimokawa kd->rawdump = 1; 22458f0484fSRodney W. Grimes if (_kvm_initvtop(kd) < 0) 22558f0484fSRodney W. Grimes goto failed; 22658f0484fSRodney W. Grimes return (kd); 22758f0484fSRodney W. Grimes failed: 22858f0484fSRodney W. Grimes /* 22958f0484fSRodney W. Grimes * Copy out the error if doing sane error semantics. 23058f0484fSRodney W. Grimes */ 23158f0484fSRodney W. Grimes if (errout != 0) 232ba3c0383SKris Kennaway strlcpy(errout, kd->errbuf, _POSIX2_LINE_MAX); 23358f0484fSRodney W. Grimes (void)kvm_close(kd); 23458f0484fSRodney W. Grimes return (0); 23558f0484fSRodney W. Grimes } 23658f0484fSRodney W. Grimes 23758f0484fSRodney W. Grimes kvm_t * 23858f0484fSRodney W. Grimes kvm_openfiles(uf, mf, sf, flag, errout) 23958f0484fSRodney W. Grimes const char *uf; 24058f0484fSRodney W. Grimes const char *mf; 241fe42e96eSRuslan Ermilov const char *sf __unused; 24258f0484fSRodney W. Grimes int flag; 24358f0484fSRodney W. Grimes char *errout; 24458f0484fSRodney W. Grimes { 245be04b6d1SDavid E. O'Brien kvm_t *kd; 24658f0484fSRodney W. Grimes 24758f0484fSRodney W. Grimes if ((kd = malloc(sizeof(*kd))) == NULL) { 248ba3c0383SKris Kennaway (void)strlcpy(errout, strerror(errno), _POSIX2_LINE_MAX); 24958f0484fSRodney W. Grimes return (0); 25058f0484fSRodney W. Grimes } 251a52219bbSPeter Wemm memset(kd, 0, sizeof(*kd)); 25258f0484fSRodney W. Grimes kd->program = 0; 2538771870cSPeter Wemm return (_kvm_open(kd, uf, mf, flag, errout)); 25458f0484fSRodney W. Grimes } 25558f0484fSRodney W. Grimes 25658f0484fSRodney W. Grimes kvm_t * 25712eaa3d5SPoul-Henning Kamp kvm_open(uf, mf, sf, flag, errstr) 25858f0484fSRodney W. Grimes const char *uf; 25958f0484fSRodney W. Grimes const char *mf; 260fe42e96eSRuslan Ermilov const char *sf __unused; 26158f0484fSRodney W. Grimes int flag; 26212eaa3d5SPoul-Henning Kamp const char *errstr; 26358f0484fSRodney W. Grimes { 264be04b6d1SDavid E. O'Brien kvm_t *kd; 26558f0484fSRodney W. Grimes 26612eaa3d5SPoul-Henning Kamp if ((kd = malloc(sizeof(*kd))) == NULL) { 26764f14011SBruce Evans if (errstr != NULL) 26812eaa3d5SPoul-Henning Kamp (void)fprintf(stderr, "%s: %s\n", 26964f14011SBruce Evans errstr, strerror(errno)); 27058f0484fSRodney W. Grimes return (0); 27158f0484fSRodney W. Grimes } 272a52219bbSPeter Wemm memset(kd, 0, sizeof(*kd)); 27312eaa3d5SPoul-Henning Kamp kd->program = errstr; 2748771870cSPeter Wemm return (_kvm_open(kd, uf, mf, flag, NULL)); 27558f0484fSRodney W. Grimes } 27658f0484fSRodney W. Grimes 27758f0484fSRodney W. Grimes int 27858f0484fSRodney W. Grimes kvm_close(kd) 27958f0484fSRodney W. Grimes kvm_t *kd; 28058f0484fSRodney W. Grimes { 281be04b6d1SDavid E. O'Brien int error = 0; 28258f0484fSRodney W. Grimes 28358f0484fSRodney W. Grimes if (kd->pmfd >= 0) 28458f0484fSRodney W. Grimes error |= close(kd->pmfd); 28558f0484fSRodney W. Grimes if (kd->vmfd >= 0) 28658f0484fSRodney W. Grimes error |= close(kd->vmfd); 28758f0484fSRodney W. Grimes if (kd->nlfd >= 0) 28858f0484fSRodney W. Grimes error |= close(kd->nlfd); 28958f0484fSRodney W. Grimes if (kd->vmst) 29058f0484fSRodney W. Grimes _kvm_freevtop(kd); 29158f0484fSRodney W. Grimes if (kd->procbase != 0) 29258f0484fSRodney W. Grimes free((void *)kd->procbase); 2938b8ffe64SXin LI if (kd->argbuf != 0) 2948b8ffe64SXin LI free((void *) kd->argbuf); 2958b8ffe64SXin LI if (kd->argspc != 0) 2968b8ffe64SXin LI free((void *) kd->argspc); 29758f0484fSRodney W. Grimes if (kd->argv != 0) 29858f0484fSRodney W. Grimes free((void *)kd->argv); 29958f0484fSRodney W. Grimes free((void *)kd); 30058f0484fSRodney W. Grimes 30158f0484fSRodney W. Grimes return (0); 30258f0484fSRodney W. Grimes } 30358f0484fSRodney W. Grimes 30458f0484fSRodney W. Grimes int 30558f0484fSRodney W. Grimes kvm_nlist(kd, nl) 30658f0484fSRodney W. Grimes kvm_t *kd; 30758f0484fSRodney W. Grimes struct nlist *nl; 30858f0484fSRodney W. Grimes { 309be04b6d1SDavid E. O'Brien struct nlist *p; 310be04b6d1SDavid E. O'Brien int nvalid; 311c4a7cdb3SPeter Wemm struct kld_sym_lookup lookup; 3126e6dfbf2SWojciech A. Koszek int error; 31358f0484fSRodney W. Grimes 31458f0484fSRodney W. Grimes /* 315c4a7cdb3SPeter Wemm * If we can't use the kld symbol lookup, revert to the 31658f0484fSRodney W. Grimes * slow library call. 31758f0484fSRodney W. Grimes */ 318c4a7cdb3SPeter Wemm if (!ISALIVE(kd)) 31958f0484fSRodney W. Grimes return (__fdnlist(kd->nlfd, nl)); 32058f0484fSRodney W. Grimes 32158f0484fSRodney W. Grimes /* 322c4a7cdb3SPeter Wemm * We can use the kld lookup syscall. Go through each nlist entry 323c4a7cdb3SPeter Wemm * and look it up with a kldsym(2) syscall. 32458f0484fSRodney W. Grimes */ 32558f0484fSRodney W. Grimes nvalid = 0; 32658f0484fSRodney W. Grimes for (p = nl; p->n_name && p->n_name[0]; ++p) { 327c4a7cdb3SPeter Wemm lookup.version = sizeof(lookup); 328c4a7cdb3SPeter Wemm lookup.symname = p->n_name; 329c4a7cdb3SPeter Wemm lookup.symvalue = 0; 330c4a7cdb3SPeter Wemm lookup.symsize = 0; 33158f0484fSRodney W. Grimes 332c4a7cdb3SPeter Wemm if (lookup.symname[0] == '_') 333c4a7cdb3SPeter Wemm lookup.symname++; 334c4a7cdb3SPeter Wemm 335c4a7cdb3SPeter Wemm if (kldsym(0, KLDSYM_LOOKUP, &lookup) != -1) { 336c4a7cdb3SPeter Wemm p->n_type = N_TEXT; 337c4a7cdb3SPeter Wemm p->n_other = 0; 338c4a7cdb3SPeter Wemm p->n_desc = 0; 339c4a7cdb3SPeter Wemm p->n_value = lookup.symvalue; 34058f0484fSRodney W. Grimes ++nvalid; 341c4a7cdb3SPeter Wemm /* lookup.symsize */ 342c4a7cdb3SPeter Wemm } 34358f0484fSRodney W. Grimes } 34458f0484fSRodney W. Grimes /* 3456e6dfbf2SWojciech A. Koszek * Return the number of entries that weren't found. If they exist, 3466e6dfbf2SWojciech A. Koszek * also fill internal error buffer. 34758f0484fSRodney W. Grimes */ 3486e6dfbf2SWojciech A. Koszek error = ((p - nl) - nvalid); 3496e6dfbf2SWojciech A. Koszek if (error) 3506e6dfbf2SWojciech A. Koszek _kvm_syserr(kd, kd->program, "kvm_nlist"); 3516e6dfbf2SWojciech A. Koszek return (error); 35258f0484fSRodney W. Grimes } 35358f0484fSRodney W. Grimes 35458f0484fSRodney W. Grimes ssize_t 35558f0484fSRodney W. Grimes kvm_read(kd, kva, buf, len) 35658f0484fSRodney W. Grimes kvm_t *kd; 357be04b6d1SDavid E. O'Brien u_long kva; 358be04b6d1SDavid E. O'Brien void *buf; 359be04b6d1SDavid E. O'Brien size_t len; 36058f0484fSRodney W. Grimes { 361be04b6d1SDavid E. O'Brien int cc; 3621a5ff928SStefan Farfeleder char *cp; 36358f0484fSRodney W. Grimes 36458f0484fSRodney W. Grimes if (ISALIVE(kd)) { 36558f0484fSRodney W. Grimes /* 36658f0484fSRodney W. Grimes * We're using /dev/kmem. Just read straight from the 36758f0484fSRodney W. Grimes * device and let the active kernel do the address translation. 36858f0484fSRodney W. Grimes */ 36958f0484fSRodney W. Grimes errno = 0; 37058f0484fSRodney W. Grimes if (lseek(kd->vmfd, (off_t)kva, 0) == -1 && errno != 0) { 37158f0484fSRodney W. Grimes _kvm_err(kd, 0, "invalid address (%x)", kva); 37291a594d8SJacques Vidrine return (-1); 37358f0484fSRodney W. Grimes } 37458f0484fSRodney W. Grimes cc = read(kd->vmfd, buf, len); 37558f0484fSRodney W. Grimes if (cc < 0) { 37658f0484fSRodney W. Grimes _kvm_syserr(kd, 0, "kvm_read"); 37791a594d8SJacques Vidrine return (-1); 37858f0484fSRodney W. Grimes } else if (cc < len) 37958f0484fSRodney W. Grimes _kvm_err(kd, kd->program, "short read"); 38058f0484fSRodney W. Grimes return (cc); 38158f0484fSRodney W. Grimes } else { 38258f0484fSRodney W. Grimes cp = buf; 38358f0484fSRodney W. Grimes while (len > 0) { 384e55a0cd8SPeter Wemm off_t pa; 38558f0484fSRodney W. Grimes 38658f0484fSRodney W. Grimes cc = _kvm_kvatop(kd, kva, &pa); 38758f0484fSRodney W. Grimes if (cc == 0) 38891a594d8SJacques Vidrine return (-1); 38958f0484fSRodney W. Grimes if (cc > len) 39058f0484fSRodney W. Grimes cc = len; 39158f0484fSRodney W. Grimes errno = 0; 392e55a0cd8SPeter Wemm if (lseek(kd->pmfd, pa, 0) == -1 && errno != 0) { 39358f0484fSRodney W. Grimes _kvm_syserr(kd, 0, _PATH_MEM); 39458f0484fSRodney W. Grimes break; 39558f0484fSRodney W. Grimes } 39658f0484fSRodney W. Grimes cc = read(kd->pmfd, cp, cc); 39758f0484fSRodney W. Grimes if (cc < 0) { 39858f0484fSRodney W. Grimes _kvm_syserr(kd, kd->program, "kvm_read"); 39958f0484fSRodney W. Grimes break; 40058f0484fSRodney W. Grimes } 40158f0484fSRodney W. Grimes /* 40258f0484fSRodney W. Grimes * If kvm_kvatop returns a bogus value or our core 40358f0484fSRodney W. Grimes * file is truncated, we might wind up seeking beyond 40458f0484fSRodney W. Grimes * the end of the core file in which case the read will 40558f0484fSRodney W. Grimes * return 0 (EOF). 40658f0484fSRodney W. Grimes */ 40758f0484fSRodney W. Grimes if (cc == 0) 40858f0484fSRodney W. Grimes break; 4091a5ff928SStefan Farfeleder cp += cc; 41058f0484fSRodney W. Grimes kva += cc; 41158f0484fSRodney W. Grimes len -= cc; 41258f0484fSRodney W. Grimes } 4131a5ff928SStefan Farfeleder return (cp - (char *)buf); 41458f0484fSRodney W. Grimes } 41558f0484fSRodney W. Grimes /* NOTREACHED */ 41658f0484fSRodney W. Grimes } 41758f0484fSRodney W. Grimes 41858f0484fSRodney W. Grimes ssize_t 41958f0484fSRodney W. Grimes kvm_write(kd, kva, buf, len) 42058f0484fSRodney W. Grimes kvm_t *kd; 421be04b6d1SDavid E. O'Brien u_long kva; 422be04b6d1SDavid E. O'Brien const void *buf; 423be04b6d1SDavid E. O'Brien size_t len; 42458f0484fSRodney W. Grimes { 425be04b6d1SDavid E. O'Brien int cc; 42658f0484fSRodney W. Grimes 42758f0484fSRodney W. Grimes if (ISALIVE(kd)) { 42858f0484fSRodney W. Grimes /* 42958f0484fSRodney W. Grimes * Just like kvm_read, only we write. 43058f0484fSRodney W. Grimes */ 43158f0484fSRodney W. Grimes errno = 0; 43258f0484fSRodney W. Grimes if (lseek(kd->vmfd, (off_t)kva, 0) == -1 && errno != 0) { 43358f0484fSRodney W. Grimes _kvm_err(kd, 0, "invalid address (%x)", kva); 43491a594d8SJacques Vidrine return (-1); 43558f0484fSRodney W. Grimes } 43658f0484fSRodney W. Grimes cc = write(kd->vmfd, buf, len); 43758f0484fSRodney W. Grimes if (cc < 0) { 43858f0484fSRodney W. Grimes _kvm_syserr(kd, 0, "kvm_write"); 43991a594d8SJacques Vidrine return (-1); 44058f0484fSRodney W. Grimes } else if (cc < len) 44158f0484fSRodney W. Grimes _kvm_err(kd, kd->program, "short write"); 44258f0484fSRodney W. Grimes return (cc); 44358f0484fSRodney W. Grimes } else { 44458f0484fSRodney W. Grimes _kvm_err(kd, kd->program, 44558f0484fSRodney W. Grimes "kvm_write not implemented for dead kernels"); 44691a594d8SJacques Vidrine return (-1); 44758f0484fSRodney W. Grimes } 44858f0484fSRodney W. Grimes /* NOTREACHED */ 44958f0484fSRodney W. Grimes } 450