Annotation of src/lib/libkvm/kvm.c, Revision 1.90
1.90 ! joerg 1: /* $NetBSD: kvm.c,v 1.89 2007/11/08 20:48:05 joerg Exp $ */
1.42 thorpej 2:
1.1 cgd 3: /*-
1.35 cgd 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.
1.1 cgd 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.
1.81 agc 19: * 3. Neither the name of the University nor the names of its contributors
1.1 cgd 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:
1.53 mikel 36: #include <sys/cdefs.h>
1.1 cgd 37: #if defined(LIBC_SCCS) && !defined(lint)
1.42 thorpej 38: #if 0
1.35 cgd 39: static char sccsid[] = "@(#)kvm.c 8.2 (Berkeley) 2/13/94";
1.42 thorpej 40: #else
1.90 ! joerg 41: __RCSID("$NetBSD: kvm.c,v 1.89 2007/11/08 20:48:05 joerg Exp $");
1.42 thorpej 42: #endif
1.1 cgd 43: #endif /* LIBC_SCCS and not lint */
44:
45: #include <sys/param.h>
46: #include <sys/user.h>
1.79 thorpej 47: #include <sys/lwp.h>
1.1 cgd 48: #include <sys/proc.h>
49: #include <sys/ioctl.h>
1.35 cgd 50: #include <sys/stat.h>
51: #include <sys/sysctl.h>
52:
1.40 leo 53: #include <sys/core.h>
54: #include <sys/exec_aout.h>
55: #include <sys/kcore.h>
1.80 ragge 56: #include <sys/ksyms.h>
1.40 leo 57:
1.67 mrg 58: #include <uvm/uvm_extern.h>
1.35 cgd 59:
1.76 atatat 60: #include <machine/cpu.h>
61:
1.35 cgd 62: #include <ctype.h>
1.87 yamt 63: #include <errno.h>
1.1 cgd 64: #include <fcntl.h>
65: #include <limits.h>
1.35 cgd 66: #include <nlist.h>
1.1 cgd 67: #include <paths.h>
1.71 wiz 68: #include <stdarg.h>
1.1 cgd 69: #include <stdio.h>
1.35 cgd 70: #include <stdlib.h>
1.1 cgd 71: #include <string.h>
1.35 cgd 72: #include <unistd.h>
1.41 leo 73: #include <kvm.h>
1.1 cgd 74:
1.35 cgd 75: #include "kvm_private.h"
1.1 cgd 76:
1.88 joerg 77: static int _kvm_get_header(kvm_t *);
78: static kvm_t *_kvm_open(kvm_t *, const char *, const char *,
79: const char *, int, char *);
1.89 joerg 80: static int clear_gap(kvm_t *, bool (*)(void *, const void *, size_t),
81: void *, size_t);
1.88 joerg 82: static int open_cloexec(const char *, int, int);
83: static off_t Lseek(kvm_t *, int, off_t, int);
84: static ssize_t Pread(kvm_t *, int, void *, size_t, off_t);
1.19 mycroft 85:
1.35 cgd 86: char *
1.88 joerg 87: kvm_geterr(kvm_t *kd)
1.35 cgd 88: {
89: return (kd->errbuf);
90: }
1.1 cgd 91:
1.35 cgd 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;
1.27 phil 102:
1.35 cgd 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,
1.60 thorpej 110: sizeof(kd->errbuf), fmt, ap);
1.26 pk 111:
1.35 cgd 112: va_end(ap);
113: }
1.26 pk 114:
1.35 cgd 115: void
116: _kvm_syserr(kvm_t *kd, const char *program, const char *fmt, ...)
117: {
118: va_list ap;
1.60 thorpej 119: size_t n;
1.26 pk 120:
1.35 cgd 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 {
1.55 perry 127: char *cp = kd->errbuf;
1.26 pk 128:
1.60 thorpej 129: (void)vsnprintf(cp, sizeof(kd->errbuf), fmt, ap);
1.35 cgd 130: n = strlen(cp);
131: (void)snprintf(&cp[n], sizeof(kd->errbuf) - n, ": %s",
132: strerror(errno));
133: }
134: va_end(ap);
135: }
1.1 cgd 136:
1.35 cgd 137: void *
1.88 joerg 138: _kvm_malloc(kvm_t *kd, size_t n)
1.35 cgd 139: {
140: void *p;
141:
142: if ((p = malloc(n)) == NULL)
1.68 sommerfe 143: _kvm_err(kd, kd->program, "%s", strerror(errno));
1.35 cgd 144: return (p);
145: }
146:
1.40 leo 147: /*
1.73 christos 148: * Open a file setting the close on exec bit.
149: */
150: static int
1.88 joerg 151: open_cloexec(const char *fname, int flags, int mode)
1.73 christos 152: {
153: int fd;
154:
155: if ((fd = open(fname, flags, mode)) == -1)
156: return fd;
1.77 christos 157: if (fcntl(fd, F_SETFD, FD_CLOEXEC) == -1)
1.73 christos 158: goto error;
159:
160: return fd;
161: error:
162: flags = errno;
163: (void)close(fd);
164: errno = flags;
165: return -1;
166: }
167:
168: /*
1.58 thorpej 169: * Wrapper around the lseek(2) system call; calls _kvm_syserr() for us
170: * in the event of emergency.
1.40 leo 171: */
172: static off_t
1.88 joerg 173: Lseek(kvm_t *kd, int fd, off_t offset, int whence)
1.40 leo 174: {
1.58 thorpej 175: off_t off;
1.40 leo 176:
177: errno = 0;
1.58 thorpej 178:
1.40 leo 179: if ((off = lseek(fd, offset, whence)) == -1 && errno != 0) {
180: _kvm_syserr(kd, kd->program, "Lseek");
1.58 thorpej 181: return ((off_t)-1);
1.40 leo 182: }
183: return (off);
184: }
185:
1.58 thorpej 186: /*
187: * Wrapper around the pread(2) system call; calls _kvm_syserr() for us
188: * in the event of emergency.
189: */
1.40 leo 190: static ssize_t
1.88 joerg 191: Pread(kvm_t *kd, int fd, void *buf, size_t nbytes, off_t offset)
1.40 leo 192: {
1.58 thorpej 193: ssize_t rv;
1.40 leo 194:
195: errno = 0;
196:
1.58 thorpej 197: if ((rv = pread(fd, buf, nbytes, offset)) != nbytes &&
198: errno != 0)
199: _kvm_syserr(kd, kd->program, "Pread");
1.40 leo 200: return (rv);
201: }
202:
1.35 cgd 203: static kvm_t *
1.88 joerg 204: _kvm_open(kvm_t *kd, const char *uf, const char *mf, const char *sf, int flag,
205: char *errout)
1.35 cgd 206: {
207: struct stat st;
1.48 cgd 208: int ufgiven;
1.35 cgd 209:
1.37 mycroft 210: kd->pmfd = -1;
1.35 cgd 211: kd->vmfd = -1;
212: kd->swfd = -1;
213: kd->nlfd = -1;
1.65 simonb 214: kd->alive = KVM_ALIVE_DEAD;
1.85 christos 215: kd->procbase = NULL;
216: kd->procbase_len = 0;
217: kd->procbase2 = NULL;
218: kd->procbase2_len = 0;
219: kd->lwpbase = NULL;
220: kd->lwpbase_len = 0;
1.36 mycroft 221: kd->nbpg = getpagesize();
1.85 christos 222: kd->swapspc = NULL;
223: kd->argspc = NULL;
224: kd->argspc_len = 0;
225: kd->argbuf = NULL;
226: kd->argv = NULL;
227: kd->vmst = NULL;
228: kd->vm_page_buckets = NULL;
229: kd->kcore_hdr = NULL;
1.43 gwr 230: kd->cpu_dsize = 0;
1.85 christos 231: kd->cpu_data = NULL;
1.40 leo 232: kd->dump_off = 0;
1.52 gwr 233:
1.65 simonb 234: if (flag & KVM_NO_FILES) {
235: kd->alive = KVM_ALIVE_SYSCTL;
236: return(kd);
237: }
238:
1.52 gwr 239: /*
240: * Call the MD open hook. This sets:
241: * usrstack, min_uva, max_uva
242: */
243: if (_kvm_mdopen(kd)) {
244: _kvm_err(kd, kd->program, "md init failed");
245: goto failed;
246: }
1.35 cgd 247:
1.48 cgd 248: ufgiven = (uf != NULL);
1.76 atatat 249: if (!ufgiven) {
250: #ifdef CPU_BOOTED_KERNEL
251: /* 130 is 128 + '/' + '\0' */
252: static char booted_kernel[130];
253: int mib[2], rc;
254: size_t len;
255:
256: mib[0] = CTL_MACHDEP;
257: mib[1] = CPU_BOOTED_KERNEL;
258: booted_kernel[0] = '/';
259: booted_kernel[1] = '\0';
260: len = sizeof(booted_kernel) - 2;
261: rc = sysctl(&mib[0], 2, &booted_kernel[1], &len, NULL, 0);
262: booted_kernel[sizeof(booted_kernel) - 1] = '\0';
263: uf = (booted_kernel[1] == '/') ?
264: &booted_kernel[1] : &booted_kernel[0];
265: if (rc != -1)
266: rc = stat(uf, &st);
267: if (rc != -1 && !S_ISREG(st.st_mode))
268: rc = -1;
269: if (rc == -1)
270: #endif /* CPU_BOOTED_KERNEL */
271: uf = _PATH_UNIX;
272: }
1.35 cgd 273: else if (strlen(uf) >= MAXPATHLEN) {
274: _kvm_err(kd, kd->program, "exec file name too long");
1.1 cgd 275: goto failed;
276: }
1.35 cgd 277: if (flag & ~O_RDWR) {
278: _kvm_err(kd, kd->program, "bad flags arg");
1.1 cgd 279: goto failed;
280: }
1.35 cgd 281: if (mf == 0)
282: mf = _PATH_MEM;
283: if (sf == 0)
284: sf = _PATH_DRUM;
285:
1.73 christos 286: if ((kd->pmfd = open_cloexec(mf, flag, 0)) < 0) {
1.35 cgd 287: _kvm_syserr(kd, kd->program, "%s", mf);
288: goto failed;
1.1 cgd 289: }
1.35 cgd 290: if (fstat(kd->pmfd, &st) < 0) {
291: _kvm_syserr(kd, kd->program, "%s", mf);
1.1 cgd 292: goto failed;
293: }
1.35 cgd 294: if (S_ISCHR(st.st_mode)) {
1.1 cgd 295: /*
1.35 cgd 296: * If this is a character special device, then check that
297: * it's /dev/mem. If so, open kmem too. (Maybe we should
298: * make it work for either /dev/mem or /dev/kmem -- in either
299: * case you're working with a live kernel.)
1.1 cgd 300: */
1.35 cgd 301: if (strcmp(mf, _PATH_MEM) != 0) { /* XXX */
302: _kvm_err(kd, kd->program,
303: "%s: not physical memory device", mf);
304: goto failed;
1.1 cgd 305: }
1.73 christos 306: if ((kd->vmfd = open_cloexec(_PATH_KMEM, flag, 0)) < 0) {
1.35 cgd 307: _kvm_syserr(kd, kd->program, "%s", _PATH_KMEM);
308: goto failed;
1.1 cgd 309: }
1.65 simonb 310: kd->alive = KVM_ALIVE_FILES;
1.73 christos 311: if ((kd->swfd = open_cloexec(sf, flag, 0)) < 0) {
1.84 yamt 312: if (errno != ENXIO) {
313: _kvm_syserr(kd, kd->program, "%s", sf);
314: goto failed;
315: }
316: /* swap is not configured? not fatal */
1.1 cgd 317: }
318: /*
1.80 ragge 319: * Open the kernel namelist. If /dev/ksyms doesn't
320: * exist, open the current kernel.
1.1 cgd 321: */
1.80 ragge 322: if (ufgiven == 0)
323: kd->nlfd = open_cloexec(_PATH_KSYMS, O_RDONLY, 0);
324: if (kd->nlfd < 0) {
325: if ((kd->nlfd = open_cloexec(uf, O_RDONLY, 0)) < 0) {
326: _kvm_syserr(kd, kd->program, "%s", uf);
327: goto failed;
328: }
1.82 cube 329: } else {
330: /*
331: * We're here because /dev/ksyms was opened
332: * successfully. However, we don't want to keep it
333: * open, so we close it now. Later, we will open
334: * it again, since it will be the only case where
335: * kd->nlfd is negative.
336: */
337: close(kd->nlfd);
338: kd->nlfd = -1;
1.3 cgd 339: }
1.35 cgd 340: } else {
1.3 cgd 341: /*
1.35 cgd 342: * This is a crash dump.
1.70 wiz 343: * Initialize the virtual address translation machinery,
1.35 cgd 344: * but first setup the namelist fd.
1.3 cgd 345: */
1.73 christos 346: if ((kd->nlfd = open_cloexec(uf, O_RDONLY, 0)) < 0) {
1.35 cgd 347: _kvm_syserr(kd, kd->program, "%s", uf);
348: goto failed;
1.3 cgd 349: }
1.40 leo 350:
351: /*
352: * If there is no valid core header, fail silently here.
1.64 simonb 353: * The address translations however will fail without
1.40 leo 354: * header. Things can be made to run by calling
355: * kvm_dump_mkheader() before doing any translation.
356: */
357: if (_kvm_get_header(kd) == 0) {
358: if (_kvm_initvtop(kd) < 0)
359: goto failed;
360: }
1.3 cgd 361: }
1.35 cgd 362: return (kd);
363: failed:
1.1 cgd 364: /*
1.35 cgd 365: * Copy out the error if doing sane error semantics.
1.1 cgd 366: */
1.35 cgd 367: if (errout != 0)
1.78 itojun 368: (void)strlcpy(errout, kd->errbuf, _POSIX2_LINE_MAX);
1.35 cgd 369: (void)kvm_close(kd);
370: return (0);
1.1 cgd 371: }
372:
1.43 gwr 373: /*
374: * The kernel dump file (from savecore) contains:
375: * kcore_hdr_t kcore_hdr;
376: * kcore_seg_t cpu_hdr;
377: * (opaque) cpu_data; (size is cpu_hdr.c_size)
378: * kcore_seg_t mem_hdr;
379: * (memory) mem_data; (size is mem_hdr.c_size)
1.64 simonb 380: *
1.43 gwr 381: * Note: khdr is padded to khdr.c_hdrsize;
382: * cpu_hdr and mem_hdr are padded to khdr.c_seghdrsize
383: */
1.40 leo 384: static int
1.88 joerg 385: _kvm_get_header(kvm_t *kd)
1.40 leo 386: {
1.43 gwr 387: kcore_hdr_t kcore_hdr;
388: kcore_seg_t cpu_hdr;
389: kcore_seg_t mem_hdr;
390: size_t offset;
391: ssize_t sz;
1.40 leo 392:
1.43 gwr 393: /*
394: * Read the kcore_hdr_t
395: */
1.58 thorpej 396: sz = Pread(kd, kd->pmfd, &kcore_hdr, sizeof(kcore_hdr), (off_t)0);
1.43 gwr 397: if (sz != sizeof(kcore_hdr))
1.40 leo 398: return (-1);
399:
400: /*
401: * Currently, we only support dump-files made by the current
402: * architecture...
403: */
1.43 gwr 404: if ((CORE_GETMAGIC(kcore_hdr) != KCORE_MAGIC) ||
405: (CORE_GETMID(kcore_hdr) != MID_MACHINE))
406: return (-1);
1.40 leo 407:
408: /*
409: * Currently, we only support exactly 2 segments: cpu-segment
410: * and data-segment in exactly that order.
411: */
1.43 gwr 412: if (kcore_hdr.c_nseg != 2)
1.40 leo 413: return (-1);
414:
415: /*
1.43 gwr 416: * Save away the kcore_hdr. All errors after this
417: * should do a to "goto fail" to deallocate things.
418: */
419: kd->kcore_hdr = _kvm_malloc(kd, sizeof(kcore_hdr));
420: memcpy(kd->kcore_hdr, &kcore_hdr, sizeof(kcore_hdr));
421: offset = kcore_hdr.c_hdrsize;
422:
423: /*
424: * Read the CPU segment header
1.40 leo 425: */
1.58 thorpej 426: sz = Pread(kd, kd->pmfd, &cpu_hdr, sizeof(cpu_hdr), (off_t)offset);
1.43 gwr 427: if (sz != sizeof(cpu_hdr))
428: goto fail;
429: if ((CORE_GETMAGIC(cpu_hdr) != KCORESEG_MAGIC) ||
430: (CORE_GETFLAG(cpu_hdr) != CORE_CPU))
431: goto fail;
432: offset += kcore_hdr.c_seghdrsize;
433:
434: /*
435: * Read the CPU segment DATA.
436: */
437: kd->cpu_dsize = cpu_hdr.c_size;
438: kd->cpu_data = _kvm_malloc(kd, cpu_hdr.c_size);
439: if (kd->cpu_data == NULL)
440: goto fail;
1.58 thorpej 441: sz = Pread(kd, kd->pmfd, kd->cpu_data, cpu_hdr.c_size, (off_t)offset);
1.43 gwr 442: if (sz != cpu_hdr.c_size)
443: goto fail;
444: offset += cpu_hdr.c_size;
1.40 leo 445:
446: /*
447: * Read the next segment header: data segment
448: */
1.58 thorpej 449: sz = Pread(kd, kd->pmfd, &mem_hdr, sizeof(mem_hdr), (off_t)offset);
1.43 gwr 450: if (sz != sizeof(mem_hdr))
451: goto fail;
452: offset += kcore_hdr.c_seghdrsize;
453:
454: if ((CORE_GETMAGIC(mem_hdr) != KCORESEG_MAGIC) ||
455: (CORE_GETFLAG(mem_hdr) != CORE_DATA))
456: goto fail;
1.40 leo 457:
1.43 gwr 458: kd->dump_off = offset;
459: return (0);
1.40 leo 460:
1.43 gwr 461: fail:
462: if (kd->kcore_hdr != NULL) {
463: free(kd->kcore_hdr);
1.40 leo 464: kd->kcore_hdr = NULL;
1.43 gwr 465: }
466: if (kd->cpu_data != NULL) {
467: free(kd->cpu_data);
468: kd->cpu_data = NULL;
469: kd->cpu_dsize = 0;
1.40 leo 470: }
1.54 mrg 471: return (-1);
1.40 leo 472: }
473:
474: /*
1.43 gwr 475: * The format while on the dump device is: (new format)
1.47 cgd 476: * kcore_seg_t cpu_hdr;
477: * (opaque) cpu_data; (size is cpu_hdr.c_size)
478: * kcore_seg_t mem_hdr;
479: * (memory) mem_data; (size is mem_hdr.c_size)
1.40 leo 480: */
481: int
1.88 joerg 482: kvm_dump_mkheader(kvm_t *kd, off_t dump_off)
1.40 leo 483: {
1.43 gwr 484: kcore_seg_t cpu_hdr;
1.60 thorpej 485: size_t hdr_size;
486: ssize_t sz;
1.40 leo 487:
1.41 leo 488: if (kd->kcore_hdr != NULL) {
489: _kvm_err(kd, kd->program, "already has a dump header");
1.40 leo 490: return (-1);
491: }
1.41 leo 492: if (ISALIVE(kd)) {
493: _kvm_err(kd, kd->program, "don't use on live kernel");
1.40 leo 494: return (-1);
495: }
496:
497: /*
1.43 gwr 498: * Validate new format crash dump
1.40 leo 499: */
1.58 thorpej 500: sz = Pread(kd, kd->pmfd, &cpu_hdr, sizeof(cpu_hdr), dump_off);
1.43 gwr 501: if (sz != sizeof(cpu_hdr))
502: return (-1);
1.44 leo 503: if ((CORE_GETMAGIC(cpu_hdr) != KCORE_MAGIC)
504: || (CORE_GETMID(cpu_hdr) != MID_MACHINE)) {
505: _kvm_err(kd, 0, "invalid magic in cpu_hdr");
1.45 leo 506: return (0);
1.44 leo 507: }
1.43 gwr 508: hdr_size = ALIGN(sizeof(cpu_hdr));
509:
510: /*
511: * Read the CPU segment.
512: */
513: kd->cpu_dsize = cpu_hdr.c_size;
514: kd->cpu_data = _kvm_malloc(kd, kd->cpu_dsize);
515: if (kd->cpu_data == NULL)
516: goto fail;
1.58 thorpej 517: sz = Pread(kd, kd->pmfd, kd->cpu_data, cpu_hdr.c_size,
518: dump_off + hdr_size);
1.43 gwr 519: if (sz != cpu_hdr.c_size)
520: goto fail;
521: hdr_size += kd->cpu_dsize;
522:
523: /*
524: * Leave phys mem pointer at beginning of memory data
525: */
526: kd->dump_off = dump_off + hdr_size;
527: if (Lseek(kd, kd->pmfd, kd->dump_off, SEEK_SET) == -1)
528: goto fail;
1.40 leo 529:
530: /*
531: * Create a kcore_hdr.
532: */
1.43 gwr 533: kd->kcore_hdr = _kvm_malloc(kd, sizeof(kcore_hdr_t));
534: if (kd->kcore_hdr == NULL)
535: goto fail;
1.40 leo 536:
1.41 leo 537: kd->kcore_hdr->c_hdrsize = ALIGN(sizeof(kcore_hdr_t));
538: kd->kcore_hdr->c_seghdrsize = ALIGN(sizeof(kcore_seg_t));
539: kd->kcore_hdr->c_nseg = 2;
540: CORE_SETMAGIC(*(kd->kcore_hdr), KCORE_MAGIC, MID_MACHINE,0);
1.40 leo 541:
542: /*
543: * Now that we have a valid header, enable translations.
544: */
1.49 pk 545: if (_kvm_initvtop(kd) == 0)
546: /* Success */
547: return (hdr_size);
1.43 gwr 548:
549: fail:
550: if (kd->kcore_hdr != NULL) {
551: free(kd->kcore_hdr);
552: kd->kcore_hdr = NULL;
553: }
554: if (kd->cpu_data != NULL) {
555: free(kd->cpu_data);
556: kd->cpu_data = NULL;
557: kd->cpu_dsize = 0;
558: }
559: return (-1);
1.40 leo 560: }
561:
562: static int
1.89 joerg 563: clear_gap(kvm_t *kd, bool (*write_buf)(void *, const void *, size_t),
564: void *cookie, size_t size)
1.40 leo 565: {
1.89 joerg 566: char buf[1024];
567: size_t len;
568:
569: (void)memset(buf, 0, size > sizeof(buf) ? sizeof(buf) : size);
570:
571: while (size > 0) {
572: len = size > sizeof(buf) ? sizeof(buf) : size;
573: if (!(*write_buf)(cookie, buf, len)) {
1.40 leo 574: _kvm_syserr(kd, kd->program, "clear_gap");
1.89 joerg 575: return -1;
1.40 leo 576: }
1.89 joerg 577: size -= len;
578: }
579:
580: return 0;
1.40 leo 581: }
582:
583: /*
1.89 joerg 584: * Write the dump header by calling write_buf with cookie as first argument.
1.40 leo 585: */
586: int
1.89 joerg 587: kvm_dump_header(kvm_t *kd, bool (*write_buf)(void *, const void *, size_t),
588: void *cookie, int dumpsize)
1.40 leo 589: {
590: kcore_seg_t seghdr;
591: long offset;
1.89 joerg 592: size_t gap;
1.40 leo 593:
1.43 gwr 594: if (kd->kcore_hdr == NULL || kd->cpu_data == NULL) {
1.40 leo 595: _kvm_err(kd, kd->program, "no valid dump header(s)");
596: return (-1);
597: }
598:
599: /*
600: * Write the generic header
601: */
602: offset = 0;
1.89 joerg 603: if (!(*write_buf)(cookie, kd->kcore_hdr, sizeof(kcore_hdr_t))) {
604: _kvm_syserr(kd, kd->program, "kvm_dump_header");
1.40 leo 605: return (-1);
606: }
607: offset += kd->kcore_hdr->c_hdrsize;
608: gap = kd->kcore_hdr->c_hdrsize - sizeof(kcore_hdr_t);
1.89 joerg 609: if (clear_gap(kd, write_buf, cookie, gap) == -1)
1.40 leo 610: return (-1);
611:
612: /*
1.83 wiz 613: * Write the CPU header
1.40 leo 614: */
615: CORE_SETMAGIC(seghdr, KCORESEG_MAGIC, 0, CORE_CPU);
1.43 gwr 616: seghdr.c_size = ALIGN(kd->cpu_dsize);
1.89 joerg 617: if (!(*write_buf)(cookie, &seghdr, sizeof(seghdr))) {
618: _kvm_syserr(kd, kd->program, "kvm_dump_header");
1.40 leo 619: return (-1);
620: }
621: offset += kd->kcore_hdr->c_seghdrsize;
622: gap = kd->kcore_hdr->c_seghdrsize - sizeof(seghdr);
1.89 joerg 623: if (clear_gap(kd, write_buf, cookie, gap) == -1)
1.40 leo 624: return (-1);
625:
1.89 joerg 626: if (!(*write_buf)(cookie, kd->cpu_data, kd->cpu_dsize)) {
627: _kvm_syserr(kd, kd->program, "kvm_dump_header");
1.40 leo 628: return (-1);
629: }
630: offset += seghdr.c_size;
1.43 gwr 631: gap = seghdr.c_size - kd->cpu_dsize;
1.90 ! joerg 632: if (clear_gap(kd, write_buf, cookie, gap) == -1)
1.40 leo 633: return (-1);
634:
635: /*
636: * Write the actual dump data segment header
637: */
638: CORE_SETMAGIC(seghdr, KCORESEG_MAGIC, 0, CORE_DATA);
639: seghdr.c_size = dumpsize;
1.89 joerg 640: if (!(*write_buf)(cookie, &seghdr, sizeof(seghdr))) {
641: _kvm_syserr(kd, kd->program, "kvm_dump_header");
1.40 leo 642: return (-1);
643: }
644: offset += kd->kcore_hdr->c_seghdrsize;
645: gap = kd->kcore_hdr->c_seghdrsize - sizeof(seghdr);
1.89 joerg 646: if (clear_gap(kd, write_buf, cookie, gap) == -1)
1.40 leo 647: return (-1);
648:
1.62 christos 649: return (int)offset;
1.40 leo 650: }
651:
1.89 joerg 652: static bool
653: kvm_dump_header_stdio(void *cookie, const void *buf, size_t len)
654: {
655: return fwrite(buf, len, 1, (FILE *)cookie) == 1;
656: }
657:
658: int
659: kvm_dump_wrtheader(kvm_t *kd, FILE *fp, int dumpsize)
660: {
661: return kvm_dump_header(kd, kvm_dump_header_stdio, fp, dumpsize);
662: }
663:
1.35 cgd 664: kvm_t *
1.88 joerg 665: kvm_openfiles(const char *uf, const char *mf, const char *sf,
666: int flag, char *errout)
1.35 cgd 667: {
1.55 perry 668: kvm_t *kd;
1.35 cgd 669:
670: if ((kd = malloc(sizeof(*kd))) == NULL) {
1.78 itojun 671: (void)strlcpy(errout, strerror(errno), _POSIX2_LINE_MAX);
1.35 cgd 672: return (0);
673: }
674: kd->program = 0;
675: return (_kvm_open(kd, uf, mf, sf, flag, errout));
676: }
677:
678: kvm_t *
1.88 joerg 679: kvm_open(const char *uf, const char *mf, const char *sf, int flag,
680: const char *program)
1.35 cgd 681: {
1.55 perry 682: kvm_t *kd;
1.35 cgd 683:
1.86 christos 684: if ((kd = malloc(sizeof(*kd))) == NULL) {
685: (void)fprintf(stderr, "%s: %s\n",
686: program ? program : getprogname(), strerror(errno));
1.35 cgd 687: return (0);
1.19 mycroft 688: }
1.35 cgd 689: kd->program = program;
690: return (_kvm_open(kd, uf, mf, sf, flag, NULL));
1.8 cgd 691: }
692:
693: int
1.88 joerg 694: kvm_close(kvm_t *kd)
1.1 cgd 695: {
1.55 perry 696: int error = 0;
1.24 mycroft 697:
1.35 cgd 698: if (kd->pmfd >= 0)
699: error |= close(kd->pmfd);
700: if (kd->vmfd >= 0)
701: error |= close(kd->vmfd);
702: if (kd->nlfd >= 0)
703: error |= close(kd->nlfd);
704: if (kd->swfd >= 0)
705: error |= close(kd->swfd);
706: if (kd->vmst)
707: _kvm_freevtop(kd);
1.43 gwr 708: kd->cpu_dsize = 0;
709: if (kd->cpu_data != NULL)
710: free((void *)kd->cpu_data);
1.40 leo 711: if (kd->kcore_hdr != NULL)
712: free((void *)kd->kcore_hdr);
1.35 cgd 713: if (kd->procbase != 0)
714: free((void *)kd->procbase);
1.65 simonb 715: if (kd->procbase2 != 0)
716: free((void *)kd->procbase2);
1.79 thorpej 717: if (kd->lwpbase != 0)
718: free((void *)kd->lwpbase);
1.36 mycroft 719: if (kd->swapspc != 0)
720: free((void *)kd->swapspc);
721: if (kd->argspc != 0)
722: free((void *)kd->argspc);
1.38 mycroft 723: if (kd->argbuf != 0)
724: free((void *)kd->argbuf);
1.35 cgd 725: if (kd->argv != 0)
726: free((void *)kd->argv);
727: free((void *)kd);
1.19 mycroft 728:
1.1 cgd 729: return (0);
730: }
731:
1.18 mycroft 732: int
1.88 joerg 733: kvm_nlist(kvm_t *kd, struct nlist *nl)
1.18 mycroft 734: {
1.82 cube 735: int rv, nlfd;
736:
737: /*
738: * kd->nlfd might be negative when we get here, and in that
739: * case that means that we're using /dev/ksyms.
740: * So open it again, just for the time we retrieve the list.
741: */
742: if (kd->nlfd < 0) {
743: nlfd = open_cloexec(_PATH_KSYMS, O_RDONLY, 0);
744: if (nlfd < 0) {
745: _kvm_err(kd, 0, "failed to open %s", _PATH_KSYMS);
746: return (nlfd);
747: }
748: } else
749: nlfd = kd->nlfd;
1.3 cgd 750:
1.35 cgd 751: /*
1.80 ragge 752: * Call the nlist(3) routines to retrieve the given namelist.
1.35 cgd 753: */
1.82 cube 754: rv = __fdnlist(nlfd, nl);
755:
1.80 ragge 756: if (rv == -1)
757: _kvm_err(kd, 0, "bad namelist");
1.82 cube 758:
759: if (kd->nlfd < 0)
760: close(nlfd);
761:
1.80 ragge 762: return (rv);
1.18 mycroft 763: }
1.3 cgd 764:
1.88 joerg 765: int
766: kvm_dump_inval(kvm_t *kd)
1.40 leo 767: {
1.60 thorpej 768: struct nlist nl[2];
1.57 thorpej 769: u_long pa, val;
1.40 leo 770:
771: if (ISALIVE(kd)) {
772: _kvm_err(kd, kd->program, "clearing dump on live kernel");
773: return (-1);
774: }
1.60 thorpej 775: nl[0].n_name = "_dumpmag";
776: nl[1].n_name = NULL;
1.40 leo 777:
1.60 thorpej 778: if (kvm_nlist(kd, nl) == -1) {
1.40 leo 779: _kvm_err(kd, 0, "bad namelist");
780: return (-1);
781: }
1.60 thorpej 782: if (_kvm_kvatop(kd, (u_long)nl[0].n_value, &pa) == 0)
1.40 leo 783: return (-1);
784:
785: errno = 0;
1.57 thorpej 786: val = 0;
1.77 christos 787: if (pwrite(kd->pmfd, (void *)&val, sizeof(val),
1.62 christos 788: _kvm_pa2off(kd, pa)) == -1) {
1.57 thorpej 789: _kvm_syserr(kd, 0, "cannot invalidate dump - pwrite");
1.40 leo 790: return (-1);
791: }
792: return (0);
793: }
794:
1.35 cgd 795: ssize_t
1.88 joerg 796: kvm_read(kvm_t *kd, u_long kva, void *buf, size_t len)
1.3 cgd 797: {
1.55 perry 798: int cc;
799: void *cp;
1.3 cgd 800:
1.65 simonb 801: if (ISKMEM(kd)) {
1.35 cgd 802: /*
803: * We're using /dev/kmem. Just read straight from the
804: * device and let the active kernel do the address translation.
805: */
806: errno = 0;
1.57 thorpej 807: cc = pread(kd->vmfd, buf, len, (off_t)kva);
1.35 cgd 808: if (cc < 0) {
809: _kvm_syserr(kd, 0, "kvm_read");
1.56 msaitoh 810: return (-1);
1.35 cgd 811: } else if (cc < len)
812: _kvm_err(kd, kd->program, "short read");
813: return (cc);
1.65 simonb 814: } else if (ISSYSCTL(kd)) {
815: _kvm_err(kd, kd->program, "kvm_open called with KVM_NO_FILES, "
816: "can't use kvm_read");
817: return (-1);
1.35 cgd 818: } else {
1.43 gwr 819: if ((kd->kcore_hdr == NULL) || (kd->cpu_data == NULL)) {
1.40 leo 820: _kvm_err(kd, kd->program, "no valid dump header");
1.56 msaitoh 821: return (-1);
1.40 leo 822: }
1.35 cgd 823: cp = buf;
824: while (len > 0) {
1.40 leo 825: u_long pa;
826: off_t foff;
1.64 simonb 827:
1.35 cgd 828: cc = _kvm_kvatop(kd, kva, &pa);
829: if (cc == 0)
1.56 msaitoh 830: return (-1);
1.35 cgd 831: if (cc > len)
832: cc = len;
1.40 leo 833: foff = _kvm_pa2off(kd, pa);
1.35 cgd 834: errno = 0;
1.62 christos 835: cc = pread(kd->pmfd, cp, (size_t)cc, foff);
1.35 cgd 836: if (cc < 0) {
837: _kvm_syserr(kd, kd->program, "kvm_read");
838: break;
839: }
840: /*
841: * If kvm_kvatop returns a bogus value or our core
842: * file is truncated, we might wind up seeking beyond
843: * the end of the core file in which case the read will
844: * return 0 (EOF).
845: */
846: if (cc == 0)
847: break;
1.39 cgd 848: cp = (char *)cp + cc;
1.35 cgd 849: kva += cc;
850: len -= cc;
1.3 cgd 851: }
1.35 cgd 852: return ((char *)cp - (char *)buf);
1.3 cgd 853: }
1.35 cgd 854: /* NOTREACHED */
1.3 cgd 855: }
856:
1.35 cgd 857: ssize_t
1.88 joerg 858: kvm_write(kvm_t *kd, u_long kva, const void *buf, size_t len)
1.35 cgd 859: {
1.55 perry 860: int cc;
1.26 pk 861:
1.65 simonb 862: if (ISKMEM(kd)) {
1.35 cgd 863: /*
864: * Just like kvm_read, only we write.
865: */
866: errno = 0;
1.57 thorpej 867: cc = pwrite(kd->vmfd, buf, len, (off_t)kva);
1.35 cgd 868: if (cc < 0) {
869: _kvm_syserr(kd, 0, "kvm_write");
1.56 msaitoh 870: return (-1);
1.35 cgd 871: } else if (cc < len)
872: _kvm_err(kd, kd->program, "short write");
873: return (cc);
1.65 simonb 874: } else if (ISSYSCTL(kd)) {
875: _kvm_err(kd, kd->program, "kvm_open called with KVM_NO_FILES, "
876: "can't use kvm_write");
877: return (-1);
1.35 cgd 878: } else {
879: _kvm_err(kd, kd->program,
880: "kvm_write not implemented for dead kernels");
1.56 msaitoh 881: return (-1);
1.26 pk 882: }
1.35 cgd 883: /* NOTREACHED */
1.1 cgd 884: }
CVSweb <webmaster@jp.NetBSD.org>