1 /**	$MirOS: src/lib/libkvm/kvm.c,v 1.4 2006/01/24 21:04:25 tg Exp $ */
2 /*	$OpenBSD: kvm.c,v 1.42 2004/09/15 19:31:31 miod Exp $ */
3 /*	$NetBSD: kvm.c,v 1.43 1996/05/05 04:31:59 gwr Exp $	*/
4 
5 /*-
6  * Copyright (c) 1989, 1992, 1993
7  *	The Regents of the University of California.  All rights reserved.
8  *
9  * This code is derived from software developed by the Computer Systems
10  * Engineering group at Lawrence Berkeley Laboratory under DARPA contract
11  * BG 91-66 and contributed to Berkeley.
12  *
13  * Redistribution and use in source and binary forms, with or without
14  * modification, are permitted provided that the following conditions
15  * are met:
16  * 1. Redistributions of source code must retain the above copyright
17  *    notice, this list of conditions and the following disclaimer.
18  * 2. Redistributions in binary form must reproduce the above copyright
19  *    notice, this list of conditions and the following disclaimer in the
20  *    documentation and/or other materials provided with the distribution.
21  * 3. Neither the name of the University nor the names of its contributors
22  *    may be used to endorse or promote products derived from this software
23  *    without specific prior written permission.
24  *
25  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
26  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
28  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
29  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
30  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
31  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
32  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
33  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
34  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
35  * SUCH DAMAGE.
36  */
37 
38 #include <sys/param.h>
39 #include <sys/user.h>
40 #include <sys/proc.h>
41 #include <sys/ioctl.h>
42 #include <sys/stat.h>
43 #include <sys/sysctl.h>
44 
45 #include <sys/core.h>
46 #include <sys/exec_aout.h>
47 #include <sys/kcore.h>
48 
49 #include <ctype.h>
50 #include <db.h>
51 #include <fcntl.h>
52 #include <libgen.h>
53 #include <limits.h>
54 #include <nlist.h>
55 #include <paths.h>
56 #include <stdio.h>
57 #include <stdlib.h>
58 #include <string.h>
59 #include <unistd.h>
60 #include <kvm.h>
61 #include <stdarg.h>
62 #include <zlib.h>
63 
64 #include "kvm_private.h"
65 
66 __SCCSID("@(#)kvm.c	8.2 (Berkeley) 2/13/94");
67 __RCSID("$MirOS: src/lib/libkvm/kvm.c,v 1.4 2006/01/24 21:04:25 tg Exp $");
68 
69 extern int __fdnlist(int, struct nlist *);
70 extern int __fnlist(FILE *, struct nlist *);
71 
72 static int	kvm_dbopen(kvm_t *, const char *);
73 static int	_kvm_get_header(kvm_t *);
74 static kvm_t	*_kvm_open(kvm_t *, const char *, const char *, const char *,
75 		    int, char *);
76 static int	clear_gap(kvm_t *, FILE *, int);
77 static int	kvm_setfd(kvm_t *);
78 
79 char *
kvm_geterr(kd)80 kvm_geterr(kd)
81 	kvm_t *kd;
82 {
83 	return (kd->errbuf);
84 }
85 
86 /*
87  * Wrapper around pread.
88  */
89 ssize_t
_kvm_pread(kvm_t * kd,int fd,void * buf,size_t nbytes,off_t offset)90 _kvm_pread(kvm_t *kd, int fd, void *buf, size_t nbytes, off_t offset)
91 {
92 	ssize_t rval;
93 
94 	errno = 0;
95 	rval = pread(fd, buf, nbytes, offset);
96 	if (rval == -1 || errno != 0) {
97 		_kvm_syserr(kd, kd->program, "pread");
98 	}
99 	return (rval);
100 }
101 
102 /*
103  * Wrapper around pwrite.
104  */
105 ssize_t
_kvm_pwrite(kvm_t * kd,int fd,void * buf,size_t nbytes,off_t offset)106 _kvm_pwrite(kvm_t *kd, int fd, void *buf, size_t nbytes, off_t offset)
107 {
108 	ssize_t rval;
109 
110 	errno = 0;
111 	rval = pwrite(fd, buf, nbytes, offset);
112 	if (rval == -1 || errno != 0) {
113 		_kvm_syserr(kd, kd->program, "pwrite");
114 	}
115 	return (rval);
116 }
117 
118 /*
119  * Report an error using printf style arguments.  "program" is kd->program
120  * on hard errors, and 0 on soft errors, so that under sun error emulation,
121  * only hard errors are printed out (otherwise, programs like gdb will
122  * generate tons of error messages when trying to access bogus pointers).
123  */
124 void
_kvm_err(kvm_t * kd,const char * program,const char * fmt,...)125 _kvm_err(kvm_t *kd, const char *program, const char *fmt, ...)
126 {
127 	va_list ap;
128 
129 	va_start(ap, fmt);
130 	if (program != NULL) {
131 		(void)fprintf(stderr, "%s: ", program);
132 		(void)vfprintf(stderr, fmt, ap);
133 		(void)fputc('\n', stderr);
134 	} else
135 		(void)vsnprintf(kd->errbuf,
136 		    sizeof(kd->errbuf), (char *)fmt, ap);
137 
138 	va_end(ap);
139 }
140 
141 void
_kvm_syserr(kvm_t * kd,const char * program,const char * fmt,...)142 _kvm_syserr(kvm_t *kd, const char *program, const char *fmt, ...)
143 {
144 	va_list ap;
145 	int n;
146 
147 	va_start(ap, fmt);
148 	if (program != NULL) {
149 		(void)fprintf(stderr, "%s: ", program);
150 		(void)vfprintf(stderr, fmt, ap);
151 		(void)fprintf(stderr, ": %s\n", strerror(errno));
152 	} else {
153 		char *cp = kd->errbuf;
154 
155 		(void)vsnprintf(cp, sizeof(kd->errbuf), (char *)fmt, ap);
156 		n = strlen(cp);
157 		(void)snprintf(&cp[n], sizeof(kd->errbuf) - n, ": %s",
158 		    strerror(errno));
159 	}
160 	va_end(ap);
161 }
162 
163 void *
_kvm_malloc(kvm_t * kd,size_t n)164 _kvm_malloc(kvm_t *kd, size_t n)
165 {
166 	void *p;
167 
168 	if ((p = malloc(n)) == NULL)
169 		_kvm_err(kd, kd->program, "%s", strerror(errno));
170 	return (p);
171 }
172 
173 static kvm_t *
_kvm_open(kvm_t * kd,const char * uf,const char * mf,const char * sf,int flag,char * errout)174 _kvm_open(kvm_t *kd, const char *uf, const char *mf, const char *sf,
175     int flag, char *errout)
176 {
177 	struct stat st;
178 
179 	kd->db = 0;
180 	kd->pmfd = -1;
181 	kd->vmfd = -1;
182 	kd->swfd = -1;
183 	kd->nlfd = -1;
184 	kd->nl_f = NULL;
185 	kd->alive = 0;
186 	kd->procbase = 0;
187 	kd->procbase2 = 0;
188 	kd->nbpg = getpagesize();
189 	kd->swapspc = 0;
190 	kd->argspc = 0;
191 	kd->argbuf = 0;
192 	kd->argv = 0;
193 	kd->vmst = NULL;
194 	kd->vm_page_buckets = 0;
195 	kd->kcore_hdr = 0;
196 	kd->cpu_dsize = 0;
197 	kd->cpu_data = 0;
198 	kd->dump_off = 0;
199 
200 	if (flag & KVM_NO_FILES) {
201 		kd->alive = 1;
202 		return (kd);
203 	}
204 
205 	if (uf && strlen(uf) >= MAXPATHLEN) {
206 		_kvm_err(kd, kd->program, "exec file name too long");
207 		goto failed;
208 	}
209 	if (flag & ~O_ACCMODE) {
210 		_kvm_err(kd, kd->program, "bad flags arg");
211 		goto failed;
212 	}
213 	if (mf == 0)
214 		mf = _PATH_MEM;
215 	if (sf == 0)
216 		sf = _PATH_DRUM;
217 
218 	if ((kd->pmfd = open(mf, flag, 0)) < 0) {
219 		_kvm_syserr(kd, kd->program, "%s", mf);
220 		goto failed;
221 	}
222 	if (fstat(kd->pmfd, &st) < 0) {
223 		_kvm_syserr(kd, kd->program, "%s", mf);
224 		goto failed;
225 	}
226 	if (S_ISCHR(st.st_mode)) {
227 		/*
228 		 * If this is a character special device, then check that
229 		 * it's /dev/mem.  If so, open kmem too.  (Maybe we should
230 		 * make it work for either /dev/mem or /dev/kmem -- in either
231 		 * case you're working with a live kernel.)
232 		 */
233 		if (strcmp(mf, _PATH_MEM) != 0) {	/* XXX */
234 			_kvm_err(kd, kd->program,
235 				 "%s: not physical memory device", mf);
236 			goto failed;
237 		}
238 		if ((kd->vmfd = open(_PATH_KMEM, flag, 0)) < 0) {
239 			_kvm_syserr(kd, kd->program, "%s", _PATH_KMEM);
240 			goto failed;
241 		}
242 		kd->alive = 1;
243 		if ((kd->swfd = open(sf, flag, 0)) < 0) {
244 			_kvm_syserr(kd, kd->program, "%s", sf);
245 			goto failed;
246 		}
247 		/*
248 		 * Open kvm nlist database.  We only try to use
249 		 * the pre-built database if the namelist file name
250 		 * pointer is NULL.  If the database cannot or should
251 		 * not be opened, open the namelist argument so we
252 		 * revert to slow nlist() calls.
253 		 * If no file is specified, try opening _PATH_KSYMS and
254 		 * fall back to _PATH_UNIX.
255 		 */
256 		if (kvm_dbopen(kd, uf ? uf : _PATH_UNIX) == -1 &&
257 		    ((uf && (kd->nlfd = open(uf, O_RDONLY, 0)) == -1) || (!uf &&
258 		    (kd->nlfd = open((uf = _PATH_KSYMS), O_RDONLY, 0)) == -1 &&
259 		    (kd->nlfd = open((uf = _PATH_UNIX), O_RDONLY, 0)) == -1))) {
260 			_kvm_syserr(kd, kd->program, "%s", uf);
261 			goto failed;
262 		}
263 	} else {
264 		/*
265 		 * This is a crash dump.
266 		 * Initialize the virtual address translation machinery,
267 		 * but first setup the namelist fd.
268 		 * If no file is specified, try opening _PATH_KSYMS and
269 		 * fall back to _PATH_UNIX.
270 		 */
271 		if ((uf && (kd->nlfd = open(uf, O_RDONLY, 0)) == -1) || (!uf &&
272 		    (kd->nlfd = open((uf = _PATH_KSYMS), O_RDONLY, 0)) == -1 &&
273 		    (kd->nlfd = open((uf = _PATH_UNIX), O_RDONLY, 0)) == -1)) {
274 			_kvm_syserr(kd, kd->program, "%s", uf);
275 			goto failed;
276 		}
277 
278 		/*
279 		 * If there is no valid core header, fail silently here.
280 		 * The address translations however will fail without
281 		 * header. Things can be made to run by calling
282 		 * kvm_dump_mkheader() before doing any translation.
283 		 */
284 		if (_kvm_get_header(kd) == 0) {
285 			if (_kvm_initvtop(kd) < 0)
286 				goto failed;
287 		}
288 	}
289 
290 	/* check for gzip'd kernel */
291 	if (kd->nlfd >= 0) {
292 		unsigned char magic[2];
293 		pread(kd->nlfd, magic, 2, lseek(kd->nlfd, 0, SEEK_CUR));
294 		if (magic[0] == 0x1f && magic[1] == 0x8b)
295 			kd->nl_f = gzfdopen(kd->nlfd, "r");
296 	}
297 
298 	if (kvm_setfd(kd) == 0)
299 		return (kd);
300 	else
301 		_kvm_syserr(kd, kd->program, "can't set close on exec flag");
302 failed:
303 	/*
304 	 * Copy out the error if doing sane error semantics.
305 	 */
306 	if (errout != 0)
307 		(void)strlcpy(errout, kd->errbuf, _POSIX2_LINE_MAX);
308 	(void)kvm_close(kd);
309 	return (0);
310 }
311 
312 /*
313  * The kernel dump file (from savecore) contains:
314  *    kcore_hdr_t kcore_hdr;
315  *    kcore_seg_t cpu_hdr;
316  *    (opaque)    cpu_data; (size is cpu_hdr.c_size)
317  *    kcore_seg_t mem_hdr;
318  *    (memory)    mem_data; (size is mem_hdr.c_size)
319  *
320  * Note: khdr is padded to khdr.c_hdrsize;
321  * cpu_hdr and mem_hdr are padded to khdr.c_seghdrsize
322  */
323 static int
_kvm_get_header(kvm_t * kd)324 _kvm_get_header(kvm_t *kd)
325 {
326 	kcore_hdr_t	kcore_hdr;
327 	kcore_seg_t	cpu_hdr;
328 	kcore_seg_t	mem_hdr;
329 	size_t		offset;
330 	ssize_t		sz;
331 
332 	/*
333 	 * Read the kcore_hdr_t
334 	 */
335 	sz = _kvm_pread(kd, kd->pmfd, &kcore_hdr, sizeof(kcore_hdr), (off_t)0);
336 	if (sz != sizeof(kcore_hdr)) {
337 		return (-1);
338 	}
339 
340 	/*
341 	 * Currently, we only support dump-files made by the current
342 	 * architecture...
343 	 */
344 	if ((CORE_GETMAGIC(kcore_hdr) != KCORE_MAGIC) ||
345 	    (CORE_GETMID(kcore_hdr) != MID_MACHINE))
346 		return (-1);
347 
348 	/*
349 	 * Currently, we only support exactly 2 segments: cpu-segment
350 	 * and data-segment in exactly that order.
351 	 */
352 	if (kcore_hdr.c_nseg != 2)
353 		return (-1);
354 
355 	/*
356 	 * Save away the kcore_hdr.  All errors after this
357 	 * should do a to "goto fail" to deallocate things.
358 	 */
359 	kd->kcore_hdr = _kvm_malloc(kd, sizeof(kcore_hdr));
360 	if (kd->kcore_hdr == NULL)
361 		goto fail;
362 	memcpy(kd->kcore_hdr, &kcore_hdr, sizeof(kcore_hdr));
363 	offset = kcore_hdr.c_hdrsize;
364 
365 	/*
366 	 * Read the CPU segment header
367 	 */
368 	sz = _kvm_pread(kd, kd->pmfd, &cpu_hdr, sizeof(cpu_hdr), (off_t)offset);
369 	if (sz != sizeof(cpu_hdr)) {
370 		goto fail;
371 	}
372 
373 	if ((CORE_GETMAGIC(cpu_hdr) != KCORESEG_MAGIC) ||
374 	    (CORE_GETFLAG(cpu_hdr) != CORE_CPU))
375 		goto fail;
376 	offset += kcore_hdr.c_seghdrsize;
377 
378 	/*
379 	 * Read the CPU segment DATA.
380 	 */
381 	kd->cpu_dsize = cpu_hdr.c_size;
382 	kd->cpu_data = _kvm_malloc(kd, cpu_hdr.c_size);
383 	if (kd->cpu_data == NULL)
384 		goto fail;
385 
386 	sz = _kvm_pread(kd, kd->pmfd, kd->cpu_data, cpu_hdr.c_size, (off_t)offset);
387 	if (sz != cpu_hdr.c_size) {
388 		goto fail;
389 	}
390 
391 	offset += cpu_hdr.c_size;
392 
393 	/*
394 	 * Read the next segment header: data segment
395 	 */
396 	sz = _kvm_pread(kd, kd->pmfd, &mem_hdr, sizeof(mem_hdr), (off_t)offset);
397 	if (sz != sizeof(mem_hdr)) {
398 		goto fail;
399 	}
400 
401 	offset += kcore_hdr.c_seghdrsize;
402 
403 	if ((CORE_GETMAGIC(mem_hdr) != KCORESEG_MAGIC) ||
404 	    (CORE_GETFLAG(mem_hdr) != CORE_DATA))
405 		goto fail;
406 
407 	kd->dump_off = offset;
408 	return (0);
409 
410 fail:
411 	if (kd->kcore_hdr != NULL) {
412 		free(kd->kcore_hdr);
413 		kd->kcore_hdr = NULL;
414 	}
415 	if (kd->cpu_data != NULL) {
416 		free(kd->cpu_data);
417 		kd->cpu_data = NULL;
418 		kd->cpu_dsize = 0;
419 	}
420 
421 	return (-1);
422 }
423 
424 /*
425  * The format while on the dump device is: (new format)
426  *    kcore_seg_t cpu_hdr;
427  *    (opaque)    cpu_data; (size is cpu_hdr.c_size)
428  *    kcore_seg_t mem_hdr;
429  *    (memory)    mem_data; (size is mem_hdr.c_size)
430  */
431 int
kvm_dump_mkheader(kvm_t * kd,off_t dump_off)432 kvm_dump_mkheader(kvm_t *kd, off_t dump_off)
433 {
434 	kcore_seg_t	cpu_hdr;
435 	int	hdr_size, sz;
436 
437 	if (kd->kcore_hdr != NULL) {
438 	    _kvm_err(kd, kd->program, "already has a dump header");
439 	    return (-1);
440 	}
441 	if (ISALIVE(kd)) {
442 		_kvm_err(kd, kd->program, "don't use on live kernel");
443 		return (-1);
444 	}
445 
446 	/*
447 	 * Validate new format crash dump
448 	 */
449 	sz = _kvm_pread(kd, kd->pmfd, &cpu_hdr, sizeof(cpu_hdr), (off_t)dump_off);
450 	if (sz != sizeof(cpu_hdr)) {
451 		return (-1);
452 	}
453 	if ((CORE_GETMAGIC(cpu_hdr) != KCORE_MAGIC)
454 		|| (CORE_GETMID(cpu_hdr) != MID_MACHINE)) {
455 		_kvm_err(kd, 0, "invalid magic in cpu_hdr");
456 		return (-1);
457 	}
458 	hdr_size = ALIGN(sizeof(cpu_hdr));
459 
460 	/*
461 	 * Read the CPU segment.
462 	 */
463 	kd->cpu_dsize = cpu_hdr.c_size;
464 	kd->cpu_data = _kvm_malloc(kd, kd->cpu_dsize);
465 	if (kd->cpu_data == NULL)
466 		goto fail;
467 
468 	sz = _kvm_pread(kd, kd->pmfd, kd->cpu_data, cpu_hdr.c_size,
469 	    (off_t)dump_off+hdr_size);
470 	if (sz != cpu_hdr.c_size) {
471 		_kvm_err(kd, 0, "invalid size in cpu_hdr");
472 		goto fail;
473 	}
474 	hdr_size += kd->cpu_dsize;
475 
476 	/*
477 	 * Leave phys mem pointer at beginning of memory data
478 	 */
479 	kd->dump_off = dump_off + hdr_size;
480 	errno = 0;
481 	if (lseek(kd->pmfd, kd->dump_off, SEEK_SET) != kd->dump_off && errno != 0) {
482 		_kvm_err(kd, 0, "invalid dump offset - lseek");
483 		goto fail;
484 	}
485 
486 	/*
487 	 * Create a kcore_hdr.
488 	 */
489 	kd->kcore_hdr = _kvm_malloc(kd, sizeof(kcore_hdr_t));
490 	if (kd->kcore_hdr == NULL)
491 		goto fail;
492 
493 	kd->kcore_hdr->c_hdrsize    = ALIGN(sizeof(kcore_hdr_t));
494 	kd->kcore_hdr->c_seghdrsize = ALIGN(sizeof(kcore_seg_t));
495 	kd->kcore_hdr->c_nseg       = 2;
496 	CORE_SETMAGIC(*(kd->kcore_hdr), KCORE_MAGIC, MID_MACHINE,0);
497 
498 	/*
499 	 * Now that we have a valid header, enable translations.
500 	 */
501 	if (_kvm_initvtop(kd) == 0)
502 		/* Success */
503 		return (hdr_size);
504 
505 fail:
506 	if (kd->kcore_hdr != NULL) {
507 		free(kd->kcore_hdr);
508 		kd->kcore_hdr = NULL;
509 	}
510 	if (kd->cpu_data != NULL) {
511 		free(kd->cpu_data);
512 		kd->cpu_data = NULL;
513 		kd->cpu_dsize = 0;
514 	}
515 	return (-1);
516 }
517 
518 static int
clear_gap(kvm_t * kd,FILE * fp,int size)519 clear_gap(kvm_t *kd, FILE *fp, int size)
520 {
521 	if (size <= 0) /* XXX - < 0 should never happen */
522 		return (0);
523 	while (size-- > 0) {
524 		if (fputc(0, fp) == EOF) {
525 			_kvm_syserr(kd, kd->program, "clear_gap");
526 			return (-1);
527 		}
528 	}
529 	return (0);
530 }
531 
532 /*
533  * Write the dump header info to 'fp'. Note that we can't use fseek(3) here
534  * because 'fp' might be a file pointer obtained by zopen().
535  */
536 int
kvm_dump_wrtheader(kvm_t * kd,FILE * fp,int dumpsize)537 kvm_dump_wrtheader(kvm_t *kd, FILE *fp, int dumpsize)
538 {
539 	kcore_seg_t	seghdr;
540 	long		offset;
541 	int		gap;
542 
543 	if (kd->kcore_hdr == NULL || kd->cpu_data == NULL) {
544 		_kvm_err(kd, kd->program, "no valid dump header(s)");
545 		return (-1);
546 	}
547 
548 	/*
549 	 * Write the generic header
550 	 */
551 	offset = 0;
552 	if (fwrite((void*)kd->kcore_hdr, sizeof(kcore_hdr_t), 1, fp) <= 0) {
553 		_kvm_syserr(kd, kd->program, "kvm_dump_wrtheader");
554 		return (-1);
555 	}
556 	offset += kd->kcore_hdr->c_hdrsize;
557 	gap     = kd->kcore_hdr->c_hdrsize - sizeof(kcore_hdr_t);
558 	if (clear_gap(kd, fp, gap) == -1)
559 		return (-1);
560 
561 	/*
562 	 * Write the cpu header
563 	 */
564 	CORE_SETMAGIC(seghdr, KCORESEG_MAGIC, 0, CORE_CPU);
565 	seghdr.c_size = ALIGN(kd->cpu_dsize);
566 	if (fwrite((void*)&seghdr, sizeof(seghdr), 1, fp) <= 0) {
567 		_kvm_syserr(kd, kd->program, "kvm_dump_wrtheader");
568 		return (-1);
569 	}
570 	offset += kd->kcore_hdr->c_seghdrsize;
571 	gap     = kd->kcore_hdr->c_seghdrsize - sizeof(seghdr);
572 	if (clear_gap(kd, fp, gap) == -1)
573 		return (-1);
574 
575 	if (fwrite((void*)kd->cpu_data, kd->cpu_dsize, 1, fp) <= 0) {
576 		_kvm_syserr(kd, kd->program, "kvm_dump_wrtheader");
577 		return (-1);
578 	}
579 	offset += seghdr.c_size;
580 	gap     = seghdr.c_size - kd->cpu_dsize;
581 	if (clear_gap(kd, fp, gap) == -1)
582 		return (-1);
583 
584 	/*
585 	 * Write the actual dump data segment header
586 	 */
587 	CORE_SETMAGIC(seghdr, KCORESEG_MAGIC, 0, CORE_DATA);
588 	seghdr.c_size = dumpsize;
589 	if (fwrite((void*)&seghdr, sizeof(seghdr), 1, fp) <= 0) {
590 		_kvm_syserr(kd, kd->program, "kvm_dump_wrtheader");
591 		return (-1);
592 	}
593 	offset += kd->kcore_hdr->c_seghdrsize;
594 	gap     = kd->kcore_hdr->c_seghdrsize - sizeof(seghdr);
595 	if (clear_gap(kd, fp, gap) == -1)
596 		return (-1);
597 
598 	return (offset);
599 }
600 
601 kvm_t *
kvm_openfiles(const char * uf,const char * mf,const char * sf,unsigned int flag,char * errout)602 kvm_openfiles(const char *uf, const char *mf, const char *sf,
603     unsigned int flag, char *errout)
604 {
605 	kvm_t *kd;
606 
607 	if ((kd = malloc(sizeof(*kd))) == NULL) {
608 		(void)strlcpy(errout, strerror(errno), _POSIX2_LINE_MAX);
609 		return (0);
610 	}
611 	kd->program = 0;
612 	return (_kvm_open(kd, uf, mf, sf, flag, errout));
613 }
614 
615 kvm_t *
kvm_open(const char * uf,const char * mf,const char * sf,int flag,const char * program)616 kvm_open(const char *uf, const char *mf, const char *sf, int flag,
617     const char *program)
618 {
619 	kvm_t *kd;
620 
621 	if ((kd = malloc(sizeof(*kd))) == NULL && program != NULL) {
622 		(void)fprintf(stderr, "%s: %s\n", program, strerror(errno));
623 		return (0);
624 	}
625 	kd->program = program;
626 	return (_kvm_open(kd, uf, mf, sf, flag, NULL));
627 }
628 
629 int
kvm_close(kvm_t * kd)630 kvm_close(kvm_t *kd)
631 {
632 	int error = 0;
633 
634 	if (kd->pmfd >= 0)
635 		error |= close(kd->pmfd);
636 	if (kd->vmfd >= 0)
637 		error |= close(kd->vmfd);
638 	kd->alive = 0;
639 	if (kd->nlfd >= 0) {
640 		if (kd->nl_f == NULL)
641 			error |= close(kd->nlfd);
642 		else
643 			error |= fclose(kd->nl_f);
644 	}
645 	if (kd->swfd >= 0)
646 		error |= close(kd->swfd);
647 	if (kd->db != 0)
648 		error |= (kd->db->close)(kd->db);
649 	if (kd->vmst)
650 		_kvm_freevtop(kd);
651 	kd->cpu_dsize = 0;
652 	if (kd->cpu_data != NULL)
653 		free((void *)kd->cpu_data);
654 	if (kd->kcore_hdr != NULL)
655 		free((void *)kd->kcore_hdr);
656 	if (kd->procbase != 0)
657 		free((void *)kd->procbase);
658 	if (kd->procbase2 != 0)
659 		free(kd->procbase2);
660 	if (kd->swapspc != 0)
661 		free((void *)kd->swapspc);
662 	if (kd->argspc != 0)
663 		free((void *)kd->argspc);
664 	if (kd->argbuf != 0)
665 		free((void *)kd->argbuf);
666 	if (kd->argv != 0)
667 		free((void *)kd->argv);
668 	free((void *)kd);
669 
670 	return (error);
671 }
672 
673 /*
674  * Set up state necessary to do queries on the kernel namelist
675  * data base.  If the data base is out-of-data/incompatible with
676  * given executable, set up things so we revert to standard nlist call.
677  * Only called for live kernels.  Return 0 on success, -1 on failure.
678  */
679 static int
kvm_dbopen(kvm_t * kd,const char * uf)680 kvm_dbopen(kvm_t *kd, const char *uf)
681 {
682 	char dbversion[_POSIX2_LINE_MAX], kversion[_POSIX2_LINE_MAX];
683 	char dbname[MAXPATHLEN];
684 	struct nlist nitem;
685 	int dbversionlen;
686 	DBT rec;
687 
688 	uf = basename((char *)uf);
689 
690 	(void)snprintf(dbname, sizeof(dbname), "%skvm_%s.db", _PATH_VARDB, uf);
691 	kd->db = dbopen(dbname, O_RDONLY, 0, DB_HASH, NULL);
692 	if (kd->db == NULL) {
693 		switch (errno) {
694 		case ENOENT:
695 			/* No kvm_bsd.db, fall back to /bsd silently */
696 			break;
697 		case EFTYPE:
698 			_kvm_err(kd, kd->program,
699 			    "file %s is incorrectly formatted", dbname);
700 			break;
701 		case EINVAL:
702 			_kvm_err(kd, kd->program,
703 			    "invalid argument to dbopen()");
704 			break;
705 		default:
706 			_kvm_err(kd, kd->program, "unknown dbopen() error");
707 			break;
708 		}
709 		return (-1);
710 	}
711 
712 	/*
713 	 * read version out of database
714 	 */
715 	rec.data = VRS_KEY;
716 	rec.size = sizeof(VRS_KEY) - 1;
717 	if ((kd->db->get)(kd->db, (DBT *)&rec, (DBT *)&rec, 0))
718 		goto close;
719 	if (rec.data == 0 || rec.size > sizeof(dbversion))
720 		goto close;
721 
722 	memmove(dbversion, rec.data, rec.size);
723 	dbversionlen = rec.size;
724 	/*
725 	 * Read version string from kernel memory.
726 	 * Since we are dealing with a live kernel, we can call kvm_read()
727 	 * at this point.
728 	 */
729 	rec.data = VRS_SYM;
730 	rec.size = sizeof(VRS_SYM) - 1;
731 	if ((kd->db->get)(kd->db, (DBT *)&rec, (DBT *)&rec, 0))
732 		goto close;
733 	if (rec.data == 0 || rec.size != sizeof(struct nlist))
734 		goto close;
735 	memmove((char *)&nitem, (char *)rec.data, sizeof(nitem));
736 	if (kvm_read(kd, (u_long)nitem.n_value, kversion, dbversionlen) !=
737 	    dbversionlen)
738 		goto close;
739 	/*
740 	 * If they match, we win - otherwise clear out kd->db so
741 	 * we revert to slow nlist().
742 	 */
743 	if (memcmp(dbversion, kversion, dbversionlen) == 0)
744 		return (0);
745 close:
746 	(void)(kd->db->close)(kd->db);
747 	kd->db = 0;
748 
749 	return (-1);
750 }
751 
752 int
kvm_nlist(kvm_t * kd,struct nlist * nl)753 kvm_nlist(kvm_t *kd, struct nlist *nl)
754 {
755 	struct nlist *p;
756 	int nvalid, rv;
757 
758 	/*
759 	 * If we can't use the data base, revert to the
760 	 * slow library call.
761 	 */
762 	if (kd->db == 0) {
763 		if (kd->nl_f == NULL)
764 			rv = __fdnlist(kd->nlfd, nl);
765 		else
766 			rv = __fnlist(kd->nl_f, nl);
767 		if (rv == -1)
768 			_kvm_err(kd, 0, "bad namelist");
769 		return (rv);
770 	}
771 
772 	/*
773 	 * We can use the kvm data base.  Go through each nlist entry
774 	 * and look it up with a db query.
775 	 */
776 	nvalid = 0;
777 	for (p = nl; p->n_name && p->n_name[0]; ++p) {
778 		int len;
779 		DBT rec;
780 
781 		if ((len = strlen(p->n_name)) > 4096) {
782 			/* sanity */
783 			_kvm_err(kd, kd->program, "symbol too large");
784 			return (-1);
785 		}
786 		rec.data = p->n_name;
787 		rec.size = len;
788 
789 		/*
790 		 * Make sure that n_value = 0 when the symbol isn't found
791 		 */
792 		p->n_value = 0;
793 
794 		if ((kd->db->get)(kd->db, (DBT *)&rec, (DBT *)&rec, 0))
795 			continue;
796 		if (rec.data == 0 || rec.size != sizeof(struct nlist))
797 			continue;
798 		++nvalid;
799 		/*
800 		 * Avoid alignment issues.
801 		 */
802 		memmove((char *)&p->n_type,
803 		    (char *)&((struct nlist *)rec.data)->n_type,
804 		    sizeof(p->n_type));
805 		memmove((char *)&p->n_value,
806 		    (char *)&((struct nlist *)rec.data)->n_value,
807 		    sizeof(p->n_value));
808 	}
809 	/*
810 	 * Return the number of entries that weren't found.
811 	 */
812 	return ((p - nl) - nvalid);
813 }
814 
815 int
kvm_dump_inval(kvm_t * kd)816 kvm_dump_inval(kvm_t *kd)
817 {
818 	struct nlist	nlist[2];
819 	u_long		pa, x;
820 
821 	if (ISALIVE(kd)) {
822 		_kvm_err(kd, kd->program, "clearing dump on live kernel");
823 		return (-1);
824 	}
825 	nlist[0].n_name = "_dumpmag";
826 	nlist[1].n_name = NULL;
827 
828 	if (kvm_nlist(kd, nlist) == -1) {
829 		_kvm_err(kd, 0, "bad namelist");
830 		return (-1);
831 	}
832 
833 	if (nlist[0].n_value == 0) {
834 		_kvm_err(kd, nlist[0].n_name, "not in name list");
835 		return (-1);
836 	}
837 
838 	if (_kvm_kvatop(kd, (u_long)nlist[0].n_value, &pa) == 0)
839 		return (-1);
840 
841 	x = 0;
842 	if (_kvm_pwrite(kd, kd->pmfd, &x, sizeof(x),
843 	    (off_t)_kvm_pa2off(kd, pa)) != sizeof(x)) {
844 		_kvm_err(kd, 0, "cannot invalidate dump");
845 		return (-1);
846 	}
847 	return (0);
848 }
849 
850 ssize_t
kvm_read(kvm_t * kd,u_long kva,void * buf,size_t len)851 kvm_read(kvm_t *kd, u_long kva, void *buf, size_t len)
852 {
853 	int cc;
854 	void *cp;
855 
856 	if (ISALIVE(kd)) {
857 		/*
858 		 * We're using /dev/kmem.  Just read straight from the
859 		 * device and let the active kernel do the address translation.
860 		 */
861 		cc = _kvm_pread(kd, kd->vmfd, buf, len, (off_t)kva);
862 		if (cc == -1) {
863 			_kvm_err(kd, 0, "invalid address (%lx)", kva);
864 			return (-1);
865 		} else if (cc < len)
866 			_kvm_err(kd, kd->program, "short read");
867 		return (cc);
868 	} else {
869 		if ((kd->kcore_hdr == NULL) || (kd->cpu_data == NULL)) {
870 			_kvm_err(kd, kd->program, "no valid dump header");
871 			return (-1);
872 		}
873 		cp = buf;
874 		while (len > 0) {
875 			u_long	pa;
876 
877 			/* In case of error, _kvm_kvatop sets the err string */
878 			cc = _kvm_kvatop(kd, kva, &pa);
879 			if (cc == 0)
880 				return (-1);
881 			if (cc > len)
882 				cc = len;
883 			cc = _kvm_pread(kd, kd->pmfd, cp, cc,
884 			    (off_t)_kvm_pa2off(kd, pa));
885 			if (cc == -1) {
886 				_kvm_syserr(kd, 0, _PATH_MEM);
887 				break;
888 			}
889 			/*
890 			 * If kvm_kvatop returns a bogus value or our core
891 			 * file is truncated, we might wind up seeking beyond
892 			 * the end of the core file in which case the read will
893 			 * return 0 (EOF).
894 			 */
895 			if (cc == 0)
896 				break;
897 			cp = (char *)cp + cc;
898 			kva += cc;
899 			len -= cc;
900 		}
901 		return ((char *)cp - (char *)buf);
902 	}
903 	/* NOTREACHED */
904 }
905 
906 ssize_t
kvm_write(kvm_t * kd,u_long kva,const void * buf,size_t len)907 kvm_write(kvm_t *kd, u_long kva, const void *buf, size_t len)
908 {
909 	int cc;
910 
911 	if (ISALIVE(kd)) {
912 		/*
913 		 * Just like kvm_read, only we write.
914 		 */
915 		cc = _kvm_pwrite(kd, kd->vmfd, (void*)buf, (size_t)len, (off_t)kva);
916 		if (cc == -1) {
917 			_kvm_err(kd, 0, "invalid address (%lx)", kva);
918 			return (-1);
919 		} else if (cc < len)
920 			_kvm_err(kd, kd->program, "short write");
921 		return (cc);
922 	} else {
923 		_kvm_err(kd, kd->program,
924 		    "kvm_write not implemented for dead kernels");
925 		return (-1);
926 	}
927 	/* NOTREACHED */
928 }
929 
930 static int
kvm_setfd(kvm_t * kd)931 kvm_setfd(kvm_t *kd)
932 {
933 	if (kd->pmfd >= 0 && fcntl(kd->pmfd, F_SETFD, FD_CLOEXEC) < 0)
934 		return (-1);
935 	if (kd->vmfd >= 0 && fcntl(kd->vmfd, F_SETFD, FD_CLOEXEC) < 0)
936 		return (-1);
937 	if (kd->nlfd >= 0 && fcntl(kd->nlfd, F_SETFD, FD_CLOEXEC) < 0)
938 		return (-1);
939 	if (kd->swfd >= 0 && fcntl(kd->swfd, F_SETFD, FD_CLOEXEC) < 0)
940 		return (-1);
941 
942 	return (0);
943 }
944