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