1*7c478bd9Sstevel@tonic-gate /* 2*7c478bd9Sstevel@tonic-gate * CDDL HEADER START 3*7c478bd9Sstevel@tonic-gate * 4*7c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*7c478bd9Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 6*7c478bd9Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 7*7c478bd9Sstevel@tonic-gate * with the License. 8*7c478bd9Sstevel@tonic-gate * 9*7c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10*7c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 11*7c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 12*7c478bd9Sstevel@tonic-gate * and limitations under the License. 13*7c478bd9Sstevel@tonic-gate * 14*7c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 15*7c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16*7c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 17*7c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 18*7c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 19*7c478bd9Sstevel@tonic-gate * 20*7c478bd9Sstevel@tonic-gate * CDDL HEADER END 21*7c478bd9Sstevel@tonic-gate */ 22*7c478bd9Sstevel@tonic-gate /* 23*7c478bd9Sstevel@tonic-gate * Copyright 2004 Sun Microsystems, Inc. All rights reserved. 24*7c478bd9Sstevel@tonic-gate * Use is subject to license terms. 25*7c478bd9Sstevel@tonic-gate */ 26*7c478bd9Sstevel@tonic-gate 27*7c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 28*7c478bd9Sstevel@tonic-gate 29*7c478bd9Sstevel@tonic-gate #include <kvm.h> 30*7c478bd9Sstevel@tonic-gate #include <stdio.h> 31*7c478bd9Sstevel@tonic-gate #include <stdlib.h> 32*7c478bd9Sstevel@tonic-gate #include <stdarg.h> 33*7c478bd9Sstevel@tonic-gate #include <unistd.h> 34*7c478bd9Sstevel@tonic-gate #include <limits.h> 35*7c478bd9Sstevel@tonic-gate #include <fcntl.h> 36*7c478bd9Sstevel@tonic-gate #include <strings.h> 37*7c478bd9Sstevel@tonic-gate #include <sys/mem.h> 38*7c478bd9Sstevel@tonic-gate #include <sys/stat.h> 39*7c478bd9Sstevel@tonic-gate #include <sys/mman.h> 40*7c478bd9Sstevel@tonic-gate #include <sys/dumphdr.h> 41*7c478bd9Sstevel@tonic-gate #include <sys/sysmacros.h> 42*7c478bd9Sstevel@tonic-gate 43*7c478bd9Sstevel@tonic-gate struct _kvmd { 44*7c478bd9Sstevel@tonic-gate struct dumphdr kvm_dump; 45*7c478bd9Sstevel@tonic-gate char *kvm_debug; 46*7c478bd9Sstevel@tonic-gate int kvm_openflag; 47*7c478bd9Sstevel@tonic-gate int kvm_corefd; 48*7c478bd9Sstevel@tonic-gate int kvm_kmemfd; 49*7c478bd9Sstevel@tonic-gate int kvm_memfd; 50*7c478bd9Sstevel@tonic-gate size_t kvm_coremapsize; 51*7c478bd9Sstevel@tonic-gate char *kvm_core; 52*7c478bd9Sstevel@tonic-gate dump_map_t *kvm_map; 53*7c478bd9Sstevel@tonic-gate pfn_t *kvm_pfn; 54*7c478bd9Sstevel@tonic-gate struct as *kvm_kas; 55*7c478bd9Sstevel@tonic-gate proc_t *kvm_practive; 56*7c478bd9Sstevel@tonic-gate pid_t kvm_pid; 57*7c478bd9Sstevel@tonic-gate char kvm_namelist[MAXNAMELEN + 1]; 58*7c478bd9Sstevel@tonic-gate proc_t kvm_proc; 59*7c478bd9Sstevel@tonic-gate }; 60*7c478bd9Sstevel@tonic-gate 61*7c478bd9Sstevel@tonic-gate #define PREAD (ssize_t (*)(int, void *, size_t, offset_t))pread64 62*7c478bd9Sstevel@tonic-gate #define PWRITE (ssize_t (*)(int, void *, size_t, offset_t))pwrite64 63*7c478bd9Sstevel@tonic-gate 64*7c478bd9Sstevel@tonic-gate static kvm_t * 65*7c478bd9Sstevel@tonic-gate fail(kvm_t *kd, const char *err, const char *message, ...) 66*7c478bd9Sstevel@tonic-gate { 67*7c478bd9Sstevel@tonic-gate va_list args; 68*7c478bd9Sstevel@tonic-gate 69*7c478bd9Sstevel@tonic-gate va_start(args, message); 70*7c478bd9Sstevel@tonic-gate if (err || (kd && kd->kvm_debug)) { 71*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "%s: ", err ? err : "KVM_DEBUG"); 72*7c478bd9Sstevel@tonic-gate (void) vfprintf(stderr, message, args); 73*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "\n"); 74*7c478bd9Sstevel@tonic-gate } 75*7c478bd9Sstevel@tonic-gate va_end(args); 76*7c478bd9Sstevel@tonic-gate if (kd != NULL) 77*7c478bd9Sstevel@tonic-gate (void) kvm_close(kd); 78*7c478bd9Sstevel@tonic-gate return (NULL); 79*7c478bd9Sstevel@tonic-gate } 80*7c478bd9Sstevel@tonic-gate 81*7c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 82*7c478bd9Sstevel@tonic-gate kvm_t * 83*7c478bd9Sstevel@tonic-gate kvm_open(const char *namelist, const char *corefile, const char *swapfile, 84*7c478bd9Sstevel@tonic-gate int flag, const char *err) 85*7c478bd9Sstevel@tonic-gate { 86*7c478bd9Sstevel@tonic-gate kvm_t *kd; 87*7c478bd9Sstevel@tonic-gate struct stat64 memstat, kmemstat, allkmemstat, corestat; 88*7c478bd9Sstevel@tonic-gate struct nlist nl[3] = { { "kas" }, { "practive" }, { "" } }; 89*7c478bd9Sstevel@tonic-gate 90*7c478bd9Sstevel@tonic-gate if ((kd = calloc(1, sizeof (kvm_t))) == NULL) 91*7c478bd9Sstevel@tonic-gate return (fail(NULL, err, "cannot allocate space for kvm_t")); 92*7c478bd9Sstevel@tonic-gate 93*7c478bd9Sstevel@tonic-gate kd->kvm_corefd = kd->kvm_kmemfd = kd->kvm_memfd = -1; 94*7c478bd9Sstevel@tonic-gate kd->kvm_debug = getenv("KVM_DEBUG"); 95*7c478bd9Sstevel@tonic-gate 96*7c478bd9Sstevel@tonic-gate if ((kd->kvm_openflag = flag) != O_RDONLY && flag != O_RDWR) 97*7c478bd9Sstevel@tonic-gate return (fail(kd, err, "illegal flag 0x%x to kvm_open()", flag)); 98*7c478bd9Sstevel@tonic-gate 99*7c478bd9Sstevel@tonic-gate if (corefile == NULL) 100*7c478bd9Sstevel@tonic-gate corefile = "/dev/kmem"; 101*7c478bd9Sstevel@tonic-gate 102*7c478bd9Sstevel@tonic-gate if (stat64(corefile, &corestat) == -1) 103*7c478bd9Sstevel@tonic-gate return (fail(kd, err, "cannot stat %s", corefile)); 104*7c478bd9Sstevel@tonic-gate 105*7c478bd9Sstevel@tonic-gate if (S_ISCHR(corestat.st_mode)) { 106*7c478bd9Sstevel@tonic-gate if (stat64("/dev/mem", &memstat) == -1) 107*7c478bd9Sstevel@tonic-gate return (fail(kd, err, "cannot stat /dev/mem")); 108*7c478bd9Sstevel@tonic-gate 109*7c478bd9Sstevel@tonic-gate if (stat64("/dev/kmem", &kmemstat) == -1) 110*7c478bd9Sstevel@tonic-gate return (fail(kd, err, "cannot stat /dev/kmem")); 111*7c478bd9Sstevel@tonic-gate 112*7c478bd9Sstevel@tonic-gate if (stat64("/dev/allkmem", &allkmemstat) == -1) 113*7c478bd9Sstevel@tonic-gate return (fail(kd, err, "cannot stat /dev/allkmem")); 114*7c478bd9Sstevel@tonic-gate if (corestat.st_rdev == memstat.st_rdev || 115*7c478bd9Sstevel@tonic-gate corestat.st_rdev == kmemstat.st_rdev || 116*7c478bd9Sstevel@tonic-gate corestat.st_rdev == allkmemstat.st_rdev) { 117*7c478bd9Sstevel@tonic-gate char *kmem = (corestat.st_rdev == allkmemstat.st_rdev ? 118*7c478bd9Sstevel@tonic-gate "/dev/allkmem" : "/dev/kmem"); 119*7c478bd9Sstevel@tonic-gate 120*7c478bd9Sstevel@tonic-gate if ((kd->kvm_kmemfd = open64(kmem, flag)) == -1) 121*7c478bd9Sstevel@tonic-gate return (fail(kd, err, "cannot open %s", kmem)); 122*7c478bd9Sstevel@tonic-gate if ((kd->kvm_memfd = open64("/dev/mem", flag)) == -1) 123*7c478bd9Sstevel@tonic-gate return (fail(kd, err, "cannot open /dev/mem")); 124*7c478bd9Sstevel@tonic-gate } 125*7c478bd9Sstevel@tonic-gate } else { 126*7c478bd9Sstevel@tonic-gate if ((kd->kvm_corefd = open64(corefile, flag)) == -1) 127*7c478bd9Sstevel@tonic-gate return (fail(kd, err, "cannot open %s", corefile)); 128*7c478bd9Sstevel@tonic-gate if (pread64(kd->kvm_corefd, &kd->kvm_dump, 129*7c478bd9Sstevel@tonic-gate sizeof (kd->kvm_dump), 0) != sizeof (kd->kvm_dump)) 130*7c478bd9Sstevel@tonic-gate return (fail(kd, err, "cannot read dump header")); 131*7c478bd9Sstevel@tonic-gate if (kd->kvm_dump.dump_magic != DUMP_MAGIC) 132*7c478bd9Sstevel@tonic-gate return (fail(kd, err, "%s is not a kernel core file " 133*7c478bd9Sstevel@tonic-gate "(bad magic number %x)", corefile, 134*7c478bd9Sstevel@tonic-gate kd->kvm_dump.dump_magic)); 135*7c478bd9Sstevel@tonic-gate if (kd->kvm_dump.dump_version != DUMP_VERSION) 136*7c478bd9Sstevel@tonic-gate return (fail(kd, err, 137*7c478bd9Sstevel@tonic-gate "libkvm version (%u) != corefile version (%u)", 138*7c478bd9Sstevel@tonic-gate DUMP_VERSION, kd->kvm_dump.dump_version)); 139*7c478bd9Sstevel@tonic-gate if (kd->kvm_dump.dump_wordsize != DUMP_WORDSIZE) 140*7c478bd9Sstevel@tonic-gate return (fail(kd, err, "%s is a %d-bit core file - " 141*7c478bd9Sstevel@tonic-gate "cannot examine with %d-bit libkvm", corefile, 142*7c478bd9Sstevel@tonic-gate kd->kvm_dump.dump_wordsize, DUMP_WORDSIZE)); 143*7c478bd9Sstevel@tonic-gate /* 144*7c478bd9Sstevel@tonic-gate * We try to mmap(2) the entire corefile for performance 145*7c478bd9Sstevel@tonic-gate * (so we can use bcopy(3C) rather than pread(2)). Failing 146*7c478bd9Sstevel@tonic-gate * that, we insist on at least mmap(2)ing the dump map. 147*7c478bd9Sstevel@tonic-gate */ 148*7c478bd9Sstevel@tonic-gate kd->kvm_coremapsize = (size_t)corestat.st_size; 149*7c478bd9Sstevel@tonic-gate if (corestat.st_size > LONG_MAX || 150*7c478bd9Sstevel@tonic-gate (kd->kvm_core = mmap64(0, kd->kvm_coremapsize, 151*7c478bd9Sstevel@tonic-gate PROT_READ, MAP_SHARED, kd->kvm_corefd, 0)) == MAP_FAILED) { 152*7c478bd9Sstevel@tonic-gate kd->kvm_coremapsize = kd->kvm_dump.dump_data; 153*7c478bd9Sstevel@tonic-gate if ((kd->kvm_core = mmap64(0, kd->kvm_coremapsize, 154*7c478bd9Sstevel@tonic-gate PROT_READ, MAP_SHARED, kd->kvm_corefd, 0)) == 155*7c478bd9Sstevel@tonic-gate MAP_FAILED) 156*7c478bd9Sstevel@tonic-gate return (fail(kd, err, "cannot mmap corefile")); 157*7c478bd9Sstevel@tonic-gate } 158*7c478bd9Sstevel@tonic-gate kd->kvm_map = (void *)(kd->kvm_core + kd->kvm_dump.dump_map); 159*7c478bd9Sstevel@tonic-gate kd->kvm_pfn = (void *)(kd->kvm_core + kd->kvm_dump.dump_pfn); 160*7c478bd9Sstevel@tonic-gate } 161*7c478bd9Sstevel@tonic-gate 162*7c478bd9Sstevel@tonic-gate if (namelist == NULL) 163*7c478bd9Sstevel@tonic-gate namelist = "/dev/ksyms"; 164*7c478bd9Sstevel@tonic-gate 165*7c478bd9Sstevel@tonic-gate (void) strncpy(kd->kvm_namelist, namelist, MAXNAMELEN); 166*7c478bd9Sstevel@tonic-gate 167*7c478bd9Sstevel@tonic-gate if (kvm_nlist(kd, nl) == -1) 168*7c478bd9Sstevel@tonic-gate return (fail(kd, err, "%s is not a %d-bit kernel namelist", 169*7c478bd9Sstevel@tonic-gate namelist, DUMP_WORDSIZE)); 170*7c478bd9Sstevel@tonic-gate 171*7c478bd9Sstevel@tonic-gate kd->kvm_kas = (struct as *)nl[0].n_value; 172*7c478bd9Sstevel@tonic-gate kd->kvm_practive = (proc_t *)nl[1].n_value; 173*7c478bd9Sstevel@tonic-gate 174*7c478bd9Sstevel@tonic-gate (void) kvm_setproc(kd); 175*7c478bd9Sstevel@tonic-gate return (kd); 176*7c478bd9Sstevel@tonic-gate } 177*7c478bd9Sstevel@tonic-gate 178*7c478bd9Sstevel@tonic-gate int 179*7c478bd9Sstevel@tonic-gate kvm_close(kvm_t *kd) 180*7c478bd9Sstevel@tonic-gate { 181*7c478bd9Sstevel@tonic-gate if (kd->kvm_core != NULL && kd->kvm_core != MAP_FAILED) 182*7c478bd9Sstevel@tonic-gate (void) munmap(kd->kvm_core, kd->kvm_coremapsize); 183*7c478bd9Sstevel@tonic-gate if (kd->kvm_corefd != -1) 184*7c478bd9Sstevel@tonic-gate (void) close(kd->kvm_corefd); 185*7c478bd9Sstevel@tonic-gate if (kd->kvm_kmemfd != -1) 186*7c478bd9Sstevel@tonic-gate (void) close(kd->kvm_kmemfd); 187*7c478bd9Sstevel@tonic-gate if (kd->kvm_memfd != -1) 188*7c478bd9Sstevel@tonic-gate (void) close(kd->kvm_memfd); 189*7c478bd9Sstevel@tonic-gate free(kd); 190*7c478bd9Sstevel@tonic-gate return (0); 191*7c478bd9Sstevel@tonic-gate } 192*7c478bd9Sstevel@tonic-gate 193*7c478bd9Sstevel@tonic-gate int 194*7c478bd9Sstevel@tonic-gate kvm_nlist(kvm_t *kd, struct nlist nl[]) 195*7c478bd9Sstevel@tonic-gate { 196*7c478bd9Sstevel@tonic-gate return (nlist(kd->kvm_namelist, nl)); 197*7c478bd9Sstevel@tonic-gate } 198*7c478bd9Sstevel@tonic-gate 199*7c478bd9Sstevel@tonic-gate static offset_t 200*7c478bd9Sstevel@tonic-gate kvm_lookup(kvm_t *kd, struct as *as, uint64_t addr) 201*7c478bd9Sstevel@tonic-gate { 202*7c478bd9Sstevel@tonic-gate uintptr_t pageoff = addr & (kd->kvm_dump.dump_pagesize - 1); 203*7c478bd9Sstevel@tonic-gate uint64_t page = addr - pageoff; 204*7c478bd9Sstevel@tonic-gate offset_t off = 0; 205*7c478bd9Sstevel@tonic-gate 206*7c478bd9Sstevel@tonic-gate if (kd->kvm_debug) 207*7c478bd9Sstevel@tonic-gate fprintf(stderr, "kvm_lookup(%p, %llx):", (void *)as, addr); 208*7c478bd9Sstevel@tonic-gate 209*7c478bd9Sstevel@tonic-gate if (as == NULL) { /* physical addressing mode */ 210*7c478bd9Sstevel@tonic-gate long first = 0; 211*7c478bd9Sstevel@tonic-gate long last = kd->kvm_dump.dump_npages - 1; 212*7c478bd9Sstevel@tonic-gate pfn_t target = (pfn_t)(page >> kd->kvm_dump.dump_pageshift); 213*7c478bd9Sstevel@tonic-gate while (last >= first) { 214*7c478bd9Sstevel@tonic-gate long middle = (first + last) / 2; 215*7c478bd9Sstevel@tonic-gate pfn_t pfn = kd->kvm_pfn[middle]; 216*7c478bd9Sstevel@tonic-gate if (kd->kvm_debug) 217*7c478bd9Sstevel@tonic-gate fprintf(stderr, " %ld ->", middle); 218*7c478bd9Sstevel@tonic-gate if (pfn == target) { 219*7c478bd9Sstevel@tonic-gate off = kd->kvm_dump.dump_data + pageoff + 220*7c478bd9Sstevel@tonic-gate ((uint64_t)middle << 221*7c478bd9Sstevel@tonic-gate kd->kvm_dump.dump_pageshift); 222*7c478bd9Sstevel@tonic-gate break; 223*7c478bd9Sstevel@tonic-gate } 224*7c478bd9Sstevel@tonic-gate if (pfn < target) 225*7c478bd9Sstevel@tonic-gate first = middle + 1; 226*7c478bd9Sstevel@tonic-gate else 227*7c478bd9Sstevel@tonic-gate last = middle - 1; 228*7c478bd9Sstevel@tonic-gate } 229*7c478bd9Sstevel@tonic-gate } else { 230*7c478bd9Sstevel@tonic-gate long hash = DUMP_HASH(&kd->kvm_dump, as, page); 231*7c478bd9Sstevel@tonic-gate off = kd->kvm_map[hash].dm_first; 232*7c478bd9Sstevel@tonic-gate while (off != 0) { 233*7c478bd9Sstevel@tonic-gate dump_map_t *dmp = (void *)(kd->kvm_core + off); 234*7c478bd9Sstevel@tonic-gate if (kd->kvm_debug) 235*7c478bd9Sstevel@tonic-gate fprintf(stderr, " %llx ->", off); 236*7c478bd9Sstevel@tonic-gate if (dmp < kd->kvm_map || 237*7c478bd9Sstevel@tonic-gate dmp > kd->kvm_map + kd->kvm_dump.dump_hashmask || 238*7c478bd9Sstevel@tonic-gate (off & (sizeof (offset_t) - 1)) != 0 || 239*7c478bd9Sstevel@tonic-gate DUMP_HASH(&kd->kvm_dump, dmp->dm_as, dmp->dm_va) != 240*7c478bd9Sstevel@tonic-gate hash) { 241*7c478bd9Sstevel@tonic-gate if (kd->kvm_debug) 242*7c478bd9Sstevel@tonic-gate fprintf(stderr, " dump map corrupt\n"); 243*7c478bd9Sstevel@tonic-gate return (0); 244*7c478bd9Sstevel@tonic-gate } 245*7c478bd9Sstevel@tonic-gate if (dmp->dm_va == page && dmp->dm_as == as) { 246*7c478bd9Sstevel@tonic-gate off = dmp->dm_data + pageoff; 247*7c478bd9Sstevel@tonic-gate break; 248*7c478bd9Sstevel@tonic-gate } 249*7c478bd9Sstevel@tonic-gate off = dmp->dm_next; 250*7c478bd9Sstevel@tonic-gate } 251*7c478bd9Sstevel@tonic-gate } 252*7c478bd9Sstevel@tonic-gate if (kd->kvm_debug) 253*7c478bd9Sstevel@tonic-gate fprintf(stderr, "%s found: %llx\n", off ? "" : " not", off); 254*7c478bd9Sstevel@tonic-gate return (off); 255*7c478bd9Sstevel@tonic-gate } 256*7c478bd9Sstevel@tonic-gate 257*7c478bd9Sstevel@tonic-gate static ssize_t 258*7c478bd9Sstevel@tonic-gate kvm_rw(kvm_t *kd, uint64_t addr, void *buf, size_t size, 259*7c478bd9Sstevel@tonic-gate struct as *as, ssize_t (*prw)(int, void *, size_t, offset_t)) 260*7c478bd9Sstevel@tonic-gate { 261*7c478bd9Sstevel@tonic-gate offset_t off; 262*7c478bd9Sstevel@tonic-gate size_t resid = size; 263*7c478bd9Sstevel@tonic-gate 264*7c478bd9Sstevel@tonic-gate /* 265*7c478bd9Sstevel@tonic-gate * read/write of zero bytes always succeeds 266*7c478bd9Sstevel@tonic-gate */ 267*7c478bd9Sstevel@tonic-gate if (size == 0) 268*7c478bd9Sstevel@tonic-gate return (0); 269*7c478bd9Sstevel@tonic-gate 270*7c478bd9Sstevel@tonic-gate if (kd->kvm_core == NULL) { 271*7c478bd9Sstevel@tonic-gate char procbuf[100]; 272*7c478bd9Sstevel@tonic-gate int procfd; 273*7c478bd9Sstevel@tonic-gate ssize_t rval; 274*7c478bd9Sstevel@tonic-gate 275*7c478bd9Sstevel@tonic-gate if (as == kd->kvm_kas) 276*7c478bd9Sstevel@tonic-gate return (prw(kd->kvm_kmemfd, buf, size, addr)); 277*7c478bd9Sstevel@tonic-gate if (as == NULL) 278*7c478bd9Sstevel@tonic-gate return (prw(kd->kvm_memfd, buf, size, addr)); 279*7c478bd9Sstevel@tonic-gate 280*7c478bd9Sstevel@tonic-gate (void) sprintf(procbuf, "/proc/%ld/as", kd->kvm_pid); 281*7c478bd9Sstevel@tonic-gate if ((procfd = open64(procbuf, kd->kvm_openflag)) == -1) 282*7c478bd9Sstevel@tonic-gate return (-1); 283*7c478bd9Sstevel@tonic-gate rval = prw(procfd, buf, size, addr); 284*7c478bd9Sstevel@tonic-gate (void) close(procfd); 285*7c478bd9Sstevel@tonic-gate return (rval); 286*7c478bd9Sstevel@tonic-gate } 287*7c478bd9Sstevel@tonic-gate 288*7c478bd9Sstevel@tonic-gate while (resid != 0) { 289*7c478bd9Sstevel@tonic-gate uintptr_t pageoff = addr & (kd->kvm_dump.dump_pagesize - 1); 290*7c478bd9Sstevel@tonic-gate ssize_t len = MIN(resid, kd->kvm_dump.dump_pagesize - pageoff); 291*7c478bd9Sstevel@tonic-gate 292*7c478bd9Sstevel@tonic-gate if ((off = kvm_lookup(kd, as, addr)) == 0) 293*7c478bd9Sstevel@tonic-gate break; 294*7c478bd9Sstevel@tonic-gate 295*7c478bd9Sstevel@tonic-gate if (prw == PREAD && off < kd->kvm_coremapsize) 296*7c478bd9Sstevel@tonic-gate bcopy(kd->kvm_core + off, buf, len); 297*7c478bd9Sstevel@tonic-gate else if ((len = prw(kd->kvm_corefd, buf, len, off)) <= 0) 298*7c478bd9Sstevel@tonic-gate break; 299*7c478bd9Sstevel@tonic-gate resid -= len; 300*7c478bd9Sstevel@tonic-gate addr += len; 301*7c478bd9Sstevel@tonic-gate buf = (char *)buf + len; 302*7c478bd9Sstevel@tonic-gate } 303*7c478bd9Sstevel@tonic-gate return (resid < size ? size - resid : -1); 304*7c478bd9Sstevel@tonic-gate } 305*7c478bd9Sstevel@tonic-gate 306*7c478bd9Sstevel@tonic-gate ssize_t 307*7c478bd9Sstevel@tonic-gate kvm_read(kvm_t *kd, uintptr_t addr, void *buf, size_t size) 308*7c478bd9Sstevel@tonic-gate { 309*7c478bd9Sstevel@tonic-gate return (kvm_rw(kd, addr, buf, size, kd->kvm_kas, PREAD)); 310*7c478bd9Sstevel@tonic-gate } 311*7c478bd9Sstevel@tonic-gate 312*7c478bd9Sstevel@tonic-gate ssize_t 313*7c478bd9Sstevel@tonic-gate kvm_kread(kvm_t *kd, uintptr_t addr, void *buf, size_t size) 314*7c478bd9Sstevel@tonic-gate { 315*7c478bd9Sstevel@tonic-gate return (kvm_rw(kd, addr, buf, size, kd->kvm_kas, PREAD)); 316*7c478bd9Sstevel@tonic-gate } 317*7c478bd9Sstevel@tonic-gate 318*7c478bd9Sstevel@tonic-gate ssize_t 319*7c478bd9Sstevel@tonic-gate kvm_uread(kvm_t *kd, uintptr_t addr, void *buf, size_t size) 320*7c478bd9Sstevel@tonic-gate { 321*7c478bd9Sstevel@tonic-gate return (kvm_rw(kd, addr, buf, size, kd->kvm_proc.p_as, PREAD)); 322*7c478bd9Sstevel@tonic-gate } 323*7c478bd9Sstevel@tonic-gate 324*7c478bd9Sstevel@tonic-gate ssize_t 325*7c478bd9Sstevel@tonic-gate kvm_aread(kvm_t *kd, uintptr_t addr, void *buf, size_t size, struct as *as) 326*7c478bd9Sstevel@tonic-gate { 327*7c478bd9Sstevel@tonic-gate return (kvm_rw(kd, addr, buf, size, as, PREAD)); 328*7c478bd9Sstevel@tonic-gate } 329*7c478bd9Sstevel@tonic-gate 330*7c478bd9Sstevel@tonic-gate ssize_t 331*7c478bd9Sstevel@tonic-gate kvm_pread(kvm_t *kd, uint64_t addr, void *buf, size_t size) 332*7c478bd9Sstevel@tonic-gate { 333*7c478bd9Sstevel@tonic-gate return (kvm_rw(kd, addr, buf, size, NULL, PREAD)); 334*7c478bd9Sstevel@tonic-gate } 335*7c478bd9Sstevel@tonic-gate 336*7c478bd9Sstevel@tonic-gate ssize_t 337*7c478bd9Sstevel@tonic-gate kvm_write(kvm_t *kd, uintptr_t addr, const void *buf, size_t size) 338*7c478bd9Sstevel@tonic-gate { 339*7c478bd9Sstevel@tonic-gate return (kvm_rw(kd, addr, (void *)buf, size, kd->kvm_kas, PWRITE)); 340*7c478bd9Sstevel@tonic-gate } 341*7c478bd9Sstevel@tonic-gate 342*7c478bd9Sstevel@tonic-gate ssize_t 343*7c478bd9Sstevel@tonic-gate kvm_kwrite(kvm_t *kd, uintptr_t addr, const void *buf, size_t size) 344*7c478bd9Sstevel@tonic-gate { 345*7c478bd9Sstevel@tonic-gate return (kvm_rw(kd, addr, (void *)buf, size, kd->kvm_kas, PWRITE)); 346*7c478bd9Sstevel@tonic-gate } 347*7c478bd9Sstevel@tonic-gate 348*7c478bd9Sstevel@tonic-gate ssize_t 349*7c478bd9Sstevel@tonic-gate kvm_uwrite(kvm_t *kd, uintptr_t addr, const void *buf, size_t size) 350*7c478bd9Sstevel@tonic-gate { 351*7c478bd9Sstevel@tonic-gate return (kvm_rw(kd, addr, (void *)buf, size, kd->kvm_proc.p_as, PWRITE)); 352*7c478bd9Sstevel@tonic-gate } 353*7c478bd9Sstevel@tonic-gate 354*7c478bd9Sstevel@tonic-gate ssize_t 355*7c478bd9Sstevel@tonic-gate kvm_awrite(kvm_t *kd, uintptr_t addr, const void *buf, size_t size, 356*7c478bd9Sstevel@tonic-gate struct as *as) 357*7c478bd9Sstevel@tonic-gate { 358*7c478bd9Sstevel@tonic-gate return (kvm_rw(kd, addr, (void *)buf, size, as, PWRITE)); 359*7c478bd9Sstevel@tonic-gate } 360*7c478bd9Sstevel@tonic-gate 361*7c478bd9Sstevel@tonic-gate ssize_t 362*7c478bd9Sstevel@tonic-gate kvm_pwrite(kvm_t *kd, uint64_t addr, const void *buf, size_t size) 363*7c478bd9Sstevel@tonic-gate { 364*7c478bd9Sstevel@tonic-gate return (kvm_rw(kd, addr, (void *)buf, size, NULL, PWRITE)); 365*7c478bd9Sstevel@tonic-gate } 366*7c478bd9Sstevel@tonic-gate 367*7c478bd9Sstevel@tonic-gate uint64_t 368*7c478bd9Sstevel@tonic-gate kvm_physaddr(kvm_t *kd, struct as *as, uintptr_t addr) 369*7c478bd9Sstevel@tonic-gate { 370*7c478bd9Sstevel@tonic-gate mem_vtop_t mem_vtop; 371*7c478bd9Sstevel@tonic-gate offset_t off; 372*7c478bd9Sstevel@tonic-gate 373*7c478bd9Sstevel@tonic-gate if (kd->kvm_core == NULL) { 374*7c478bd9Sstevel@tonic-gate mem_vtop.m_as = as; 375*7c478bd9Sstevel@tonic-gate mem_vtop.m_va = (void *)addr; 376*7c478bd9Sstevel@tonic-gate if (ioctl(kd->kvm_kmemfd, MEM_VTOP, &mem_vtop) == 0) 377*7c478bd9Sstevel@tonic-gate return ((uint64_t)mem_vtop.m_pfn * getpagesize() + 378*7c478bd9Sstevel@tonic-gate (addr & (getpagesize() - 1))); 379*7c478bd9Sstevel@tonic-gate } else { 380*7c478bd9Sstevel@tonic-gate if ((off = kvm_lookup(kd, as, addr)) != 0) { 381*7c478bd9Sstevel@tonic-gate long pfn_index = 382*7c478bd9Sstevel@tonic-gate (u_offset_t)(off - kd->kvm_dump.dump_data) >> 383*7c478bd9Sstevel@tonic-gate kd->kvm_dump.dump_pageshift; 384*7c478bd9Sstevel@tonic-gate return (((uint64_t)kd->kvm_pfn[pfn_index] << 385*7c478bd9Sstevel@tonic-gate kd->kvm_dump.dump_pageshift) + 386*7c478bd9Sstevel@tonic-gate (addr & (kd->kvm_dump.dump_pagesize - 1))); 387*7c478bd9Sstevel@tonic-gate } 388*7c478bd9Sstevel@tonic-gate } 389*7c478bd9Sstevel@tonic-gate return (-1ULL); 390*7c478bd9Sstevel@tonic-gate } 391*7c478bd9Sstevel@tonic-gate 392*7c478bd9Sstevel@tonic-gate struct proc * 393*7c478bd9Sstevel@tonic-gate kvm_getproc(kvm_t *kd, pid_t pid) 394*7c478bd9Sstevel@tonic-gate { 395*7c478bd9Sstevel@tonic-gate (void) kvm_setproc(kd); 396*7c478bd9Sstevel@tonic-gate while (kvm_nextproc(kd) != NULL) 397*7c478bd9Sstevel@tonic-gate if (kd->kvm_pid == pid) 398*7c478bd9Sstevel@tonic-gate return (&kd->kvm_proc); 399*7c478bd9Sstevel@tonic-gate return (NULL); 400*7c478bd9Sstevel@tonic-gate } 401*7c478bd9Sstevel@tonic-gate 402*7c478bd9Sstevel@tonic-gate struct proc * 403*7c478bd9Sstevel@tonic-gate kvm_nextproc(kvm_t *kd) 404*7c478bd9Sstevel@tonic-gate { 405*7c478bd9Sstevel@tonic-gate if (kd->kvm_proc.p_next == NULL || 406*7c478bd9Sstevel@tonic-gate kvm_kread(kd, (uintptr_t)kd->kvm_proc.p_next, 407*7c478bd9Sstevel@tonic-gate &kd->kvm_proc, sizeof (proc_t)) != sizeof (proc_t) || 408*7c478bd9Sstevel@tonic-gate kvm_kread(kd, (uintptr_t)&kd->kvm_proc.p_pidp->pid_id, 409*7c478bd9Sstevel@tonic-gate &kd->kvm_pid, sizeof (pid_t)) != sizeof (pid_t)) 410*7c478bd9Sstevel@tonic-gate return (NULL); 411*7c478bd9Sstevel@tonic-gate 412*7c478bd9Sstevel@tonic-gate return (&kd->kvm_proc); 413*7c478bd9Sstevel@tonic-gate } 414*7c478bd9Sstevel@tonic-gate 415*7c478bd9Sstevel@tonic-gate int 416*7c478bd9Sstevel@tonic-gate kvm_setproc(kvm_t *kd) 417*7c478bd9Sstevel@tonic-gate { 418*7c478bd9Sstevel@tonic-gate (void) kvm_kread(kd, (uintptr_t)kd->kvm_practive, 419*7c478bd9Sstevel@tonic-gate &kd->kvm_proc.p_next, sizeof (proc_t *)); 420*7c478bd9Sstevel@tonic-gate kd->kvm_pid = -1; 421*7c478bd9Sstevel@tonic-gate return (0); 422*7c478bd9Sstevel@tonic-gate } 423*7c478bd9Sstevel@tonic-gate 424*7c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 425*7c478bd9Sstevel@tonic-gate struct user * 426*7c478bd9Sstevel@tonic-gate kvm_getu(kvm_t *kd, struct proc *p) 427*7c478bd9Sstevel@tonic-gate { 428*7c478bd9Sstevel@tonic-gate return (&p->p_user); 429*7c478bd9Sstevel@tonic-gate } 430