[BACK]Return to kvm_proc.c CVS log [TXT][DIR] Up to [cvs.NetBSD.org] / src / lib / libkvm

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>