kvm.c revision 1.12 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.12 1993/08/01 18:31:57 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 #ifdef SPPWAIT
58 #define NEWVM
59 #endif
60
61 #ifdef NEWVM
62 #define btop(x) (((unsigned)(x)) >> PGSHIFT) /* XXX */
63 #define ptob(x) ((caddr_t)((x) << PGSHIFT)) /* XXX */
64 #include <vm/vm.h> /* ??? kinfo_proc currently includes this*/
65 #include <vm/vm_page.h>
66 #include <vm/swap_pager.h>
67 #include <sys/kinfo_proc.h>
68 #ifdef hp300
69 #include <hp300/hp300/pte.h>
70 #endif
71 #else /* NEWVM */
72 #include <machine/pte.h>
73 #include <sys/vmmac.h>
74 #include <sys/text.h>
75 #endif /* NEWVM */
76
77 /*
78 * files
79 */
80 static const char *unixf, *memf, *kmemf, *swapf;
81 static int unixx, mem, kmem, swap;
82 static DBM *db;
83 /*
84 * flags
85 */
86 static int deadkernel;
87 static int kvminit = 0;
88 static int kvmfilesopen = 0;
89 /*
90 * state
91 */
92 static struct kinfo_proc *kvmprocbase, *kvmprocptr;
93 static int kvmnprocs;
94 /*
95 * u. buffer
96 */
97 static union {
98 struct user user;
99 char upages[UPAGES][NBPG];
100 } user;
101
102 #ifdef NEWVM
103 struct swapblk {
104 long offset; /* offset in swap device */
105 long size; /* remaining size of block in swap device */
106 };
107 #endif
108 /*
109 * random other stuff
110 */
111 #ifndef NEWVM
112 static struct pte *Usrptmap, *usrpt;
113 static struct pte *Sysmap;
114 static int Syssize;
115 #endif
116 static int dmmin, dmmax;
117 static int pcbpf;
118 static int nswap;
119 static char *tmp;
120 #if defined(hp300)
121 static int lowram;
122 static struct ste *Sysseg;
123 #endif
124 #if defined(i386)
125 static struct pde *PTD;
126 #endif
127
128 #define basename(cp) ((tmp=rindex((cp), '/')) ? tmp+1 : (cp))
129 #define MAXSYMSIZE 256
130
131 #if defined(hp300)
132 #define pftoc(f) ((f) - lowram)
133 #define iskva(v) (1)
134 #endif
135
136 #ifndef pftoc
137 #define pftoc(f) (f)
138 #endif
139 #ifndef iskva
140 #define iskva(v) ((u_long)(v) & KERNBASE)
141 #endif
142
143 static struct nlist nl[] = {
144 { "_Usrptmap" },
145 #define X_USRPTMAP 0
146 { "_usrpt" },
147 #define X_USRPT 1
148 { "_nswap" },
149 #define X_NSWAP 2
150 { "_dmmin" },
151 #define X_DMMIN 3
152 { "_dmmax" },
153 #define X_DMMAX 4
154 { "_vm_page_buckets" },
155 #define X_VM_PAGE_BUCKETS 5
156 { "_vm_page_hash_mask" },
157 #define X_VM_PAGE_HASH_MASK 6
158 { "_page_shift" },
159 #define X_PAGE_SHIFT 7
160 /*
161 * everything here and down, only if a dead kernel
162 */
163 { "_Sysmap" },
164 #define X_SYSMAP 8
165 #define X_DEADKERNEL X_SYSMAP
166 { "_Syssize" },
167 #define X_SYSSIZE 9
168 { "_allproc" },
169 #define X_ALLPROC 10
170 { "_zombproc" },
171 #define X_ZOMBPROC 11
172 { "_nproc" },
173 #define X_NPROC 12
174 #define X_LAST 12
175 #if defined(hp300)
176 { "_Sysseg" },
177 #define X_SYSSEG (X_LAST+1)
178 { "_lowram" },
179 #define X_LOWRAM (X_LAST+2)
180 #endif
181 #if defined(i386)
182 { "_IdlePTD" },
183 #define X_IdlePTD (X_LAST+1)
184 #endif
185 { "" },
186 };
187
188 static off_t Vtophys();
189 static void klseek(), seterr(), setsyserr(), vstodb();
190 static int getkvars(), kvm_doprocs(), kvm_init();
191 #ifdef NEWVM
192 static int vatosw();
193 static int findpage();
194 #endif
195
196 /*
197 * returns 0 if files were opened now,
198 * 1 if files were already opened,
199 * -1 if files could not be opened.
200 */
201 kvm_openfiles(uf, mf, sf)
202 const char *uf, *mf, *sf;
203 {
204 if (kvmfilesopen)
205 return (1);
206 unixx = mem = kmem = swap = -1;
207 unixf = (uf == NULL) ? _PATH_UNIX : uf;
208 memf = (mf == NULL) ? _PATH_MEM : mf;
209
210 if ((unixx = open(unixf, O_RDONLY, 0)) == -1) {
211 setsyserr("can't open %s", unixf);
212 goto failed;
213 }
214 if ((mem = open(memf, O_RDONLY, 0)) == -1) {
215 setsyserr("can't open %s", memf);
216 goto failed;
217 }
218 if (sf != NULL)
219 swapf = sf;
220 if (mf != NULL) {
221 deadkernel++;
222 kmemf = mf;
223 kmem = mem;
224 swap = -1;
225 } else {
226 kmemf = _PATH_KMEM;
227 if ((kmem = open(kmemf, O_RDONLY, 0)) == -1) {
228 setsyserr("can't open %s", kmemf);
229 goto failed;
230 }
231 swapf = (sf == NULL) ? _PATH_DRUM : sf;
232 /*
233 * live kernel - avoid looking up nlist entries
234 * past X_DEADKERNEL.
235 */
236 nl[X_DEADKERNEL].n_name = "";
237 }
238 if (swapf != NULL && ((swap = open(swapf, O_RDONLY, 0)) == -1)) {
239 seterr("can't open %s", swapf);
240 goto failed;
241 }
242 kvmfilesopen++;
243 if (kvminit == 0 && kvm_init(NULL, NULL, NULL, 0) == -1) /*XXX*/
244 return (-1);
245 return (0);
246 failed:
247 kvm_close();
248 return (-1);
249 }
250
251 static
252 kvm_init(uf, mf, sf)
253 char *uf, *mf, *sf;
254 {
255 if (kvmfilesopen == 0 && kvm_openfiles(NULL, NULL, NULL) == -1)
256 return (-1);
257 if (getkvars() == -1)
258 return (-1);
259 kvminit = 1;
260
261 return (0);
262 }
263
264 kvm_close()
265 {
266 if (unixx != -1) {
267 close(unixx);
268 unixx = -1;
269 }
270 if (kmem != -1) {
271 if (kmem != mem)
272 close(kmem);
273 /* otherwise kmem is a copy of mem, and will be closed below */
274 kmem = -1;
275 }
276 if (mem != -1) {
277 close(mem);
278 mem = -1;
279 }
280 if (swap != -1) {
281 close(swap);
282 swap = -1;
283 }
284 if (db != NULL) {
285 dbm_close(db);
286 db = NULL;
287 }
288 kvminit = 0;
289 kvmfilesopen = 0;
290 deadkernel = 0;
291 #ifndef NEWVM
292 if (Sysmap) {
293 free(Sysmap);
294 Sysmap = NULL;
295 }
296 #endif
297 }
298
299 kvm_nlist(nl)
300 struct nlist *nl;
301 {
302 datum key, data;
303 char dbname[MAXPATHLEN];
304 char dbversion[_POSIX2_LINE_MAX];
305 char kversion[_POSIX2_LINE_MAX];
306 int dbversionlen;
307 char symbuf[MAXSYMSIZE];
308 struct nlist nbuf, *n;
309 int num, did;
310
311 if (kvmfilesopen == 0 && kvm_openfiles(NULL, NULL, NULL) == -1)
312 return (-1);
313 if (deadkernel)
314 goto hard2;
315 /*
316 * initialize key datum
317 */
318 key.dptr = symbuf;
319
320 if (db != NULL)
321 goto win; /* off to the races */
322 /*
323 * open database
324 */
325 sprintf(dbname, "%s/kvm_%s", _PATH_VARRUN, basename(unixf));
326 if ((db = dbm_open(dbname, O_RDONLY, 0)) == NULL)
327 goto hard2;
328 /*
329 * read version out of database
330 */
331 bcopy("VERSION", symbuf, sizeof ("VERSION")-1);
332 key.dsize = (sizeof ("VERSION") - 1);
333 data = dbm_fetch(db, key);
334 if (data.dptr == NULL)
335 goto hard1;
336 bcopy(data.dptr, dbversion, data.dsize);
337 dbversionlen = data.dsize;
338 /*
339 * read version string from kernel memory
340 */
341 bcopy("_version", symbuf, sizeof ("_version")-1);
342 key.dsize = (sizeof ("_version")-1);
343 data = dbm_fetch(db, key);
344 if (data.dptr == NULL)
345 goto hard1;
346 if (data.dsize != sizeof (struct nlist))
347 goto hard1;
348 bcopy(data.dptr, &nbuf, sizeof (struct nlist));
349 lseek(kmem, nbuf.n_value, 0);
350 if (read(kmem, kversion, dbversionlen) != dbversionlen)
351 goto hard1;
352 /*
353 * if they match, we win - otherwise do it the hard way
354 */
355 if (bcmp(dbversion, kversion, dbversionlen) != 0)
356 goto hard1;
357 /*
358 * getem from the database.
359 */
360 win:
361 num = did = 0;
362 for (n = nl; n->n_name && n->n_name[0]; n++, num++) {
363 int len;
364 /*
365 * clear out fields from users buffer
366 */
367 n->n_type = 0;
368 n->n_other = 0;
369 n->n_desc = 0;
370 n->n_value = 0;
371 /*
372 * query db
373 */
374 if ((len = strlen(n->n_name)) > MAXSYMSIZE) {
375 seterr("symbol too large");
376 return (-1);
377 }
378 (void)strcpy(symbuf, n->n_name);
379 key.dsize = len;
380 data = dbm_fetch(db, key);
381 if (data.dptr == NULL || data.dsize != sizeof (struct nlist))
382 continue;
383 bcopy(data.dptr, &nbuf, sizeof (struct nlist));
384 n->n_value = nbuf.n_value;
385 n->n_type = nbuf.n_type;
386 n->n_desc = nbuf.n_desc;
387 n->n_other = nbuf.n_other;
388 did++;
389 }
390 return (num - did);
391 hard1:
392 dbm_close(db);
393 db = NULL;
394 hard2:
395 num = nlist(unixf, nl);
396 if (num == -1)
397 seterr("nlist (hard way) failed");
398 return (num);
399 }
400
401 kvm_getprocs(what, arg)
402 int what, arg;
403 {
404 static int ocopysize = -1;
405
406 if (kvminit == 0 && kvm_init(NULL, NULL, NULL, 0) == -1)
407 return (NULL);
408 if (!deadkernel) {
409 int ret, copysize;
410
411 if ((ret = getkerninfo(what, NULL, NULL, arg)) == -1) {
412 setsyserr("can't get estimate for kerninfo");
413 return (-1);
414 }
415 copysize = ret;
416 if (copysize > ocopysize || !kvmprocbase) {
417 if (ocopysize == -1 || !kvmprocbase)
418 kvmprocbase =
419 (struct kinfo_proc *)malloc(copysize);
420 else
421 kvmprocbase =
422 (struct kinfo_proc *)realloc(kvmprocbase,
423 copysize);
424 if (!kvmprocbase) {
425 seterr("out of memory");
426 return (-1);
427 }
428 }
429 ocopysize = copysize;
430 if ((ret = getkerninfo(what, kvmprocbase, ©size,
431 arg)) == -1) {
432 setsyserr("can't get proc list");
433 return (-1);
434 }
435 if (copysize % sizeof (struct kinfo_proc)) {
436 seterr("proc size mismatch (got %d total, kinfo_proc: %d)",
437 copysize, sizeof (struct kinfo_proc));
438 return (-1);
439 }
440 kvmnprocs = copysize / sizeof (struct kinfo_proc);
441 } else {
442 int nproc;
443
444 if (kvm_read((void *) nl[X_NPROC].n_value, &nproc,
445 sizeof (int)) != sizeof (int)) {
446 seterr("can't read nproc");
447 return (-1);
448 }
449 if ((kvmprocbase = (struct kinfo_proc *)
450 malloc(nproc * sizeof (struct kinfo_proc))) == NULL) {
451 seterr("out of memory (addr: %x nproc = %d)",
452 nl[X_NPROC].n_value, nproc);
453 return (-1);
454 }
455 kvmnprocs = kvm_doprocs(what, arg, kvmprocbase);
456 realloc(kvmprocbase, kvmnprocs * sizeof (struct kinfo_proc));
457 }
458 kvmprocptr = kvmprocbase;
459
460 return (kvmnprocs);
461 }
462
463 /*
464 * XXX - should NOT give up so easily - especially since the kernel
465 * may be corrupt (it died). Should gather as much information as possible.
466 * Follows proc ptrs instead of reading table since table may go
467 * away soon.
468 */
469 static
470 kvm_doprocs(what, arg, buff)
471 int what, arg;
472 char *buff;
473 {
474 struct proc *p, proc;
475 register char *bp = buff;
476 int i = 0;
477 int doingzomb = 0;
478 struct eproc eproc;
479 struct pgrp pgrp;
480 struct session sess;
481 struct tty tty;
482 #ifndef NEWVM
483 struct text text;
484 #endif
485
486 /* allproc */
487 if (kvm_read((void *) nl[X_ALLPROC].n_value, &p,
488 sizeof (struct proc *)) != sizeof (struct proc *)) {
489 seterr("can't read allproc");
490 return (-1);
491 }
492
493 again:
494 for (; p; p = proc.p_nxt) {
495 if (kvm_read(p, &proc, sizeof (struct proc)) !=
496 sizeof (struct proc)) {
497 seterr("can't read proc at %x", p);
498 return (-1);
499 }
500 #ifdef NEWVM
501 if (kvm_read(proc.p_cred, &eproc.e_pcred,
502 sizeof (struct pcred)) == sizeof (struct pcred))
503 (void) kvm_read(eproc.e_pcred.pc_ucred, &eproc.e_ucred,
504 sizeof (struct ucred));
505 switch(ki_op(what)) {
506
507 case KINFO_PROC_PID:
508 if (proc.p_pid != (pid_t)arg)
509 continue;
510 break;
511
512
513 case KINFO_PROC_UID:
514 if (eproc.e_ucred.cr_uid != (uid_t)arg)
515 continue;
516 break;
517
518 case KINFO_PROC_RUID:
519 if (eproc.e_pcred.p_ruid != (uid_t)arg)
520 continue;
521 break;
522 }
523 #else
524 switch(ki_op(what)) {
525
526 case KINFO_PROC_PID:
527 if (proc.p_pid != (pid_t)arg)
528 continue;
529 break;
530
531
532 case KINFO_PROC_UID:
533 if (proc.p_uid != (uid_t)arg)
534 continue;
535 break;
536
537 case KINFO_PROC_RUID:
538 if (proc.p_ruid != (uid_t)arg)
539 continue;
540 break;
541 }
542 #endif
543 /*
544 * gather eproc
545 */
546 eproc.e_paddr = p;
547 if (kvm_read(proc.p_pgrp, &pgrp, sizeof (struct pgrp)) !=
548 sizeof (struct pgrp)) {
549 seterr("can't read pgrp at %x", proc.p_pgrp);
550 return (-1);
551 }
552 eproc.e_sess = pgrp.pg_session;
553 eproc.e_pgid = pgrp.pg_id;
554 eproc.e_jobc = pgrp.pg_jobc;
555 if (kvm_read(pgrp.pg_session, &sess, sizeof (struct session))
556 != sizeof (struct session)) {
557 seterr("can't read session at %x", pgrp.pg_session);
558 return (-1);
559 }
560 if ((proc.p_flag&SCTTY) && sess.s_ttyp != NULL) {
561 if (kvm_read(sess.s_ttyp, &tty, sizeof (struct tty))
562 != sizeof (struct tty)) {
563 seterr("can't read tty at %x", sess.s_ttyp);
564 return (-1);
565 }
566 eproc.e_tdev = tty.t_dev;
567 eproc.e_tsess = tty.t_session;
568 if (tty.t_pgrp != NULL) {
569 if (kvm_read(tty.t_pgrp, &pgrp, sizeof (struct
570 pgrp)) != sizeof (struct pgrp)) {
571 seterr("can't read tpgrp at &x",
572 tty.t_pgrp);
573 return (-1);
574 }
575 eproc.e_tpgid = pgrp.pg_id;
576 } else
577 eproc.e_tpgid = -1;
578 } else
579 eproc.e_tdev = NODEV;
580 if (proc.p_wmesg)
581 kvm_read(proc.p_wmesg, eproc.e_wmesg, WMESGLEN);
582 #ifdef NEWVM
583 (void) kvm_read(proc.p_vmspace, &eproc.e_vm,
584 sizeof (struct vmspace));
585 eproc.e_xsize = eproc.e_xrssize =
586 eproc.e_xccount = eproc.e_xswrss = 0;
587 #else
588 if (proc.p_textp) {
589 kvm_read(proc.p_textp, &text, sizeof (text));
590 eproc.e_xsize = text.x_size;
591 eproc.e_xrssize = text.x_rssize;
592 eproc.e_xccount = text.x_ccount;
593 eproc.e_xswrss = text.x_swrss;
594 } else {
595 eproc.e_xsize = eproc.e_xrssize =
596 eproc.e_xccount = eproc.e_xswrss = 0;
597 }
598 #endif
599
600 switch(ki_op(what)) {
601
602 case KINFO_PROC_PGRP:
603 if (eproc.e_pgid != (pid_t)arg)
604 continue;
605 break;
606
607 case KINFO_PROC_TTY:
608 if ((proc.p_flag&SCTTY) == 0 ||
609 eproc.e_tdev != (dev_t)arg)
610 continue;
611 break;
612 }
613
614 i++;
615 bcopy(&proc, bp, sizeof (struct proc));
616 bp += sizeof (struct proc);
617 bcopy(&eproc, bp, sizeof (struct eproc));
618 bp+= sizeof (struct eproc);
619 }
620 if (!doingzomb) {
621 /* zombproc */
622 if (kvm_read((void *) nl[X_ZOMBPROC].n_value, &p,
623 sizeof (struct proc *)) != sizeof (struct proc *)) {
624 seterr("can't read zombproc");
625 return (-1);
626 }
627 doingzomb = 1;
628 goto again;
629 }
630
631 return (i);
632 }
633
634 struct proc *
635 kvm_nextproc()
636 {
637
638 if (!kvmprocbase && kvm_getprocs(0, 0) == -1)
639 return (NULL);
640 if (kvmprocptr >= (kvmprocbase + kvmnprocs)) {
641 seterr("end of proc list");
642 return (NULL);
643 }
644 return((struct proc *)(kvmprocptr++));
645 }
646
647 struct eproc *
648 kvm_geteproc(p)
649 const struct proc *p;
650 {
651 return ((struct eproc *)(((char *)p) + sizeof (struct proc)));
652 }
653
654 kvm_setproc()
655 {
656 kvmprocptr = kvmprocbase;
657 }
658
659 kvm_freeprocs()
660 {
661
662 if (kvmprocbase) {
663 free(kvmprocbase);
664 kvmprocbase = NULL;
665 }
666 }
667
668 #ifdef NEWVM
669 struct user *
670 kvm_getu(p)
671 const struct proc *p;
672 {
673 register struct kinfo_proc *kp = (struct kinfo_proc *)p;
674 register int i;
675 register char *up;
676 u_int vaddr;
677 struct swapblk swb;
678
679 if (kvminit == 0 && kvm_init(NULL, NULL, NULL, 0) == -1)
680 return (NULL);
681 if (p->p_stat == SZOMB) {
682 seterr("zombie process");
683 return (NULL);
684 }
685
686 if ((p->p_flag & SLOAD) == 0) {
687 vm_offset_t maddr;
688
689 if (swap < 0) {
690 seterr("no swap");
691 return (NULL);
692 }
693 /*
694 * Costly operation, better set enable_swap to zero
695 * in vm/vm_glue.c, since paging of user pages isn't
696 * done yet anyway.
697 */
698 if (vatosw(p, USRSTACK + i * NBPG, &maddr, &swb) == 0)
699 return NULL;
700
701 if (maddr == 0 && swb.size < UPAGES * NBPG)
702 return NULL;
703
704 for (i = 0; i < UPAGES; i++) {
705 if (maddr) {
706 (void) lseek(mem, maddr + i * NBPG, 0);
707 if (read(mem,
708 (char *)user.upages[i], NBPG) != NBPG) {
709 seterr(
710 "can't read u for pid %d from %s",
711 p->p_pid, swapf);
712 return NULL;
713 }
714 } else {
715 (void) lseek(swap, swb.offset + i * NBPG, 0);
716 if (read(swap,
717 (char *)user.upages[i], NBPG) != NBPG) {
718 seterr(
719 "can't read u for pid %d from %s",
720 p->p_pid, swapf);
721 return NULL;
722 }
723 }
724 }
725 return(&user.user);
726 }
727 /*
728 * Read u-area one page at a time for the benefit of post-mortems
729 */
730 up = (char *) p->p_addr;
731 for (i = 0; i < UPAGES; i++) {
732 klseek(kmem, (long)up, 0);
733 if (read(kmem, user.upages[i], CLBYTES) != CLBYTES) {
734 seterr("cant read page %x of u of pid %d from %s",
735 up, p->p_pid, kmemf);
736 return(NULL);
737 }
738 up += CLBYTES;
739 }
740 pcbpf = (int) btop(p->p_addr); /* what should this be really? */
741
742 kp->kp_eproc.e_vm.vm_rssize =
743 kp->kp_eproc.e_vm.vm_pmap.pm_stats.resident_count; /* XXX */
744 return(&user.user);
745 }
746 #else
747 struct user *
748 kvm_getu(p)
749 const struct proc *p;
750 {
751 struct pte *pteaddr, apte;
752 struct pte arguutl[HIGHPAGES+(CLSIZE*2)];
753 register int i;
754 int ncl;
755
756 if (kvminit == 0 && kvm_init(NULL, NULL, NULL, 0) == -1)
757 return (NULL);
758 if (p->p_stat == SZOMB) {
759 seterr("zombie process");
760 return (NULL);
761 }
762 if ((p->p_flag & SLOAD) == 0) {
763 if (swap < 0) {
764 seterr("no swap");
765 return (NULL);
766 }
767 (void) lseek(swap, (long)dtob(p->p_swaddr), 0);
768 if (read(swap, (char *)&user.user, sizeof (struct user)) !=
769 sizeof (struct user)) {
770 seterr("can't read u for pid %d from %s",
771 p->p_pid, swapf);
772 return (NULL);
773 }
774 pcbpf = 0;
775 argaddr0 = 0;
776 argaddr1 = 0;
777 return (&user.user);
778 }
779 pteaddr = &Usrptmap[btokmx(p->p_p0br) + p->p_szpt - 1];
780 klseek(kmem, (long)pteaddr, 0);
781 if (read(kmem, (char *)&apte, sizeof(apte)) != sizeof(apte)) {
782 seterr("can't read indir pte to get u for pid %d from %s",
783 p->p_pid, kmemf);
784 return (NULL);
785 }
786 lseek(mem, (long)ctob(pftoc(apte.pg_pfnum+1)) - sizeof(arguutl), 0);
787 if (read(mem, (char *)arguutl, sizeof(arguutl)) != sizeof(arguutl)) {
788 seterr("can't read page table for u of pid %d from %s",
789 p->p_pid, memf);
790 return (NULL);
791 }
792 if (arguutl[0].pg_fod == 0 && arguutl[0].pg_pfnum)
793 argaddr0 = ctob(pftoc(arguutl[0].pg_pfnum));
794 else
795 argaddr0 = 0;
796 if (arguutl[CLSIZE*1].pg_fod == 0 && arguutl[CLSIZE*1].pg_pfnum)
797 argaddr1 = ctob(pftoc(arguutl[CLSIZE*1].pg_pfnum));
798 else
799 argaddr1 = 0;
800 pcbpf = arguutl[CLSIZE*2].pg_pfnum;
801 ncl = (sizeof (struct user) + CLBYTES - 1) / CLBYTES;
802 while (--ncl >= 0) {
803 i = ncl * CLSIZE;
804 lseek(mem,
805 (long)ctob(pftoc(arguutl[(CLSIZE*2)+i].pg_pfnum)), 0);
806 if (read(mem, user.upages[i], CLBYTES) != CLBYTES) {
807 seterr("can't read page %d of u of pid %d from %s",
808 arguutl[(CLSIZE*2)+i].pg_pfnum, p->p_pid, memf);
809 return(NULL);
810 }
811 }
812 return (&user.user);
813 }
814 #endif
815
816 int
817 kvm_procread(p, addr, buf, len)
818 const struct proc *p;
819 const unsigned addr, len;
820 char *buf;
821 {
822 register struct kinfo_proc *kp = (struct kinfo_proc *) p;
823 struct swapblk swb;
824 vm_offset_t swaddr = 0, memaddr = 0;
825 unsigned real_len;
826
827 real_len = len < (CLBYTES - (addr & CLOFSET)) ? len : (CLBYTES - (addr & CLOFSET));
828
829 #if defined(hp300)
830 /*
831 * XXX DANGER WILL ROBINSON -- i have *no* idea to what extent this
832 * works... -- cgd
833 */
834 BREAK HERE!!!
835 #endif
836 #if defined(i386)
837 if (kp->kp_eproc.e_vm.vm_pmap.pm_pdir) {
838 struct pde pde;
839
840 klseek(kmem,
841 (long)(&kp->kp_eproc.e_vm.vm_pmap.pm_pdir[pdei(addr)]), 0);
842
843 if (read(kmem, (char *)&pde, sizeof pde) == sizeof pde
844 && pde.pd_v) {
845
846 struct pte pte;
847
848 if (lseek(mem, (long)ctob(pde.pd_pfnum) +
849 (ptei(addr) * sizeof pte), 0) == -1)
850 seterr("kvm_procread: lseek");
851 if (read(mem, (char *)&pte, sizeof pte) == sizeof pte) {
852 if (pte.pg_v) {
853 memaddr = (long)ctob(pte.pg_pfnum) +
854 (addr % (1 << PGSHIFT));
855 }
856 } else {
857 seterr("kvm_procread: read");
858 }
859 }
860 }
861 #endif /* i386 */
862
863 if (memaddr == 0 && vatosw(p, addr & ~CLOFSET, &memaddr, &swb)) {
864 if (memaddr != 0) {
865 memaddr += addr & CLOFSET;
866 } else {
867 swaddr = swb.offset + (addr & CLOFSET);
868 swb.size -= addr & CLOFSET;
869 }
870 }
871
872 if (memaddr) {
873 if (lseek(mem, memaddr, 0) == -1)
874 seterr("kvm_getu: lseek");
875 real_len = read(mem, buf, real_len);
876 if (real_len == -1) {
877 seterr("kvm_procread: read");
878 return 0;
879 }
880 } else if (swaddr) {
881 char bouncebuf[CLBYTES];
882 unsigned len;
883 if (lseek(swap, swaddr & ~CLOFSET, 0) == -1) {
884 seterr("kvm_procread: lseek");
885 return 0;
886 }
887 len = read(swap, bouncebuf, CLBYTES);
888 if (len == -1 || len <= (swaddr & CLOFSET)) {
889 seterr("kvm_procread: read");
890 return 0;
891 }
892 len = MIN(len - (swaddr & CLOFSET), real_len);
893 memcpy(buf, &bouncebuf[swaddr & CLOFSET], len);
894 return len;
895 } else
896 real_len = 0;
897
898 return real_len;
899 }
900
901 int
902 kvm_procreadstr(p, addr, buf, len)
903 const struct proc *p;
904 const unsigned addr;
905 char *buf;
906 unsigned len;
907 {
908 int done, little;
909 char copy[200], *pb;
910 char a;
911
912 done = 0;
913 while (len) {
914 little = kvm_procread(p, addr+done, copy, MIN(len, sizeof copy));
915 if (little<1)
916 break;
917 pb = copy;
918 while (little--) {
919 len--;
920 if( (*buf++ = *pb++) == '\0' )
921 return done;
922 done++;
923 }
924 }
925 return done;
926 }
927
928 char *
929 kvm_getargs(p, up)
930 const struct proc *p;
931 const struct user *up;
932 {
933 static char cmdbuf[ARG_MAX + sizeof(p->p_comm) + 5];
934 register char *cp, *acp;
935 int left, rv;
936 struct ps_strings arginfo;
937
938 if (up == NULL || p->p_pid == 0 || p->p_pid == 2)
939 goto retucomm;
940
941 if (kvm_procread(p, PS_STRINGS, (char *)&arginfo, sizeof(arginfo)) !=
942 sizeof(arginfo))
943 goto bad;
944
945 cp = cmdbuf;
946 acp = arginfo.ps_argvstr;
947 left = ARG_MAX + 1;
948 while (arginfo.ps_nargvstr--) {
949 if ((rv = kvm_procreadstr(p, acp, cp, left)) >= 0) {
950 acp += rv + 1;
951 left -= rv + 1;
952 cp += rv;
953 *cp++ = ' ';
954 *cp = '\0';
955 } else
956 goto bad;
957 }
958 cp-- ; *cp = '\0';
959
960 if (cmdbuf[0] == '-' || cmdbuf[0] == '?' || cmdbuf[0] <= ' ') {
961 (void) strcat(cmdbuf, " (");
962 (void) strncat(cmdbuf, p->p_comm, sizeof(p->p_comm));
963 (void) strcat(cmdbuf, ")");
964 }
965 return (cmdbuf);
966
967 bad:
968 seterr("error locating command name for pid %d", p->p_pid);
969 retucomm:
970 (void) strcpy(cmdbuf, "(");
971 (void) strncat(cmdbuf, p->p_comm, sizeof (p->p_comm));
972 (void) strcat(cmdbuf, ")");
973 return (cmdbuf);
974 }
975
976 char *
977 kvm_getenv(p, up)
978 const struct proc *p;
979 const struct user *up;
980 {
981 static char envbuf[ARG_MAX + 1];
982 register char *cp, *acp;
983 int left, rv;
984 struct ps_strings arginfo;
985
986 if (up == NULL || p->p_pid == 0 || p->p_pid == 2)
987 goto retemptyenv;
988
989 if (kvm_procread(p, PS_STRINGS, (char *)&arginfo, sizeof(arginfo)) !=
990 sizeof(arginfo))
991 goto bad;
992
993 cp = envbuf;
994 acp = arginfo.ps_envstr;
995 left = ARG_MAX + 1;
996 while (arginfo.ps_nenvstr--) {
997 if ((rv = kvm_procreadstr(p, acp, cp, left)) >= 0) {
998 acp += rv + 1;
999 left -= rv + 1;
1000 cp += rv;
1001 *cp++ = ' ';
1002 *cp = '\0';
1003 } else
1004 goto bad;
1005 }
1006 cp-- ; *cp = '\0';
1007 return (envbuf);
1008
1009 bad:
1010 seterr("error locating environment for pid %d", p->p_pid);
1011 retemptyenv:
1012 envbuf[0] = '\0';
1013 return (envbuf);
1014 }
1015
1016 static
1017 getkvars()
1018 {
1019 if (kvm_nlist(nl) == -1)
1020 return (-1);
1021 if (deadkernel) {
1022 /* We must do the sys map first because klseek uses it */
1023 long addr;
1024
1025 #ifndef NEWVM
1026 Syssize = nl[X_SYSSIZE].n_value;
1027 Sysmap = (struct pte *)
1028 calloc((unsigned) Syssize, sizeof (struct pte));
1029 if (Sysmap == NULL) {
1030 seterr("out of space for Sysmap");
1031 return (-1);
1032 }
1033 addr = (long) nl[X_SYSMAP].n_value;
1034 addr &= ~KERNBASE;
1035 (void) lseek(kmem, addr, 0);
1036 if (read(kmem, (char *) Sysmap, Syssize * sizeof (struct pte))
1037 != Syssize * sizeof (struct pte)) {
1038 seterr("can't read Sysmap");
1039 return (-1);
1040 }
1041 #endif
1042 #if defined(hp300)
1043 addr = (long) nl[X_LOWRAM].n_value;
1044 (void) lseek(kmem, addr, 0);
1045 if (read(kmem, (char *) &lowram, sizeof (lowram))
1046 != sizeof (lowram)) {
1047 seterr("can't read lowram");
1048 return (-1);
1049 }
1050 lowram = btop(lowram);
1051 Sysseg = (struct ste *) malloc(NBPG);
1052 if (Sysseg == NULL) {
1053 seterr("out of space for Sysseg");
1054 return (-1);
1055 }
1056 addr = (long) nl[X_SYSSEG].n_value;
1057 (void) lseek(kmem, addr, 0);
1058 read(kmem, (char *)&addr, sizeof(addr));
1059 (void) lseek(kmem, (long)addr, 0);
1060 if (read(kmem, (char *) Sysseg, NBPG) != NBPG) {
1061 seterr("can't read Sysseg");
1062 return (-1);
1063 }
1064 #endif
1065 #if defined(i386)
1066 PTD = (struct pde *) malloc(NBPG);
1067 if (PTD == NULL) {
1068 seterr("out of space for PTD");
1069 return (-1);
1070 }
1071 addr = (long) nl[X_IdlePTD].n_value;
1072 (void) lseek(kmem, addr, 0);
1073 read(kmem, (char *)&addr, sizeof(addr));
1074 (void) lseek(kmem, (long)addr, 0);
1075 if (read(kmem, (char *) PTD, NBPG) != NBPG) {
1076 seterr("can't read PTD");
1077 return (-1);
1078 }
1079 #endif
1080 }
1081 #ifndef NEWVM
1082 usrpt = (struct pte *)nl[X_USRPT].n_value;
1083 Usrptmap = (struct pte *)nl[X_USRPTMAP].n_value;
1084 #endif
1085 if (kvm_read((void *) nl[X_NSWAP].n_value, &nswap, sizeof (long)) !=
1086 sizeof (long)) {
1087 seterr("can't read nswap");
1088 return (-1);
1089 }
1090 if (kvm_read((void *) nl[X_DMMIN].n_value, &dmmin, sizeof (long)) !=
1091 sizeof (long)) {
1092 seterr("can't read dmmin");
1093 return (-1);
1094 }
1095 if (kvm_read((void *) nl[X_DMMAX].n_value, &dmmax, sizeof (long)) !=
1096 sizeof (long)) {
1097 seterr("can't read dmmax");
1098 return (-1);
1099 }
1100 return (0);
1101 }
1102
1103 kvm_read(loc, buf, len)
1104 void *loc;
1105 void *buf;
1106 {
1107 if (kvmfilesopen == 0 && kvm_openfiles(NULL, NULL, NULL) == -1)
1108 return (-1);
1109 if (iskva(loc)) {
1110 klseek(kmem, (off_t) loc, 0);
1111 if (read(kmem, buf, len) != len) {
1112 seterr("error reading kmem at %x", loc);
1113 return (-1);
1114 }
1115 } else {
1116 lseek(mem, (off_t) loc, 0);
1117 if (read(mem, buf, len) != len) {
1118 seterr("error reading mem at %x", loc);
1119 return (-1);
1120 }
1121 }
1122 return (len);
1123 }
1124
1125 static void
1126 klseek(fd, loc, off)
1127 int fd;
1128 off_t loc;
1129 int off;
1130 {
1131
1132 if (deadkernel) {
1133 if ((loc = Vtophys(loc)) == -1)
1134 return;
1135 }
1136 (void) lseek(fd, (off_t)loc, off);
1137 }
1138
1139 #ifndef NEWVM
1140 /*
1141 * Given a base/size pair in virtual swap area,
1142 * return a physical base/size pair which is the
1143 * (largest) initial, physically contiguous block.
1144 */
1145 static void
1146 vstodb(vsbase, vssize, dmp, dbp, rev)
1147 register int vsbase;
1148 int vssize;
1149 struct dmap *dmp;
1150 register struct dblock *dbp;
1151 {
1152 register int blk = dmmin;
1153 register swblk_t *ip = dmp->dm_map;
1154
1155 vsbase = ctod(vsbase);
1156 vssize = ctod(vssize);
1157 if (vsbase < 0 || vsbase + vssize > dmp->dm_size)
1158 /*panic("vstodb")*/;
1159 while (vsbase >= blk) {
1160 vsbase -= blk;
1161 if (blk < dmmax)
1162 blk *= 2;
1163 ip++;
1164 }
1165 if (*ip <= 0 || *ip + blk > nswap)
1166 /*panic("vstodb")*/;
1167 dbp->db_size = MIN(vssize, blk - vsbase);
1168 dbp->db_base = *ip + (rev ? blk - (vsbase + dbp->db_size) : vsbase);
1169 }
1170 #endif
1171
1172 #ifdef NEWVM
1173 static off_t
1174 Vtophys(loc)
1175 u_long loc;
1176 {
1177 off_t newloc = (off_t) -1;
1178 #ifdef hp300
1179 int p, ste, pte;
1180
1181 ste = *(int *)&Sysseg[loc >> SG_ISHIFT];
1182 if ((ste & SG_V) == 0) {
1183 seterr("vtophys: segment not valid");
1184 return((off_t) -1);
1185 }
1186 p = btop(loc & SG_PMASK);
1187 newloc = (ste & SG_FRAME) + (p * sizeof(struct pte));
1188 (void) lseek(kmem, (long)(newloc-(off_t)ptob(lowram)), 0);
1189 if (read(kmem, (char *)&pte, sizeof pte) != sizeof pte) {
1190 seterr("vtophys: cannot locate pte");
1191 return((off_t) -1);
1192 }
1193 newloc = pte & PG_FRAME;
1194 if (pte == PG_NV || newloc < (off_t)ptob(lowram)) {
1195 seterr("vtophys: page not valid");
1196 return((off_t) -1);
1197 }
1198 newloc = (newloc - (off_t)ptob(lowram)) + (loc & PGOFSET);
1199 #endif
1200 #ifdef i386
1201 struct pde pde;
1202 struct pte pte;
1203 int p;
1204
1205 pde = PTD[loc >> PD_SHIFT];
1206 if (pde.pd_v == 0) {
1207 seterr("vtophys: page directory entry not valid");
1208 return((off_t) -1);
1209 }
1210 p = btop(loc & PT_MASK);
1211 newloc = pde.pd_pfnum + (p * sizeof(struct pte));
1212 (void) lseek(kmem, (long)newloc, 0);
1213 if (read(kmem, (char *)&pte, sizeof pte) != sizeof pte) {
1214 seterr("vtophys: cannot obtain desired pte");
1215 return((off_t) -1);
1216 }
1217 newloc = pte.pg_pfnum;
1218 if (pte.pg_v == 0) {
1219 seterr("vtophys: page table entry not valid");
1220 return((off_t) -1);
1221 }
1222 newloc += (loc & PGOFSET);
1223 #endif
1224 return((off_t) newloc);
1225 }
1226 #else
1227 static off_t
1228 vtophys(loc)
1229 long loc;
1230 {
1231 int p;
1232 off_t newloc;
1233 register struct pte *pte;
1234
1235 newloc = loc & ~KERNBASE;
1236 p = btop(newloc);
1237 #if defined(vax) || defined(tahoe)
1238 if ((loc & KERNBASE) == 0) {
1239 seterr("vtophys: translating non-kernel address");
1240 return((off_t) -1);
1241 }
1242 #endif
1243 if (p >= Syssize) {
1244 seterr("vtophys: page out of bound (%d>=%d)", p, Syssize);
1245 return((off_t) -1);
1246 }
1247 pte = &Sysmap[p];
1248 if (pte->pg_v == 0 && (pte->pg_fod || pte->pg_pfnum == 0)) {
1249 seterr("vtophys: page not valid");
1250 return((off_t) -1);
1251 }
1252 #if defined(hp300)
1253 if (pte->pg_pfnum < lowram) {
1254 seterr("vtophys: non-RAM page (%d<%d)", pte->pg_pfnum, lowram);
1255 return((off_t) -1);
1256 }
1257 #endif
1258 loc = (long) (ptob(pftoc(pte->pg_pfnum)) + (loc & PGOFSET));
1259 return(loc);
1260 }
1261 #endif
1262
1263
1264 #ifdef NEWVM
1265 /*
1266 * locate address of unwired or swapped page
1267 */
1268
1269 #define DEBUG 0
1270
1271 #define KREAD(off, addr, len) \
1272 (kvm_read((void *)(off), (char *)(addr), (len)) == (len))
1273
1274
1275 static int
1276 vatosw(p, vaddr, maddr, swb)
1277 struct proc *p ;
1278 vm_offset_t vaddr;
1279 vm_offset_t *maddr;
1280 struct swapblk *swb;
1281 {
1282 register struct kinfo_proc *kp = (struct kinfo_proc *)p;
1283 vm_map_t mp = &kp->kp_eproc.e_vm.vm_map;
1284 struct vm_object vm_object;
1285 struct vm_map_entry vm_entry;
1286 struct pager_struct pager;
1287 struct swpager swpager;
1288 struct swblock swblock;
1289 long addr, off;
1290 int i;
1291
1292 if (p->p_pid == 0 || p->p_pid == 2)
1293 return 0;
1294
1295 addr = (long)mp->header.next;
1296 for (i = 0; i < mp->nentries; i++) {
1297 /* Weed through map entries until vaddr in range */
1298 if (!KREAD(addr, &vm_entry, sizeof(vm_entry))) {
1299 setsyserr("vatosw: read vm_map_entry");
1300 return 0;
1301 }
1302 if ((vaddr >= vm_entry.start) && (vaddr <= vm_entry.end) &&
1303 (vm_entry.object.vm_object != 0))
1304 break;
1305
1306 addr = (long)vm_entry.next;
1307 }
1308 if (i == mp->nentries) {
1309 seterr("%u: map not found\n", p->p_pid);
1310 return 0;
1311 }
1312
1313 if (vm_entry.is_a_map || vm_entry.is_sub_map) {
1314 seterr("%u: Is a map\n", p->p_pid);
1315 return 0;
1316 }
1317
1318 /* Locate memory object */
1319 off = (vaddr - vm_entry.start) + vm_entry.offset;
1320 addr = (long)vm_entry.object.vm_object;
1321 while (1) {
1322 if (!KREAD(addr, &vm_object, sizeof vm_object)) {
1323 setsyserr("vatosw: read vm_object");
1324 return 0;
1325 }
1326
1327 #if DEBUG
1328 fprintf(stderr, "%u: find page: object %#x offset %x\n",
1329 p->p_pid, addr, off);
1330 #endif
1331
1332 /* Lookup in page queue */
1333 if (findpage(addr, off, maddr))
1334 return 1;
1335
1336 if (vm_object.shadow == 0)
1337 break;
1338
1339 #if DEBUG
1340 fprintf(stderr, "%u: shadow obj at %x: offset %x+%x\n",
1341 p->p_pid, addr, off, vm_object.shadow_offset);
1342 #endif
1343
1344 addr = (long)vm_object.shadow;
1345 off += vm_object.shadow_offset;
1346 }
1347
1348 if (!vm_object.pager) {
1349 seterr("%u: no pager\n", p->p_pid);
1350 return 0;
1351 }
1352
1353 /* Find address in swap space */
1354 if (!KREAD(vm_object.pager, &pager, sizeof pager)) {
1355 setsyserr("vatosw: read pager");
1356 return 0;
1357 }
1358 if (pager.pg_type != PG_SWAP) {
1359 seterr("%u: weird pager\n", p->p_pid);
1360 return 0;
1361 }
1362
1363 /* Get swap pager data */
1364 if (!KREAD(pager.pg_data, &swpager, sizeof swpager)) {
1365 setsyserr("vatosw: read swpager");
1366 return 0;
1367 }
1368
1369 off += vm_object.paging_offset;
1370
1371 /* Read swap block array */
1372 if (!KREAD((long)swpager.sw_blocks +
1373 (off/dbtob(swpager.sw_bsize)) * sizeof swblock,
1374 &swblock, sizeof swblock)) {
1375 setsyserr("vatosw: read swblock");
1376 return 0;
1377 }
1378 swb->offset = dbtob(swblock.swb_block)+ (off % dbtob(swpager.sw_bsize));
1379 swb->size = dbtob(swpager.sw_bsize) - (off % dbtob(swpager.sw_bsize));
1380 return 1;
1381 }
1382
1383
1384 #define atop(x) (((unsigned)(x)) >> page_shift)
1385 #define vm_page_hash(object, offset) \
1386 (((unsigned)object+(unsigned)atop(offset))&vm_page_hash_mask)
1387
1388 static int
1389 findpage(object, offset, maddr)
1390 long object;
1391 long offset;
1392 vm_offset_t *maddr;
1393 {
1394 static long vm_page_hash_mask;
1395 static long vm_page_buckets;
1396 static long page_shift;
1397 queue_head_t bucket;
1398 struct vm_page mem;
1399 long addr, baddr;
1400
1401 if (vm_page_hash_mask == 0 && !KREAD(nl[X_VM_PAGE_HASH_MASK].n_value,
1402 &vm_page_hash_mask, sizeof (long))) {
1403 seterr("can't read vm_page_hash_mask");
1404 return 0;
1405 }
1406 if (page_shift == 0 && !KREAD(nl[X_PAGE_SHIFT].n_value,
1407 &page_shift, sizeof (long))) {
1408 seterr("can't read page_shift");
1409 return 0;
1410 }
1411 if (vm_page_buckets == 0 && !KREAD(nl[X_VM_PAGE_BUCKETS].n_value,
1412 &vm_page_buckets, sizeof (long))) {
1413 seterr("can't read vm_page_buckets");
1414 return 0;
1415 }
1416
1417 baddr = vm_page_buckets + vm_page_hash(object,offset) * sizeof(queue_head_t);
1418 if (!KREAD(baddr, &bucket, sizeof (bucket))) {
1419 seterr("can't read vm_page_bucket");
1420 return 0;
1421 }
1422
1423 addr = (long)bucket.next;
1424 while (addr != baddr) {
1425 if (!KREAD(addr, &mem, sizeof (mem))) {
1426 seterr("can't read vm_page");
1427 return 0;
1428 }
1429 if ((long)mem.object == object && mem.offset == offset) {
1430 *maddr = (long)mem.phys_addr;
1431 return 1;
1432 }
1433 addr = (long)mem.hashq.next;
1434 }
1435 return 0;
1436 }
1437 #endif /* NEWVM */
1438
1439 #include <varargs.h>
1440 static char errbuf[_POSIX2_LINE_MAX];
1441
1442 static void
1443 seterr(va_alist)
1444 va_dcl
1445 {
1446 char *fmt;
1447 va_list ap;
1448
1449 va_start(ap);
1450 fmt = va_arg(ap, char *);
1451 (void) vsnprintf(errbuf, _POSIX2_LINE_MAX, fmt, ap);
1452 #if DEBUG
1453 (void) vfprintf(stderr, fmt, ap);
1454 #endif
1455 va_end(ap);
1456 }
1457
1458 static void
1459 setsyserr(va_alist)
1460 va_dcl
1461 {
1462 char *fmt, *cp;
1463 va_list ap;
1464 extern int errno;
1465
1466 va_start(ap);
1467 fmt = va_arg(ap, char *);
1468 (void) vsnprintf(errbuf, _POSIX2_LINE_MAX, fmt, ap);
1469 for (cp=errbuf; *cp; cp++)
1470 ;
1471 snprintf(cp, _POSIX2_LINE_MAX - (cp - errbuf), ": %s", strerror(errno));
1472 va_end(ap);
1473 }
1474
1475 char *
1476 kvm_geterr()
1477 {
1478 return (errbuf);
1479 }
1480