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