Annotation of src/lib/libkvm/kvm_proc.c, Revision 1.63
1.63 ! yamt 1: /* $NetBSD: kvm_proc.c,v 1.62 2006/05/11 12:00:20 yamt Exp $ */
1.26 mycroft 2:
3: /*-
4: * Copyright (c) 1998 The NetBSD Foundation, Inc.
5: * All rights reserved.
6: *
7: * This code is derived from software contributed to The NetBSD Foundation
8: * by Charles M. Hannum.
9: *
10: * Redistribution and use in source and binary forms, with or without
11: * modification, are permitted provided that the following conditions
12: * are met:
13: * 1. Redistributions of source code must retain the above copyright
14: * notice, this list of conditions and the following disclaimer.
15: * 2. Redistributions in binary form must reproduce the above copyright
16: * notice, this list of conditions and the following disclaimer in the
17: * documentation and/or other materials provided with the distribution.
18: * 3. All advertising materials mentioning features or use of this software
19: * must display the following acknowledgement:
20: * This product includes software developed by the NetBSD
21: * Foundation, Inc. and its contributors.
22: * 4. Neither the name of The NetBSD Foundation nor the names of its
23: * contributors may be used to endorse or promote products derived
24: * from this software without specific prior written permission.
25: *
26: * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
27: * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
28: * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
29: * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
30: * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
31: * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
32: * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
33: * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
34: * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
35: * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
36: * POSSIBILITY OF SUCH DAMAGE.
37: */
1.16 thorpej 38:
1.1 cgd 39: /*-
40: * Copyright (c) 1989, 1992, 1993
41: * The Regents of the University of California. All rights reserved.
42: *
43: * This code is derived from software developed by the Computer Systems
44: * Engineering group at Lawrence Berkeley Laboratory under DARPA contract
45: * BG 91-66 and contributed to Berkeley.
46: *
47: * Redistribution and use in source and binary forms, with or without
48: * modification, are permitted provided that the following conditions
49: * are met:
50: * 1. Redistributions of source code must retain the above copyright
51: * notice, this list of conditions and the following disclaimer.
52: * 2. Redistributions in binary form must reproduce the above copyright
53: * notice, this list of conditions and the following disclaimer in the
54: * documentation and/or other materials provided with the distribution.
1.54 agc 55: * 3. Neither the name of the University nor the names of its contributors
1.1 cgd 56: * may be used to endorse or promote products derived from this software
57: * without specific prior written permission.
58: *
59: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
60: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
61: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
62: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
63: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
64: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
65: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
66: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
67: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
68: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
69: * SUCH DAMAGE.
70: */
71:
1.19 mikel 72: #include <sys/cdefs.h>
1.1 cgd 73: #if defined(LIBC_SCCS) && !defined(lint)
1.16 thorpej 74: #if 0
1.1 cgd 75: static char sccsid[] = "@(#)kvm_proc.c 8.3 (Berkeley) 9/23/93";
1.16 thorpej 76: #else
1.63 ! yamt 77: __RCSID("$NetBSD: kvm_proc.c,v 1.62 2006/05/11 12:00:20 yamt Exp $");
1.16 thorpej 78: #endif
1.1 cgd 79: #endif /* LIBC_SCCS and not lint */
80:
81: /*
82: * Proc traversal interface for kvm. ps and w are (probably) the exclusive
83: * users of this code, so we've factored it out into a separate module.
84: * Thus, we keep this grunge out of the other kvm applications (i.e.,
85: * most other applications are interested only in open/close/read/nlist).
86: */
87:
88: #include <sys/param.h>
89: #include <sys/user.h>
1.46 thorpej 90: #include <sys/lwp.h>
1.1 cgd 91: #include <sys/proc.h>
92: #include <sys/exec.h>
93: #include <sys/stat.h>
94: #include <sys/ioctl.h>
95: #include <sys/tty.h>
1.62 yamt 96: #include <sys/resourcevar.h>
1.63 ! yamt 97: #include <errno.h>
1.7 cgd 98: #include <stdlib.h>
1.52 ross 99: #include <stddef.h>
1.10 mycroft 100: #include <string.h>
1.1 cgd 101: #include <unistd.h>
102: #include <nlist.h>
103: #include <kvm.h>
104:
1.23 chs 105: #include <uvm/uvm_extern.h>
1.29 mrg 106: #include <uvm/uvm_amap.h>
1.23 chs 107:
1.1 cgd 108: #include <sys/sysctl.h>
109:
110: #include <limits.h>
111: #include <db.h>
112: #include <paths.h>
113:
114: #include "kvm_private.h"
115:
1.34 simonb 116: /*
117: * Common info from kinfo_proc and kinfo_proc2 used by helper routines.
118: */
119: struct miniproc {
120: struct vmspace *p_vmspace;
121: char p_stat;
122: struct proc *p_paddr;
123: pid_t p_pid;
124: };
125:
126: /*
127: * Convert from struct proc and kinfo_proc{,2} to miniproc.
128: */
129: #define PTOMINI(kp, p) \
1.48 enami 130: do { \
1.34 simonb 131: (p)->p_stat = (kp)->p_stat; \
132: (p)->p_pid = (kp)->p_pid; \
133: (p)->p_paddr = NULL; \
134: (p)->p_vmspace = (kp)->p_vmspace; \
135: } while (/*CONSTCOND*/0);
136:
137: #define KPTOMINI(kp, p) \
1.48 enami 138: do { \
1.34 simonb 139: (p)->p_stat = (kp)->kp_proc.p_stat; \
140: (p)->p_pid = (kp)->kp_proc.p_pid; \
141: (p)->p_paddr = (kp)->kp_eproc.e_paddr; \
142: (p)->p_vmspace = (kp)->kp_proc.p_vmspace; \
143: } while (/*CONSTCOND*/0);
144:
145: #define KP2TOMINI(kp, p) \
1.48 enami 146: do { \
1.34 simonb 147: (p)->p_stat = (kp)->p_stat; \
148: (p)->p_pid = (kp)->p_pid; \
149: (p)->p_paddr = (void *)(long)(kp)->p_paddr; \
150: (p)->p_vmspace = (void *)(long)(kp)->p_vmspace; \
151: } while (/*CONSTCOND*/0);
152:
153:
1.2 mycroft 154: #define KREAD(kd, addr, obj) \
1.34 simonb 155: (kvm_read(kd, addr, (obj), sizeof(*obj)) != sizeof(*obj))
1.2 mycroft 156:
1.34 simonb 157: /* XXX: What uses these two functions? */
158: char *_kvm_uread __P((kvm_t *, const struct proc *, u_long,
159: u_long *));
1.15 cgd 160: ssize_t kvm_uread __P((kvm_t *, const struct proc *, u_long, char *,
161: size_t));
162:
1.34 simonb 163: static char *_kvm_ureadm __P((kvm_t *, const struct miniproc *, u_long,
164: u_long *));
165: static ssize_t kvm_ureadm __P((kvm_t *, const struct miniproc *, u_long,
166: char *, size_t));
167:
168: static char **kvm_argv __P((kvm_t *, const struct miniproc *, u_long, int,
1.15 cgd 169: int));
1.53 christos 170: static int kvm_deadprocs __P((kvm_t *, int, int, u_long, u_long, int));
1.34 simonb 171: static char **kvm_doargv __P((kvm_t *, const struct miniproc *, int,
1.15 cgd 172: void (*)(struct ps_strings *, u_long *, int *)));
1.34 simonb 173: static char **kvm_doargv2 __P((kvm_t *, pid_t, int, int));
1.15 cgd 174: static int kvm_proclist __P((kvm_t *, int, int, struct proc *,
175: struct kinfo_proc *, int));
1.34 simonb 176: static int proc_verify __P((kvm_t *, u_long, const struct miniproc *));
1.15 cgd 177: static void ps_str_a __P((struct ps_strings *, u_long *, int *));
178: static void ps_str_e __P((struct ps_strings *, u_long *, int *));
1.2 mycroft 179:
1.34 simonb 180:
181: static char *
182: _kvm_ureadm(kd, p, va, cnt)
1.1 cgd 183: kvm_t *kd;
1.34 simonb 184: const struct miniproc *p;
1.1 cgd 185: u_long va;
186: u_long *cnt;
187: {
1.28 christos 188: int true = 1;
1.21 perry 189: u_long addr, head;
190: u_long offset;
1.1 cgd 191: struct vm_map_entry vme;
1.23 chs 192: struct vm_amap amap;
193: struct vm_anon *anonp, anon;
194: struct vm_page pg;
1.28 christos 195: u_long slot;
1.1 cgd 196:
1.36 tron 197: if (kd->swapspc == NULL) {
1.61 christos 198: kd->swapspc = _kvm_malloc(kd, (size_t)kd->nbpg);
1.36 tron 199: if (kd->swapspc == NULL)
1.48 enami 200: return (NULL);
1.5 deraadt 201: }
1.8 mycroft 202:
1.1 cgd 203: /*
204: * Look through the address map for the memory object
205: * that corresponds to the given virtual address.
206: * The header just has the entire valid range.
207: */
1.8 mycroft 208: head = (u_long)&p->p_vmspace->vm_map.header;
1.1 cgd 209: addr = head;
1.28 christos 210: while (true) {
1.2 mycroft 211: if (KREAD(kd, addr, &vme))
1.48 enami 212: return (NULL);
1.1 cgd 213:
1.23 chs 214: if (va >= vme.start && va < vme.end &&
215: vme.aref.ar_amap != NULL)
216: break;
217:
1.1 cgd 218: addr = (u_long)vme.next;
1.2 mycroft 219: if (addr == head)
1.48 enami 220: return (NULL);
1.1 cgd 221: }
1.2 mycroft 222:
1.1 cgd 223: /*
1.23 chs 224: * we found the map entry, now to find the object...
225: */
226: if (vme.aref.ar_amap == NULL)
1.48 enami 227: return (NULL);
1.23 chs 228:
229: addr = (u_long)vme.aref.ar_amap;
230: if (KREAD(kd, addr, &amap))
1.48 enami 231: return (NULL);
1.23 chs 232:
233: offset = va - vme.start;
1.29 mrg 234: slot = offset / kd->nbpg + vme.aref.ar_pageoff;
1.23 chs 235: /* sanity-check slot number */
1.48 enami 236: if (slot > amap.am_nslot)
237: return (NULL);
1.23 chs 238:
239: addr = (u_long)amap.am_anon + (offset / kd->nbpg) * sizeof(anonp);
240: if (KREAD(kd, addr, &anonp))
1.48 enami 241: return (NULL);
1.23 chs 242:
243: addr = (u_long)anonp;
244: if (KREAD(kd, addr, &anon))
1.48 enami 245: return (NULL);
1.23 chs 246:
1.59 jmc 247: addr = (u_long)anon.an_page;
1.23 chs 248: if (addr) {
249: if (KREAD(kd, addr, &pg))
1.48 enami 250: return (NULL);
1.23 chs 251:
1.34 simonb 252: if (pread(kd->pmfd, kd->swapspc, (size_t)kd->nbpg,
1.24 thorpej 253: (off_t)pg.phys_addr) != kd->nbpg)
1.48 enami 254: return (NULL);
255: } else {
1.60 yamt 256: if (kd->swfd < 0 ||
257: pread(kd->swfd, kd->swapspc, (size_t)kd->nbpg,
1.24 thorpej 258: (off_t)(anon.an_swslot * kd->nbpg)) != kd->nbpg)
1.48 enami 259: return (NULL);
1.23 chs 260: }
1.8 mycroft 261:
1.2 mycroft 262: /* Found the page. */
1.6 mycroft 263: offset %= kd->nbpg;
264: *cnt = kd->nbpg - offset;
1.28 christos 265: return (&kd->swapspc[(size_t)offset]);
1.2 mycroft 266: }
1.1 cgd 267:
1.34 simonb 268: char *
269: _kvm_uread(kd, p, va, cnt)
270: kvm_t *kd;
271: const struct proc *p;
272: u_long va;
273: u_long *cnt;
274: {
275: struct miniproc mp;
276:
277: PTOMINI(p, &mp);
278: return (_kvm_ureadm(kd, &mp, va, cnt));
279: }
280:
1.1 cgd 281: /*
282: * Read proc's from memory file into buffer bp, which has space to hold
283: * at most maxcnt procs.
284: */
285: static int
286: kvm_proclist(kd, what, arg, p, bp, maxcnt)
287: kvm_t *kd;
288: int what, arg;
289: struct proc *p;
290: struct kinfo_proc *bp;
291: int maxcnt;
292: {
1.21 perry 293: int cnt = 0;
1.46 thorpej 294: int nlwps;
295: struct kinfo_lwp *kl;
1.1 cgd 296: struct eproc eproc;
297: struct pgrp pgrp;
298: struct session sess;
299: struct tty tty;
300: struct proc proc;
301:
1.4 mycroft 302: for (; cnt < maxcnt && p != NULL; p = proc.p_list.le_next) {
1.1 cgd 303: if (KREAD(kd, (u_long)p, &proc)) {
1.41 sommerfe 304: _kvm_err(kd, kd->program, "can't read proc at %p", p);
1.1 cgd 305: return (-1);
306: }
307: if (KREAD(kd, (u_long)proc.p_cred, &eproc.e_pcred) == 0)
1.28 christos 308: if (KREAD(kd, (u_long)eproc.e_pcred.pc_ucred,
309: &eproc.e_ucred)) {
310: _kvm_err(kd, kd->program,
1.41 sommerfe 311: "can't read proc credentials at %p", p);
1.48 enami 312: return (-1);
1.28 christos 313: }
1.1 cgd 314:
1.48 enami 315: switch (what) {
1.31 simonb 316:
1.1 cgd 317: case KERN_PROC_PID:
318: if (proc.p_pid != (pid_t)arg)
319: continue;
320: break;
321:
322: case KERN_PROC_UID:
323: if (eproc.e_ucred.cr_uid != (uid_t)arg)
324: continue;
325: break;
326:
327: case KERN_PROC_RUID:
328: if (eproc.e_pcred.p_ruid != (uid_t)arg)
329: continue;
330: break;
331: }
332: /*
333: * We're going to add another proc to the set. If this
334: * will overflow the buffer, assume the reason is because
335: * nprocs (or the proc list) is corrupt and declare an error.
336: */
337: if (cnt >= maxcnt) {
338: _kvm_err(kd, kd->program, "nprocs corrupt");
339: return (-1);
340: }
341: /*
342: * gather eproc
343: */
344: eproc.e_paddr = p;
345: if (KREAD(kd, (u_long)proc.p_pgrp, &pgrp)) {
1.41 sommerfe 346: _kvm_err(kd, kd->program, "can't read pgrp at %p",
1.48 enami 347: proc.p_pgrp);
1.1 cgd 348: return (-1);
349: }
350: eproc.e_sess = pgrp.pg_session;
351: eproc.e_pgid = pgrp.pg_id;
352: eproc.e_jobc = pgrp.pg_jobc;
353: if (KREAD(kd, (u_long)pgrp.pg_session, &sess)) {
1.41 sommerfe 354: _kvm_err(kd, kd->program, "can't read session at %p",
1.48 enami 355: pgrp.pg_session);
1.1 cgd 356: return (-1);
357: }
358: if ((proc.p_flag & P_CONTROLT) && sess.s_ttyp != NULL) {
359: if (KREAD(kd, (u_long)sess.s_ttyp, &tty)) {
360: _kvm_err(kd, kd->program,
1.48 enami 361: "can't read tty at %p", sess.s_ttyp);
1.1 cgd 362: return (-1);
363: }
364: eproc.e_tdev = tty.t_dev;
365: eproc.e_tsess = tty.t_session;
366: if (tty.t_pgrp != NULL) {
367: if (KREAD(kd, (u_long)tty.t_pgrp, &pgrp)) {
368: _kvm_err(kd, kd->program,
1.48 enami 369: "can't read tpgrp at %p",
370: tty.t_pgrp);
1.1 cgd 371: return (-1);
372: }
373: eproc.e_tpgid = pgrp.pg_id;
374: } else
375: eproc.e_tpgid = -1;
376: } else
377: eproc.e_tdev = NODEV;
378: eproc.e_flag = sess.s_ttyvp ? EPROC_CTTY : 0;
1.33 simonb 379: eproc.e_sid = sess.s_sid;
1.1 cgd 380: if (sess.s_leader == p)
381: eproc.e_flag |= EPROC_SLEADER;
1.48 enami 382: /*
383: * Fill in the old-style proc.p_wmesg by copying the wmesg
1.55 wiz 384: * from the first available LWP.
1.46 thorpej 385: */
1.47 christos 386: kl = kvm_getlwps(kd, proc.p_pid,
1.57 atatat 387: (u_long)PTRTOUINT64(eproc.e_paddr),
1.46 thorpej 388: sizeof(struct kinfo_lwp), &nlwps);
389: if (kl) {
390: if (nlwps > 0) {
391: strcpy(eproc.e_wmesg, kl[0].l_wmesg);
392: }
393: }
1.34 simonb 394: (void)kvm_read(kd, (u_long)proc.p_vmspace, &eproc.e_vm,
395: sizeof(eproc.e_vm));
1.9 pk 396:
1.1 cgd 397: eproc.e_xsize = eproc.e_xrssize = 0;
398: eproc.e_xccount = eproc.e_xswrss = 0;
399:
400: switch (what) {
401:
402: case KERN_PROC_PGRP:
403: if (eproc.e_pgid != (pid_t)arg)
404: continue;
405: break;
406:
407: case KERN_PROC_TTY:
1.31 simonb 408: if ((proc.p_flag & P_CONTROLT) == 0 ||
1.48 enami 409: eproc.e_tdev != (dev_t)arg)
1.1 cgd 410: continue;
411: break;
412: }
1.25 perry 413: memcpy(&bp->kp_proc, &proc, sizeof(proc));
414: memcpy(&bp->kp_eproc, &eproc, sizeof(eproc));
1.1 cgd 415: ++bp;
416: ++cnt;
417: }
418: return (cnt);
419: }
420:
421: /*
422: * Build proc info array by reading in proc list from a crash dump.
423: * Return number of procs read. maxcnt is the max we will read.
424: */
425: static int
1.53 christos 426: kvm_deadprocs(kd, what, arg, a_allproc, a_zombproc, maxcnt)
1.1 cgd 427: kvm_t *kd;
428: int what, arg;
429: u_long a_allproc;
430: u_long a_zombproc;
431: int maxcnt;
432: {
1.21 perry 433: struct kinfo_proc *bp = kd->procbase;
1.53 christos 434: int acnt, zcnt;
1.1 cgd 435: struct proc *p;
436:
437: if (KREAD(kd, a_allproc, &p)) {
438: _kvm_err(kd, kd->program, "cannot read allproc");
439: return (-1);
440: }
441: acnt = kvm_proclist(kd, what, arg, p, bp, maxcnt);
442: if (acnt < 0)
443: return (acnt);
444:
445: if (KREAD(kd, a_zombproc, &p)) {
446: _kvm_err(kd, kd->program, "cannot read zombproc");
447: return (-1);
448: }
1.27 thorpej 449: zcnt = kvm_proclist(kd, what, arg, p, bp + acnt,
1.53 christos 450: maxcnt - acnt);
1.1 cgd 451: if (zcnt < 0)
452: zcnt = 0;
453:
454: return (acnt + zcnt);
455: }
456:
1.34 simonb 457: struct kinfo_proc2 *
458: kvm_getproc2(kd, op, arg, esize, cnt)
459: kvm_t *kd;
460: int op, arg;
461: size_t esize;
462: int *cnt;
463: {
464: size_t size;
465: int mib[6], st, nprocs;
1.46 thorpej 466: struct pstats pstats;
1.34 simonb 467:
468: if (ISSYSCTL(kd)) {
469: size = 0;
470: mib[0] = CTL_KERN;
471: mib[1] = KERN_PROC2;
472: mib[2] = op;
473: mib[3] = arg;
1.52 ross 474: mib[4] = (int)esize;
1.63 ! yamt 475: again:
1.34 simonb 476: mib[5] = 0;
1.52 ross 477: st = sysctl(mib, 6, NULL, &size, NULL, (size_t)0);
1.34 simonb 478: if (st == -1) {
479: _kvm_syserr(kd, kd->program, "kvm_getproc2");
1.48 enami 480: return (NULL);
1.34 simonb 481: }
482:
1.52 ross 483: mib[5] = (int) (size / esize);
1.61 christos 484: KVM_ALLOC(kd, procbase2, size);
1.52 ross 485: st = sysctl(mib, 6, kd->procbase2, &size, NULL, (size_t)0);
1.34 simonb 486: if (st == -1) {
1.63 ! yamt 487: if (errno == ENOMEM) {
! 488: goto again;
! 489: }
1.34 simonb 490: _kvm_syserr(kd, kd->program, "kvm_getproc2");
1.48 enami 491: return (NULL);
1.34 simonb 492: }
1.52 ross 493: nprocs = (int) (size / esize);
1.34 simonb 494: } else {
495: char *kp2c;
496: struct kinfo_proc *kp;
497: struct kinfo_proc2 kp2, *kp2p;
1.46 thorpej 498: struct kinfo_lwp *kl;
499: int i, nlwps;
1.34 simonb 500:
501: kp = kvm_getprocs(kd, op, arg, &nprocs);
502: if (kp == NULL)
1.48 enami 503: return (NULL);
1.34 simonb 504:
1.61 christos 505: size = nprocs * esize;
506: KVM_ALLOC(kd, procbase2, size);
1.39 christos 507: kp2c = (char *)(void *)kd->procbase2;
1.34 simonb 508: kp2p = &kp2;
509: for (i = 0; i < nprocs; i++, kp++) {
1.48 enami 510: kl = kvm_getlwps(kd, kp->kp_proc.p_pid,
1.57 atatat 511: (u_long)PTRTOUINT64(kp->kp_eproc.e_paddr),
1.46 thorpej 512: sizeof(struct kinfo_lwp), &nlwps);
513: /* We use kl[0] as the "representative" LWP */
1.34 simonb 514: memset(kp2p, 0, sizeof(kp2));
1.46 thorpej 515: kp2p->p_forw = kl[0].l_forw;
516: kp2p->p_back = kl[0].l_back;
1.57 atatat 517: kp2p->p_paddr = PTRTOUINT64(kp->kp_eproc.e_paddr);
1.46 thorpej 518: kp2p->p_addr = kl[0].l_addr;
1.57 atatat 519: kp2p->p_fd = PTRTOUINT64(kp->kp_proc.p_fd);
520: kp2p->p_cwdi = PTRTOUINT64(kp->kp_proc.p_cwdi);
521: kp2p->p_stats = PTRTOUINT64(kp->kp_proc.p_stats);
522: kp2p->p_limit = PTRTOUINT64(kp->kp_proc.p_limit);
523: kp2p->p_vmspace = PTRTOUINT64(kp->kp_proc.p_vmspace);
524: kp2p->p_sigacts = PTRTOUINT64(kp->kp_proc.p_sigacts);
525: kp2p->p_sess = PTRTOUINT64(kp->kp_eproc.e_sess);
1.34 simonb 526: kp2p->p_tsess = 0;
1.57 atatat 527: kp2p->p_ru = PTRTOUINT64(kp->kp_proc.p_ru);
1.34 simonb 528:
529: kp2p->p_eflag = 0;
530: kp2p->p_exitsig = kp->kp_proc.p_exitsig;
531: kp2p->p_flag = kp->kp_proc.p_flag;
532:
533: kp2p->p_pid = kp->kp_proc.p_pid;
534:
535: kp2p->p_ppid = kp->kp_eproc.e_ppid;
536: kp2p->p_sid = kp->kp_eproc.e_sid;
537: kp2p->p__pgid = kp->kp_eproc.e_pgid;
538:
1.51 dsl 539: kp2p->p_tpgid = -1 /* XXX NO_PGID! */;
1.34 simonb 540:
541: kp2p->p_uid = kp->kp_eproc.e_ucred.cr_uid;
542: kp2p->p_ruid = kp->kp_eproc.e_pcred.p_ruid;
1.50 atatat 543: kp2p->p_svuid = kp->kp_eproc.e_pcred.p_svuid;
1.34 simonb 544: kp2p->p_gid = kp->kp_eproc.e_ucred.cr_gid;
545: kp2p->p_rgid = kp->kp_eproc.e_pcred.p_rgid;
1.50 atatat 546: kp2p->p_svgid = kp->kp_eproc.e_pcred.p_svgid;
1.34 simonb 547:
1.39 christos 548: /*CONSTCOND*/
1.34 simonb 549: memcpy(kp2p->p_groups, kp->kp_eproc.e_ucred.cr_groups,
1.48 enami 550: MIN(sizeof(kp2p->p_groups),
551: sizeof(kp->kp_eproc.e_ucred.cr_groups)));
1.34 simonb 552: kp2p->p_ngroups = kp->kp_eproc.e_ucred.cr_ngroups;
553:
554: kp2p->p_jobc = kp->kp_eproc.e_jobc;
555: kp2p->p_tdev = kp->kp_eproc.e_tdev;
556: kp2p->p_tpgid = kp->kp_eproc.e_tpgid;
1.57 atatat 557: kp2p->p_tsess = PTRTOUINT64(kp->kp_eproc.e_tsess);
1.34 simonb 558:
559: kp2p->p_estcpu = kp->kp_proc.p_estcpu;
560: kp2p->p_rtime_sec = kp->kp_proc.p_estcpu;
561: kp2p->p_rtime_usec = kp->kp_proc.p_estcpu;
562: kp2p->p_cpticks = kp->kp_proc.p_cpticks;
563: kp2p->p_pctcpu = kp->kp_proc.p_pctcpu;
1.46 thorpej 564: kp2p->p_swtime = kl[0].l_swtime;
565: kp2p->p_slptime = kl[0].l_slptime;
1.35 thorpej 566: #if 0 /* XXX thorpej */
1.34 simonb 567: kp2p->p_schedflags = kp->kp_proc.p_schedflags;
1.35 thorpej 568: #else
569: kp2p->p_schedflags = 0;
570: #endif
1.34 simonb 571:
572: kp2p->p_uticks = kp->kp_proc.p_uticks;
573: kp2p->p_sticks = kp->kp_proc.p_sticks;
574: kp2p->p_iticks = kp->kp_proc.p_iticks;
575:
1.57 atatat 576: kp2p->p_tracep = PTRTOUINT64(kp->kp_proc.p_tracep);
1.34 simonb 577: kp2p->p_traceflag = kp->kp_proc.p_traceflag;
578:
1.46 thorpej 579: kp2p->p_holdcnt = kl[0].l_holdcnt;
1.34 simonb 580:
1.48 enami 581: memcpy(&kp2p->p_siglist,
582: &kp->kp_proc.p_sigctx.ps_siglist,
583: sizeof(ki_sigset_t));
584: memcpy(&kp2p->p_sigmask,
585: &kp->kp_proc.p_sigctx.ps_sigmask,
586: sizeof(ki_sigset_t));
587: memcpy(&kp2p->p_sigignore,
588: &kp->kp_proc.p_sigctx.ps_sigignore,
589: sizeof(ki_sigset_t));
590: memcpy(&kp2p->p_sigcatch,
591: &kp->kp_proc.p_sigctx.ps_sigcatch,
592: sizeof(ki_sigset_t));
1.34 simonb 593:
594: kp2p->p_stat = kp->kp_proc.p_stat;
1.46 thorpej 595: kp2p->p_priority = kl[0].l_priority;
596: kp2p->p_usrpri = kl[0].l_usrpri;
1.34 simonb 597: kp2p->p_nice = kp->kp_proc.p_nice;
598:
599: kp2p->p_xstat = kp->kp_proc.p_xstat;
600: kp2p->p_acflag = kp->kp_proc.p_acflag;
601:
1.39 christos 602: /*CONSTCOND*/
1.34 simonb 603: strncpy(kp2p->p_comm, kp->kp_proc.p_comm,
1.48 enami 604: MIN(sizeof(kp2p->p_comm),
605: sizeof(kp->kp_proc.p_comm)));
1.34 simonb 606:
1.48 enami 607: strncpy(kp2p->p_wmesg, kp->kp_eproc.e_wmesg,
608: sizeof(kp2p->p_wmesg));
1.46 thorpej 609: kp2p->p_wchan = kl[0].l_wchan;
1.48 enami 610: strncpy(kp2p->p_login, kp->kp_eproc.e_login,
611: sizeof(kp2p->p_login));
1.34 simonb 612:
613: kp2p->p_vm_rssize = kp->kp_eproc.e_xrssize;
614: kp2p->p_vm_tsize = kp->kp_eproc.e_vm.vm_tsize;
615: kp2p->p_vm_dsize = kp->kp_eproc.e_vm.vm_dsize;
616: kp2p->p_vm_ssize = kp->kp_eproc.e_vm.vm_ssize;
617:
1.39 christos 618: kp2p->p_eflag = (int32_t)kp->kp_eproc.e_flag;
1.34 simonb 619:
1.46 thorpej 620: kp2p->p_realflag = kp->kp_proc.p_flag;
621: kp2p->p_nlwps = kp->kp_proc.p_nlwps;
622: kp2p->p_nrlwps = kp->kp_proc.p_nrlwps;
623: kp2p->p_realstat = kp->kp_proc.p_stat;
624:
1.48 enami 625: if (P_ZOMBIE(&kp->kp_proc) ||
1.46 thorpej 626: kp->kp_proc.p_stats == NULL ||
1.48 enami 627: KREAD(kd, (u_long)kp->kp_proc.p_stats, &pstats)) {
1.34 simonb 628: kp2p->p_uvalid = 0;
629: } else {
630: kp2p->p_uvalid = 1;
631:
1.39 christos 632: kp2p->p_ustart_sec = (u_int32_t)
1.46 thorpej 633: pstats.p_start.tv_sec;
1.39 christos 634: kp2p->p_ustart_usec = (u_int32_t)
1.46 thorpej 635: pstats.p_start.tv_usec;
1.39 christos 636:
637: kp2p->p_uutime_sec = (u_int32_t)
1.46 thorpej 638: pstats.p_ru.ru_utime.tv_sec;
1.39 christos 639: kp2p->p_uutime_usec = (u_int32_t)
1.46 thorpej 640: pstats.p_ru.ru_utime.tv_usec;
1.39 christos 641: kp2p->p_ustime_sec = (u_int32_t)
1.46 thorpej 642: pstats.p_ru.ru_stime.tv_sec;
1.39 christos 643: kp2p->p_ustime_usec = (u_int32_t)
1.46 thorpej 644: pstats.p_ru.ru_stime.tv_usec;
1.34 simonb 645:
1.46 thorpej 646: kp2p->p_uru_maxrss = pstats.p_ru.ru_maxrss;
647: kp2p->p_uru_ixrss = pstats.p_ru.ru_ixrss;
648: kp2p->p_uru_idrss = pstats.p_ru.ru_idrss;
649: kp2p->p_uru_isrss = pstats.p_ru.ru_isrss;
650: kp2p->p_uru_minflt = pstats.p_ru.ru_minflt;
651: kp2p->p_uru_majflt = pstats.p_ru.ru_majflt;
652: kp2p->p_uru_nswap = pstats.p_ru.ru_nswap;
653: kp2p->p_uru_inblock = pstats.p_ru.ru_inblock;
654: kp2p->p_uru_oublock = pstats.p_ru.ru_oublock;
655: kp2p->p_uru_msgsnd = pstats.p_ru.ru_msgsnd;
656: kp2p->p_uru_msgrcv = pstats.p_ru.ru_msgrcv;
657: kp2p->p_uru_nsignals = pstats.p_ru.ru_nsignals;
658: kp2p->p_uru_nvcsw = pstats.p_ru.ru_nvcsw;
659: kp2p->p_uru_nivcsw = pstats.p_ru.ru_nivcsw;
1.34 simonb 660:
1.39 christos 661: kp2p->p_uctime_sec = (u_int32_t)
1.46 thorpej 662: (pstats.p_cru.ru_utime.tv_sec +
663: pstats.p_cru.ru_stime.tv_sec);
1.39 christos 664: kp2p->p_uctime_usec = (u_int32_t)
1.46 thorpej 665: (pstats.p_cru.ru_utime.tv_usec +
666: pstats.p_cru.ru_stime.tv_usec);
1.34 simonb 667: }
668:
669: memcpy(kp2c, &kp2, esize);
670: kp2c += esize;
671: }
672: }
673: *cnt = nprocs;
674: return (kd->procbase2);
1.46 thorpej 675: }
676:
677: struct kinfo_lwp *
678: kvm_getlwps(kd, pid, paddr, esize, cnt)
679: kvm_t *kd;
680: int pid;
681: u_long paddr;
682: size_t esize;
683: int *cnt;
684: {
685: size_t size;
1.52 ross 686: int mib[5], nlwps;
687: ssize_t st;
1.46 thorpej 688: struct kinfo_lwp *kl;
689:
690: if (ISSYSCTL(kd)) {
691: size = 0;
692: mib[0] = CTL_KERN;
693: mib[1] = KERN_LWP;
694: mib[2] = pid;
1.52 ross 695: mib[3] = (int)esize;
1.46 thorpej 696: mib[4] = 0;
1.52 ross 697: st = sysctl(mib, 5, NULL, &size, NULL, (size_t)0);
1.46 thorpej 698: if (st == -1) {
699: _kvm_syserr(kd, kd->program, "kvm_getlwps");
1.48 enami 700: return (NULL);
1.46 thorpej 701: }
702:
1.52 ross 703: mib[4] = (int) (size / esize);
1.61 christos 704: KVM_ALLOC(kd, lwpbase, size);
1.52 ross 705: st = sysctl(mib, 5, kd->lwpbase, &size, NULL, (size_t)0);
1.46 thorpej 706: if (st == -1) {
707: _kvm_syserr(kd, kd->program, "kvm_getlwps");
1.48 enami 708: return (NULL);
1.46 thorpej 709: }
1.52 ross 710: nlwps = (int) (size / esize);
1.46 thorpej 711: } else {
712: /* grovel through the memory image */
713: struct proc p;
714: struct lwp l;
715: u_long laddr;
716: int i;
717:
718: st = kvm_read(kd, paddr, &p, sizeof(p));
719: if (st == -1) {
720: _kvm_syserr(kd, kd->program, "kvm_getlwps");
1.48 enami 721: return (NULL);
1.46 thorpej 722: }
723:
724: nlwps = p.p_nlwps;
1.61 christos 725: size = nlwps * sizeof(*kd->lwpbase);
726: KVM_ALLOC(kd, lwpbase, size);
1.57 atatat 727: laddr = (u_long)PTRTOUINT64(p.p_lwps.lh_first);
1.46 thorpej 728: for (i = 0; (i < nlwps) && (laddr != 0); i++) {
729: st = kvm_read(kd, laddr, &l, sizeof(l));
730: if (st == -1) {
731: _kvm_syserr(kd, kd->program, "kvm_getlwps");
1.48 enami 732: return (NULL);
1.46 thorpej 733: }
734: kl = &kd->lwpbase[i];
735: kl->l_laddr = laddr;
1.57 atatat 736: kl->l_forw = PTRTOUINT64(l.l_forw);
737: kl->l_back = PTRTOUINT64(l.l_back);
738: kl->l_addr = PTRTOUINT64(l.l_addr);
1.46 thorpej 739: kl->l_lid = l.l_lid;
740: kl->l_flag = l.l_flag;
741: kl->l_swtime = l.l_swtime;
742: kl->l_slptime = l.l_slptime;
743: kl->l_schedflags = 0; /* XXX */
744: kl->l_holdcnt = l.l_holdcnt;
745: kl->l_priority = l.l_priority;
746: kl->l_usrpri = l.l_usrpri;
747: kl->l_stat = l.l_stat;
1.57 atatat 748: kl->l_wchan = PTRTOUINT64(l.l_wchan);
1.46 thorpej 749: if (l.l_wmesg)
750: (void)kvm_read(kd, (u_long)l.l_wmesg,
1.52 ross 751: kl->l_wmesg, (size_t)WMESGLEN);
1.46 thorpej 752: kl->l_cpuid = KI_NOCPU;
1.57 atatat 753: laddr = (u_long)PTRTOUINT64(l.l_sibling.le_next);
1.46 thorpej 754: }
755: }
756:
757: *cnt = nlwps;
1.48 enami 758: return (kd->lwpbase);
1.34 simonb 759: }
760:
1.1 cgd 761: struct kinfo_proc *
762: kvm_getprocs(kd, op, arg, cnt)
763: kvm_t *kd;
764: int op, arg;
765: int *cnt;
766: {
1.7 cgd 767: size_t size;
768: int mib[4], st, nprocs;
1.1 cgd 769:
1.34 simonb 770: if (ISKMEM(kd)) {
1.1 cgd 771: size = 0;
772: mib[0] = CTL_KERN;
773: mib[1] = KERN_PROC;
774: mib[2] = op;
775: mib[3] = arg;
1.52 ross 776: st = sysctl(mib, 4, NULL, &size, NULL, (size_t)0);
1.1 cgd 777: if (st == -1) {
778: _kvm_syserr(kd, kd->program, "kvm_getprocs");
1.48 enami 779: return (NULL);
1.1 cgd 780: }
1.61 christos 781: KVM_ALLOC(kd, procbase, size);
1.52 ross 782: st = sysctl(mib, 4, kd->procbase, &size, NULL, (size_t)0);
1.1 cgd 783: if (st == -1) {
784: _kvm_syserr(kd, kd->program, "kvm_getprocs");
1.48 enami 785: return (NULL);
1.1 cgd 786: }
787: if (size % sizeof(struct kinfo_proc) != 0) {
788: _kvm_err(kd, kd->program,
1.42 enami 789: "proc size mismatch (%lu total, %lu chunks)",
790: (u_long)size, (u_long)sizeof(struct kinfo_proc));
1.48 enami 791: return (NULL);
1.1 cgd 792: }
1.52 ross 793: nprocs = (int) (size / sizeof(struct kinfo_proc));
1.34 simonb 794: } else if (ISSYSCTL(kd)) {
795: _kvm_err(kd, kd->program, "kvm_open called with KVM_NO_FILES, "
796: "can't use kvm_getprocs");
1.48 enami 797: return (NULL);
1.1 cgd 798: } else {
1.53 christos 799: struct nlist nl[4], *p;
1.1 cgd 800:
1.56 christos 801: (void)memset(nl, 0, sizeof(nl));
1.1 cgd 802: nl[0].n_name = "_nprocs";
803: nl[1].n_name = "_allproc";
1.53 christos 804: nl[2].n_name = "_zombproc";
805: nl[3].n_name = NULL;
1.1 cgd 806:
807: if (kvm_nlist(kd, nl) != 0) {
808: for (p = nl; p->n_type != 0; ++p)
1.48 enami 809: continue;
1.1 cgd 810: _kvm_err(kd, kd->program,
1.48 enami 811: "%s: no such symbol", p->n_name);
812: return (NULL);
1.1 cgd 813: }
814: if (KREAD(kd, nl[0].n_value, &nprocs)) {
815: _kvm_err(kd, kd->program, "can't read nprocs");
1.48 enami 816: return (NULL);
1.1 cgd 817: }
1.61 christos 818: size = nprocs * sizeof(*kd->procbase);
819: KVM_ALLOC(kd, procbase, size);
1.1 cgd 820: nprocs = kvm_deadprocs(kd, op, arg, nl[1].n_value,
1.53 christos 821: nl[2].n_value, nprocs);
1.32 chs 822: if (nprocs < 0)
1.48 enami 823: return (NULL);
1.1 cgd 824: #ifdef notdef
825: size = nprocs * sizeof(struct kinfo_proc);
826: (void)realloc(kd->procbase, size);
827: #endif
828: }
829: *cnt = nprocs;
830: return (kd->procbase);
831: }
832:
833: void *
834: _kvm_realloc(kd, p, n)
835: kvm_t *kd;
836: void *p;
837: size_t n;
838: {
1.34 simonb 839: void *np = realloc(p, n);
1.1 cgd 840:
1.36 tron 841: if (np == NULL)
1.1 cgd 842: _kvm_err(kd, kd->program, "out of memory");
843: return (np);
844: }
845:
846: /*
847: * Read in an argument vector from the user address space of process p.
1.31 simonb 848: * addr if the user-space base address of narg null-terminated contiguous
1.1 cgd 849: * strings. This is used to read in both the command arguments and
850: * environment strings. Read at most maxcnt characters of strings.
851: */
852: static char **
853: kvm_argv(kd, p, addr, narg, maxcnt)
854: kvm_t *kd;
1.34 simonb 855: const struct miniproc *p;
1.21 perry 856: u_long addr;
857: int narg;
858: int maxcnt;
859: {
860: char *np, *cp, *ep, *ap;
1.28 christos 861: u_long oaddr = (u_long)~0L;
862: u_long len;
863: size_t cc;
1.21 perry 864: char **argv;
1.1 cgd 865:
866: /*
1.58 toshii 867: * Check that there aren't an unreasonable number of arguments,
1.1 cgd 868: * and that the address is in user space.
869: */
1.18 gwr 870: if (narg > ARG_MAX || addr < kd->min_uva || addr >= kd->max_uva)
1.48 enami 871: return (NULL);
1.1 cgd 872:
1.36 tron 873: if (kd->argv == NULL) {
1.1 cgd 874: /*
875: * Try to avoid reallocs.
876: */
877: kd->argc = MAX(narg + 1, 32);
1.61 christos 878: kd->argv = _kvm_malloc(kd, kd->argc * sizeof(*kd->argv));
1.36 tron 879: if (kd->argv == NULL)
1.48 enami 880: return (NULL);
1.1 cgd 881: } else if (narg + 1 > kd->argc) {
882: kd->argc = MAX(2 * kd->argc, narg + 1);
1.61 christos 883: kd->argv = _kvm_realloc(kd, kd->argv, kd->argc *
1.48 enami 884: sizeof(*kd->argv));
1.36 tron 885: if (kd->argv == NULL)
1.48 enami 886: return (NULL);
1.1 cgd 887: }
1.36 tron 888: if (kd->argspc == NULL) {
1.61 christos 889: kd->argspc = _kvm_malloc(kd, (size_t)kd->nbpg);
1.36 tron 890: if (kd->argspc == NULL)
1.48 enami 891: return (NULL);
1.61 christos 892: kd->argspc_len = kd->nbpg;
1.1 cgd 893: }
1.36 tron 894: if (kd->argbuf == NULL) {
1.61 christos 895: kd->argbuf = _kvm_malloc(kd, (size_t)kd->nbpg);
1.36 tron 896: if (kd->argbuf == NULL)
1.48 enami 897: return (NULL);
1.10 mycroft 898: }
899: cc = sizeof(char *) * narg;
1.34 simonb 900: if (kvm_ureadm(kd, p, addr, (void *)kd->argv, cc) != cc)
1.48 enami 901: return (NULL);
1.10 mycroft 902: ap = np = kd->argspc;
1.1 cgd 903: argv = kd->argv;
904: len = 0;
905: /*
906: * Loop over pages, filling in the argument vector.
907: */
1.36 tron 908: while (argv < kd->argv + narg && *argv != NULL) {
1.10 mycroft 909: addr = (u_long)*argv & ~(kd->nbpg - 1);
910: if (addr != oaddr) {
1.34 simonb 911: if (kvm_ureadm(kd, p, addr, kd->argbuf,
1.28 christos 912: (size_t)kd->nbpg) != kd->nbpg)
1.48 enami 913: return (NULL);
1.10 mycroft 914: oaddr = addr;
915: }
916: addr = (u_long)*argv & (kd->nbpg - 1);
1.28 christos 917: cp = kd->argbuf + (size_t)addr;
918: cc = kd->nbpg - (size_t)addr;
919: if (maxcnt > 0 && cc > (size_t)(maxcnt - len))
920: cc = (size_t)(maxcnt - len);
1.10 mycroft 921: ep = memchr(cp, '\0', cc);
1.36 tron 922: if (ep != NULL)
1.10 mycroft 923: cc = ep - cp + 1;
1.61 christos 924: if (len + cc > kd->argspc_len) {
1.52 ross 925: ptrdiff_t off;
1.21 perry 926: char **pp;
927: char *op = kd->argspc;
1.1 cgd 928:
1.61 christos 929: kd->argspc_len *= 2;
930: kd->argspc = _kvm_realloc(kd, kd->argspc,
931: kd->argspc_len);
1.36 tron 932: if (kd->argspc == NULL)
1.48 enami 933: return (NULL);
1.1 cgd 934: /*
935: * Adjust argv pointers in case realloc moved
936: * the string space.
937: */
938: off = kd->argspc - op;
1.13 mycroft 939: for (pp = kd->argv; pp < argv; pp++)
1.1 cgd 940: *pp += off;
1.12 mycroft 941: ap += off;
942: np += off;
1.1 cgd 943: }
1.10 mycroft 944: memcpy(np, cp, cc);
945: np += cc;
1.1 cgd 946: len += cc;
1.36 tron 947: if (ep != NULL) {
1.10 mycroft 948: *argv++ = ap;
949: ap = np;
950: } else
951: *argv += cc;
1.1 cgd 952: if (maxcnt > 0 && len >= maxcnt) {
953: /*
954: * We're stopping prematurely. Terminate the
1.10 mycroft 955: * current string.
1.1 cgd 956: */
1.36 tron 957: if (ep == NULL) {
1.10 mycroft 958: *np = '\0';
1.14 mycroft 959: *argv++ = ap;
1.10 mycroft 960: }
961: break;
1.1 cgd 962: }
963: }
1.10 mycroft 964: /* Make sure argv is terminated. */
1.36 tron 965: *argv = NULL;
1.10 mycroft 966: return (kd->argv);
1.1 cgd 967: }
968:
969: static void
970: ps_str_a(p, addr, n)
971: struct ps_strings *p;
972: u_long *addr;
973: int *n;
974: {
1.48 enami 975:
1.1 cgd 976: *addr = (u_long)p->ps_argvstr;
977: *n = p->ps_nargvstr;
978: }
979:
980: static void
981: ps_str_e(p, addr, n)
982: struct ps_strings *p;
983: u_long *addr;
984: int *n;
985: {
1.48 enami 986:
1.1 cgd 987: *addr = (u_long)p->ps_envstr;
988: *n = p->ps_nenvstr;
989: }
990:
991: /*
992: * Determine if the proc indicated by p is still active.
993: * This test is not 100% foolproof in theory, but chances of
994: * being wrong are very low.
995: */
996: static int
997: proc_verify(kd, kernp, p)
998: kvm_t *kd;
999: u_long kernp;
1.34 simonb 1000: const struct miniproc *p;
1.1 cgd 1001: {
1002: struct proc kernproc;
1003:
1004: /*
1005: * Just read in the whole proc. It's not that big relative
1006: * to the cost of the read system call.
1007: */
1.34 simonb 1008: if (kvm_read(kd, kernp, &kernproc, sizeof(kernproc)) !=
1.1 cgd 1009: sizeof(kernproc))
1.48 enami 1010: return (0);
1.1 cgd 1011: return (p->p_pid == kernproc.p_pid &&
1.48 enami 1012: (kernproc.p_stat != SZOMB || p->p_stat == SZOMB));
1.1 cgd 1013: }
1014:
1015: static char **
1.34 simonb 1016: kvm_doargv(kd, p, nchr, info)
1.1 cgd 1017: kvm_t *kd;
1.34 simonb 1018: const struct miniproc *p;
1.1 cgd 1019: int nchr;
1.10 mycroft 1020: void (*info)(struct ps_strings *, u_long *, int *);
1.1 cgd 1021: {
1.21 perry 1022: char **ap;
1.1 cgd 1023: u_long addr;
1024: int cnt;
1025: struct ps_strings arginfo;
1026:
1027: /*
1028: * Pointers are stored at the top of the user stack.
1029: */
1.18 gwr 1030: if (p->p_stat == SZOMB)
1.48 enami 1031: return (NULL);
1.52 ross 1032: cnt = (int)kvm_ureadm(kd, p, kd->usrstack - sizeof(arginfo),
1.28 christos 1033: (void *)&arginfo, sizeof(arginfo));
1.18 gwr 1034: if (cnt != sizeof(arginfo))
1.48 enami 1035: return (NULL);
1.1 cgd 1036:
1037: (*info)(&arginfo, &addr, &cnt);
1.3 mycroft 1038: if (cnt == 0)
1.48 enami 1039: return (NULL);
1.1 cgd 1040: ap = kvm_argv(kd, p, addr, cnt, nchr);
1041: /*
1042: * For live kernels, make sure this process didn't go away.
1043: */
1.36 tron 1044: if (ap != NULL && ISALIVE(kd) &&
1.34 simonb 1045: !proc_verify(kd, (u_long)p->p_paddr, p))
1.36 tron 1046: ap = NULL;
1.1 cgd 1047: return (ap);
1048: }
1049:
1050: /*
1051: * Get the command args. This code is now machine independent.
1052: */
1053: char **
1054: kvm_getargv(kd, kp, nchr)
1055: kvm_t *kd;
1056: const struct kinfo_proc *kp;
1057: int nchr;
1058: {
1.34 simonb 1059: struct miniproc p;
1060:
1061: KPTOMINI(kp, &p);
1062: return (kvm_doargv(kd, &p, nchr, ps_str_a));
1.1 cgd 1063: }
1064:
1065: char **
1066: kvm_getenvv(kd, kp, nchr)
1067: kvm_t *kd;
1068: const struct kinfo_proc *kp;
1069: int nchr;
1070: {
1.34 simonb 1071: struct miniproc p;
1072:
1073: KPTOMINI(kp, &p);
1074: return (kvm_doargv(kd, &p, nchr, ps_str_e));
1075: }
1076:
1077: static char **
1078: kvm_doargv2(kd, pid, type, nchr)
1079: kvm_t *kd;
1080: pid_t pid;
1081: int type;
1082: int nchr;
1083: {
1084: size_t bufs;
1.39 christos 1085: int narg, mib[4];
1.61 christos 1086: size_t newargspc_len;
1.34 simonb 1087: char **ap, *bp, *endp;
1088:
1089: /*
1.58 toshii 1090: * Check that there aren't an unreasonable number of arguments.
1.34 simonb 1091: */
1092: if (nchr > ARG_MAX)
1.48 enami 1093: return (NULL);
1.34 simonb 1094:
1095: if (nchr == 0)
1096: nchr = ARG_MAX;
1097:
1098: /* Get number of strings in argv */
1099: mib[0] = CTL_KERN;
1100: mib[1] = KERN_PROC_ARGS;
1101: mib[2] = pid;
1102: mib[3] = type == KERN_PROC_ARGV ? KERN_PROC_NARGV : KERN_PROC_NENV;
1103: bufs = sizeof(narg);
1.52 ross 1104: if (sysctl(mib, 4, &narg, &bufs, NULL, (size_t)0) == -1)
1.48 enami 1105: return (NULL);
1.34 simonb 1106:
1.36 tron 1107: if (kd->argv == NULL) {
1.34 simonb 1108: /*
1109: * Try to avoid reallocs.
1110: */
1111: kd->argc = MAX(narg + 1, 32);
1.61 christos 1112: kd->argv = _kvm_malloc(kd, kd->argc * sizeof(*kd->argv));
1.36 tron 1113: if (kd->argv == NULL)
1.48 enami 1114: return (NULL);
1.34 simonb 1115: } else if (narg + 1 > kd->argc) {
1116: kd->argc = MAX(2 * kd->argc, narg + 1);
1.61 christos 1117: kd->argv = _kvm_realloc(kd, kd->argv, kd->argc *
1.48 enami 1118: sizeof(*kd->argv));
1.36 tron 1119: if (kd->argv == NULL)
1.48 enami 1120: return (NULL);
1.34 simonb 1121: }
1122:
1.61 christos 1123: newargspc_len = MIN(nchr, ARG_MAX);
1124: KVM_ALLOC(kd, argspc, newargspc_len);
1125: memset(kd->argspc, 0, (size_t)kd->argspc_len); /* XXX necessary? */
1.34 simonb 1126:
1127: mib[0] = CTL_KERN;
1128: mib[1] = KERN_PROC_ARGS;
1129: mib[2] = pid;
1130: mib[3] = type;
1.61 christos 1131: bufs = kd->argspc_len;
1.52 ross 1132: if (sysctl(mib, 4, kd->argspc, &bufs, NULL, (size_t)0) == -1)
1.48 enami 1133: return (NULL);
1.34 simonb 1134:
1135: bp = kd->argspc;
1.61 christos 1136: bp[kd->argspc_len-1] = '\0'; /* make sure the string ends with nul */
1.34 simonb 1137: ap = kd->argv;
1138: endp = bp + MIN(nchr, bufs);
1139:
1140: while (bp < endp) {
1141: *ap++ = bp;
1.48 enami 1142: /*
1143: * XXX: don't need following anymore, or stick check
1144: * for max argc in above while loop?
1145: */
1.34 simonb 1146: if (ap >= kd->argv + kd->argc) {
1147: kd->argc *= 2;
1148: kd->argv = _kvm_realloc(kd, kd->argv,
1149: kd->argc * sizeof(*kd->argv));
1.44 jdolecek 1150: ap = kd->argv;
1.34 simonb 1151: }
1152: bp += strlen(bp) + 1;
1153: }
1154: *ap = NULL;
1.48 enami 1155:
1.34 simonb 1156: return (kd->argv);
1157: }
1158:
1159: char **
1160: kvm_getargv2(kd, kp, nchr)
1161: kvm_t *kd;
1162: const struct kinfo_proc2 *kp;
1163: int nchr;
1164: {
1.48 enami 1165:
1.34 simonb 1166: return (kvm_doargv2(kd, kp->p_pid, KERN_PROC_ARGV, nchr));
1167: }
1168:
1169: char **
1170: kvm_getenvv2(kd, kp, nchr)
1171: kvm_t *kd;
1172: const struct kinfo_proc2 *kp;
1173: int nchr;
1174: {
1.48 enami 1175:
1.34 simonb 1176: return (kvm_doargv2(kd, kp->p_pid, KERN_PROC_ENV, nchr));
1.1 cgd 1177: }
1178:
1179: /*
1180: * Read from user space. The user context is given by p.
1181: */
1.34 simonb 1182: static ssize_t
1183: kvm_ureadm(kd, p, uva, buf, len)
1.1 cgd 1184: kvm_t *kd;
1.34 simonb 1185: const struct miniproc *p;
1.21 perry 1186: u_long uva;
1187: char *buf;
1188: size_t len;
1.1 cgd 1189: {
1.21 perry 1190: char *cp;
1.1 cgd 1191:
1192: cp = buf;
1193: while (len > 0) {
1.28 christos 1194: size_t cc;
1.21 perry 1195: char *dp;
1.15 cgd 1196: u_long cnt;
1.8 mycroft 1197:
1.34 simonb 1198: dp = _kvm_ureadm(kd, p, uva, &cnt);
1.36 tron 1199: if (dp == NULL) {
1.41 sommerfe 1200: _kvm_err(kd, 0, "invalid address (%lx)", uva);
1.48 enami 1201: return (0);
1.8 mycroft 1202: }
1.28 christos 1203: cc = (size_t)MIN(cnt, len);
1.25 perry 1204: memcpy(cp, dp, cc);
1.1 cgd 1205: cp += cc;
1206: uva += cc;
1207: len -= cc;
1208: }
1209: return (ssize_t)(cp - buf);
1.34 simonb 1210: }
1211:
1212: ssize_t
1213: kvm_uread(kd, p, uva, buf, len)
1214: kvm_t *kd;
1215: const struct proc *p;
1.48 enami 1216: u_long uva;
1.34 simonb 1217: char *buf;
1218: size_t len;
1219: {
1220: struct miniproc mp;
1221:
1222: PTOMINI(p, &mp);
1223: return (kvm_ureadm(kd, &mp, uva, buf, len));
1.1 cgd 1224: }
CVSweb <webmaster@jp.NetBSD.org>