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