date and time created 90/05/15 09:10:25 by bostic
[unix-history] / usr / src / lib / libkvm / kvm_proc.c
CommitLineData
41a4fbbe
MT
1/*
2 * Copyright (c) 1989 The Regents of the University of California.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms is permitted
6 * provided that all copyright information, including this notice,
7 * is retained in all such forms, and that any documentation,
8 * advertising or other materials related to such distribution and
9 * use acknowledge that the software was
10 * developed by the University of California, Berkeley. The name
11 * of the University may not be used to endorse or promote products
12 * derived from this software without specific prior written permission.
13 *
14 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
15 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
16 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
17 */
18
19
20#include <machine/pte.h>
21#include <sys/param.h>
22#include <sys/user.h>
23#include <sys/proc.h>
24#include <sys/file.h>
25#include <sys/text.h>
26#include <sys/stat.h>
27#include <sys/time.h>
28#include <sys/vmmac.h>
29#include <sys/ioctl.h>
30#include <sys/tty.h>
0e005c87 31#include <kvm.h>
41a4fbbe 32#include <ctype.h>
0e005c87 33#include <cencode.h>
41a4fbbe
MT
34#include <nlist.h>
35#include <pwd.h>
36#include <strings.h>
37#include <ndbm.h>
38#include <limits.h>
39#include <paths.h>
0e005c87 40#include <stdio.h>
41a4fbbe
MT
41
42/*
43 * files
44 */
45static char *unixf, *memf, *kmemf, *swapf;
46static int unixx, mem, kmem, swap;
0e005c87 47static DBM *db;
41a4fbbe
MT
48/*
49 * flags
50 */
51static int deadkernel;
52static int kvminit = 0;
53static int kvmfilesopen = 0;
54/*
55 * state
56 */
57static struct kinfo_proc *kvmprocbase, *kvmprocptr;
58static int kvmnprocs;
41a4fbbe
MT
59/*
60 * u. buffer
61 */
62static union {
63 struct user user;
64 char upages[UPAGES][NBPG];
65} user;
66/*
67 * random other stuff
68 */
69static struct pte *Usrptmap, *usrpt;
70static int dmmin, dmmax;
71static struct pte *Sysmap;
72static int Syssize;
73static int pcbpf;
0e005c87
MT
74static int argaddr0; /* XXX */
75static int argaddr1;
41a4fbbe 76static int nswap;
0e005c87 77static char *tmp;
41a4fbbe 78
0e005c87 79#define basename(cp) ((tmp=rindex((cp), '/')) ? tmp+1 : (cp))
41a4fbbe 80#define MAXSYMSIZE 256
41a4fbbe
MT
81
82static struct nlist nl[] = {
83 { "_Usrptmap" },
84#define X_USRPTMAP 0
85 { "_usrpt" },
86#define X_USRPT 1
87 { "_nswap" },
88#define X_NSWAP 2
89 { "_dmmin" },
90#define X_DMMIN 3
91 { "_dmmax" },
92#define X_DMMAX 4
93 /*
94 * everything here and down, only if a dead kernel
95 */
96 { "_Sysmap" },
97#define X_SYSMAP 5
98#define X_DEADKERNEL X_SYSMAP
99 { "_Syssize" },
100#define X_SYSSIZE 6
101 { "_allproc" },
102#define X_ALLPROC 7
103 { "_zombproc" },
104#define X_ZOMBPROC 8
105 { "_nproc" },
106#define X_NPROC 9
107 { "" },
108};
109
110static char *savestr();
111
0e005c87
MT
112/*
113 * returns 0 if files were opened now,
114 * 1 if files were already opened,
115 * -1 if files could not be opened.
116 */
41a4fbbe 117kvm_openfiles(uf, mf, sf)
0e005c87
MT
118 char *uf, *mf, *sf;
119{
120 if (kvmfilesopen)
121 return (1);
41a4fbbe
MT
122 unixx = mem = kmem = swap = -1;
123 unixf = (uf == NULL) ? _PATH_UNIX : uf;
124 memf = (mf == NULL) ? _PATH_MEM : mf;
125
126 if ((unixx = open(unixf, O_RDONLY, 0)) == -1) {
127 setsyserr("can't open %s", unixf);
128 goto failed;
129 }
130 if ((mem = open(memf, O_RDONLY, 0)) == -1) {
131 setsyserr("can't open %s", memf);
132 goto failed;
133 }
134 if (sf != NULL)
135 swapf = sf;
136 if (mf != NULL) {
137 deadkernel++;
138 kmemf = mf;
139 kmem = mem;
140 swap = -1;
141 } else {
142 kmemf = _PATH_KMEM;
143 if ((kmem = open(kmemf, O_RDONLY, 0)) == -1) {
144 setsyserr("can't open %s", kmemf);
145 goto failed;
146 }
147 swapf = (sf == NULL) ? _PATH_DRUM : sf;
148 /*
149 * live kernel - avoid looking up nlist entries
150 * past X_DEADKERNEL.
151 */
152 nl[X_DEADKERNEL].n_name = "";
153 }
154 if (swapf != NULL && ((swap = open(swapf, O_RDONLY, 0)) == -1)) {
155 seterr("can't open %s", swapf);
156 goto failed;
157 }
158 kvmfilesopen++;
159 return (0);
160failed:
161 kvm_close();
162 return (-1);
163}
164
0e005c87
MT
165static
166kvm_init(uf, mf, sf)
167 char *uf, *mf, *sf;
168{
169 if (kvmfilesopen == 0 && kvm_openfiles(NULL, NULL, NULL) == -1)
170 return (-1);
171 if (getkvars() == -1)
172 return (-1);
173 kvminit = 1;
174
175 return (0);
176}
177
41a4fbbe
MT
178kvm_close()
179{
0e005c87 180 if (unixx != -1) {
41a4fbbe 181 close(unixx);
0e005c87
MT
182 unixx = -1;
183 }
184 if (kmem != -1) {
185 if (kmem != mem)
186 close(kmem);
187 /* otherwise kmem is a copy of mem, and will be closed below */
188 kmem = -1;
189 }
190 if (mem != -1) {
41a4fbbe 191 close(mem);
0e005c87
MT
192 mem = -1;
193 }
194 if (swap != -1) {
41a4fbbe 195 close(swap);
0e005c87
MT
196 swap = -1;
197 }
198 if (db != NULL) {
41a4fbbe 199 dbm_close(db);
0e005c87
MT
200 db = NULL;
201 }
41a4fbbe
MT
202 kvminit = 0;
203 kvmfilesopen = 0;
0e005c87
MT
204 deadkernel = 0;
205 if (Sysmap) {
206 free(Sysmap);
207 Sysmap = NULL;
208 }
41a4fbbe
MT
209}
210
211kvm_nlist(nl)
212 struct nlist *nl;
213{
214 datum key, data;
215 char dbname[MAXPATHLEN];
216 char dbversion[LINE_MAX];
217 char kversion[LINE_MAX];
218 int dbversionlen;
219 char symbuf[MAXSYMSIZE+1];
220 struct nlist nbuf, *n;
221 int num, did;
222
223 if (kvmfilesopen == 0 && kvm_openfiles(NULL, NULL, NULL) == -1)
224 return (-1);
225 if (deadkernel)
226 goto hard2;
41a4fbbe 227 /*
0e005c87 228 * initialize key datum
41a4fbbe
MT
229 */
230 key.dptr = symbuf;
231 symbuf[0] = KVMDB_NLIST;
0e005c87
MT
232
233 if (db != NULL)
234 goto win; /* off to the races */
41a4fbbe 235 /*
0e005c87
MT
236 * open database
237 */
238 sprintf(dbname, "%s/kvm_%s", KVMDBDIR, basename(unixf));
239 if ((db = dbm_open(dbname, O_RDONLY, 0)) == NULL)
240 goto hard2;
241 /*
242 * read version out of database
41a4fbbe
MT
243 */
244 bcopy("VERSION", symbuf+1, sizeof ("VERSION")-1);
245 key.dsize = (sizeof ("VERSION") - 1) + 1;
246 data = dbm_fetch(db, key);
247 if (data.dptr == NULL)
248 goto hard1;
249 bcopy(data.dptr, dbversion, data.dsize);
250 dbversionlen = data.dsize;
251 /*
252 * read version string from kernel memory
253 */
254 bcopy("_version", symbuf+1, sizeof ("_version")-1);
255 key.dsize = (sizeof ("_version")-1) + 1;
256 data = dbm_fetch(db, key);
257 if (data.dptr == NULL)
258 goto hard1;
259 if (data.dsize != sizeof (struct nlist))
260 goto hard1;
261 bcopy(data.dptr, &nbuf, sizeof (struct nlist));
262 lseek(kmem, nbuf.n_value, 0);
263 if (read(kmem, kversion, dbversionlen) != dbversionlen)
264 goto hard1;
265 /*
266 * if they match, we win - otherwise do it the hard way
267 */
268 if (bcmp(dbversion, kversion, dbversionlen) != 0)
269 goto hard1;
270 /*
271 * getem from the database.
272 */
273win:
274 num = did = 0;
275 for (n = nl; n->n_name && n->n_name[0]; n++, num++) {
276 int len;
277 /*
0e005c87 278 * clear out fields from users buffer
41a4fbbe
MT
279 */
280 n->n_type = 0;
281 n->n_other = 0;
282 n->n_desc = 0;
283 n->n_value = 0;
284 /*
285 * query db
286 */
287 if ((len = strlen(n->n_name)) > MAXSYMSIZE) {
288 seterr("kvm_nlist: symbol too large");
289 return (-1);
290 }
291 strcpy(symbuf+1, n->n_name);
292 key.dsize = len + 1;
293 data = dbm_fetch(db, key);
294 if (data.dptr == NULL || data.dsize != sizeof (struct nlist))
295 continue;
296 bcopy(data.dptr, &nbuf, sizeof (struct nlist));
297 n->n_value = nbuf.n_value;
298 n->n_type = nbuf.n_type;
299 n->n_desc = nbuf.n_desc;
300 n->n_other = nbuf.n_other;
301 did++;
302 }
303 return (num - did);
304hard1:
305 dbm_close(db);
306 db = NULL;
307hard2:
0e005c87 308 return (nlist(unixf, nl)); /* XXX seterr if -1 */
41a4fbbe
MT
309}
310
311kvm_getprocs(what, arg)
312{
0e005c87
MT
313 if (kvminit == 0 && kvm_init(NULL, NULL, NULL, 0) == -1)
314 return (NULL);
41a4fbbe
MT
315 if (!deadkernel) {
316 int ret, copysize;
317
318 if ((ret = getkerninfo(what, NULL, NULL, arg)) == -1) {
319 setsyserr("can't get estimate for kerninfo");
320 return (-1);
321 }
322 copysize = ret;
323 if ((kvmprocbase = (struct kinfo_proc *)malloc(copysize))
324 == NULL) {
325 seterr("out of memory");
326 return (-1);
327 }
328 if ((ret = getkerninfo(what, kvmprocbase, &copysize,
329 arg)) == -1) {
330 setsyserr("can't get proc list");
331 return (-1);
332 }
333 if (copysize % sizeof (struct kinfo_proc)) {
3ba498c1
MT
334 seterr("proc size mismatch (kinfo_proc: %d)",
335 sizeof (struct kinfo_proc));
41a4fbbe
MT
336 return (-1);
337 }
338 kvmnprocs = copysize / sizeof (struct kinfo_proc);
339 } else {
41a4fbbe
MT
340 int nproc;
341
342 if (kvm_read(nl[X_NPROC].n_value, &nproc, sizeof (int)) !=
343 sizeof (int)) {
344 seterr("can't read nproc");
345 return (-1);
346 }
347 if ((kvmprocbase = (struct kinfo_proc *)
348 malloc(nproc * sizeof (struct kinfo_proc))) == NULL) {
0e005c87
MT
349 seterr("out of memory (addr: %x nproc = %d)",
350 nl[X_NPROC].n_value, nproc);
41a4fbbe
MT
351 return (-1);
352 }
353 kvmnprocs = kvm_doprocs(what, arg, kvmprocbase);
354 realloc(kvmprocbase, kvmnprocs * sizeof (struct kinfo_proc));
355 }
356 kvmprocptr = kvmprocbase;
357
358 return (kvmnprocs);
359}
360
361/*
362 * XXX - should NOT give up so easily - especially since the kernel
363 * may be corrupt (it died). Should gather as much information as possible.
364 * Follows proc ptrs instead of reading table since table may go
365 * away soon.
366 */
367static
368kvm_doprocs(what, arg, buff)
369 int what, arg;
370 char *buff;
371{
372 struct proc *p, proc;
373 register char *bp = buff;
374 int i = 0;
375 int doingzomb = 0;
376 struct eproc eproc;
377 struct pgrp pgrp;
378 struct session sess;
379 struct tty tty;
380 struct text text;
381
382 /* allproc */
383 if (kvm_read(nl[X_ALLPROC].n_value, &p,
384 sizeof (struct proc *)) != sizeof (struct proc *)) {
385 seterr("can't read allproc");
386 return (-1);
387 }
388
389again:
390 for (; p; p = proc.p_nxt) {
391 if (kvm_read(p, &proc, sizeof (struct proc)) !=
392 sizeof (struct proc)) {
393 seterr("can't read proc at %x", p);
394 return (-1);
395 }
396 switch(ki_op(what)) {
397
398 case KINFO_PROC_PID:
399 if (proc.p_pid != (pid_t)arg)
400 continue;
401 break;
402
403
404 case KINFO_PROC_UID:
405 if (proc.p_uid != (uid_t)arg)
406 continue;
407 break;
408
409 case KINFO_PROC_RUID:
410 if (proc.p_ruid != (uid_t)arg)
411 continue;
412 break;
413 }
414 /*
415 * gather eproc
416 */
417 eproc.e_paddr = p;
418 if (kvm_read(proc.p_pgrp, &pgrp, sizeof (struct pgrp)) !=
419 sizeof (struct pgrp)) {
420 seterr("can't read pgrp at %x", proc.p_pgrp);
421 return (-1);
422 }
423 eproc.e_sess = pgrp.pg_session;
424 eproc.e_pgid = pgrp.pg_id;
425 eproc.e_jobc = pgrp.pg_jobc;
426 if (kvm_read(pgrp.pg_session, &sess, sizeof (struct session))
427 != sizeof (struct session)) {
428 seterr("can't read session at %x", pgrp.pg_session);
429 return (-1);
430 }
431 if ((proc.p_flag&SCTTY) && sess.s_ttyp != NULL) {
432 if (kvm_read(sess.s_ttyp, &tty, sizeof (struct tty))
433 != sizeof (struct tty)) {
434 seterr("can't read tty at %x", sess.s_ttyp);
435 return (-1);
436 }
437 eproc.e_tdev = tty.t_dev;
438 eproc.e_tsess = tty.t_session;
439 if (tty.t_pgrp != NULL) {
440 if (kvm_read(tty.t_pgrp, &pgrp, sizeof (struct
441 pgrp)) != sizeof (struct pgrp)) {
442 seterr("can't read tpgrp at &x",
443 tty.t_pgrp);
444 return (-1);
445 }
446 eproc.e_tpgid = pgrp.pg_id;
447 } else
448 eproc.e_tpgid = -1;
449 } else
450 eproc.e_tdev = NODEV;
451 if (proc.p_wmesg)
452 kvm_read(proc.p_wmesg, eproc.e_wmesg, WMESGLEN);
453 if (proc.p_textp) {
454 kvm_read(proc.p_textp, &text, sizeof (text));
455 eproc.e_xsize = text.x_size;
456 eproc.e_xrssize = text.x_rssize;
457 eproc.e_xccount = text.x_ccount;
458 eproc.e_xswrss = text.x_swrss;
459 } else {
460 eproc.e_xsize = eproc.e_xrssize =
461 eproc.e_xccount = eproc.e_xswrss = 0;
462 }
463
464 switch(ki_op(what)) {
465
466 case KINFO_PROC_PGRP:
467 if (eproc.e_pgid != (pid_t)arg)
468 continue;
469 break;
470
471 case KINFO_PROC_TTY:
472 if ((proc.p_flag&SCTTY) == 0 ||
473 eproc.e_tdev != (dev_t)arg)
474 continue;
475 break;
476 }
477
478 i++;
479 bcopy(&proc, bp, sizeof (struct proc));
480 bp += sizeof (struct proc);
481 bcopy(&eproc, bp, sizeof (struct eproc));
482 bp+= sizeof (struct eproc);
483 }
484 if (!doingzomb) {
485 /* zombproc */
486 if (kvm_read(nl[X_ZOMBPROC].n_value, &p,
487 sizeof (struct proc *)) != sizeof (struct proc *)) {
488 seterr("can't read zombproc");
489 return (-1);
490 }
491 doingzomb = 1;
492 goto again;
493 }
494
495 return (i);
496}
497
498
499struct proc *
500kvm_nextproc()
501{
502
503 if (!kvmprocbase && kvm_getprocs(0, 0) == -1)
504 return (NULL);
505 if (kvmprocptr >= (kvmprocbase + kvmnprocs)) {
506 seterr("end of proc list");
507 return (NULL);
508 }
509 return((struct proc *)(kvmprocptr++));
510}
511
512struct eproc *
513kvm_geteproc(p)
514 struct proc *p;
515{
516 return ((struct eproc *)(((char *)p) + sizeof (struct proc)));
517}
518
519kvm_setproc()
520{
521
522 kvmprocptr = kvmprocbase;
523}
524
525kvm_freeprocs()
526{
527
528 if (kvmprocbase) {
529 free(kvmprocbase);
530 kvmprocbase = NULL;
531 }
532}
533
534struct user *
535kvm_getu(p)
536 struct proc *p;
537{
538 struct pte *pteaddr, apte;
0e005c87 539 struct pte arguutl[UPAGES+(CLSIZE*2)];
41a4fbbe
MT
540 register int i;
541 int ncl;
542
543 if (kvminit == 0 && kvm_init(NULL, NULL, NULL, 0) == -1)
544 return (NULL);
0e005c87
MT
545 if (p->p_stat == SZOMB) {
546 seterr("zombie process");
41a4fbbe 547 return (NULL);
0e005c87 548 }
41a4fbbe 549 if ((p->p_flag & SLOAD) == 0) {
0e005c87
MT
550 if (swap < 0) {
551 seterr("no swap");
41a4fbbe 552 return (NULL);
0e005c87 553 }
41a4fbbe
MT
554 (void) lseek(swap, (long)dtob(p->p_swaddr), 0);
555 if (read(swap, (char *)&user.user, sizeof (struct user)) !=
556 sizeof (struct user)) {
557 seterr("can't read u for pid %d from %s\n",
558 p->p_pid, swapf);
559 return (NULL);
560 }
561 pcbpf = 0;
0e005c87
MT
562 argaddr0 = 0;
563 argaddr1 = 0;
41a4fbbe
MT
564 return (&user.user);
565 }
566 pteaddr = &Usrptmap[btokmx(p->p_p0br) + p->p_szpt - 1];
567 klseek(kmem, (long)pteaddr, 0);
568 if (read(kmem, (char *)&apte, sizeof(apte)) != sizeof(apte)) {
569 seterr("can't read indir pte to get u for pid %d from %s",
570 p->p_pid, kmemf);
571 return (NULL);
572 }
573 lseek(mem,
0e005c87 574 (long)ctob(apte.pg_pfnum+1) - (UPAGES+(CLSIZE*2)) * sizeof (struct pte),
41a4fbbe
MT
575 0);
576 if (read(mem, (char *)arguutl, sizeof(arguutl)) != sizeof(arguutl)) {
577 seterr("can't read page table for u of pid %d from %s",
578 p->p_pid, memf);
579 return (NULL);
580 }
581 if (arguutl[0].pg_fod == 0 && arguutl[0].pg_pfnum)
0e005c87 582 argaddr0 = ctob(arguutl[0].pg_pfnum);
41a4fbbe 583 else
0e005c87
MT
584 argaddr0 = 0;
585 if (arguutl[CLSIZE*1].pg_fod == 0 && arguutl[CLSIZE*1].pg_pfnum)
586 argaddr1 = ctob(arguutl[CLSIZE*1].pg_pfnum);
587 else
588 argaddr1 = 0;
589 pcbpf = arguutl[CLSIZE*2].pg_pfnum;
41a4fbbe
MT
590 ncl = (sizeof (struct user) + NBPG*CLSIZE - 1) / (NBPG*CLSIZE);
591 while (--ncl >= 0) {
592 i = ncl * CLSIZE;
0e005c87 593 lseek(mem, (long)ctob(arguutl[(CLSIZE*2)+i].pg_pfnum), 0);
41a4fbbe
MT
594 if (read(mem, user.upages[i], CLSIZE*NBPG) != CLSIZE*NBPG) {
595 seterr("can't read page %d of u of pid %d from %s",
596 arguutl[CLSIZE+i].pg_pfnum, p->p_pid, memf);
597 return(NULL);
598 }
599 }
600 return (&user.user);
601}
602
603char *
604kvm_getargs(p, up)
605 struct proc *p;
606 struct user *up;
607{
0e005c87 608 char cmdbuf[CLSIZE*NBPG*2];
41a4fbbe 609 union {
0e005c87
MT
610 char argc[CLSIZE*NBPG*2];
611 int argi[CLSIZE*NBPG*2/sizeof (int)];
41a4fbbe
MT
612 } argspac;
613 register char *cp;
614 register int *ip;
615 char c;
616 int nbad;
617 struct dblock db;
618 char *file;
619
0e005c87 620 if (up == NULL || p->p_pid == 0 || p->p_pid == 2)
41a4fbbe 621 goto retucomm;
0e005c87 622 if ((p->p_flag & SLOAD) == 0 || argaddr1 == 0) {
41a4fbbe
MT
623 if (swap < 0)
624 goto retucomm;
625 vstodb(0, CLSIZE, &up->u_smap, &db, 1);
626 (void) lseek(swap, (long)dtob(db.db_base), 0);
0e005c87
MT
627 if (read(swap, (char *)&argspac.argc[NBPG*CLSIZE],
628 NBPG*CLSIZE) != NBPG*CLSIZE)
629 goto bad;
630 vstodb(1, CLSIZE, &up->u_smap, &db, 1);
631 (void) lseek(swap, (long)dtob(db.db_base), 0);
632 if (read(swap, (char *)&argspac.argc[0],
633 NBPG*CLSIZE) != NBPG*CLSIZE)
41a4fbbe
MT
634 goto bad;
635 file = swapf;
636 } else {
0e005c87
MT
637 if (argaddr0) {
638 lseek(mem, (long)argaddr0, 0);
639 if (read(mem, (char *)&argspac, NBPG*CLSIZE)
640 != NBPG*CLSIZE)
641 goto bad;
642 } else
643 bzero(&argspac, NBPG*CLSIZE);
644 lseek(mem, (long)argaddr1, 0);
645 if (read(mem, &argspac.argc[NBPG*CLSIZE], NBPG*CLSIZE)
646 != NBPG*CLSIZE)
41a4fbbe
MT
647 goto bad;
648 file = memf;
649 }
0e005c87 650 ip = &argspac.argi[CLSIZE*NBPG*2/sizeof (int)];
41a4fbbe
MT
651 ip -= 2; /* last arg word and .long 0 */
652 while (*--ip) {
653 if (ip == argspac.argi)
654 goto retucomm;
655 }
656 *(char *)ip = ' ';
657 ip++;
658 nbad = 0;
0e005c87 659 for (cp = (char *)ip; cp < &argspac.argc[CLSIZE*NBPG*2]; cp++) {
41a4fbbe
MT
660 c = *cp & 0177;
661 if (c == 0)
662 *cp = ' ';
663 else if (c < ' ' || c > 0176) {
664 if (++nbad >= 5*(0+1)) { /* eflg -> 0 XXX */
665 *cp++ = ' ';
666 break;
667 }
668 *cp = '?';
669 } else if (0 == 0 && c == '=') { /* eflg -> 0 XXX */
670 while (*--cp != ' ')
671 if (cp <= (char *)ip)
672 break;
673 break;
674 }
675 }
676 *cp = 0;
677 while (*--cp == ' ')
678 *cp = 0;
679 cp = (char *)ip;
0e005c87 680 (void) strncpy(cmdbuf, cp, &argspac.argc[CLSIZE*NBPG*2] - cp);
41a4fbbe
MT
681 if (cp[0] == '-' || cp[0] == '?' || cp[0] <= ' ') {
682 (void) strcat(cmdbuf, " (");
683 (void) strncat(cmdbuf, p->p_comm, sizeof(p->p_comm));
684 (void) strcat(cmdbuf, ")");
685 }
686 return (cmdbuf);
687
688bad:
689 seterr("error locating command name for pid %d from %s\n",
690 p->p_pid, file);
691retucomm:
692 (void) strcpy(cmdbuf, " (");
693 (void) strncat(cmdbuf, p->p_comm, sizeof (p->p_comm));
694 (void) strcat(cmdbuf, ")");
695 return (cmdbuf);
696}
697
698
699static
700getkvars()
701{
702
703 if (kvm_nlist(nl) == -1)
704 return (-1);
705 if (deadkernel) {
706 /* We must do the sys map first because klseek uses it */
707 long addr;
708
709 Syssize = nl[X_SYSSIZE].n_value;
710 Sysmap = (struct pte *)
711 calloc((unsigned) Syssize, sizeof (struct pte));
712 if (Sysmap == NULL) {
713 seterr("out of space for Sysmap");
714 return (-1);
715 }
716 addr = (long) nl[X_SYSMAP].n_value;
717 addr &= ~KERNBASE;
718 (void) lseek(kmem, addr, 0);
719 if (read(kmem, (char *) Sysmap, Syssize * sizeof (struct pte))
720 != Syssize * sizeof (struct pte)) {
721 seterr("can't read Sysmap");
722 return (-1);
723 }
724 }
725 usrpt = (struct pte *)nl[X_USRPT].n_value;
726 Usrptmap = (struct pte *)nl[X_USRPTMAP].n_value;
727 if (kvm_read((long)nl[X_NSWAP].n_value, &nswap, sizeof (long)) !=
728 sizeof (long)) {
729 seterr("can't read nswap");
730 return (-1);
731 }
732 if (kvm_read((long)nl[X_DMMIN].n_value, &dmmin, sizeof (long)) !=
733 sizeof (long)) {
734 seterr("can't read dmmin");
735 return (-1);
736 }
737 if (kvm_read((long)nl[X_DMMAX].n_value, &dmmax, sizeof (long)) !=
738 sizeof (long)) {
739 seterr("can't read dmmax");
740 return (-1);
741 }
742 return (0);
743}
744
745kvm_read(loc, buf, len)
746 unsigned long loc;
747 char *buf;
748{
0e005c87
MT
749 if (kvmfilesopen == 0 && kvm_openfiles(NULL, NULL, NULL) == -1)
750 return (-1);
41a4fbbe
MT
751 if (loc & KERNBASE) {
752 klseek(kmem, loc, 0);
753 if (read(kmem, buf, len) != len) {
754 seterr("error reading kmem at %x\n", loc);
755 return (-1);
756 }
757 } else {
758 lseek(mem, loc, 0);
759 if (read(mem, buf, len) != len) {
760 seterr("error reading mem at %x\n", loc);
761 return (-1);
762 }
763 }
764 return (len);
765}
766
767static
768klseek(fd, loc, off)
769 int fd;
0e005c87 770 off_t loc;
41a4fbbe
MT
771 int off;
772{
0e005c87 773
41a4fbbe 774 if (deadkernel) {
0e005c87
MT
775 off_t vtophys();
776
41a4fbbe
MT
777 if ((loc = vtophys(loc)) == -1)
778 return;
779 }
0e005c87 780 (void) lseek(fd, (off_t)loc, off);
41a4fbbe
MT
781}
782
783/*
784 * Given a base/size pair in virtual swap area,
785 * return a physical base/size pair which is the
786 * (largest) initial, physically contiguous block.
787 */
788static
789vstodb(vsbase, vssize, dmp, dbp, rev)
790 register int vsbase;
791 int vssize;
792 struct dmap *dmp;
793 register struct dblock *dbp;
794{
795 register int blk = dmmin;
796 register swblk_t *ip = dmp->dm_map;
797
798 vsbase = ctod(vsbase);
799 vssize = ctod(vssize);
800 if (vsbase < 0 || vsbase + vssize > dmp->dm_size)
801 /*panic("vstodb")*/;
802 while (vsbase >= blk) {
803 vsbase -= blk;
804 if (blk < dmmax)
805 blk *= 2;
806 ip++;
807 }
808 if (*ip <= 0 || *ip + blk > nswap)
809 /*panic("vstodb")*/;
810 dbp->db_size = MIN(vssize, blk - vsbase);
811 dbp->db_base = *ip + (rev ? blk - (vsbase + dbp->db_size) : vsbase);
812}
813
814/*
815 * This routine was stolen from adb to simulate memory management
816 * on the VAX.
817 */
818static off_t
819vtophys(loc)
820 long loc;
821{
822 register p;
823 off_t newloc;
824
825 newloc = loc & ~KERNBASE;
826 p = btop(newloc);
827 if ((loc & KERNBASE) == 0) {
828 seterr("vtophys: translating non-kernel address");
829 return((off_t) -1);
830 }
831 if (p >= Syssize) {
832 seterr("vtophys: page out of bound (%d>=%d)", p, Syssize);
833 return((off_t) -1);
834 }
835 if (Sysmap[p].pg_v == 0 &&
836 (Sysmap[p].pg_fod || Sysmap[p].pg_pfnum == 0)) {
837 seterr("vtophys: page not valid");
838 return((off_t) -1);
839 }
840 loc = (long) (ptob(Sysmap[p].pg_pfnum) + (loc & PGOFSET));
841 return(loc);
842}
843
844#include <varargs.h>
845static char errbuf[LINE_MAX];
846
847static
848seterr(va_alist)
849 va_dcl
850{
851 char *fmt;
852 va_list ap;
853
854 va_start(ap);
855 fmt = va_arg(ap, char *);
856 (void) vsprintf(errbuf, fmt, ap);
857 va_end(ap);
858}
859
860static
861setsyserr(va_alist)
862 va_dcl
863{
864 char *fmt, *cp;
865 va_list ap;
866 extern errno;
867
868 va_start(ap);
869 fmt = va_arg(ap, char *);
870 (void) vsprintf(errbuf, fmt, ap);
871 for (cp=errbuf; *cp; cp++)
872 ;
873 sprintf(cp, ": %s", strerror(errno));
874 va_end(ap);
875}
876
877char *
878kvm_geterr()
879{
880
881 return (errbuf);
882}