db_xxx.c revision 1.54 1 /* $NetBSD: db_xxx.c,v 1.54 2008/11/25 15:14:07 ad Exp $ */
2
3 /*
4 * Copyright (c) 1982, 1986, 1989, 1991, 1993
5 * The Regents of the University of California. All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the University nor the names of its contributors
16 * may be used to endorse or promote products derived from this software
17 * without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 *
31 * from: kern_proc.c 8.4 (Berkeley) 1/4/94
32 */
33
34 /*
35 * Miscellaneous DDB functions that are intimate (xxx) with various
36 * data structures and functions used by the kernel (proc, callout).
37 */
38
39 #include <sys/cdefs.h>
40 __KERNEL_RCSID(0, "$NetBSD: db_xxx.c,v 1.54 2008/11/25 15:14:07 ad Exp $");
41
42 #include "opt_kgdb.h"
43 #include "opt_aio.h"
44
45 #include <sys/param.h>
46 #include <sys/systm.h>
47 #include <sys/kernel.h>
48 #include <sys/proc.h>
49 #include <sys/msgbuf.h>
50
51 #include <sys/callout.h>
52 #include <sys/file.h>
53 #include <sys/filedesc.h>
54 #include <sys/lockdebug.h>
55 #include <sys/signalvar.h>
56 #include <sys/resourcevar.h>
57 #include <sys/pool.h>
58 #include <sys/kauth.h>
59 #include <sys/mqueue.h>
60 #include <sys/vnode.h>
61 #include <sys/module.h>
62
63 #include <machine/db_machdep.h>
64
65 #include <ddb/db_access.h>
66 #include <ddb/db_command.h>
67 #include <ddb/db_interface.h>
68 #include <ddb/db_lex.h>
69 #include <ddb/db_output.h>
70 #include <ddb/db_sym.h>
71 #include <ddb/db_extern.h>
72 #ifdef KGDB
73 #include <sys/kgdb.h>
74 #endif
75
76 void
77 db_kill_proc(db_expr_t addr, bool haddr,
78 db_expr_t count, const char *modif)
79 {
80 struct proc *p;
81 db_expr_t pid, sig;
82 int t;
83
84 /* What pid? */
85 if (!db_expression(&pid)) {
86 db_error("pid?\n");
87 /*NOTREACHED*/
88 }
89 /* What sig? */
90 t = db_read_token();
91 if (t == tCOMMA) {
92 if (!db_expression(&sig)) {
93 db_error("sig?\n");
94 /*NOTREACHED*/
95 }
96 } else {
97 db_unread_token(t);
98 sig = 15;
99 }
100 if (db_read_token() != tEOL) {
101 db_error("?\n");
102 /*NOTREACHED*/
103 }
104
105 p = pfind((pid_t)pid);
106 if (p == NULL) {
107 db_error("no such proc\n");
108 /*NOTREACHED*/
109 }
110 psignal(p, (int)sig);
111 }
112
113 #ifdef KGDB
114 void
115 db_kgdb_cmd(db_expr_t addr, bool haddr,
116 db_expr_t count, const char *modif)
117 {
118 kgdb_active++;
119 kgdb_trap(db_trap_type, DDB_REGS);
120 kgdb_active--;
121 }
122 #endif
123
124 void
125 db_show_files_cmd(db_expr_t addr, bool haddr,
126 db_expr_t count, const char *modif)
127 {
128 struct proc *p;
129 int i;
130 filedesc_t *fdp;
131 fdfile_t *ff;
132 file_t *fp;
133 struct vnode *vn;
134 bool full = false;
135
136 if (modif[0] == 'f')
137 full = true;
138
139 p = (struct proc *) (uintptr_t) addr;
140
141 fdp = p->p_fd;
142 for (i = 0; i < fdp->fd_nfiles; i++) {
143 if ((ff = fdp->fd_ofiles[i]) == NULL)
144 continue;
145
146 fp = ff->ff_file;
147
148 /* Only look at vnodes... */
149 if ((fp != NULL) && (fp->f_type == DTYPE_VNODE)) {
150 if (fp->f_data != NULL) {
151 vn = (struct vnode *) fp->f_data;
152 vfs_vnode_print(vn, full, db_printf);
153
154 #ifdef LOCKDEBUG
155 db_printf("\nv_uobj.vmobjlock lock details:\n");
156 lockdebug_lock_print(&(vn->v_uobj.vmobjlock),
157 db_printf);
158 db_printf("\n");
159 #endif
160 }
161 }
162 }
163 }
164
165 #ifdef AIO
166 void
167 db_show_aio_jobs(db_expr_t addr, bool haddr,
168 db_expr_t count, const char *modif)
169 {
170 aio_print_jobs(db_printf);
171 }
172 #endif
173
174 void
175 db_show_mqueue_cmd(db_expr_t addr, bool haddr,
176 db_expr_t count, const char *modif)
177 {
178 mqueue_print_list(db_printf);
179 }
180
181 void
182 db_show_module_cmd(db_expr_t addr, bool haddr,
183 db_expr_t count, const char *modif)
184 {
185 module_print_list(db_printf);
186 }
187
188 void
189 db_show_all_procs(db_expr_t addr, bool haddr,
190 db_expr_t count, const char *modif)
191 {
192 const char *mode;
193 struct proc *p, *pp, *cp;
194 struct lwp *l, *cl;
195 const struct proclist_desc *pd;
196 char db_nbuf[MAXCOMLEN + 1];
197
198 if (modif[0] == 0)
199 mode = "n"; /* default == normal mode */
200 else
201 mode = strchr("mawln", modif[0]);
202
203 if (mode == NULL || *mode == 'm') {
204 db_printf("usage: show all procs [/a] [/l] [/n] [/w]\n");
205 db_printf("\t/a == show process address info\n");
206 db_printf("\t/l == show LWP info\n");
207 db_printf("\t/n == show normal process info [default]\n");
208 db_printf("\t/w == show process wait/emul info\n");
209 return;
210 }
211
212 switch (*mode) {
213 case 'a':
214 db_printf(" PID %10s %18s %18s %18s\n",
215 "COMMAND", "STRUCT PROC *", "UAREA *", "VMSPACE/VM_MAP");
216 break;
217 case 'l':
218 db_printf(" PID %4s S %9s %18s %18s %-8s\n",
219 "LID", "FLAGS", "STRUCT LWP *", "NAME", "WAIT");
220 break;
221 case 'n':
222 db_printf(" PID %8s %8s %10s S %7s %4s %16s %7s\n",
223 "PPID", "PGRP", "UID", "FLAGS", "LWPS", "COMMAND", "WAIT");
224 break;
225 case 'w':
226 db_printf(" PID %4s %16s %8s %4s %-12s%s\n",
227 "LID", "COMMAND", "EMUL", "PRI", "WAIT-MSG",
228 "WAIT-CHANNEL");
229 break;
230 }
231
232 /* XXX LOCKING XXX */
233 pd = proclists;
234 cp = curproc;
235 cl = curlwp;
236 for (pd = proclists; pd->pd_list != NULL; pd++) {
237 LIST_FOREACH(p, pd->pd_list, p_list) {
238 pp = p->p_pptr;
239 if (p->p_stat == 0) {
240 continue;
241 }
242 l = LIST_FIRST(&p->p_lwps);
243 db_printf("%c%-10d", (cp == p ? '>' : ' '), p->p_pid);
244
245 switch (*mode) {
246
247 case 'a':
248 db_printf("%10.10s %18lx %18lx %18lx\n",
249 p->p_comm, (long)p,
250 (long)(l != NULL ? l->l_addr : 0),
251 (long)p->p_vmspace);
252 break;
253 case 'l':
254 while (l != NULL) {
255 if (l->l_name != NULL) {
256 snprintf(db_nbuf,
257 sizeof(db_nbuf),
258 "%s", l->l_name);
259 } else
260 snprintf(db_nbuf,
261 sizeof(db_nbuf),
262 "%s", p->p_comm);
263 db_printf("%c%4d %d %9x %18lx %18s %-8s\n",
264 (cl == l ? '>' : ' '), l->l_lid,
265 l->l_stat, l->l_flag, (long)l,
266 db_nbuf,
267 (l->l_wchan && l->l_wmesg) ?
268 l->l_wmesg : "");
269
270 l = LIST_NEXT(l, l_sibling);
271 if (l)
272 db_printf("%11s","");
273 }
274 break;
275 case 'n':
276 db_printf("%8d %8d %10d %d %#7x %4d %16s %7.7s\n",
277 pp ? pp->p_pid : -1, p->p_pgrp->pg_id,
278 kauth_cred_getuid(p->p_cred), p->p_stat, p->p_flag,
279 p->p_nlwps, p->p_comm,
280 (p->p_nlwps != 1) ? "*" : (
281 (l->l_wchan && l->l_wmesg) ?
282 l->l_wmesg : ""));
283 break;
284
285 case 'w':
286 while (l != NULL) {
287 db_printf(
288 "%4d %16s %8s %4d %-12s %-18lx\n",
289 l->l_lid, p->p_comm,
290 p->p_emul->e_name, l->l_priority,
291 (l->l_wchan && l->l_wmesg) ?
292 l->l_wmesg : "", (long)l->l_wchan);
293 l = LIST_NEXT(l, l_sibling);
294 if (l != NULL) {
295 db_printf("%c%-10d", (cp == p ?
296 '>' : ' '), p->p_pid);
297 }
298 }
299 break;
300 }
301 }
302 }
303 }
304
305 void
306 db_show_all_pools(db_expr_t addr, bool haddr,
307 db_expr_t count, const char *modif)
308 {
309
310 pool_printall(modif, db_printf);
311 }
312
313 void
314 db_dmesg(db_expr_t addr, bool haddr, db_expr_t count,
315 const char *modif)
316 {
317 struct kern_msgbuf *mbp;
318 db_expr_t print;
319 int ch, newl, skip, i;
320 char *p, *bufdata;
321
322 if (!msgbufenabled || msgbufp->msg_magic != MSG_MAGIC) {
323 db_printf("message buffer not available\n");
324 return;
325 }
326
327 mbp = msgbufp;
328 bufdata = &mbp->msg_bufc[0];
329
330 if (haddr && addr < mbp->msg_bufs)
331 print = addr;
332 else
333 print = mbp->msg_bufs;
334
335 for (newl = skip = i = 0, p = bufdata + mbp->msg_bufx;
336 i < mbp->msg_bufs; i++, p++) {
337 if (p == bufdata + mbp->msg_bufs)
338 p = bufdata;
339 if (i < mbp->msg_bufs - print)
340 continue;
341 ch = *p;
342 /* Skip "\n<.*>" syslog sequences. */
343 if (skip) {
344 if (ch == '>')
345 newl = skip = 0;
346 continue;
347 }
348 if (newl && ch == '<') {
349 skip = 1;
350 continue;
351 }
352 if (ch == '\0')
353 continue;
354 newl = ch == '\n';
355 db_printf("%c", ch);
356 }
357 if (!newl)
358 db_printf("\n");
359 }
360
361 void
362 db_show_sched_qs(db_expr_t addr, bool haddr,
363 db_expr_t count, const char *modif)
364 {
365
366 sched_print_runqueue(db_printf);
367 }
368