File: | ddb/db_command.c |
Warning: | line 292, column 3 1st function call argument is an uninitialized value |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
1 | /* $OpenBSD: db_command.c,v 1.100 2023/09/19 11:35:30 claudio Exp $ */ | |||
2 | /* $NetBSD: db_command.c,v 1.20 1996/03/30 22:30:05 christos Exp $ */ | |||
3 | ||||
4 | /* | |||
5 | * Mach Operating System | |||
6 | * Copyright (c) 1993,1992,1991,1990 Carnegie Mellon University | |||
7 | * All Rights Reserved. | |||
8 | * | |||
9 | * Permission to use, copy, modify and distribute this software and its | |||
10 | * documentation is hereby granted, provided that both the copyright | |||
11 | * notice and this permission notice appear in all copies of the | |||
12 | * software, derivative works or modified versions, and any portions | |||
13 | * thereof, and that both notices appear in supporting documentation. | |||
14 | * | |||
15 | * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" | |||
16 | * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR | |||
17 | * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. | |||
18 | * | |||
19 | * Carnegie Mellon requests users of this software to return to | |||
20 | * | |||
21 | * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU | |||
22 | * School of Computer Science | |||
23 | * Carnegie Mellon University | |||
24 | * Pittsburgh PA 15213-3890 | |||
25 | * | |||
26 | * any improvements or extensions that they make and grant Carnegie Mellon | |||
27 | * the rights to redistribute these changes. | |||
28 | */ | |||
29 | ||||
30 | /* | |||
31 | * Command dispatcher. | |||
32 | */ | |||
33 | #include <sys/param.h> | |||
34 | #include <sys/systm.h> | |||
35 | #include <sys/proc.h> | |||
36 | #include <sys/reboot.h> | |||
37 | #include <sys/extent.h> | |||
38 | #include <sys/pool.h> | |||
39 | #include <sys/msgbuf.h> | |||
40 | #include <sys/malloc.h> | |||
41 | #include <sys/mount.h> | |||
42 | ||||
43 | #include <uvm/uvm_extern.h> | |||
44 | #include <machine/db_machdep.h> /* type definitions */ | |||
45 | ||||
46 | #include <ddb/db_access.h> | |||
47 | #include <ddb/db_lex.h> | |||
48 | #include <ddb/db_output.h> | |||
49 | #include <ddb/db_command.h> | |||
50 | #include <ddb/db_break.h> | |||
51 | #include <ddb/db_watch.h> | |||
52 | #include <ddb/db_run.h> | |||
53 | #include <ddb/db_sym.h> | |||
54 | #include <ddb/db_var.h> | |||
55 | #include <ddb/db_variables.h> | |||
56 | #include <ddb/db_interface.h> | |||
57 | #include <ddb/db_extern.h> | |||
58 | ||||
59 | #include <netinet/ip_ipsp.h> | |||
60 | #include <uvm/uvm_ddb.h> | |||
61 | ||||
62 | /* | |||
63 | * Exported global variables | |||
64 | */ | |||
65 | int db_cmd_loop_done; | |||
66 | label_t *db_recover; | |||
67 | ||||
68 | /* | |||
69 | * if 'ed' style: 'dot' is set at start of last item printed, | |||
70 | * and '+' points to next line. | |||
71 | * Otherwise: 'dot' points to next item, '..' points to last. | |||
72 | */ | |||
73 | int db_ed_style = 1; | |||
74 | ||||
75 | vaddr_t db_dot; /* current location */ | |||
76 | vaddr_t db_last_addr; /* last explicit address typed */ | |||
77 | vaddr_t db_prev; /* last address examined | |||
78 | or written */ | |||
79 | vaddr_t db_next; /* next address to be examined | |||
80 | or written */ | |||
81 | ||||
82 | int db_cmd_search(char *, const struct db_command *, | |||
83 | const struct db_command **); | |||
84 | void db_cmd_list(const struct db_command *); | |||
85 | void db_ctf_pprint_cmd(db_expr_t, int, db_expr_t,char *); | |||
86 | void db_map_print_cmd(db_expr_t, int, db_expr_t, char *); | |||
87 | void db_buf_print_cmd(db_expr_t, int, db_expr_t, char *); | |||
88 | void db_malloc_print_cmd(db_expr_t, int, db_expr_t, char *); | |||
89 | void db_mbuf_print_cmd(db_expr_t, int, db_expr_t, char *); | |||
90 | void db_mount_print_cmd(db_expr_t, int, db_expr_t, char *); | |||
91 | void db_show_all_mounts(db_expr_t, int, db_expr_t, char *); | |||
92 | void db_show_all_vnodes(db_expr_t, int, db_expr_t, char *); | |||
93 | void db_show_all_bufs(db_expr_t, int, db_expr_t, char *); | |||
94 | void db_show_all_tdbs(db_expr_t, int, db_expr_t, char *); | |||
95 | void db_object_print_cmd(db_expr_t, int, db_expr_t, char *); | |||
96 | void db_page_print_cmd(db_expr_t, int, db_expr_t, char *); | |||
97 | void db_extent_print_cmd(db_expr_t, int, db_expr_t, char *); | |||
98 | void db_pool_print_cmd(db_expr_t, int, db_expr_t, char *); | |||
99 | void db_proc_print_cmd(db_expr_t, int, db_expr_t, char *); | |||
100 | void db_uvmexp_print_cmd(db_expr_t, int, db_expr_t, char *); | |||
101 | void db_tdb_print_cmd(db_expr_t, int, db_expr_t, char *); | |||
102 | void db_vnode_print_cmd(db_expr_t, int, db_expr_t, char *); | |||
103 | void db_nfsreq_print_cmd(db_expr_t, int, db_expr_t, char *); | |||
104 | void db_nfsnode_print_cmd(db_expr_t, int, db_expr_t, char *); | |||
105 | void db_swap_print_cmd(db_expr_t, int, db_expr_t, char *); | |||
106 | void db_help_cmd(db_expr_t, int, db_expr_t, char *); | |||
107 | void db_fncall(db_expr_t, int, db_expr_t, char *); | |||
108 | void db_boot_sync_cmd(db_expr_t, int, db_expr_t, char *); | |||
109 | void db_boot_crash_cmd(db_expr_t, int, db_expr_t, char *); | |||
110 | void db_boot_dump_cmd(db_expr_t, int, db_expr_t, char *); | |||
111 | void db_boot_halt_cmd(db_expr_t, int, db_expr_t, char *); | |||
112 | void db_boot_reboot_cmd(db_expr_t, int, db_expr_t, char *); | |||
113 | void db_boot_poweroff_cmd(db_expr_t, int, db_expr_t, char *); | |||
114 | void db_stack_trace_cmd(db_expr_t, int, db_expr_t, char *); | |||
115 | void db_dmesg_cmd(db_expr_t, int, db_expr_t, char *); | |||
116 | void db_show_panic_cmd(db_expr_t, int, db_expr_t, char *); | |||
117 | void db_bcstats_print_cmd(db_expr_t, int, db_expr_t, char *); | |||
118 | void db_struct_offset_cmd(db_expr_t, int, db_expr_t, char *); | |||
119 | void db_ctf_show_struct(db_expr_t, int, db_expr_t, char *); | |||
120 | void db_show_regs(db_expr_t, int, db_expr_t, char *); | |||
121 | void db_write_cmd(db_expr_t, int, db_expr_t, char *); | |||
122 | void db_witness_display(db_expr_t, int, db_expr_t, char *); | |||
123 | void db_witness_list(db_expr_t, int, db_expr_t, char *); | |||
124 | void db_witness_list_all(db_expr_t, int, db_expr_t, char *); | |||
125 | ||||
126 | ||||
127 | /* | |||
128 | * Utility routine - discard tokens through end-of-line. | |||
129 | */ | |||
130 | void | |||
131 | db_skip_to_eol(void) | |||
132 | { | |||
133 | int t; | |||
134 | do { | |||
135 | t = db_read_token(); | |||
136 | } while (t != tEOL1); | |||
137 | } | |||
138 | ||||
139 | /* | |||
140 | * Results of command search. | |||
141 | */ | |||
142 | #define CMD_UNIQUE0 0 | |||
143 | #define CMD_FOUND1 1 | |||
144 | #define CMD_NONE2 2 | |||
145 | #define CMD_AMBIGUOUS3 3 | |||
146 | ||||
147 | /* | |||
148 | * Search for command prefix. | |||
149 | */ | |||
150 | int | |||
151 | db_cmd_search(char *name, const struct db_command *table, | |||
152 | const struct db_command **cmdp) | |||
153 | { | |||
154 | const struct db_command *cmd; | |||
155 | int result = CMD_NONE2; | |||
156 | ||||
157 | for (cmd = table; cmd->name != 0; cmd++) { | |||
158 | char *lp = name, *rp = cmd->name; | |||
159 | int c; | |||
160 | ||||
161 | while ((c = *lp) == *rp) { | |||
162 | if (c == 0) { | |||
163 | /* complete match */ | |||
164 | *cmdp = cmd; | |||
165 | return (CMD_UNIQUE0); | |||
166 | } | |||
167 | lp++; | |||
168 | rp++; | |||
169 | } | |||
170 | if (c == 0) { | |||
171 | /* end of name, not end of command - partial match */ | |||
172 | if (result == CMD_FOUND1) { | |||
173 | result = CMD_AMBIGUOUS3; | |||
174 | /* but keep looking for a full match - | |||
175 | this lets us match single letters */ | |||
176 | } else { | |||
177 | *cmdp = cmd; | |||
178 | result = CMD_FOUND1; | |||
179 | } | |||
180 | } | |||
181 | } | |||
182 | return (result); | |||
183 | } | |||
184 | ||||
185 | void | |||
186 | db_cmd_list(const struct db_command *table) | |||
187 | { | |||
188 | const struct db_command *cmd; | |||
189 | ||||
190 | for (cmd = table; cmd->name != 0; cmd++) { | |||
191 | db_printf("%-12s", cmd->name); | |||
192 | db_end_line(12); | |||
193 | } | |||
194 | } | |||
195 | ||||
196 | void | |||
197 | db_command(const struct db_command **last_cmdp, | |||
198 | const struct db_command *cmd_table) | |||
199 | { | |||
200 | const struct db_command *cmd; | |||
201 | char modif[TOK_STRING_SIZE120]; | |||
202 | db_expr_t addr, count; | |||
203 | int t, result, have_addr = 0; | |||
204 | ||||
205 | t = db_read_token(); | |||
206 | if (t == tEOL1) { | |||
207 | /* empty line repeats last command, at 'next' */ | |||
208 | cmd = *last_cmdp; | |||
209 | addr = (db_expr_t)db_next; | |||
210 | have_addr = 0; | |||
211 | count = 1; | |||
212 | modif[0] = '\0'; | |||
213 | } else if (t == tEXCL17) { | |||
214 | db_fncall(0, 0, 0, NULL((void *)0)); | |||
215 | return; | |||
216 | } else if (t != tIDENT3) { | |||
217 | db_printf("?\n"); | |||
218 | db_flush_lex(); | |||
219 | return; | |||
220 | } else { | |||
221 | /* Search for command */ | |||
222 | while (cmd_table) { | |||
223 | result = db_cmd_search(db_tok_string, | |||
224 | cmd_table, &cmd); | |||
225 | switch (result) { | |||
226 | case CMD_NONE2: | |||
227 | db_printf("No such command\n"); | |||
228 | db_flush_lex(); | |||
229 | return; | |||
230 | case CMD_AMBIGUOUS3: | |||
231 | db_printf("Ambiguous\n"); | |||
232 | db_flush_lex(); | |||
233 | return; | |||
234 | default: | |||
235 | break; | |||
236 | } | |||
237 | if ((cmd_table = cmd->more) != 0) { | |||
238 | t = db_read_token(); | |||
239 | if (t != tIDENT3) { | |||
240 | db_cmd_list(cmd_table); | |||
241 | db_flush_lex(); | |||
242 | return; | |||
243 | } | |||
244 | } | |||
245 | } | |||
246 | ||||
247 | if ((cmd->flag & CS_OWN0x1) == 0) { | |||
248 | /* | |||
249 | * Standard syntax: | |||
250 | * command [/modifier] [addr] [,count] | |||
251 | */ | |||
252 | t = db_read_token(); | |||
253 | if (t == tSLASH8) { | |||
254 | t = db_read_token(); | |||
255 | if (t != tIDENT3) { | |||
256 | db_printf("Bad modifier\n"); | |||
257 | db_flush_lex(); | |||
258 | return; | |||
259 | } | |||
260 | db_strlcpy(modif, db_tok_string, sizeof(modif)); | |||
261 | } else { | |||
262 | db_unread_token(t); | |||
263 | modif[0] = '\0'; | |||
264 | } | |||
265 | ||||
266 | if (db_expression(&addr)) { | |||
267 | db_dot = (vaddr_t) addr; | |||
268 | db_last_addr = db_dot; | |||
269 | have_addr = 1; | |||
270 | } else { | |||
271 | addr = (db_expr_t) db_dot; | |||
272 | have_addr = 0; | |||
273 | } | |||
274 | t = db_read_token(); | |||
275 | if (t == tCOMMA14) { | |||
276 | if (!db_expression(&count)) { | |||
277 | db_printf("Count missing\n"); | |||
278 | db_flush_lex(); | |||
279 | return; | |||
280 | } | |||
281 | } else { | |||
282 | db_unread_token(t); | |||
283 | count = -1; | |||
284 | } | |||
285 | if ((cmd->flag & CS_MORE0x2) == 0) | |||
286 | db_skip_to_eol(); | |||
287 | } | |||
288 | } | |||
289 | *last_cmdp = cmd; | |||
290 | if (cmd
| |||
291 | /* Execute the command. */ | |||
292 | (*cmd->fcn)(addr, have_addr, count, modif); | |||
| ||||
293 | ||||
294 | if (cmd->flag & CS_SET_DOT0x100) { | |||
295 | /* | |||
296 | * If command changes dot, set dot to | |||
297 | * previous address displayed (if 'ed' style). | |||
298 | */ | |||
299 | if (db_ed_style) | |||
300 | db_dot = db_prev; | |||
301 | else | |||
302 | db_dot = db_next; | |||
303 | } | |||
304 | } else { | |||
305 | /* | |||
306 | * If command does not change dot, | |||
307 | * set 'next' location to be the same. | |||
308 | */ | |||
309 | db_next = db_dot; | |||
310 | } | |||
311 | } | |||
312 | ||||
313 | void | |||
314 | db_buf_print_cmd(db_expr_t addr, int have_addr, db_expr_t count, char *modif) | |||
315 | { | |||
316 | int full = 0; | |||
317 | ||||
318 | if (modif[0] == 'f') | |||
319 | full = 1; | |||
320 | ||||
321 | vfs_buf_print((void *) addr, full, db_printf); | |||
322 | } | |||
323 | ||||
324 | void | |||
325 | db_map_print_cmd(db_expr_t addr, int have_addr, db_expr_t count, char *modif) | |||
326 | { | |||
327 | int full = 0; | |||
328 | ||||
329 | if (modif[0] == 'f') | |||
330 | full = 1; | |||
331 | ||||
332 | uvm_map_printit((struct vm_map *) addr, full, db_printf); | |||
333 | } | |||
334 | ||||
335 | void | |||
336 | db_malloc_print_cmd(db_expr_t addr, int have_addr, db_expr_t count, char *modif) | |||
337 | { | |||
338 | malloc_printit(db_printf); | |||
339 | } | |||
340 | ||||
341 | void | |||
342 | db_mbuf_print_cmd(db_expr_t addr, int have_addr, db_expr_t count, char *modif) | |||
343 | { | |||
344 | m_print((void *)addr, db_printf); | |||
345 | } | |||
346 | ||||
347 | void | |||
348 | db_socket_print_cmd(db_expr_t addr, int have_addr, db_expr_t count, char *modif) | |||
349 | { | |||
350 | so_print((void *)addr, db_printf); | |||
351 | } | |||
352 | ||||
353 | void | |||
354 | db_mount_print_cmd(db_expr_t addr, int have_addr, db_expr_t count, char *modif) | |||
355 | { | |||
356 | int full = 0; | |||
357 | ||||
358 | if (modif[0] == 'f') | |||
359 | full = 1; | |||
360 | ||||
361 | vfs_mount_print((struct mount *) addr, full, db_printf); | |||
362 | } | |||
363 | ||||
364 | void | |||
365 | db_show_all_mounts(db_expr_t addr, int have_addr, db_expr_t count, char *modif) | |||
366 | { | |||
367 | int full = 0; | |||
368 | struct mount *mp; | |||
369 | ||||
370 | if (modif[0] == 'f') | |||
371 | full = 1; | |||
372 | ||||
373 | TAILQ_FOREACH(mp, &mountlist, mnt_list)for((mp) = ((&mountlist)->tqh_first); (mp) != ((void * )0); (mp) = ((mp)->mnt_list.tqe_next)) { | |||
374 | db_printf("mountpoint %p\n", mp); | |||
375 | vfs_mount_print(mp, full, db_printf); | |||
376 | } | |||
377 | } | |||
378 | ||||
379 | extern struct pool vnode_pool; | |||
380 | void | |||
381 | db_show_all_vnodes(db_expr_t addr, int have_addr, db_expr_t count, char *modif) | |||
382 | { | |||
383 | int full = 0; | |||
384 | ||||
385 | if (modif[0] == 'f') | |||
386 | full = 1; | |||
387 | ||||
388 | pool_walk(&vnode_pool, full, db_printf, vfs_vnode_print); | |||
389 | } | |||
390 | ||||
391 | extern struct pool bufpool; | |||
392 | void | |||
393 | db_show_all_bufs(db_expr_t addr, int have_addr, db_expr_t count, char *modif) | |||
394 | { | |||
395 | int full = 0; | |||
396 | ||||
397 | if (modif[0] == 'f') | |||
398 | full = 1; | |||
399 | ||||
400 | pool_walk(&bufpool, full, db_printf, vfs_buf_print); | |||
401 | } | |||
402 | ||||
403 | #ifdef IPSEC1 | |||
404 | void | |||
405 | db_show_all_tdbs(db_expr_t addr, int have_addr, db_expr_t count, char *modif) | |||
406 | { | |||
407 | int full = 0; | |||
408 | ||||
409 | if (modif[0] == 'f') | |||
410 | full = 1; | |||
411 | ||||
412 | pool_walk(&tdb_pool, full, db_printf, tdb_printit); | |||
413 | } | |||
414 | #endif | |||
415 | ||||
416 | void | |||
417 | db_show_all_routes(db_expr_t addr, int have_addr, db_expr_t count, char *modif) | |||
418 | { | |||
419 | u_int rtableid = 0; | |||
420 | ||||
421 | if (have_addr) | |||
422 | rtableid = addr; | |||
423 | if (count == -1) | |||
424 | count = 1; | |||
425 | ||||
426 | while (count--) { | |||
427 | if (modif[0] != 'I') | |||
428 | db_show_rtable(AF_INET2, rtableid); | |||
429 | if (modif[0] != 'i') | |||
430 | db_show_rtable(AF_INET624, rtableid); | |||
431 | rtableid++; | |||
432 | } | |||
433 | } | |||
434 | ||||
435 | void | |||
436 | db_show_route(db_expr_t addr, int have_addr, db_expr_t count, char *modif) | |||
437 | { | |||
438 | db_show_rtentry((void *)addr, NULL((void *)0), -1); | |||
439 | } | |||
440 | ||||
441 | void | |||
442 | db_object_print_cmd(db_expr_t addr, int have_addr, db_expr_t count, char *modif) | |||
443 | { | |||
444 | int full = 0; | |||
445 | ||||
446 | if (modif[0] == 'f') | |||
447 | full = 1; | |||
448 | ||||
449 | uvm_object_printit((struct uvm_object *) addr, full, db_printf); | |||
450 | } | |||
451 | ||||
452 | void | |||
453 | db_page_print_cmd(db_expr_t addr, int have_addr, db_expr_t count, char *modif) | |||
454 | { | |||
455 | int full = 0; | |||
456 | ||||
457 | if (modif[0] == 'f') | |||
458 | full = 1; | |||
459 | ||||
460 | uvm_page_printit((struct vm_page *) addr, full, db_printf); | |||
461 | } | |||
462 | ||||
463 | void | |||
464 | db_vnode_print_cmd(db_expr_t addr, int have_addr, db_expr_t count, char *modif) | |||
465 | { | |||
466 | int full = 0; | |||
467 | ||||
468 | if (modif[0] == 'f') | |||
469 | full = 1; | |||
470 | ||||
471 | vfs_vnode_print((void *)addr, full, db_printf); | |||
472 | } | |||
473 | ||||
474 | #ifdef NFSCLIENT1 | |||
475 | void | |||
476 | db_nfsreq_print_cmd(db_expr_t addr, int have_addr, db_expr_t count, | |||
477 | char *modif) | |||
478 | { | |||
479 | int full = 0; | |||
480 | ||||
481 | if (modif[0] == 'f') | |||
482 | full = 1; | |||
483 | ||||
484 | nfs_request_print((void *)addr, full, db_printf); | |||
485 | } | |||
486 | ||||
487 | void | |||
488 | db_nfsnode_print_cmd(db_expr_t addr, int have_addr, db_expr_t count, | |||
489 | char *modif) | |||
490 | { | |||
491 | int full = 0; | |||
492 | ||||
493 | if (modif[0] == 'f') | |||
494 | full = 1; | |||
495 | ||||
496 | nfs_node_print((void *)addr, full, db_printf); | |||
497 | } | |||
498 | #endif | |||
499 | ||||
500 | void | |||
501 | db_swap_print_cmd(db_expr_t addr, int have_addr, db_expr_t count, | |||
502 | char *modif) | |||
503 | { | |||
504 | swap_print_all(db_printf); | |||
505 | } | |||
506 | ||||
507 | void | |||
508 | db_show_panic_cmd(db_expr_t addr, int have_addr, db_expr_t count, char *modif) | |||
509 | { | |||
510 | struct cpu_info *ci; | |||
511 | char *prefix; | |||
512 | CPU_INFO_ITERATORint cii; | |||
513 | int panicked = 0; | |||
514 | ||||
515 | CPU_INFO_FOREACH(cii, ci)for (cii = 0, ci = cpu_info_list; ci != ((void *)0); ci = ci-> ci_next) { | |||
516 | if (ci->ci_panicbuf[0] != '\0') { | |||
517 | prefix = (panicstr == ci->ci_panicbuf) ? "*" : " "; | |||
518 | db_printf("%scpu%d: %s\n", | |||
519 | prefix, CPU_INFO_UNIT(ci)((ci)->ci_dev ? (ci)->ci_dev->dv_unit : 0), ci->ci_panicbuf); | |||
520 | panicked = 1; | |||
521 | } | |||
522 | } | |||
523 | if (!panicked) | |||
524 | db_printf("the kernel did not panic\n"); /* yet */ | |||
525 | } | |||
526 | ||||
527 | void | |||
528 | db_extent_print_cmd(db_expr_t addr, int have_addr, db_expr_t count, char *modif) | |||
529 | { | |||
530 | extent_print_all(); | |||
531 | } | |||
532 | ||||
533 | void | |||
534 | db_pool_print_cmd(db_expr_t addr, int have_addr, db_expr_t count, char *modif) | |||
535 | { | |||
536 | pool_printit((struct pool *)addr, modif, db_printf); | |||
537 | } | |||
538 | ||||
539 | void | |||
540 | db_proc_print_cmd(db_expr_t addr, int have_addr, db_expr_t count, char *modif) | |||
541 | { | |||
542 | if (!have_addr) | |||
543 | addr = (db_expr_t)curproc({struct cpu_info *__ci; asm volatile("movq %%gs:%P1,%0" : "=r" (__ci) :"n" (__builtin_offsetof(struct cpu_info, ci_self))); __ci;})->ci_curproc; | |||
544 | if (modif[0] == 't') { | |||
545 | addr = (db_expr_t)tfind((pid_t)addr); | |||
546 | if (addr == 0) { | |||
547 | db_printf("not found\n"); | |||
548 | return; | |||
549 | } | |||
550 | } | |||
551 | ||||
552 | proc_printit((struct proc *)addr, modif, db_printf); | |||
553 | } | |||
554 | ||||
555 | #ifdef IPSEC1 | |||
556 | void | |||
557 | db_tdb_print_cmd(db_expr_t addr, int have_addr, db_expr_t count, char *modif) | |||
558 | { | |||
559 | int full = 0; | |||
560 | ||||
561 | if (modif[0] == 'f') | |||
562 | full = 1; | |||
563 | ||||
564 | tdb_printit((void *)addr, full, db_printf); | |||
565 | } | |||
566 | #endif | |||
567 | ||||
568 | void | |||
569 | db_uvmexp_print_cmd(db_expr_t addr, int have_addr, db_expr_t count, char *modif) | |||
570 | { | |||
571 | uvmexp_print(db_printf); | |||
572 | } | |||
573 | ||||
574 | void bcstats_print(int (*)(const char *, ...)); | |||
575 | ||||
576 | void | |||
577 | db_bcstats_print_cmd(db_expr_t addr, int have_addr, db_expr_t count, char *modif) | |||
578 | { | |||
579 | bcstats_print(db_printf); | |||
580 | } | |||
581 | ||||
582 | /* | |||
583 | * 'show' commands | |||
584 | */ | |||
585 | ||||
586 | const struct db_command db_show_all_cmds[] = { | |||
587 | { "procs", db_show_all_procs, 0, NULL((void *)0) }, | |||
588 | { "callout", db_show_callout, 0, NULL((void *)0) }, | |||
589 | { "clockintr", db_show_all_clockintr, 0, NULL((void *)0) }, | |||
590 | { "pools", db_show_all_pools, 0, NULL((void *)0) }, | |||
591 | { "mounts", db_show_all_mounts, 0, NULL((void *)0) }, | |||
592 | { "vnodes", db_show_all_vnodes, 0, NULL((void *)0) }, | |||
593 | { "bufs", db_show_all_bufs, 0, NULL((void *)0) }, | |||
594 | { "routes", db_show_all_routes, 0, NULL((void *)0) }, | |||
595 | #ifdef NFSCLIENT1 | |||
596 | { "nfsreqs", db_show_all_nfsreqs, 0, NULL((void *)0) }, | |||
597 | { "nfsnodes", db_show_all_nfsnodes, 0, NULL((void *)0) }, | |||
598 | #endif | |||
599 | #ifdef IPSEC1 | |||
600 | { "tdbs", db_show_all_tdbs, 0, NULL((void *)0) }, | |||
601 | #endif | |||
602 | #ifdef WITNESS | |||
603 | { "locks", db_witness_list_all, 0, NULL((void *)0) }, | |||
604 | #endif | |||
605 | { NULL((void *)0), NULL((void *)0), 0, NULL((void *)0) } | |||
606 | }; | |||
607 | ||||
608 | const struct db_command db_show_cmds[] = { | |||
609 | { "all", NULL((void *)0), 0, db_show_all_cmds }, | |||
610 | { "bcstats", db_bcstats_print_cmd, 0, NULL((void *)0) }, | |||
611 | { "breaks", db_listbreak_cmd, 0, NULL((void *)0) }, | |||
612 | { "buf", db_buf_print_cmd, 0, NULL((void *)0) }, | |||
613 | { "extents", db_extent_print_cmd, 0, NULL((void *)0) }, | |||
614 | #ifdef WITNESS | |||
615 | { "locks", db_witness_list, 0, NULL((void *)0) }, | |||
616 | #endif | |||
617 | { "malloc", db_malloc_print_cmd, 0, NULL((void *)0) }, | |||
618 | { "map", db_map_print_cmd, 0, NULL((void *)0) }, | |||
619 | { "mbuf", db_mbuf_print_cmd, 0, NULL((void *)0) }, | |||
620 | { "mount", db_mount_print_cmd, 0, NULL((void *)0) }, | |||
621 | #ifdef NFSCLIENT1 | |||
622 | { "nfsreq", db_nfsreq_print_cmd, 0, NULL((void *)0) }, | |||
623 | { "nfsnode", db_nfsnode_print_cmd, 0, NULL((void *)0) }, | |||
624 | #endif | |||
625 | { "object", db_object_print_cmd, 0, NULL((void *)0) }, | |||
626 | { "page", db_page_print_cmd, 0, NULL((void *)0) }, | |||
627 | { "panic", db_show_panic_cmd, 0, NULL((void *)0) }, | |||
628 | { "pool", db_pool_print_cmd, 0, NULL((void *)0) }, | |||
629 | { "proc", db_proc_print_cmd, 0, NULL((void *)0) }, | |||
630 | { "registers", db_show_regs, 0, NULL((void *)0) }, | |||
631 | { "route", db_show_route, 0, NULL((void *)0) }, | |||
632 | { "socket", db_socket_print_cmd, 0, NULL((void *)0) }, | |||
633 | { "struct", db_ctf_show_struct, CS_OWN0x1, NULL((void *)0) }, | |||
634 | { "swap", db_swap_print_cmd, 0, NULL((void *)0) }, | |||
635 | #ifdef IPSEC1 | |||
636 | { "tdb", db_tdb_print_cmd, 0, NULL((void *)0) }, | |||
637 | #endif | |||
638 | { "uvmexp", db_uvmexp_print_cmd, 0, NULL((void *)0) }, | |||
639 | { "vnode", db_vnode_print_cmd, 0, NULL((void *)0) }, | |||
640 | { "watches", db_listwatch_cmd, 0, NULL((void *)0) }, | |||
641 | #ifdef WITNESS | |||
642 | { "witness", db_witness_display, 0, NULL((void *)0) }, | |||
643 | #endif | |||
644 | { NULL((void *)0), NULL((void *)0), 0, NULL((void *)0) } | |||
645 | }; | |||
646 | ||||
647 | const struct db_command db_boot_cmds[] = { | |||
648 | { "sync", db_boot_sync_cmd, 0, 0 }, | |||
649 | { "crash", db_boot_crash_cmd, 0, 0 }, | |||
650 | { "dump", db_boot_dump_cmd, 0, 0 }, | |||
651 | { "halt", db_boot_halt_cmd, 0, 0 }, | |||
652 | { "reboot", db_boot_reboot_cmd, 0, 0 }, | |||
653 | { "poweroff", db_boot_poweroff_cmd, 0, 0 }, | |||
654 | { NULL((void *)0), } | |||
655 | }; | |||
656 | ||||
657 | const struct db_command db_command_table[] = { | |||
658 | #ifdef DB_MACHINE_COMMANDS | |||
659 | /* this must be the first entry, if it exists */ | |||
660 | { "machine", NULL((void *)0), 0, db_machine_command_table }, | |||
661 | #endif | |||
662 | { "kill", db_kill_cmd, 0, NULL((void *)0) }, | |||
663 | { "print", db_print_cmd, 0, NULL((void *)0) }, | |||
664 | { "p", db_print_cmd, 0, NULL((void *)0) }, | |||
665 | { "pprint", db_ctf_pprint_cmd, CS_OWN0x1, NULL((void *)0) }, | |||
666 | { "examine", db_examine_cmd, CS_SET_DOT0x100, NULL((void *)0) }, | |||
667 | { "x", db_examine_cmd, CS_SET_DOT0x100, NULL((void *)0) }, | |||
668 | { "search", db_search_cmd, CS_OWN0x1|CS_SET_DOT0x100, NULL((void *)0) }, | |||
669 | { "set", db_set_cmd, CS_OWN0x1, NULL((void *)0) }, | |||
670 | { "write", db_write_cmd, CS_MORE0x2|CS_SET_DOT0x100, NULL((void *)0) }, | |||
671 | { "w", db_write_cmd, CS_MORE0x2|CS_SET_DOT0x100, NULL((void *)0) }, | |||
672 | { "delete", db_delete_cmd, 0, NULL((void *)0) }, | |||
673 | { "d", db_delete_cmd, 0, NULL((void *)0) }, | |||
674 | { "break", db_breakpoint_cmd, 0, NULL((void *)0) }, | |||
675 | { "dwatch", db_deletewatch_cmd, 0, NULL((void *)0) }, | |||
676 | { "watch", db_watchpoint_cmd, CS_MORE0x2, NULL((void *)0) }, | |||
677 | { "step", db_single_step_cmd, 0, NULL((void *)0) }, | |||
678 | { "s", db_single_step_cmd, 0, NULL((void *)0) }, | |||
679 | { "continue", db_continue_cmd, 0, NULL((void *)0) }, | |||
680 | { "c", db_continue_cmd, 0, NULL((void *)0) }, | |||
681 | { "until", db_trace_until_call_cmd,0, NULL((void *)0) }, | |||
682 | { "next", db_trace_until_matching_cmd,0, NULL((void *)0) }, | |||
683 | { "match", db_trace_until_matching_cmd,0, NULL((void *)0) }, | |||
684 | { "trace", db_stack_trace_cmd, 0, NULL((void *)0) }, | |||
685 | { "bt", db_stack_trace_cmd, 0, NULL((void *)0) }, | |||
686 | { "call", db_fncall, CS_OWN0x1, NULL((void *)0) }, | |||
687 | { "ps", db_show_all_procs, 0, NULL((void *)0) }, | |||
688 | { "callout", db_show_callout, 0, NULL((void *)0) }, | |||
689 | { "reboot", db_boot_reboot_cmd, 0, NULL((void *)0) }, | |||
690 | { "show", NULL((void *)0), 0, db_show_cmds }, | |||
691 | { "boot", NULL((void *)0), 0, db_boot_cmds }, | |||
692 | { "help", db_help_cmd, 0, NULL((void *)0) }, | |||
693 | { "hangman", db_hangman, 0, NULL((void *)0) }, | |||
694 | { "dmesg", db_dmesg_cmd, 0, NULL((void *)0) }, | |||
695 | { NULL((void *)0), NULL((void *)0), 0, NULL((void *)0) } | |||
696 | }; | |||
697 | ||||
698 | const struct db_command *db_last_command = NULL((void *)0); | |||
699 | ||||
700 | void | |||
701 | db_help_cmd(db_expr_t addr, int haddr, db_expr_t count, char *modif) | |||
702 | { | |||
703 | db_cmd_list(db_command_table); | |||
704 | } | |||
705 | ||||
706 | void | |||
707 | db_command_loop(void) | |||
708 | { | |||
709 | label_t db_jmpbuf; | |||
710 | label_t *savejmp; | |||
711 | extern int db_output_line; | |||
712 | ||||
713 | /* | |||
714 | * Initialize 'prev' and 'next' to dot. | |||
715 | */ | |||
716 | db_prev = db_dot; | |||
717 | db_next = db_dot; | |||
718 | ||||
719 | db_cmd_loop_done = 0; | |||
720 | ||||
721 | savejmp = db_recover; | |||
722 | db_recover = &db_jmpbuf; | |||
723 | (void) setjmp(&db_jmpbuf); | |||
724 | ||||
725 | while (!db_cmd_loop_done) { | |||
| ||||
726 | ||||
727 | if (db_print_position() != 0) | |||
728 | db_printf("\n"); | |||
729 | db_output_line = 0; | |||
730 | ||||
731 | #ifdef MULTIPROCESSOR1 | |||
732 | db_printf("ddb{%d}> ", CPU_INFO_UNIT(curcpu())((({struct cpu_info *__ci; asm volatile("movq %%gs:%P1,%0" : "=r" (__ci) :"n" (__builtin_offsetof(struct cpu_info, ci_self))); __ci;}))->ci_dev ? (({struct cpu_info *__ci; asm volatile ("movq %%gs:%P1,%0" : "=r" (__ci) :"n" (__builtin_offsetof(struct cpu_info, ci_self))); __ci;}))->ci_dev->dv_unit : 0)); | |||
733 | #else | |||
734 | db_printf("ddb> "); | |||
735 | #endif | |||
736 | (void) db_read_line(); | |||
737 | ||||
738 | db_command(&db_last_command, db_command_table); | |||
739 | } | |||
740 | ||||
741 | db_recover = savejmp; | |||
742 | } | |||
743 | ||||
744 | void | |||
745 | db_error(char *s) | |||
746 | { | |||
747 | if (s) | |||
748 | db_printf("%s", s); | |||
749 | db_flush_lex(); | |||
750 | if (db_recover != NULL((void *)0)) | |||
751 | longjmp(db_recover); | |||
752 | } | |||
753 | ||||
754 | ||||
755 | /* | |||
756 | * Call random function: | |||
757 | * !expr(arg,arg,arg) | |||
758 | */ | |||
759 | void | |||
760 | db_fncall(db_expr_t addr, int have_addr, db_expr_t count, char *modif) | |||
761 | { | |||
762 | db_expr_t fn_addr; | |||
763 | #define MAXARGS11 11 | |||
764 | db_expr_t args[MAXARGS11]; | |||
765 | int nargs = 0; | |||
766 | db_expr_t retval; | |||
767 | db_expr_t (*func)(db_expr_t, ...); | |||
768 | int t; | |||
769 | char tmpfmt[28]; | |||
770 | ||||
771 | if (!db_expression(&fn_addr)) { | |||
772 | db_printf("Bad function\n"); | |||
773 | db_flush_lex(); | |||
774 | return; | |||
775 | } | |||
776 | func = (db_expr_t (*)(db_expr_t, ...)) fn_addr; | |||
777 | ||||
778 | t = db_read_token(); | |||
779 | if (t == tLPAREN10) { | |||
780 | if (db_expression(&args[0])) { | |||
781 | nargs++; | |||
782 | while ((t = db_read_token()) == tCOMMA14) { | |||
783 | if (nargs == MAXARGS11) { | |||
784 | db_printf("Too many arguments\n"); | |||
785 | db_flush_lex(); | |||
786 | return; | |||
787 | } | |||
788 | if (!db_expression(&args[nargs])) { | |||
789 | db_printf("Argument missing\n"); | |||
790 | db_flush_lex(); | |||
791 | return; | |||
792 | } | |||
793 | nargs++; | |||
794 | } | |||
795 | db_unread_token(t); | |||
796 | } | |||
797 | if (db_read_token() != tRPAREN11) { | |||
798 | db_printf("?\n"); | |||
799 | db_flush_lex(); | |||
800 | return; | |||
801 | } | |||
802 | } | |||
803 | db_skip_to_eol(); | |||
804 | ||||
805 | while (nargs < MAXARGS11) | |||
806 | args[nargs++] = 0; | |||
807 | ||||
808 | retval = (*func)(args[0], args[1], args[2], args[3], args[4], | |||
809 | args[5], args[6], args[7], args[8], args[9]); | |||
810 | db_printf("%s\n", db_format(tmpfmt, sizeof tmpfmt, retval, | |||
811 | DB_FORMAT_N3, 1, 0)); | |||
812 | } | |||
813 | ||||
814 | void | |||
815 | db_reboot(int howto) | |||
816 | { | |||
817 | spl0()spllower(0x0); | |||
818 | if (!curproc({struct cpu_info *__ci; asm volatile("movq %%gs:%P1,%0" : "=r" (__ci) :"n" (__builtin_offsetof(struct cpu_info, ci_self))); __ci;})->ci_curproc) | |||
819 | curproc({struct cpu_info *__ci; asm volatile("movq %%gs:%P1,%0" : "=r" (__ci) :"n" (__builtin_offsetof(struct cpu_info, ci_self))); __ci;})->ci_curproc = &proc0; | |||
820 | reboot(howto); | |||
821 | } | |||
822 | ||||
823 | void | |||
824 | db_boot_sync_cmd(db_expr_t addr, int haddr, db_expr_t count, char *modif) | |||
825 | { | |||
826 | db_reboot(RB_AUTOBOOT0 | RB_TIMEBAD0x00800 | RB_USERREQ0x04000); | |||
827 | } | |||
828 | ||||
829 | void | |||
830 | db_boot_crash_cmd(db_expr_t addr, int haddr, db_expr_t count, char *modif) | |||
831 | { | |||
832 | db_reboot(RB_NOSYNC0x00004 | RB_DUMP0x00100 | RB_TIMEBAD0x00800 | RB_USERREQ0x04000); | |||
833 | } | |||
834 | ||||
835 | void | |||
836 | db_boot_dump_cmd(db_expr_t addr, int haddr, db_expr_t count, char *modif) | |||
837 | { | |||
838 | db_reboot(RB_DUMP0x00100 | RB_TIMEBAD0x00800 | RB_USERREQ0x04000); | |||
839 | } | |||
840 | ||||
841 | void | |||
842 | db_boot_halt_cmd(db_expr_t addr, int haddr, db_expr_t count, char *modif) | |||
843 | { | |||
844 | db_reboot(RB_NOSYNC0x00004 | RB_HALT0x00008 | RB_TIMEBAD0x00800 | RB_USERREQ0x04000); | |||
845 | } | |||
846 | ||||
847 | void | |||
848 | db_boot_reboot_cmd(db_expr_t addr, int haddr, db_expr_t count, char *modif) | |||
849 | { | |||
850 | boot(RB_RESET0x08000 | RB_AUTOBOOT0 | RB_NOSYNC0x00004 | RB_TIMEBAD0x00800 | RB_USERREQ0x04000); | |||
851 | } | |||
852 | ||||
853 | void | |||
854 | db_boot_poweroff_cmd(db_expr_t addr, int haddr, db_expr_t count, char *modif) | |||
855 | { | |||
856 | db_reboot(RB_NOSYNC0x00004 | RB_HALT0x00008 | RB_POWERDOWN0x01000 | RB_TIMEBAD0x00800 | RB_USERREQ0x04000); | |||
857 | } | |||
858 | ||||
859 | void | |||
860 | db_dmesg_cmd(db_expr_t addr, int haddr, db_expr_t count, char *modif) | |||
861 | { | |||
862 | int i, off; | |||
863 | char *p; | |||
864 | ||||
865 | if (!msgbufp || msgbufp->msg_magic != MSG_MAGIC0x063061) | |||
866 | return; | |||
867 | off = msgbufp->msg_bufx; | |||
868 | if (off > msgbufp->msg_bufs) | |||
869 | off = 0; | |||
870 | for (i = 0, p = msgbufp->msg_bufc + off; | |||
871 | i < msgbufp->msg_bufs; i++, p++) { | |||
872 | if (p >= msgbufp->msg_bufc + msgbufp->msg_bufs) | |||
873 | p = msgbufp->msg_bufc; | |||
874 | if (*p != '\0') | |||
875 | db_putchar(*p); | |||
876 | } | |||
877 | db_putchar('\n'); | |||
878 | } | |||
879 | ||||
880 | void | |||
881 | db_stack_trace_cmd(db_expr_t addr, int have_addr, db_expr_t count, char *modif) | |||
882 | { | |||
883 | db_stack_trace_print(addr, have_addr, count, modif, db_printf); | |||
884 | } | |||
885 | ||||
886 | void | |||
887 | db_show_regs(db_expr_t addr, int have_addr, db_expr_t count, char *modif) | |||
888 | { | |||
889 | struct db_variable *regp; | |||
890 | db_expr_t value, offset; | |||
891 | char * name; | |||
892 | char tmpfmt[28]; | |||
893 | ||||
894 | for (regp = db_regs; regp < db_eregs; regp++) { | |||
895 | db_read_variable(regp, &value); | |||
896 | db_printf("%-12s%s", regp->name, | |||
897 | db_format(tmpfmt, sizeof tmpfmt, | |||
898 | (long)value, DB_FORMAT_N3, 1, sizeof(long) * 3)); | |||
899 | db_find_xtrn_sym_and_offset((vaddr_t)value, &name, &offset)db_symbol_values(db_search_symbol((vaddr_t)value,1,&offset ),&name,((void *)0)); | |||
900 | if (name != 0 && offset <= db_maxoff && offset != value) { | |||
901 | db_printf("\t%s", name); | |||
902 | if (offset != 0) | |||
903 | db_printf("+%s", | |||
904 | db_format(tmpfmt, sizeof tmpfmt, | |||
905 | (long)offset, DB_FORMAT_R2, 1, 0)); | |||
906 | } | |||
907 | db_printf("\n"); | |||
908 | } | |||
909 | db_print_loc_and_inst(PC_REGS(&ddb_regs)((vaddr_t)(&ddb_regs)->tf_rip)); | |||
910 | } | |||
911 | ||||
912 | /* | |||
913 | * Write to file. | |||
914 | */ | |||
915 | void | |||
916 | db_write_cmd(db_expr_t address, int have_addr, db_expr_t count, char *modif) | |||
917 | { | |||
918 | vaddr_t addr; | |||
919 | db_expr_t old_value; | |||
920 | db_expr_t new_value; | |||
921 | int size, wrote_one = 0; | |||
922 | char tmpfmt[28]; | |||
923 | ||||
924 | addr = (vaddr_t) address; | |||
925 | ||||
926 | switch (modif[0]) { | |||
927 | case 'b': | |||
928 | size = 1; | |||
929 | break; | |||
930 | case 'h': | |||
931 | size = 2; | |||
932 | break; | |||
933 | case 'l': | |||
934 | case '\0': | |||
935 | size = 4; | |||
936 | break; | |||
937 | #ifdef __LP64__1 | |||
938 | case 'q': | |||
939 | size = 8; | |||
940 | break; | |||
941 | #endif | |||
942 | default: | |||
943 | size = -1; | |||
944 | db_error("Unknown size\n"); | |||
945 | /*NOTREACHED*/ | |||
946 | } | |||
947 | ||||
948 | while (db_expression(&new_value)) { | |||
949 | old_value = db_get_value(addr, size, 0); | |||
950 | db_printsym(addr, DB_STGY_ANY0, db_printf); | |||
951 | db_printf("\t\t%s\t", db_format(tmpfmt, sizeof tmpfmt, | |||
952 | old_value, DB_FORMAT_N3, 0, 8)); | |||
953 | db_printf("=\t%s\n", db_format(tmpfmt, sizeof tmpfmt, | |||
954 | new_value, DB_FORMAT_N3, 0, 8)); | |||
955 | db_put_value(addr, size, new_value); | |||
956 | addr += size; | |||
957 | ||||
958 | wrote_one = 1; | |||
959 | } | |||
960 | ||||
961 | if (!wrote_one) { | |||
962 | db_error("Nothing written.\n"); | |||
963 | /*NOTREACHED*/ | |||
964 | } | |||
965 | ||||
966 | db_next = addr; | |||
967 | db_prev = addr - size; | |||
968 | ||||
969 | db_skip_to_eol(); | |||
970 | } |