Merge branch 'vendor/FILE'
[dragonfly.git] / lib / libkvm / kvm_proc.c
1 /*-
2  * Copyright (c) 1989, 1992, 1993
3  *      The Regents of the University of California.  All rights reserved.
4  *
5  * This code is derived from software developed by the Computer Systems
6  * Engineering group at Lawrence Berkeley Laboratory under DARPA contract
7  * BG 91-66 and contributed to Berkeley.
8  *
9  * Redistribution and use in source and binary forms, with or without
10  * modification, are permitted provided that the following conditions
11  * are met:
12  * 1. Redistributions of source code must retain the above copyright
13  *    notice, this list of conditions and the following disclaimer.
14  * 2. Redistributions in binary form must reproduce the above copyright
15  *    notice, this list of conditions and the following disclaimer in the
16  *    documentation and/or other materials provided with the distribution.
17  * 3. Neither the name of the University nor the names of its contributors
18  *    may be used to endorse or promote products derived from this software
19  *    without specific prior written permission.
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31  * SUCH DAMAGE.
32  *
33  * $FreeBSD: src/lib/libkvm/kvm_proc.c,v 1.25.2.3 2002/08/24 07:27:46 kris Exp $
34  *
35  * @(#)kvm_proc.c       8.3 (Berkeley) 9/23/93
36  */
37
38 /*
39  * Proc traversal interface for kvm.  ps and w are (probably) the exclusive
40  * users of this code, so we've factored it out into a separate module.
41  * Thus, we keep this grunge out of the other kvm applications (i.e.,
42  * most other applications are interested only in open/close/read/nlist).
43  */
44
45 #include <sys/user.h>   /* MUST BE FIRST */
46 #include <sys/conf.h>
47 #include <sys/param.h>
48 #include <sys/proc.h>
49 #include <sys/exec.h>
50 #include <sys/stat.h>
51 #include <sys/globaldata.h>
52 #include <sys/ioctl.h>
53 #include <sys/tty.h>
54 #include <sys/file.h>
55 #include <sys/jail.h>
56 #include <stdio.h>
57 #include <stdlib.h>
58 #include <stddef.h>
59 #include <unistd.h>
60 #include <nlist.h>
61 #include <kvm.h>
62
63 #include <vm/vm.h>
64 #include <vm/vm_param.h>
65 #include <vm/swap_pager.h>
66
67 #include <sys/sysctl.h>
68
69 #include <limits.h>
70 #include <memory.h>
71 #include <paths.h>
72
73 #include "kvm_private.h"
74
75 #if used
76 static char *
77 kvm_readswap(kvm_t *kd, const struct proc *p, u_long va, u_long *cnt)
78 {
79 #if defined(__FreeBSD__) || defined(__DragonFly__)
80         /* XXX Stubbed out, our vm system is differnet */
81         _kvm_err(kd, kd->program, "kvm_readswap not implemented");
82         return(0);
83 #endif
84 }
85 #endif
86
87 #define KREAD(kd, addr, obj) \
88         (kvm_read(kd, addr, (char *)(obj), sizeof(*obj)) != sizeof(*obj))
89 #define KREADSTR(kd, addr) \
90         kvm_readstr(kd, (u_long)addr, NULL, NULL)
91
92 static struct kinfo_proc *
93 kinfo_resize_proc(kvm_t *kd, struct kinfo_proc *bp)
94 {
95         if (bp < kd->procend)
96                 return bp;
97
98         size_t pos = bp - kd->procend;
99         size_t size = kd->procend - kd->procbase;
100
101         if (size == 0)
102                 size = 8;
103         else
104                 size *= 2;
105         kd->procbase = _kvm_realloc(kd, kd->procbase, sizeof(*bp) * size);
106         if (kd->procbase == NULL)
107                 return NULL;
108         kd->procend = kd->procbase + size;
109         bp = kd->procbase + pos;
110         return bp;
111 }
112
113 /*
114  * note: this function is also used by /usr/src/sys/kern/kern_kinfo.c as
115  * compiled by userland.
116  */
117 dev_t
118 dev2udev(cdev_t dev)
119 {
120         if (dev == NULL)
121                 return NOUDEV;
122         if ((dev->si_umajor & 0xffffff00) ||
123             (dev->si_uminor & 0x0000ff00)) {
124                 return NOUDEV;
125         }
126         return((dev->si_umajor << 8) | dev->si_uminor);
127 }
128
129 /*
130  * Helper routine which traverses the left hand side of a red-black sub-tree.
131  */
132 static uintptr_t
133 kvm_lwptraverse(kvm_t *kd, struct lwp *lwp, uintptr_t lwppos)
134 {
135         for (;;) {
136                 if (KREAD(kd, lwppos, lwp)) {
137                         _kvm_err(kd, kd->program, "can't read lwp at %p",
138                                  (void *)lwppos);
139                         return ((uintptr_t)-1);
140                 }
141                 if (lwp->u.lwp_rbnode.rbe_left == NULL)
142                         break;
143                 lwppos = (uintptr_t)lwp->u.lwp_rbnode.rbe_left;
144         }
145         return(lwppos);
146 }
147
148 /*
149  * Iterate LWPs in a process.
150  *
151  * The first lwp in a red-black tree is a left-side traversal of the tree.
152  */
153 static uintptr_t
154 kvm_firstlwp(kvm_t *kd, struct lwp *lwp, struct proc *proc)
155 {
156         return(kvm_lwptraverse(kd, lwp, (uintptr_t)proc->p_lwp_tree.rbh_root));
157 }
158
159 /*
160  * If the current element is the left side of the parent the next element 
161  * will be a left side traversal of the parent's right side.  If the parent
162  * has no right side the next element will be the parent.
163  *
164  * If the current element is the right side of the parent the next element
165  * is the parent.
166  *
167  * If the parent is NULL we are done.
168  */
169 static uintptr_t
170 kvm_nextlwp(kvm_t *kd, uintptr_t lwppos, struct lwp *lwp, struct proc *proc)
171 {
172         uintptr_t nextpos;
173
174         nextpos = (uintptr_t)lwp->u.lwp_rbnode.rbe_parent;
175         if (nextpos) {
176                 if (KREAD(kd, nextpos, lwp)) {
177                         _kvm_err(kd, kd->program, "can't read lwp at %p",
178                                  (void *)lwppos);
179                         return ((uintptr_t)-1);
180                 }
181                 if (lwppos == (uintptr_t)lwp->u.lwp_rbnode.rbe_left) {
182                         /*
183                          * If we had gone down the left side the next element
184                          * is a left hand traversal of the parent's right
185                          * side, or the parent itself if there is no right
186                          * side.
187                          */
188                         lwppos = (uintptr_t)lwp->u.lwp_rbnode.rbe_right;
189                         if (lwppos)
190                                 nextpos = kvm_lwptraverse(kd, lwp, lwppos);
191                 } else {
192                         /*
193                          * If we had gone down the right side the next
194                          * element is the parent.
195                          */
196                         /* nextpos = nextpos */
197                 }
198         }
199         return(nextpos);
200 }
201
202 /*
203  * Read proc's from memory file into buffer bp, which has space to hold
204  * at most maxcnt procs.
205  */
206 static int
207 kvm_proclist(kvm_t *kd, int what, int arg, struct proc *p,
208              struct kinfo_proc *bp)
209 {
210         struct pgrp pgrp;
211         struct pgrp tpgrp;
212         struct globaldata gdata;
213         struct session sess;
214         struct session tsess;
215         struct tty tty;
216         struct proc proc;
217         struct ucred ucred;
218         struct thread thread;
219         struct proc pproc;
220         struct cdev cdev;
221         struct vmspace vmspace;
222         struct prison prison;
223         struct sigacts sigacts;
224         struct lwp lwp;
225         uintptr_t lwppos;
226         int count;
227         char *wmesg;
228
229         count = 0;
230
231         for (; p != NULL; p = proc.p_list.le_next) {
232                 if (KREAD(kd, (u_long)p, &proc)) {
233                         _kvm_err(kd, kd->program, "can't read proc at %p", p);
234                         return (-1);
235                 }
236                 if (KREAD(kd, (u_long)proc.p_ucred, &ucred)) {
237                         _kvm_err(kd, kd->program, "can't read ucred at %p",
238                                  proc.p_ucred);
239                         return (-1);
240                 }
241                 proc.p_ucred = &ucred;
242
243                 switch(what & ~KERN_PROC_FLAGMASK) {
244
245                 case KERN_PROC_PID:
246                         if (proc.p_pid != (pid_t)arg)
247                                 continue;
248                         break;
249
250                 case KERN_PROC_UID:
251                         if (ucred.cr_uid != (uid_t)arg)
252                                 continue;
253                         break;
254
255                 case KERN_PROC_RUID:
256                         if (ucred.cr_ruid != (uid_t)arg)
257                                 continue;
258                         break;
259                 }
260
261                 if (KREAD(kd, (u_long)proc.p_pgrp, &pgrp)) {
262                         _kvm_err(kd, kd->program, "can't read pgrp at %p",
263                                  proc.p_pgrp);
264                         return (-1);
265                 }
266                 proc.p_pgrp = &pgrp;
267                 if (proc.p_pptr) {
268                   if (KREAD(kd, (u_long)proc.p_pptr, &pproc)) {
269                         _kvm_err(kd, kd->program, "can't read pproc at %p",
270                                  proc.p_pptr);
271                         return (-1);
272                   }
273                   proc.p_pptr = &pproc;
274                 }
275
276                 if (proc.p_sigacts) {
277                         if (KREAD(kd, (u_long)proc.p_sigacts, &sigacts)) {
278                                 _kvm_err(kd, kd->program,
279                                          "can't read sigacts at %p",
280                                          proc.p_sigacts);
281                                 return (-1);
282                         }
283                         proc.p_sigacts = &sigacts;
284                 }
285
286                 if (KREAD(kd, (u_long)pgrp.pg_session, &sess)) {
287                         _kvm_err(kd, kd->program, "can't read session at %p",
288                                 pgrp.pg_session);
289                         return (-1);
290                 }
291                 pgrp.pg_session = &sess;
292
293                 if ((proc.p_flags & P_CONTROLT) && sess.s_ttyp != NULL) {
294                         if (KREAD(kd, (u_long)sess.s_ttyp, &tty)) {
295                                 _kvm_err(kd, kd->program,
296                                          "can't read tty at %p", sess.s_ttyp);
297                                 return (-1);
298                         }
299                         sess.s_ttyp = &tty;
300                         if (tty.t_dev != NULL) {
301                                 if (KREAD(kd, (u_long)tty.t_dev, &cdev))
302                                         tty.t_dev = NULL;
303                                 else
304                                         tty.t_dev = &cdev;
305                         }
306                         if (tty.t_pgrp != NULL) {
307                                 if (KREAD(kd, (u_long)tty.t_pgrp, &tpgrp)) {
308                                         _kvm_err(kd, kd->program,
309                                                  "can't read tpgrp at %p",
310                                                 tty.t_pgrp);
311                                         return (-1);
312                                 }
313                                 tty.t_pgrp = &tpgrp;
314                         }
315                         if (tty.t_session != NULL) {
316                                 if (KREAD(kd, (u_long)tty.t_session, &tsess)) {
317                                         _kvm_err(kd, kd->program,
318                                                  "can't read tsess at %p",
319                                                 tty.t_session);
320                                         return (-1);
321                                 }
322                                 tty.t_session = &tsess;
323                         }
324                 }
325
326                 if (KREAD(kd, (u_long)proc.p_vmspace, &vmspace)) {
327                         _kvm_err(kd, kd->program, "can't read vmspace at %p",
328                                  proc.p_vmspace);
329                         return (-1);
330                 }
331                 proc.p_vmspace = &vmspace;
332
333                 if (ucred.cr_prison != NULL) {
334                         if (KREAD(kd, (u_long)ucred.cr_prison, &prison)) {
335                                 _kvm_err(kd, kd->program, "can't read prison at %p",
336                                          ucred.cr_prison);
337                                 return (-1);
338                         }
339                         ucred.cr_prison = &prison;
340                 }
341
342                 switch (what & ~KERN_PROC_FLAGMASK) {
343
344                 case KERN_PROC_PGRP:
345                         if (proc.p_pgrp->pg_id != (pid_t)arg)
346                                 continue;
347                         break;
348
349                 case KERN_PROC_TTY:
350                         if ((proc.p_flags & P_CONTROLT) == 0 ||
351                             dev2udev(proc.p_pgrp->pg_session->s_ttyp->t_dev)
352                                         != (dev_t)arg)
353                                 continue;
354                         break;
355                 }
356
357                 if ((bp = kinfo_resize_proc(kd, bp)) == NULL)
358                         return (-1);
359                 fill_kinfo_proc(&proc, bp);
360                 bp->kp_paddr = (uintptr_t)p;
361
362                 lwppos = kvm_firstlwp(kd, &lwp, &proc);
363                 if (lwppos == 0) {
364                         bp++;           /* Just export the proc then */
365                         count++;
366                 }
367                 while (lwppos && lwppos != (uintptr_t)-1) {
368                         if (p != lwp.lwp_proc) {
369                                 _kvm_err(kd, kd->program, "lwp has wrong parent");
370                                 return (-1);
371                         }
372                         lwp.lwp_proc = &proc;
373                         if (KREAD(kd, (u_long)lwp.lwp_thread, &thread)) {
374                                 _kvm_err(kd, kd->program, "can't read thread at %p",
375                                     lwp.lwp_thread);
376                                 return (-1);
377                         }
378                         lwp.lwp_thread = &thread;
379
380                         if (thread.td_gd) {
381                                 if (KREAD(kd, (u_long)thread.td_gd, &gdata)) {
382                                         _kvm_err(kd, kd->program, "can't read"
383                                                   " gd at %p",
384                                                   thread.td_gd);
385                                         return(-1);
386                                 }
387                                 thread.td_gd = &gdata;
388                         }
389                         if (thread.td_wmesg) {
390                                 wmesg = (void *)KREADSTR(kd, thread.td_wmesg);
391                                 if (wmesg == NULL) {
392                                         _kvm_err(kd, kd->program, "can't read"
393                                                   " wmesg %p",
394                                                   thread.td_wmesg);
395                                         return(-1);
396                                 }
397                                 thread.td_wmesg = wmesg;
398                         } else {
399                                 wmesg = NULL;
400                         }
401
402                         if ((bp = kinfo_resize_proc(kd, bp)) == NULL)
403                                 return (-1);
404                         fill_kinfo_proc(&proc, bp);
405                         fill_kinfo_lwp(&lwp, &bp->kp_lwp);
406                         bp->kp_paddr = (uintptr_t)p;
407                         bp++;
408                         count++;
409                         if (wmesg)
410                                 free(wmesg);
411                         if ((what & KERN_PROC_FLAG_LWP) == 0)
412                                 break;
413                         lwppos = kvm_nextlwp(kd, lwppos, &lwp, &proc);
414                 }
415                 if (lwppos == (uintptr_t)-1)
416                         return(-1);
417         }
418         return (count);
419 }
420
421 /*
422  * Build proc info array by reading in proc list from a crash dump.
423  * We reallocate kd->procbase as necessary.
424  */
425 static int
426 kvm_deadprocs(kvm_t *kd, int what, int arg, u_long a_procglob,
427               int allproc_hsize)
428 {
429         struct kinfo_proc *bp;
430         struct proc *p;
431         struct proclist **pl;
432         int cnt, partcnt, n;
433         u_long nextoff;
434         u_long a_allproc;
435
436         cnt = partcnt = 0;
437         nextoff = 0;
438
439         /*
440          * Dynamically allocate space for all the elements of the
441          * allprocs array and KREAD() them.
442          */
443         pl = _kvm_malloc(kd, allproc_hsize * sizeof(struct proclist *));
444         for (n = 0; n < allproc_hsize; n++) {
445                 pl[n] = _kvm_malloc(kd, sizeof(struct proclist));
446                 a_allproc = sizeof(struct procglob) * n +
447                             offsetof(struct procglob, allproc);
448                 nextoff = a_allproc;
449                 if (KREAD(kd, (u_long)nextoff, pl[n])) {
450                         _kvm_err(kd, kd->program, "can't read proclist at 0x%lx",
451                                 a_allproc);
452                         return (-1);
453                 }
454
455                 /* Ignore empty proclists */
456                 if (LIST_EMPTY(pl[n]))
457                         continue;
458
459                 bp = kd->procbase + cnt;
460                 p = pl[n]->lh_first;
461                 partcnt = kvm_proclist(kd, what, arg, p, bp);
462                 if (partcnt < 0) {
463                         free(pl[n]);
464                         return (partcnt);
465                 }
466
467                 cnt += partcnt;
468                 free(pl[n]);
469         }
470
471         return (cnt);
472 }
473
474 struct kinfo_proc *
475 kvm_getprocs(kvm_t *kd, int op, int arg, int *cnt)
476 {
477         int mib[4], st, nprocs, allproc_hsize;
478         int miblen = ((op & ~KERN_PROC_FLAGMASK) == KERN_PROC_ALL) ? 3 : 4;
479         size_t size;
480
481         if (kd->procbase != 0) {
482                 free((void *)kd->procbase);
483                 /*
484                  * Clear this pointer in case this call fails.  Otherwise,
485                  * kvm_close() will free it again.
486                  */
487                 kd->procbase = 0;
488         }
489         if (kvm_ishost(kd)) {
490                 size = 0;
491                 mib[0] = CTL_KERN;
492                 mib[1] = KERN_PROC;
493                 mib[2] = op;
494                 mib[3] = arg;
495                 st = sysctl(mib, miblen, NULL, &size, NULL, 0);
496                 if (st == -1) {
497                         _kvm_syserr(kd, kd->program, "kvm_getprocs");
498                         return (0);
499                 }
500                 do {
501                         size += size / 10;
502                         kd->procbase = (struct kinfo_proc *)
503                             _kvm_realloc(kd, kd->procbase, size);
504                         if (kd->procbase == 0)
505                                 return (0);
506                         st = sysctl(mib, miblen, kd->procbase, &size, NULL, 0);
507                 } while (st == -1 && errno == ENOMEM);
508                 if (st == -1) {
509                         _kvm_syserr(kd, kd->program, "kvm_getprocs");
510                         return (0);
511                 }
512                 if (size % sizeof(struct kinfo_proc) != 0) {
513                         _kvm_err(kd, kd->program,
514                                 "proc size mismatch (%zd total, %zd chunks)",
515                                 size, sizeof(struct kinfo_proc));
516                         return (0);
517                 }
518                 nprocs = size / sizeof(struct kinfo_proc);
519         } else {
520                 struct nlist nl[4], *p;
521
522                 nl[0].n_name = "_nprocs";
523                 nl[1].n_name = "_procglob";
524                 nl[2].n_name = "_allproc_hsize";
525                 nl[3].n_name = 0;
526
527                 if (kvm_nlist(kd, nl) != 0) {
528                         for (p = nl; p->n_type != 0; ++p)
529                                 ;
530                         _kvm_err(kd, kd->program,
531                                  "%s: no such symbol", p->n_name);
532                         return (0);
533                 }
534                 if (KREAD(kd, nl[0].n_value, &nprocs)) {
535                         _kvm_err(kd, kd->program, "can't read nprocs");
536                         return (0);
537                 }
538                 if (KREAD(kd, nl[2].n_value, &allproc_hsize)) {
539                         _kvm_err(kd, kd->program, "can't read allproc_hsize");
540                         return (0);
541                 }
542                 nprocs = kvm_deadprocs(kd, op, arg, nl[1].n_value,
543                                       allproc_hsize);
544 #ifdef notdef
545                 size = nprocs * sizeof(struct kinfo_proc);
546                 (void)realloc(kd->procbase, size);
547 #endif
548         }
549         *cnt = nprocs;
550         return (kd->procbase);
551 }
552
553 void
554 _kvm_freeprocs(kvm_t *kd)
555 {
556         if (kd->procbase) {
557                 free(kd->procbase);
558                 kd->procbase = 0;
559         }
560 }
561
562 void *
563 _kvm_realloc(kvm_t *kd, void *p, size_t n)
564 {
565         void *np = (void *)realloc(p, n);
566
567         if (np == NULL) {
568                 free(p);
569                 _kvm_err(kd, kd->program, "out of memory");
570         }
571         return (np);
572 }
573
574 #ifndef MAX
575 #define MAX(a, b) ((a) > (b) ? (a) : (b))
576 #endif
577
578 /*
579  * Read in an argument vector from the user address space of process pid.
580  * addr if the user-space base address of narg null-terminated contiguous
581  * strings.  This is used to read in both the command arguments and
582  * environment strings.  Read at most maxcnt characters of strings.
583  */
584 static char **
585 kvm_argv(kvm_t *kd, pid_t pid, u_long addr, int narg, int maxcnt)
586 {
587         char *np, *cp, *ep, *ap;
588         u_long oaddr = -1;
589         int len, cc;
590         char **argv;
591
592         /*
593          * Check that there aren't an unreasonable number of agruments,
594          * and that the address is in user space.
595          */
596         if (narg > 512 || 
597             addr < VM_MIN_USER_ADDRESS || addr >= VM_MAX_USER_ADDRESS) {
598                 return (0);
599         }
600
601         /*
602          * kd->argv : work space for fetching the strings from the target 
603          *            process's space, and is converted for returning to caller
604          */
605         if (kd->argv == 0) {
606                 /*
607                  * Try to avoid reallocs.
608                  */
609                 kd->argc = MAX(narg + 1, 32);
610                 kd->argv = (char **)_kvm_malloc(kd, kd->argc *
611                                                 sizeof(*kd->argv));
612                 if (kd->argv == 0)
613                         return (0);
614         } else if (narg + 1 > kd->argc) {
615                 kd->argc = MAX(2 * kd->argc, narg + 1);
616                 kd->argv = (char **)_kvm_realloc(kd, kd->argv, kd->argc *
617                                                 sizeof(*kd->argv));
618                 if (kd->argv == 0)
619                         return (0);
620         }
621         /*
622          * kd->argspc : returned to user, this is where the kd->argv
623          *              arrays are left pointing to the collected strings.
624          */
625         if (kd->argspc == 0) {
626                 kd->argspc = (char *)_kvm_malloc(kd, PAGE_SIZE);
627                 if (kd->argspc == 0)
628                         return (0);
629                 kd->arglen = PAGE_SIZE;
630         }
631         /*
632          * kd->argbuf : used to pull in pages from the target process.
633          *              the strings are copied out of here.
634          */
635         if (kd->argbuf == 0) {
636                 kd->argbuf = (char *)_kvm_malloc(kd, PAGE_SIZE);
637                 if (kd->argbuf == 0)
638                         return (0);
639         }
640
641         /* Pull in the target process'es argv vector */
642         cc = sizeof(char *) * narg;
643         if (kvm_uread(kd, pid, addr, (char *)kd->argv, cc) != cc)
644                 return (0);
645         /*
646          * ap : saved start address of string we're working on in kd->argspc
647          * np : pointer to next place to write in kd->argspc
648          * len: length of data in kd->argspc
649          * argv: pointer to the argv vector that we are hunting around the
650          *       target process space for, and converting to addresses in
651          *       our address space (kd->argspc).
652          */
653         ap = np = kd->argspc;
654         argv = kd->argv;
655         len = 0;
656         /*
657          * Loop over pages, filling in the argument vector.
658          * Note that the argv strings could be pointing *anywhere* in
659          * the user address space and are no longer contiguous.
660          * Note that *argv is modified when we are going to fetch a string
661          * that crosses a page boundary.  We copy the next part of the string
662          * into to "np" and eventually convert the pointer.
663          */
664         while (argv < kd->argv + narg && *argv != NULL) {
665
666                 /* get the address that the current argv string is on */
667                 addr = (u_long)*argv & ~(PAGE_SIZE - 1);
668
669                 /* is it the same page as the last one? */
670                 if (addr != oaddr) {
671                         if (kvm_uread(kd, pid, addr, kd->argbuf, PAGE_SIZE) !=
672                             PAGE_SIZE)
673                                 return (0);
674                         oaddr = addr;
675                 }
676
677                 /* offset within the page... kd->argbuf */
678                 addr = (u_long)*argv & (PAGE_SIZE - 1);
679
680                 /* cp = start of string, cc = count of chars in this chunk */
681                 cp = kd->argbuf + addr;
682                 cc = PAGE_SIZE - addr;
683
684                 /* dont get more than asked for by user process */
685                 if (maxcnt > 0 && cc > maxcnt - len)
686                         cc = maxcnt - len;
687
688                 /* pointer to end of string if we found it in this page */
689                 ep = memchr(cp, '\0', cc);
690                 if (ep != NULL)
691                         cc = ep - cp + 1;
692                 /*
693                  * at this point, cc is the count of the chars that we are
694                  * going to retrieve this time. we may or may not have found
695                  * the end of it.  (ep points to the null if the end is known)
696                  */
697
698                 /* will we exceed the malloc/realloced buffer? */
699                 if (len + cc > kd->arglen) {
700                         size_t off;
701                         char **pp;
702                         char *op = kd->argspc;
703
704                         kd->arglen *= 2;
705                         kd->argspc = (char *)_kvm_realloc(kd, kd->argspc,
706                                                           kd->arglen);
707                         if (kd->argspc == 0)
708                                 return (0);
709                         /*
710                          * Adjust argv pointers in case realloc moved
711                          * the string space.
712                          */
713                         off = kd->argspc - op;
714                         for (pp = kd->argv; pp < argv; pp++)
715                                 *pp += off;
716                         ap += off;
717                         np += off;
718                 }
719                 /* np = where to put the next part of the string in kd->argspc*/
720                 /* np is kinda redundant.. could use "kd->argspc + len" */
721                 memcpy(np, cp, cc);
722                 np += cc;       /* inc counters */
723                 len += cc;
724
725                 /*
726                  * if end of string found, set the *argv pointer to the
727                  * saved beginning of string, and advance. argv points to
728                  * somewhere in kd->argv..  This is initially relative
729                  * to the target process, but when we close it off, we set
730                  * it to point in our address space.
731                  */
732                 if (ep != NULL) {
733                         *argv++ = ap;
734                         ap = np;
735                 } else {
736                         /* update the address relative to the target process */
737                         *argv += cc;
738                 }
739
740                 if (maxcnt > 0 && len >= maxcnt) {
741                         /*
742                          * We're stopping prematurely.  Terminate the
743                          * current string.
744                          */
745                         if (ep == NULL) {
746                                 *np = '\0';
747                                 *argv++ = ap;
748                         }
749                         break;
750                 }
751         }
752         /* Make sure argv is terminated. */
753         *argv = NULL;
754         return (kd->argv);
755 }
756
757 static void
758 ps_str_a(struct ps_strings *p, u_long *addr, int *n)
759 {
760         *addr = (u_long)p->ps_argvstr;
761         *n = p->ps_nargvstr;
762 }
763
764 static void
765 ps_str_e(struct ps_strings *p, u_long *addr, int *n)
766 {
767         *addr = (u_long)p->ps_envstr;
768         *n = p->ps_nenvstr;
769 }
770
771 /*
772  * Determine if the proc indicated by p is still active.
773  * This test is not 100% foolproof in theory, but chances of
774  * being wrong are very low.
775  */
776 static int
777 proc_verify(kvm_t *kd, const struct kinfo_proc *p)
778 {
779         struct kinfo_proc kp;
780         int mib[4];
781         size_t len;
782         int error;
783
784         mib[0] = CTL_KERN;
785         mib[1] = KERN_PROC;
786         mib[2] = KERN_PROC_PID;
787         mib[3] = p->kp_pid;
788
789         len = sizeof(kp);
790         error = sysctl(mib, 4, &kp, &len, NULL, 0);
791         if (error)
792                 return (0);
793
794         error = (p->kp_pid == kp.kp_pid &&
795             (kp.kp_stat != SZOMB || p->kp_stat == SZOMB));
796         return (error);
797 }
798
799 static char **
800 kvm_doargv(kvm_t *kd, const struct kinfo_proc *kp, int nchr,
801            void (*info)(struct ps_strings *, u_long *, int *))
802 {
803         char **ap;
804         u_long addr;
805         int cnt;
806         static struct ps_strings arginfo;
807         static u_long ps_strings;
808         size_t len;
809
810         if (ps_strings == 0) {
811                 len = sizeof(ps_strings);
812                 if (sysctlbyname("kern.ps_strings", &ps_strings, &len, NULL,
813                     0) == -1)
814                         ps_strings = PS_STRINGS;
815         }
816
817         /*
818          * Pointers are stored at the top of the user stack.
819          */
820         if (kp->kp_stat == SZOMB ||
821             kvm_uread(kd, kp->kp_pid, ps_strings, (char *)&arginfo,
822                       sizeof(arginfo)) != sizeof(arginfo))
823                 return (0);
824
825         (*info)(&arginfo, &addr, &cnt);
826         if (cnt == 0)
827                 return (0);
828         ap = kvm_argv(kd, kp->kp_pid, addr, cnt, nchr);
829         /*
830          * For live kernels, make sure this process didn't go away.
831          */
832         if (ap != NULL && (kvm_ishost(kd) || kvm_isvkernel(kd)) &&
833             !proc_verify(kd, kp))
834                 ap = NULL;
835         return (ap);
836 }
837
838 /*
839  * Get the command args.  This code is now machine independent.
840  */
841 char **
842 kvm_getargv(kvm_t *kd, const struct kinfo_proc *kp, int nchr)
843 {
844         int oid[4];
845         int i;
846         size_t bufsz;
847         static unsigned long buflen;
848         static char *buf, *p;
849         static char **bufp;
850         static int argc;
851
852         if (!kvm_ishost(kd)) { /* XXX: vkernels */
853                 _kvm_err(kd, kd->program,
854                     "cannot read user space from dead kernel");
855                 return (0);
856         }
857
858         if (!buflen) {
859                 bufsz = sizeof(buflen);
860                 i = sysctlbyname("kern.ps_arg_cache_limit", 
861                     &buflen, &bufsz, NULL, 0);
862                 if (i == -1) {
863                         buflen = 0;
864                 } else {
865                         buf = malloc(buflen);
866                         if (buf == NULL)
867                                 buflen = 0;
868                         argc = 32;
869                         bufp = malloc(sizeof(char *) * argc);
870                 }
871         }
872         if (buf != NULL) {
873                 oid[0] = CTL_KERN;
874                 oid[1] = KERN_PROC;
875                 oid[2] = KERN_PROC_ARGS;
876                 oid[3] = kp->kp_pid;
877                 bufsz = buflen;
878                 i = sysctl(oid, 4, buf, &bufsz, 0, 0);
879                 if (i == 0 && bufsz > 0) {
880                         i = 0;
881                         p = buf;
882                         do {
883                                 bufp[i++] = p;
884                                 p += strlen(p) + 1;
885                                 if (i >= argc) {
886                                         argc += argc;
887                                         bufp = realloc(bufp,
888                                             sizeof(char *) * argc);
889                                 }
890                         } while (p < buf + bufsz);
891                         bufp[i++] = NULL;
892                         return (bufp);
893                 }
894         }
895         if (kp->kp_flags & P_SYSTEM)
896                 return (NULL);
897         return (kvm_doargv(kd, kp, nchr, ps_str_a));
898 }
899
900 char **
901 kvm_getenvv(kvm_t *kd, const struct kinfo_proc *kp, int nchr)
902 {
903         return (kvm_doargv(kd, kp, nchr, ps_str_e));
904 }
905
906 /*
907  * Read from user space.  The user context is given by pid.
908  */
909 ssize_t
910 kvm_uread(kvm_t *kd, pid_t pid, u_long uva, char *buf, size_t len)
911 {
912         char *cp;
913         char procfile[MAXPATHLEN];
914         ssize_t amount;
915         int fd;
916
917         if (!kvm_ishost(kd)) { /* XXX: vkernels */
918                 _kvm_err(kd, kd->program,
919                     "cannot read user space from dead kernel");
920                 return (0);
921         }
922
923         sprintf(procfile, "/proc/%d/mem", pid);
924         fd = open(procfile, O_RDONLY, 0);
925         if (fd < 0) {
926                 _kvm_err(kd, kd->program, "cannot open %s", procfile);
927                 close(fd);
928                 return (0);
929         }
930
931         cp = buf;
932         while (len > 0) {
933                 errno = 0;
934                 if (lseek(fd, (off_t)uva, 0) == -1 && errno != 0) {
935                         _kvm_err(kd, kd->program, "invalid address (%lx) in %s",
936                             uva, procfile);
937                         break;
938                 }
939                 amount = read(fd, cp, len);
940                 if (amount < 0) {
941                         _kvm_syserr(kd, kd->program, "error reading %s",
942                             procfile);
943                         break;
944                 }
945                 if (amount == 0) {
946                         _kvm_err(kd, kd->program, "EOF reading %s", procfile);
947                         break;
948                 }
949                 cp += amount;
950                 uva += amount;
951                 len -= amount;
952         }
953
954         close(fd);
955         return ((ssize_t)(cp - buf));
956 }