kvm.c revision 1.19 1 /*-
2 * Copyright (c) 1993 Christopher G. Demetriou
3 * Copyright (c) 1989 The Regents of the University of California.
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * 3. All advertising materials mentioning features or use of this software
15 * must display the following acknowledgement:
16 * This product includes software developed by the University of
17 * California, Berkeley and its contributors.
18 * 4. Neither the name of the University nor the names of its contributors
19 * may be used to endorse or promote products derived from this software
20 * without specific prior written permission.
21 *
22 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32 * SUCH DAMAGE.
33 */
34
35 #if defined(LIBC_SCCS) && !defined(lint)
36 /*static char sccsid[] = "from: @(#)kvm.c 5.18 (Berkeley) 5/7/91";*/
37 static char rcsid[] = "$Id: kvm.c,v 1.19 1993/10/02 07:07:43 mycroft Exp $";
38 #endif /* LIBC_SCCS and not lint */
39
40 #include <sys/param.h>
41 #include <sys/user.h>
42 #include <sys/proc.h>
43 #include <sys/ioctl.h>
44 #include <sys/kinfo.h>
45 #include <sys/tty.h>
46 #include <sys/exec.h>
47 #include <machine/vmparam.h>
48 #include <fcntl.h>
49 #include <nlist.h>
50 #include <kvm.h>
51 #include <ndbm.h>
52 #include <limits.h>
53 #include <paths.h>
54 #include <stdio.h>
55 #include <string.h>
56
57 #define btop(x) (((unsigned)(x)) >> PGSHIFT) /* XXX */
58 #define ptob(x) ((caddr_t)((x) << PGSHIFT)) /* XXX */
59 #include <vm/vm.h> /* ??? kinfo_proc currently includes this*/
60 #include <vm/vm_page.h>
61 #include <vm/swap_pager.h>
62 #include <sys/kinfo_proc.h>
63 #if defined(hp300) || defined(amiga)
64 #include <machine/pte.h>
65 #define btos(x) (((unsigned)(x)) >> SEGSHIFT) /* XXX */
66 #endif
67
68 /*
69 * files
70 */
71 static const char *unixf, *memf, *kmemf, *swapf;
72 static int unixx, mem, kmem, swap;
73 static DBM *db;
74 /*
75 * flags
76 */
77 static int deadkernel;
78 static int kvminit = 0;
79 static int kvmfilesopen = 0;
80 /*
81 * state
82 */
83 static struct kinfo_proc *kvmprocbase, *kvmprocptr;
84 static int kvmnprocs;
85 /*
86 * u. buffer
87 */
88 static union {
89 struct user user;
90 char upages[UPAGES][NBPG];
91 } user;
92
93 struct swapblk {
94 long offset; /* offset in swap device */
95 long size; /* remaining size of block in swap device */
96 };
97
98 /*
99 * random other stuff
100 */
101 static int dmmin, dmmax;
102 static int pcbpf;
103 static int nswap;
104 static long vm_page_hash_mask;
105 static long vm_page_buckets;
106 static long page_shift;
107 static char *tmp;
108 #if defined(hp300) || defined(amiga)
109 static int lowram;
110 static struct ste *Sysseg;
111 #endif
112 #if defined(i386)
113 static struct pde *PTD;
114 #endif
115
116 #define atop(x) (((unsigned)(x)) >> page_shift)
117 #define vm_page_hash(object, offset) \
118 (((unsigned)object+(unsigned)atop(offset))&vm_page_hash_mask)
119
120 #define basename(cp) ((tmp=rindex((cp), '/')) ? tmp+1 : (cp))
121 #define MAXSYMSIZE 256
122
123 static struct nlist nl[] = {
124 { "_Usrptmap" },
125 #define X_USRPTMAP 0
126 { "_usrpt" },
127 #define X_USRPT 1
128 { "_nswap" },
129 #define X_NSWAP 2
130 { "_dmmin" },
131 #define X_DMMIN 3
132 { "_dmmax" },
133 #define X_DMMAX 4
134 { "_vm_page_buckets" },
135 #define X_VM_PAGE_BUCKETS 5
136 { "_vm_page_hash_mask" },
137 #define X_VM_PAGE_HASH_MASK 6
138 { "_page_shift" },
139 #define X_PAGE_SHIFT 7
140 /*
141 * everything here and down, only if a dead kernel
142 */
143 { "_Sysmap" },
144 #define X_SYSMAP 8
145 #define X_DEADKERNEL X_SYSMAP
146 { "_Syssize" },
147 #define X_SYSSIZE 9
148 { "_allproc" },
149 #define X_ALLPROC 10
150 { "_zombproc" },
151 #define X_ZOMBPROC 11
152 { "_nproc" },
153 #define X_NPROC 12
154 #define X_LAST 12
155 #if defined(hp300) || defined(amiga)
156 { "_Sysseg" },
157 #define X_SYSSEG (X_LAST+1)
158 { "_lowram" },
159 #define X_LOWRAM (X_LAST+2)
160 #endif
161 #if defined(i386)
162 { "_IdlePTD" },
163 #define X_IdlePTD (X_LAST+1)
164 #endif
165 { "" },
166 };
167
168 static off_t Vtophys();
169 static void klseek(), seterr(), setsyserr(), vstodb();
170 static int getkvars(), kvm_doprocs(), kvm_init();
171 static int vatosw();
172 static int pager_get();
173 static int findpage();
174
175 /*
176 * returns 0 if files were opened now,
177 * 1 if files were already opened,
178 * -1 if files could not be opened.
179 */
180 kvm_openfiles(uf, mf, sf)
181 const char *uf, *mf, *sf;
182 {
183 if (kvmfilesopen)
184 return (1);
185 unixx = mem = kmem = swap = -1;
186 unixf = (uf == NULL) ? _PATH_UNIX : uf;
187 memf = (mf == NULL) ? _PATH_MEM : mf;
188
189 if ((unixx = open(unixf, O_RDONLY, 0)) == -1) {
190 setsyserr("can't open %s", unixf);
191 goto failed;
192 }
193 if ((mem = open(memf, O_RDONLY, 0)) == -1) {
194 setsyserr("can't open %s", memf);
195 goto failed;
196 }
197 if (sf != NULL)
198 swapf = sf;
199 if (mf != NULL) {
200 deadkernel++;
201 kmemf = mf;
202 kmem = mem;
203 swap = -1;
204 } else {
205 kmemf = _PATH_KMEM;
206 if ((kmem = open(kmemf, O_RDONLY, 0)) == -1) {
207 setsyserr("can't open %s", kmemf);
208 goto failed;
209 }
210 swapf = (sf == NULL) ? _PATH_DRUM : sf;
211 /*
212 * live kernel - avoid looking up nlist entries
213 * past X_DEADKERNEL.
214 */
215 nl[X_DEADKERNEL].n_name = "";
216 }
217 if (swapf != NULL && ((swap = open(swapf, O_RDONLY, 0)) == -1)) {
218 seterr("can't open %s", swapf);
219 goto failed;
220 }
221 kvmfilesopen++;
222 if (kvminit == 0 && kvm_init(NULL, NULL, NULL, 0) == -1) /*XXX*/
223 return (-1);
224 return (0);
225 failed:
226 kvm_close();
227 return (-1);
228 }
229
230 static
231 kvm_init(uf, mf, sf)
232 char *uf, *mf, *sf;
233 {
234 if (kvmfilesopen == 0 && kvm_openfiles(NULL, NULL, NULL) == -1)
235 return (-1);
236 if (getkvars() == -1)
237 return (-1);
238 kvminit = 1;
239
240 return (0);
241 }
242
243 kvm_close()
244 {
245 if (unixx != -1) {
246 close(unixx);
247 unixx = -1;
248 }
249 if (kmem != -1) {
250 if (kmem != mem)
251 close(kmem);
252 /* otherwise kmem is a copy of mem, and will be closed below */
253 kmem = -1;
254 }
255 if (mem != -1) {
256 close(mem);
257 mem = -1;
258 }
259 if (swap != -1) {
260 close(swap);
261 swap = -1;
262 }
263 if (db != NULL) {
264 dbm_close(db);
265 db = NULL;
266 }
267 kvminit = 0;
268 kvmfilesopen = 0;
269 deadkernel = 0;
270 }
271
272 kvm_nlist(nl)
273 struct nlist *nl;
274 {
275 datum key, data;
276 char dbname[MAXPATHLEN];
277 char dbversion[_POSIX2_LINE_MAX];
278 char kversion[_POSIX2_LINE_MAX];
279 int dbversionlen;
280 char symbuf[MAXSYMSIZE];
281 struct nlist nbuf, *n;
282 int num, did;
283
284 if (kvmfilesopen == 0 && kvm_openfiles(NULL, NULL, NULL) == -1)
285 return (-1);
286 if (deadkernel)
287 goto hard2;
288 /*
289 * initialize key datum
290 */
291 key.dptr = symbuf;
292
293 if (db != NULL)
294 goto win; /* off to the races */
295 /*
296 * open database
297 */
298 sprintf(dbname, "%s/kvm_%s", _PATH_VARRUN, basename(unixf));
299 if ((db = dbm_open(dbname, O_RDONLY, 0)) == NULL)
300 goto hard2;
301 /*
302 * read version out of database
303 */
304 bcopy("VERSION", symbuf, sizeof ("VERSION")-1);
305 key.dsize = (sizeof ("VERSION") - 1);
306 data = dbm_fetch(db, key);
307 if (data.dptr == NULL)
308 goto hard1;
309 bcopy(data.dptr, dbversion, data.dsize);
310 dbversionlen = data.dsize;
311 /*
312 * read version string from kernel memory
313 */
314 bcopy("_version", symbuf, sizeof ("_version")-1);
315 key.dsize = (sizeof ("_version")-1);
316 data = dbm_fetch(db, key);
317 if (data.dptr == NULL)
318 goto hard1;
319 if (data.dsize != sizeof (struct nlist))
320 goto hard1;
321 bcopy(data.dptr, &nbuf, sizeof (struct nlist));
322 lseek(kmem, nbuf.n_value, 0);
323 if (read(kmem, kversion, dbversionlen) != dbversionlen)
324 goto hard1;
325 /*
326 * if they match, we win - otherwise do it the hard way
327 */
328 if (bcmp(dbversion, kversion, dbversionlen) != 0)
329 goto hard1;
330 /*
331 * getem from the database.
332 */
333 win:
334 num = did = 0;
335 for (n = nl; n->n_name && n->n_name[0]; n++, num++) {
336 int len;
337 /*
338 * clear out fields from users buffer
339 */
340 n->n_type = 0;
341 n->n_other = 0;
342 n->n_desc = 0;
343 n->n_value = 0;
344 /*
345 * query db
346 */
347 if ((len = strlen(n->n_name)) > MAXSYMSIZE) {
348 seterr("symbol too large");
349 return (-1);
350 }
351 (void)strcpy(symbuf, n->n_name);
352 key.dsize = len;
353 data = dbm_fetch(db, key);
354 if (data.dptr == NULL || data.dsize != sizeof (struct nlist))
355 continue;
356 bcopy(data.dptr, &nbuf, sizeof (struct nlist));
357 n->n_value = nbuf.n_value;
358 n->n_type = nbuf.n_type;
359 n->n_desc = nbuf.n_desc;
360 n->n_other = nbuf.n_other;
361 did++;
362 }
363 return (num - did);
364 hard1:
365 dbm_close(db);
366 db = NULL;
367 hard2:
368 num = nlist(unixf, nl);
369 if (num == -1)
370 seterr("nlist (hard way) failed");
371 return (num);
372 }
373
374 kvm_getprocs(what, arg)
375 int what, arg;
376 {
377 static int ocopysize = -1;
378
379 if (kvminit == 0 && kvm_init(NULL, NULL, NULL, 0) == -1)
380 return (NULL);
381 if (!deadkernel) {
382 int ret, copysize;
383
384 if ((ret = getkerninfo(what, NULL, NULL, arg)) == -1) {
385 setsyserr("can't get estimate for kerninfo");
386 return (-1);
387 }
388 copysize = ret;
389 if (copysize > ocopysize || !kvmprocbase) {
390 if (ocopysize == -1 || !kvmprocbase)
391 kvmprocbase =
392 (struct kinfo_proc *)malloc(copysize);
393 else
394 kvmprocbase =
395 (struct kinfo_proc *)realloc(kvmprocbase,
396 copysize);
397 if (!kvmprocbase) {
398 seterr("out of memory");
399 return (-1);
400 }
401 }
402 ocopysize = copysize;
403 if ((ret = getkerninfo(what, kvmprocbase, ©size,
404 arg)) == -1) {
405 setsyserr("can't get proc list");
406 return (-1);
407 }
408 if (copysize % sizeof (struct kinfo_proc)) {
409 seterr("proc size mismatch (got %d total, kinfo_proc: %d)",
410 copysize, sizeof (struct kinfo_proc));
411 return (-1);
412 }
413 kvmnprocs = copysize / sizeof (struct kinfo_proc);
414 } else {
415 int nproc;
416
417 if (kvm_read((void *) nl[X_NPROC].n_value, &nproc,
418 sizeof (int)) == -1) {
419 seterr("can't read nproc");
420 return (-1);
421 }
422 if ((kvmprocbase = (struct kinfo_proc *)
423 malloc(nproc * sizeof (struct kinfo_proc))) == NULL) {
424 seterr("out of memory (addr: %x nproc = %d)",
425 nl[X_NPROC].n_value, nproc);
426 return (-1);
427 }
428 kvmnprocs = kvm_doprocs(what, arg, kvmprocbase);
429 realloc(kvmprocbase, kvmnprocs * sizeof (struct kinfo_proc));
430 }
431 kvmprocptr = kvmprocbase;
432
433 return (kvmnprocs);
434 }
435
436 /*
437 * XXX - should NOT give up so easily - especially since the kernel
438 * may be corrupt (it died). Should gather as much information as possible.
439 * Follows proc ptrs instead of reading table since table may go
440 * away soon.
441 */
442 static
443 kvm_doprocs(what, arg, buff)
444 int what, arg;
445 char *buff;
446 {
447 struct proc *p, proc;
448 register char *bp = buff;
449 int i = 0;
450 int doingzomb = 0;
451 struct eproc eproc;
452 struct pgrp pgrp;
453 struct session sess;
454 struct tty tty;
455
456 /* allproc */
457 if (kvm_read((void *) nl[X_ALLPROC].n_value, &p,
458 sizeof (struct proc *)) == -1) {
459 seterr("can't read allproc");
460 return (-1);
461 }
462
463 again:
464 for (; p; p = proc.p_nxt) {
465 if (kvm_read(p, &proc, sizeof (struct proc)) == -1) {
466 seterr("can't read proc at %x", p);
467 return (-1);
468 }
469 if (kvm_read(proc.p_cred, &eproc.e_pcred,
470 sizeof (struct pcred)) != -1)
471 (void) kvm_read(eproc.e_pcred.pc_ucred, &eproc.e_ucred,
472 sizeof (struct ucred));
473
474 switch(ki_op(what)) {
475
476 case KINFO_PROC_PID:
477 if (proc.p_pid != (pid_t)arg)
478 continue;
479 break;
480
481
482 case KINFO_PROC_UID:
483 if (eproc.e_ucred.cr_uid != (uid_t)arg)
484 continue;
485 break;
486
487 case KINFO_PROC_RUID:
488 if (eproc.e_pcred.p_ruid != (uid_t)arg)
489 continue;
490 break;
491 }
492 /*
493 * gather eproc
494 */
495 eproc.e_paddr = p;
496 if (kvm_read(proc.p_pgrp, &pgrp, sizeof (struct pgrp)) == -1) {
497 seterr("can't read pgrp at %x", proc.p_pgrp);
498 return (-1);
499 }
500 eproc.e_sess = pgrp.pg_session;
501 eproc.e_pgid = pgrp.pg_id;
502 eproc.e_jobc = pgrp.pg_jobc;
503 if (kvm_read(pgrp.pg_session, &sess, sizeof (struct session))
504 == -1) {
505 seterr("can't read session at %x", pgrp.pg_session);
506 return (-1);
507 }
508 if ((proc.p_flag&SCTTY) && sess.s_ttyp != NULL) {
509 if (kvm_read(sess.s_ttyp, &tty, sizeof (struct tty))
510 == -1) {
511 seterr("can't read tty at %x", sess.s_ttyp);
512 return (-1);
513 }
514 eproc.e_tdev = tty.t_dev;
515 eproc.e_tsess = tty.t_session;
516 if (tty.t_pgrp != NULL) {
517 if (kvm_read(tty.t_pgrp, &pgrp, sizeof (struct
518 pgrp)) == -1) {
519 seterr("can't read tpgrp at &x",
520 tty.t_pgrp);
521 return (-1);
522 }
523 eproc.e_tpgid = pgrp.pg_id;
524 } else
525 eproc.e_tpgid = -1;
526 } else
527 eproc.e_tdev = NODEV;
528 if (proc.p_wmesg)
529 (void) kvm_read(proc.p_wmesg, eproc.e_wmesg, WMESGLEN);
530 (void) kvm_read(proc.p_vmspace, &eproc.e_vm,
531 sizeof (struct vmspace));
532 eproc.e_xsize = eproc.e_xrssize =
533 eproc.e_xccount = eproc.e_xswrss = 0;
534
535 switch(ki_op(what)) {
536
537 case KINFO_PROC_PGRP:
538 if (eproc.e_pgid != (pid_t)arg)
539 continue;
540 break;
541
542 case KINFO_PROC_TTY:
543 if ((proc.p_flag&SCTTY) == 0 ||
544 eproc.e_tdev != (dev_t)arg)
545 continue;
546 break;
547 }
548
549 i++;
550 bcopy(&proc, bp, sizeof (struct proc));
551 bp += sizeof (struct proc);
552 bcopy(&eproc, bp, sizeof (struct eproc));
553 bp+= sizeof (struct eproc);
554 }
555 if (!doingzomb) {
556 /* zombproc */
557 if (kvm_read((void *) nl[X_ZOMBPROC].n_value, &p,
558 sizeof (struct proc *)) == -1) {
559 seterr("can't read zombproc");
560 return (-1);
561 }
562 doingzomb = 1;
563 goto again;
564 }
565
566 return (i);
567 }
568
569 struct proc *
570 kvm_nextproc()
571 {
572
573 if (!kvmprocbase && kvm_getprocs(0, 0) == -1)
574 return (NULL);
575 if (kvmprocptr >= (kvmprocbase + kvmnprocs)) {
576 seterr("end of proc list");
577 return (NULL);
578 }
579 return((struct proc *)(kvmprocptr++));
580 }
581
582 struct eproc *
583 kvm_geteproc(p)
584 const struct proc *p;
585 {
586 return ((struct eproc *)(((char *)p) + sizeof (struct proc)));
587 }
588
589 kvm_setproc()
590 {
591 kvmprocptr = kvmprocbase;
592 }
593
594 kvm_freeprocs()
595 {
596
597 if (kvmprocbase) {
598 free(kvmprocbase);
599 kvmprocbase = NULL;
600 }
601 }
602
603 struct user *
604 kvm_getu(p)
605 const struct proc *p;
606 {
607 register struct kinfo_proc *kp = (struct kinfo_proc *)p;
608 register int i;
609 register char *up;
610 u_int vaddr;
611 struct swapblk swb;
612
613 if (kvminit == 0 && kvm_init(NULL, NULL, NULL, 0) == -1)
614 return (NULL);
615 if (p->p_stat == SZOMB) {
616 seterr("zombie process");
617 return (NULL);
618 }
619
620 if ((p->p_flag & SLOAD) == 0) {
621 vm_offset_t maddr;
622
623 if (swap < 0) {
624 seterr("no swap");
625 return (NULL);
626 }
627 /*
628 * Costly operation, better set enable_swap to zero
629 * in vm/vm_glue.c, since paging of user pages isn't
630 * done yet anyway.
631 */
632 if (vatosw(&kp->kp_eproc.e_vm.vm_map, USRSTACK + i * NBPG,
633 &maddr, &swb) == 0)
634 return NULL;
635
636 if (maddr == 0 && swb.size < UPAGES * NBPG)
637 return NULL;
638
639 for (i = 0; i < UPAGES; i++) {
640 if (maddr) {
641 (void) lseek(mem, maddr + i * NBPG, 0);
642 if (read(mem,
643 (char *)user.upages[i], NBPG) != NBPG) {
644 seterr(
645 "can't read u for pid %d from %s",
646 p->p_pid, swapf);
647 return NULL;
648 }
649 } else {
650 (void) lseek(swap, swb.offset + i * NBPG, 0);
651 if (read(swap,
652 (char *)user.upages[i], NBPG) != NBPG) {
653 seterr(
654 "can't read u for pid %d from %s",
655 p->p_pid, swapf);
656 return NULL;
657 }
658 }
659 }
660 return(&user.user);
661 }
662 /*
663 * Read u-area one page at a time for the benefit of post-mortems
664 */
665 up = (char *) p->p_addr;
666 for (i = 0; i < UPAGES; i++) {
667 klseek(kmem, (long)up, 0);
668 if (read(kmem, user.upages[i], CLBYTES) != CLBYTES) {
669 seterr("cant read page %x of u of pid %d from %s",
670 up, p->p_pid, kmemf);
671 return(NULL);
672 }
673 up += CLBYTES;
674 }
675 pcbpf = (int) btop(p->p_addr); /* what should this be really? */
676
677 kp->kp_eproc.e_vm.vm_rssize =
678 kp->kp_eproc.e_vm.vm_pmap.pm_stats.resident_count; /* XXX */
679 return(&user.user);
680 }
681
682 int
683 kvm_procread(p, addr, buf, len)
684 const struct proc *p;
685 const unsigned addr;
686 unsigned len;
687 char *buf;
688 {
689 register struct kinfo_proc *kp = (struct kinfo_proc *) p;
690 struct swapblk swb;
691 vm_offset_t swaddr = 0, memaddr = 0;
692 unsigned real_len;
693
694 real_len = len < (CLBYTES - (addr & CLOFSET)) ? len : (CLBYTES - (addr & CLOFSET));
695
696 if (vatosw(&kp->kp_eproc.e_vm.vm_map, addr & ~CLOFSET, &memaddr,
697 &swb) == 0)
698 return 0;
699
700 if (memaddr) {
701 memaddr += addr & CLOFSET;
702 if (lseek(mem, memaddr, 0) == -1)
703 seterr("kvm_procread: lseek mem");
704 len = read(mem, buf, real_len);
705 if (len == -1) {
706 seterr("kvm_procread: read mem");
707 return 0;
708 }
709 } else {
710 char bouncebuf[CLBYTES];
711 swaddr = swb.offset + (addr & CLOFSET);
712 swb.size -= addr & CLOFSET;
713 if (lseek(swap, swaddr & ~CLOFSET, 0) == -1) {
714 seterr("kvm_procread: lseek swap");
715 return 0;
716 }
717 len = read(swap, bouncebuf, CLBYTES);
718 if (len == -1 || len <= (swaddr & CLOFSET)) {
719 seterr("kvm_procread: read swap");
720 return 0;
721 }
722 len = MIN(len - (swaddr & CLOFSET), real_len);
723 memcpy(buf, &bouncebuf[swaddr & CLOFSET], len);
724 }
725
726 return len;
727 }
728
729 int
730 kvm_procreadstr(p, addr, buf, len)
731 const struct proc *p;
732 const unsigned addr;
733 char *buf;
734 unsigned len;
735 {
736 int done, little;
737 char copy[200], *pb;
738 char a;
739
740 done = 0;
741 copy[0] = '\0';
742 while (len) {
743 little = kvm_procread(p, addr+done, copy, MIN(len, sizeof copy));
744 if (little<1)
745 break;
746 pb = copy;
747 while (little--) {
748 len--;
749 if( (*buf++ = *pb++) == '\0' )
750 return done;
751 done++;
752 }
753 }
754 return done;
755 }
756
757 char *
758 kvm_getargs(p, up)
759 const struct proc *p;
760 const struct user *up;
761 {
762 static char cmdbuf[ARG_MAX + sizeof(p->p_comm) + 5];
763 register char *cp, *acp;
764 int left, rv;
765 struct ps_strings arginfo;
766
767 if (up == NULL || p->p_pid == 0 || p->p_pid == 2)
768 goto retucomm;
769
770 if (kvm_procread(p, PS_STRINGS, (char *)&arginfo, sizeof(arginfo)) !=
771 sizeof(arginfo))
772 goto bad;
773
774 cmdbuf[0] = '\0';
775 cp = cmdbuf;
776 acp = arginfo.ps_argvstr;
777 left = ARG_MAX + 1;
778 while (arginfo.ps_nargvstr--) {
779 if ((rv = kvm_procreadstr(p, acp, cp, left)) >= 0) {
780 acp += rv + 1;
781 left -= rv + 1;
782 cp += rv;
783 *cp++ = ' ';
784 *cp = '\0';
785 } else
786 goto bad;
787 }
788 cp-- ; *cp = '\0';
789
790 if (cmdbuf[0] == '-' || cmdbuf[0] == '?' || cmdbuf[0] <= ' ') {
791 (void) strcat(cmdbuf, " (");
792 (void) strncat(cmdbuf, p->p_comm, sizeof(p->p_comm));
793 (void) strcat(cmdbuf, ")");
794 }
795 return (cmdbuf);
796
797 bad:
798 seterr("error locating command name for pid %d", p->p_pid);
799 retucomm:
800 (void) strcpy(cmdbuf, "(");
801 (void) strncat(cmdbuf, p->p_comm, sizeof (p->p_comm));
802 (void) strcat(cmdbuf, ")");
803 return (cmdbuf);
804 }
805
806 char *
807 kvm_getenv(p, up)
808 const struct proc *p;
809 const struct user *up;
810 {
811 static char envbuf[ARG_MAX + 1];
812 register char *cp, *acp;
813 int left, rv;
814 struct ps_strings arginfo;
815
816 if (up == NULL || p->p_pid == 0 || p->p_pid == 2)
817 goto retemptyenv;
818
819 if (kvm_procread(p, PS_STRINGS, (char *)&arginfo, sizeof(arginfo)) !=
820 sizeof(arginfo))
821 goto bad;
822
823 cp = envbuf;
824 acp = arginfo.ps_envstr;
825 left = ARG_MAX + 1;
826 while (arginfo.ps_nenvstr--) {
827 if ((rv = kvm_procreadstr(p, acp, cp, left)) >= 0) {
828 acp += rv + 1;
829 left -= rv + 1;
830 cp += rv;
831 *cp++ = ' ';
832 *cp = '\0';
833 } else
834 goto bad;
835 }
836 cp-- ; *cp = '\0';
837 return (envbuf);
838
839 bad:
840 seterr("error locating environment for pid %d", p->p_pid);
841 retemptyenv:
842 envbuf[0] = '\0';
843 return (envbuf);
844 }
845
846 static
847 getkvars()
848 {
849 if (kvm_nlist(nl) == -1)
850 return (-1);
851 if (deadkernel) {
852 /* We must do the sys map first because klseek uses it */
853 long addr;
854
855 #if defined(hp300) || defined(amiga)
856 addr = (long) nl[X_LOWRAM].n_value;
857 (void) lseek(kmem, addr, 0);
858 if (read(kmem, (char *) &lowram, sizeof (lowram))
859 != sizeof (lowram)) {
860 seterr("can't read lowram");
861 return (-1);
862 }
863 lowram = btop(lowram);
864 Sysseg = (struct ste *) malloc(NBPG);
865 if (Sysseg == NULL) {
866 seterr("out of space for Sysseg");
867 return (-1);
868 }
869 addr = (long) nl[X_SYSSEG].n_value;
870 (void) lseek(kmem, addr, 0);
871 read(kmem, (char *)&addr, sizeof(addr));
872 (void) lseek(kmem, (long)addr, 0);
873 if (read(kmem, (char *) Sysseg, NBPG) != NBPG) {
874 seterr("can't read Sysseg");
875 return (-1);
876 }
877 #endif
878 #if defined(i386)
879 PTD = (struct pde *) malloc(NBPG);
880 if (PTD == NULL) {
881 seterr("out of space for PTD");
882 return (-1);
883 }
884 addr = (long) nl[X_IdlePTD].n_value;
885 (void) lseek(kmem, addr, 0);
886 read(kmem, (char *)&addr, sizeof(addr));
887 (void) lseek(kmem, (long)addr, 0);
888 if (read(kmem, (char *) PTD, NBPG) != NBPG) {
889 seterr("can't read PTD");
890 return (-1);
891 }
892 #endif
893 }
894 if (kvm_read((void *) nl[X_NSWAP].n_value, &nswap, sizeof (long)) == -1) {
895 seterr("can't read nswap");
896 return (-1);
897 }
898 if (kvm_read((void *) nl[X_DMMIN].n_value, &dmmin, sizeof (long)) == -1) {
899 seterr("can't read dmmin");
900 return (-1);
901 }
902 if (kvm_read((void *) nl[X_DMMAX].n_value, &dmmax, sizeof (long)) == -1) {
903 seterr("can't read dmmax");
904 return (-1);
905 }
906 if (kvm_read((void *) nl[X_VM_PAGE_HASH_MASK].n_value,
907 &vm_page_hash_mask, sizeof (long)) == -1) {
908 seterr("can't read vm_page_hash_mask");
909 return (-1);
910 }
911 if (kvm_read((void *) nl[X_VM_PAGE_BUCKETS].n_value,
912 &vm_page_buckets, sizeof (long)) == -1) {
913 seterr("can't read vm_page_buckets");
914 return (-1);
915 }
916 if (kvm_read((void *) nl[X_PAGE_SHIFT].n_value,
917 &page_shift, sizeof (long)) == -1) {
918 seterr("can't read page_shift");
919 return (-1);
920 }
921
922 return (0);
923 }
924
925 kvm_read(loc, buf, len)
926 void *loc;
927 void *buf;
928 {
929 if (kvmfilesopen == 0 && kvm_openfiles(NULL, NULL, NULL) == -1)
930 return (-1);
931 klseek(kmem, (off_t) loc, 0);
932 if (read(kmem, buf, len) != len) {
933 seterr("error reading kmem at %x", loc);
934 return (-1);
935 }
936 return (len);
937 }
938
939 static void
940 klseek(fd, loc, off)
941 int fd;
942 off_t loc;
943 int off;
944 {
945
946 if (deadkernel) {
947 if ((loc = Vtophys(loc)) == -1)
948 return;
949 }
950 (void) lseek(fd, (off_t)loc, off);
951 }
952
953 static off_t
954 Vtophys(loc)
955 u_long loc;
956 {
957 off_t newloc = (off_t) -1;
958 #if defined(hp300) || defined(amiga)
959 int p, ste, pte;
960
961 ste = *(int *)&Sysseg[btos(loc)];
962 if ((ste & SG_V) == 0) {
963 seterr("vtophys: segment not valid");
964 return((off_t) -1);
965 }
966 p = btop(loc & SG_PMASK);
967 newloc = (ste & SG_FRAME) + (p * sizeof(struct pte));
968 (void) lseek(mem, newloc, 0);
969 if (read(mem, (char *)&pte, sizeof pte) != sizeof pte) {
970 seterr("vtophys: cannot locate pte");
971 return((off_t) -1);
972 }
973 newloc = pte & PG_FRAME;
974 if (pte == PG_NV || newloc < (off_t)ptob(lowram)) {
975 seterr("vtophys: page not valid");
976 return((off_t) -1);
977 }
978 newloc = (newloc - (off_t)ptob(lowram)) + (loc & PGOFSET);
979 #endif
980 #ifdef i386
981 struct pde pde;
982 struct pte pte;
983 int p;
984
985 pde = PTD[loc >> PD_SHIFT];
986 if (pde.pd_v == 0) {
987 seterr("vtophys: page directory entry not valid");
988 return((off_t) -1);
989 }
990 p = btop(loc & PT_MASK);
991 newloc = pde.pd_pfnum + (p * sizeof(struct pte));
992 (void) lseek(kmem, (long)newloc, 0);
993 if (read(kmem, (char *)&pte, sizeof pte) != sizeof pte) {
994 seterr("vtophys: cannot obtain desired pte");
995 return((off_t) -1);
996 }
997 newloc = pte.pg_pfnum;
998 if (pte.pg_v == 0) {
999 seterr("vtophys: page table entry not valid");
1000 return((off_t) -1);
1001 }
1002 newloc += (loc & PGOFSET);
1003 #endif
1004 return((off_t) newloc);
1005 }
1006
1007 /*
1008 * locate address of unwired or swapped page
1009 */
1010
1011 static int
1012 vatosw(mp, vaddr, maddr, swb)
1013 vm_map_t mp;
1014 vm_offset_t vaddr;
1015 vm_offset_t *maddr;
1016 struct swapblk *swb;
1017 {
1018 struct vm_object vm_object;
1019 struct vm_map_entry vm_entry;
1020 long saddr, addr, off;
1021 int i;
1022
1023 saddr = addr = (long)mp->header.next;
1024 #ifdef DEBUG
1025 fprintf(stderr, "vatosw: head=%x\n", &mp->header);
1026 #endif
1027 for (i = 0; ; i++) {
1028 /* Weed through map entries until vaddr in range */
1029 if (kvm_read((void *) addr, &vm_entry, sizeof(vm_entry)) == -1) {
1030 setsyserr("vatosw: read vm_map_entry");
1031 return 0;
1032 }
1033 #ifdef DEBUG
1034 fprintf(stderr, "vatosw: %d/%d, vaddr=%x, start=%x, end=%x ",
1035 i, mp->nentries, vaddr, vm_entry.start, vm_entry.end);
1036 fprintf(stderr, "addr=%x, next=%x\n", addr, vm_entry.next);
1037 #endif
1038 if ((vaddr >= vm_entry.start) && (vaddr < vm_entry.end))
1039 if (vm_entry.object.vm_object != 0)
1040 break;
1041 else {
1042 #ifdef DEBUG
1043 fprintf(stderr, "vatosw: no object\n");
1044 #endif
1045 seterr("vatosw: no object\n");
1046 return 0;
1047 }
1048
1049 addr = (long)vm_entry.next;
1050
1051 if (addr == saddr) {
1052 seterr("vatosw: map not found\n");
1053 return 0;
1054 }
1055 }
1056
1057 if (vm_entry.is_a_map || vm_entry.is_sub_map) {
1058 #ifdef DEBUG
1059 fprintf(stderr, "vatosw: is a %smap\n",
1060 vm_entry.is_sub_map ? "sub " : "");
1061 #endif
1062 seterr("vatosw: is a %smap\n",
1063 vm_entry.is_sub_map ? "sub " : "");
1064 return 0;
1065 }
1066
1067 /* Locate memory object */
1068 off = (vaddr - vm_entry.start) + vm_entry.offset;
1069 addr = (long)vm_entry.object.vm_object;
1070 while (1) {
1071 if (kvm_read((void *) addr, &vm_object, sizeof (vm_object)) == -1) {
1072 setsyserr("vatosw: read vm_object");
1073 return 0;
1074 }
1075
1076 #ifdef DEBUG
1077 fprintf(stderr, "vatosw: find page: object %#x offset %x\n",
1078 addr, off);
1079 #endif
1080
1081 /* Lookup in page queue */
1082 if ((i = findpage(addr, off, maddr)) != -1)
1083 return i;
1084
1085 if (vm_object.pager != 0 &&
1086 (i = pager_get(&vm_object, off, swb)) != -1)
1087 return i;
1088
1089 if (vm_object.shadow == 0)
1090 break;
1091
1092 #ifdef DEBUG
1093 fprintf(stderr, "vatosw: shadow obj at %x: offset %x+%x\n",
1094 addr, off, vm_object.shadow_offset);
1095 #endif
1096
1097 addr = (long)vm_object.shadow;
1098 off += vm_object.shadow_offset;
1099 }
1100
1101 seterr("vatosw: page not found\n");
1102 return 0;
1103 }
1104
1105
1106 int
1107 pager_get(object, off, swb)
1108 struct vm_object *object;
1109 long off;
1110 struct swapblk *swb;
1111 {
1112 struct pager_struct pager;
1113 struct swpager swpager;
1114 struct swblock swblock;
1115
1116 /* Find address in swap space */
1117 if (kvm_read(object->pager, &pager, sizeof (pager)) == -1) {
1118 setsyserr("pager_get: read pager");
1119 return 0;
1120 }
1121 if (pager.pg_type != PG_SWAP) {
1122 seterr("pager_get: weird pager\n");
1123 return 0;
1124 }
1125
1126 /* Get swap pager data */
1127 if (kvm_read(pager.pg_data, &swpager, sizeof (swpager)) == -1) {
1128 setsyserr("pager_get: read swpager");
1129 return 0;
1130 }
1131
1132 off += object->paging_offset;
1133
1134 /* Read swap block array */
1135 if (kvm_read((void *) swpager.sw_blocks +
1136 (off/dbtob(swpager.sw_bsize)) * sizeof swblock,
1137 &swblock, sizeof (swblock)) == -1) {
1138 setsyserr("pager_get: read swblock");
1139 return 0;
1140 }
1141
1142 off %= dbtob(swpager.sw_bsize);
1143
1144 if (swblock.swb_mask & (1 << atop(off))) {
1145 swb->offset = dbtob(swblock.swb_block) + off;
1146 swb->size = dbtob(swpager.sw_bsize) - off;
1147 return 1;
1148 }
1149
1150 return -1;
1151 }
1152
1153 static int
1154 findpage(object, offset, maddr)
1155 long object;
1156 long offset;
1157 vm_offset_t *maddr;
1158 {
1159 queue_head_t bucket;
1160 struct vm_page mem;
1161 long addr, baddr;
1162
1163 baddr = vm_page_buckets +
1164 vm_page_hash(object,offset) * sizeof(queue_head_t);
1165
1166 if (kvm_read((void *) baddr, &bucket, sizeof (bucket)) == -1) {
1167 seterr("can't read vm_page_bucket");
1168 return 0;
1169 }
1170
1171 addr = (long)bucket.next;
1172
1173 while (addr != baddr) {
1174 if (kvm_read((void *) addr, &mem, sizeof (mem)) == -1) {
1175 seterr("can't read vm_page");
1176 return 0;
1177 }
1178
1179 if ((long)mem.object == object && mem.offset == offset) {
1180 *maddr = (long)mem.phys_addr;
1181 return 1;
1182 }
1183
1184 addr = (long)mem.hashq.next;
1185 }
1186
1187 return -1;
1188 }
1189
1190 #include <varargs.h>
1191 static char errbuf[_POSIX2_LINE_MAX];
1192
1193 static void
1194 seterr(va_alist)
1195 va_dcl
1196 {
1197 char *fmt;
1198 va_list ap;
1199
1200 va_start(ap);
1201 fmt = va_arg(ap, char *);
1202 (void) vsnprintf(errbuf, _POSIX2_LINE_MAX, fmt, ap);
1203 #ifdef DEBUG
1204 (void) printf("%s", errbuf);
1205 #endif
1206 va_end(ap);
1207 }
1208
1209 static void
1210 setsyserr(va_alist)
1211 va_dcl
1212 {
1213 char *fmt, *cp;
1214 va_list ap;
1215 extern int errno;
1216
1217 va_start(ap);
1218 fmt = va_arg(ap, char *);
1219 (void) vsnprintf(errbuf, _POSIX2_LINE_MAX, fmt, ap);
1220 cp += strlen(cp);
1221 (void) snprintf(cp, _POSIX2_LINE_MAX - (cp - errbuf), ": %s",
1222 strerror(errno));
1223 #ifdef DEBUG
1224 (void) printf("%s", errbuf);
1225 #endif
1226 va_end(ap);
1227 }
1228
1229 char *
1230 kvm_geterr()
1231 {
1232 return (errbuf);
1233 }
1234