1 | /* $NetBSD: db_xxx.c,v 1.71 2015/02/27 00:47:30 ozaki-r 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.71 2015/02/27 00:47:30 ozaki-r Exp $" ); |
41 | |
42 | #ifdef _KERNEL_OPT |
43 | #include "opt_kgdb.h" |
44 | #include "opt_aio.h" |
45 | #include "opt_mqueue.h" |
46 | #endif |
47 | |
48 | #ifndef _KERNEL |
49 | #include <stdbool.h> |
50 | #endif |
51 | |
52 | #include <sys/param.h> |
53 | #include <sys/systm.h> |
54 | #include <sys/kernel.h> |
55 | #include <sys/proc.h> |
56 | #include <sys/msgbuf.h> |
57 | #include <sys/callout.h> |
58 | #include <sys/file.h> |
59 | #include <sys/filedesc.h> |
60 | #include <sys/lockdebug.h> |
61 | #include <sys/signalvar.h> |
62 | #include <sys/resourcevar.h> |
63 | #include <sys/pool.h> |
64 | #include <sys/uio.h> |
65 | #include <sys/kauth.h> |
66 | #include <sys/mqueue.h> |
67 | #include <sys/vnode.h> |
68 | #include <sys/module.h> |
69 | #include <sys/cpu.h> |
70 | #include <sys/vmem.h> |
71 | |
72 | #include <ddb/ddb.h> |
73 | #include <ddb/db_user.h> |
74 | |
75 | #ifdef KGDB |
76 | #include <sys/kgdb.h> |
77 | #endif |
78 | |
79 | void |
80 | db_kill_proc(db_expr_t addr, bool haddr, |
81 | db_expr_t count, const char *modif) |
82 | { |
83 | #ifdef _KERNEL /* XXX CRASH(8) */ |
84 | struct proc *p; |
85 | ksiginfo_t ksi; |
86 | db_expr_t pid, sig; |
87 | int t; |
88 | |
89 | /* What pid? */ |
90 | if (!db_expression(&pid)) { |
91 | db_error("pid?\n" ); |
92 | /*NOTREACHED*/ |
93 | } |
94 | /* What sig? */ |
95 | t = db_read_token(); |
96 | if (t == tCOMMA) { |
97 | if (!db_expression(&sig)) { |
98 | db_error("sig?\n" ); |
99 | /*NOTREACHED*/ |
100 | } |
101 | } else { |
102 | db_unread_token(t); |
103 | sig = 15; |
104 | } |
105 | if (db_read_token() != tEOL) { |
106 | db_error("?\n" ); |
107 | /*NOTREACHED*/ |
108 | } |
109 | /* We might stop when the mutex is held or when not */ |
110 | t = mutex_tryenter(proc_lock); |
111 | #ifdef DIAGNOSTIC |
112 | if (!t) { |
113 | db_error("could not acquire proc_lock mutex\n" ); |
114 | /*NOTREACHED*/ |
115 | } |
116 | #endif |
117 | p = proc_find((pid_t)pid); |
118 | if (p == NULL) { |
119 | if (t) |
120 | mutex_exit(proc_lock); |
121 | db_error("no such proc\n" ); |
122 | /*NOTREACHED*/ |
123 | } |
124 | KSI_INIT(&ksi); |
125 | ksi.ksi_signo = sig; |
126 | ksi.ksi_code = SI_USER; |
127 | ksi.ksi_pid = 0; |
128 | ksi.ksi_uid = 0; |
129 | mutex_enter(p->p_lock); |
130 | kpsignal2(p, &ksi); |
131 | mutex_exit(p->p_lock); |
132 | if (t) |
133 | mutex_exit(proc_lock); |
134 | #else |
135 | db_printf("This command is not currently supported.\n" ); |
136 | #endif |
137 | } |
138 | |
139 | #ifdef KGDB |
140 | void |
141 | db_kgdb_cmd(db_expr_t addr, bool haddr, |
142 | db_expr_t count, const char *modif) |
143 | { |
144 | kgdb_active++; |
145 | kgdb_trap(db_trap_type, DDB_REGS); |
146 | kgdb_active--; |
147 | } |
148 | #endif |
149 | |
150 | void |
151 | db_show_files_cmd(db_expr_t addr, bool haddr, |
152 | db_expr_t count, const char *modif) |
153 | { |
154 | #ifdef _KERNEL /* XXX CRASH(8) */ |
155 | struct proc *p; |
156 | int i; |
157 | filedesc_t *fdp; |
158 | fdfile_t *ff; |
159 | file_t *fp; |
160 | struct vnode *vp; |
161 | bool full = false; |
162 | fdtab_t *dt; |
163 | |
164 | if (!haddr) { |
165 | db_printf("usage: show files address\n" ); |
166 | db_printf("\taddress == an address of a proc structure\n" ); |
167 | return; |
168 | } |
169 | |
170 | if (modif[0] == 'f') |
171 | full = true; |
172 | |
173 | p = (struct proc *) (uintptr_t) addr; |
174 | |
175 | fdp = p->p_fd; |
176 | dt = fdp->fd_dt; |
177 | for (i = 0; i < dt->dt_nfiles; i++) { |
178 | if ((ff = dt->dt_ff[i]) == NULL) |
179 | continue; |
180 | |
181 | fp = ff->ff_file; |
182 | |
183 | /* Only look at vnodes... */ |
184 | if (fp != NULL && fp->f_type == DTYPE_VNODE |
185 | && fp->f_vnode != NULL) { |
186 | vp = fp->f_vnode; |
187 | vfs_vnode_print(vp, full, db_printf); |
188 | |
189 | #ifdef LOCKDEBUG |
190 | db_printf("\nv_uobj.vmobjlock lock details:\n" ); |
191 | lockdebug_lock_print(vp->v_uobj.vmobjlock, db_printf); |
192 | db_printf("\n" ); |
193 | #endif |
194 | } |
195 | } |
196 | #endif |
197 | } |
198 | |
199 | #ifdef AIO |
200 | void |
201 | db_show_aio_jobs(db_expr_t addr, bool haddr, |
202 | db_expr_t count, const char *modif) |
203 | { |
204 | |
205 | aio_print_jobs(db_printf); |
206 | } |
207 | #endif |
208 | |
209 | #ifdef MQUEUE |
210 | void |
211 | db_show_mqueue_cmd(db_expr_t addr, bool haddr, |
212 | db_expr_t count, const char *modif) |
213 | { |
214 | |
215 | #ifdef _KERNEL /* XXX CRASH(8) */ |
216 | mqueue_print_list(db_printf); |
217 | #endif |
218 | } |
219 | #endif |
220 | |
221 | void |
222 | db_show_module_cmd(db_expr_t addr, bool haddr, |
223 | db_expr_t count, const char *modif) |
224 | { |
225 | |
226 | #ifdef _KERNEL /* XXX CRASH(8) */ |
227 | module_print_list(db_printf); |
228 | #endif |
229 | } |
230 | |
231 | void |
232 | db_show_all_pools(db_expr_t addr, bool haddr, |
233 | db_expr_t count, const char *modif) |
234 | { |
235 | |
236 | #ifdef _KERNEL /* XXX CRASH(8) */ |
237 | pool_printall(modif, db_printf); |
238 | #endif |
239 | } |
240 | |
241 | void |
242 | db_show_all_vmems(db_expr_t addr, bool have_addr, |
243 | db_expr_t count, const char *modif) |
244 | { |
245 | |
246 | #ifdef _KERNEL /* XXX CRASH(8) */ |
247 | vmem_printall(modif, db_printf); |
248 | #endif |
249 | } |
250 | |
251 | void |
252 | db_dmesg(db_expr_t addr, bool haddr, db_expr_t count, const char *modif) |
253 | { |
254 | struct kern_msgbuf mb, *mbp; |
255 | db_expr_t print; |
256 | int newl, skip, i; |
257 | char *p, *bufdata, ch; |
258 | |
259 | if (!db_read_int("msgbufenabled" )) { |
260 | db_printf("message buffer not available\n" ); |
261 | return; |
262 | } |
263 | mbp = (struct kern_msgbuf *)db_read_ptr("msgbufp" ); |
264 | db_read_bytes((db_addr_t)mbp, sizeof(mb), (char *)&mb); |
265 | if (mb.msg_magic != MSG_MAGIC) { |
266 | db_printf("message buffer not available\n" ); |
267 | return; |
268 | } |
269 | |
270 | bufdata = &mbp->msg_bufc[0]; |
271 | |
272 | if (haddr && addr < mb.msg_bufs) |
273 | print = addr; |
274 | else |
275 | print = mb.msg_bufs; |
276 | |
277 | for (newl = skip = i = 0, p = bufdata + mb.msg_bufx; |
278 | i < mb.msg_bufs; i++, p++) { |
279 | if (p == bufdata + mb.msg_bufs) |
280 | p = bufdata; |
281 | if (i < mb.msg_bufs - print) { |
282 | continue; |
283 | } |
284 | db_read_bytes((db_addr_t)p, sizeof(ch), &ch); |
285 | /* Skip "\n<.*>" syslog sequences. */ |
286 | if (skip) { |
287 | if (ch == '>') |
288 | newl = skip = 0; |
289 | continue; |
290 | } |
291 | if (newl && ch == '<') { |
292 | skip = 1; |
293 | continue; |
294 | } |
295 | if (ch == '\0') |
296 | continue; |
297 | newl = ch == '\n'; |
298 | db_printf("%c" , ch); |
299 | } |
300 | if (!newl) |
301 | db_printf("\n" ); |
302 | } |
303 | |
304 | void |
305 | db_show_sched_qs(db_expr_t addr, bool haddr, |
306 | db_expr_t count, const char *modif) |
307 | { |
308 | |
309 | #ifdef _KERNEL /* XXX CRASH(8) */ |
310 | sched_print_runqueue(db_printf); |
311 | #endif |
312 | } |
313 | |
314 | void |
315 | db_show_panic(db_expr_t addr, bool haddr, db_expr_t count, const char *modif) |
316 | { |
317 | #ifdef _KERNEL /* XXX CRASH(8) */ |
318 | int s; |
319 | |
320 | s = splhigh(); |
321 | |
322 | db_printf("Panic string: %s\n" , panicstr); |
323 | |
324 | (void)splx(s); |
325 | #endif |
326 | } |
327 | |