diff options
| author | Rodney W. Grimes <rgrimes@FreeBSD.org> | 1994-05-27 05:00:24 +0000 | 
|---|---|---|
| committer | Rodney W. Grimes <rgrimes@FreeBSD.org> | 1994-05-27 05:00:24 +0000 | 
| commit | 58f0484fa251c266ede97b591b499fe3dd4f578e (patch) | |
| tree | 41932a7161f4cd72005330a9c69747e7bab2ee5b /lib/libkvm | |
| parent | fb49e767ba942f74b1cee8814e085e5f2615ac53 (diff) | |
Notes
Diffstat (limited to 'lib/libkvm')
| -rw-r--r-- | lib/libkvm/Makefile | 14 | ||||
| -rw-r--r-- | lib/libkvm/kvm.3 | 101 | ||||
| -rw-r--r-- | lib/libkvm/kvm.c | 540 | ||||
| -rw-r--r-- | lib/libkvm/kvm_file.c | 188 | ||||
| -rw-r--r-- | lib/libkvm/kvm_geterr.3 | 80 | ||||
| -rw-r--r-- | lib/libkvm/kvm_getfiles.3 | 86 | ||||
| -rw-r--r-- | lib/libkvm/kvm_getloadavg.3 | 65 | ||||
| -rw-r--r-- | lib/libkvm/kvm_getloadavg.c | 105 | ||||
| -rw-r--r-- | lib/libkvm/kvm_getprocs.3 | 163 | ||||
| -rw-r--r-- | lib/libkvm/kvm_hp300.c | 286 | ||||
| -rw-r--r-- | lib/libkvm/kvm_mips.c | 207 | ||||
| -rw-r--r-- | lib/libkvm/kvm_nlist.3 | 88 | ||||
| -rw-r--r-- | lib/libkvm/kvm_open.3 | 186 | ||||
| -rw-r--r-- | lib/libkvm/kvm_private.h | 81 | ||||
| -rw-r--r-- | lib/libkvm/kvm_proc.c | 705 | ||||
| -rw-r--r-- | lib/libkvm/kvm_read.3 | 92 | ||||
| -rw-r--r-- | lib/libkvm/kvm_sparc.c | 236 | 
17 files changed, 3223 insertions, 0 deletions
| diff --git a/lib/libkvm/Makefile b/lib/libkvm/Makefile new file mode 100644 index 000000000000..db3621d66ef1 --- /dev/null +++ b/lib/libkvm/Makefile @@ -0,0 +1,14 @@ +#	@(#)Makefile	8.1 (Berkeley) 6/4/93 + +LIB=	kvm +CFLAGS+=-DLIBC_SCCS -I/sys +SRCS=	kvm.c kvm_${MACHINE}.c kvm_file.c kvm_getloadavg.c kvm_proc.c + +MAN3=	kvm.0 kvm_geterr.0 kvm_getfiles.0 kvm_getloadavg.0 kvm_getprocs.0 \ +	kvm_nlist.0 kvm_open.0 kvm_read.0 + +MLINKS+=kvm_getprocs.3 kvm_getargv.3 kvm_getprocs.3 kvm_getenvv.3 +MLINKS+=kvm_open.3 kvm_openfiles.3 kvm_open.3 kvm_close.3 +MLINKS+=kvm_read.3 kvm_write.3 + +.include <bsd.lib.mk> diff --git a/lib/libkvm/kvm.3 b/lib/libkvm/kvm.3 new file mode 100644 index 000000000000..0343d46907f5 --- /dev/null +++ b/lib/libkvm/kvm.3 @@ -0,0 +1,101 @@ +.\" Copyright (c) 1992, 1993 +.\"	The Regents of the University of California.  All rights reserved. +.\" +.\" This code is derived from software developed by the Computer Systems +.\" Engineering group at Lawrence Berkeley Laboratory under DARPA contract +.\" BG 91-66 and contributed to Berkeley. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\"    notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\"    notice, this list of conditions and the following disclaimer in the +.\"    documentation and/or other materials provided with the distribution. +.\" 3. All advertising materials mentioning features or use of this software +.\"    must display the following acknowledgement: +.\"	This product includes software developed by the University of +.\"	California, Berkeley and its contributors. +.\" 4. Neither the name of the University nor the names of its contributors +.\"    may be used to endorse or promote products derived from this software +.\"    without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\"     @(#)kvm.3	8.1 (Berkeley) 6/4/93 +.\" +.Dd June 4, 1993 +.Dt KVM 3 +.Os +.Sh NAME +.Nm kvm +.Nd kernel memory interface +.Sh DESCRIPTION +The +.Xr kvm 3 +library provides a uniform interface for accessing kernel virtual memory +images, including live systems and crashdumps. +Access to live systems is via +/dev/mem +while crashdumps can be examined via the core file generated by +.Xr savecore 8 . +The interface behaves identically in both cases. +Memory can be read and written, kernel symbol addresses can be +looked up efficiently, and information about user processes can +be gathered. +.Pp +.Fn kvm_open +is first called to obtain a descriptor for all subsequent calls. +.Sh COMPATIBILITY +The kvm interface was first introduced in SunOS.  A considerable +number of programs have been developed that use this interface, +making backward compatibility highly desirable. +In most respects, the Sun kvm interface is consistent and clean. +Accordingly, the generic portion of the interface (i.e., +.Fn kvm_open , +.Fn kvm_close , +.Fn kvm_read , +.Fn kvm_write , +and +.Fn kvm_nlist ) +has been incorporated into the BSD interface.  Indeed, many kvm +applications (i.e., debuggers and statistical monitors) use only +this subset of the interface. +.Pp +The process interface was not kept.  This is not a portability +issue since any code that manipulates processes is inherently +machine dependent. +.Pp +Finally, the Sun kvm error reporting semantics are poorly defined. +The library can be configured either to print errors to stderr automatically, +or to print no error messages at all. +In the latter case, the nature of the error cannot be determined. +To overcome this, the BSD interface includes a +routine, +.Xr kvm_geterr 3 , +to return (not print out) the error message +corresponding to the most recent error condition on the +given descriptor. +.Sh SEE ALSO +.Xr kvm_close 3 , +.Xr kvm_getargv 3 , +.Xr kvm_getenvv 3 , +.Xr kvm_geterr 3 , +.Xr kvm_getloadavg 3 , +.Xr kvm_getprocs 3 , +.Xr kvm_nlist 3 , +.Xr kvm_open 3 , +.Xr kvm_openfiles 3 , +.Xr kvm_read 3 , +.Xr kvm_write 3 diff --git a/lib/libkvm/kvm.c b/lib/libkvm/kvm.c new file mode 100644 index 000000000000..a76f61e8d52c --- /dev/null +++ b/lib/libkvm/kvm.c @@ -0,0 +1,540 @@ +/*- + * Copyright (c) 1989, 1992, 1993 + *	The Regents of the University of California.  All rights reserved. + * + * This code is derived from software developed by the Computer Systems + * Engineering group at Lawrence Berkeley Laboratory under DARPA contract + * BG 91-66 and contributed to Berkeley. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + *    notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + *    notice, this list of conditions and the following disclaimer in the + *    documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + *    must display the following acknowledgement: + *	This product includes software developed by the University of + *	California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + *    may be used to endorse or promote products derived from this software + *    without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#if defined(LIBC_SCCS) && !defined(lint) +static char sccsid[] = "@(#)kvm.c	8.2 (Berkeley) 2/13/94"; +#endif /* LIBC_SCCS and not lint */ + +#include <sys/param.h> +#include <sys/user.h> +#include <sys/proc.h> +#include <sys/ioctl.h> +#include <sys/stat.h> +#include <sys/sysctl.h> + +#include <vm/vm.h> +#include <vm/vm_param.h> +#include <vm/swap_pager.h> + +#include <machine/vmparam.h> + +#include <ctype.h> +#include <db.h> +#include <fcntl.h> +#include <kvm.h> +#include <limits.h> +#include <nlist.h> +#include <paths.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> + +#include "kvm_private.h" + +static int kvm_dbopen __P((kvm_t *, const char *)); + +char * +kvm_geterr(kd) +	kvm_t *kd; +{ +	return (kd->errbuf); +} + +#if __STDC__ +#include <stdarg.h> +#else +#include <varargs.h> +#endif + +/* + * Report an error using printf style arguments.  "program" is kd->program + * on hard errors, and 0 on soft errors, so that under sun error emulation, + * only hard errors are printed out (otherwise, programs like gdb will + * generate tons of error messages when trying to access bogus pointers). + */ +void +#if __STDC__ +_kvm_err(kvm_t *kd, const char *program, const char *fmt, ...) +#else +_kvm_err(kd, program, fmt, va_alist) +	kvm_t *kd; +	char *program, *fmt; +	va_dcl +#endif +{ +	va_list ap; + +#ifdef __STDC__ +	va_start(ap, fmt); +#else +	va_start(ap); +#endif +	if (program != NULL) { +		(void)fprintf(stderr, "%s: ", program); +		(void)vfprintf(stderr, fmt, ap); +		(void)fputc('\n', stderr); +	} else +		(void)vsnprintf(kd->errbuf, +		    sizeof(kd->errbuf), (char *)fmt, ap); + +	va_end(ap); +} + +void +#if __STDC__ +_kvm_syserr(kvm_t *kd, const char *program, const char *fmt, ...) +#else +_kvm_syserr(kd, program, fmt, va_alist) +	kvm_t *kd; +	char *program, *fmt; +	va_dcl +#endif +{ +	va_list ap; +	register int n; + +#if __STDC__ +	va_start(ap, fmt); +#else +	va_start(ap); +#endif +	if (program != NULL) { +		(void)fprintf(stderr, "%s: ", program); +		(void)vfprintf(stderr, fmt, ap); +		(void)fprintf(stderr, ": %s\n", strerror(errno)); +	} else { +		register char *cp = kd->errbuf; + +		(void)vsnprintf(cp, sizeof(kd->errbuf), (char *)fmt, ap); +		n = strlen(cp); +		(void)snprintf(&cp[n], sizeof(kd->errbuf) - n, ": %s", +		    strerror(errno)); +	} +	va_end(ap); +} + +void * +_kvm_malloc(kd, n) +	register kvm_t *kd; +	register size_t n; +{ +	void *p; + +	if ((p = malloc(n)) == NULL) +		_kvm_err(kd, kd->program, strerror(errno)); +	return (p); +} + +static kvm_t * +_kvm_open(kd, uf, mf, sf, flag, errout) +	register kvm_t *kd; +	const char *uf; +	const char *mf; +	const char *sf; +	int flag; +	char *errout; +{ +	struct stat st; + +	kd->vmfd = -1; +	kd->pmfd = -1; +	kd->swfd = -1; +	kd->nlfd = -1; +	kd->vmst = 0; +	kd->db = 0; +	kd->procbase = 0; +	kd->argspc = 0; +	kd->argv = 0; + +	if (uf == 0) +		uf = _PATH_UNIX; +	else if (strlen(uf) >= MAXPATHLEN) { +		_kvm_err(kd, kd->program, "exec file name too long"); +		goto failed; +	} +	if (flag & ~O_RDWR) { +		_kvm_err(kd, kd->program, "bad flags arg"); +		goto failed; +	} +	if (mf == 0) +		mf = _PATH_MEM; +	if (sf == 0) +		sf = _PATH_DRUM; + +	if ((kd->pmfd = open(mf, flag, 0)) < 0) { +		_kvm_syserr(kd, kd->program, "%s", mf); +		goto failed; +	} +	if (fstat(kd->pmfd, &st) < 0) { +		_kvm_syserr(kd, kd->program, "%s", mf); +		goto failed; +	} +	if (S_ISCHR(st.st_mode)) { +		/* +		 * If this is a character special device, then check that +		 * it's /dev/mem.  If so, open kmem too.  (Maybe we should +		 * make it work for either /dev/mem or /dev/kmem -- in either +		 * case you're working with a live kernel.) +		 */ +		if (strcmp(mf, _PATH_MEM) != 0) {	/* XXX */ +			_kvm_err(kd, kd->program, +				 "%s: not physical memory device", mf); +			goto failed; +		} +		if ((kd->vmfd = open(_PATH_KMEM, flag)) < 0) { +			_kvm_syserr(kd, kd->program, "%s", _PATH_KMEM); +			goto failed; +		} +		if ((kd->swfd = open(sf, flag, 0)) < 0) { +			_kvm_syserr(kd, kd->program, "%s", sf); +			goto failed; +		} +		/* +		 * Open kvm nlist database.  We go ahead and do this +		 * here so that we don't have to hold on to the vmunix +		 * path name.  Since a kvm application will surely do +		 * a kvm_nlist(), this probably won't be a wasted effort. +		 * If the database cannot be opened, open the namelist +		 * argument so we revert to slow nlist() calls. +		 */ +		if (kvm_dbopen(kd, uf) < 0 &&  +		    (kd->nlfd = open(uf, O_RDONLY, 0)) < 0) { +			_kvm_syserr(kd, kd->program, "%s", uf); +			goto failed; +		} +	} else { +		/* +		 * This is a crash dump. +		 * Initalize the virtual address translation machinery, +		 * but first setup the namelist fd. +		 */ +		if ((kd->nlfd = open(uf, O_RDONLY, 0)) < 0) { +			_kvm_syserr(kd, kd->program, "%s", uf); +			goto failed; +		} +		if (_kvm_initvtop(kd) < 0) +			goto failed; +	} +	return (kd); +failed: +	/* +	 * Copy out the error if doing sane error semantics. +	 */ +	if (errout != 0) +		strcpy(errout, kd->errbuf); +	(void)kvm_close(kd); +	return (0); +} + +kvm_t * +kvm_openfiles(uf, mf, sf, flag, errout) +	const char *uf; +	const char *mf; +	const char *sf; +	int flag; +	char *errout; +{ +	register kvm_t *kd; + +	if ((kd = malloc(sizeof(*kd))) == NULL) { +		(void)strcpy(errout, strerror(errno)); +		return (0); +	} +	kd->program = 0; +	return (_kvm_open(kd, uf, mf, sf, flag, errout)); +} + +kvm_t * +kvm_open(uf, mf, sf, flag, program) +	const char *uf; +	const char *mf; +	const char *sf; +	int flag; +	const char *program; +{ +	register kvm_t *kd; + +	if ((kd = malloc(sizeof(*kd))) == NULL && program != NULL) { +		(void)fprintf(stderr, "%s: %s\n", strerror(errno)); +		return (0); +	} +	kd->program = program; +	return (_kvm_open(kd, uf, mf, sf, flag, NULL)); +} + +int +kvm_close(kd) +	kvm_t *kd; +{ +	register int error = 0; + +	if (kd->pmfd >= 0) +		error |= close(kd->pmfd); +	if (kd->vmfd >= 0) +		error |= close(kd->vmfd); +	if (kd->nlfd >= 0) +		error |= close(kd->nlfd); +	if (kd->swfd >= 0) +		error |= close(kd->swfd); +	if (kd->db != 0) +		error |= (kd->db->close)(kd->db); +	if (kd->vmst) +		_kvm_freevtop(kd); +	if (kd->procbase != 0) +		free((void *)kd->procbase); +	if (kd->argv != 0) +		free((void *)kd->argv); +	free((void *)kd); + +	return (0); +} + +/* + * Set up state necessary to do queries on the kernel namelist + * data base.  If the data base is out-of-data/incompatible with  + * given executable, set up things so we revert to standard nlist call. + * Only called for live kernels.  Return 0 on success, -1 on failure. + */ +static int +kvm_dbopen(kd, uf) +	kvm_t *kd; +	const char *uf; +{ +	char *cp; +	DBT rec; +	int dbversionlen; +	struct nlist nitem; +	char dbversion[_POSIX2_LINE_MAX]; +	char kversion[_POSIX2_LINE_MAX]; +	char dbname[MAXPATHLEN]; + +	if ((cp = rindex(uf, '/')) != 0) +		uf = cp + 1; + +	(void)snprintf(dbname, sizeof(dbname), "%skvm_%s.db", _PATH_VARDB, uf); +	kd->db = dbopen(dbname, O_RDONLY, 0, DB_HASH, NULL); +	if (kd->db == 0) +		return (-1); +	/* +	 * read version out of database +	 */ +	rec.data = VRS_KEY; +	rec.size = sizeof(VRS_KEY) - 1; +	if ((kd->db->get)(kd->db, (DBT *)&rec, (DBT *)&rec, 0)) +		goto close; +	if (rec.data == 0 || rec.size > sizeof(dbversion)) +		goto close; + +	bcopy(rec.data, dbversion, rec.size); +	dbversionlen = rec.size; +	/* +	 * Read version string from kernel memory. +	 * Since we are dealing with a live kernel, we can call kvm_read() +	 * at this point. +	 */ +	rec.data = VRS_SYM; +	rec.size = sizeof(VRS_SYM) - 1; +	if ((kd->db->get)(kd->db, (DBT *)&rec, (DBT *)&rec, 0)) +		goto close; +	if (rec.data == 0 || rec.size != sizeof(struct nlist)) +		goto close; +	bcopy((char *)rec.data, (char *)&nitem, sizeof(nitem)); +	if (kvm_read(kd, (u_long)nitem.n_value, kversion, dbversionlen) !=  +	    dbversionlen) +		goto close; +	/* +	 * If they match, we win - otherwise clear out kd->db so +	 * we revert to slow nlist(). +	 */ +	if (bcmp(dbversion, kversion, dbversionlen) == 0) +		return (0); +close: +	(void)(kd->db->close)(kd->db); +	kd->db = 0; + +	return (-1); +} + +int +kvm_nlist(kd, nl) +	kvm_t *kd; +	struct nlist *nl; +{ +	register struct nlist *p; +	register int nvalid; + +	/* +	 * If we can't use the data base, revert to the  +	 * slow library call. +	 */ +	if (kd->db == 0) +		return (__fdnlist(kd->nlfd, nl)); + +	/* +	 * We can use the kvm data base.  Go through each nlist entry +	 * and look it up with a db query. +	 */ +	nvalid = 0; +	for (p = nl; p->n_name && p->n_name[0]; ++p) { +		register int len; +		DBT rec; + +		if ((len = strlen(p->n_name)) > 4096) { +			/* sanity */ +			_kvm_err(kd, kd->program, "symbol too large"); +			return (-1); +		} +		rec.data = p->n_name; +		rec.size = len; +		if ((kd->db->get)(kd->db, (DBT *)&rec, (DBT *)&rec, 0)) +			continue; +		if (rec.data == 0 || rec.size != sizeof(struct nlist)) +			continue; +		++nvalid; +		/* +		 * Avoid alignment issues. +		 */ +		bcopy((char *)&((struct nlist *)rec.data)->n_type, +		      (char *)&p->n_type,  +		      sizeof(p->n_type)); +		bcopy((char *)&((struct nlist *)rec.data)->n_value, +		      (char *)&p->n_value,  +		      sizeof(p->n_value)); +	} +	/* +	 * Return the number of entries that weren't found. +	 */ +	return ((p - nl) - nvalid); +} + +ssize_t +kvm_read(kd, kva, buf, len) +	kvm_t *kd; +	register u_long kva; +	register void *buf; +	register size_t len; +{ +	register int cc; +	register void *cp; + +	if (ISALIVE(kd)) { +		/* +		 * We're using /dev/kmem.  Just read straight from the +		 * device and let the active kernel do the address translation. +		 */ +		errno = 0; +		if (lseek(kd->vmfd, (off_t)kva, 0) == -1 && errno != 0) { +			_kvm_err(kd, 0, "invalid address (%x)", kva); +			return (0); +		} +		cc = read(kd->vmfd, buf, len); +		if (cc < 0) { +			_kvm_syserr(kd, 0, "kvm_read"); +			return (0); +		} else if (cc < len) +			_kvm_err(kd, kd->program, "short read"); +		return (cc); +	} else { +		cp = buf; +		while (len > 0) { +			u_long pa; +		 +			cc = _kvm_kvatop(kd, kva, &pa); +			if (cc == 0) +				return (0); +			if (cc > len) +				cc = len; +			errno = 0; +			if (lseek(kd->pmfd, (off_t)pa, 0) == -1 && errno != 0) { +				_kvm_syserr(kd, 0, _PATH_MEM); +				break; +			} +			cc = read(kd->pmfd, cp, cc); +			if (cc < 0) { +				_kvm_syserr(kd, kd->program, "kvm_read"); +				break; +			} +			/* +			 * If kvm_kvatop returns a bogus value or our core +			 * file is truncated, we might wind up seeking beyond +			 * the end of the core file in which case the read will +			 * return 0 (EOF). +			 */ +			if (cc == 0) +				break; +			(char *)cp += cc; +			kva += cc; +			len -= cc; +		} +		return ((char *)cp - (char *)buf); +	} +	/* NOTREACHED */ +} + +ssize_t +kvm_write(kd, kva, buf, len) +	kvm_t *kd; +	register u_long kva; +	register const void *buf; +	register size_t len; +{ +	register int cc; + +	if (ISALIVE(kd)) { +		/* +		 * Just like kvm_read, only we write. +		 */ +		errno = 0; +		if (lseek(kd->vmfd, (off_t)kva, 0) == -1 && errno != 0) { +			_kvm_err(kd, 0, "invalid address (%x)", kva); +			return (0); +		} +		cc = write(kd->vmfd, buf, len); +		if (cc < 0) { +			_kvm_syserr(kd, 0, "kvm_write"); +			return (0); +		} else if (cc < len) +			_kvm_err(kd, kd->program, "short write"); +		return (cc); +	} else { +		_kvm_err(kd, kd->program, +		    "kvm_write not implemented for dead kernels"); +		return (0); +	} +	/* NOTREACHED */ +} diff --git a/lib/libkvm/kvm_file.c b/lib/libkvm/kvm_file.c new file mode 100644 index 000000000000..c8b9f4d6888b --- /dev/null +++ b/lib/libkvm/kvm_file.c @@ -0,0 +1,188 @@ +/*- + * Copyright (c) 1989, 1992, 1993 + *	The Regents of the University of California.  All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + *    notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + *    notice, this list of conditions and the following disclaimer in the + *    documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + *    must display the following acknowledgement: + *	This product includes software developed by the University of + *	California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + *    may be used to endorse or promote products derived from this software + *    without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#if defined(LIBC_SCCS) && !defined(lint) +static char sccsid[] = "@(#)kvm_file.c	8.1 (Berkeley) 6/4/93"; +#endif /* LIBC_SCCS and not lint */ + +/* + * File list interface for kvm.  pstat, fstat and netstat are  + * users of this code, so we've factored it out into a separate module. + * Thus, we keep this grunge out of the other kvm applications (i.e., + * most other applications are interested only in open/close/read/nlist). + */ + +#include <sys/param.h> +#include <sys/user.h> +#include <sys/proc.h> +#include <sys/exec.h> +#define KERNEL +#include <sys/file.h> +#undef KERNEL +#include <sys/stat.h> +#include <sys/ioctl.h> +#include <sys/tty.h> +#include <nlist.h> +#include <kvm.h> + +#include <vm/vm.h> +#include <vm/vm_param.h> +#include <vm/swap_pager.h> + +#include <sys/sysctl.h> + +#include <limits.h> +#include <ndbm.h> +#include <paths.h> + +#include "kvm_private.h" + +#define KREAD(kd, addr, obj) \ +	(kvm_read(kd, addr, obj, sizeof(*obj)) != sizeof(*obj)) + +/* + * Get file structures. + */ +static +kvm_deadfiles(kd, op, arg, filehead_o, nfiles) +	kvm_t *kd; +	int op, arg, nfiles; +	long filehead_o; +{ +	int buflen = kd->arglen, needed = buflen, error, n = 0; +	struct file *fp, file, *filehead; +	register char *where = kd->argspc; +	char *start = where; + +	/* +	 * first copyout filehead +	 */ +	if (buflen > sizeof (filehead)) { +		if (KREAD(kd, filehead_o, &filehead)) { +			_kvm_err(kd, kd->program, "can't read filehead"); +			return (0); +		} +		buflen -= sizeof (filehead); +		where += sizeof (filehead); +		*(struct file **)kd->argspc = filehead; +	} +	/* +	 * followed by an array of file structures +	 */ +	for (fp = filehead; fp != NULL; fp = fp->f_filef) { +		if (buflen > sizeof (struct file)) { +			if (KREAD(kd, (long)fp, ((struct file *)where))) { +				_kvm_err(kd, kd->program, "can't read kfp"); +				return (0); +			} +			buflen -= sizeof (struct file); +			fp = (struct file *)where; +			where += sizeof (struct file); +			n++; +		} +	} +	if (n != nfiles) { +		_kvm_err(kd, kd->program, "inconsistant nfiles"); +		return (0); +	} +	return (nfiles); +} + +char * +kvm_getfiles(kd, op, arg, cnt) +	kvm_t *kd; +	int op, arg; +	int *cnt; +{ +	int mib[2], size, st, nfiles; +	struct file *filehead, *fp, *fplim; + +	if (ISALIVE(kd)) { +		size = 0; +		mib[0] = CTL_KERN; +		mib[1] = KERN_FILE; +		st = sysctl(mib, 2, NULL, &size, NULL, 0); +		if (st == -1) { +			_kvm_syserr(kd, kd->program, "kvm_getprocs"); +			return (0); +		} +		if (kd->argspc == 0) +			kd->argspc = (char *)_kvm_malloc(kd, size); +		else if (kd->arglen < size) +			kd->argspc = (char *)_kvm_realloc(kd, kd->argspc, size); +		if (kd->argspc == 0) +			return (0); +		kd->arglen = size; +		st = sysctl(mib, 2, kd->argspc, &size, NULL, 0); +		if (st == -1 || size < sizeof(filehead)) { +			_kvm_syserr(kd, kd->program, "kvm_getfiles"); +			return (0); +		} +		filehead = *(struct file **)kd->argspc; +		fp = (struct file *)(kd->argspc + sizeof (filehead)); +		fplim = (struct file *)(kd->argspc + size); +		for (nfiles = 0; filehead && (fp < fplim); nfiles++, fp++) +			filehead = fp->f_filef; +	} else { +		struct nlist nl[3], *p; + +		nl[0].n_name = "_filehead"; +		nl[1].n_name = "_nfiles"; +		nl[2].n_name = 0; + +		if (kvm_nlist(kd, nl) != 0) { +			for (p = nl; p->n_type != 0; ++p) +				; +			_kvm_err(kd, kd->program, +				 "%s: no such symbol", p->n_name); +			return (0); +		} +		if (KREAD(kd, nl[0].n_value, &nfiles)) { +			_kvm_err(kd, kd->program, "can't read nfiles"); +			return (0); +		} +		size = sizeof(filehead) + (nfiles + 10) * sizeof(struct file); +		if (kd->argspc == 0) +			kd->argspc = (char *)_kvm_malloc(kd, size); +		else if (kd->arglen < size) +			kd->argspc = (char *)_kvm_realloc(kd, kd->argspc, size); +		if (kd->argspc == 0) +			return (0); +		kd->arglen = size; +		nfiles = kvm_deadfiles(kd, op, arg, nl[1].n_value, nfiles); +		if (nfiles == 0) +			return (0); +	} +	*cnt = nfiles; +	return (kd->argspc); +} diff --git a/lib/libkvm/kvm_geterr.3 b/lib/libkvm/kvm_geterr.3 new file mode 100644 index 000000000000..b8eefa7aa748 --- /dev/null +++ b/lib/libkvm/kvm_geterr.3 @@ -0,0 +1,80 @@ +.\" Copyright (c) 1992, 1993 +.\"	The Regents of the University of California.  All rights reserved. +.\" +.\" This code is derived from software developed by the Computer Systems +.\" Engineering group at Lawrence Berkeley Laboratory under DARPA contract +.\" BG 91-66 and contributed to Berkeley. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\"    notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\"    notice, this list of conditions and the following disclaimer in the +.\"    documentation and/or other materials provided with the distribution. +.\" 3. All advertising materials mentioning features or use of this software +.\"    must display the following acknowledgement: +.\"	This product includes software developed by the University of +.\"	California, Berkeley and its contributors. +.\" 4. Neither the name of the University nor the names of its contributors +.\"    may be used to endorse or promote products derived from this software +.\"    without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\"     @(#)kvm_geterr.3	8.1 (Berkeley) 6/4/93 +.\" +.Dd June 4, 1993 +.Dt KVM_GETERR 3 +.Os +.Sh NAME +.Nm kvm_geterr +.Nd get error message on kvm descriptor +.Sh SYNOPSIS +.Fd #include <kvm.h> +.br +.Ft char * +.Fn kvm_geterr "kvm_t *kd" +.Sh DESCRIPTION +This function returns a string describing the most recent error condition +on the descriptor +.Fa kd . +The results are undefined if the most recent +.Xr kvm 3 +library call did not produce an error. +The string returned is stored in memory owned by  +.Xr kvm 3 +so the message should be copied out and saved elsewhere if necessary. +.Sh BUGS +This routine cannot be used to access error conditions due to a failed +.Fn kvm_openfiles +call, since failure is indicated by returning a +.Dv NULL +descriptor. +Therefore, errors on open are output to the special error buffer +passed to  +.Fn kvm_openfiles . +This option is not available to +.Fn kvm_open . +.Sh SEE ALSO +.Xr kvm 3 , +.Xr kvm_close 3 , +.Xr kvm_getargv 3 , +.Xr kvm_getenvv 3 , +.Xr kvm_getprocs 3 , +.Xr kvm_nlist 3 , +.Xr kvm_open 3 , +.Xr kvm_openfiles 3 , +.Xr kvm_read 3 , +.Xr kvm_write 3 diff --git a/lib/libkvm/kvm_getfiles.3 b/lib/libkvm/kvm_getfiles.3 new file mode 100644 index 000000000000..bad2e7492b03 --- /dev/null +++ b/lib/libkvm/kvm_getfiles.3 @@ -0,0 +1,86 @@ +.\" Copyright (c) 1992, 1993 +.\"	The Regents of the University of California.  All rights reserved. +.\" +.\" This code is derived from software developed by the Computer Systems +.\" Engineering group at Lawrence Berkeley Laboratory under DARPA contract +.\" BG 91-66 and contributed to Berkeley. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\"    notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\"    notice, this list of conditions and the following disclaimer in the +.\"    documentation and/or other materials provided with the distribution. +.\" 3. All advertising materials mentioning features or use of this software +.\"    must display the following acknowledgement: +.\"	This product includes software developed by the University of +.\"	California, Berkeley and its contributors. +.\" 4. Neither the name of the University nor the names of its contributors +.\"    may be used to endorse or promote products derived from this software +.\"    without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\"     @(#)kvm_getfiles.3	8.2 (Berkeley) 4/19/94 +.\" +.Dd April 19, 1994 +.Dt KVM_GETFILES 3 +.Os +.Sh NAME +.Nm kvm_getfiles +.Nd survey open files +.Sh SYNOPSIS +.Fd #include <kvm.h> +.Fd #include <sys/kinfo.h> +.Fd #define KERNEL +.Fd #include <sys/file.h> +.Fd #undef KERNEL +.\" .Fa kvm_t *kd +.br +.Ft char * +.Fn kvm_getfiles "kvm_t *kd" "int op" "int arg" "int *cnt" +.Sh DESCRIPTION +.Fn kvm_getfiles +returns a (sub-)set of the open files in the kernel indicated by +.Fa kd. +The +.Fa op +and +.Fa arg +arguments constitute a predicate which limits the set of files +returned.  No predicates are currently defined. +.Pp +The number of processes found is returned in the reference parameter +.Fa cnt . +The files are returned as a contiguous array of file structures, +preceded by the address of the first file entry in the kernel. +This memory is owned by kvm and is not guaranteed to be persistent across +subsequent kvm library calls.  Data should be copied out if it needs to be +saved. +.Sh RETURN VALUES +.Fn kvm_getfiles +will return NULL on failure. +.Pp +.Sh BUGS +This routine does not belong in the kvm interface. +.Sh SEE ALSO +.Xr kvm 3 , +.Xr kvm_open 3 , +.Xr kvm_openfiles 3 , +.Xr kvm_close 3 , +.Xr kvm_read 3 , +.Xr kvm_write 3 , +.Xr kvm_nlist 3 , +.Xr kvm_geterr 3 diff --git a/lib/libkvm/kvm_getloadavg.3 b/lib/libkvm/kvm_getloadavg.3 new file mode 100644 index 000000000000..80dc3b1d4c2b --- /dev/null +++ b/lib/libkvm/kvm_getloadavg.3 @@ -0,0 +1,65 @@ +.\" Copyright (c) 1992, 1993 +.\"	The Regents of the University of California.  All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\"    notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\"    notice, this list of conditions and the following disclaimer in the +.\"    documentation and/or other materials provided with the distribution. +.\" 3. All advertising materials mentioning features or use of this software +.\"    must display the following acknowledgement: +.\"	This product includes software developed by the University of +.\"	California, Berkeley and its contributors. +.\" 4. Neither the name of the University nor the names of its contributors +.\"    may be used to endorse or promote products derived from this software +.\"    without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\"     @(#)kvm_getloadavg.3	8.1 (Berkeley) 6/4/93 +.\" +.Dd June 4, 1993 +.Dt KVM_GETLOADAVG 3 +.Os +.Sh NAME +.Nm kvm_getloadavg +.Nd get error message on kvm descriptor +.Sh SYNOPSIS +.Fd #include <sys/resource.h> +.Fd #include <kvm.h> +.br +.Ft int +.Fn kvm_getloadavg "kvm_t *kd" "double loadavg[]" "int nelem" +.Sh DESCRIPTION +The +.Fn kvm_getloadavg +function returns the number of processes in the system run queue +of the kernel indicated by +.Fa kd , +averaged over various periods of time. +Up to +.Fa nelem +samples are retrieved and assigned to successive elements of +.Fa loadavg Ns Bq . +The system imposes a maximum of 3 samples, representing averages +over the last 1, 5, and 15 minutes, respectively. +.Sh DIAGNOSTICS +If the load average was unobtainable, \-1 is returned; otherwise, +the number of samples actually retrieved is returned. +.Sh SEE ALSO +.Xr uptime 1 , +.Xr kvm 3 , +.Xr getloadavg 3 diff --git a/lib/libkvm/kvm_getloadavg.c b/lib/libkvm/kvm_getloadavg.c new file mode 100644 index 000000000000..e13ee1d46e8b --- /dev/null +++ b/lib/libkvm/kvm_getloadavg.c @@ -0,0 +1,105 @@ +/*- + * Copyright (c) 1993 + *	The Regents of the University of California.  All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + *    notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + *    notice, this list of conditions and the following disclaimer in the + *    documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + *    must display the following acknowledgement: + *	This product includes software developed by the University of + *	California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + *    may be used to endorse or promote products derived from this software + *    without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#if defined(LIBC_SCCS) && !defined(lint) +static char sccsid[] = "@(#)kvm_getloadavg.c	8.1 (Berkeley) 6/4/93"; +#endif /* LIBC_SCCS and not lint */ + +#include <sys/param.h> +#include <sys/time.h> +#include <sys/resource.h> +#include <sys/proc.h> +#include <sys/sysctl.h> +#include <vm/vm_param.h> + +#include <db.h> +#include <fcntl.h> +#include <limits.h> +#include <nlist.h> +#include <kvm.h> + +#include "kvm_private.h" + +static struct nlist nl[] = { +	{ "_averunnable" }, +#define	X_AVERUNNABLE	0 +	{ "_fscale" }, +#define	X_FSCALE	1 +	{ "" }, +}; + +/* + * kvm_getloadavg() -- Get system load averages, from live or dead kernels. + * + * Put `nelem' samples into `loadavg' array. + * Return number of samples retrieved, or -1 on error. + */ +int +kvm_getloadavg(kd, loadavg, nelem) +	kvm_t *kd; +	double loadavg[]; +	int nelem; +{ +	struct loadavg loadinfo; +	struct nlist *p; +	int fscale, i; + +	if (ISALIVE(kd)) +		return (getloadavg(loadavg, nelem)); + +	if (kvm_nlist(kd, nl) != 0) { +		for (p = nl; p->n_type != 0; ++p); +		_kvm_err(kd, kd->program, +		    "%s: no such symbol", p->n_name); +		return (-1); +	} + +#define KREAD(kd, addr, obj) \ +	(kvm_read(kd, addr, (char *)(obj), sizeof(*obj)) != sizeof(*obj)) +	if (KREAD(kd, nl[X_AVERUNNABLE].n_value, &loadinfo)) { +		_kvm_err(kd, kd->program, "can't read averunnable"); +		return (-1); +	} + +	/* +	 * Old kernels have fscale separately; if not found assume +	 * running new format. +	 */ +	if (!KREAD(kd, nl[X_FSCALE].n_value, &fscale)) +		loadinfo.fscale = fscale; + +	nelem = MIN(nelem, sizeof(loadinfo.ldavg) / sizeof(fixpt_t)); +	for (i = 0; i < nelem; i++) +		loadavg[i] = (double) loadinfo.ldavg[i] / loadinfo.fscale; +	return (nelem); +} diff --git a/lib/libkvm/kvm_getprocs.3 b/lib/libkvm/kvm_getprocs.3 new file mode 100644 index 000000000000..a5eacb9a34aa --- /dev/null +++ b/lib/libkvm/kvm_getprocs.3 @@ -0,0 +1,163 @@ +.\" Copyright (c) 1992, 1993 +.\"	The Regents of the University of California.  All rights reserved. +.\" +.\" This code is derived from software developed by the Computer Systems +.\" Engineering group at Lawrence Berkeley Laboratory under DARPA contract +.\" BG 91-66 and contributed to Berkeley. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\"    notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\"    notice, this list of conditions and the following disclaimer in the +.\"    documentation and/or other materials provided with the distribution. +.\" 3. All advertising materials mentioning features or use of this software +.\"    must display the following acknowledgement: +.\"	This product includes software developed by the University of +.\"	California, Berkeley and its contributors. +.\" 4. Neither the name of the University nor the names of its contributors +.\"    may be used to endorse or promote products derived from this software +.\"    without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\"     @(#)kvm_getprocs.3	8.1 (Berkeley) 6/4/93 +.\" +.Dd June 4, 1993 +.Dt KVM_GETPROCS 3 +.Os +.Sh NAME +.Nm kvm_getprocs , +.Nm kvm_getargv , +.Nm kvm_getenvv  +.Nd access user process state +.Sh SYNOPSIS +.Fd #include <kvm.h> +.Fd #include <sys/kinfo.h> +.Fd #include <sys/kinfo_proc.h> +.\" .Fa kvm_t *kd +.br +.Ft struct kinfo_proc * +.Fn kvm_getprocs "kvm_t *kd" "int op" "int arg" "int *cnt" +.Ft char ** +.Fn kvm_getargv "kvm_t *kd" "const struct kinfo_proc *p" "int nchr" +.Ft char ** +.Fn kvm_getenvv "kvm_t *kd" "const struct kinfo_proc *p" "int nchr" +.Sh DESCRIPTION +.Fn kvm_getprocs +returns a (sub-)set of active processes in the kernel indicated by +.Fa kd. +The +.Fa op +and +.Fa arg +arguments constitute a predicate which limits the set of processes +returned.  The value of +.Fa op +describes the filtering predicate as follows: +.Pp +.Bl -tag -width 20n -offset indent -compact +.It Sy KINFO_PROC_ALL +all processes +.It Sy KINFO_PROC_PID +processes with process id  +.Fa arg +.It Sy KINFO_PROC_PGRP +processes with process group +.Fa arg +.It Sy KINFO_PROC_SESSION +processes with session +.Fa arg +.It Sy KINFO_PROC_TTY +processes with tty +.Fa arg +.It Sy KINFO_PROC_UID +processes with effective user id +.Fa arg +.It Sy KINFO_PROC_RUID +processes with real user id +.Fa arg +.El +.Pp +The number of processes found is returned in the reference parameter +.Fa cnt . +The processes are returned as a contiguous array of kinfo_proc structures. +This memory is locally allocated, and subsequent calls to +.Fn kvm_getprocs  +and  +.Fn kvm_close +will overwrite this storage. +.Pp +.Fn kvm_getargv +returns a null-terminated argument vector that corresponds to the  +command line arguments passed to process indicated by +.Fa p . +Most likely, these arguments correspond to the values passed to +.Xr exec 3 +on process creation.  This information is, however, +deliberately under control of the process itself. +Note that the original command name can be found, unaltered, +in the p_comm field of the process structure returned by +.Fn kvm_getprocs . +.Pp +The  +.Fa nchr +argument indicates the maximum number of characters, including null bytes, +to use in building the strings.  If this amount is exceeded, the string +causing the overflow is truncated and the partial result is returned. +This is handy for programs like +.Xr ps 1 +and +.Xr w 1 +that print only a one line summary of a command and should not copy +out large amounts of text only to ignore it. +If +.Fa nchr +is zero, no limit is imposed and all argument strings are returned in  +their entirety. +.Pp +The memory allocated to the argv pointers and string storage +is owned by the kvm library.  Subsequent  +.Fn kvm_getprocs  +and  +.Xr kvm_close 3 +calls will clobber this storage. +.Pp +The +.Fn kvm_getenvv +function is similar to +.Fn kvm_getargv +but returns the vector of environment strings.  This data is +also alterable by the process. +.Sh RETURN VALUES +.Fn kvm_getprocs , +.Fn kvm_getargv , +and +.Fn kvm_getenvv , +all return +.Dv NULL +on failure. +.Pp +.Sh BUGS +These routines do not belong in the kvm interface. +.Sh SEE ALSO +.Xr kvm 3 , +.Xr kvm_close 3 , +.Xr kvm_geterr 3 , +.Xr kvm_nlist 3 , +.Xr kvm_open 3 , +.Xr kvm_openfiles 3 , +.Xr kvm_read 3 , +.Xr kvm_write 3 diff --git a/lib/libkvm/kvm_hp300.c b/lib/libkvm/kvm_hp300.c new file mode 100644 index 000000000000..2154a23f3007 --- /dev/null +++ b/lib/libkvm/kvm_hp300.c @@ -0,0 +1,286 @@ +/*- + * Copyright (c) 1989, 1992, 1993 + *	The Regents of the University of California.  All rights reserved. + * + * This code is derived from software developed by the Computer Systems + * Engineering group at Lawrence Berkeley Laboratory under DARPA contract + * BG 91-66 and contributed to Berkeley. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + *    notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + *    notice, this list of conditions and the following disclaimer in the + *    documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + *    must display the following acknowledgement: + *	This product includes software developed by the University of + *	California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + *    may be used to endorse or promote products derived from this software + *    without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#if defined(LIBC_SCCS) && !defined(lint) +static char sccsid[] = "@(#)kvm_hp300.c	8.1 (Berkeley) 6/4/93"; +#endif /* LIBC_SCCS and not lint */ + +/* + * Hp300 machine dependent routines for kvm.  Hopefully, the forthcoming  + * vm code will one day obsolete this module. + */ + +#include <sys/param.h> +#include <sys/user.h> +#include <sys/proc.h> +#include <sys/stat.h> +#include <unistd.h> +#include <nlist.h> +#include <kvm.h> + +#include <vm/vm.h> +#include <vm/vm_param.h> + +#include <limits.h> +#include <db.h> + +#include "kvm_private.h" + +#if defined(hp300) +#include <hp300/hp300/pte.h> +#endif + +#if defined(luna68k) +#include <luna68k/luna68k/pte.h> +#endif + +#ifndef btop +#define	btop(x)		(((unsigned)(x)) >> PGSHIFT)	/* XXX */ +#define	ptob(x)		((caddr_t)((x) << PGSHIFT))	/* XXX */ +#endif + +struct vmstate { +	u_long lowram; +	int mmutype; +	struct ste *Sysseg; +}; + +#define KREAD(kd, addr, p)\ +	(kvm_read(kd, addr, (char *)(p), sizeof(*(p))) != sizeof(*(p))) + +void +_kvm_freevtop(kd) +	kvm_t *kd; +{ +	if (kd->vmst != 0) +		free(kd->vmst); +} + +int +_kvm_initvtop(kd) +	kvm_t *kd; +{ +	struct vmstate *vm; +	struct nlist nlist[4]; + +	vm = (struct vmstate *)_kvm_malloc(kd, sizeof(*vm)); +	if (vm == 0) +		return (-1); +	kd->vmst = vm; + +	nlist[0].n_name = "_lowram"; +	nlist[1].n_name = "_mmutype"; +	nlist[2].n_name = "_Sysseg"; +	nlist[3].n_name = 0; + +	if (kvm_nlist(kd, nlist) != 0) { +		_kvm_err(kd, kd->program, "bad namelist"); +		return (-1); +	} +	vm->Sysseg = 0; +	if (KREAD(kd, (u_long)nlist[0].n_value, &vm->lowram)) { +		_kvm_err(kd, kd->program, "cannot read lowram"); +		return (-1); +	} +	if (KREAD(kd, (u_long)nlist[1].n_value, &vm->mmutype)) { +		_kvm_err(kd, kd->program, "cannot read mmutype"); +		return (-1); +	} +	if (KREAD(kd, (u_long)nlist[2].n_value, &vm->Sysseg)) { +		_kvm_err(kd, kd->program, "cannot read segment table"); +		return (-1); +	} +	return (0); +} + +static int +_kvm_vatop(kd, sta, va, pa) +	kvm_t *kd; +	struct ste *sta; +	u_long va; +	u_long *pa; +{ +	register struct vmstate *vm; +	register u_long lowram; +	register u_long addr; +	int p, ste, pte; +	int offset; + +	if (ISALIVE(kd)) { +		_kvm_err(kd, 0, "vatop called in live kernel!"); +		return((off_t)0); +	} +	vm = kd->vmst; +	offset = va & PGOFSET; +	/* +	 * If we are initializing (kernel segment table pointer not yet set) +	 * then return pa == va to avoid infinite recursion. +	 */ +	if (vm->Sysseg == 0) { +		*pa = va; +		return (NBPG - offset); +	} +	lowram = vm->lowram; +	if (vm->mmutype == -2) { +		struct ste *sta2; + +		addr = (u_long)&sta[va >> SG4_SHIFT1]; +		/* +		 * Can't use KREAD to read kernel segment table entries. +		 * Fortunately it is 1-to-1 mapped so we don't have to.  +		 */ +		if (sta == vm->Sysseg) { +			if (lseek(kd->pmfd, (off_t)addr, 0) == -1 || +			    read(kd->pmfd, (char *)&ste, sizeof(ste)) < 0) +				goto invalid; +		} else if (KREAD(kd, addr, &ste)) +			goto invalid; +		if ((ste & SG_V) == 0) { +			_kvm_err(kd, 0, "invalid level 1 descriptor (%x)", +				 ste); +			return((off_t)0); +		} +		sta2 = (struct ste *)(ste & SG4_ADDR1); +		addr = (u_long)&sta2[(va & SG4_MASK2) >> SG4_SHIFT2]; +		/* +		 * Address from level 1 STE is a physical address, +		 * so don't use kvm_read. +		 */ +		if (lseek(kd->pmfd, (off_t)(addr - lowram), 0) == -1 ||  +		    read(kd->pmfd, (char *)&ste, sizeof(ste)) < 0) +			goto invalid; +		if ((ste & SG_V) == 0) { +			_kvm_err(kd, 0, "invalid level 2 descriptor (%x)", +				 ste); +			return((off_t)0); +		} +		sta2 = (struct ste *)(ste & SG4_ADDR2); +		addr = (u_long)&sta2[(va & SG4_MASK3) >> SG4_SHIFT3]; +	} else { +		addr = (u_long)&sta[va >> SEGSHIFT]; +		/* +		 * Can't use KREAD to read kernel segment table entries. +		 * Fortunately it is 1-to-1 mapped so we don't have to.  +		 */ +		if (sta == vm->Sysseg) { +			if (lseek(kd->pmfd, (off_t)addr, 0) == -1 || +			    read(kd->pmfd, (char *)&ste, sizeof(ste)) < 0) +				goto invalid; +		} else if (KREAD(kd, addr, &ste)) +			goto invalid; +		if ((ste & SG_V) == 0) { +			_kvm_err(kd, 0, "invalid segment (%x)", ste); +			return((off_t)0); +		} +		p = btop(va & SG_PMASK); +		addr = (ste & SG_FRAME) + (p * sizeof(struct pte)); +	} +	/* +	 * Address from STE is a physical address so don't use kvm_read. +	 */ +	if (lseek(kd->pmfd, (off_t)(addr - lowram), 0) == -1 ||  +	    read(kd->pmfd, (char *)&pte, sizeof(pte)) < 0) +		goto invalid; +	addr = pte & PG_FRAME; +	if (pte == PG_NV) { +		_kvm_err(kd, 0, "page not valid"); +		return (0); +	} +	*pa = addr - lowram + offset; +	 +	return (NBPG - offset); +invalid: +	_kvm_err(kd, 0, "invalid address (%x)", va); +	return (0); +} + +int +_kvm_kvatop(kd, va, pa) +	kvm_t *kd; +	u_long va; +	u_long *pa; +{ +	return (_kvm_vatop(kd, (u_long)kd->vmst->Sysseg, va, pa)); +} + +/* + * Translate a user virtual address to a physical address. + */ +int +_kvm_uvatop(kd, p, va, pa) +	kvm_t *kd; +	const struct proc *p; +	u_long va; +	u_long *pa; +{ +	register struct vmspace *vms = p->p_vmspace; +	int kva; + +	/* +	 * If this is a live kernel we just look it up in the kernel +	 * virtually allocated flat 4mb page table (i.e. let the kernel +	 * do the table walk).  In this way, we avoid needing to know +	 * the MMU type. +	 */ +	if (ISALIVE(kd)) { +		struct pte *ptab; +		int pte, offset; + +		kva = (int)&vms->vm_pmap.pm_ptab; +		if (KREAD(kd, kva, &ptab)) { +			_kvm_err(kd, 0, "invalid address (%x)", va); +			return (0); +		} +		kva = (int)&ptab[btop(va)]; +		if (KREAD(kd, kva, &pte) || (pte & PG_V) == 0) { +			_kvm_err(kd, 0, "invalid address (%x)", va); +			return (0); +		} +		offset = va & PGOFSET; +		*pa = (pte & PG_FRAME) | offset; +		return (NBPG - offset); +	} +	/* +	 * Otherwise, we just walk the table ourself. +	 */ +	kva = (int)&vms->vm_pmap.pm_stab; +	if (KREAD(kd, kva, &kva)) { +		_kvm_err(kd, 0, "invalid address (%x)", va); +		return (0); +	} +	return (_kvm_vatop(kd, kva, va, pa)); +} diff --git a/lib/libkvm/kvm_mips.c b/lib/libkvm/kvm_mips.c new file mode 100644 index 000000000000..b0f4cfe31b7a --- /dev/null +++ b/lib/libkvm/kvm_mips.c @@ -0,0 +1,207 @@ +/*- + * Copyright (c) 1989, 1992, 1993 + *	The Regents of the University of California.  All rights reserved. + * + * This code is derived from software developed by the Computer Systems + * Engineering group at Lawrence Berkeley Laboratory under DARPA contract + * BG 91-66 and contributed to Berkeley. Modified for MIPS by Ralph Campbell. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + *    notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + *    notice, this list of conditions and the following disclaimer in the + *    documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + *    must display the following acknowledgement: + *	This product includes software developed by the University of + *	California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + *    may be used to endorse or promote products derived from this software + *    without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#if defined(LIBC_SCCS) && !defined(lint) +static char sccsid[] = "@(#)kvm_mips.c	8.1 (Berkeley) 6/4/93"; +#endif /* LIBC_SCCS and not lint */ +/* + * MIPS machine dependent routines for kvm.  Hopefully, the forthcoming  + * vm code will one day obsolete this module. + */ + +#include <sys/param.h> +#include <sys/user.h> +#include <sys/proc.h> +#include <sys/stat.h> +#include <unistd.h> +#include <nlist.h> +#include <kvm.h> + +#include <vm/vm.h> +#include <vm/vm_param.h> + +#include <limits.h> +#include <db.h> + +#include "kvm_private.h" + +#include <machine/machConst.h> +#include <machine/pte.h> +#include <machine/pmap.h> + +struct vmstate { +	pt_entry_t	*Sysmap; +	u_int		Sysmapsize; +}; + +#define KREAD(kd, addr, p)\ +	(kvm_read(kd, addr, (char *)(p), sizeof(*(p))) != sizeof(*(p))) + +void +_kvm_freevtop(kd) +	kvm_t *kd; +{ +	if (kd->vmst != 0) +		free(kd->vmst); +} + +int +_kvm_initvtop(kd) +	kvm_t *kd; +{ +	struct vmstate *vm; +	struct nlist nlist[3]; + +	vm = (struct vmstate *)_kvm_malloc(kd, sizeof(*vm)); +	if (vm == 0) +		return (-1); +	kd->vmst = vm; + +	nlist[0].n_name = "Sysmap"; +	nlist[1].n_name = "Sysmapsize"; +	nlist[2].n_name = 0; + +	if (kvm_nlist(kd, nlist) != 0) { +		_kvm_err(kd, kd->program, "bad namelist"); +		return (-1); +	} +	if (KREAD(kd, (u_long)nlist[0].n_value, &vm->Sysmap)) { +		_kvm_err(kd, kd->program, "cannot read Sysmap"); +		return (-1); +	} +	if (KREAD(kd, (u_long)nlist[1].n_value, &vm->Sysmapsize)) { +		_kvm_err(kd, kd->program, "cannot read mmutype"); +		return (-1); +	} +	return (0); +} + +/* + * Translate a kernel virtual address to a physical address. + */ +int +_kvm_kvatop(kd, va, pa) +	kvm_t *kd; +	u_long va; +	u_long *pa; +{ +	register struct vmstate *vm; +	u_long pte, addr, offset; + +	if (ISALIVE(kd)) { +		_kvm_err(kd, 0, "vatop called in live kernel!"); +		return((off_t)0); +	} +	vm = kd->vmst; +	offset = va & PGOFSET; +	/* +	 * If we are initializing (kernel segment table pointer not yet set) +	 * then return pa == va to avoid infinite recursion. +	 */ +	if (vm->Sysmap == 0) { +		*pa = va; +		return (NBPG - offset); +	} +	if (va < KERNBASE || +	    va >= VM_MIN_KERNEL_ADDRESS + vm->Sysmapsize * NBPG) +		goto invalid; +	if (va < VM_MIN_KERNEL_ADDRESS) { +		*pa = MACH_CACHED_TO_PHYS(va); +		return (NBPG - offset); +	} +	addr = (u_long)(vm->Sysmap + ((va - VM_MIN_KERNEL_ADDRESS) >> PGSHIFT)); +	/* +	 * Can't use KREAD to read kernel segment table entries. +	 * Fortunately it is 1-to-1 mapped so we don't have to.  +	 */ +	if (lseek(kd->pmfd, (off_t)addr, 0) < 0 || +	    read(kd->pmfd, (char *)&pte, sizeof(pte)) < 0) +		goto invalid; +	if (!(pte & PG_V)) +		goto invalid; +	*pa = (pte & PG_FRAME) | offset; +	return (NBPG - offset); + +invalid: +	_kvm_err(kd, 0, "invalid address (%x)", va); +	return (0); +} + +/* + * Translate a user virtual address to a physical address. + */ +int +_kvm_uvatop(kd, p, va, pa) +	kvm_t *kd; +	const struct proc *p; +	u_long va; +	u_long *pa; +{ +	register struct vmspace *vms = p->p_vmspace; +	u_long kva, offset; + +	if (va >= KERNBASE) +		goto invalid; + +	/* read the address of the first level table */ +	kva = (u_long)&vms->vm_pmap.pm_segtab; +	if (kvm_read(kd, kva, (char *)&kva, sizeof(kva)) != sizeof(kva)) +		goto invalid; +	if (kva == 0) +		goto invalid; + +	/* read the address of the second level table */ +	kva += (va >> SEGSHIFT) * sizeof(caddr_t); +	if (kvm_read(kd, kva, (char *)&kva, sizeof(kva)) != sizeof(kva)) +		goto invalid; +	if (kva == 0) +		goto invalid; + +	/* read the pte from the second level table */ +	kva += (va >> PGSHIFT) & (NPTEPG - 1); +	if (kvm_read(kd, kva, (char *)&kva, sizeof(kva)) != sizeof(kva)) +		goto invalid; +	if (!(kva & PG_V)) +		goto invalid; +	offset = va & PGOFSET; +	*pa = (kva & PG_FRAME) | offset; +	return (NBPG - offset); + +invalid: +	_kvm_err(kd, 0, "invalid address (%x)", va); +	return (0); +} diff --git a/lib/libkvm/kvm_nlist.3 b/lib/libkvm/kvm_nlist.3 new file mode 100644 index 000000000000..1c0cd89af75b --- /dev/null +++ b/lib/libkvm/kvm_nlist.3 @@ -0,0 +1,88 @@ +.\" Copyright (c) 1992, 1993 +.\"	The Regents of the University of California.  All rights reserved. +.\" +.\" This code is derived from software developed by the Computer Systems +.\" Engineering group at Lawrence Berkeley Laboratory under DARPA contract +.\" BG 91-66 and contributed to Berkeley. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\"    notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\"    notice, this list of conditions and the following disclaimer in the +.\"    documentation and/or other materials provided with the distribution. +.\" 3. All advertising materials mentioning features or use of this software +.\"    must display the following acknowledgement: +.\"	This product includes software developed by the University of +.\"	California, Berkeley and its contributors. +.\" 4. Neither the name of the University nor the names of its contributors +.\"    may be used to endorse or promote products derived from this software +.\"    without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\"     @(#)kvm_nlist.3	8.1 (Berkeley) 6/4/93 +.\" +.Dd June 4, 1993 +.Dt KVM_NLIST 3 +.Os +.Sh NAME +.Nm kvm_nlist +.Nd retrieve symbol table names from a kernel image +.Sh SYNOPSIS +.Fd #include <kvm.h> +.Fd #include <nlist.h> +.Ft int +.Fn kvm_nlist "kvm_t *kd" "struct nlist *nl" +.Sh DESCRIPTION +.Fn kvm_nlist +retrieves the symbol table entries indicated by the name list argument +.Fa \&nl . +This argument points to an array of nlist structures, terminated by +an entry whose n_name field is +.Dv NULL +(see +.Xr nlist 3 ) . +Each symbol is looked up using the n_name field, and if found, the +corresponding n_type and n_value fields are filled in.  These fields are set +to 0 if the symbol is not found. +.Pp +The program +.Xr kvm_mkdb 8 +builds a database from the running kernel's namelist. +If the database matches the opened kernel, +.Fn kvm_nlist +uses it to speed lookups. +.Sh RETURN VALUES +The +.Fn kvm_nlist +function returns the number of invalid entries found. +If the kernel symbol table was unreadable, -1 is returned. +.Sh FILES +.Bl -tag -width /var/db/kvm_vmunix.db -compact +.It Pa /var/db/kvm_vmunix.db +.El +.Sh SEE ALSO +.Xr kvm 3 , +.Xr kvm_close 3 , +.Xr kvm_getargv 3 , +.Xr kvm_getenvv 3 , +.Xr kvm_geterr 3 , +.Xr kvm_getprocs 3 , +.Xr kvm_open 3 , +.Xr kvm_openfiles 3 , +.Xr kvm_read 3 , +.Xr kvm_write 3 , +.Xr kvm_mkdb 8 diff --git a/lib/libkvm/kvm_open.3 b/lib/libkvm/kvm_open.3 new file mode 100644 index 000000000000..dd6895b417d4 --- /dev/null +++ b/lib/libkvm/kvm_open.3 @@ -0,0 +1,186 @@ +.\" Copyright (c) 1992, 1993 +.\"	The Regents of the University of California.  All rights reserved. +.\" +.\" This code is derived from software developed by the Computer Systems +.\" Engineering group at Lawrence Berkeley Laboratory under DARPA contract +.\" BG 91-66 and contributed to Berkeley. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\"    notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\"    notice, this list of conditions and the following disclaimer in the +.\"    documentation and/or other materials provided with the distribution. +.\" 3. All advertising materials mentioning features or use of this software +.\"    must display the following acknowledgement: +.\"	This product includes software developed by the University of +.\"	California, Berkeley and its contributors. +.\" 4. Neither the name of the University nor the names of its contributors +.\"    may be used to endorse or promote products derived from this software +.\"    without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\"     @(#)kvm_open.3	8.3 (Berkeley) 4/19/94 +.\" +.Dd April 19, 1994 +.Dt KVM_OPEN 3 +.Os +.Sh NAME +.Nm kvm_open , +.Nm kvm_openfiles , +.Nm kvm_close +.Nd initialize kernel virtual memory access +.Sh SYNOPSIS +.Fd #include <fcntl.h> +.Fd #include <kvm.h> +.br +.Ft kvm_t * +.Fn kvm_open "const char *execfile" "const char *corefile" "char *swapfile" "int flags" "const char *errstr" +.Ft kvm_t * +.Fn kvm_openfiles "const char *execfile" "const char *corefile" "char *swapfile" "int flags" "char *errbuf" +.Ft int +.Fn kvm_close "kvm_t *kd" +.Sh DESCRIPTION +The functions +.Fn kvm_open +and  +.Fn kvm_openfiles +return a descriptor used to access kernel virtual memory +via the  +.Xr kvm 3 +library routines.  Both active kernels and crash dumps are accessible +through this interface. +.Pp +.Fa execfile +is the executable image of the kernel being examined. +This file must contain a symbol table. +If this argument is +.Dv NULL , +the currently running system is assumed, +which is indicated by +.Dv _PATH_UNIX +in <paths.h>. +.Pp +.Fa corefile  +is the kernel memory device file.  It can be either /dev/mem +or a crash dump core generated by  +.Xr savecore 8 . +If +.Fa corefile +is +.Dv NULL , +the default indicated by +.Dv _PATH_MEM +from <paths.h> is used. +.Pp +.Fa swapfile +should indicate the swap device.  If +.Dv NULL , +.Dv _PATH_DRUM +from <paths.h> is used. +.Pp +The +.Fa flags  +argument indicates read/write access as in +.Xr open 2 +and applies only to the core file. +Only +.Dv O_RDONLY , +.Dv O_WRONLY , +and +.Dv O_RDWR +are permitted. +.Pp +There are two open routines which differ only with respect to  +the error mechanism. +One provides backward compatibility with the SunOS kvm library, while the +other provides an improved error reporting framework. +.Pp +The +.Fn kvm_open +function is the Sun kvm compatible open call.  Here, the +.Fa errstr +argument indicates how errors should be handled.  If it is +.Dv NULL , +no errors are reported and the application cannot know the  +specific nature of the failed kvm call. +If it is not +.Dv NULL , +errors are printed to stderr with  +.Fa errstr +prepended to the message, as in +.Xr perror 3 . +Normally, the name of the program is used here. +The string is assumed to persist at least until the corresponding +.Fn kvm_close +call. +.Pp +The +.Fn kvm_openfiles +function provides BSD style error reporting. +Here, error messages are not printed out by the library. +Instead, the application obtains the error message +corresponding to the most recent kvm library call using +.Fn kvm_geterr +(see +.Xr kvm_geterr 3 ). +The results are undefined if the most recent kvm call did not produce +an error. +Since +.Fn kvm_geterr +requires a kvm descriptor, but the open routines return +.Dv NULL +on failure, +.Fn kvm_geterr +cannot be used to get the error message if open fails. +Thus, +.Fn kvm_openfiles +will place any error message in the +.Fa errbuf +argument.  This buffer should be _POSIX2_LINE_MAX characters large (from +<limits.h>). +.Sh RETURN VALUES +The +.Fn kvm_open +and  +.Fn kvm_openfiles +functions both return a descriptor to be used +in all subsequent kvm library calls. +The library is fully re-entrant. +On failure, +.Dv NULL +is returned, in which case +.Fn kvm_openfiles +writes the error message into  +.Fa errbuf . +.Pp +The +.Fn kvm_close +function returns 0 on success and -1 on failure. +.Sh BUGS +There should not be two open calls.  The ill-defined error semantics +of the Sun library and the desire to have a backward-compatible library +for BSD left little choice. +.Sh SEE ALSO +.Xr open 2 , +.Xr kvm 3 , +.Xr kvm_getargv 3 , +.Xr kvm_getenvv 3 , +.Xr kvm_geterr 3 , +.Xr kvm_getprocs 3 , +.Xr kvm_nlist 3 , +.Xr kvm_read 3 , +.Xr kvm_write 3 diff --git a/lib/libkvm/kvm_private.h b/lib/libkvm/kvm_private.h new file mode 100644 index 000000000000..baaeb053814b --- /dev/null +++ b/lib/libkvm/kvm_private.h @@ -0,0 +1,81 @@ +/*- + * Copyright (c) 1992, 1993 + *	The Regents of the University of California.  All rights reserved. + * + * This code is derived from software developed by the Computer Systems + * Engineering group at Lawrence Berkeley Laboratory under DARPA contract + * BG 91-66 and contributed to Berkeley. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + *    notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + *    notice, this list of conditions and the following disclaimer in the + *    documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + *    must display the following acknowledgement: + *	This product includes software developed by the University of + *	California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + *    may be used to endorse or promote products derived from this software + *    without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + *	@(#)kvm_private.h	8.1 (Berkeley) 6/4/93 + */ + +struct __kvm { +	/* +	 * a string to be prepended to error messages +	 * provided for compatibility with sun's interface +	 * if this value is null, errors are saved in errbuf[] +	 */ +	const char *program; +	char	*errp;		/* XXX this can probably go away */ +	char	errbuf[_POSIX2_LINE_MAX]; +	DB	*db; +#define ISALIVE(kd) ((kd)->vmfd >= 0) +	int	pmfd;		/* physical memory file (or crashdump) */ +	int	vmfd;		/* virtual memory file (-1 if crashdump) */ +	int	swfd;		/* swap file (e.g., /dev/drum) */ +	int	nlfd;		/* namelist file (e.g., /vmunix) */ +	struct kinfo_proc *procbase; +	char	*argspc;	/* (dynamic) storage for argv strings */ +	int	arglen;		/* length of the above */ +	char	**argv;		/* (dynamic) storage for argv pointers */ +	int	argc;		/* length of above (not actual # present) */ +	/* +	 * Kernel virtual address translation state.  This only gets filled +	 * in for dead kernels; otherwise, the running kernel (i.e. kmem) +	 * will do the translations for us.  It could be big, so we +	 * only allocate it if necessary. +	 */ +	struct vmstate *vmst; +}; + +/* + * Functions used internally by kvm, but across kvm modules. + */ +void	 _kvm_err __P((kvm_t *kd, const char *program, const char *fmt, ...)); +void	 _kvm_freeprocs __P((kvm_t *kd)); +void	 _kvm_freevtop __P((kvm_t *)); +int	 _kvm_initvtop __P((kvm_t *)); +int	 _kvm_kvatop __P((kvm_t *, u_long, u_long *)); +void	*_kvm_malloc __P((kvm_t *kd, size_t)); +void	*_kvm_realloc __P((kvm_t *kd, void *, size_t)); +void	 _kvm_syserr +	    __P((kvm_t *kd, const char *program, const char *fmt, ...)); +int	 _kvm_uvatop __P((kvm_t *, const struct proc *, u_long, u_long *)); diff --git a/lib/libkvm/kvm_proc.c b/lib/libkvm/kvm_proc.c new file mode 100644 index 000000000000..5daccd53d33d --- /dev/null +++ b/lib/libkvm/kvm_proc.c @@ -0,0 +1,705 @@ +/*- + * Copyright (c) 1989, 1992, 1993 + *	The Regents of the University of California.  All rights reserved. + * + * This code is derived from software developed by the Computer Systems + * Engineering group at Lawrence Berkeley Laboratory under DARPA contract + * BG 91-66 and contributed to Berkeley. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + *    notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + *    notice, this list of conditions and the following disclaimer in the + *    documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + *    must display the following acknowledgement: + *	This product includes software developed by the University of + *	California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + *    may be used to endorse or promote products derived from this software + *    without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#if defined(LIBC_SCCS) && !defined(lint) +static char sccsid[] = "@(#)kvm_proc.c	8.3 (Berkeley) 9/23/93"; +#endif /* LIBC_SCCS and not lint */ + +/* + * Proc traversal interface for kvm.  ps and w are (probably) the exclusive + * users of this code, so we've factored it out into a separate module. + * Thus, we keep this grunge out of the other kvm applications (i.e., + * most other applications are interested only in open/close/read/nlist). + */ + +#include <sys/param.h> +#include <sys/user.h> +#include <sys/proc.h> +#include <sys/exec.h> +#include <sys/stat.h> +#include <sys/ioctl.h> +#include <sys/tty.h> +#include <unistd.h> +#include <nlist.h> +#include <kvm.h> + +#include <vm/vm.h> +#include <vm/vm_param.h> +#include <vm/swap_pager.h> + +#include <sys/sysctl.h> + +#include <limits.h> +#include <db.h> +#include <paths.h> + +#include "kvm_private.h" + +static char * +kvm_readswap(kd, p, va, cnt) +	kvm_t *kd; +	const struct proc *p; +	u_long va; +	u_long *cnt; +{ +	register int ix; +	register u_long addr, head; +	register u_long offset, pagestart, sbstart, pgoff; +	register off_t seekpoint; +	struct vm_map_entry vme; +	struct vm_object vmo; +	struct pager_struct pager; +	struct swpager swap; +	struct swblock swb; +	static char page[NBPG]; + +	head = (u_long)&p->p_vmspace->vm_map.header; +	/* +	 * Look through the address map for the memory object +	 * that corresponds to the given virtual address. +	 * The header just has the entire valid range. +	 */ +	addr = head; +	while (1) { +		if (kvm_read(kd, addr, (char *)&vme, sizeof(vme)) !=  +		    sizeof(vme)) +			return (0); + +		if (va >= vme.start && va <= vme.end &&  +		    vme.object.vm_object != 0) +			break; + +		addr = (u_long)vme.next; +		if (addr == 0 || addr == head) +			return (0); +	} +	/* +	 * We found the right object -- follow shadow links. +	 */ +	offset = va - vme.start + vme.offset; +	addr = (u_long)vme.object.vm_object; +	while (1) { +		if (kvm_read(kd, addr, (char *)&vmo, sizeof(vmo)) !=  +		    sizeof(vmo)) +			return (0); +		addr = (u_long)vmo.shadow; +		if (addr == 0) +			break; +		offset += vmo.shadow_offset; +	} +	if (vmo.pager == 0) +		return (0); + +	offset += vmo.paging_offset; +	/* +	 * Read in the pager info and make sure it's a swap device. +	 */ +	addr = (u_long)vmo.pager; +	if (kvm_read(kd, addr, (char *)&pager, sizeof(pager)) != sizeof(pager) +	    || pager.pg_type != PG_SWAP) +		return (0); + +	/* +	 * Read in the swap_pager private data, and compute the +	 * swap offset. +	 */ +	addr = (u_long)pager.pg_data; +	if (kvm_read(kd, addr, (char *)&swap, sizeof(swap)) != sizeof(swap)) +		return (0); +	ix = offset / dbtob(swap.sw_bsize); +	if (swap.sw_blocks == 0 || ix >= swap.sw_nblocks) +		return (0); + +	addr = (u_long)&swap.sw_blocks[ix]; +	if (kvm_read(kd, addr, (char *)&swb, sizeof(swb)) != sizeof(swb)) +		return (0); + +	sbstart = (offset / dbtob(swap.sw_bsize)) * dbtob(swap.sw_bsize); +	sbstart /= NBPG; +	pagestart = offset / NBPG; +	pgoff = pagestart - sbstart; + +	if (swb.swb_block == 0 || (swb.swb_mask & (1 << pgoff)) == 0) +		return (0); + +	seekpoint = dbtob(swb.swb_block) + ctob(pgoff); +	errno = 0; +	if (lseek(kd->swfd, seekpoint, 0) == -1 && errno != 0) +		return (0); +	if (read(kd->swfd, page, sizeof(page)) != sizeof(page)) +		return (0); + +	offset %= NBPG; +	*cnt = NBPG - offset; +	return (&page[offset]); +} + +#define KREAD(kd, addr, obj) \ +	(kvm_read(kd, addr, (char *)(obj), sizeof(*obj)) != sizeof(*obj)) + +/* + * Read proc's from memory file into buffer bp, which has space to hold + * at most maxcnt procs. + */ +static int +kvm_proclist(kd, what, arg, p, bp, maxcnt) +	kvm_t *kd; +	int what, arg; +	struct proc *p; +	struct kinfo_proc *bp; +	int maxcnt; +{ +	register int cnt = 0; +	struct eproc eproc; +	struct pgrp pgrp; +	struct session sess; +	struct tty tty; +	struct proc proc; + +	for (; cnt < maxcnt && p != NULL; p = proc.p_next) { +		if (KREAD(kd, (u_long)p, &proc)) { +			_kvm_err(kd, kd->program, "can't read proc at %x", p); +			return (-1); +		} +		if (KREAD(kd, (u_long)proc.p_cred, &eproc.e_pcred) == 0) +			KREAD(kd, (u_long)eproc.e_pcred.pc_ucred, +			      &eproc.e_ucred); + +		switch(what) { +			 +		case KERN_PROC_PID: +			if (proc.p_pid != (pid_t)arg) +				continue; +			break; + +		case KERN_PROC_UID: +			if (eproc.e_ucred.cr_uid != (uid_t)arg) +				continue; +			break; + +		case KERN_PROC_RUID: +			if (eproc.e_pcred.p_ruid != (uid_t)arg) +				continue; +			break; +		} +		/* +		 * We're going to add another proc to the set.  If this +		 * will overflow the buffer, assume the reason is because +		 * nprocs (or the proc list) is corrupt and declare an error. +		 */ +		if (cnt >= maxcnt) { +			_kvm_err(kd, kd->program, "nprocs corrupt"); +			return (-1); +		} +		/* +		 * gather eproc +		 */ +		eproc.e_paddr = p; +		if (KREAD(kd, (u_long)proc.p_pgrp, &pgrp)) { +			_kvm_err(kd, kd->program, "can't read pgrp at %x", +				 proc.p_pgrp); +			return (-1); +		} +		eproc.e_sess = pgrp.pg_session; +		eproc.e_pgid = pgrp.pg_id; +		eproc.e_jobc = pgrp.pg_jobc; +		if (KREAD(kd, (u_long)pgrp.pg_session, &sess)) { +			_kvm_err(kd, kd->program, "can't read session at %x",  +				pgrp.pg_session); +			return (-1); +		} +		if ((proc.p_flag & P_CONTROLT) && sess.s_ttyp != NULL) { +			if (KREAD(kd, (u_long)sess.s_ttyp, &tty)) { +				_kvm_err(kd, kd->program, +					 "can't read tty at %x", sess.s_ttyp); +				return (-1); +			} +			eproc.e_tdev = tty.t_dev; +			eproc.e_tsess = tty.t_session; +			if (tty.t_pgrp != NULL) { +				if (KREAD(kd, (u_long)tty.t_pgrp, &pgrp)) { +					_kvm_err(kd, kd->program, +						 "can't read tpgrp at &x",  +						tty.t_pgrp); +					return (-1); +				} +				eproc.e_tpgid = pgrp.pg_id; +			} else +				eproc.e_tpgid = -1; +		} else +			eproc.e_tdev = NODEV; +		eproc.e_flag = sess.s_ttyvp ? EPROC_CTTY : 0; +		if (sess.s_leader == p) +			eproc.e_flag |= EPROC_SLEADER; +		if (proc.p_wmesg) +			(void)kvm_read(kd, (u_long)proc.p_wmesg,  +			    eproc.e_wmesg, WMESGLEN); + +#ifdef sparc +		(void)kvm_read(kd, (u_long)&proc.p_vmspace->vm_rssize, +		    (char *)&eproc.e_vm.vm_rssize, +		    sizeof(eproc.e_vm.vm_rssize)); +		(void)kvm_read(kd, (u_long)&proc.p_vmspace->vm_tsize, +		    (char *)&eproc.e_vm.vm_tsize, +		    3 * sizeof(eproc.e_vm.vm_rssize));	/* XXX */ +#else +		(void)kvm_read(kd, (u_long)proc.p_vmspace, +		    (char *)&eproc.e_vm, sizeof(eproc.e_vm)); +#endif +		eproc.e_xsize = eproc.e_xrssize = 0; +		eproc.e_xccount = eproc.e_xswrss = 0; + +		switch (what) { + +		case KERN_PROC_PGRP: +			if (eproc.e_pgid != (pid_t)arg) +				continue; +			break; + +		case KERN_PROC_TTY: +			if ((proc.p_flag & P_CONTROLT) == 0 ||  +			     eproc.e_tdev != (dev_t)arg) +				continue; +			break; +		} +		bcopy(&proc, &bp->kp_proc, sizeof(proc)); +		bcopy(&eproc, &bp->kp_eproc, sizeof(eproc)); +		++bp; +		++cnt; +	} +	return (cnt); +} + +/* + * Build proc info array by reading in proc list from a crash dump. + * Return number of procs read.  maxcnt is the max we will read. + */ +static int +kvm_deadprocs(kd, what, arg, a_allproc, a_zombproc, maxcnt) +	kvm_t *kd; +	int what, arg; +	u_long a_allproc; +	u_long a_zombproc; +	int maxcnt; +{ +	register struct kinfo_proc *bp = kd->procbase; +	register int acnt, zcnt; +	struct proc *p; + +	if (KREAD(kd, a_allproc, &p)) { +		_kvm_err(kd, kd->program, "cannot read allproc"); +		return (-1); +	} +	acnt = kvm_proclist(kd, what, arg, p, bp, maxcnt); +	if (acnt < 0) +		return (acnt); + +	if (KREAD(kd, a_zombproc, &p)) { +		_kvm_err(kd, kd->program, "cannot read zombproc"); +		return (-1); +	} +	zcnt = kvm_proclist(kd, what, arg, p, bp + acnt, maxcnt - acnt); +	if (zcnt < 0) +		zcnt = 0; + +	return (acnt + zcnt); +} + +struct kinfo_proc * +kvm_getprocs(kd, op, arg, cnt) +	kvm_t *kd; +	int op, arg; +	int *cnt; +{ +	int mib[4], size, st, nprocs; + +	if (kd->procbase != 0) { +		free((void *)kd->procbase); +		/*  +		 * Clear this pointer in case this call fails.  Otherwise, +		 * kvm_close() will free it again. +		 */ +		kd->procbase = 0; +	} +	if (ISALIVE(kd)) { +		size = 0; +		mib[0] = CTL_KERN; +		mib[1] = KERN_PROC; +		mib[2] = op; +		mib[3] = arg; +		st = sysctl(mib, 4, NULL, &size, NULL, 0); +		if (st == -1) { +			_kvm_syserr(kd, kd->program, "kvm_getprocs"); +			return (0); +		} +		kd->procbase = (struct kinfo_proc *)_kvm_malloc(kd, size); +		if (kd->procbase == 0) +			return (0); +		st = sysctl(mib, 4, kd->procbase, &size, NULL, 0); +		if (st == -1) { +			_kvm_syserr(kd, kd->program, "kvm_getprocs"); +			return (0); +		} +		if (size % sizeof(struct kinfo_proc) != 0) { +			_kvm_err(kd, kd->program, +				"proc size mismatch (%d total, %d chunks)", +				size, sizeof(struct kinfo_proc)); +			return (0); +		} +		nprocs = size / sizeof(struct kinfo_proc); +	} else { +		struct nlist nl[4], *p; + +		nl[0].n_name = "_nprocs"; +		nl[1].n_name = "_allproc"; +		nl[2].n_name = "_zombproc"; +		nl[3].n_name = 0; + +		if (kvm_nlist(kd, nl) != 0) { +			for (p = nl; p->n_type != 0; ++p) +				; +			_kvm_err(kd, kd->program, +				 "%s: no such symbol", p->n_name); +			return (0); +		} +		if (KREAD(kd, nl[0].n_value, &nprocs)) { +			_kvm_err(kd, kd->program, "can't read nprocs"); +			return (0); +		} +		size = nprocs * sizeof(struct kinfo_proc); +		kd->procbase = (struct kinfo_proc *)_kvm_malloc(kd, size); +		if (kd->procbase == 0) +			return (0); + +		nprocs = kvm_deadprocs(kd, op, arg, nl[1].n_value, +				      nl[2].n_value, nprocs); +#ifdef notdef +		size = nprocs * sizeof(struct kinfo_proc); +		(void)realloc(kd->procbase, size); +#endif +	} +	*cnt = nprocs; +	return (kd->procbase); +} + +void +_kvm_freeprocs(kd) +	kvm_t *kd; +{ +	if (kd->procbase) { +		free(kd->procbase); +		kd->procbase = 0; +	} +} + +void * +_kvm_realloc(kd, p, n) +	kvm_t *kd; +	void *p; +	size_t n; +{ +	void *np = (void *)realloc(p, n); + +	if (np == 0) +		_kvm_err(kd, kd->program, "out of memory"); +	return (np); +} + +#ifndef MAX +#define MAX(a, b) ((a) > (b) ? (a) : (b)) +#endif + +/* + * Read in an argument vector from the user address space of process p. + * addr if the user-space base address of narg null-terminated contiguous  + * strings.  This is used to read in both the command arguments and + * environment strings.  Read at most maxcnt characters of strings. + */ +static char ** +kvm_argv(kd, p, addr, narg, maxcnt) +	kvm_t *kd; +	struct proc *p; +	register u_long addr; +	register int narg; +	register int maxcnt; +{ +	register char *cp; +	register int len, cc; +	register char **argv; + +	/* +	 * Check that there aren't an unreasonable number of agruments, +	 * and that the address is in user space. +	 */ +	if (narg > 512 || addr < VM_MIN_ADDRESS || addr >= VM_MAXUSER_ADDRESS) +		return (0); + +	if (kd->argv == 0) { +		/* +		 * Try to avoid reallocs. +		 */ +		kd->argc = MAX(narg + 1, 32); +		kd->argv = (char **)_kvm_malloc(kd, kd->argc *  +						sizeof(*kd->argv)); +		if (kd->argv == 0) +			return (0); +	} else if (narg + 1 > kd->argc) { +		kd->argc = MAX(2 * kd->argc, narg + 1); +		kd->argv = (char **)_kvm_realloc(kd, kd->argv, kd->argc *  +						sizeof(*kd->argv)); +		if (kd->argv == 0) +			return (0); +	} +	if (kd->argspc == 0) { +		kd->argspc = (char *)_kvm_malloc(kd, NBPG); +		if (kd->argspc == 0) +			return (0); +		kd->arglen = NBPG; +	} +	cp = kd->argspc; +	argv = kd->argv; +	*argv = cp; +	len = 0; +	/* +	 * Loop over pages, filling in the argument vector. +	 */ +	while (addr < VM_MAXUSER_ADDRESS) { +		cc = NBPG - (addr & PGOFSET); +		if (maxcnt > 0 && cc > maxcnt - len) +			cc = maxcnt - len;; +		if (len + cc > kd->arglen) { +			register int off; +			register char **pp; +			register char *op = kd->argspc; + +			kd->arglen *= 2; +			kd->argspc = (char *)_kvm_realloc(kd, kd->argspc, +							  kd->arglen); +			if (kd->argspc == 0) +				return (0); +			cp = &kd->argspc[len]; +			/* +			 * Adjust argv pointers in case realloc moved +			 * the string space. +			 */ +			off = kd->argspc - op; +			for (pp = kd->argv; pp < argv; ++pp) +				*pp += off; +		} +		if (kvm_uread(kd, p, addr, cp, cc) != cc) +			/* XXX */ +			return (0); +		len += cc; +		addr += cc; + +		if (maxcnt == 0 && len > 16 * NBPG) +			/* sanity */ +			return (0); + +		while (--cc >= 0) { +			if (*cp++ == 0) { +				if (--narg <= 0) { +					*++argv = 0; +					return (kd->argv); +				} else +					*++argv = cp; +			} +		} +		if (maxcnt > 0 && len >= maxcnt) { +			/* +			 * We're stopping prematurely.  Terminate the +			 * argv and current string. +			 */ +			*++argv = 0; +			*cp = 0; +			return (kd->argv); +		} +	} +} + +static void +ps_str_a(p, addr, n) +	struct ps_strings *p; +	u_long *addr; +	int *n; +{ +	*addr = (u_long)p->ps_argvstr; +	*n = p->ps_nargvstr; +} + +static void +ps_str_e(p, addr, n) +	struct ps_strings *p; +	u_long *addr; +	int *n; +{ +	*addr = (u_long)p->ps_envstr; +	*n = p->ps_nenvstr; +} + +/* + * Determine if the proc indicated by p is still active. + * This test is not 100% foolproof in theory, but chances of + * being wrong are very low. + */ +static int +proc_verify(kd, kernp, p) +	kvm_t *kd; +	u_long kernp; +	const struct proc *p; +{ +	struct proc kernproc; + +	/* +	 * Just read in the whole proc.  It's not that big relative +	 * to the cost of the read system call. +	 */ +	if (kvm_read(kd, kernp, (char *)&kernproc, sizeof(kernproc)) !=  +	    sizeof(kernproc)) +		return (0); +	return (p->p_pid == kernproc.p_pid && +		(kernproc.p_stat != SZOMB || p->p_stat == SZOMB)); +} + +static char ** +kvm_doargv(kd, kp, nchr, info) +	kvm_t *kd; +	const struct kinfo_proc *kp; +	int nchr; +	int (*info)(struct ps_strings*, u_long *, int *); +{ +	register const struct proc *p = &kp->kp_proc; +	register char **ap; +	u_long addr; +	int cnt; +	struct ps_strings arginfo; + +	/* +	 * Pointers are stored at the top of the user stack. +	 */ +	if (p->p_stat == SZOMB ||  +	    kvm_uread(kd, p, USRSTACK - sizeof(arginfo), (char *)&arginfo, +		      sizeof(arginfo)) != sizeof(arginfo)) +		return (0); + +	(*info)(&arginfo, &addr, &cnt); +	ap = kvm_argv(kd, p, addr, cnt, nchr); +	/* +	 * For live kernels, make sure this process didn't go away. +	 */ +	if (ap != 0 && ISALIVE(kd) && +	    !proc_verify(kd, (u_long)kp->kp_eproc.e_paddr, p)) +		ap = 0; +	return (ap); +} + +/* + * Get the command args.  This code is now machine independent. + */ +char ** +kvm_getargv(kd, kp, nchr) +	kvm_t *kd; +	const struct kinfo_proc *kp; +	int nchr; +{ +	return (kvm_doargv(kd, kp, nchr, ps_str_a)); +} + +char ** +kvm_getenvv(kd, kp, nchr) +	kvm_t *kd; +	const struct kinfo_proc *kp; +	int nchr; +{ +	return (kvm_doargv(kd, kp, nchr, ps_str_e)); +} + +/* + * Read from user space.  The user context is given by p. + */ +ssize_t +kvm_uread(kd, p, uva, buf, len) +	kvm_t *kd; +	register struct proc *p; +	register u_long uva; +	register char *buf; +	register size_t len; +{ +	register char *cp; + +	cp = buf; +	while (len > 0) { +		u_long pa; +		register int cc; +		 +		cc = _kvm_uvatop(kd, p, uva, &pa); +		if (cc > 0) { +			if (cc > len) +				cc = len; +			errno = 0; +			if (lseek(kd->pmfd, (off_t)pa, 0) == -1 && errno != 0) { +				_kvm_err(kd, 0, "invalid address (%x)", uva); +				break; +			} +			cc = read(kd->pmfd, cp, cc); +			if (cc < 0) { +				_kvm_syserr(kd, 0, _PATH_MEM); +				break; +			} else if (cc < len) { +				_kvm_err(kd, kd->program, "short read"); +				break; +			} +		} else if (ISALIVE(kd)) { +			/* try swap */ +			register char *dp; +			int cnt; + +			dp = kvm_readswap(kd, p, uva, &cnt); +			if (dp == 0) { +				_kvm_err(kd, 0, "invalid address (%x)", uva); +				return (0); +			} +			cc = MIN(cnt, len); +			bcopy(dp, cp, cc); +		} else +			break; +		cp += cc; +		uva += cc; +		len -= cc; +	} +	return (ssize_t)(cp - buf); +} diff --git a/lib/libkvm/kvm_read.3 b/lib/libkvm/kvm_read.3 new file mode 100644 index 000000000000..b5609599f6ab --- /dev/null +++ b/lib/libkvm/kvm_read.3 @@ -0,0 +1,92 @@ +.\" Copyright (c) 1992, 1993 +.\"	The Regents of the University of California.  All rights reserved. +.\" +.\" This code is derived from software developed by the Computer Systems +.\" Engineering group at Lawrence Berkeley Laboratory under DARPA contract +.\" BG 91-66 and contributed to Berkeley. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\"    notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\"    notice, this list of conditions and the following disclaimer in the +.\"    documentation and/or other materials provided with the distribution. +.\" 3. All advertising materials mentioning features or use of this software +.\"    must display the following acknowledgement: +.\"	This product includes software developed by the University of +.\"	California, Berkeley and its contributors. +.\" 4. Neither the name of the University nor the names of its contributors +.\"    may be used to endorse or promote products derived from this software +.\"    without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\"     @(#)kvm_read.3	8.1 (Berkeley) 6/4/93 +.\" +.Dd June 4, 1993 +.Dt KVM_READ 3 +.Os +.Sh NAME +.Nm kvm_read , +.Nm kvm_write +.Nd read or write kernel virtual memory +.Sh SYNOPSIS +.Fd #include <kvm.h> +.Ft ssize_t +.Fn kvm_read "kvm_t *kd" "u_long addr" "void *buf" "size_t nbytes" +.Ft ssize_t +.Fn kvm_write "kvm_t *kd" "u_long addr" "const void *buf" "size_t nbytes" +.Sh DESCRIPTION +The +.Fn kvm_read +and +.Fn kvm_write +functions are used to read and write kernel virtual memory (or a crash +dump file). See +.Fn kvm_open 3 +or +.Fn kvm_openfiles 3 +for information regarding opening kernel virtual memory and crash dumps. +.Pp +The +.Fn kvm_read +function transfers +.Fa nbytes  +bytes of data from +the kernel space address +.Fa addr +to +.Fa buf . +Conversely,  +.Fn kvm_write +transfers data from +.Fa buf +to +.Fa addr . +Unlike their SunOS counterparts, these functions cannot be used to  +read or write process address spaces. +.Sh RETURN VALUES +Upon success, the number of bytes actually transferred is returned. +Otherwise, -1 is returned. +.Sh SEE ALSO +.Xr kvm 3 , +.Xr kvm_close 3 , +.Xr kvm_getargv 3 , +.Xr kvm_getenvv 3 , +.Xr kvm_geterr 3 , +.Xr kvm_getprocs 3 , +.Xr kvm_nlist 3 , +.Xr kvm_open 3 , +.Xr kvm_openfiles 3 diff --git a/lib/libkvm/kvm_sparc.c b/lib/libkvm/kvm_sparc.c new file mode 100644 index 000000000000..5275068b6ea3 --- /dev/null +++ b/lib/libkvm/kvm_sparc.c @@ -0,0 +1,236 @@ +/*- + * Copyright (c) 1992, 1993 + *	The Regents of the University of California.  All rights reserved. + * + * This code is derived from software developed by the Computer Systems + * Engineering group at Lawrence Berkeley Laboratory under DARPA contract + * BG 91-66 and contributed to Berkeley. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + *    notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + *    notice, this list of conditions and the following disclaimer in the + *    documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + *    must display the following acknowledgement: + *	This product includes software developed by the University of + *	California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + *    may be used to endorse or promote products derived from this software + *    without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#if defined(LIBC_SCCS) && !defined(lint) +static char sccsid[] = "@(#)kvm_sparc.c	8.1 (Berkeley) 6/4/93"; +#endif /* LIBC_SCCS and not lint */ + +/* + * Sparc machine dependent routines for kvm.  Hopefully, the forthcoming  + * vm code will one day obsolete this module. + */ + +#include <sys/param.h> +#include <sys/user.h> +#include <sys/proc.h> +#include <sys/stat.h> +#include <unistd.h> +#include <nlist.h> +#include <kvm.h> + +#include <vm/vm.h> +#include <vm/vm_param.h> + +#include <limits.h> +#include <db.h> + +#include "kvm_private.h" + +#define NPMEG 128 + +/* XXX from sparc/pmap.c */ +#define MAXMEM  (128 * 1024 * 1024)     /* no more than 128 MB phys mem */ +#define NPGBANK 16                      /* 2^4 pages per bank (64K / bank) */ +#define BSHIFT  4                       /* log2(NPGBANK) */ +#define BOFFSET (NPGBANK - 1) +#define BTSIZE  (MAXMEM / NBPG / NPGBANK) +#define HWTOSW(pmap_stod, pg) (pmap_stod[(pg) >> BSHIFT] | ((pg) & BOFFSET)) + +struct vmstate { +	pmeg_t segmap[NKSEG]; +	int pmeg[NPMEG][NPTESG]; +	int pmap_stod[BTSIZE];              /* dense to sparse */ +}; + +void +_kvm_freevtop(kd) +	kvm_t *kd; +{ +	if (kd->vmst != 0) +		free(kd->vmst); +} + +int +_kvm_initvtop(kd) +	kvm_t *kd; +{ +	register int i; +	register int off; +	register struct vmstate *vm; +	struct stat st; +	struct nlist nlist[2]; + +	vm = (struct vmstate *)_kvm_malloc(kd, sizeof(*vm)); +	if (vm == 0) +		return (-1); + +	kd->vmst = vm; + +	if (fstat(kd->pmfd, &st) < 0) +		return (-1); +	/* +	 * Read segment table. +	 */ +	off = st.st_size - ctob(btoc(sizeof(vm->segmap))); +	errno = 0; +	if (lseek(kd->pmfd, (off_t)off, 0) == -1 && errno != 0 ||  +	    read(kd->pmfd, (char *)vm->segmap, sizeof(vm->segmap)) < 0) { +		_kvm_err(kd, kd->program, "cannot read segment map"); +		return (-1); +	} +	/* +	 * Read PMEGs. +	 */ +	off = st.st_size - ctob(btoc(sizeof(vm->pmeg)) + +	    btoc(sizeof(vm->segmap))); +	errno = 0; +	if (lseek(kd->pmfd, (off_t)off, 0) == -1 && errno != 0 ||  +	    read(kd->pmfd, (char *)vm->pmeg, sizeof(vm->pmeg)) < 0) { +		_kvm_err(kd, kd->program, "cannot read PMEG table"); +		return (-1); +	} +	/* +	 * Make pmap_stod be an identity map so we can bootstrap it in. +	 * We assume it's in the first contiguous chunk of physical memory. +	 */ +	for (i = 0; i < BTSIZE; ++i)  +		vm->pmap_stod[i] = i << 4; + +	/* +	 * It's okay to do this nlist separately from the one kvm_getprocs() +	 * does, since the only time we could gain anything by combining +	 * them is if we do a kvm_getprocs() on a dead kernel, which is +	 * not too common. +	 */ +	nlist[0].n_name = "_pmap_stod"; +	nlist[1].n_name = 0; +	if (kvm_nlist(kd, nlist) != 0) { +		_kvm_err(kd, kd->program, "pmap_stod: no such symbol"); +		return (-1); +	} +	if (kvm_read(kd, (u_long)nlist[0].n_value,  +		     (char *)vm->pmap_stod, sizeof(vm->pmap_stod)) +	    != sizeof(vm->pmap_stod)) { +		_kvm_err(kd, kd->program, "cannot read pmap_stod"); +		return (-1); +	} +	return (0); +} + +#define VA_OFF(va) (va & (NBPG - 1)) + +/* + * Translate a user virtual address to a physical address. + */ +int +_kvm_uvatop(kd, p, va, pa) +	kvm_t *kd; +	const struct proc *p; +	u_long va; +	u_long *pa; +{ +	int kva, pte; +	register int off, frame; +	register struct vmspace *vms = p->p_vmspace; + +	if ((u_long)vms < KERNBASE) { +		_kvm_err(kd, kd->program, "_kvm_uvatop: corrupt proc"); +		return (0); +	} +	if (va >= KERNBASE) +		return (0); +	/* +	 * Get the PTE.  This takes two steps.  We read the +	 * base address of the table, then we index it. +	 * Note that the index pte table is indexed by +	 * virtual segment rather than physical segment. +	 */ +	kva = (u_long)&vms->vm_pmap.pm_rpte[VA_VSEG(va)]; +	if (kvm_read(kd, kva, (char *)&kva, 4) != 4 || kva == 0) +		goto invalid; +	kva += sizeof(vms->vm_pmap.pm_rpte[0]) * VA_VPG(va); +	if (kvm_read(kd, kva, (char *)&pte, 4) == 4 && (pte & PG_V)) { +		off = VA_OFF(va); +		/* +		 * /dev/mem adheres to the hardware model of physical memory +		 * (with holes in the address space), while crashdumps +		 * adhere to the contiguous software model. +		 */ +		if (ISALIVE(kd)) +			frame = pte & PG_PFNUM; +		else +			frame = HWTOSW(kd->vmst->pmap_stod, pte & PG_PFNUM); +		*pa = (frame << PGSHIFT) | off;		 +		return (NBPG - off); +	} +invalid: +	_kvm_err(kd, 0, "invalid address (%x)", va); +	return (0); +} + +/* + * Translate a kernel virtual address to a physical address using the + * mapping information in kd->vm.  Returns the result in pa, and returns + * the number of bytes that are contiguously available from this  + * physical address.  This routine is used only for crashdumps. + */ +int +_kvm_kvatop(kd, va, pa) +	kvm_t *kd; +	u_long va; +	u_long *pa; +{ +	register struct vmstate *vm; +	register int s; +	register int pte; +	register int off; + +	if (va >= KERNBASE) { +		vm = kd->vmst; +		s = vm->segmap[VA_VSEG(va) - NUSEG]; +		pte = vm->pmeg[s][VA_VPG(va)]; +		if ((pte & PG_V) != 0) { +			off = VA_OFF(va); +			*pa = (HWTOSW(vm->pmap_stod, pte & PG_PFNUM) +			       << PGSHIFT) | off; + +			return (NBPG - off); +		} +	} +	_kvm_err(kd, 0, "invalid address (%x)", va); +	return (0); +} | 
