kvm.c revision 1.23 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.23 1994/01/07 19:10:06 cgd 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(m68k)
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(m68k)
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(m68k)
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 return(&user.user);
678 }
679
680 int
681 kvm_procread(p, addr, buf, len)
682 const struct proc *p;
683 const unsigned addr;
684 unsigned len;
685 char *buf;
686 {
687 register struct kinfo_proc *kp = (struct kinfo_proc *) p;
688 struct swapblk swb;
689 vm_offset_t swaddr = 0, memaddr = 0;
690 unsigned real_len;
691
692 real_len = len < (CLBYTES - (addr & CLOFSET)) ? len : (CLBYTES - (addr & CLOFSET));
693
694 if (vatosw(&kp->kp_eproc.e_vm.vm_map, addr & ~CLOFSET, &memaddr,
695 &swb) == 0)
696 return 0;
697
698 if (memaddr) {
699 memaddr += addr & CLOFSET;
700 if (lseek(mem, memaddr, 0) == -1)
701 seterr("kvm_procread: lseek mem");
702 len = read(mem, buf, real_len);
703 if (len == -1) {
704 seterr("kvm_procread: read mem");
705 return 0;
706 }
707 } else {
708 char bouncebuf[CLBYTES];
709 swaddr = swb.offset + (addr & CLOFSET);
710 swb.size -= addr & CLOFSET;
711 if (lseek(swap, swaddr & ~CLOFSET, 0) == -1) {
712 seterr("kvm_procread: lseek swap");
713 return 0;
714 }
715 len = read(swap, bouncebuf, CLBYTES);
716 if (len == -1 || len <= (swaddr & CLOFSET)) {
717 seterr("kvm_procread: read swap");
718 return 0;
719 }
720 len = MIN(len - (swaddr & CLOFSET), real_len);
721 memcpy(buf, &bouncebuf[swaddr & CLOFSET], len);
722 }
723
724 return len;
725 }
726
727 int
728 kvm_procreadstr(p, addr, buf, len)
729 const struct proc *p;
730 const unsigned addr;
731 char *buf;
732 unsigned len;
733 {
734 int done, little;
735 char copy[200], *pb;
736 char a;
737
738 done = 0;
739 copy[0] = '\0';
740 while (len) {
741 little = kvm_procread(p, addr+done, copy, MIN(len, sizeof copy));
742 if (little<1)
743 break;
744 pb = copy;
745 while (little--) {
746 len--;
747 if( (*buf++ = *pb++) == '\0' )
748 return done;
749 done++;
750 }
751 }
752 return done;
753 }
754
755 char *
756 kvm_getargs(p, up)
757 const struct proc *p;
758 const struct user *up;
759 {
760 static char cmdbuf[ARG_MAX + sizeof(p->p_comm) + 5];
761 register char *cp, *acp;
762 int left, rv;
763 struct ps_strings arginfo;
764
765 if (up == NULL || p->p_pid == 0 || p->p_pid == 2)
766 goto retucomm;
767
768 if (kvm_procread(p, PS_STRINGS, (char *)&arginfo, sizeof(arginfo)) !=
769 sizeof(arginfo))
770 goto bad;
771
772 cmdbuf[0] = '\0';
773 cp = cmdbuf;
774 acp = arginfo.ps_argvstr;
775 left = ARG_MAX + 1;
776 while (arginfo.ps_nargvstr--) {
777 if ((rv = kvm_procreadstr(p, acp, cp, left)) >= 0) {
778 acp += rv + 1;
779 left -= rv + 1;
780 cp += rv;
781 *cp++ = ' ';
782 *cp = '\0';
783 } else
784 goto bad;
785 }
786 cp-- ; *cp = '\0';
787
788 if (cmdbuf[0] == '-' || cmdbuf[0] == '?' || cmdbuf[0] <= ' ') {
789 (void) strcat(cmdbuf, " (");
790 (void) strncat(cmdbuf, p->p_comm, sizeof(p->p_comm));
791 (void) strcat(cmdbuf, ")");
792 }
793 return (cmdbuf);
794
795 bad:
796 seterr("error locating command name for pid %d", p->p_pid);
797 retucomm:
798 (void) strcpy(cmdbuf, "(");
799 (void) strncat(cmdbuf, p->p_comm, sizeof (p->p_comm));
800 (void) strcat(cmdbuf, ")");
801 return (cmdbuf);
802 }
803
804 char *
805 kvm_getenv(p, up)
806 const struct proc *p;
807 const struct user *up;
808 {
809 static char envbuf[ARG_MAX + 1];
810 register char *cp, *acp;
811 int left, rv;
812 struct ps_strings arginfo;
813
814 if (up == NULL || p->p_pid == 0 || p->p_pid == 2)
815 goto retemptyenv;
816
817 if (kvm_procread(p, PS_STRINGS, (char *)&arginfo, sizeof(arginfo)) !=
818 sizeof(arginfo))
819 goto bad;
820
821 cp = envbuf;
822 acp = arginfo.ps_envstr;
823 left = ARG_MAX + 1;
824 while (arginfo.ps_nenvstr--) {
825 if ((rv = kvm_procreadstr(p, acp, cp, left)) >= 0) {
826 acp += rv + 1;
827 left -= rv + 1;
828 cp += rv;
829 *cp++ = ' ';
830 *cp = '\0';
831 } else
832 goto bad;
833 }
834 cp-- ; *cp = '\0';
835 return (envbuf);
836
837 bad:
838 seterr("error locating environment for pid %d", p->p_pid);
839 retemptyenv:
840 envbuf[0] = '\0';
841 return (envbuf);
842 }
843
844 static
845 getkvars()
846 {
847 if (kvm_nlist(nl) == -1)
848 return (-1);
849 if (deadkernel) {
850 /* We must do the sys map first because klseek uses it */
851 long addr;
852
853 #if defined(m68k)
854 addr = (long) nl[X_LOWRAM].n_value;
855 (void) lseek(kmem, addr, 0);
856 if (read(kmem, (char *) &lowram, sizeof (lowram))
857 != sizeof (lowram)) {
858 seterr("can't read lowram");
859 return (-1);
860 }
861 lowram = btop(lowram);
862 Sysseg = (struct ste *) malloc(NBPG);
863 if (Sysseg == NULL) {
864 seterr("out of space for Sysseg");
865 return (-1);
866 }
867 addr = (long) nl[X_SYSSEG].n_value;
868 (void) lseek(kmem, addr, 0);
869 read(kmem, (char *)&addr, sizeof(addr));
870 (void) lseek(kmem, (long)addr, 0);
871 if (read(kmem, (char *) Sysseg, NBPG) != NBPG) {
872 seterr("can't read Sysseg");
873 return (-1);
874 }
875 #endif
876 #if defined(i386)
877 PTD = (struct pde *) malloc(NBPG);
878 if (PTD == NULL) {
879 seterr("out of space for PTD");
880 return (-1);
881 }
882 addr = (long) nl[X_IdlePTD].n_value;
883 (void) lseek(kmem, addr, 0);
884 read(kmem, (char *)&addr, sizeof(addr));
885 (void) lseek(kmem, (long)addr, 0);
886 if (read(kmem, (char *) PTD, NBPG) != NBPG) {
887 seterr("can't read PTD");
888 return (-1);
889 }
890 #endif
891 }
892 if (kvm_read((void *) nl[X_NSWAP].n_value, &nswap, sizeof (long)) == -1) {
893 seterr("can't read nswap");
894 return (-1);
895 }
896 if (kvm_read((void *) nl[X_DMMIN].n_value, &dmmin, sizeof (long)) == -1) {
897 seterr("can't read dmmin");
898 return (-1);
899 }
900 if (kvm_read((void *) nl[X_DMMAX].n_value, &dmmax, sizeof (long)) == -1) {
901 seterr("can't read dmmax");
902 return (-1);
903 }
904 if (kvm_read((void *) nl[X_VM_PAGE_HASH_MASK].n_value,
905 &vm_page_hash_mask, sizeof (long)) == -1) {
906 seterr("can't read vm_page_hash_mask");
907 return (-1);
908 }
909 if (kvm_read((void *) nl[X_VM_PAGE_BUCKETS].n_value,
910 &vm_page_buckets, sizeof (long)) == -1) {
911 seterr("can't read vm_page_buckets");
912 return (-1);
913 }
914 if (kvm_read((void *) nl[X_PAGE_SHIFT].n_value,
915 &page_shift, sizeof (long)) == -1) {
916 seterr("can't read page_shift");
917 return (-1);
918 }
919
920 return (0);
921 }
922
923 kvm_read(loc, buf, len)
924 void *loc;
925 void *buf;
926 {
927 if (kvmfilesopen == 0 && kvm_openfiles(NULL, NULL, NULL) == -1)
928 return (-1);
929 klseek(kmem, (off_t) loc, 0);
930 if (read(kmem, buf, len) != len) {
931 seterr("error reading kmem at %x", loc);
932 return (-1);
933 }
934 return (len);
935 }
936
937 static void
938 klseek(fd, loc, off)
939 int fd;
940 off_t loc;
941 int off;
942 {
943
944 if (deadkernel) {
945 if ((loc = Vtophys(loc)) == -1)
946 return;
947 }
948 (void) lseek(fd, (off_t)loc, off);
949 }
950
951 static off_t
952 Vtophys(loc)
953 u_long loc;
954 {
955 off_t newloc = (off_t) -1;
956 #if defined(m68k)
957 int p, ste, pte;
958
959 ste = *(int *)&Sysseg[btos(loc)];
960 if ((ste & SG_V) == 0) {
961 seterr("vtophys: segment not valid");
962 return((off_t) -1);
963 }
964 p = btop(loc & SG_PMASK);
965 newloc = (ste & SG_FRAME) + (p * sizeof(struct pte));
966 (void) lseek(mem, newloc, 0);
967 if (read(mem, (char *)&pte, sizeof pte) != sizeof pte) {
968 seterr("vtophys: cannot locate pte");
969 return((off_t) -1);
970 }
971 newloc = pte & PG_FRAME;
972 if (pte == PG_NV || newloc < (off_t)ptob(lowram)) {
973 seterr("vtophys: page not valid");
974 return((off_t) -1);
975 }
976 newloc = (newloc - (off_t)ptob(lowram)) + (loc & PGOFSET);
977 #endif
978 #ifdef i386
979 struct pde pde;
980 struct pte pte;
981 int p;
982
983 pde = PTD[loc >> PDSHIFT];
984 if (pde.pd_v == 0) {
985 seterr("vtophys: page directory entry not valid");
986 return((off_t) -1);
987 }
988 p = btop(loc & PT_MASK);
989 newloc = pde.pd_pfnum + (p * sizeof(struct pte));
990 (void) lseek(kmem, (long)newloc, 0);
991 if (read(kmem, (char *)&pte, sizeof pte) != sizeof pte) {
992 seterr("vtophys: cannot obtain desired pte");
993 return((off_t) -1);
994 }
995 newloc = pte.pg_pfnum;
996 if (pte.pg_v == 0) {
997 seterr("vtophys: page table entry not valid");
998 return((off_t) -1);
999 }
1000 newloc += (loc & PGOFSET);
1001 #endif
1002 return((off_t) newloc);
1003 }
1004
1005 /*
1006 * locate address of unwired or swapped page
1007 */
1008
1009 static int
1010 vatosw(mp, vaddr, maddr, swb)
1011 vm_map_t mp;
1012 vm_offset_t vaddr;
1013 vm_offset_t *maddr;
1014 struct swapblk *swb;
1015 {
1016 struct vm_object vm_object;
1017 struct vm_map_entry vm_entry;
1018 long saddr, addr, off;
1019 int i;
1020
1021 saddr = addr = (long)mp->header.next;
1022 #ifdef DEBUG
1023 fprintf(stderr, "vatosw: head=%x\n", &mp->header);
1024 #endif
1025 for (i = 0; ; i++) {
1026 /* Weed through map entries until vaddr in range */
1027 if (kvm_read((void *) addr, &vm_entry, sizeof(vm_entry)) == -1) {
1028 setsyserr("vatosw: read vm_map_entry");
1029 return 0;
1030 }
1031 #ifdef DEBUG
1032 fprintf(stderr, "vatosw: %d/%d, vaddr=%x, start=%x, end=%x ",
1033 i, mp->nentries, vaddr, vm_entry.start, vm_entry.end);
1034 fprintf(stderr, "addr=%x, next=%x\n", addr, vm_entry.next);
1035 #endif
1036 if ((vaddr >= vm_entry.start) && (vaddr < vm_entry.end))
1037 if (vm_entry.object.vm_object != 0)
1038 break;
1039 else {
1040 #ifdef DEBUG
1041 fprintf(stderr, "vatosw: no object\n");
1042 #endif
1043 seterr("vatosw: no object\n");
1044 return 0;
1045 }
1046
1047 addr = (long)vm_entry.next;
1048
1049 if (addr == saddr) {
1050 seterr("vatosw: map not found\n");
1051 return 0;
1052 }
1053 }
1054
1055 if (vm_entry.is_a_map || vm_entry.is_sub_map) {
1056 #ifdef DEBUG
1057 fprintf(stderr, "vatosw: is a %smap\n",
1058 vm_entry.is_sub_map ? "sub " : "");
1059 #endif
1060 seterr("vatosw: is a %smap\n",
1061 vm_entry.is_sub_map ? "sub " : "");
1062 return 0;
1063 }
1064
1065 /* Locate memory object */
1066 off = (vaddr - vm_entry.start) + vm_entry.offset;
1067 addr = (long)vm_entry.object.vm_object;
1068 while (1) {
1069 if (kvm_read((void *) addr, &vm_object, sizeof (vm_object)) == -1) {
1070 setsyserr("vatosw: read vm_object");
1071 return 0;
1072 }
1073
1074 #ifdef DEBUG
1075 fprintf(stderr, "vatosw: find page: object %#x offset %x\n",
1076 addr, off);
1077 #endif
1078
1079 /* Lookup in page queue */
1080 if ((i = findpage(addr, off, maddr)) != -1)
1081 return i;
1082
1083 if (vm_object.pager != 0 &&
1084 (i = pager_get(&vm_object, off, swb)) != -1)
1085 return i;
1086
1087 if (vm_object.shadow == 0)
1088 break;
1089
1090 #ifdef DEBUG
1091 fprintf(stderr, "vatosw: shadow obj at %x: offset %x+%x\n",
1092 addr, off, vm_object.shadow_offset);
1093 #endif
1094
1095 addr = (long)vm_object.shadow;
1096 off += vm_object.shadow_offset;
1097 }
1098
1099 seterr("vatosw: page not found\n");
1100 return 0;
1101 }
1102
1103
1104 int
1105 pager_get(object, off, swb)
1106 struct vm_object *object;
1107 long off;
1108 struct swapblk *swb;
1109 {
1110 struct pager_struct pager;
1111 struct swpager swpager;
1112 struct swblock swblock;
1113
1114 /* Find address in swap space */
1115 if (kvm_read(object->pager, &pager, sizeof (pager)) == -1) {
1116 setsyserr("pager_get: read pager");
1117 return 0;
1118 }
1119 if (pager.pg_type != PG_SWAP) {
1120 seterr("pager_get: weird pager\n");
1121 return 0;
1122 }
1123
1124 /* Get swap pager data */
1125 if (kvm_read(pager.pg_data, &swpager, sizeof (swpager)) == -1) {
1126 setsyserr("pager_get: read swpager");
1127 return 0;
1128 }
1129
1130 off += object->paging_offset;
1131
1132 /* Read swap block array */
1133 if (kvm_read((void *) swpager.sw_blocks +
1134 (off/dbtob(swpager.sw_bsize)) * sizeof swblock,
1135 &swblock, sizeof (swblock)) == -1) {
1136 setsyserr("pager_get: read swblock");
1137 return 0;
1138 }
1139
1140 off %= dbtob(swpager.sw_bsize);
1141
1142 if (swblock.swb_mask & (1 << atop(off))) {
1143 swb->offset = dbtob(swblock.swb_block) + off;
1144 swb->size = dbtob(swpager.sw_bsize) - off;
1145 return 1;
1146 }
1147
1148 return -1;
1149 }
1150
1151 static int
1152 findpage(object, offset, maddr)
1153 long object;
1154 long offset;
1155 vm_offset_t *maddr;
1156 {
1157 queue_head_t bucket;
1158 struct vm_page mem;
1159 long addr, baddr;
1160
1161 baddr = vm_page_buckets +
1162 vm_page_hash(object,offset) * sizeof(queue_head_t);
1163
1164 if (kvm_read((void *) baddr, &bucket, sizeof (bucket)) == -1) {
1165 seterr("can't read vm_page_bucket");
1166 return 0;
1167 }
1168
1169 addr = (long)bucket.next;
1170
1171 while (addr != baddr) {
1172 if (kvm_read((void *) addr, &mem, sizeof (mem)) == -1) {
1173 seterr("can't read vm_page");
1174 return 0;
1175 }
1176
1177 if ((long)mem.object == object && mem.offset == offset) {
1178 *maddr = (long)mem.phys_addr;
1179 return 1;
1180 }
1181
1182 addr = (long)mem.hashq.next;
1183 }
1184
1185 return -1;
1186 }
1187
1188 #include <varargs.h>
1189 static char errbuf[_POSIX2_LINE_MAX];
1190
1191 static void
1192 seterr(va_alist)
1193 va_dcl
1194 {
1195 char *fmt;
1196 va_list ap;
1197
1198 va_start(ap);
1199 fmt = va_arg(ap, char *);
1200 (void) vsnprintf(errbuf, _POSIX2_LINE_MAX, fmt, ap);
1201 #ifdef DEBUG
1202 (void) printf("%s", errbuf);
1203 #endif
1204 va_end(ap);
1205 }
1206
1207 static void
1208 setsyserr(va_alist)
1209 va_dcl
1210 {
1211 char *fmt, *cp;
1212 va_list ap;
1213 extern int errno;
1214
1215 va_start(ap);
1216 fmt = va_arg(ap, char *);
1217 (void) vsnprintf(cp = errbuf, _POSIX2_LINE_MAX, fmt, ap);
1218 cp += strlen(cp);
1219 (void) snprintf(cp, _POSIX2_LINE_MAX - (cp - errbuf), ": %s",
1220 strerror(errno));
1221 #ifdef DEBUG
1222 (void) printf("%s", errbuf);
1223 #endif
1224 va_end(ap);
1225 }
1226
1227 char *
1228 kvm_geterr()
1229 {
1230 return (errbuf);
1231 }
1232