kvm_proc.c revision 1.45.2.3 1 1.45.2.3 nathanw /* $NetBSD: kvm_proc.c,v 1.45.2.3 2002/04/23 22:03:39 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.3 nathanw __RCSID("$NetBSD: kvm_proc.c,v 1.45.2.3 2002/04/23 22:03:39 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 }
397 1.45.2.2 nathanw (void)kvm_read(kd, (u_long)proc.p_vmspace, &eproc.e_vm,
398 1.45.2.2 nathanw sizeof(eproc.e_vm));
399 1.45.2.2 nathanw
400 1.45.2.2 nathanw eproc.e_xsize = eproc.e_xrssize = 0;
401 1.45.2.2 nathanw eproc.e_xccount = eproc.e_xswrss = 0;
402 1.45.2.2 nathanw
403 1.45.2.2 nathanw switch (what) {
404 1.45.2.2 nathanw
405 1.45.2.2 nathanw case KERN_PROC_PGRP:
406 1.45.2.2 nathanw if (eproc.e_pgid != (pid_t)arg)
407 1.45.2.2 nathanw continue;
408 1.45.2.2 nathanw break;
409 1.45.2.2 nathanw
410 1.45.2.2 nathanw case KERN_PROC_TTY:
411 1.45.2.2 nathanw if ((proc.p_flag & P_CONTROLT) == 0 ||
412 1.45.2.2 nathanw eproc.e_tdev != (dev_t)arg)
413 1.45.2.2 nathanw continue;
414 1.45.2.2 nathanw break;
415 1.45.2.2 nathanw }
416 1.45.2.2 nathanw memcpy(&bp->kp_proc, &proc, sizeof(proc));
417 1.45.2.2 nathanw memcpy(&bp->kp_eproc, &eproc, sizeof(eproc));
418 1.45.2.2 nathanw ++bp;
419 1.45.2.2 nathanw ++cnt;
420 1.45.2.2 nathanw }
421 1.45.2.2 nathanw return (cnt);
422 1.45.2.2 nathanw }
423 1.45.2.2 nathanw
424 1.45.2.2 nathanw /*
425 1.45.2.2 nathanw * Build proc info array by reading in proc list from a crash dump.
426 1.45.2.2 nathanw * Return number of procs read. maxcnt is the max we will read.
427 1.45.2.2 nathanw */
428 1.45.2.2 nathanw static int
429 1.45.2.2 nathanw kvm_deadprocs(kd, what, arg, a_allproc, a_deadproc, a_zombproc, maxcnt)
430 1.45.2.2 nathanw kvm_t *kd;
431 1.45.2.2 nathanw int what, arg;
432 1.45.2.2 nathanw u_long a_allproc;
433 1.45.2.2 nathanw u_long a_deadproc;
434 1.45.2.2 nathanw u_long a_zombproc;
435 1.45.2.2 nathanw int maxcnt;
436 1.45.2.2 nathanw {
437 1.45.2.2 nathanw struct kinfo_proc *bp = kd->procbase;
438 1.45.2.2 nathanw int acnt, dcnt, zcnt;
439 1.45.2.2 nathanw struct proc *p;
440 1.45.2.2 nathanw
441 1.45.2.2 nathanw if (KREAD(kd, a_allproc, &p)) {
442 1.45.2.2 nathanw _kvm_err(kd, kd->program, "cannot read allproc");
443 1.45.2.2 nathanw return (-1);
444 1.45.2.2 nathanw }
445 1.45.2.2 nathanw acnt = kvm_proclist(kd, what, arg, p, bp, maxcnt);
446 1.45.2.2 nathanw if (acnt < 0)
447 1.45.2.2 nathanw return (acnt);
448 1.45.2.2 nathanw
449 1.45.2.2 nathanw if (KREAD(kd, a_deadproc, &p)) {
450 1.45.2.2 nathanw _kvm_err(kd, kd->program, "cannot read deadproc");
451 1.45.2.2 nathanw return (-1);
452 1.45.2.2 nathanw }
453 1.45.2.2 nathanw
454 1.45.2.2 nathanw dcnt = kvm_proclist(kd, what, arg, p, bp, maxcnt - acnt);
455 1.45.2.2 nathanw if (dcnt < 0)
456 1.45.2.2 nathanw dcnt = 0;
457 1.45.2.2 nathanw
458 1.45.2.2 nathanw if (KREAD(kd, a_zombproc, &p)) {
459 1.45.2.2 nathanw _kvm_err(kd, kd->program, "cannot read zombproc");
460 1.45.2.2 nathanw return (-1);
461 1.45.2.2 nathanw }
462 1.45.2.2 nathanw zcnt = kvm_proclist(kd, what, arg, p, bp + acnt,
463 1.45.2.2 nathanw maxcnt - (acnt + dcnt));
464 1.45.2.2 nathanw if (zcnt < 0)
465 1.45.2.2 nathanw zcnt = 0;
466 1.45.2.2 nathanw
467 1.45.2.2 nathanw return (acnt + zcnt);
468 1.45.2.2 nathanw }
469 1.45.2.2 nathanw
470 1.45.2.2 nathanw struct kinfo_proc2 *
471 1.45.2.2 nathanw kvm_getproc2(kd, op, arg, esize, cnt)
472 1.45.2.2 nathanw kvm_t *kd;
473 1.45.2.2 nathanw int op, arg;
474 1.45.2.2 nathanw size_t esize;
475 1.45.2.2 nathanw int *cnt;
476 1.45.2.2 nathanw {
477 1.45.2.2 nathanw size_t size;
478 1.45.2.2 nathanw int mib[6], st, nprocs;
479 1.45.2.2 nathanw struct pstats pstats;
480 1.45.2.2 nathanw
481 1.45.2.2 nathanw if (kd->procbase2 != NULL) {
482 1.45.2.2 nathanw free(kd->procbase2);
483 1.45.2.2 nathanw /*
484 1.45.2.2 nathanw * Clear this pointer in case this call fails. Otherwise,
485 1.45.2.2 nathanw * kvm_close() will free it again.
486 1.45.2.2 nathanw */
487 1.45.2.2 nathanw kd->procbase2 = NULL;
488 1.45.2.2 nathanw }
489 1.45.2.2 nathanw
490 1.45.2.2 nathanw if (ISSYSCTL(kd)) {
491 1.45.2.2 nathanw size = 0;
492 1.45.2.2 nathanw mib[0] = CTL_KERN;
493 1.45.2.2 nathanw mib[1] = KERN_PROC2;
494 1.45.2.2 nathanw mib[2] = op;
495 1.45.2.2 nathanw mib[3] = arg;
496 1.45.2.2 nathanw mib[4] = esize;
497 1.45.2.2 nathanw mib[5] = 0;
498 1.45.2.2 nathanw st = sysctl(mib, 6, NULL, &size, NULL, 0);
499 1.45.2.2 nathanw if (st == -1) {
500 1.45.2.2 nathanw _kvm_syserr(kd, kd->program, "kvm_getproc2");
501 1.45.2.2 nathanw return NULL;
502 1.45.2.2 nathanw }
503 1.45.2.2 nathanw
504 1.45.2.2 nathanw mib[5] = size / esize;
505 1.45.2.2 nathanw kd->procbase2 = (struct kinfo_proc2 *)_kvm_malloc(kd, size);
506 1.45.2.2 nathanw if (kd->procbase2 == NULL)
507 1.45.2.2 nathanw return NULL;
508 1.45.2.2 nathanw st = sysctl(mib, 6, kd->procbase2, &size, NULL, 0);
509 1.45.2.2 nathanw if (st == -1) {
510 1.45.2.2 nathanw _kvm_syserr(kd, kd->program, "kvm_getproc2");
511 1.45.2.2 nathanw return NULL;
512 1.45.2.2 nathanw }
513 1.45.2.2 nathanw nprocs = size / esize;
514 1.45.2.2 nathanw } else {
515 1.45.2.2 nathanw char *kp2c;
516 1.45.2.2 nathanw struct kinfo_proc *kp;
517 1.45.2.2 nathanw struct kinfo_proc2 kp2, *kp2p;
518 1.45.2.2 nathanw struct kinfo_lwp *kl;
519 1.45.2.2 nathanw int i, nlwps;
520 1.45.2.2 nathanw
521 1.45.2.2 nathanw kp = kvm_getprocs(kd, op, arg, &nprocs);
522 1.45.2.2 nathanw if (kp == NULL)
523 1.45.2.2 nathanw return NULL;
524 1.45.2.2 nathanw
525 1.45.2.2 nathanw kd->procbase2 = _kvm_malloc(kd, nprocs * esize);
526 1.45.2.2 nathanw kp2c = (char *)(void *)kd->procbase2;
527 1.45.2.2 nathanw kp2p = &kp2;
528 1.45.2.2 nathanw for (i = 0; i < nprocs; i++, kp++) {
529 1.45.2.2 nathanw kl = kvm_getlwps(kd, kp->kp_proc.p_pid,
530 1.45.2.2 nathanw PTRTOINT64(kp->kp_eproc.e_paddr),
531 1.45.2.2 nathanw sizeof(struct kinfo_lwp), &nlwps);
532 1.45.2.2 nathanw /* We use kl[0] as the "representative" LWP */
533 1.45.2.2 nathanw memset(kp2p, 0, sizeof(kp2));
534 1.45.2.2 nathanw kp2p->p_forw = kl[0].l_forw;
535 1.45.2.2 nathanw kp2p->p_back = kl[0].l_back;
536 1.45.2.2 nathanw kp2p->p_paddr = PTRTOINT64(kp->kp_eproc.e_paddr);
537 1.45.2.2 nathanw kp2p->p_addr = kl[0].l_addr;
538 1.45.2.2 nathanw kp2p->p_fd = PTRTOINT64(kp->kp_proc.p_fd);
539 1.45.2.2 nathanw kp2p->p_cwdi = PTRTOINT64(kp->kp_proc.p_cwdi);
540 1.45.2.2 nathanw kp2p->p_stats = PTRTOINT64(kp->kp_proc.p_stats);
541 1.45.2.2 nathanw kp2p->p_limit = PTRTOINT64(kp->kp_proc.p_limit);
542 1.45.2.2 nathanw kp2p->p_vmspace = PTRTOINT64(kp->kp_proc.p_vmspace);
543 1.45.2.2 nathanw kp2p->p_sigacts = PTRTOINT64(kp->kp_proc.p_sigacts);
544 1.45.2.2 nathanw kp2p->p_sess = PTRTOINT64(kp->kp_eproc.e_sess);
545 1.45.2.2 nathanw kp2p->p_tsess = 0;
546 1.45.2.2 nathanw kp2p->p_ru = PTRTOINT64(kp->kp_proc.p_ru);
547 1.45.2.2 nathanw
548 1.45.2.2 nathanw kp2p->p_eflag = 0;
549 1.45.2.2 nathanw kp2p->p_exitsig = kp->kp_proc.p_exitsig;
550 1.45.2.2 nathanw kp2p->p_flag = kp->kp_proc.p_flag;
551 1.45.2.2 nathanw
552 1.45.2.2 nathanw kp2p->p_pid = kp->kp_proc.p_pid;
553 1.45.2.2 nathanw
554 1.45.2.2 nathanw kp2p->p_ppid = kp->kp_eproc.e_ppid;
555 1.45.2.2 nathanw kp2p->p_sid = kp->kp_eproc.e_sid;
556 1.45.2.2 nathanw kp2p->p__pgid = kp->kp_eproc.e_pgid;
557 1.45.2.2 nathanw
558 1.45.2.2 nathanw kp2p->p_tpgid = 30001 /* XXX NO_PID! */;
559 1.45.2.2 nathanw
560 1.45.2.2 nathanw kp2p->p_uid = kp->kp_eproc.e_ucred.cr_uid;
561 1.45.2.2 nathanw kp2p->p_ruid = kp->kp_eproc.e_pcred.p_ruid;
562 1.45.2.2 nathanw kp2p->p_gid = kp->kp_eproc.e_ucred.cr_gid;
563 1.45.2.2 nathanw kp2p->p_rgid = kp->kp_eproc.e_pcred.p_rgid;
564 1.45.2.2 nathanw
565 1.45.2.2 nathanw /*CONSTCOND*/
566 1.45.2.2 nathanw memcpy(kp2p->p_groups, kp->kp_eproc.e_ucred.cr_groups,
567 1.45.2.2 nathanw MIN(sizeof(kp2p->p_groups), sizeof(kp->kp_eproc.e_ucred.cr_groups)));
568 1.45.2.2 nathanw kp2p->p_ngroups = kp->kp_eproc.e_ucred.cr_ngroups;
569 1.45.2.2 nathanw
570 1.45.2.2 nathanw kp2p->p_jobc = kp->kp_eproc.e_jobc;
571 1.45.2.2 nathanw kp2p->p_tdev = kp->kp_eproc.e_tdev;
572 1.45.2.2 nathanw kp2p->p_tpgid = kp->kp_eproc.e_tpgid;
573 1.45.2.2 nathanw kp2p->p_tsess = PTRTOINT64(kp->kp_eproc.e_tsess);
574 1.45.2.2 nathanw
575 1.45.2.2 nathanw kp2p->p_estcpu = kp->kp_proc.p_estcpu;
576 1.45.2.2 nathanw kp2p->p_rtime_sec = kp->kp_proc.p_estcpu;
577 1.45.2.2 nathanw kp2p->p_rtime_usec = kp->kp_proc.p_estcpu;
578 1.45.2.2 nathanw kp2p->p_cpticks = kp->kp_proc.p_cpticks;
579 1.45.2.2 nathanw kp2p->p_pctcpu = kp->kp_proc.p_pctcpu;
580 1.45.2.2 nathanw kp2p->p_swtime = kl[0].l_swtime;
581 1.45.2.2 nathanw kp2p->p_slptime = kl[0].l_slptime;
582 1.45.2.2 nathanw #if 0 /* XXX thorpej */
583 1.45.2.2 nathanw kp2p->p_schedflags = kp->kp_proc.p_schedflags;
584 1.45.2.2 nathanw #else
585 1.45.2.2 nathanw kp2p->p_schedflags = 0;
586 1.45.2.2 nathanw #endif
587 1.45.2.2 nathanw
588 1.45.2.2 nathanw kp2p->p_uticks = kp->kp_proc.p_uticks;
589 1.45.2.2 nathanw kp2p->p_sticks = kp->kp_proc.p_sticks;
590 1.45.2.2 nathanw kp2p->p_iticks = kp->kp_proc.p_iticks;
591 1.45.2.2 nathanw
592 1.45.2.2 nathanw kp2p->p_tracep = PTRTOINT64(kp->kp_proc.p_tracep);
593 1.45.2.2 nathanw kp2p->p_traceflag = kp->kp_proc.p_traceflag;
594 1.45.2.2 nathanw
595 1.45.2.2 nathanw kp2p->p_holdcnt = kl[0].l_holdcnt;
596 1.45.2.2 nathanw
597 1.45.2.2 nathanw memcpy(&kp2p->p_siglist, &kp->kp_proc.p_sigctx.ps_siglist, sizeof(ki_sigset_t));
598 1.45.2.2 nathanw memcpy(&kp2p->p_sigmask, &kp->kp_proc.p_sigctx.ps_sigmask, sizeof(ki_sigset_t));
599 1.45.2.2 nathanw memcpy(&kp2p->p_sigignore, &kp->kp_proc.p_sigctx.ps_sigignore, sizeof(ki_sigset_t));
600 1.45.2.2 nathanw memcpy(&kp2p->p_sigcatch, &kp->kp_proc.p_sigctx.ps_sigcatch, sizeof(ki_sigset_t));
601 1.45.2.2 nathanw
602 1.45.2.2 nathanw kp2p->p_stat = kp->kp_proc.p_stat;
603 1.45.2.2 nathanw kp2p->p_priority = kl[0].l_priority;
604 1.45.2.2 nathanw kp2p->p_usrpri = kl[0].l_usrpri;
605 1.45.2.2 nathanw kp2p->p_nice = kp->kp_proc.p_nice;
606 1.45.2.2 nathanw
607 1.45.2.2 nathanw kp2p->p_xstat = kp->kp_proc.p_xstat;
608 1.45.2.2 nathanw kp2p->p_acflag = kp->kp_proc.p_acflag;
609 1.45.2.2 nathanw
610 1.45.2.2 nathanw /*CONSTCOND*/
611 1.45.2.2 nathanw strncpy(kp2p->p_comm, kp->kp_proc.p_comm,
612 1.45.2.2 nathanw MIN(sizeof(kp2p->p_comm), sizeof(kp->kp_proc.p_comm)));
613 1.45.2.2 nathanw
614 1.45.2.2 nathanw strncpy(kp2p->p_wmesg, kp->kp_eproc.e_wmesg, sizeof(kp2p->p_wmesg));
615 1.45.2.2 nathanw kp2p->p_wchan = kl[0].l_wchan;
616 1.45.2.2 nathanw strncpy(kp2p->p_login, kp->kp_eproc.e_login, sizeof(kp2p->p_login));
617 1.45.2.2 nathanw
618 1.45.2.2 nathanw kp2p->p_vm_rssize = kp->kp_eproc.e_xrssize;
619 1.45.2.2 nathanw kp2p->p_vm_tsize = kp->kp_eproc.e_vm.vm_tsize;
620 1.45.2.2 nathanw kp2p->p_vm_dsize = kp->kp_eproc.e_vm.vm_dsize;
621 1.45.2.2 nathanw kp2p->p_vm_ssize = kp->kp_eproc.e_vm.vm_ssize;
622 1.45.2.2 nathanw
623 1.45.2.2 nathanw kp2p->p_eflag = (int32_t)kp->kp_eproc.e_flag;
624 1.45.2.2 nathanw
625 1.45.2.2 nathanw if (P_ZOMBIE(&kp->kp_proc)
626 1.45.2.2 nathanw ||
627 1.45.2.2 nathanw kp->kp_proc.p_stats == NULL ||
628 1.45.2.2 nathanw KREAD(kd, (u_long)kp->kp_proc.p_stats, &pstats)
629 1.45.2.2 nathanw ) {
630 1.45.2.2 nathanw kp2p->p_uvalid = 0;
631 1.45.2.2 nathanw } else {
632 1.45.2.2 nathanw kp2p->p_uvalid = 1;
633 1.45.2.2 nathanw
634 1.45.2.2 nathanw kp2p->p_ustart_sec = (u_int32_t)
635 1.45.2.2 nathanw pstats.p_start.tv_sec;
636 1.45.2.2 nathanw kp2p->p_ustart_usec = (u_int32_t)
637 1.45.2.2 nathanw pstats.p_start.tv_usec;
638 1.45.2.2 nathanw
639 1.45.2.2 nathanw kp2p->p_uutime_sec = (u_int32_t)
640 1.45.2.2 nathanw pstats.p_ru.ru_utime.tv_sec;
641 1.45.2.2 nathanw kp2p->p_uutime_usec = (u_int32_t)
642 1.45.2.2 nathanw pstats.p_ru.ru_utime.tv_usec;
643 1.45.2.2 nathanw kp2p->p_ustime_sec = (u_int32_t)
644 1.45.2.2 nathanw pstats.p_ru.ru_stime.tv_sec;
645 1.45.2.2 nathanw kp2p->p_ustime_usec = (u_int32_t)
646 1.45.2.2 nathanw pstats.p_ru.ru_stime.tv_usec;
647 1.45.2.2 nathanw
648 1.45.2.2 nathanw kp2p->p_uru_maxrss = pstats.p_ru.ru_maxrss;
649 1.45.2.2 nathanw kp2p->p_uru_ixrss = pstats.p_ru.ru_ixrss;
650 1.45.2.2 nathanw kp2p->p_uru_idrss = pstats.p_ru.ru_idrss;
651 1.45.2.2 nathanw kp2p->p_uru_isrss = pstats.p_ru.ru_isrss;
652 1.45.2.2 nathanw kp2p->p_uru_minflt = pstats.p_ru.ru_minflt;
653 1.45.2.2 nathanw kp2p->p_uru_majflt = pstats.p_ru.ru_majflt;
654 1.45.2.2 nathanw kp2p->p_uru_nswap = pstats.p_ru.ru_nswap;
655 1.45.2.2 nathanw kp2p->p_uru_inblock = pstats.p_ru.ru_inblock;
656 1.45.2.2 nathanw kp2p->p_uru_oublock = pstats.p_ru.ru_oublock;
657 1.45.2.2 nathanw kp2p->p_uru_msgsnd = pstats.p_ru.ru_msgsnd;
658 1.45.2.2 nathanw kp2p->p_uru_msgrcv = pstats.p_ru.ru_msgrcv;
659 1.45.2.2 nathanw kp2p->p_uru_nsignals = pstats.p_ru.ru_nsignals;
660 1.45.2.2 nathanw kp2p->p_uru_nvcsw = pstats.p_ru.ru_nvcsw;
661 1.45.2.2 nathanw kp2p->p_uru_nivcsw = pstats.p_ru.ru_nivcsw;
662 1.45.2.2 nathanw
663 1.45.2.2 nathanw kp2p->p_uctime_sec = (u_int32_t)
664 1.45.2.2 nathanw (pstats.p_cru.ru_utime.tv_sec +
665 1.45.2.2 nathanw pstats.p_cru.ru_stime.tv_sec);
666 1.45.2.2 nathanw kp2p->p_uctime_usec = (u_int32_t)
667 1.45.2.2 nathanw (pstats.p_cru.ru_utime.tv_usec +
668 1.45.2.2 nathanw pstats.p_cru.ru_stime.tv_usec);
669 1.45.2.2 nathanw }
670 1.45.2.2 nathanw
671 1.45.2.2 nathanw memcpy(kp2c, &kp2, esize);
672 1.45.2.2 nathanw kp2c += esize;
673 1.45.2.2 nathanw }
674 1.45.2.2 nathanw
675 1.45.2.2 nathanw free(kd->procbase);
676 1.45.2.2 nathanw }
677 1.45.2.2 nathanw *cnt = nprocs;
678 1.45.2.2 nathanw return (kd->procbase2);
679 1.45.2.2 nathanw }
680 1.45.2.2 nathanw
681 1.45.2.2 nathanw struct kinfo_lwp *
682 1.45.2.2 nathanw kvm_getlwps(kd, pid, paddr, esize, cnt)
683 1.45.2.2 nathanw kvm_t *kd;
684 1.45.2.2 nathanw int pid;
685 1.45.2.2 nathanw u_long paddr;
686 1.45.2.2 nathanw size_t esize;
687 1.45.2.2 nathanw int *cnt;
688 1.45.2.2 nathanw {
689 1.45.2.2 nathanw size_t size;
690 1.45.2.2 nathanw int mib[5], st, nlwps;
691 1.45.2.2 nathanw struct kinfo_lwp *kl;
692 1.45.2.2 nathanw
693 1.45.2.2 nathanw if (kd->lwpbase != NULL) {
694 1.45.2.2 nathanw free(kd->lwpbase);
695 1.45.2.2 nathanw /*
696 1.45.2.2 nathanw * Clear this pointer in case this call fails. Otherwise,
697 1.45.2.2 nathanw * kvm_close() will free it again.
698 1.45.2.2 nathanw */
699 1.45.2.2 nathanw kd->lwpbase = NULL;
700 1.45.2.2 nathanw }
701 1.45.2.2 nathanw
702 1.45.2.2 nathanw if (ISSYSCTL(kd)) {
703 1.45.2.2 nathanw size = 0;
704 1.45.2.2 nathanw mib[0] = CTL_KERN;
705 1.45.2.2 nathanw mib[1] = KERN_LWP;
706 1.45.2.2 nathanw mib[2] = pid;
707 1.45.2.2 nathanw mib[3] = esize;
708 1.45.2.2 nathanw mib[4] = 0;
709 1.45.2.2 nathanw st = sysctl(mib, 5, NULL, &size, NULL, 0);
710 1.45.2.2 nathanw if (st == -1) {
711 1.45.2.2 nathanw _kvm_syserr(kd, kd->program, "kvm_getlwps");
712 1.45.2.2 nathanw return NULL;
713 1.45.2.2 nathanw }
714 1.45.2.2 nathanw
715 1.45.2.2 nathanw mib[4] = size / esize;
716 1.45.2.2 nathanw kd->lwpbase = (struct kinfo_lwp *)_kvm_malloc(kd, size);
717 1.45.2.2 nathanw if (kd->lwpbase == NULL)
718 1.45.2.2 nathanw return NULL;
719 1.45.2.2 nathanw st = sysctl(mib, 5, kd->lwpbase, &size, NULL, 0);
720 1.45.2.2 nathanw if (st == -1) {
721 1.45.2.2 nathanw _kvm_syserr(kd, kd->program, "kvm_getlwps");
722 1.45.2.2 nathanw return NULL;
723 1.45.2.2 nathanw }
724 1.45.2.2 nathanw nlwps = size / esize;
725 1.45.2.2 nathanw } else {
726 1.45.2.2 nathanw /* grovel through the memory image */
727 1.45.2.2 nathanw struct proc p;
728 1.45.2.2 nathanw struct lwp l;
729 1.45.2.2 nathanw u_long laddr;
730 1.45.2.2 nathanw int i;
731 1.45.2.2 nathanw
732 1.45.2.2 nathanw st = kvm_read(kd, paddr, &p, sizeof(p));
733 1.45.2.2 nathanw if (st == -1) {
734 1.45.2.2 nathanw _kvm_syserr(kd, kd->program, "kvm_getlwps");
735 1.45.2.2 nathanw return NULL;
736 1.45.2.2 nathanw }
737 1.45.2.2 nathanw
738 1.45.2.2 nathanw nlwps = p.p_nlwps;
739 1.45.2.2 nathanw kd->lwpbase = (struct kinfo_lwp *)_kvm_malloc(kd,
740 1.45.2.2 nathanw nlwps * sizeof(struct kinfo_lwp));
741 1.45.2.2 nathanw if (kd->lwpbase == NULL)
742 1.45.2.2 nathanw return NULL;
743 1.45.2.2 nathanw laddr = PTRTOINT64(p.p_lwps.lh_first);
744 1.45.2.2 nathanw for (i = 0; (i < nlwps) && (laddr != 0); i++) {
745 1.45.2.2 nathanw st = kvm_read(kd, laddr, &l, sizeof(l));
746 1.45.2.2 nathanw if (st == -1) {
747 1.45.2.2 nathanw _kvm_syserr(kd, kd->program, "kvm_getlwps");
748 1.45.2.2 nathanw return NULL;
749 1.45.2.2 nathanw }
750 1.45.2.2 nathanw kl = &kd->lwpbase[i];
751 1.45.2.2 nathanw kl->l_laddr = laddr;
752 1.45.2.2 nathanw kl->l_forw = PTRTOINT64(l.l_forw);
753 1.45.2.2 nathanw kl->l_back = PTRTOINT64(l.l_back);
754 1.45.2.2 nathanw kl->l_addr = PTRTOINT64(l.l_addr);
755 1.45.2.2 nathanw kl->l_lid = l.l_lid;
756 1.45.2.2 nathanw kl->l_flag = l.l_flag;
757 1.45.2.2 nathanw kl->l_swtime = l.l_swtime;
758 1.45.2.2 nathanw kl->l_slptime = l.l_slptime;
759 1.45.2.2 nathanw kl->l_schedflags = 0; /* XXX */
760 1.45.2.2 nathanw kl->l_holdcnt = l.l_holdcnt;
761 1.45.2.2 nathanw kl->l_priority = l.l_priority;
762 1.45.2.2 nathanw kl->l_usrpri = l.l_usrpri;
763 1.45.2.2 nathanw kl->l_stat = l.l_stat;
764 1.45.2.2 nathanw kl->l_wchan = PTRTOINT64(l.l_wchan);
765 1.45.2.2 nathanw strncpy(kl->l_wmesg, l.l_wmesg,
766 1.45.2.2 nathanw sizeof(kl->l_wmesg));
767 1.45.2.2 nathanw kl->l_cpuid = KI_NOCPU;
768 1.45.2.2 nathanw }
769 1.45.2.2 nathanw }
770 1.45.2.2 nathanw
771 1.45.2.2 nathanw *cnt = nlwps;
772 1.45.2.2 nathanw return kd->lwpbase;
773 1.45.2.2 nathanw }
774 1.45.2.2 nathanw
775 1.45.2.2 nathanw struct kinfo_proc *
776 1.45.2.2 nathanw kvm_getprocs(kd, op, arg, cnt)
777 1.45.2.2 nathanw kvm_t *kd;
778 1.45.2.2 nathanw int op, arg;
779 1.45.2.2 nathanw int *cnt;
780 1.45.2.2 nathanw {
781 1.45.2.2 nathanw size_t size;
782 1.45.2.2 nathanw int mib[4], st, nprocs;
783 1.45.2.2 nathanw
784 1.45.2.2 nathanw if (kd->procbase != NULL) {
785 1.45.2.2 nathanw free(kd->procbase);
786 1.45.2.2 nathanw /*
787 1.45.2.2 nathanw * Clear this pointer in case this call fails. Otherwise,
788 1.45.2.2 nathanw * kvm_close() will free it again.
789 1.45.2.2 nathanw */
790 1.45.2.2 nathanw kd->procbase = NULL;
791 1.45.2.2 nathanw }
792 1.45.2.2 nathanw if (ISKMEM(kd)) {
793 1.45.2.2 nathanw size = 0;
794 1.45.2.2 nathanw mib[0] = CTL_KERN;
795 1.45.2.2 nathanw mib[1] = KERN_PROC;
796 1.45.2.2 nathanw mib[2] = op;
797 1.45.2.2 nathanw mib[3] = arg;
798 1.45.2.2 nathanw st = sysctl(mib, 4, NULL, &size, NULL, 0);
799 1.45.2.2 nathanw if (st == -1) {
800 1.45.2.2 nathanw _kvm_syserr(kd, kd->program, "kvm_getprocs");
801 1.45.2.2 nathanw return NULL;
802 1.45.2.2 nathanw }
803 1.45.2.2 nathanw kd->procbase = (struct kinfo_proc *)_kvm_malloc(kd, size);
804 1.45.2.2 nathanw if (kd->procbase == NULL)
805 1.45.2.2 nathanw return NULL;
806 1.45.2.2 nathanw st = sysctl(mib, 4, kd->procbase, &size, NULL, 0);
807 1.45.2.2 nathanw if (st == -1) {
808 1.45.2.2 nathanw _kvm_syserr(kd, kd->program, "kvm_getprocs");
809 1.45.2.2 nathanw return NULL;
810 1.45.2.2 nathanw }
811 1.45.2.2 nathanw if (size % sizeof(struct kinfo_proc) != 0) {
812 1.45.2.2 nathanw _kvm_err(kd, kd->program,
813 1.45.2.2 nathanw "proc size mismatch (%lu total, %lu chunks)",
814 1.45.2.2 nathanw (u_long)size, (u_long)sizeof(struct kinfo_proc));
815 1.45.2.2 nathanw return NULL;
816 1.45.2.2 nathanw }
817 1.45.2.2 nathanw nprocs = size / sizeof(struct kinfo_proc);
818 1.45.2.2 nathanw } else if (ISSYSCTL(kd)) {
819 1.45.2.2 nathanw _kvm_err(kd, kd->program, "kvm_open called with KVM_NO_FILES, "
820 1.45.2.2 nathanw "can't use kvm_getprocs");
821 1.45.2.2 nathanw return NULL;
822 1.45.2.2 nathanw } else {
823 1.45.2.2 nathanw struct nlist nl[5], *p;
824 1.45.2.2 nathanw
825 1.45.2.2 nathanw nl[0].n_name = "_nprocs";
826 1.45.2.2 nathanw nl[1].n_name = "_allproc";
827 1.45.2.2 nathanw nl[2].n_name = "_deadproc";
828 1.45.2.2 nathanw nl[3].n_name = "_zombproc";
829 1.45.2.2 nathanw nl[4].n_name = NULL;
830 1.45.2.2 nathanw
831 1.45.2.2 nathanw if (kvm_nlist(kd, nl) != 0) {
832 1.45.2.2 nathanw for (p = nl; p->n_type != 0; ++p)
833 1.45.2.2 nathanw ;
834 1.45.2.2 nathanw _kvm_err(kd, kd->program,
835 1.45.2.2 nathanw "%s: no such symbol", p->n_name);
836 1.45.2.2 nathanw return NULL;
837 1.45.2.2 nathanw }
838 1.45.2.2 nathanw if (KREAD(kd, nl[0].n_value, &nprocs)) {
839 1.45.2.2 nathanw _kvm_err(kd, kd->program, "can't read nprocs");
840 1.45.2.2 nathanw return NULL;
841 1.45.2.2 nathanw }
842 1.45.2.2 nathanw size = nprocs * sizeof(struct kinfo_proc);
843 1.45.2.2 nathanw kd->procbase = (struct kinfo_proc *)_kvm_malloc(kd, size);
844 1.45.2.2 nathanw if (kd->procbase == NULL)
845 1.45.2.2 nathanw return NULL;
846 1.45.2.2 nathanw
847 1.45.2.2 nathanw nprocs = kvm_deadprocs(kd, op, arg, nl[1].n_value,
848 1.45.2.2 nathanw nl[2].n_value, nl[3].n_value, nprocs);
849 1.45.2.2 nathanw if (nprocs < 0)
850 1.45.2.2 nathanw return NULL;
851 1.45.2.2 nathanw #ifdef notdef
852 1.45.2.2 nathanw size = nprocs * sizeof(struct kinfo_proc);
853 1.45.2.2 nathanw (void)realloc(kd->procbase, size);
854 1.45.2.2 nathanw #endif
855 1.45.2.2 nathanw }
856 1.45.2.2 nathanw *cnt = nprocs;
857 1.45.2.2 nathanw return (kd->procbase);
858 1.45.2.2 nathanw }
859 1.45.2.2 nathanw
860 1.45.2.2 nathanw void
861 1.45.2.2 nathanw _kvm_freeprocs(kd)
862 1.45.2.2 nathanw kvm_t *kd;
863 1.45.2.2 nathanw {
864 1.45.2.2 nathanw if (kd->procbase) {
865 1.45.2.2 nathanw free(kd->procbase);
866 1.45.2.2 nathanw kd->procbase = NULL;
867 1.45.2.2 nathanw }
868 1.45.2.2 nathanw }
869 1.45.2.2 nathanw
870 1.45.2.2 nathanw void *
871 1.45.2.2 nathanw _kvm_realloc(kd, p, n)
872 1.45.2.2 nathanw kvm_t *kd;
873 1.45.2.2 nathanw void *p;
874 1.45.2.2 nathanw size_t n;
875 1.45.2.2 nathanw {
876 1.45.2.2 nathanw void *np = realloc(p, n);
877 1.45.2.2 nathanw
878 1.45.2.2 nathanw if (np == NULL)
879 1.45.2.2 nathanw _kvm_err(kd, kd->program, "out of memory");
880 1.45.2.2 nathanw return (np);
881 1.45.2.2 nathanw }
882 1.45.2.2 nathanw
883 1.45.2.2 nathanw /*
884 1.45.2.2 nathanw * Read in an argument vector from the user address space of process p.
885 1.45.2.2 nathanw * addr if the user-space base address of narg null-terminated contiguous
886 1.45.2.2 nathanw * strings. This is used to read in both the command arguments and
887 1.45.2.2 nathanw * environment strings. Read at most maxcnt characters of strings.
888 1.45.2.2 nathanw */
889 1.45.2.2 nathanw static char **
890 1.45.2.2 nathanw kvm_argv(kd, p, addr, narg, maxcnt)
891 1.45.2.2 nathanw kvm_t *kd;
892 1.45.2.2 nathanw const struct miniproc *p;
893 1.45.2.2 nathanw u_long addr;
894 1.45.2.2 nathanw int narg;
895 1.45.2.2 nathanw int maxcnt;
896 1.45.2.2 nathanw {
897 1.45.2.2 nathanw char *np, *cp, *ep, *ap;
898 1.45.2.2 nathanw u_long oaddr = (u_long)~0L;
899 1.45.2.2 nathanw u_long len;
900 1.45.2.2 nathanw size_t cc;
901 1.45.2.2 nathanw char **argv;
902 1.45.2.2 nathanw
903 1.45.2.2 nathanw /*
904 1.45.2.2 nathanw * Check that there aren't an unreasonable number of agruments,
905 1.45.2.2 nathanw * and that the address is in user space.
906 1.45.2.2 nathanw */
907 1.45.2.2 nathanw if (narg > ARG_MAX || addr < kd->min_uva || addr >= kd->max_uva)
908 1.45.2.2 nathanw return NULL;
909 1.45.2.2 nathanw
910 1.45.2.2 nathanw if (kd->argv == NULL) {
911 1.45.2.2 nathanw /*
912 1.45.2.2 nathanw * Try to avoid reallocs.
913 1.45.2.2 nathanw */
914 1.45.2.2 nathanw kd->argc = MAX(narg + 1, 32);
915 1.45.2.2 nathanw kd->argv = (char **)_kvm_malloc(kd, kd->argc *
916 1.45.2.2 nathanw sizeof(*kd->argv));
917 1.45.2.2 nathanw if (kd->argv == NULL)
918 1.45.2.2 nathanw return NULL;
919 1.45.2.2 nathanw } else if (narg + 1 > kd->argc) {
920 1.45.2.2 nathanw kd->argc = MAX(2 * kd->argc, narg + 1);
921 1.45.2.2 nathanw kd->argv = (char **)_kvm_realloc(kd, kd->argv, kd->argc *
922 1.45.2.2 nathanw sizeof(*kd->argv));
923 1.45.2.2 nathanw if (kd->argv == NULL)
924 1.45.2.2 nathanw return NULL;
925 1.45.2.2 nathanw }
926 1.45.2.2 nathanw if (kd->argspc == NULL) {
927 1.45.2.2 nathanw kd->argspc = (char *)_kvm_malloc(kd, (size_t)kd->nbpg);
928 1.45.2.2 nathanw if (kd->argspc == NULL)
929 1.45.2.2 nathanw return NULL;
930 1.45.2.2 nathanw kd->arglen = kd->nbpg;
931 1.45.2.2 nathanw }
932 1.45.2.2 nathanw if (kd->argbuf == NULL) {
933 1.45.2.2 nathanw kd->argbuf = (char *)_kvm_malloc(kd, (size_t)kd->nbpg);
934 1.45.2.2 nathanw if (kd->argbuf == NULL)
935 1.45.2.2 nathanw return NULL;
936 1.45.2.2 nathanw }
937 1.45.2.2 nathanw cc = sizeof(char *) * narg;
938 1.45.2.2 nathanw if (kvm_ureadm(kd, p, addr, (void *)kd->argv, cc) != cc)
939 1.45.2.2 nathanw return NULL;
940 1.45.2.2 nathanw ap = np = kd->argspc;
941 1.45.2.2 nathanw argv = kd->argv;
942 1.45.2.2 nathanw len = 0;
943 1.45.2.2 nathanw /*
944 1.45.2.2 nathanw * Loop over pages, filling in the argument vector.
945 1.45.2.2 nathanw */
946 1.45.2.2 nathanw while (argv < kd->argv + narg && *argv != NULL) {
947 1.45.2.2 nathanw addr = (u_long)*argv & ~(kd->nbpg - 1);
948 1.45.2.2 nathanw if (addr != oaddr) {
949 1.45.2.2 nathanw if (kvm_ureadm(kd, p, addr, kd->argbuf,
950 1.45.2.2 nathanw (size_t)kd->nbpg) != kd->nbpg)
951 1.45.2.2 nathanw return NULL;
952 1.45.2.2 nathanw oaddr = addr;
953 1.45.2.2 nathanw }
954 1.45.2.2 nathanw addr = (u_long)*argv & (kd->nbpg - 1);
955 1.45.2.2 nathanw cp = kd->argbuf + (size_t)addr;
956 1.45.2.2 nathanw cc = kd->nbpg - (size_t)addr;
957 1.45.2.2 nathanw if (maxcnt > 0 && cc > (size_t)(maxcnt - len))
958 1.45.2.2 nathanw cc = (size_t)(maxcnt - len);
959 1.45.2.2 nathanw ep = memchr(cp, '\0', cc);
960 1.45.2.2 nathanw if (ep != NULL)
961 1.45.2.2 nathanw cc = ep - cp + 1;
962 1.45.2.2 nathanw if (len + cc > kd->arglen) {
963 1.45.2.2 nathanw int off;
964 1.45.2.2 nathanw char **pp;
965 1.45.2.2 nathanw char *op = kd->argspc;
966 1.45.2.2 nathanw
967 1.45.2.2 nathanw kd->arglen *= 2;
968 1.45.2.2 nathanw kd->argspc = (char *)_kvm_realloc(kd, kd->argspc,
969 1.45.2.2 nathanw (size_t)kd->arglen);
970 1.45.2.2 nathanw if (kd->argspc == NULL)
971 1.45.2.2 nathanw return NULL;
972 1.45.2.2 nathanw /*
973 1.45.2.2 nathanw * Adjust argv pointers in case realloc moved
974 1.45.2.2 nathanw * the string space.
975 1.45.2.2 nathanw */
976 1.45.2.2 nathanw off = kd->argspc - op;
977 1.45.2.2 nathanw for (pp = kd->argv; pp < argv; pp++)
978 1.45.2.2 nathanw *pp += off;
979 1.45.2.2 nathanw ap += off;
980 1.45.2.2 nathanw np += off;
981 1.45.2.2 nathanw }
982 1.45.2.2 nathanw memcpy(np, cp, cc);
983 1.45.2.2 nathanw np += cc;
984 1.45.2.2 nathanw len += cc;
985 1.45.2.2 nathanw if (ep != NULL) {
986 1.45.2.2 nathanw *argv++ = ap;
987 1.45.2.2 nathanw ap = np;
988 1.45.2.2 nathanw } else
989 1.45.2.2 nathanw *argv += cc;
990 1.45.2.2 nathanw if (maxcnt > 0 && len >= maxcnt) {
991 1.45.2.2 nathanw /*
992 1.45.2.2 nathanw * We're stopping prematurely. Terminate the
993 1.45.2.2 nathanw * current string.
994 1.45.2.2 nathanw */
995 1.45.2.2 nathanw if (ep == NULL) {
996 1.45.2.2 nathanw *np = '\0';
997 1.45.2.2 nathanw *argv++ = ap;
998 1.45.2.2 nathanw }
999 1.45.2.2 nathanw break;
1000 1.45.2.2 nathanw }
1001 1.45.2.2 nathanw }
1002 1.45.2.2 nathanw /* Make sure argv is terminated. */
1003 1.45.2.2 nathanw *argv = NULL;
1004 1.45.2.2 nathanw return (kd->argv);
1005 1.45.2.2 nathanw }
1006 1.45.2.2 nathanw
1007 1.45.2.2 nathanw static void
1008 1.45.2.2 nathanw ps_str_a(p, addr, n)
1009 1.45.2.2 nathanw struct ps_strings *p;
1010 1.45.2.2 nathanw u_long *addr;
1011 1.45.2.2 nathanw int *n;
1012 1.45.2.2 nathanw {
1013 1.45.2.2 nathanw *addr = (u_long)p->ps_argvstr;
1014 1.45.2.2 nathanw *n = p->ps_nargvstr;
1015 1.45.2.2 nathanw }
1016 1.45.2.2 nathanw
1017 1.45.2.2 nathanw static void
1018 1.45.2.2 nathanw ps_str_e(p, addr, n)
1019 1.45.2.2 nathanw struct ps_strings *p;
1020 1.45.2.2 nathanw u_long *addr;
1021 1.45.2.2 nathanw int *n;
1022 1.45.2.2 nathanw {
1023 1.45.2.2 nathanw *addr = (u_long)p->ps_envstr;
1024 1.45.2.2 nathanw *n = p->ps_nenvstr;
1025 1.45.2.2 nathanw }
1026 1.45.2.2 nathanw
1027 1.45.2.2 nathanw /*
1028 1.45.2.2 nathanw * Determine if the proc indicated by p is still active.
1029 1.45.2.2 nathanw * This test is not 100% foolproof in theory, but chances of
1030 1.45.2.2 nathanw * being wrong are very low.
1031 1.45.2.2 nathanw */
1032 1.45.2.2 nathanw static int
1033 1.45.2.2 nathanw proc_verify(kd, kernp, p)
1034 1.45.2.2 nathanw kvm_t *kd;
1035 1.45.2.2 nathanw u_long kernp;
1036 1.45.2.2 nathanw const struct miniproc *p;
1037 1.45.2.2 nathanw {
1038 1.45.2.2 nathanw struct proc kernproc;
1039 1.45.2.2 nathanw
1040 1.45.2.2 nathanw /*
1041 1.45.2.2 nathanw * Just read in the whole proc. It's not that big relative
1042 1.45.2.2 nathanw * to the cost of the read system call.
1043 1.45.2.2 nathanw */
1044 1.45.2.2 nathanw if (kvm_read(kd, kernp, &kernproc, sizeof(kernproc)) !=
1045 1.45.2.2 nathanw sizeof(kernproc))
1046 1.45.2.2 nathanw return 0;
1047 1.45.2.2 nathanw return (p->p_pid == kernproc.p_pid &&
1048 1.45.2.2 nathanw (kernproc.p_stat != SZOMB || p->p_stat == SZOMB));
1049 1.45.2.2 nathanw }
1050 1.45.2.2 nathanw
1051 1.45.2.2 nathanw static char **
1052 1.45.2.2 nathanw kvm_doargv(kd, p, nchr, info)
1053 1.45.2.2 nathanw kvm_t *kd;
1054 1.45.2.2 nathanw const struct miniproc *p;
1055 1.45.2.2 nathanw int nchr;
1056 1.45.2.2 nathanw void (*info)(struct ps_strings *, u_long *, int *);
1057 1.45.2.2 nathanw {
1058 1.45.2.2 nathanw char **ap;
1059 1.45.2.2 nathanw u_long addr;
1060 1.45.2.2 nathanw int cnt;
1061 1.45.2.2 nathanw struct ps_strings arginfo;
1062 1.45.2.2 nathanw
1063 1.45.2.2 nathanw /*
1064 1.45.2.2 nathanw * Pointers are stored at the top of the user stack.
1065 1.45.2.2 nathanw */
1066 1.45.2.2 nathanw if (p->p_stat == SZOMB)
1067 1.45.2.2 nathanw return NULL;
1068 1.45.2.2 nathanw cnt = kvm_ureadm(kd, p, kd->usrstack - sizeof(arginfo),
1069 1.45.2.2 nathanw (void *)&arginfo, sizeof(arginfo));
1070 1.45.2.2 nathanw if (cnt != sizeof(arginfo))
1071 1.45.2.2 nathanw return NULL;
1072 1.45.2.2 nathanw
1073 1.45.2.2 nathanw (*info)(&arginfo, &addr, &cnt);
1074 1.45.2.2 nathanw if (cnt == 0)
1075 1.45.2.2 nathanw return NULL;
1076 1.45.2.2 nathanw ap = kvm_argv(kd, p, addr, cnt, nchr);
1077 1.45.2.2 nathanw /*
1078 1.45.2.2 nathanw * For live kernels, make sure this process didn't go away.
1079 1.45.2.2 nathanw */
1080 1.45.2.2 nathanw if (ap != NULL && ISALIVE(kd) &&
1081 1.45.2.2 nathanw !proc_verify(kd, (u_long)p->p_paddr, p))
1082 1.45.2.2 nathanw ap = NULL;
1083 1.45.2.2 nathanw return (ap);
1084 1.45.2.2 nathanw }
1085 1.45.2.2 nathanw
1086 1.45.2.2 nathanw /*
1087 1.45.2.2 nathanw * Get the command args. This code is now machine independent.
1088 1.45.2.2 nathanw */
1089 1.45.2.2 nathanw char **
1090 1.45.2.2 nathanw kvm_getargv(kd, kp, nchr)
1091 1.45.2.2 nathanw kvm_t *kd;
1092 1.45.2.2 nathanw const struct kinfo_proc *kp;
1093 1.45.2.2 nathanw int nchr;
1094 1.45.2.2 nathanw {
1095 1.45.2.2 nathanw struct miniproc p;
1096 1.45.2.2 nathanw
1097 1.45.2.2 nathanw KPTOMINI(kp, &p);
1098 1.45.2.2 nathanw return (kvm_doargv(kd, &p, nchr, ps_str_a));
1099 1.45.2.2 nathanw }
1100 1.45.2.2 nathanw
1101 1.45.2.2 nathanw char **
1102 1.45.2.2 nathanw kvm_getenvv(kd, kp, nchr)
1103 1.45.2.2 nathanw kvm_t *kd;
1104 1.45.2.2 nathanw const struct kinfo_proc *kp;
1105 1.45.2.2 nathanw int nchr;
1106 1.45.2.2 nathanw {
1107 1.45.2.2 nathanw struct miniproc p;
1108 1.45.2.2 nathanw
1109 1.45.2.2 nathanw KPTOMINI(kp, &p);
1110 1.45.2.2 nathanw return (kvm_doargv(kd, &p, nchr, ps_str_e));
1111 1.45.2.2 nathanw }
1112 1.45.2.2 nathanw
1113 1.45.2.2 nathanw static char **
1114 1.45.2.2 nathanw kvm_doargv2(kd, pid, type, nchr)
1115 1.45.2.2 nathanw kvm_t *kd;
1116 1.45.2.2 nathanw pid_t pid;
1117 1.45.2.2 nathanw int type;
1118 1.45.2.2 nathanw int nchr;
1119 1.45.2.2 nathanw {
1120 1.45.2.2 nathanw size_t bufs;
1121 1.45.2.2 nathanw int narg, mib[4];
1122 1.45.2.2 nathanw size_t newarglen;
1123 1.45.2.2 nathanw char **ap, *bp, *endp;
1124 1.45.2.2 nathanw
1125 1.45.2.2 nathanw /*
1126 1.45.2.2 nathanw * Check that there aren't an unreasonable number of agruments.
1127 1.45.2.2 nathanw */
1128 1.45.2.2 nathanw if (nchr > ARG_MAX)
1129 1.45.2.2 nathanw return NULL;
1130 1.45.2.2 nathanw
1131 1.45.2.2 nathanw if (nchr == 0)
1132 1.45.2.2 nathanw nchr = ARG_MAX;
1133 1.45.2.2 nathanw
1134 1.45.2.2 nathanw /* Get number of strings in argv */
1135 1.45.2.2 nathanw mib[0] = CTL_KERN;
1136 1.45.2.2 nathanw mib[1] = KERN_PROC_ARGS;
1137 1.45.2.2 nathanw mib[2] = pid;
1138 1.45.2.2 nathanw mib[3] = type == KERN_PROC_ARGV ? KERN_PROC_NARGV : KERN_PROC_NENV;
1139 1.45.2.2 nathanw bufs = sizeof(narg);
1140 1.45.2.2 nathanw if (sysctl(mib, 4, &narg, &bufs, NULL, NULL) == -1)
1141 1.45.2.2 nathanw return NULL;
1142 1.45.2.2 nathanw
1143 1.45.2.2 nathanw if (kd->argv == NULL) {
1144 1.45.2.2 nathanw /*
1145 1.45.2.2 nathanw * Try to avoid reallocs.
1146 1.45.2.2 nathanw */
1147 1.45.2.2 nathanw kd->argc = MAX(narg + 1, 32);
1148 1.45.2.2 nathanw kd->argv = (char **)_kvm_malloc(kd, kd->argc *
1149 1.45.2.2 nathanw sizeof(*kd->argv));
1150 1.45.2.2 nathanw if (kd->argv == NULL)
1151 1.45.2.2 nathanw return NULL;
1152 1.45.2.2 nathanw } else if (narg + 1 > kd->argc) {
1153 1.45.2.2 nathanw kd->argc = MAX(2 * kd->argc, narg + 1);
1154 1.45.2.2 nathanw kd->argv = (char **)_kvm_realloc(kd, kd->argv, kd->argc *
1155 1.45.2.2 nathanw sizeof(*kd->argv));
1156 1.45.2.2 nathanw if (kd->argv == NULL)
1157 1.45.2.2 nathanw return NULL;
1158 1.45.2.2 nathanw }
1159 1.45.2.2 nathanw
1160 1.45.2.2 nathanw newarglen = MIN(nchr, ARG_MAX);
1161 1.45.2.2 nathanw if (kd->arglen < newarglen) {
1162 1.45.2.2 nathanw if (kd->arglen == 0)
1163 1.45.2.2 nathanw kd->argspc = (char *)_kvm_malloc(kd, newarglen);
1164 1.45.2.2 nathanw else
1165 1.45.2.2 nathanw kd->argspc = (char *)_kvm_realloc(kd, kd->argspc,
1166 1.45.2.2 nathanw newarglen);
1167 1.45.2.2 nathanw if (kd->argspc == NULL)
1168 1.45.2.2 nathanw return NULL;
1169 1.45.2.2 nathanw kd->arglen = newarglen;
1170 1.45.2.2 nathanw }
1171 1.45.2.2 nathanw memset(kd->argspc, 0, (size_t)kd->arglen); /* XXX necessary? */
1172 1.45.2.2 nathanw
1173 1.45.2.2 nathanw mib[0] = CTL_KERN;
1174 1.45.2.2 nathanw mib[1] = KERN_PROC_ARGS;
1175 1.45.2.2 nathanw mib[2] = pid;
1176 1.45.2.2 nathanw mib[3] = type;
1177 1.45.2.2 nathanw bufs = kd->arglen;
1178 1.45.2.2 nathanw if (sysctl(mib, 4, kd->argspc, &bufs, NULL, NULL) == -1)
1179 1.45.2.2 nathanw return NULL;
1180 1.45.2.2 nathanw
1181 1.45.2.2 nathanw bp = kd->argspc;
1182 1.45.2.2 nathanw bp[kd->arglen-1] = '\0'; /* make sure the string ends with nul */
1183 1.45.2.2 nathanw ap = kd->argv;
1184 1.45.2.2 nathanw endp = bp + MIN(nchr, bufs);
1185 1.45.2.2 nathanw
1186 1.45.2.2 nathanw while (bp < endp) {
1187 1.45.2.2 nathanw *ap++ = bp;
1188 1.45.2.2 nathanw /* XXX: don't need following anymore, or stick check for max argc in above while loop? */
1189 1.45.2.2 nathanw if (ap >= kd->argv + kd->argc) {
1190 1.45.2.2 nathanw kd->argc *= 2;
1191 1.45.2.2 nathanw kd->argv = _kvm_realloc(kd, kd->argv,
1192 1.45.2.2 nathanw kd->argc * sizeof(*kd->argv));
1193 1.45.2.2 nathanw ap = kd->argv;
1194 1.45.2.2 nathanw }
1195 1.45.2.2 nathanw bp += strlen(bp) + 1;
1196 1.45.2.2 nathanw }
1197 1.45.2.2 nathanw *ap = NULL;
1198 1.45.2.2 nathanw
1199 1.45.2.2 nathanw return (kd->argv);
1200 1.45.2.2 nathanw }
1201 1.45.2.2 nathanw
1202 1.45.2.2 nathanw char **
1203 1.45.2.2 nathanw kvm_getargv2(kd, kp, nchr)
1204 1.45.2.2 nathanw kvm_t *kd;
1205 1.45.2.2 nathanw const struct kinfo_proc2 *kp;
1206 1.45.2.2 nathanw int nchr;
1207 1.45.2.2 nathanw {
1208 1.45.2.2 nathanw return (kvm_doargv2(kd, kp->p_pid, KERN_PROC_ARGV, nchr));
1209 1.45.2.2 nathanw }
1210 1.45.2.2 nathanw
1211 1.45.2.2 nathanw char **
1212 1.45.2.2 nathanw kvm_getenvv2(kd, kp, nchr)
1213 1.45.2.2 nathanw kvm_t *kd;
1214 1.45.2.2 nathanw const struct kinfo_proc2 *kp;
1215 1.45.2.2 nathanw int nchr;
1216 1.45.2.2 nathanw {
1217 1.45.2.2 nathanw return (kvm_doargv2(kd, kp->p_pid, KERN_PROC_ENV, nchr));
1218 1.45.2.2 nathanw }
1219 1.45.2.2 nathanw
1220 1.45.2.2 nathanw /*
1221 1.45.2.2 nathanw * Read from user space. The user context is given by p.
1222 1.45.2.2 nathanw */
1223 1.45.2.2 nathanw static ssize_t
1224 1.45.2.2 nathanw kvm_ureadm(kd, p, uva, buf, len)
1225 1.45.2.2 nathanw kvm_t *kd;
1226 1.45.2.2 nathanw const struct miniproc *p;
1227 1.45.2.2 nathanw u_long uva;
1228 1.45.2.2 nathanw char *buf;
1229 1.45.2.2 nathanw size_t len;
1230 1.45.2.2 nathanw {
1231 1.45.2.2 nathanw char *cp;
1232 1.45.2.2 nathanw
1233 1.45.2.2 nathanw cp = buf;
1234 1.45.2.2 nathanw while (len > 0) {
1235 1.45.2.2 nathanw size_t cc;
1236 1.45.2.2 nathanw char *dp;
1237 1.45.2.2 nathanw u_long cnt;
1238 1.45.2.2 nathanw
1239 1.45.2.2 nathanw dp = _kvm_ureadm(kd, p, uva, &cnt);
1240 1.45.2.2 nathanw if (dp == NULL) {
1241 1.45.2.2 nathanw _kvm_err(kd, 0, "invalid address (%lx)", uva);
1242 1.45.2.2 nathanw return 0;
1243 1.45.2.2 nathanw }
1244 1.45.2.2 nathanw cc = (size_t)MIN(cnt, len);
1245 1.45.2.2 nathanw memcpy(cp, dp, cc);
1246 1.45.2.2 nathanw cp += cc;
1247 1.45.2.2 nathanw uva += cc;
1248 1.45.2.2 nathanw len -= cc;
1249 1.45.2.2 nathanw }
1250 1.45.2.2 nathanw return (ssize_t)(cp - buf);
1251 1.45.2.2 nathanw }
1252 1.45.2.2 nathanw
1253 1.45.2.2 nathanw ssize_t
1254 1.45.2.2 nathanw kvm_uread(kd, p, uva, buf, len)
1255 1.45.2.2 nathanw kvm_t *kd;
1256 1.45.2.2 nathanw const struct proc *p;
1257 1.45.2.2 nathanw u_long uva;
1258 1.45.2.2 nathanw char *buf;
1259 1.45.2.2 nathanw size_t len;
1260 1.45.2.2 nathanw {
1261 1.45.2.2 nathanw struct miniproc mp;
1262 1.45.2.2 nathanw
1263 1.45.2.2 nathanw PTOMINI(p, &mp);
1264 1.45.2.2 nathanw return (kvm_ureadm(kd, &mp, uva, buf, len));
1265 1.45.2.2 nathanw }
1266