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 | |
79 | proc_t * |
80 | db_proc_first(void) |
81 | { |
82 | |
83 | return db_read_ptr("allproc" ); |
84 | } |
85 | |
86 | proc_t * |
87 | db_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 | |
94 | proc_t * |
95 | db_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 | |
110 | void |
111 | db_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 | |
263 | void |
264 | db_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 | |