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