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