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> 447f911abeSJohn Baldwin #include <sys/fnv_hash.h> 457cf8b4b9SBjoern A. Zeeb 467cf8b4b9SBjoern A. Zeeb #define _WANT_VNET 477cf8b4b9SBjoern A. Zeeb 4858f0484fSRodney W. Grimes #include <sys/user.h> 49c4a7cdb3SPeter Wemm #include <sys/linker.h> 505f67450dSDimitry Andric #include <sys/pcpu.h> 517f911abeSJohn Baldwin #include <sys/stat.h> 5258f0484fSRodney W. Grimes 537cf8b4b9SBjoern A. Zeeb #include <net/vnet.h> 547cf8b4b9SBjoern A. Zeeb 5558f0484fSRodney W. Grimes #include <fcntl.h> 5658f0484fSRodney W. Grimes #include <kvm.h> 5758f0484fSRodney W. Grimes #include <limits.h> 5858f0484fSRodney W. Grimes #include <paths.h> 597f911abeSJohn Baldwin #include <stdint.h> 6058f0484fSRodney W. Grimes #include <stdio.h> 6158f0484fSRodney W. Grimes #include <stdlib.h> 6258f0484fSRodney W. Grimes #include <string.h> 6358f0484fSRodney W. Grimes #include <unistd.h> 6458f0484fSRodney W. Grimes 6558f0484fSRodney W. Grimes #include "kvm_private.h" 6658f0484fSRodney W. Grimes 677f911abeSJohn Baldwin SET_DECLARE(kvm_arch, struct kvm_arch); 683f6558c4SMarcel Moolenaar 6958f0484fSRodney W. Grimes char * 70c10970ddSUlrich Spörlein kvm_geterr(kvm_t *kd) 7158f0484fSRodney W. Grimes { 7258f0484fSRodney W. Grimes return (kd->errbuf); 7358f0484fSRodney W. Grimes } 7458f0484fSRodney W. Grimes 757f911abeSJohn Baldwin static int 767f911abeSJohn Baldwin _kvm_read_kernel_ehdr(kvm_t *kd) 777f911abeSJohn Baldwin { 787f911abeSJohn Baldwin Elf *elf; 797f911abeSJohn Baldwin 807f911abeSJohn Baldwin if (elf_version(EV_CURRENT) == EV_NONE) { 817f911abeSJohn Baldwin _kvm_err(kd, kd->program, "Unsupported libelf"); 827f911abeSJohn Baldwin return (-1); 837f911abeSJohn Baldwin } 847f911abeSJohn Baldwin elf = elf_begin(kd->nlfd, ELF_C_READ, NULL); 857f911abeSJohn Baldwin if (elf == NULL) { 867f911abeSJohn Baldwin _kvm_err(kd, kd->program, "%s", elf_errmsg(0)); 877f911abeSJohn Baldwin return (-1); 887f911abeSJohn Baldwin } 897f911abeSJohn Baldwin if (elf_kind(elf) != ELF_K_ELF) { 907f911abeSJohn Baldwin _kvm_err(kd, kd->program, "kernel is not an ELF file"); 917f911abeSJohn Baldwin return (-1); 927f911abeSJohn Baldwin } 937f911abeSJohn Baldwin if (gelf_getehdr(elf, &kd->nlehdr) == NULL) { 947f911abeSJohn Baldwin _kvm_err(kd, kd->program, "%s", elf_errmsg(0)); 957f911abeSJohn Baldwin elf_end(elf); 967f911abeSJohn Baldwin return (-1); 977f911abeSJohn Baldwin } 987f911abeSJohn Baldwin elf_end(elf); 997f911abeSJohn Baldwin 1007f911abeSJohn Baldwin switch (kd->nlehdr.e_ident[EI_DATA]) { 1017f911abeSJohn Baldwin case ELFDATA2LSB: 1027f911abeSJohn Baldwin case ELFDATA2MSB: 1037f911abeSJohn Baldwin return (0); 1047f911abeSJohn Baldwin default: 1057f911abeSJohn Baldwin _kvm_err(kd, kd->program, 1067f911abeSJohn Baldwin "unsupported ELF data encoding for kernel"); 1077f911abeSJohn Baldwin return (-1); 1087f911abeSJohn Baldwin } 1097f911abeSJohn Baldwin } 1107f911abeSJohn Baldwin 11158f0484fSRodney W. Grimes static kvm_t * 112c10970ddSUlrich Spörlein _kvm_open(kvm_t *kd, const char *uf, const char *mf, int flag, char *errout) 11358f0484fSRodney W. Grimes { 1147f911abeSJohn Baldwin struct kvm_arch **parch; 11558f0484fSRodney W. Grimes struct stat st; 11658f0484fSRodney W. Grimes 11758f0484fSRodney W. Grimes kd->vmfd = -1; 11858f0484fSRodney W. Grimes kd->pmfd = -1; 11958f0484fSRodney W. Grimes kd->nlfd = -1; 120fb0e1892SEnji Cooper kd->vmst = NULL; 121fb0e1892SEnji Cooper kd->procbase = NULL; 122fb0e1892SEnji Cooper kd->argspc = NULL; 123fb0e1892SEnji Cooper kd->argv = NULL; 12458f0484fSRodney W. Grimes 125fb0e1892SEnji Cooper if (uf == NULL) 1264be4929cSGarrett Wollman uf = getbootfile(); 12758f0484fSRodney W. Grimes else if (strlen(uf) >= MAXPATHLEN) { 12858f0484fSRodney W. Grimes _kvm_err(kd, kd->program, "exec file name too long"); 12958f0484fSRodney W. Grimes goto failed; 13058f0484fSRodney W. Grimes } 13158f0484fSRodney W. Grimes if (flag & ~O_RDWR) { 13258f0484fSRodney W. Grimes _kvm_err(kd, kd->program, "bad flags arg"); 13358f0484fSRodney W. Grimes goto failed; 13458f0484fSRodney W. Grimes } 135fb0e1892SEnji Cooper if (mf == NULL) 13658f0484fSRodney W. Grimes mf = _PATH_MEM; 13758f0484fSRodney W. Grimes 13876dce67fSJilles Tjoelker if ((kd->pmfd = open(mf, flag | O_CLOEXEC, 0)) < 0) { 13958f0484fSRodney W. Grimes _kvm_syserr(kd, kd->program, "%s", mf); 14058f0484fSRodney W. Grimes goto failed; 14158f0484fSRodney W. Grimes } 14258f0484fSRodney W. Grimes if (fstat(kd->pmfd, &st) < 0) { 14358f0484fSRodney W. Grimes _kvm_syserr(kd, kd->program, "%s", mf); 14458f0484fSRodney W. Grimes goto failed; 14558f0484fSRodney W. Grimes } 14665efc5eeSChristian S.J. Peron if (S_ISREG(st.st_mode) && st.st_size <= 0) { 14765efc5eeSChristian S.J. Peron errno = EINVAL; 14865efc5eeSChristian S.J. Peron _kvm_syserr(kd, kd->program, "empty file"); 14965efc5eeSChristian S.J. Peron goto failed; 15065efc5eeSChristian S.J. Peron } 15158f0484fSRodney W. Grimes if (S_ISCHR(st.st_mode)) { 15258f0484fSRodney W. Grimes /* 15358f0484fSRodney W. Grimes * If this is a character special device, then check that 15458f0484fSRodney W. Grimes * it's /dev/mem. If so, open kmem too. (Maybe we should 15558f0484fSRodney W. Grimes * make it work for either /dev/mem or /dev/kmem -- in either 15658f0484fSRodney W. Grimes * case you're working with a live kernel.) 15758f0484fSRodney W. Grimes */ 15835e6b695SPoul-Henning Kamp if (strcmp(mf, _PATH_DEVNULL) == 0) { 1597b05a799SJilles Tjoelker kd->vmfd = open(_PATH_DEVNULL, O_RDONLY | O_CLOEXEC); 1607928124aSHidetoshi Shimokawa return (kd); 1617928124aSHidetoshi Shimokawa } else if (strcmp(mf, _PATH_MEM) == 0) { 16276dce67fSJilles Tjoelker if ((kd->vmfd = open(_PATH_KMEM, flag | O_CLOEXEC)) < 16376dce67fSJilles Tjoelker 0) { 164f76b74d6SJacques Vidrine _kvm_syserr(kd, kd->program, "%s", _PATH_KMEM); 165f76b74d6SJacques Vidrine goto failed; 166f76b74d6SJacques Vidrine } 1677928124aSHidetoshi Shimokawa return (kd); 16835e6b695SPoul-Henning Kamp } 1697928124aSHidetoshi Shimokawa } 17058f0484fSRodney W. Grimes /* 17158f0484fSRodney W. Grimes * This is a crash dump. 1727f911abeSJohn Baldwin * Open the namelist fd and determine the architecture. 17358f0484fSRodney W. Grimes */ 17476dce67fSJilles Tjoelker if ((kd->nlfd = open(uf, O_RDONLY | O_CLOEXEC, 0)) < 0) { 175f76b74d6SJacques Vidrine _kvm_syserr(kd, kd->program, "%s", uf); 176f76b74d6SJacques Vidrine goto failed; 177f76b74d6SJacques Vidrine } 1787f911abeSJohn Baldwin if (_kvm_read_kernel_ehdr(kd) < 0) 1797f911abeSJohn Baldwin goto failed; 180d7dc9f76SHidetoshi Shimokawa if (strncmp(mf, _PATH_FWMEM, strlen(_PATH_FWMEM)) == 0) 181d7dc9f76SHidetoshi Shimokawa kd->rawdump = 1; 1827f911abeSJohn Baldwin SET_FOREACH(parch, kvm_arch) { 1837f911abeSJohn Baldwin if ((*parch)->ka_probe(kd)) { 1847f911abeSJohn Baldwin kd->arch = *parch; 1857f911abeSJohn Baldwin break; 1867f911abeSJohn Baldwin } 1877f911abeSJohn Baldwin } 1887f911abeSJohn Baldwin if (kd->arch == NULL) { 1897f911abeSJohn Baldwin _kvm_err(kd, kd->program, "unsupported architecture"); 1907f911abeSJohn Baldwin goto failed; 1917f911abeSJohn Baldwin } 1927f911abeSJohn Baldwin 1937f911abeSJohn Baldwin /* 1947f911abeSJohn Baldwin * Non-native kernels require a symbol resolver. 1957f911abeSJohn Baldwin */ 1967f911abeSJohn Baldwin if (!kd->arch->ka_native(kd) && kd->resolve_symbol == NULL) { 1977f911abeSJohn Baldwin _kvm_err(kd, kd->program, 1987f911abeSJohn Baldwin "non-native kernel requires a symbol resolver"); 1997f911abeSJohn Baldwin goto failed; 2007f911abeSJohn Baldwin } 2017f911abeSJohn Baldwin 2027f911abeSJohn Baldwin /* 2037f911abeSJohn Baldwin * Initialize the virtual address translation machinery. 2047f911abeSJohn Baldwin */ 2057f911abeSJohn Baldwin if (kd->arch->ka_initvtop(kd) < 0) 20658f0484fSRodney W. Grimes goto failed; 20758f0484fSRodney W. Grimes return (kd); 20858f0484fSRodney W. Grimes failed: 20958f0484fSRodney W. Grimes /* 21058f0484fSRodney W. Grimes * Copy out the error if doing sane error semantics. 21158f0484fSRodney W. Grimes */ 212fb0e1892SEnji Cooper if (errout != NULL) 213ba3c0383SKris Kennaway strlcpy(errout, kd->errbuf, _POSIX2_LINE_MAX); 21458f0484fSRodney W. Grimes (void)kvm_close(kd); 21558f0484fSRodney W. Grimes return (0); 21658f0484fSRodney W. Grimes } 21758f0484fSRodney W. Grimes 21858f0484fSRodney W. Grimes kvm_t * 219c10970ddSUlrich Spörlein kvm_openfiles(const char *uf, const char *mf, const char *sf __unused, int flag, 220c10970ddSUlrich Spörlein char *errout) 22158f0484fSRodney W. Grimes { 222be04b6d1SDavid E. O'Brien kvm_t *kd; 22358f0484fSRodney W. Grimes 22401c56ef2SXin LI if ((kd = calloc(1, sizeof(*kd))) == NULL) { 225fb0e1892SEnji Cooper if (errout != NULL) 226fb0e1892SEnji Cooper (void)strlcpy(errout, strerror(errno), 227fb0e1892SEnji Cooper _POSIX2_LINE_MAX); 22858f0484fSRodney W. Grimes return (0); 22958f0484fSRodney W. Grimes } 2308771870cSPeter Wemm return (_kvm_open(kd, uf, mf, flag, errout)); 23158f0484fSRodney W. Grimes } 23258f0484fSRodney W. Grimes 23358f0484fSRodney W. Grimes kvm_t * 234c10970ddSUlrich Spörlein kvm_open(const char *uf, const char *mf, const char *sf __unused, int flag, 235c10970ddSUlrich Spörlein const char *errstr) 23658f0484fSRodney W. Grimes { 237be04b6d1SDavid E. O'Brien kvm_t *kd; 23858f0484fSRodney W. Grimes 23901c56ef2SXin LI if ((kd = calloc(1, sizeof(*kd))) == NULL) { 24064f14011SBruce Evans if (errstr != NULL) 24112eaa3d5SPoul-Henning Kamp (void)fprintf(stderr, "%s: %s\n", 24264f14011SBruce Evans errstr, strerror(errno)); 24358f0484fSRodney W. Grimes return (0); 24458f0484fSRodney W. Grimes } 24512eaa3d5SPoul-Henning Kamp kd->program = errstr; 2468771870cSPeter Wemm return (_kvm_open(kd, uf, mf, flag, NULL)); 24758f0484fSRodney W. Grimes } 24858f0484fSRodney W. Grimes 2497f911abeSJohn Baldwin kvm_t * 2507f911abeSJohn Baldwin kvm_open2(const char *uf, const char *mf, int flag, char *errout, 2517f911abeSJohn Baldwin int (*resolver)(const char *, kvaddr_t *)) 2527f911abeSJohn Baldwin { 2537f911abeSJohn Baldwin kvm_t *kd; 2547f911abeSJohn Baldwin 2557f911abeSJohn Baldwin if ((kd = calloc(1, sizeof(*kd))) == NULL) { 256fb0e1892SEnji Cooper if (errout != NULL) 257fb0e1892SEnji Cooper (void)strlcpy(errout, strerror(errno), 258fb0e1892SEnji Cooper _POSIX2_LINE_MAX); 2597f911abeSJohn Baldwin return (0); 2607f911abeSJohn Baldwin } 2617f911abeSJohn Baldwin kd->resolve_symbol = resolver; 2627f911abeSJohn Baldwin return (_kvm_open(kd, uf, mf, flag, errout)); 2637f911abeSJohn Baldwin } 2647f911abeSJohn Baldwin 26558f0484fSRodney W. Grimes int 266c10970ddSUlrich Spörlein kvm_close(kvm_t *kd) 26758f0484fSRodney W. Grimes { 268be04b6d1SDavid E. O'Brien int error = 0; 26958f0484fSRodney W. Grimes 2707f911abeSJohn Baldwin if (kd->vmst != NULL) 2717f911abeSJohn Baldwin kd->arch->ka_freevtop(kd); 27258f0484fSRodney W. Grimes if (kd->pmfd >= 0) 27358f0484fSRodney W. Grimes error |= close(kd->pmfd); 27458f0484fSRodney W. Grimes if (kd->vmfd >= 0) 27558f0484fSRodney W. Grimes error |= close(kd->vmfd); 27658f0484fSRodney W. Grimes if (kd->nlfd >= 0) 27758f0484fSRodney W. Grimes error |= close(kd->nlfd); 27858f0484fSRodney W. Grimes if (kd->procbase != 0) 27958f0484fSRodney W. Grimes free((void *)kd->procbase); 2808b8ffe64SXin LI if (kd->argbuf != 0) 2818b8ffe64SXin LI free((void *) kd->argbuf); 2828b8ffe64SXin LI if (kd->argspc != 0) 2838b8ffe64SXin LI free((void *) kd->argspc); 28458f0484fSRodney W. Grimes if (kd->argv != 0) 28558f0484fSRodney W. Grimes free((void *)kd->argv); 286*ffdeef32SWill Andrews if (kd->pt_map != NULL) 287*ffdeef32SWill Andrews free(kd->pt_map); 28858f0484fSRodney W. Grimes free((void *)kd); 28958f0484fSRodney W. Grimes 29058f0484fSRodney W. Grimes return (0); 29158f0484fSRodney W. Grimes } 29258f0484fSRodney W. Grimes 2937cf8b4b9SBjoern A. Zeeb int 2947f911abeSJohn Baldwin kvm_nlist2(kvm_t *kd, struct kvm_nlist *nl) 2957cf8b4b9SBjoern A. Zeeb { 2967cf8b4b9SBjoern A. Zeeb 2977cf8b4b9SBjoern A. Zeeb /* 29875f46cf6SPedro F. Giffuni * If called via the public interface, permit initialization of 2997cf8b4b9SBjoern A. Zeeb * further virtualized modules on demand. 3007cf8b4b9SBjoern A. Zeeb */ 3017cf8b4b9SBjoern A. Zeeb return (_kvm_nlist(kd, nl, 1)); 3027cf8b4b9SBjoern A. Zeeb } 3037cf8b4b9SBjoern A. Zeeb 3047f911abeSJohn Baldwin int 3057f911abeSJohn Baldwin kvm_nlist(kvm_t *kd, struct nlist *nl) 3067f911abeSJohn Baldwin { 3077f911abeSJohn Baldwin struct kvm_nlist *kl; 3087f911abeSJohn Baldwin int count, i, nfail; 3097f911abeSJohn Baldwin 3107f911abeSJohn Baldwin /* 3117f911abeSJohn Baldwin * Avoid reporting truncated addresses by failing for non-native 3127f911abeSJohn Baldwin * cores. 3137f911abeSJohn Baldwin */ 3147f911abeSJohn Baldwin if (!kvm_native(kd)) { 3157f911abeSJohn Baldwin _kvm_err(kd, kd->program, "kvm_nlist of non-native vmcore"); 3167f911abeSJohn Baldwin return (-1); 3177f911abeSJohn Baldwin } 3187f911abeSJohn Baldwin 3197f911abeSJohn Baldwin for (count = 0; nl[count].n_name != NULL && nl[count].n_name[0] != '\0'; 3207f911abeSJohn Baldwin count++) 3217f911abeSJohn Baldwin ; 3227f911abeSJohn Baldwin if (count == 0) 3237f911abeSJohn Baldwin return (0); 3247f911abeSJohn Baldwin kl = calloc(count + 1, sizeof(*kl)); 3257f911abeSJohn Baldwin for (i = 0; i < count; i++) 3267f911abeSJohn Baldwin kl[i].n_name = nl[i].n_name; 3277f911abeSJohn Baldwin nfail = kvm_nlist2(kd, kl); 3287f911abeSJohn Baldwin for (i = 0; i < count; i++) { 3297f911abeSJohn Baldwin nl[i].n_type = kl[i].n_type; 3307f911abeSJohn Baldwin nl[i].n_other = 0; 3317f911abeSJohn Baldwin nl[i].n_desc = 0; 3327f911abeSJohn Baldwin nl[i].n_value = kl[i].n_value; 3337f911abeSJohn Baldwin } 3347f911abeSJohn Baldwin return (nfail); 3357f911abeSJohn Baldwin } 3367f911abeSJohn Baldwin 33758f0484fSRodney W. Grimes ssize_t 338c10970ddSUlrich Spörlein kvm_read(kvm_t *kd, u_long kva, void *buf, size_t len) 33958f0484fSRodney W. Grimes { 3407f911abeSJohn Baldwin 3417f911abeSJohn Baldwin return (kvm_read2(kd, kva, buf, len)); 3427f911abeSJohn Baldwin } 3437f911abeSJohn Baldwin 3447f911abeSJohn Baldwin ssize_t 3457f911abeSJohn Baldwin kvm_read2(kvm_t *kd, kvaddr_t kva, void *buf, size_t len) 3467f911abeSJohn Baldwin { 347be04b6d1SDavid E. O'Brien int cc; 348c10970ddSUlrich Spörlein ssize_t cr; 349c10970ddSUlrich Spörlein off_t pa; 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) { 3597f911abeSJohn Baldwin _kvm_err(kd, 0, "invalid address (0x%jx)", 3607f911abeSJohn Baldwin (uintmax_t)kva); 36191a594d8SJacques Vidrine return (-1); 36258f0484fSRodney W. Grimes } 363c10970ddSUlrich Spörlein cr = read(kd->vmfd, buf, len); 364c10970ddSUlrich Spörlein if (cr < 0) { 36558f0484fSRodney W. Grimes _kvm_syserr(kd, 0, "kvm_read"); 36691a594d8SJacques Vidrine return (-1); 367c10970ddSUlrich Spörlein } else if (cr < (ssize_t)len) 36858f0484fSRodney W. Grimes _kvm_err(kd, kd->program, "short read"); 369c10970ddSUlrich Spörlein return (cr); 370c10970ddSUlrich Spörlein } 371c10970ddSUlrich Spörlein 37258f0484fSRodney W. Grimes cp = buf; 37358f0484fSRodney W. Grimes while (len > 0) { 3747f911abeSJohn Baldwin cc = kd->arch->ka_kvatop(kd, kva, &pa); 37558f0484fSRodney W. Grimes if (cc == 0) 37691a594d8SJacques Vidrine return (-1); 377c10970ddSUlrich Spörlein if (cc > (ssize_t)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 } 384c10970ddSUlrich Spörlein cr = read(kd->pmfd, cp, cc); 385c10970ddSUlrich Spörlein if (cr < 0) { 38658f0484fSRodney W. Grimes _kvm_syserr(kd, kd->program, "kvm_read"); 38758f0484fSRodney W. Grimes break; 38858f0484fSRodney W. Grimes } 38958f0484fSRodney W. Grimes /* 3907f911abeSJohn Baldwin * If ka_kvatop returns a bogus value or our core file is 391c10970ddSUlrich Spörlein * truncated, we might wind up seeking beyond the end of the 392c10970ddSUlrich Spörlein * core file in which case the read will return 0 (EOF). 39358f0484fSRodney W. Grimes */ 394c10970ddSUlrich Spörlein if (cr == 0) 39558f0484fSRodney W. Grimes break; 396c10970ddSUlrich Spörlein cp += cr; 397c10970ddSUlrich Spörlein kva += cr; 398c10970ddSUlrich Spörlein len -= cr; 39958f0484fSRodney W. Grimes } 400c10970ddSUlrich Spörlein 4011a5ff928SStefan Farfeleder return (cp - (char *)buf); 40258f0484fSRodney W. Grimes } 40358f0484fSRodney W. Grimes 40458f0484fSRodney W. Grimes ssize_t 405c10970ddSUlrich Spörlein kvm_write(kvm_t *kd, u_long kva, const void *buf, size_t len) 40658f0484fSRodney W. Grimes { 407be04b6d1SDavid E. O'Brien int cc; 40858f0484fSRodney W. Grimes 40958f0484fSRodney W. Grimes if (ISALIVE(kd)) { 41058f0484fSRodney W. Grimes /* 41158f0484fSRodney W. Grimes * Just like kvm_read, only we write. 41258f0484fSRodney W. Grimes */ 41358f0484fSRodney W. Grimes errno = 0; 41458f0484fSRodney W. Grimes if (lseek(kd->vmfd, (off_t)kva, 0) == -1 && errno != 0) { 415c10970ddSUlrich Spörlein _kvm_err(kd, 0, "invalid address (%lx)", kva); 41691a594d8SJacques Vidrine return (-1); 41758f0484fSRodney W. Grimes } 41858f0484fSRodney W. Grimes cc = write(kd->vmfd, buf, len); 41958f0484fSRodney W. Grimes if (cc < 0) { 42058f0484fSRodney W. Grimes _kvm_syserr(kd, 0, "kvm_write"); 42191a594d8SJacques Vidrine return (-1); 422c10970ddSUlrich Spörlein } else if ((size_t)cc < len) 42358f0484fSRodney W. Grimes _kvm_err(kd, kd->program, "short write"); 42458f0484fSRodney W. Grimes return (cc); 42558f0484fSRodney W. Grimes } else { 42658f0484fSRodney W. Grimes _kvm_err(kd, kd->program, 42758f0484fSRodney W. Grimes "kvm_write not implemented for dead kernels"); 42891a594d8SJacques Vidrine return (-1); 42958f0484fSRodney W. Grimes } 43058f0484fSRodney W. Grimes /* NOTREACHED */ 43158f0484fSRodney W. Grimes } 4327f911abeSJohn Baldwin 4337f911abeSJohn Baldwin int 4347f911abeSJohn Baldwin kvm_native(kvm_t *kd) 4357f911abeSJohn Baldwin { 4367f911abeSJohn Baldwin 4377f911abeSJohn Baldwin if (ISALIVE(kd)) 4387f911abeSJohn Baldwin return (1); 4397f911abeSJohn Baldwin return (kd->arch->ka_native(kd)); 4407f911abeSJohn Baldwin } 441