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