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