| @@ -1,298 +1,308 @@ | | | @@ -1,298 +1,308 @@ |
1 | /* $NetBSD: db_xxx.c,v 1.65 2011/12/02 23:57:58 christos Exp $ */ | | 1 | /* $NetBSD: db_xxx.c,v 1.66 2011/12/03 16:25:49 christos Exp $ */ |
2 | | | 2 | |
3 | /* | | 3 | /* |
4 | * Copyright (c) 1982, 1986, 1989, 1991, 1993 | | 4 | * Copyright (c) 1982, 1986, 1989, 1991, 1993 |
5 | * The Regents of the University of California. All rights reserved. | | 5 | * The Regents of the University of California. All rights reserved. |
6 | * | | 6 | * |
7 | * Redistribution and use in source and binary forms, with or without | | 7 | * Redistribution and use in source and binary forms, with or without |
8 | * modification, are permitted provided that the following conditions | | 8 | * modification, are permitted provided that the following conditions |
9 | * are met: | | 9 | * are met: |
10 | * 1. Redistributions of source code must retain the above copyright | | 10 | * 1. Redistributions of source code must retain the above copyright |
11 | * notice, this list of conditions and the following disclaimer. | | 11 | * notice, this list of conditions and the following disclaimer. |
12 | * 2. Redistributions in binary form must reproduce the above copyright | | 12 | * 2. Redistributions in binary form must reproduce the above copyright |
13 | * notice, this list of conditions and the following disclaimer in the | | 13 | * notice, this list of conditions and the following disclaimer in the |
14 | * documentation and/or other materials provided with the distribution. | | 14 | * documentation and/or other materials provided with the distribution. |
15 | * 3. Neither the name of the University nor the names of its contributors | | 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 | | 16 | * may be used to endorse or promote products derived from this software |
17 | * without specific prior written permission. | | 17 | * without specific prior written permission. |
18 | * | | 18 | * |
19 | * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND | | 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 | | 20 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
21 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | | 21 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
22 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE | | 22 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE |
23 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | | 23 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
24 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | | 24 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS |
25 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | | 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 | | 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 | | 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 | | 28 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
29 | * SUCH DAMAGE. | | 29 | * SUCH DAMAGE. |
30 | * | | 30 | * |
31 | * from: kern_proc.c 8.4 (Berkeley) 1/4/94 | | 31 | * from: kern_proc.c 8.4 (Berkeley) 1/4/94 |
32 | */ | | 32 | */ |
33 | | | 33 | |
34 | /* | | 34 | /* |
35 | * Miscellaneous DDB functions that are intimate (xxx) with various | | 35 | * Miscellaneous DDB functions that are intimate (xxx) with various |
36 | * data structures and functions used by the kernel (proc, callout). | | 36 | * data structures and functions used by the kernel (proc, callout). |
37 | */ | | 37 | */ |
38 | | | 38 | |
39 | #include <sys/cdefs.h> | | 39 | #include <sys/cdefs.h> |
40 | __KERNEL_RCSID(0, "$NetBSD: db_xxx.c,v 1.65 2011/12/02 23:57:58 christos Exp $"); | | 40 | __KERNEL_RCSID(0, "$NetBSD: db_xxx.c,v 1.66 2011/12/03 16:25:49 christos Exp $"); |
41 | | | 41 | |
42 | #ifdef _KERNEL_OPT | | 42 | #ifdef _KERNEL_OPT |
43 | #include "opt_kgdb.h" | | 43 | #include "opt_kgdb.h" |
44 | #include "opt_aio.h" | | 44 | #include "opt_aio.h" |
45 | #include "opt_mqueue.h" | | 45 | #include "opt_mqueue.h" |
46 | #endif | | 46 | #endif |
47 | | | 47 | |
48 | #ifndef _KERNEL | | 48 | #ifndef _KERNEL |
49 | #include <stdbool.h> | | 49 | #include <stdbool.h> |
50 | #endif | | 50 | #endif |
51 | | | 51 | |
52 | #include <sys/param.h> | | 52 | #include <sys/param.h> |
53 | #include <sys/systm.h> | | 53 | #include <sys/systm.h> |
54 | #include <sys/kernel.h> | | 54 | #include <sys/kernel.h> |
55 | #include <sys/proc.h> | | 55 | #include <sys/proc.h> |
56 | #include <sys/msgbuf.h> | | 56 | #include <sys/msgbuf.h> |
57 | #include <sys/callout.h> | | 57 | #include <sys/callout.h> |
58 | #include <sys/file.h> | | 58 | #include <sys/file.h> |
59 | #include <sys/filedesc.h> | | 59 | #include <sys/filedesc.h> |
60 | #include <sys/lockdebug.h> | | 60 | #include <sys/lockdebug.h> |
61 | #include <sys/signalvar.h> | | 61 | #include <sys/signalvar.h> |
62 | #include <sys/resourcevar.h> | | 62 | #include <sys/resourcevar.h> |
63 | #include <sys/pool.h> | | 63 | #include <sys/pool.h> |
64 | #include <sys/uio.h> | | 64 | #include <sys/uio.h> |
65 | #include <sys/kauth.h> | | 65 | #include <sys/kauth.h> |
66 | #include <sys/mqueue.h> | | 66 | #include <sys/mqueue.h> |
67 | #include <sys/vnode.h> | | 67 | #include <sys/vnode.h> |
68 | #include <sys/module.h> | | 68 | #include <sys/module.h> |
69 | #include <sys/cpu.h> | | 69 | #include <sys/cpu.h> |
70 | #include <sys/vmem.h> | | 70 | #include <sys/vmem.h> |
71 | | | 71 | |
72 | #include <ddb/ddb.h> | | 72 | #include <ddb/ddb.h> |
73 | #include <ddb/db_user.h> | | 73 | #include <ddb/db_user.h> |
74 | | | 74 | |
75 | #ifdef KGDB | | 75 | #ifdef KGDB |
76 | #include <sys/kgdb.h> | | 76 | #include <sys/kgdb.h> |
77 | #endif | | 77 | #endif |
78 | | | 78 | |
79 | void | | 79 | void |
80 | db_kill_proc(db_expr_t addr, bool haddr, | | 80 | db_kill_proc(db_expr_t addr, bool haddr, |
81 | db_expr_t count, const char *modif) | | 81 | db_expr_t count, const char *modif) |
82 | { | | 82 | { |
83 | #ifdef _KERNEL /* XXX CRASH(8) */ | | 83 | #ifdef _KERNEL /* XXX CRASH(8) */ |
84 | struct proc *p; | | 84 | struct proc *p; |
85 | ksiginfo_t ksi; | | 85 | ksiginfo_t ksi; |
86 | db_expr_t pid, sig; | | 86 | db_expr_t pid, sig; |
87 | int t; | | 87 | int t; |
88 | | | 88 | |
89 | /* What pid? */ | | 89 | /* What pid? */ |
90 | if (!db_expression(&pid)) { | | 90 | if (!db_expression(&pid)) { |
91 | db_error("pid?\n"); | | 91 | db_error("pid?\n"); |
92 | /*NOTREACHED*/ | | 92 | /*NOTREACHED*/ |
93 | } | | 93 | } |
94 | /* What sig? */ | | 94 | /* What sig? */ |
95 | t = db_read_token(); | | 95 | t = db_read_token(); |
96 | if (t == tCOMMA) { | | 96 | if (t == tCOMMA) { |
97 | if (!db_expression(&sig)) { | | 97 | if (!db_expression(&sig)) { |
98 | db_error("sig?\n"); | | 98 | db_error("sig?\n"); |
99 | /*NOTREACHED*/ | | 99 | /*NOTREACHED*/ |
100 | } | | 100 | } |
101 | } else { | | 101 | } else { |
102 | db_unread_token(t); | | 102 | db_unread_token(t); |
103 | sig = 15; | | 103 | sig = 15; |
104 | } | | 104 | } |
105 | if (db_read_token() != tEOL) { | | 105 | if (db_read_token() != tEOL) { |
106 | db_error("?\n"); | | 106 | db_error("?\n"); |
107 | /*NOTREACHED*/ | | 107 | /*NOTREACHED*/ |
108 | } | | 108 | } |
109 | /* We might stop when the mutex is held or when not */ | | 109 | /* We might stop when the mutex is held or when not */ |
110 | t = mutex_tryenter(proc_lock); | | 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 |
111 | p = proc_find((pid_t)pid); | | 117 | p = proc_find((pid_t)pid); |
112 | if (t) | | | |
113 | mutex_exit(proc_lock); | | | |
114 | if (p == NULL) { | | 118 | if (p == NULL) { |
115 | db_error("no such proc\n"); | | 119 | if (t) |
116 | /*NOTREACHED*/ | | 120 | mutex_exit(proc_lock); |
| | | 121 | db_error("no such proc\n"); |
| | | 122 | /*NOTREACHED*/ |
117 | } | | 123 | } |
118 | KSI_INIT(&ksi); | | 124 | KSI_INIT(&ksi); |
119 | ksi.ksi_signo = sig; | | 125 | ksi.ksi_signo = sig; |
120 | ksi.ksi_code = SI_USER; | | 126 | ksi.ksi_code = SI_USER; |
121 | ksi.ksi_pid = 0; | | 127 | ksi.ksi_pid = 0; |
122 | ksi.ksi_uid = 0; | | 128 | ksi.ksi_uid = 0; |
| | | 129 | mutex_enter(p->p_lock); |
123 | kpsignal2(p, &ksi); | | 130 | kpsignal2(p, &ksi); |
| | | 131 | mutex_exit(p->p_lock); |
| | | 132 | if (t) |
| | | 133 | mutex_exit(proc_lock); |
124 | #else | | 134 | #else |
125 | db_printf("This command is not currently supported.\n"); | | 135 | db_printf("This command is not currently supported.\n"); |
126 | #endif | | 136 | #endif |
127 | } | | 137 | } |
128 | | | 138 | |
129 | #ifdef KGDB | | 139 | #ifdef KGDB |
130 | void | | 140 | void |
131 | db_kgdb_cmd(db_expr_t addr, bool haddr, | | 141 | db_kgdb_cmd(db_expr_t addr, bool haddr, |
132 | db_expr_t count, const char *modif) | | 142 | db_expr_t count, const char *modif) |
133 | { | | 143 | { |
134 | kgdb_active++; | | 144 | kgdb_active++; |
135 | kgdb_trap(db_trap_type, DDB_REGS); | | 145 | kgdb_trap(db_trap_type, DDB_REGS); |
136 | kgdb_active--; | | 146 | kgdb_active--; |
137 | } | | 147 | } |
138 | #endif | | 148 | #endif |
139 | | | 149 | |
140 | void | | 150 | void |
141 | db_show_files_cmd(db_expr_t addr, bool haddr, | | 151 | db_show_files_cmd(db_expr_t addr, bool haddr, |
142 | db_expr_t count, const char *modif) | | 152 | db_expr_t count, const char *modif) |
143 | { | | 153 | { |
144 | #ifdef _KERNEL /* XXX CRASH(8) */ | | 154 | #ifdef _KERNEL /* XXX CRASH(8) */ |
145 | struct proc *p; | | 155 | struct proc *p; |
146 | int i; | | 156 | int i; |
147 | filedesc_t *fdp; | | 157 | filedesc_t *fdp; |
148 | fdfile_t *ff; | | 158 | fdfile_t *ff; |
149 | file_t *fp; | | 159 | file_t *fp; |
150 | struct vnode *vn; | | 160 | struct vnode *vn; |
151 | bool full = false; | | 161 | bool full = false; |
152 | fdtab_t *dt; | | 162 | fdtab_t *dt; |
153 | | | 163 | |
154 | if (modif[0] == 'f') | | 164 | if (modif[0] == 'f') |
155 | full = true; | | 165 | full = true; |
156 | | | 166 | |
157 | p = (struct proc *) (uintptr_t) addr; | | 167 | p = (struct proc *) (uintptr_t) addr; |
158 | | | 168 | |
159 | fdp = p->p_fd; | | 169 | fdp = p->p_fd; |
160 | dt = fdp->fd_dt; | | 170 | dt = fdp->fd_dt; |
161 | for (i = 0; i < dt->dt_nfiles; i++) { | | 171 | for (i = 0; i < dt->dt_nfiles; i++) { |
162 | if ((ff = dt->dt_ff[i]) == NULL) | | 172 | if ((ff = dt->dt_ff[i]) == NULL) |
163 | continue; | | 173 | continue; |
164 | | | 174 | |
165 | fp = ff->ff_file; | | 175 | fp = ff->ff_file; |
166 | | | 176 | |
167 | /* Only look at vnodes... */ | | 177 | /* Only look at vnodes... */ |
168 | if ((fp != NULL) && (fp->f_type == DTYPE_VNODE)) { | | 178 | if ((fp != NULL) && (fp->f_type == DTYPE_VNODE)) { |
169 | if (fp->f_data != NULL) { | | 179 | if (fp->f_data != NULL) { |
170 | vn = (struct vnode *) fp->f_data; | | 180 | vn = (struct vnode *) fp->f_data; |
171 | vfs_vnode_print(vn, full, db_printf); | | 181 | vfs_vnode_print(vn, full, db_printf); |
172 | | | 182 | |
173 | #ifdef LOCKDEBUG | | 183 | #ifdef LOCKDEBUG |
174 | db_printf("\nv_uobj.vmobjlock lock details:\n"); | | 184 | db_printf("\nv_uobj.vmobjlock lock details:\n"); |
175 | lockdebug_lock_print(vn->v_uobj.vmobjlock, | | 185 | lockdebug_lock_print(vn->v_uobj.vmobjlock, |
176 | db_printf); | | 186 | db_printf); |
177 | db_printf("\n"); | | 187 | db_printf("\n"); |
178 | #endif | | 188 | #endif |
179 | } | | 189 | } |
180 | } | | 190 | } |
181 | } | | 191 | } |
182 | #endif | | 192 | #endif |
183 | } | | 193 | } |
184 | | | 194 | |
185 | #ifdef AIO | | 195 | #ifdef AIO |
186 | void | | 196 | void |
187 | db_show_aio_jobs(db_expr_t addr, bool haddr, | | 197 | db_show_aio_jobs(db_expr_t addr, bool haddr, |
188 | db_expr_t count, const char *modif) | | 198 | db_expr_t count, const char *modif) |
189 | { | | 199 | { |
190 | | | 200 | |
191 | aio_print_jobs(db_printf); | | 201 | aio_print_jobs(db_printf); |
192 | } | | 202 | } |
193 | #endif | | 203 | #endif |
194 | | | 204 | |
195 | #ifdef MQUEUE | | 205 | #ifdef MQUEUE |
196 | void | | 206 | void |
197 | db_show_mqueue_cmd(db_expr_t addr, bool haddr, | | 207 | db_show_mqueue_cmd(db_expr_t addr, bool haddr, |
198 | db_expr_t count, const char *modif) | | 208 | db_expr_t count, const char *modif) |
199 | { | | 209 | { |
200 | | | 210 | |
201 | #ifdef _KERNEL /* XXX CRASH(8) */ | | 211 | #ifdef _KERNEL /* XXX CRASH(8) */ |
202 | mqueue_print_list(db_printf); | | 212 | mqueue_print_list(db_printf); |
203 | #endif | | 213 | #endif |
204 | } | | 214 | } |
205 | #endif | | 215 | #endif |
206 | | | 216 | |
207 | void | | 217 | void |
208 | db_show_module_cmd(db_expr_t addr, bool haddr, | | 218 | db_show_module_cmd(db_expr_t addr, bool haddr, |
209 | db_expr_t count, const char *modif) | | 219 | db_expr_t count, const char *modif) |
210 | { | | 220 | { |
211 | | | 221 | |
212 | #ifdef _KERNEL /* XXX CRASH(8) */ | | 222 | #ifdef _KERNEL /* XXX CRASH(8) */ |
213 | module_print_list(db_printf); | | 223 | module_print_list(db_printf); |
214 | #endif | | 224 | #endif |
215 | } | | 225 | } |
216 | | | 226 | |
217 | void | | 227 | void |
218 | db_show_all_pools(db_expr_t addr, bool haddr, | | 228 | db_show_all_pools(db_expr_t addr, bool haddr, |
219 | db_expr_t count, const char *modif) | | 229 | db_expr_t count, const char *modif) |
220 | { | | 230 | { |
221 | | | 231 | |
222 | #ifdef _KERNEL /* XXX CRASH(8) */ | | 232 | #ifdef _KERNEL /* XXX CRASH(8) */ |
223 | pool_printall(modif, db_printf); | | 233 | pool_printall(modif, db_printf); |
224 | #endif | | 234 | #endif |
225 | } | | 235 | } |
226 | | | 236 | |
227 | void | | 237 | void |
228 | db_show_all_vmems(db_expr_t addr, bool have_addr, | | 238 | db_show_all_vmems(db_expr_t addr, bool have_addr, |
229 | db_expr_t count, const char *modif) | | 239 | db_expr_t count, const char *modif) |
230 | { | | 240 | { |
231 | | | 241 | |
232 | #ifdef _KERNEL /* XXX CRASH(8) */ | | 242 | #ifdef _KERNEL /* XXX CRASH(8) */ |
233 | vmem_printall(modif, db_printf); | | 243 | vmem_printall(modif, db_printf); |
234 | #endif | | 244 | #endif |
235 | } | | 245 | } |
236 | | | 246 | |
237 | void | | 247 | void |
238 | db_dmesg(db_expr_t addr, bool haddr, db_expr_t count, const char *modif) | | 248 | db_dmesg(db_expr_t addr, bool haddr, db_expr_t count, const char *modif) |
239 | { | | 249 | { |
240 | struct kern_msgbuf mb, *mbp; | | 250 | struct kern_msgbuf mb, *mbp; |
241 | db_expr_t print; | | 251 | db_expr_t print; |
242 | int newl, skip, i; | | 252 | int newl, skip, i; |
243 | char *p, *bufdata, ch; | | 253 | char *p, *bufdata, ch; |
244 | | | 254 | |
245 | if (!db_read_int("msgbufenabled")) { | | 255 | if (!db_read_int("msgbufenabled")) { |
246 | db_printf("message buffer not available\n"); | | 256 | db_printf("message buffer not available\n"); |
247 | return; | | 257 | return; |
248 | } | | 258 | } |
249 | mbp = (struct kern_msgbuf *)db_read_ptr("msgbufp"); | | 259 | mbp = (struct kern_msgbuf *)db_read_ptr("msgbufp"); |
250 | db_read_bytes((db_addr_t)mbp, sizeof(mb), (char *)&mb); | | 260 | db_read_bytes((db_addr_t)mbp, sizeof(mb), (char *)&mb); |
251 | if (mb.msg_magic != MSG_MAGIC) { | | 261 | if (mb.msg_magic != MSG_MAGIC) { |
252 | db_printf("message buffer not available\n"); | | 262 | db_printf("message buffer not available\n"); |
253 | return; | | 263 | return; |
254 | } | | 264 | } |
255 | | | 265 | |
256 | bufdata = &mbp->msg_bufc[0]; | | 266 | bufdata = &mbp->msg_bufc[0]; |
257 | | | 267 | |
258 | if (haddr && addr < mb.msg_bufs) | | 268 | if (haddr && addr < mb.msg_bufs) |
259 | print = addr; | | 269 | print = addr; |
260 | else | | 270 | else |
261 | print = mb.msg_bufs; | | 271 | print = mb.msg_bufs; |
262 | | | 272 | |
263 | for (newl = skip = i = 0, p = bufdata + mb.msg_bufx; | | 273 | for (newl = skip = i = 0, p = bufdata + mb.msg_bufx; |
264 | i < mb.msg_bufs; i++, p++) { | | 274 | i < mb.msg_bufs; i++, p++) { |
265 | if (p == bufdata + mb.msg_bufs) | | 275 | if (p == bufdata + mb.msg_bufs) |
266 | p = bufdata; | | 276 | p = bufdata; |
267 | if (i < mb.msg_bufs - print) { | | 277 | if (i < mb.msg_bufs - print) { |
268 | continue; | | 278 | continue; |
269 | } | | 279 | } |
270 | db_read_bytes((db_addr_t)p, sizeof(ch), &ch); | | 280 | db_read_bytes((db_addr_t)p, sizeof(ch), &ch); |
271 | /* Skip "\n<.*>" syslog sequences. */ | | 281 | /* Skip "\n<.*>" syslog sequences. */ |
272 | if (skip) { | | 282 | if (skip) { |
273 | if (ch == '>') | | 283 | if (ch == '>') |
274 | newl = skip = 0; | | 284 | newl = skip = 0; |
275 | continue; | | 285 | continue; |
276 | } | | 286 | } |
277 | if (newl && ch == '<') { | | 287 | if (newl && ch == '<') { |
278 | skip = 1; | | 288 | skip = 1; |
279 | continue; | | 289 | continue; |
280 | } | | 290 | } |
281 | if (ch == '\0') | | 291 | if (ch == '\0') |
282 | continue; | | 292 | continue; |
283 | newl = ch == '\n'; | | 293 | newl = ch == '\n'; |
284 | db_printf("%c", ch); | | 294 | db_printf("%c", ch); |
285 | } | | 295 | } |
286 | if (!newl) | | 296 | if (!newl) |
287 | db_printf("\n"); | | 297 | db_printf("\n"); |
288 | } | | 298 | } |
289 | | | 299 | |
290 | void | | 300 | void |
291 | db_show_sched_qs(db_expr_t addr, bool haddr, | | 301 | db_show_sched_qs(db_expr_t addr, bool haddr, |
292 | db_expr_t count, const char *modif) | | 302 | db_expr_t count, const char *modif) |
293 | { | | 303 | { |
294 | | | 304 | |
295 | #ifdef _KERNEL /* XXX CRASH(8) */ | | 305 | #ifdef _KERNEL /* XXX CRASH(8) */ |
296 | sched_print_runqueue(db_printf); | | 306 | sched_print_runqueue(db_printf); |
297 | #endif | | 307 | #endif |
298 | } | | 308 | } |