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