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