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