1/* $NetBSD: db_proc.c,v 1.6 2011/10/23 13:30:20 jym Exp $ */
2
3/*-
4 * Copyright (c) 2009 The NetBSD Foundation, Inc.
5 * All rights reserved.
6 *
7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Andrew Doran.
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE.
30 */
31
32/*
33 * Copyright (c) 1982, 1986, 1989, 1991, 1993
34 * The Regents of the University of California. All rights reserved.
35 *
36 * Redistribution and use in source and binary forms, with or without
37 * modification, are permitted provided that the following conditions
38 * are met:
39 * 1. Redistributions of source code must retain the above copyright
40 * notice, this list of conditions and the following disclaimer.
41 * 2. Redistributions in binary form must reproduce the above copyright
42 * notice, this list of conditions and the following disclaimer in the
43 * documentation and/or other materials provided with the distribution.
44 * 3. Neither the name of the University nor the names of its contributors
45 * may be used to endorse or promote products derived from this software
46 * without specific prior written permission.
47 *
48 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
49 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
50 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
51 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
52 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
53 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
54 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
55 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
56 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
57 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
58 * SUCH DAMAGE.
59 *
60 * from: kern_proc.c 8.4 (Berkeley) 1/4/94
61 */
62
63#include <sys/cdefs.h>
64__KERNEL_RCSID(0, "$NetBSD: db_proc.c,v 1.6 2011/10/23 13:30:20 jym Exp $");
65
66#ifndef _KERNEL
67#include <stdbool.h>
68#endif
69
70#include <sys/param.h>
71#include <sys/cpu.h>
72#include <sys/proc.h>
73#ifdef _KERNEL /* XXX */
74#include <sys/kauth.h>
75#endif
76
77#include <ddb/ddb.h>
78
79proc_t *
80db_proc_first(void)
81{
82
83 return db_read_ptr("allproc");
84}
85
86proc_t *
87db_proc_next(proc_t *p)
88{
89
90 db_read_bytes((db_addr_t)&p->p_list.le_next, sizeof(p), (char *)&p);
91 return p;
92}
93
94proc_t *
95db_proc_find(pid_t pid)
96{
97 proc_t *p;
98 pid_t tp;
99
100 for (p = db_proc_first(); p != NULL; p = db_proc_next(p)) {
101 db_read_bytes((db_addr_t)&p->p_pid, sizeof(tp),
102 (char *)&tp);
103 if (tp == pid) {
104 return p;
105 }
106 }
107 return NULL;
108}
109
110void
111db_show_all_procs(db_expr_t addr, bool haddr, db_expr_t count,
112 const char *modif)
113{
114 static struct pgrp pgrp;
115 static proc_t p;
116 static lwp_t l;
117 const char *mode, *ename;
118 proc_t *pp;
119 lwp_t *lp;
120 char db_nbuf[MAXCOMLEN + 1], wbuf[MAXCOMLEN + 1];
121 bool run;
122 int cpuno;
123
124 if (modif[0] == 0)
125 mode = "l"; /* default == lwp mode */
126 else
127 mode = strchr("mawln", modif[0]);
128
129 if (mode == NULL || *mode == 'm') {
130 db_printf("usage: show all procs [/a] [/l] [/n] [/w]\n");
131 db_printf("\t/a == show process address info\n");
132 db_printf("\t/l == show LWP info [default]\n");
133 db_printf("\t/n == show normal process info\n");
134 db_printf("\t/w == show process wait/emul info\n");
135 return;
136 }
137
138 switch (*mode) {
139 case 'a':
140 db_printf("PID %10s %18s %18s %18s\n",
141 "COMMAND", "STRUCT PROC *", "UAREA *", "VMSPACE/VM_MAP");
142 break;
143 case 'l':
144 db_printf("PID %4s S %3s %9s %18s %18s %-8s\n",
145 "LID", "CPU", "FLAGS", "STRUCT LWP *", "NAME", "WAIT");
146 break;
147 case 'n':
148 db_printf("PID %8s %8s %10s S %7s %4s %16s %7s\n",
149 "PPID", "PGRP", "UID", "FLAGS", "LWPS", "COMMAND", "WAIT");
150 break;
151 case 'w':
152 db_printf("PID %4s %16s %8s %4s %-12s%s\n",
153 "LID", "COMMAND", "EMUL", "PRI", "WAIT-MSG",
154 "WAIT-CHANNEL");
155 break;
156 }
157
158 for (pp = db_proc_first(); pp != NULL; pp = db_proc_next(pp)) {
159 db_read_bytes((db_addr_t)pp, sizeof(p), (char *)&p);
160 if (p.p_stat == 0) {
161 continue;
162 }
163 lp = p.p_lwps.lh_first;
164 if (lp != NULL) {
165 db_read_bytes((db_addr_t)lp, sizeof(l), (char *)&l);
166 }
167 db_printf("%-5d", p.p_pid);
168
169 switch (*mode) {
170 case 'a':
171 db_printf("%10.10s %18lx %18lx %18lx\n",
172 p.p_comm, (long)pp,
173 (long)(lp != NULL ? l.l_addr : 0),
174 (long)p.p_vmspace);
175 break;
176 case 'l':
177 while (lp != NULL) {
178 if (l.l_name != NULL) {
179 db_read_bytes((db_addr_t)l.l_name,
180 MAXCOMLEN, db_nbuf);
181 } else {
182 strlcpy(db_nbuf, p.p_comm,
183 sizeof(db_nbuf));
184 }
185 run = (l.l_stat == LSONPROC ||
186 (l.l_pflag & LP_RUNNING) != 0);
187 if (l.l_cpu != NULL) {
188 db_read_bytes((db_addr_t)
189 &l.l_cpu->ci_data.cpu_index,
190 sizeof(cpuno), (char *)&cpuno);
191 } else
192 cpuno = -1;
193 if (l.l_wchan && l.l_wmesg) {
194 db_read_bytes((db_addr_t)l.l_wmesg,
195 sizeof(wbuf), (char *)wbuf);
196 } else {
197 wbuf[0] = '\0';
198 }
199 db_printf("%c%4d %d %3d %9x %18lx %18s %-8s\n",
200 (run ? '>' : ' '), l.l_lid,
201 l.l_stat, cpuno, l.l_flag, (long)lp,
202 db_nbuf, wbuf);
203 lp = LIST_NEXT((&l), l_sibling);
204 if (lp != NULL) {
205 db_printf("%-5d", p.p_pid);
206 db_read_bytes((db_addr_t)lp, sizeof(l),
207 (char *)&l);
208 }
209 }
210 break;
211 case 'n':
212 db_read_bytes((db_addr_t)p.p_pgrp, sizeof(pgrp),
213 (char *)&pgrp);
214 if (lp != NULL && l.l_wchan && l.l_wmesg) {
215 db_read_bytes((db_addr_t)l.l_wmesg,
216 sizeof(wbuf), (char *)wbuf);
217 } else {
218 wbuf[0] = '\0';
219 }
220 db_printf("%8d %8d %10d %d %#7x %4d %16s %7.7s\n",
221 p.p_pptr != NULL ? p.p_pid : -1, pgrp.pg_id,
222#ifdef _KERNEL
223 kauth_cred_getuid(p.p_cred),
224#else
225 /* XXX CRASH(8) */ 666,
226#endif
227 p.p_stat, p.p_flag,
228 p.p_nlwps, p.p_comm,
229 (p.p_nlwps != 1) ? "*" : wbuf);
230 break;
231
232 case 'w':
233 while (lp != NULL) {
234 if (l.l_wchan && l.l_wmesg) {
235 db_read_bytes((db_addr_t)l.l_wmesg,
236 sizeof(wbuf), (char *)wbuf);
237 } else {
238 wbuf[0] = '\0';
239 }
240 run = (l.l_stat == LSONPROC ||
241 (l.l_pflag & LP_RUNNING) != 0);
242 db_read_bytes((db_addr_t)&p.p_emul->e_name,
243 sizeof(ename), (char *)&ename);
244 db_read_bytes((db_addr_t)ename,
245 sizeof(db_nbuf), db_nbuf);
246 db_printf(
247 "%c%4d %16s %8s %4d %-12s %-18lx\n",
248 (run ? '>' : ' '), l.l_lid,
249 p.p_comm, db_nbuf,
250 l.l_priority, wbuf, (long)l.l_wchan);
251 lp = LIST_NEXT((&l), l_sibling);
252 if (lp != NULL) {
253 db_printf("%-5d", p.p_pid);
254 db_read_bytes((db_addr_t)lp, sizeof(l),
255 (char *)&l);
256 }
257 }
258 break;
259 }
260 }
261}
262
263void
264db_show_proc(db_expr_t addr, bool haddr, db_expr_t count, const char *modif)
265{
266 static proc_t p;
267 static lwp_t l;
268 const char *mode;
269 proc_t *pp;
270 lwp_t *lp;
271 char db_nbuf[MAXCOMLEN + 1], wbuf[MAXCOMLEN + 1];
272 bool run;
273 int cpuno;
274
275 if (modif[0] == 0)
276 mode = "p"; /* default == by pid */
277 else
278 mode = strchr("ap", modif[0]);
279
280 if (mode == NULL || !haddr) {
281 db_printf("usage: show proc [/a] [/p] address|pid\n");
282 db_printf("\t/a == argument is an address of any lwp\n");
283 db_printf("\t/p == argument is a pid [default]\n");
284 return;
285 }
286
287 switch (*mode) {
288 case 'a':
289 lp = (lwp_t *)(uintptr_t)addr;
290 db_printf("lwp_t %lx\n", (long)lp);
291 db_read_bytes((db_addr_t)lp, sizeof(l), (char *)&l);
292 pp = l.l_proc;
293 break;
294 default:
295 case 'p':
296 pp = db_proc_find((pid_t)addr);
297 lp = NULL;
298 break;
299 }
300
301 if (pp == NULL) {
302 db_printf("bad address\n");
303 return;
304 }
305
306 db_read_bytes((db_addr_t)pp, sizeof(p), (char *)&p);
307 if (lp == NULL)
308 lp = p.p_lwps.lh_first;
309
310 db_printf("%s: pid %d proc %lx vmspace/map %lx flags %x\n",
311 p.p_comm, p.p_pid, (long)pp, (long)p.p_vmspace, p.p_flag);
312
313 while (lp != NULL) {
314 db_read_bytes((db_addr_t)lp, sizeof(l), (char *)&l);
315
316 run = (l.l_stat == LSONPROC ||
317 (l.l_pflag & LP_RUNNING) != 0);
318
319 db_printf("%slwp %d", (run ? "> " : " "), l.l_lid);
320 if (l.l_name != NULL) {
321 db_read_bytes((db_addr_t)l.l_name,
322 MAXCOMLEN, db_nbuf);
323 db_printf(" [%s]", db_nbuf);
324 }
325 db_printf(" %lx pcb %lx\n", (long)lp, (long)l.l_addr);
326
327 if (l.l_cpu != NULL) {
328 db_read_bytes((db_addr_t)
329 &l.l_cpu->ci_data.cpu_index,
330 sizeof(cpuno), (char *)&cpuno);
331 } else
332 cpuno = -1;
333 db_printf(" stat %d flags %x cpu %d pri %d \n",
334 l.l_stat, l.l_flag, cpuno, l.l_priority);
335
336 if (l.l_wchan && l.l_wmesg) {
337 db_read_bytes((db_addr_t)l.l_wmesg,
338 sizeof(wbuf), (char *)wbuf);
339 db_printf(" wmesg %s wchan %lx\n",
340 wbuf, (long)l.l_wchan);
341 }
342
343 lp = LIST_NEXT(&l, l_sibling);
344 }
345}
346