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