xref: /freebsd/lib/libkvm/kvm.c (revision 0e1497aefd602cea581d2380d22e67dfdcac6b4e)
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 #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 */
77 int __fdnlist(int, struct nlist *);
78 
79 char *
80 kvm_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  */
94 void
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 
111 void
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 
133 void *
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 
146 static 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);
234 failed:
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 
244 kvm_t *
245 kvm_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 
262 kvm_t *
263 kvm_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 
282 int
283 kvm_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  */
313 static int
314 kvm_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 
412 int
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;
449 again:
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 
513 int
514 kvm_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 
526 ssize_t
527 kvm_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 
590 ssize_t
591 kvm_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