kvm.c revision 1.48 1 /* $NetBSD: kvm.c,v 1.48 1996/10/12 00:50:11 cgd 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.48 1996/10/12 00:50:11 cgd 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 ufgiven = (uf != NULL);
244 if (!ufgiven)
245 uf = _PATH_UNIX;
246 else if (strlen(uf) >= MAXPATHLEN) {
247 _kvm_err(kd, kd->program, "exec file name too long");
248 goto failed;
249 }
250 if (flag & ~O_RDWR) {
251 _kvm_err(kd, kd->program, "bad flags arg");
252 goto failed;
253 }
254 if (mf == 0)
255 mf = _PATH_MEM;
256 if (sf == 0)
257 sf = _PATH_DRUM;
258
259 if ((kd->pmfd = open(mf, flag, 0)) < 0) {
260 _kvm_syserr(kd, kd->program, "%s", mf);
261 goto failed;
262 }
263 if (fstat(kd->pmfd, &st) < 0) {
264 _kvm_syserr(kd, kd->program, "%s", mf);
265 goto failed;
266 }
267 if (S_ISCHR(st.st_mode)) {
268 /*
269 * If this is a character special device, then check that
270 * it's /dev/mem. If so, open kmem too. (Maybe we should
271 * make it work for either /dev/mem or /dev/kmem -- in either
272 * case you're working with a live kernel.)
273 */
274 if (strcmp(mf, _PATH_MEM) != 0) { /* XXX */
275 _kvm_err(kd, kd->program,
276 "%s: not physical memory device", mf);
277 goto failed;
278 }
279 if ((kd->vmfd = open(_PATH_KMEM, flag)) < 0) {
280 _kvm_syserr(kd, kd->program, "%s", _PATH_KMEM);
281 goto failed;
282 }
283 if ((kd->swfd = open(sf, flag, 0)) < 0) {
284 _kvm_syserr(kd, kd->program, "%s", sf);
285 goto failed;
286 }
287 /*
288 * Open kvm nlist database. We only try to use
289 * the pre-built database if the namelist file name
290 * pointer is NULL. If the database cannot or should
291 * not be opened, open the namelist argument so we
292 * revert to slow nlist() calls.
293 */
294 if ((ufgiven || kvm_dbopen(kd) < 0) &&
295 (kd->nlfd = open(uf, O_RDONLY, 0)) < 0) {
296 _kvm_syserr(kd, kd->program, "%s", uf);
297 goto failed;
298 }
299 } else {
300 /*
301 * This is a crash dump.
302 * Initalize the virtual address translation machinery,
303 * but first setup the namelist fd.
304 */
305 if ((kd->nlfd = open(uf, O_RDONLY, 0)) < 0) {
306 _kvm_syserr(kd, kd->program, "%s", uf);
307 goto failed;
308 }
309
310 /*
311 * If there is no valid core header, fail silently here.
312 * The address translations however will fail without
313 * header. Things can be made to run by calling
314 * kvm_dump_mkheader() before doing any translation.
315 */
316 if (_kvm_get_header(kd) == 0) {
317 if (_kvm_initvtop(kd) < 0)
318 goto failed;
319 }
320 }
321 return (kd);
322 failed:
323 /*
324 * Copy out the error if doing sane error semantics.
325 */
326 if (errout != 0)
327 strcpy(errout, kd->errbuf);
328 (void)kvm_close(kd);
329 return (0);
330 }
331
332 /*
333 * The kernel dump file (from savecore) contains:
334 * kcore_hdr_t kcore_hdr;
335 * kcore_seg_t cpu_hdr;
336 * (opaque) cpu_data; (size is cpu_hdr.c_size)
337 * kcore_seg_t mem_hdr;
338 * (memory) mem_data; (size is mem_hdr.c_size)
339 *
340 * Note: khdr is padded to khdr.c_hdrsize;
341 * cpu_hdr and mem_hdr are padded to khdr.c_seghdrsize
342 */
343 static int
344 _kvm_get_header(kd)
345 kvm_t *kd;
346 {
347 kcore_hdr_t kcore_hdr;
348 kcore_seg_t cpu_hdr;
349 kcore_seg_t mem_hdr;
350 size_t offset;
351 ssize_t sz;
352
353 /*
354 * Read the kcore_hdr_t
355 */
356 if (Lseek(kd, kd->pmfd, (off_t)0, SEEK_SET) == -1)
357 return (-1);
358 sz = Read(kd, kd->pmfd, &kcore_hdr, sizeof(kcore_hdr));
359 if (sz != sizeof(kcore_hdr))
360 return (-1);
361
362 /*
363 * Currently, we only support dump-files made by the current
364 * architecture...
365 */
366 if ((CORE_GETMAGIC(kcore_hdr) != KCORE_MAGIC) ||
367 (CORE_GETMID(kcore_hdr) != MID_MACHINE))
368 return (-1);
369
370 /*
371 * Currently, we only support exactly 2 segments: cpu-segment
372 * and data-segment in exactly that order.
373 */
374 if (kcore_hdr.c_nseg != 2)
375 return (-1);
376
377 /*
378 * Save away the kcore_hdr. All errors after this
379 * should do a to "goto fail" to deallocate things.
380 */
381 kd->kcore_hdr = _kvm_malloc(kd, sizeof(kcore_hdr));
382 memcpy(kd->kcore_hdr, &kcore_hdr, sizeof(kcore_hdr));
383 offset = kcore_hdr.c_hdrsize;
384
385 /*
386 * Read the CPU segment header
387 */
388 if (Lseek(kd, kd->pmfd, (off_t)offset, SEEK_SET) == -1)
389 goto fail;
390 sz = Read(kd, kd->pmfd, &cpu_hdr, sizeof(cpu_hdr));
391 if (sz != sizeof(cpu_hdr))
392 goto fail;
393 if ((CORE_GETMAGIC(cpu_hdr) != KCORESEG_MAGIC) ||
394 (CORE_GETFLAG(cpu_hdr) != CORE_CPU))
395 goto fail;
396 offset += kcore_hdr.c_seghdrsize;
397
398 /*
399 * Read the CPU segment DATA.
400 */
401 kd->cpu_dsize = cpu_hdr.c_size;
402 kd->cpu_data = _kvm_malloc(kd, cpu_hdr.c_size);
403 if (kd->cpu_data == NULL)
404 goto fail;
405 if (Lseek(kd, kd->pmfd, (off_t)offset, SEEK_SET) == -1)
406 goto fail;
407 sz = Read(kd, kd->pmfd, kd->cpu_data, cpu_hdr.c_size);
408 if (sz != cpu_hdr.c_size)
409 goto fail;
410 offset += cpu_hdr.c_size;
411
412 /*
413 * Read the next segment header: data segment
414 */
415 if (Lseek(kd, kd->pmfd, (off_t)offset, SEEK_SET) == -1)
416 goto fail;
417 sz = Read(kd, kd->pmfd, &mem_hdr, sizeof(mem_hdr));
418 if (sz != sizeof(mem_hdr))
419 goto fail;
420 offset += kcore_hdr.c_seghdrsize;
421
422 if ((CORE_GETMAGIC(mem_hdr) != KCORESEG_MAGIC) ||
423 (CORE_GETFLAG(mem_hdr) != CORE_DATA))
424 goto fail;
425
426 kd->dump_off = offset;
427 return (0);
428
429 fail:
430 if (kd->kcore_hdr != NULL) {
431 free(kd->kcore_hdr);
432 kd->kcore_hdr = NULL;
433 }
434 if (kd->cpu_data != NULL) {
435 free(kd->cpu_data);
436 kd->cpu_data = NULL;
437 kd->cpu_dsize = 0;
438 }
439
440 }
441
442 /*
443 * The format while on the dump device is: (new format)
444 * kcore_seg_t cpu_hdr;
445 * (opaque) cpu_data; (size is cpu_hdr.c_size)
446 * kcore_seg_t mem_hdr;
447 * (memory) mem_data; (size is mem_hdr.c_size)
448 */
449 int
450 kvm_dump_mkheader(kd, dump_off)
451 kvm_t *kd;
452 off_t dump_off;
453 {
454 kcore_seg_t cpu_hdr;
455 int hdr_size, sz;
456
457 if (kd->kcore_hdr != NULL) {
458 _kvm_err(kd, kd->program, "already has a dump header");
459 return (-1);
460 }
461 if (ISALIVE(kd)) {
462 _kvm_err(kd, kd->program, "don't use on live kernel");
463 return (-1);
464 }
465
466 /*
467 * Validate new format crash dump
468 */
469 if (Lseek(kd, kd->pmfd, dump_off, SEEK_SET) == -1)
470 return (-1);
471 sz = Read(kd, kd->pmfd, &cpu_hdr, sizeof(cpu_hdr));
472 if (sz != sizeof(cpu_hdr))
473 return (-1);
474 if ((CORE_GETMAGIC(cpu_hdr) != KCORE_MAGIC)
475 || (CORE_GETMID(cpu_hdr) != MID_MACHINE)) {
476 _kvm_err(kd, 0, "invalid magic in cpu_hdr");
477 return (0);
478 }
479 hdr_size = ALIGN(sizeof(cpu_hdr));
480
481 /*
482 * Read the CPU segment.
483 */
484 kd->cpu_dsize = cpu_hdr.c_size;
485 kd->cpu_data = _kvm_malloc(kd, kd->cpu_dsize);
486 if (kd->cpu_data == NULL)
487 goto fail;
488 if (Lseek(kd, kd->pmfd, dump_off+hdr_size, SEEK_SET) == -1)
489 goto fail;
490 sz = Read(kd, kd->pmfd, kd->cpu_data, cpu_hdr.c_size);
491 if (sz != cpu_hdr.c_size)
492 goto fail;
493 hdr_size += kd->cpu_dsize;
494
495 /*
496 * Leave phys mem pointer at beginning of memory data
497 */
498 kd->dump_off = dump_off + hdr_size;
499 if (Lseek(kd, kd->pmfd, kd->dump_off, SEEK_SET) == -1)
500 goto fail;
501
502 /*
503 * Create a kcore_hdr.
504 */
505 kd->kcore_hdr = _kvm_malloc(kd, sizeof(kcore_hdr_t));
506 if (kd->kcore_hdr == NULL)
507 goto fail;
508
509 kd->kcore_hdr->c_hdrsize = ALIGN(sizeof(kcore_hdr_t));
510 kd->kcore_hdr->c_seghdrsize = ALIGN(sizeof(kcore_seg_t));
511 kd->kcore_hdr->c_nseg = 2;
512 CORE_SETMAGIC(*(kd->kcore_hdr), KCORE_MAGIC, MID_MACHINE,0);
513
514 /*
515 * Now that we have a valid header, enable translations.
516 */
517 _kvm_initvtop(kd);
518
519 return(hdr_size);
520
521 fail:
522 if (kd->kcore_hdr != NULL) {
523 free(kd->kcore_hdr);
524 kd->kcore_hdr = NULL;
525 }
526 if (kd->cpu_data != NULL) {
527 free(kd->cpu_data);
528 kd->cpu_data = NULL;
529 kd->cpu_dsize = 0;
530 }
531 return (-1);
532 }
533
534 static int
535 clear_gap(kd, fp, size)
536 kvm_t *kd;
537 FILE *fp;
538 int size;
539 {
540 if (size <= 0) /* XXX - < 0 should never happen */
541 return (0);
542 while (size-- > 0) {
543 if (fputc(0, fp) == EOF) {
544 _kvm_syserr(kd, kd->program, "clear_gap");
545 return (-1);
546 }
547 }
548 return (0);
549 }
550
551 /*
552 * Write the dump header info to 'fp'. Note that we can't use fseek(3) here
553 * because 'fp' might be a file pointer obtained by zopen().
554 */
555 int
556 kvm_dump_wrtheader(kd, fp, dumpsize)
557 kvm_t *kd;
558 FILE *fp;
559 int dumpsize;
560 {
561 kcore_seg_t seghdr;
562 long offset;
563 int gap;
564
565 if (kd->kcore_hdr == NULL || kd->cpu_data == NULL) {
566 _kvm_err(kd, kd->program, "no valid dump header(s)");
567 return (-1);
568 }
569
570 /*
571 * Write the generic header
572 */
573 offset = 0;
574 if (fwrite((void*)kd->kcore_hdr, sizeof(kcore_hdr_t), 1, fp) <= 0) {
575 _kvm_syserr(kd, kd->program, "kvm_dump_wrtheader");
576 return (-1);
577 }
578 offset += kd->kcore_hdr->c_hdrsize;
579 gap = kd->kcore_hdr->c_hdrsize - sizeof(kcore_hdr_t);
580 if (clear_gap(kd, fp, gap) == -1)
581 return (-1);
582
583 /*
584 * Write the cpu header
585 */
586 CORE_SETMAGIC(seghdr, KCORESEG_MAGIC, 0, CORE_CPU);
587 seghdr.c_size = ALIGN(kd->cpu_dsize);
588 if (fwrite((void*)&seghdr, sizeof(seghdr), 1, fp) <= 0) {
589 _kvm_syserr(kd, kd->program, "kvm_dump_wrtheader");
590 return (-1);
591 }
592 offset += kd->kcore_hdr->c_seghdrsize;
593 gap = kd->kcore_hdr->c_seghdrsize - sizeof(seghdr);
594 if (clear_gap(kd, fp, gap) == -1)
595 return (-1);
596
597 if (fwrite((void*)kd->cpu_data, kd->cpu_dsize, 1, fp) <= 0) {
598 _kvm_syserr(kd, kd->program, "kvm_dump_wrtheader");
599 return (-1);
600 }
601 offset += seghdr.c_size;
602 gap = seghdr.c_size - kd->cpu_dsize;
603 if (clear_gap(kd, fp, gap) == -1)
604 return (-1);
605
606 /*
607 * Write the actual dump data segment header
608 */
609 CORE_SETMAGIC(seghdr, KCORESEG_MAGIC, 0, CORE_DATA);
610 seghdr.c_size = dumpsize;
611 if (fwrite((void*)&seghdr, sizeof(seghdr), 1, fp) <= 0) {
612 _kvm_syserr(kd, kd->program, "kvm_dump_wrtheader");
613 return (-1);
614 }
615 offset += kd->kcore_hdr->c_seghdrsize;
616 gap = kd->kcore_hdr->c_seghdrsize - sizeof(seghdr);
617 if (clear_gap(kd, fp, gap) == -1)
618 return (-1);
619
620 return (offset);
621 }
622
623 kvm_t *
624 kvm_openfiles(uf, mf, sf, flag, errout)
625 const char *uf;
626 const char *mf;
627 const char *sf;
628 int flag;
629 char *errout;
630 {
631 register kvm_t *kd;
632
633 if ((kd = malloc(sizeof(*kd))) == NULL) {
634 (void)strcpy(errout, strerror(errno));
635 return (0);
636 }
637 kd->program = 0;
638 return (_kvm_open(kd, uf, mf, sf, flag, errout));
639 }
640
641 kvm_t *
642 kvm_open(uf, mf, sf, flag, program)
643 const char *uf;
644 const char *mf;
645 const char *sf;
646 int flag;
647 const char *program;
648 {
649 register kvm_t *kd;
650
651 if ((kd = malloc(sizeof(*kd))) == NULL && program != NULL) {
652 (void)fprintf(stderr, "%s: %s\n", strerror(errno));
653 return (0);
654 }
655 kd->program = program;
656 return (_kvm_open(kd, uf, mf, sf, flag, NULL));
657 }
658
659 int
660 kvm_close(kd)
661 kvm_t *kd;
662 {
663 register int error = 0;
664
665 if (kd->pmfd >= 0)
666 error |= close(kd->pmfd);
667 if (kd->vmfd >= 0)
668 error |= close(kd->vmfd);
669 if (kd->nlfd >= 0)
670 error |= close(kd->nlfd);
671 if (kd->swfd >= 0)
672 error |= close(kd->swfd);
673 if (kd->db != 0)
674 error |= (kd->db->close)(kd->db);
675 if (kd->vmst)
676 _kvm_freevtop(kd);
677 kd->cpu_dsize = 0;
678 if (kd->cpu_data != NULL)
679 free((void *)kd->cpu_data);
680 if (kd->kcore_hdr != NULL)
681 free((void *)kd->kcore_hdr);
682 if (kd->procbase != 0)
683 free((void *)kd->procbase);
684 if (kd->swapspc != 0)
685 free((void *)kd->swapspc);
686 if (kd->argspc != 0)
687 free((void *)kd->argspc);
688 if (kd->argbuf != 0)
689 free((void *)kd->argbuf);
690 if (kd->argv != 0)
691 free((void *)kd->argv);
692 free((void *)kd);
693
694 return (0);
695 }
696
697 /*
698 * Set up state necessary to do queries on the kernel namelist
699 * data base. If the data base is out-of-data/incompatible with
700 * given executable, set up things so we revert to standard nlist call.
701 * Only called for live kernels. Return 0 on success, -1 on failure.
702 */
703 static int
704 kvm_dbopen(kd)
705 kvm_t *kd;
706 {
707 DBT rec;
708 int dbversionlen;
709 struct nlist nitem;
710 char dbversion[_POSIX2_LINE_MAX];
711 char kversion[_POSIX2_LINE_MAX];
712
713 kd->db = dbopen(_PATH_KVMDB, O_RDONLY, 0, DB_HASH, NULL);
714 if (kd->db == 0)
715 return (-1);
716 /*
717 * read version out of database
718 */
719 rec.data = VRS_KEY;
720 rec.size = sizeof(VRS_KEY) - 1;
721 if ((kd->db->get)(kd->db, (DBT *)&rec, (DBT *)&rec, 0))
722 goto close;
723 if (rec.data == 0 || rec.size > sizeof(dbversion))
724 goto close;
725
726 bcopy(rec.data, dbversion, rec.size);
727 dbversionlen = rec.size;
728 /*
729 * Read version string from kernel memory.
730 * Since we are dealing with a live kernel, we can call kvm_read()
731 * at this point.
732 */
733 rec.data = VRS_SYM;
734 rec.size = sizeof(VRS_SYM) - 1;
735 if ((kd->db->get)(kd->db, (DBT *)&rec, (DBT *)&rec, 0))
736 goto close;
737 if (rec.data == 0 || rec.size != sizeof(struct nlist))
738 goto close;
739 bcopy((char *)rec.data, (char *)&nitem, sizeof(nitem));
740 if (kvm_read(kd, (u_long)nitem.n_value, kversion, dbversionlen) !=
741 dbversionlen)
742 goto close;
743 /*
744 * If they match, we win - otherwise clear out kd->db so
745 * we revert to slow nlist().
746 */
747 if (bcmp(dbversion, kversion, dbversionlen) == 0)
748 return (0);
749 close:
750 (void)(kd->db->close)(kd->db);
751 kd->db = 0;
752
753 return (-1);
754 }
755
756 int
757 kvm_nlist(kd, nl)
758 kvm_t *kd;
759 struct nlist *nl;
760 {
761 register struct nlist *p;
762 register int nvalid, rv;
763
764 /*
765 * If we can't use the data base, revert to the
766 * slow library call.
767 */
768 if (kd->db == 0) {
769 rv = __fdnlist(kd->nlfd, nl);
770 if (rv == -1)
771 _kvm_err(kd, 0, "bad namelist");
772 return (rv);
773 }
774
775 /*
776 * We can use the kvm data base. Go through each nlist entry
777 * and look it up with a db query.
778 */
779 nvalid = 0;
780 for (p = nl; p->n_name && p->n_name[0]; ++p) {
781 register int len;
782 DBT rec;
783
784 if ((len = strlen(p->n_name)) > 4096) {
785 /* sanity */
786 _kvm_err(kd, kd->program, "symbol too large");
787 return (-1);
788 }
789 rec.data = p->n_name;
790 rec.size = len;
791
792 /*
793 * Make sure that n_value = 0 when the symbol isn't found
794 */
795 p->n_value = 0;
796
797 if ((kd->db->get)(kd->db, (DBT *)&rec, (DBT *)&rec, 0))
798 continue;
799 if (rec.data == 0 || rec.size != sizeof(struct nlist))
800 continue;
801 ++nvalid;
802 /*
803 * Avoid alignment issues.
804 */
805 bcopy((char *)&((struct nlist *)rec.data)->n_type,
806 (char *)&p->n_type,
807 sizeof(p->n_type));
808 bcopy((char *)&((struct nlist *)rec.data)->n_value,
809 (char *)&p->n_value,
810 sizeof(p->n_value));
811 }
812 /*
813 * Return the number of entries that weren't found.
814 */
815 return ((p - nl) - nvalid);
816 }
817
818 int kvm_dump_inval(kd)
819 kvm_t *kd;
820 {
821 struct nlist nlist[2];
822 u_long pa;
823
824 if (ISALIVE(kd)) {
825 _kvm_err(kd, kd->program, "clearing dump on live kernel");
826 return (-1);
827 }
828 nlist[0].n_name = "_dumpmag";
829 nlist[1].n_name = NULL;
830
831 if (kvm_nlist(kd, nlist) == -1) {
832 _kvm_err(kd, 0, "bad namelist");
833 return (-1);
834 }
835 if (_kvm_kvatop(kd, (u_long)nlist[0].n_value, &pa) == 0)
836 return (-1);
837
838 errno = 0;
839 if (lseek(kd->pmfd, _kvm_pa2off(kd, pa), SEEK_SET) == -1
840 && errno != 0) {
841 _kvm_err(kd, 0, "cannot invalidate dump - lseek");
842 return (-1);
843 }
844 pa = 0;
845 if (write(kd->pmfd, &pa, sizeof(pa)) != sizeof(pa)) {
846 _kvm_err(kd, 0, "cannot invalidate dump - write");
847 return (-1);
848 }
849 return (0);
850 }
851
852 ssize_t
853 kvm_read(kd, kva, buf, len)
854 kvm_t *kd;
855 register u_long kva;
856 register void *buf;
857 register size_t len;
858 {
859 register int cc;
860 register void *cp;
861
862 if (ISALIVE(kd)) {
863 /*
864 * We're using /dev/kmem. Just read straight from the
865 * device and let the active kernel do the address translation.
866 */
867 errno = 0;
868 if (lseek(kd->vmfd, (off_t)kva, SEEK_SET) == -1
869 && errno != 0) {
870 _kvm_err(kd, 0, "invalid address (%x)", kva);
871 return (0);
872 }
873 cc = read(kd->vmfd, buf, len);
874 if (cc < 0) {
875 _kvm_syserr(kd, 0, "kvm_read");
876 return (0);
877 } else if (cc < len)
878 _kvm_err(kd, kd->program, "short read");
879 return (cc);
880 } else {
881 if ((kd->kcore_hdr == NULL) || (kd->cpu_data == NULL)) {
882 _kvm_err(kd, kd->program, "no valid dump header");
883 return (0);
884 }
885 cp = buf;
886 while (len > 0) {
887 u_long pa;
888 off_t foff;
889
890 cc = _kvm_kvatop(kd, kva, &pa);
891 if (cc == 0)
892 return (0);
893 if (cc > len)
894 cc = len;
895 foff = _kvm_pa2off(kd, pa);
896 errno = 0;
897 if (lseek(kd->pmfd, foff, SEEK_SET) == -1
898 && errno != 0) {
899 _kvm_syserr(kd, 0, _PATH_MEM);
900 break;
901 }
902 cc = read(kd->pmfd, cp, cc);
903 if (cc < 0) {
904 _kvm_syserr(kd, kd->program, "kvm_read");
905 break;
906 }
907 /*
908 * If kvm_kvatop returns a bogus value or our core
909 * file is truncated, we might wind up seeking beyond
910 * the end of the core file in which case the read will
911 * return 0 (EOF).
912 */
913 if (cc == 0)
914 break;
915 cp = (char *)cp + cc;
916 kva += cc;
917 len -= cc;
918 }
919 return ((char *)cp - (char *)buf);
920 }
921 /* NOTREACHED */
922 }
923
924 ssize_t
925 kvm_write(kd, kva, buf, len)
926 kvm_t *kd;
927 register u_long kva;
928 register const void *buf;
929 register size_t len;
930 {
931 register int cc;
932
933 if (ISALIVE(kd)) {
934 /*
935 * Just like kvm_read, only we write.
936 */
937 errno = 0;
938 if (lseek(kd->vmfd, (off_t)kva, SEEK_SET) == -1
939 && errno != 0) {
940 _kvm_err(kd, 0, "invalid address (%x)", kva);
941 return (0);
942 }
943 cc = write(kd->vmfd, buf, len);
944 if (cc < 0) {
945 _kvm_syserr(kd, 0, "kvm_write");
946 return (0);
947 } else if (cc < len)
948 _kvm_err(kd, kd->program, "short write");
949 return (cc);
950 } else {
951 _kvm_err(kd, kd->program,
952 "kvm_write not implemented for dead kernels");
953 return (0);
954 }
955 /* NOTREACHED */
956 }
957