kvm.c revision 147672
11195Srgrimes/*- 22570Srgrimes * Copyright (c) 1989, 1992, 1993 337Srgrimes * The Regents of the University of California. All rights reserved. 437Srgrimes * 537Srgrimes * This code is derived from software developed by the Computer Systems 6147Srgrimes * Engineering group at Lawrence Berkeley Laboratory under DARPA contract 7147Srgrimes * BG 91-66 and contributed to Berkeley. 8147Srgrimes * 9207Snate * Redistribution and use in source and binary forms, with or without 101734Sjkh * modification, are permitted provided that the following conditions 111518Sguido * are met: 121518Sguido * 1. Redistributions of source code must retain the above copyright 131734Sjkh * notice, this list of conditions and the following disclaimer. 141734Sjkh * 2. Redistributions in binary form must reproduce the above copyright 151734Sjkh * notice, this list of conditions and the following disclaimer in the 1637Srgrimes * documentation and/or other materials provided with the distribution. 1737Srgrimes * 3. All advertising materials mentioning features or use of this software 1837Srgrimes * must display the following acknowledgement: 1937Srgrimes * This product includes software developed by the University of 201773Sjkh * California, Berkeley and its contributors. 21147Srgrimes * 4. Neither the name of the University nor the names of its contributors 22147Srgrimes * may be used to endorse or promote products derived from this software 232570Srgrimes * without specific prior written permission. 242570Srgrimes * 252570Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 261767Sjkh * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 272570Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 282570Srgrimes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 292570Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 302570Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 312570Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 322570Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 332570Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 342570Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 351782Sjkh * SUCH DAMAGE. 361782Sjkh */ 37491Srgrimes 3837Srgrimes#include <sys/cdefs.h> 3937Srgrimes__FBSDID("$FreeBSD: head/lib/libkvm/kvm.c 147672 2005-06-29 22:39:41Z peter $"); 4037Srgrimes 4137Srgrimes#if defined(LIBC_SCCS) && !defined(lint) 4237Srgrimes#if 0 43263Srgrimesstatic char sccsid[] = "@(#)kvm.c 8.2 (Berkeley) 2/13/94"; 441130Srgrimes#endif 451767Sjkh#endif /* LIBC_SCCS and not lint */ 461126Srgrimes 47993Srgrimes#include <sys/param.h> 48277Srgrimes#include <sys/user.h> 49277Srgrimes#include <sys/proc.h> 50284Srgrimes#include <sys/ioctl.h> 51463Srgrimes#include <sys/stat.h> 521205Srgrimes#include <sys/sysctl.h> 53284Srgrimes#include <sys/linker.h> 54284Srgrimes 55284Srgrimes#include <vm/vm.h> 56284Srgrimes#include <vm/vm_param.h> 57284Srgrimes 581285Srgrimes#include <machine/vmparam.h> 59284Srgrimes 601767Sjkh#include <ctype.h> 611285Srgrimes#include <fcntl.h> 622499Sgpalmer#include <kvm.h> 631285Srgrimes#include <limits.h> 64284Srgrimes#include <nlist.h> 651371Srgrimes#include <paths.h> 661371Srgrimes#include <stdio.h> 671194Srgrimes#include <stdlib.h> 68358Srgrimes#include <string.h> 69358Srgrimes#include <unistd.h> 70412Salm 71358Srgrimes#include "kvm_private.h" 72452Srgrimes 73358Srgrimes/* from src/lib/libc/gen/nlist.c */ 741194Srgrimesint __fdnlist(int, struct nlist *); 751767Sjkh 761194Srgrimeschar * 771194Srgrimeskvm_geterr(kd) 781194Srgrimes kvm_t *kd; 791194Srgrimes{ 801194Srgrimes return (kd->errbuf); 811194Srgrimes} 821194Srgrimes 831194Srgrimes#include <stdarg.h> 841194Srgrimes 851194Srgrimes/* 861194Srgrimes * Report an error using printf style arguments. "program" is kd->program 871194Srgrimes * on hard errors, and 0 on soft errors, so that under sun error emulation, 881194Srgrimes * only hard errors are printed out (otherwise, programs like gdb will 891194Srgrimes * generate tons of error messages when trying to access bogus pointers). 901194Srgrimes */ 911194Srgrimesvoid 921194Srgrimes_kvm_err(kvm_t *kd, const char *program, const char *fmt, ...) 931194Srgrimes{ 941243Srgrimes va_list ap; 95263Srgrimes 96358Srgrimes va_start(ap, fmt); 971194Srgrimes if (program != NULL) { 981194Srgrimes (void)fprintf(stderr, "%s: ", program); 991194Srgrimes (void)vfprintf(stderr, fmt, ap); 1001773Sjkh (void)fputc('\n', stderr); 1012499Sgpalmer } else 1021194Srgrimes (void)vsnprintf(kd->errbuf, 103452Srgrimes sizeof(kd->errbuf), (char *)fmt, ap); 1041194Srgrimes 1051194Srgrimes va_end(ap); 106358Srgrimes} 1071194Srgrimes 1081695Scsgrvoid 1091695Scsgr_kvm_syserr(kvm_t *kd, const char *program, const char *fmt, ...) 1101695Scsgr{ 1111695Scsgr va_list ap; 1121695Scsgr int n; 1131695Scsgr 1141695Scsgr va_start(ap, fmt); 1151243Srgrimes if (program != NULL) { 1161194Srgrimes (void)fprintf(stderr, "%s: ", program); 1171194Srgrimes (void)vfprintf(stderr, fmt, ap); 1181243Srgrimes (void)fprintf(stderr, ": %s\n", strerror(errno)); 1191243Srgrimes } else { 120284Srgrimes char *cp = kd->errbuf; 1212570Srgrimes 1222570Srgrimes (void)vsnprintf(cp, sizeof(kd->errbuf), (char *)fmt, ap); 123372Srgrimes n = strlen(cp); 124372Srgrimes (void)snprintf(&cp[n], sizeof(kd->errbuf) - n, ": %s", 125372Srgrimes strerror(errno)); 1262570Srgrimes } 1272570Srgrimes va_end(ap); 128372Srgrimes} 1291126Srgrimes 130347Srgrimesvoid * 1311767Sjkh_kvm_malloc(kd, n) 13237Srgrimes kvm_t *kd; 1332538Spst size_t n; 134347Srgrimes{ 1352538Spst void *p; 136355Srgrimes 137372Srgrimes if ((p = calloc(n, sizeof(char))) == NULL) 138347Srgrimes _kvm_err(kd, kd->program, "can't allocate %u bytes: %s", 139355Srgrimes n, strerror(errno)); 140347Srgrimes return (p); 1412538Spst} 1422538Spst 1432538Spststatic kvm_t * 1442538Spst_kvm_open(kd, uf, mf, flag, errout) 1452538Spst kvm_t *kd; 146372Srgrimes const char *uf; 147347Srgrimes const char *mf; 148355Srgrimes int flag; 149347Srgrimes char *errout; 150347Srgrimes{ 1512538Spst struct stat st; 152147Srgrimes 1531759Sjkh kd->vmfd = -1; 1541759Sjkh kd->pmfd = -1; 1551759Sjkh kd->nlfd = -1; 1561759Sjkh kd->vmst = 0; 1571759Sjkh kd->procbase = 0; 1581731Sjkh kd->argspc = 0; 1591759Sjkh kd->argv = 0; 1601731Sjkh 1611759Sjkh if (uf == 0) 1621759Sjkh uf = getbootfile(); 16337Srgrimes else if (strlen(uf) >= MAXPATHLEN) { 1641759Sjkh _kvm_err(kd, kd->program, "exec file name too long"); 165347Srgrimes goto failed; 1661759Sjkh } 167347Srgrimes if (flag & ~O_RDWR) { 1681731Sjkh _kvm_err(kd, kd->program, "bad flags arg"); 1691731Sjkh goto failed; 17037Srgrimes } 1711731Sjkh if (mf == 0) 17237Srgrimes mf = _PATH_MEM; 1731731Sjkh 17437Srgrimes if ((kd->pmfd = open(mf, flag, 0)) < 0) { 1751731Sjkh _kvm_syserr(kd, kd->program, "%s", mf); 17637Srgrimes goto failed; 17737Srgrimes } 17837Srgrimes if (fstat(kd->pmfd, &st) < 0) { 17937Srgrimes _kvm_syserr(kd, kd->program, "%s", mf); 1801731Sjkh goto failed; 1811731Sjkh } 1821731Sjkh if (fcntl(kd->pmfd, F_SETFD, FD_CLOEXEC) < 0) { 1831731Sjkh _kvm_syserr(kd, kd->program, "%s", mf); 18437Srgrimes goto failed; 18537Srgrimes } 186147Srgrimes if (S_ISCHR(st.st_mode)) { 187147Srgrimes /* 18837Srgrimes * If this is a character special device, then check that 189147Srgrimes * it's /dev/mem. If so, open kmem too. (Maybe we should 19037Srgrimes * make it work for either /dev/mem or /dev/kmem -- in either 19137Srgrimes * case you're working with a live kernel.) 19237Srgrimes */ 193288Srgrimes if (strcmp(mf, _PATH_DEVNULL) == 0) { 194288Srgrimes kd->vmfd = open(_PATH_DEVNULL, O_RDONLY); 195147Srgrimes return (kd); 19637Srgrimes } else if (strcmp(mf, _PATH_MEM) == 0) { 197147Srgrimes if ((kd->vmfd = open(_PATH_KMEM, flag)) < 0) { 198147Srgrimes _kvm_syserr(kd, kd->program, "%s", _PATH_KMEM); 19937Srgrimes goto failed; 2001759Sjkh } 2011759Sjkh if (fcntl(kd->vmfd, F_SETFD, FD_CLOEXEC) < 0) { 2021759Sjkh _kvm_syserr(kd, kd->program, "%s", _PATH_KMEM); 2031759Sjkh goto failed; 204347Srgrimes } 2052538Spst return (kd); 2062538Spst } 207347Srgrimes } 2082538Spst /* 2091775Sjkh * This is a crash dump. 210347Srgrimes * Initialize the virtual address translation machinery, 2111759Sjkh * but first setup the namelist fd. 212355Srgrimes */ 213277Srgrimes if ((kd->nlfd = open(uf, O_RDONLY, 0)) < 0) { 2141126Srgrimes _kvm_syserr(kd, kd->program, "%s", uf); 2151126Srgrimes goto failed; 2161731Sjkh } 217238Sroot if (fcntl(kd->nlfd, F_SETFD, FD_CLOEXEC) < 0) { 2181759Sjkh _kvm_syserr(kd, kd->program, "%s", uf); 2191731Sjkh goto failed; 2201759Sjkh } 2211759Sjkh if (_kvm_initvtop(kd) < 0) 222333Srgrimes goto failed; 2231759Sjkh return (kd); 2241759Sjkhfailed: 225168Srgrimes /* 226333Srgrimes * Copy out the error if doing sane error semantics. 2271759Sjkh */ 2281759Sjkh if (errout != 0) 229333Srgrimes strlcpy(errout, kd->errbuf, _POSIX2_LINE_MAX); 23037Srgrimes (void)kvm_close(kd); 2311731Sjkh return (0); 2321739Sjkh} 2331782Sjkh 2341739Sjkhkvm_t * 2351782Sjkhkvm_openfiles(uf, mf, sf, flag, errout) 2361731Sjkh const char *uf; 2371731Sjkh const char *mf; 2381731Sjkh const char *sf __unused; 2392570Srgrimes int flag; 2402570Srgrimes char *errout; 2411731Sjkh{ 2422570Srgrimes kvm_t *kd; 2432570Srgrimes 2441731Sjkh if ((kd = malloc(sizeof(*kd))) == NULL) { 2452570Srgrimes (void)strlcpy(errout, strerror(errno), _POSIX2_LINE_MAX); 2462570Srgrimes return (0); 2471731Sjkh } 24837Srgrimes memset(kd, 0, sizeof(*kd)); 2491759Sjkh kd->program = 0; 2501759Sjkh return (_kvm_open(kd, uf, mf, flag, errout)); 25137Srgrimes} 2521759Sjkh 2531759Sjkhkvm_t * 2541759Sjkhkvm_open(uf, mf, sf, flag, errstr) 2551759Sjkh const char *uf; 2561731Sjkh const char *mf; 257320Srgrimes const char *sf __unused; 2581759Sjkh int flag; 2591731Sjkh const char *errstr; 260320Srgrimes{ 261320Srgrimes kvm_t *kd; 262358Srgrimes 263568Srgrimes if ((kd = malloc(sizeof(*kd))) == NULL) { 2641672Sjkh if (errstr != NULL) 2651762Sjkh (void)fprintf(stderr, "%s: %s\n", 2661027Sache errstr, strerror(errno)); 2671027Sache return (0); 2681731Sjkh } 269333Srgrimes memset(kd, 0, sizeof(*kd)); 270284Srgrimes kd->program = errstr; 271320Srgrimes return (_kvm_open(kd, uf, mf, flag, NULL)); 2722570Srgrimes} 273284Srgrimes 274320Srgrimesint 2751731Sjkhkvm_close(kd) 2761731Sjkh kvm_t *kd; 2771731Sjkh{ 2781762Sjkh int error = 0; 2791194Srgrimes 2801194Srgrimes if (kd->pmfd >= 0) 2811194Srgrimes error |= close(kd->pmfd); 2821194Srgrimes if (kd->vmfd >= 0) 283320Srgrimes error |= close(kd->vmfd); 2841205Srgrimes if (kd->nlfd >= 0) 2852570Srgrimes error |= close(kd->nlfd); 2861759Sjkh if (kd->vmst) 2871731Sjkh _kvm_freevtop(kd); 288277Srgrimes if (kd->procbase != 0) 2891027Sache free((void *)kd->procbase); 2901027Sache if (kd->argv != 0) 2911205Srgrimes free((void *)kd->argv); 292358Srgrimes free((void *)kd); 2931205Srgrimes 2941782Sjkh return (0); 295277Srgrimes} 2961205Srgrimes 2972570Srgrimesint 2981759Sjkhkvm_nlist(kd, nl) 2991731Sjkh kvm_t *kd; 300320Srgrimes struct nlist *nl; 3011027Sache{ 3021027Sache struct nlist *p; 3031205Srgrimes int nvalid; 304358Srgrimes struct kld_sym_lookup lookup; 3051205Srgrimes 3061782Sjkh /* 307320Srgrimes * If we can't use the kld symbol lookup, revert to the 3081285Srgrimes * slow library call. 3092570Srgrimes */ 3101371Srgrimes if (!ISALIVE(kd)) 3111371Srgrimes return (__fdnlist(kd->nlfd, nl)); 3121371Srgrimes 3131371Srgrimes /* 3141371Srgrimes * We can use the kld lookup syscall. Go through each nlist entry 3151285Srgrimes * and look it up with a kldsym(2) syscall. 3161731Sjkh */ 3171285Srgrimes nvalid = 0; 3181731Sjkh for (p = nl; p->n_name && p->n_name[0]; ++p) { 3191731Sjkh lookup.version = sizeof(lookup); 3201731Sjkh lookup.symname = p->n_name; 3211731Sjkh lookup.symvalue = 0; 3221285Srgrimes lookup.symsize = 0; 3231285Srgrimes 3242570Srgrimes if (lookup.symname[0] == '_') 3251759Sjkh lookup.symname++; 3261731Sjkh 3271285Srgrimes if (kldsym(0, KLDSYM_LOOKUP, &lookup) != -1) { 3281285Srgrimes p->n_type = N_TEXT; 3291285Srgrimes p->n_other = 0; 3301285Srgrimes p->n_desc = 0; 3311285Srgrimes p->n_value = lookup.symvalue; 3321285Srgrimes ++nvalid; 3331782Sjkh /* lookup.symsize */ 3341285Srgrimes } 3351285Srgrimes } 3362570Srgrimes /* 3371759Sjkh * Return the number of entries that weren't found. 3381731Sjkh */ 3391285Srgrimes return ((p - nl) - nvalid); 3401285Srgrimes} 3411285Srgrimes 3421285Srgrimesssize_t 3431285Srgrimeskvm_read(kd, kva, buf, len) 3441285Srgrimes kvm_t *kd; 3451782Sjkh u_long kva; 3461285Srgrimes void *buf; 3471205Srgrimes size_t len; 348568Srgrimes{ 3491672Sjkh int cc; 350568Srgrimes char *cp; 3511027Sache 3521027Sache if (ISALIVE(kd)) { 3531731Sjkh /* 354333Srgrimes * We're using /dev/kmem. Just read straight from the 355284Srgrimes * device and let the active kernel do the address translation. 356358Srgrimes */ 3572570Srgrimes errno = 0; 358284Srgrimes if (lseek(kd->vmfd, (off_t)kva, 0) == -1 && errno != 0) { 3591194Srgrimes _kvm_err(kd, 0, "invalid address (%x)", kva); 3601243Srgrimes return (-1); 3611194Srgrimes } 3621194Srgrimes cc = read(kd->vmfd, buf, len); 3631731Sjkh if (cc < 0) { 3641731Sjkh _kvm_syserr(kd, 0, "kvm_read"); 3651731Sjkh return (-1); 3661731Sjkh } else if (cc < len) 3671731Sjkh _kvm_err(kd, kd->program, "short read"); 3681762Sjkh return (cc); 369284Srgrimes } else { 3701194Srgrimes cp = buf; 3711194Srgrimes while (len > 0) { 3721194Srgrimes off_t pa; 3731194Srgrimes 374358Srgrimes cc = _kvm_kvatop(kd, kva, &pa); 3751194Srgrimes if (cc == 0) 376358Srgrimes return (-1); 377358Srgrimes if (cc > len) 3781243Srgrimes cc = len; 379333Srgrimes errno = 0; 380284Srgrimes if (lseek(kd->pmfd, pa, 0) == -1 && errno != 0) { 3811027Sache _kvm_syserr(kd, 0, _PATH_MEM); 3821027Sache break; 3831205Srgrimes } 384358Srgrimes cc = read(kd->pmfd, cp, cc); 3851205Srgrimes if (cc < 0) { 3861782Sjkh _kvm_syserr(kd, kd->program, "kvm_read"); 387284Srgrimes break; 3881205Srgrimes } 389568Srgrimes /* 3901672Sjkh * If kvm_kvatop returns a bogus value or our core 391568Srgrimes * file is truncated, we might wind up seeking beyond 3921027Sache * the end of the core file in which case the read will 3931027Sache * return 0 (EOF). 3941731Sjkh */ 395333Srgrimes if (cc == 0) 396284Srgrimes break; 397358Srgrimes cp += cc; 3981769Sjkh kva += cc; 3991769Sjkh len -= cc; 4001769Sjkh } 4011773Sjkh return (cp - (char *)buf); 4021773Sjkh } 4031773Sjkh /* NOTREACHED */ 4041769Sjkh} 4051769Sjkh 4061769Sjkhssize_t 4071773Sjkhkvm_write(kd, kva, buf, len) 4081773Sjkh kvm_t *kd; 4091773Sjkh u_long kva; 410284Srgrimes const void *buf; 411444Srgrimes size_t len; 4121194Srgrimes{ 4131194Srgrimes int cc; 4141773Sjkh 4151769Sjkh if (ISALIVE(kd)) { 4161773Sjkh /* 4171773Sjkh * Just like kvm_read, only we write. 4181731Sjkh */ 4191731Sjkh errno = 0; 4201731Sjkh if (lseek(kd->vmfd, (off_t)kva, 0) == -1 && errno != 0) { 4211731Sjkh _kvm_err(kd, 0, "invalid address (%x)", kva); 4221731Sjkh return (-1); 4231731Sjkh } 424284Srgrimes cc = write(kd->vmfd, buf, len); 4251027Sache if (cc < 0) { 4261027Sache _kvm_syserr(kd, 0, "kvm_write"); 4271205Srgrimes return (-1); 428358Srgrimes } else if (cc < len) 4291205Srgrimes _kvm_err(kd, kd->program, "short write"); 4301782Sjkh return (cc); 431284Srgrimes } else { 432372Srgrimes _kvm_err(kd, kd->program, 433372Srgrimes "kvm_write not implemented for dead kernels"); 434538Srgrimes return (-1); 4351782Sjkh } 436372Srgrimes /* NOTREACHED */ 4371782Sjkh} 4382570Srgrimes