kvm.c revision 215315
1/*-
2 * Copyright (c) 1989, 1992, 1993
3 *	The Regents of the University of California.  All rights reserved.
4 *
5 * This code is derived from software developed by the Computer Systems
6 * Engineering group at Lawrence Berkeley Laboratory under DARPA contract
7 * BG 91-66 and contributed to Berkeley.
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
11 * are met:
12 * 1. Redistributions of source code must retain the above copyright
13 *    notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 *    notice, this list of conditions and the following disclaimer in the
16 *    documentation and/or other materials provided with the distribution.
17 * 4. Neither the name of the University nor the names of its contributors
18 *    may be used to endorse or promote products derived from this software
19 *    without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
32 */
33
34#include <sys/cdefs.h>
35__FBSDID("$FreeBSD: head/lib/libkvm/kvm.c 215315 2010-11-14 20:14:25Z dim $");
36
37#if defined(LIBC_SCCS) && !defined(lint)
38#if 0
39static char sccsid[] = "@(#)kvm.c	8.2 (Berkeley) 2/13/94";
40#endif
41#endif /* LIBC_SCCS and not lint */
42
43#include <sys/param.h>
44
45#define	_WANT_VNET
46
47#include <sys/user.h>
48#include <sys/proc.h>
49#include <sys/ioctl.h>
50#include <sys/stat.h>
51#include <sys/sysctl.h>
52#include <sys/linker.h>
53#include <sys/pcpu.h>
54
55#include <net/vnet.h>
56
57#include <vm/vm.h>
58#include <vm/vm_param.h>
59
60#include <machine/vmparam.h>
61
62#include <ctype.h>
63#include <fcntl.h>
64#include <kvm.h>
65#include <limits.h>
66#include <nlist.h>
67#include <paths.h>
68#include <stdio.h>
69#include <stdlib.h>
70#include <string.h>
71#include <strings.h>
72#include <unistd.h>
73
74#include "kvm_private.h"
75
76/* from src/lib/libc/gen/nlist.c */
77int __fdnlist(int, struct nlist *);
78
79char *
80kvm_geterr(kd)
81	kvm_t *kd;
82{
83	return (kd->errbuf);
84}
85
86#include <stdarg.h>
87
88/*
89 * Report an error using printf style arguments.  "program" is kd->program
90 * on hard errors, and 0 on soft errors, so that under sun error emulation,
91 * only hard errors are printed out (otherwise, programs like gdb will
92 * generate tons of error messages when trying to access bogus pointers).
93 */
94void
95_kvm_err(kvm_t *kd, const char *program, const char *fmt, ...)
96{
97	va_list ap;
98
99	va_start(ap, fmt);
100	if (program != NULL) {
101		(void)fprintf(stderr, "%s: ", program);
102		(void)vfprintf(stderr, fmt, ap);
103		(void)fputc('\n', stderr);
104	} else
105		(void)vsnprintf(kd->errbuf,
106		    sizeof(kd->errbuf), (char *)fmt, ap);
107
108	va_end(ap);
109}
110
111void
112_kvm_syserr(kvm_t *kd, const char *program, const char *fmt, ...)
113{
114	va_list ap;
115	int n;
116
117	va_start(ap, fmt);
118	if (program != NULL) {
119		(void)fprintf(stderr, "%s: ", program);
120		(void)vfprintf(stderr, fmt, ap);
121		(void)fprintf(stderr, ": %s\n", strerror(errno));
122	} else {
123		char *cp = kd->errbuf;
124
125		(void)vsnprintf(cp, sizeof(kd->errbuf), (char *)fmt, ap);
126		n = strlen(cp);
127		(void)snprintf(&cp[n], sizeof(kd->errbuf) - n, ": %s",
128		    strerror(errno));
129	}
130	va_end(ap);
131}
132
133void *
134_kvm_malloc(kd, n)
135	kvm_t *kd;
136	size_t n;
137{
138	void *p;
139
140	if ((p = calloc(n, sizeof(char))) == NULL)
141		_kvm_err(kd, kd->program, "can't allocate %u bytes: %s",
142			 n, strerror(errno));
143	return (p);
144}
145
146static kvm_t *
147_kvm_open(kd, uf, mf, flag, errout)
148	kvm_t *kd;
149	const char *uf;
150	const char *mf;
151	int flag;
152	char *errout;
153{
154	struct stat st;
155
156	kd->vmfd = -1;
157	kd->pmfd = -1;
158	kd->nlfd = -1;
159	kd->vmst = 0;
160	kd->procbase = 0;
161	kd->argspc = 0;
162	kd->argv = 0;
163
164	if (uf == 0)
165		uf = getbootfile();
166	else if (strlen(uf) >= MAXPATHLEN) {
167		_kvm_err(kd, kd->program, "exec file name too long");
168		goto failed;
169	}
170	if (flag & ~O_RDWR) {
171		_kvm_err(kd, kd->program, "bad flags arg");
172		goto failed;
173	}
174	if (mf == 0)
175		mf = _PATH_MEM;
176
177	if ((kd->pmfd = open(mf, flag, 0)) < 0) {
178		_kvm_syserr(kd, kd->program, "%s", mf);
179		goto failed;
180	}
181	if (fstat(kd->pmfd, &st) < 0) {
182		_kvm_syserr(kd, kd->program, "%s", mf);
183		goto failed;
184	}
185	if (S_ISREG(st.st_mode) && st.st_size <= 0) {
186		errno = EINVAL;
187		_kvm_syserr(kd, kd->program, "empty file");
188		goto failed;
189	}
190	if (fcntl(kd->pmfd, F_SETFD, FD_CLOEXEC) < 0) {
191		_kvm_syserr(kd, kd->program, "%s", mf);
192		goto failed;
193	}
194	if (S_ISCHR(st.st_mode)) {
195		/*
196		 * If this is a character special device, then check that
197		 * it's /dev/mem.  If so, open kmem too.  (Maybe we should
198		 * make it work for either /dev/mem or /dev/kmem -- in either
199		 * case you're working with a live kernel.)
200		 */
201		if (strcmp(mf, _PATH_DEVNULL) == 0) {
202			kd->vmfd = open(_PATH_DEVNULL, O_RDONLY);
203			return (kd);
204		} else if (strcmp(mf, _PATH_MEM) == 0) {
205			if ((kd->vmfd = open(_PATH_KMEM, flag)) < 0) {
206				_kvm_syserr(kd, kd->program, "%s", _PATH_KMEM);
207				goto failed;
208			}
209			if (fcntl(kd->vmfd, F_SETFD, FD_CLOEXEC) < 0) {
210				_kvm_syserr(kd, kd->program, "%s", _PATH_KMEM);
211				goto failed;
212			}
213			return (kd);
214		}
215	}
216	/*
217	 * This is a crash dump.
218	 * Initialize the virtual address translation machinery,
219	 * but first setup the namelist fd.
220	 */
221	if ((kd->nlfd = open(uf, O_RDONLY, 0)) < 0) {
222		_kvm_syserr(kd, kd->program, "%s", uf);
223		goto failed;
224	}
225	if (fcntl(kd->nlfd, F_SETFD, FD_CLOEXEC) < 0) {
226		_kvm_syserr(kd, kd->program, "%s", uf);
227		goto failed;
228	}
229	if (strncmp(mf, _PATH_FWMEM, strlen(_PATH_FWMEM)) == 0)
230		kd->rawdump = 1;
231	if (_kvm_initvtop(kd) < 0)
232		goto failed;
233	return (kd);
234failed:
235	/*
236	 * Copy out the error if doing sane error semantics.
237	 */
238	if (errout != 0)
239		strlcpy(errout, kd->errbuf, _POSIX2_LINE_MAX);
240	(void)kvm_close(kd);
241	return (0);
242}
243
244kvm_t *
245kvm_openfiles(uf, mf, sf, flag, errout)
246	const char *uf;
247	const char *mf;
248	const char *sf __unused;
249	int flag;
250	char *errout;
251{
252	kvm_t *kd;
253
254	if ((kd = calloc(1, sizeof(*kd))) == NULL) {
255		(void)strlcpy(errout, strerror(errno), _POSIX2_LINE_MAX);
256		return (0);
257	}
258	kd->program = 0;
259	return (_kvm_open(kd, uf, mf, flag, errout));
260}
261
262kvm_t *
263kvm_open(uf, mf, sf, flag, errstr)
264	const char *uf;
265	const char *mf;
266	const char *sf __unused;
267	int flag;
268	const char *errstr;
269{
270	kvm_t *kd;
271
272	if ((kd = calloc(1, sizeof(*kd))) == NULL) {
273		if (errstr != NULL)
274			(void)fprintf(stderr, "%s: %s\n",
275				      errstr, strerror(errno));
276		return (0);
277	}
278	kd->program = errstr;
279	return (_kvm_open(kd, uf, mf, flag, NULL));
280}
281
282int
283kvm_close(kd)
284	kvm_t *kd;
285{
286	int error = 0;
287
288	if (kd->pmfd >= 0)
289		error |= close(kd->pmfd);
290	if (kd->vmfd >= 0)
291		error |= close(kd->vmfd);
292	if (kd->nlfd >= 0)
293		error |= close(kd->nlfd);
294	if (kd->vmst)
295		_kvm_freevtop(kd);
296	if (kd->procbase != 0)
297		free((void *)kd->procbase);
298	if (kd->argbuf != 0)
299		free((void *) kd->argbuf);
300	if (kd->argspc != 0)
301		free((void *) kd->argspc);
302	if (kd->argv != 0)
303		free((void *)kd->argv);
304	free((void *)kd);
305
306	return (0);
307}
308
309/*
310 * Walk the list of unresolved symbols, generate a new list and prefix the
311 * symbol names, try again, and merge back what we could resolve.
312 */
313static int
314kvm_fdnlist_prefix(kvm_t *kd, struct nlist *nl, int missing, const char *prefix,
315    uintptr_t (*validate_fn)(kvm_t *, uintptr_t))
316{
317	struct nlist *n, *np, *p;
318	char *cp, *ce;
319	size_t len;
320	int unresolved;
321
322	/*
323	 * Calculate the space we need to malloc for nlist and names.
324	 * We are going to store the name twice for later lookups: once
325	 * with the prefix and once the unmodified name delmited by \0.
326	 */
327	len = 0;
328	unresolved = 0;
329	for (p = nl; p->n_name && p->n_name[0]; ++p) {
330		if (p->n_type != N_UNDF)
331			continue;
332		len += sizeof(struct nlist) + strlen(prefix) +
333		    2 * (strlen(p->n_name) + 1);
334		unresolved++;
335	}
336	if (unresolved == 0)
337		return (unresolved);
338	/* Add space for the terminating nlist entry. */
339	len += sizeof(struct nlist);
340	unresolved++;
341
342	/* Alloc one chunk for (nlist, [names]) and setup pointers. */
343	n = np = malloc(len);
344	bzero(n, len);
345	if (n == NULL)
346		return (missing);
347	cp = ce = (char *)np;
348	cp += unresolved * sizeof(struct nlist);
349	ce += len;
350
351	/* Generate shortened nlist with special prefix. */
352	unresolved = 0;
353	for (p = nl; p->n_name && p->n_name[0]; ++p) {
354		if (p->n_type != N_UNDF)
355			continue;
356		bcopy(p, np, sizeof(struct nlist));
357		/* Save the new\0orig. name so we can later match it again. */
358		len = snprintf(cp, ce - cp, "%s%s%c%s", prefix,
359		    (prefix[0] != '\0' && p->n_name[0] == '_') ?
360			(p->n_name + 1) : p->n_name, '\0', p->n_name);
361		if (len >= ce - cp)
362			continue;
363		np->n_name = cp;
364		cp += len + 1;
365		np++;
366		unresolved++;
367	}
368
369	/* Do lookup on the reduced list. */
370	np = n;
371	unresolved = __fdnlist(kd->nlfd, np);
372
373	/* Check if we could resolve further symbols and update the list. */
374	if (unresolved >= 0 && unresolved < missing) {
375		/* Find the first freshly resolved entry. */
376		for (; np->n_name && np->n_name[0]; np++)
377			if (np->n_type != N_UNDF)
378				break;
379		/*
380		 * The lists are both in the same order,
381		 * so we can walk them in parallel.
382		 */
383		for (p = nl; np->n_name && np->n_name[0] &&
384		    p->n_name && p->n_name[0]; ++p) {
385			if (p->n_type != N_UNDF)
386				continue;
387			/* Skip expanded name and compare to orig. one. */
388			cp = np->n_name + strlen(np->n_name) + 1;
389			if (strcmp(cp, p->n_name))
390				continue;
391			/* Update nlist with new, translated results. */
392			p->n_type = np->n_type;
393			p->n_other = np->n_other;
394			p->n_desc = np->n_desc;
395			if (validate_fn)
396				p->n_value = (*validate_fn)(kd, np->n_value);
397			else
398				p->n_value = np->n_value;
399			missing--;
400			/* Find next freshly resolved entry. */
401			for (np++; np->n_name && np->n_name[0]; np++)
402				if (np->n_type != N_UNDF)
403					break;
404		}
405	}
406	/* We could assert missing = unresolved here. */
407
408	free(n);
409	return (unresolved);
410}
411
412int
413_kvm_nlist(kvm_t *kd, struct nlist *nl, int initialize)
414{
415	struct nlist *p;
416	int nvalid;
417	struct kld_sym_lookup lookup;
418	int error;
419	char *prefix = "", symname[1024]; /* XXX-BZ symbol name length limit? */
420	int tried_vnet, tried_dpcpu;
421
422	/*
423	 * If we can't use the kld symbol lookup, revert to the
424	 * slow library call.
425	 */
426	if (!ISALIVE(kd)) {
427		error = __fdnlist(kd->nlfd, nl);
428		if (error <= 0)			/* Hard error or success. */
429			return (error);
430
431		if (_kvm_vnet_initialized(kd, initialize))
432			error = kvm_fdnlist_prefix(kd, nl, error,
433			    VNET_SYMPREFIX, _kvm_vnet_validaddr);
434
435		if (error > 0 && _kvm_dpcpu_initialized(kd, initialize))
436			error = kvm_fdnlist_prefix(kd, nl, error,
437			    DPCPU_SYMPREFIX, _kvm_dpcpu_validaddr);
438
439		return (error);
440	}
441
442	/*
443	 * We can use the kld lookup syscall.  Go through each nlist entry
444	 * and look it up with a kldsym(2) syscall.
445	 */
446	nvalid = 0;
447	tried_vnet = 0;
448	tried_dpcpu = 0;
449again:
450	for (p = nl; p->n_name && p->n_name[0]; ++p) {
451		if (p->n_type != N_UNDF)
452			continue;
453
454		lookup.version = sizeof(lookup);
455		lookup.symvalue = 0;
456		lookup.symsize = 0;
457
458		error = snprintf(symname, sizeof(symname), "%s%s", prefix,
459		    (prefix[0] != '\0' && p->n_name[0] == '_') ?
460			(p->n_name + 1) : p->n_name);
461		if (error >= sizeof(symname))
462			continue;
463
464		lookup.symname = symname;
465		if (lookup.symname[0] == '_')
466			lookup.symname++;
467
468		if (kldsym(0, KLDSYM_LOOKUP, &lookup) != -1) {
469			p->n_type = N_TEXT;
470			p->n_other = 0;
471			p->n_desc = 0;
472			if (_kvm_vnet_initialized(kd, initialize) &&
473			    !strcmp(prefix, VNET_SYMPREFIX))
474				p->n_value =
475				    _kvm_vnet_validaddr(kd, lookup.symvalue);
476			else if (_kvm_dpcpu_initialized(kd, initialize) &&
477			    !strcmp(prefix, DPCPU_SYMPREFIX))
478				p->n_value =
479				    _kvm_dpcpu_validaddr(kd, lookup.symvalue);
480			else
481				p->n_value = lookup.symvalue;
482			++nvalid;
483			/* lookup.symsize */
484		}
485	}
486
487	/*
488	 * Check the number of entries that weren't found. If they exist,
489	 * try again with a prefix for virtualized or DPCPU symbol names.
490	 */
491	error = ((p - nl) - nvalid);
492	if (error && _kvm_vnet_initialized(kd, initialize) && !tried_vnet) {
493		tried_vnet = 1;
494		prefix = VNET_SYMPREFIX;
495		goto again;
496	}
497	if (error && _kvm_dpcpu_initialized(kd, initialize) && !tried_dpcpu) {
498		tried_dpcpu = 1;
499		prefix = DPCPU_SYMPREFIX;
500		goto again;
501	}
502
503	/*
504	 * Return the number of entries that weren't found. If they exist,
505	 * also fill internal error buffer.
506	 */
507	error = ((p - nl) - nvalid);
508	if (error)
509		_kvm_syserr(kd, kd->program, "kvm_nlist");
510	return (error);
511}
512
513int
514kvm_nlist(kd, nl)
515	kvm_t *kd;
516	struct nlist *nl;
517{
518
519	/*
520	 * If called via the public interface, permit intialization of
521	 * further virtualized modules on demand.
522	 */
523	return (_kvm_nlist(kd, nl, 1));
524}
525
526ssize_t
527kvm_read(kd, kva, buf, len)
528	kvm_t *kd;
529	u_long kva;
530	void *buf;
531	size_t len;
532{
533	int cc;
534	char *cp;
535
536	if (ISALIVE(kd)) {
537		/*
538		 * We're using /dev/kmem.  Just read straight from the
539		 * device and let the active kernel do the address translation.
540		 */
541		errno = 0;
542		if (lseek(kd->vmfd, (off_t)kva, 0) == -1 && errno != 0) {
543			_kvm_err(kd, 0, "invalid address (%x)", kva);
544			return (-1);
545		}
546		cc = read(kd->vmfd, buf, len);
547		if (cc < 0) {
548			_kvm_syserr(kd, 0, "kvm_read");
549			return (-1);
550		} else if (cc < len)
551			_kvm_err(kd, kd->program, "short read");
552		return (cc);
553	} else {
554		cp = buf;
555		while (len > 0) {
556			off_t pa;
557
558			cc = _kvm_kvatop(kd, kva, &pa);
559			if (cc == 0)
560				return (-1);
561			if (cc > len)
562				cc = len;
563			errno = 0;
564			if (lseek(kd->pmfd, pa, 0) == -1 && errno != 0) {
565				_kvm_syserr(kd, 0, _PATH_MEM);
566				break;
567			}
568			cc = read(kd->pmfd, cp, cc);
569			if (cc < 0) {
570				_kvm_syserr(kd, kd->program, "kvm_read");
571				break;
572			}
573			/*
574			 * If kvm_kvatop returns a bogus value or our core
575			 * file is truncated, we might wind up seeking beyond
576			 * the end of the core file in which case the read will
577			 * return 0 (EOF).
578			 */
579			if (cc == 0)
580				break;
581			cp += cc;
582			kva += cc;
583			len -= cc;
584		}
585		return (cp - (char *)buf);
586	}
587	/* NOTREACHED */
588}
589
590ssize_t
591kvm_write(kd, kva, buf, len)
592	kvm_t *kd;
593	u_long kva;
594	const void *buf;
595	size_t len;
596{
597	int cc;
598
599	if (ISALIVE(kd)) {
600		/*
601		 * Just like kvm_read, only we write.
602		 */
603		errno = 0;
604		if (lseek(kd->vmfd, (off_t)kva, 0) == -1 && errno != 0) {
605			_kvm_err(kd, 0, "invalid address (%x)", kva);
606			return (-1);
607		}
608		cc = write(kd->vmfd, buf, len);
609		if (cc < 0) {
610			_kvm_syserr(kd, 0, "kvm_write");
611			return (-1);
612		} else if (cc < len)
613			_kvm_err(kd, kd->program, "short write");
614		return (cc);
615	} else {
616		_kvm_err(kd, kd->program,
617		    "kvm_write not implemented for dead kernels");
618		return (-1);
619	}
620	/* NOTREACHED */
621}
622