kvm.c revision 1.46 1 /* $NetBSD: kvm.c,v 1.46 1996/10/01 18:56:14 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.46 1996/10/01 18:56:14 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 *, 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 || (CORE_GETMID(cpu_hdr) != MID_MACHINE)) {
475 _kvm_err(kd, 0, "invalid magic in cpu_hdr");
476 return (0);
477 }
478 hdr_size = ALIGN(sizeof(cpu_hdr));
479
480 /*
481 * Read the CPU segment.
482 */
483 kd->cpu_dsize = cpu_hdr.c_size;
484 kd->cpu_data = _kvm_malloc(kd, kd->cpu_dsize);
485 if (kd->cpu_data == NULL)
486 goto fail;
487 if (Lseek(kd, kd->pmfd, dump_off+hdr_size, SEEK_SET) == -1)
488 goto fail;
489 sz = Read(kd, kd->pmfd, kd->cpu_data, cpu_hdr.c_size);
490 if (sz != cpu_hdr.c_size)
491 goto fail;
492 hdr_size += kd->cpu_dsize;
493
494 /*
495 * Leave phys mem pointer at beginning of memory data
496 */
497 kd->dump_off = dump_off + hdr_size;
498 if (Lseek(kd, kd->pmfd, kd->dump_off, SEEK_SET) == -1)
499 goto fail;
500
501 /*
502 * Create a kcore_hdr.
503 */
504 kd->kcore_hdr = _kvm_malloc(kd, sizeof(kcore_hdr_t));
505 if (kd->kcore_hdr == NULL)
506 goto fail;
507
508 kd->kcore_hdr->c_hdrsize = ALIGN(sizeof(kcore_hdr_t));
509 kd->kcore_hdr->c_seghdrsize = ALIGN(sizeof(kcore_seg_t));
510 kd->kcore_hdr->c_nseg = 2;
511 CORE_SETMAGIC(*(kd->kcore_hdr), KCORE_MAGIC, MID_MACHINE,0);
512
513 /*
514 * Now that we have a valid header, enable translations.
515 */
516 _kvm_initvtop(kd);
517
518 return(hdr_size);
519
520 fail:
521 if (kd->kcore_hdr != NULL) {
522 free(kd->kcore_hdr);
523 kd->kcore_hdr = NULL;
524 }
525 if (kd->cpu_data != NULL) {
526 free(kd->cpu_data);
527 kd->cpu_data = NULL;
528 kd->cpu_dsize = 0;
529 }
530 return (-1);
531 }
532
533 static int
534 clear_gap(kd, fp, size)
535 kvm_t *kd;
536 FILE *fp;
537 int size;
538 {
539 if (size <= 0) /* XXX - < 0 should never happen */
540 return (0);
541 while (size-- > 0) {
542 if (fputc(0, fp) == EOF) {
543 _kvm_syserr(kd, kd->program, "clear_gap");
544 return (-1);
545 }
546 }
547 return (0);
548 }
549
550 /*
551 * Write the dump header info to 'fp'. Note that we can't use fseek(3) here
552 * because 'fp' might be a file pointer obtained by zopen().
553 */
554 int
555 kvm_dump_wrtheader(kd, fp, dumpsize)
556 kvm_t *kd;
557 FILE *fp;
558 int dumpsize;
559 {
560 kcore_seg_t seghdr;
561 long offset;
562 int gap;
563
564 if (kd->kcore_hdr == NULL || kd->cpu_data == NULL) {
565 _kvm_err(kd, kd->program, "no valid dump header(s)");
566 return (-1);
567 }
568
569 /*
570 * Write the generic header
571 */
572 offset = 0;
573 if (fwrite((void*)kd->kcore_hdr, sizeof(kcore_hdr_t), 1, fp) <= 0) {
574 _kvm_syserr(kd, kd->program, "kvm_dump_wrtheader");
575 return (-1);
576 }
577 offset += kd->kcore_hdr->c_hdrsize;
578 gap = kd->kcore_hdr->c_hdrsize - sizeof(kcore_hdr_t);
579 if (clear_gap(kd, fp, gap) == -1)
580 return (-1);
581
582 /*
583 * Write the cpu header
584 */
585 CORE_SETMAGIC(seghdr, KCORESEG_MAGIC, 0, CORE_CPU);
586 seghdr.c_size = ALIGN(kd->cpu_dsize);
587 if (fwrite((void*)&seghdr, sizeof(seghdr), 1, fp) <= 0) {
588 _kvm_syserr(kd, kd->program, "kvm_dump_wrtheader");
589 return (-1);
590 }
591 offset += kd->kcore_hdr->c_seghdrsize;
592 gap = kd->kcore_hdr->c_seghdrsize - sizeof(seghdr);
593 if (clear_gap(kd, fp, gap) == -1)
594 return (-1);
595
596 if (fwrite((void*)kd->cpu_data, kd->cpu_dsize, 1, fp) <= 0) {
597 _kvm_syserr(kd, kd->program, "kvm_dump_wrtheader");
598 return (-1);
599 }
600 offset += seghdr.c_size;
601 gap = seghdr.c_size - kd->cpu_dsize;
602 if (clear_gap(kd, fp, gap) == -1)
603 return (-1);
604
605 /*
606 * Write the actual dump data segment header
607 */
608 CORE_SETMAGIC(seghdr, KCORESEG_MAGIC, 0, CORE_DATA);
609 seghdr.c_size = dumpsize;
610 if (fwrite((void*)&seghdr, sizeof(seghdr), 1, fp) <= 0) {
611 _kvm_syserr(kd, kd->program, "kvm_dump_wrtheader");
612 return (-1);
613 }
614 offset += kd->kcore_hdr->c_seghdrsize;
615 gap = kd->kcore_hdr->c_seghdrsize - sizeof(seghdr);
616 if (clear_gap(kd, fp, gap) == -1)
617 return (-1);
618
619 return (offset);
620 }
621
622 kvm_t *
623 kvm_openfiles(uf, mf, sf, flag, errout)
624 const char *uf;
625 const char *mf;
626 const char *sf;
627 int flag;
628 char *errout;
629 {
630 register kvm_t *kd;
631
632 if ((kd = malloc(sizeof(*kd))) == NULL) {
633 (void)strcpy(errout, strerror(errno));
634 return (0);
635 }
636 kd->program = 0;
637 return (_kvm_open(kd, uf, mf, sf, flag, errout));
638 }
639
640 kvm_t *
641 kvm_open(uf, mf, sf, flag, program)
642 const char *uf;
643 const char *mf;
644 const char *sf;
645 int flag;
646 const char *program;
647 {
648 register kvm_t *kd;
649
650 if ((kd = malloc(sizeof(*kd))) == NULL && program != NULL) {
651 (void)fprintf(stderr, "%s: %s\n", strerror(errno));
652 return (0);
653 }
654 kd->program = program;
655 return (_kvm_open(kd, uf, mf, sf, flag, NULL));
656 }
657
658 int
659 kvm_close(kd)
660 kvm_t *kd;
661 {
662 register int error = 0;
663
664 if (kd->pmfd >= 0)
665 error |= close(kd->pmfd);
666 if (kd->vmfd >= 0)
667 error |= close(kd->vmfd);
668 if (kd->nlfd >= 0)
669 error |= close(kd->nlfd);
670 if (kd->swfd >= 0)
671 error |= close(kd->swfd);
672 if (kd->db != 0)
673 error |= (kd->db->close)(kd->db);
674 if (kd->vmst)
675 _kvm_freevtop(kd);
676 kd->cpu_dsize = 0;
677 if (kd->cpu_data != NULL)
678 free((void *)kd->cpu_data);
679 if (kd->kcore_hdr != NULL)
680 free((void *)kd->kcore_hdr);
681 if (kd->procbase != 0)
682 free((void *)kd->procbase);
683 if (kd->swapspc != 0)
684 free((void *)kd->swapspc);
685 if (kd->argspc != 0)
686 free((void *)kd->argspc);
687 if (kd->argbuf != 0)
688 free((void *)kd->argbuf);
689 if (kd->argv != 0)
690 free((void *)kd->argv);
691 free((void *)kd);
692
693 return (0);
694 }
695
696 /*
697 * Set up state necessary to do queries on the kernel namelist
698 * data base. If the data base is out-of-data/incompatible with
699 * given executable, set up things so we revert to standard nlist call.
700 * Only called for live kernels. Return 0 on success, -1 on failure.
701 */
702 static int
703 kvm_dbopen(kd, uf)
704 kvm_t *kd;
705 const char *uf;
706 {
707 char *cp;
708 DBT rec;
709 int dbversionlen;
710 struct nlist nitem;
711 char dbversion[_POSIX2_LINE_MAX];
712 char kversion[_POSIX2_LINE_MAX];
713 char dbname[MAXPATHLEN];
714
715 if ((cp = rindex(uf, '/')) != 0)
716 uf = cp + 1;
717
718 (void)snprintf(dbname, sizeof(dbname), "%skvm_%s.db", _PATH_VARDB, uf);
719 kd->db = dbopen(dbname, O_RDONLY, 0, DB_HASH, NULL);
720 if (kd->db == 0)
721 return (-1);
722 /*
723 * read version out of database
724 */
725 rec.data = VRS_KEY;
726 rec.size = sizeof(VRS_KEY) - 1;
727 if ((kd->db->get)(kd->db, (DBT *)&rec, (DBT *)&rec, 0))
728 goto close;
729 if (rec.data == 0 || rec.size > sizeof(dbversion))
730 goto close;
731
732 bcopy(rec.data, dbversion, rec.size);
733 dbversionlen = rec.size;
734 /*
735 * Read version string from kernel memory.
736 * Since we are dealing with a live kernel, we can call kvm_read()
737 * at this point.
738 */
739 rec.data = VRS_SYM;
740 rec.size = sizeof(VRS_SYM) - 1;
741 if ((kd->db->get)(kd->db, (DBT *)&rec, (DBT *)&rec, 0))
742 goto close;
743 if (rec.data == 0 || rec.size != sizeof(struct nlist))
744 goto close;
745 bcopy((char *)rec.data, (char *)&nitem, sizeof(nitem));
746 if (kvm_read(kd, (u_long)nitem.n_value, kversion, dbversionlen) !=
747 dbversionlen)
748 goto close;
749 /*
750 * If they match, we win - otherwise clear out kd->db so
751 * we revert to slow nlist().
752 */
753 if (bcmp(dbversion, kversion, dbversionlen) == 0)
754 return (0);
755 close:
756 (void)(kd->db->close)(kd->db);
757 kd->db = 0;
758
759 return (-1);
760 }
761
762 int
763 kvm_nlist(kd, nl)
764 kvm_t *kd;
765 struct nlist *nl;
766 {
767 register struct nlist *p;
768 register int nvalid, rv;
769
770 /*
771 * If we can't use the data base, revert to the
772 * slow library call.
773 */
774 if (kd->db == 0) {
775 rv = __fdnlist(kd->nlfd, nl);
776 if (rv == -1)
777 _kvm_err(kd, 0, "bad namelist");
778 return (rv);
779 }
780
781 /*
782 * We can use the kvm data base. Go through each nlist entry
783 * and look it up with a db query.
784 */
785 nvalid = 0;
786 for (p = nl; p->n_name && p->n_name[0]; ++p) {
787 register int len;
788 DBT rec;
789
790 if ((len = strlen(p->n_name)) > 4096) {
791 /* sanity */
792 _kvm_err(kd, kd->program, "symbol too large");
793 return (-1);
794 }
795 rec.data = p->n_name;
796 rec.size = len;
797
798 /*
799 * Make sure that n_value = 0 when the symbol isn't found
800 */
801 p->n_value = 0;
802
803 if ((kd->db->get)(kd->db, (DBT *)&rec, (DBT *)&rec, 0))
804 continue;
805 if (rec.data == 0 || rec.size != sizeof(struct nlist))
806 continue;
807 ++nvalid;
808 /*
809 * Avoid alignment issues.
810 */
811 bcopy((char *)&((struct nlist *)rec.data)->n_type,
812 (char *)&p->n_type,
813 sizeof(p->n_type));
814 bcopy((char *)&((struct nlist *)rec.data)->n_value,
815 (char *)&p->n_value,
816 sizeof(p->n_value));
817 }
818 /*
819 * Return the number of entries that weren't found.
820 */
821 return ((p - nl) - nvalid);
822 }
823
824 int kvm_dump_inval(kd)
825 kvm_t *kd;
826 {
827 struct nlist nlist[2];
828 u_long pa;
829
830 if (ISALIVE(kd)) {
831 _kvm_err(kd, kd->program, "clearing dump on live kernel");
832 return (-1);
833 }
834 nlist[0].n_name = "_dumpmag";
835 nlist[1].n_name = NULL;
836
837 if (kvm_nlist(kd, nlist) == -1) {
838 _kvm_err(kd, 0, "bad namelist");
839 return (-1);
840 }
841 if (_kvm_kvatop(kd, (u_long)nlist[0].n_value, &pa) == 0)
842 return (-1);
843
844 errno = 0;
845 if (lseek(kd->pmfd, _kvm_pa2off(kd, pa), SEEK_SET) == -1
846 && errno != 0) {
847 _kvm_err(kd, 0, "cannot invalidate dump - lseek");
848 return (-1);
849 }
850 pa = 0;
851 if (write(kd->pmfd, &pa, sizeof(pa)) != sizeof(pa)) {
852 _kvm_err(kd, 0, "cannot invalidate dump - write");
853 return (-1);
854 }
855 return (0);
856 }
857
858 ssize_t
859 kvm_read(kd, kva, buf, len)
860 kvm_t *kd;
861 register u_long kva;
862 register void *buf;
863 register size_t len;
864 {
865 register int cc;
866 register void *cp;
867
868 if (ISALIVE(kd)) {
869 /*
870 * We're using /dev/kmem. Just read straight from the
871 * device and let the active kernel do the address translation.
872 */
873 errno = 0;
874 if (lseek(kd->vmfd, (off_t)kva, SEEK_SET) == -1
875 && errno != 0) {
876 _kvm_err(kd, 0, "invalid address (%x)", kva);
877 return (0);
878 }
879 cc = read(kd->vmfd, buf, len);
880 if (cc < 0) {
881 _kvm_syserr(kd, 0, "kvm_read");
882 return (0);
883 } else if (cc < len)
884 _kvm_err(kd, kd->program, "short read");
885 return (cc);
886 } else {
887 if ((kd->kcore_hdr == NULL) || (kd->cpu_data == NULL)) {
888 _kvm_err(kd, kd->program, "no valid dump header");
889 return (0);
890 }
891 cp = buf;
892 while (len > 0) {
893 u_long pa;
894 off_t foff;
895
896 cc = _kvm_kvatop(kd, kva, &pa);
897 if (cc == 0)
898 return (0);
899 if (cc > len)
900 cc = len;
901 foff = _kvm_pa2off(kd, pa);
902 errno = 0;
903 if (lseek(kd->pmfd, foff, SEEK_SET) == -1
904 && errno != 0) {
905 _kvm_syserr(kd, 0, _PATH_MEM);
906 break;
907 }
908 cc = read(kd->pmfd, cp, cc);
909 if (cc < 0) {
910 _kvm_syserr(kd, kd->program, "kvm_read");
911 break;
912 }
913 /*
914 * If kvm_kvatop returns a bogus value or our core
915 * file is truncated, we might wind up seeking beyond
916 * the end of the core file in which case the read will
917 * return 0 (EOF).
918 */
919 if (cc == 0)
920 break;
921 cp = (char *)cp + cc;
922 kva += cc;
923 len -= cc;
924 }
925 return ((char *)cp - (char *)buf);
926 }
927 /* NOTREACHED */
928 }
929
930 ssize_t
931 kvm_write(kd, kva, buf, len)
932 kvm_t *kd;
933 register u_long kva;
934 register const void *buf;
935 register size_t len;
936 {
937 register int cc;
938
939 if (ISALIVE(kd)) {
940 /*
941 * Just like kvm_read, only we write.
942 */
943 errno = 0;
944 if (lseek(kd->vmfd, (off_t)kva, SEEK_SET) == -1
945 && errno != 0) {
946 _kvm_err(kd, 0, "invalid address (%x)", kva);
947 return (0);
948 }
949 cc = write(kd->vmfd, buf, len);
950 if (cc < 0) {
951 _kvm_syserr(kd, 0, "kvm_write");
952 return (0);
953 } else if (cc < len)
954 _kvm_err(kd, kd->program, "short write");
955 return (cc);
956 } else {
957 _kvm_err(kd, kd->program,
958 "kvm_write not implemented for dead kernels");
959 return (0);
960 }
961 /* NOTREACHED */
962 }
963