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