db_command.c revision 1.114.6.2 1 1.114.6.2 mjf /* $NetBSD: db_command.c,v 1.114.6.2 2008/06/02 13:23:10 mjf Exp $ */
2 1.114.6.2 mjf /*
3 1.114.6.2 mjf * Mach Operating System
4 1.114.6.2 mjf * Copyright (c) 1991,1990 Carnegie Mellon University
5 1.114.6.2 mjf * All Rights Reserved.
6 1.114.6.2 mjf *
7 1.114.6.2 mjf * Permission to use, copy, modify and distribute this software and its
8 1.114.6.2 mjf * documentation is hereby granted, provided that both the copyright
9 1.114.6.2 mjf * notice and this permission notice appear in all copies of the
10 1.114.6.2 mjf * software, derivative works or modified versions, and any portions
11 1.114.6.2 mjf * thereof, and that both notices appear in supporting documentation.
12 1.114.6.2 mjf *
13 1.114.6.2 mjf * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
14 1.114.6.2 mjf * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
15 1.114.6.2 mjf * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
16 1.114.6.2 mjf *
17 1.114.6.2 mjf * Carnegie Mellon requests users of this software to return to
18 1.114.6.2 mjf *
19 1.114.6.2 mjf * Software Distribution Coordinator or Software.Distribution (at) CS.CMU.EDU
20 1.114.6.2 mjf * School of Computer Science
21 1.114.6.2 mjf * Carnegie Mellon University
22 1.114.6.2 mjf * Pittsburgh PA 15213-3890
23 1.114.6.2 mjf *
24 1.114.6.2 mjf * any improvements or extensions that they make and grant Carnegie the
25 1.114.6.2 mjf * rights to redistribute these changes.
26 1.114.6.2 mjf */
27 1.114.6.2 mjf /*
28 1.114.6.2 mjf * Copyright (c) 1996, 1997, 1998, 1999, 2002 The NetBSD Foundation, Inc.
29 1.114.6.2 mjf * All rights reserved.
30 1.114.6.2 mjf *
31 1.114.6.2 mjf * This code is derived from software contributed to The NetBSD Foundation
32 1.114.6.2 mjf * by Adam Hamsik.
33 1.114.6.2 mjf *
34 1.114.6.2 mjf * Redistribution and use in source and binary forms, with or without
35 1.114.6.2 mjf * modification, are permitted provided that the following conditions
36 1.114.6.2 mjf * are met:
37 1.114.6.2 mjf * 1. Redistributions of source code must retain the above copyright
38 1.114.6.2 mjf * notice, this list of conditions and the following disclaimer.
39 1.114.6.2 mjf * 2. Redistributions in binary form must reproduce the above copyright
40 1.114.6.2 mjf * notice, this list of conditions and the following disclaimer in the
41 1.114.6.2 mjf * documentation and/or other materials provided with the distribution.
42 1.114.6.2 mjf *
43 1.114.6.2 mjf * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
44 1.114.6.2 mjf * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
45 1.114.6.2 mjf * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
46 1.114.6.2 mjf * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
47 1.114.6.2 mjf * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
48 1.114.6.2 mjf * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
49 1.114.6.2 mjf * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
50 1.114.6.2 mjf * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
51 1.114.6.2 mjf * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
52 1.114.6.2 mjf * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
53 1.114.6.2 mjf * POSSIBILITY OF SUCH DAMAGE.
54 1.114.6.2 mjf */
55 1.114.6.2 mjf
56 1.114.6.2 mjf /*
57 1.114.6.2 mjf * Command dispatcher.
58 1.114.6.2 mjf */
59 1.114.6.2 mjf
60 1.114.6.2 mjf #include <sys/cdefs.h>
61 1.114.6.2 mjf __KERNEL_RCSID(0, "$NetBSD: db_command.c,v 1.114.6.2 2008/06/02 13:23:10 mjf Exp $");
62 1.114.6.2 mjf
63 1.114.6.2 mjf #include "opt_ddb.h"
64 1.114.6.2 mjf #include "opt_kgdb.h"
65 1.114.6.2 mjf #include "opt_inet.h"
66 1.114.6.2 mjf #include "opt_ddbparam.h"
67 1.114.6.2 mjf
68 1.114.6.2 mjf #include <sys/param.h>
69 1.114.6.2 mjf #include <sys/systm.h>
70 1.114.6.2 mjf #include <sys/reboot.h>
71 1.114.6.2 mjf #include <sys/device.h>
72 1.114.6.2 mjf #include <sys/lwp.h>
73 1.114.6.2 mjf #include <sys/malloc.h>
74 1.114.6.2 mjf #include <sys/mbuf.h>
75 1.114.6.2 mjf #include <sys/namei.h>
76 1.114.6.2 mjf #include <sys/pool.h>
77 1.114.6.2 mjf #include <sys/proc.h>
78 1.114.6.2 mjf #include <sys/vnode.h>
79 1.114.6.2 mjf #include <sys/vmem.h>
80 1.114.6.2 mjf #include <sys/lockdebug.h>
81 1.114.6.2 mjf #include <sys/sleepq.h>
82 1.114.6.2 mjf #include <sys/cpu.h>
83 1.114.6.2 mjf
84 1.114.6.2 mjf /*include queue macros*/
85 1.114.6.2 mjf #include <sys/queue.h>
86 1.114.6.2 mjf
87 1.114.6.2 mjf #include <machine/db_machdep.h> /* type definitions */
88 1.114.6.2 mjf
89 1.114.6.2 mjf #if defined(_KERNEL_OPT)
90 1.114.6.2 mjf #include "opt_multiprocessor.h"
91 1.114.6.2 mjf #endif
92 1.114.6.2 mjf
93 1.114.6.2 mjf #include <ddb/db_lex.h>
94 1.114.6.2 mjf #include <ddb/db_output.h>
95 1.114.6.2 mjf #include <ddb/db_command.h>
96 1.114.6.2 mjf #include <ddb/db_break.h>
97 1.114.6.2 mjf #include <ddb/db_watch.h>
98 1.114.6.2 mjf #include <ddb/db_run.h>
99 1.114.6.2 mjf #include <ddb/db_variables.h>
100 1.114.6.2 mjf #include <ddb/db_interface.h>
101 1.114.6.2 mjf #include <ddb/db_sym.h>
102 1.114.6.2 mjf #include <ddb/db_extern.h>
103 1.114.6.2 mjf
104 1.114.6.2 mjf #include <uvm/uvm_extern.h>
105 1.114.6.2 mjf #include <uvm/uvm_ddb.h>
106 1.114.6.2 mjf
107 1.114.6.2 mjf #include "arp.h"
108 1.114.6.2 mjf
109 1.114.6.2 mjf /*
110 1.114.6.2 mjf * Results of command search.
111 1.114.6.2 mjf */
112 1.114.6.2 mjf #define CMD_UNIQUE 0
113 1.114.6.2 mjf #define CMD_FOUND 1
114 1.114.6.2 mjf #define CMD_NONE 2
115 1.114.6.2 mjf #define CMD_AMBIGUOUS 3
116 1.114.6.2 mjf
117 1.114.6.2 mjf /*
118 1.114.6.2 mjf * Exported global variables
119 1.114.6.2 mjf */
120 1.114.6.2 mjf bool db_cmd_loop_done;
121 1.114.6.2 mjf label_t *db_recover;
122 1.114.6.2 mjf db_addr_t db_dot;
123 1.114.6.2 mjf db_addr_t db_last_addr;
124 1.114.6.2 mjf db_addr_t db_prev;
125 1.114.6.2 mjf db_addr_t db_next;
126 1.114.6.2 mjf
127 1.114.6.2 mjf
128 1.114.6.2 mjf /*
129 1.114.6.2 mjf New DDB api for adding and removing commands uses three lists, because
130 1.114.6.2 mjf we use two types of commands
131 1.114.6.2 mjf a) standard commands without subcommands -> reboot
132 1.114.6.2 mjf b) show commands which are subcommands of show command -> show aio_jobs
133 1.114.6.2 mjf c) if defined machine specific commands
134 1.114.6.2 mjf
135 1.114.6.2 mjf ddb_add_cmd, ddb_rem_cmd use type (DDB_SHOW_CMD||DDB_BASE_CMD)argument to
136 1.114.6.2 mjf add them to representativ lists.
137 1.114.6.2 mjf */
138 1.114.6.2 mjf
139 1.114.6.2 mjf static const struct db_command db_command_table[];
140 1.114.6.2 mjf static const struct db_command db_show_cmds[];
141 1.114.6.2 mjf #ifdef DB_MACHINE_COMMANDS
142 1.114.6.2 mjf static const struct db_command db_machine_command_table[];
143 1.114.6.2 mjf #endif
144 1.114.6.2 mjf
145 1.114.6.2 mjf /* the global queue of all command tables */
146 1.114.6.2 mjf TAILQ_HEAD(db_cmd_tbl_en_head, db_cmd_tbl_en);
147 1.114.6.2 mjf
148 1.114.6.2 mjf /* TAILQ entry used to register command tables */
149 1.114.6.2 mjf struct db_cmd_tbl_en {
150 1.114.6.2 mjf const struct db_command *db_cmd; /* cmd table */
151 1.114.6.2 mjf TAILQ_ENTRY(db_cmd_tbl_en) db_cmd_next;
152 1.114.6.2 mjf };
153 1.114.6.2 mjf
154 1.114.6.2 mjf /* head of base commands list */
155 1.114.6.2 mjf static struct db_cmd_tbl_en_head db_base_cmd_list =
156 1.114.6.2 mjf TAILQ_HEAD_INITIALIZER(db_base_cmd_list);
157 1.114.6.2 mjf static struct db_cmd_tbl_en db_base_cmd_builtins =
158 1.114.6.2 mjf { .db_cmd = db_command_table };
159 1.114.6.2 mjf
160 1.114.6.2 mjf /* head of show commands list */
161 1.114.6.2 mjf static struct db_cmd_tbl_en_head db_show_cmd_list =
162 1.114.6.2 mjf TAILQ_HEAD_INITIALIZER(db_show_cmd_list);
163 1.114.6.2 mjf static struct db_cmd_tbl_en db_show_cmd_builtins =
164 1.114.6.2 mjf { .db_cmd = db_show_cmds };
165 1.114.6.2 mjf
166 1.114.6.2 mjf /* head of machine commands list */
167 1.114.6.2 mjf static struct db_cmd_tbl_en_head db_mach_cmd_list =
168 1.114.6.2 mjf TAILQ_HEAD_INITIALIZER(db_mach_cmd_list);
169 1.114.6.2 mjf #ifdef DB_MACHINE_COMMANDS
170 1.114.6.2 mjf static struct db_cmd_tbl_en db_mach_cmd_builtins =
171 1.114.6.2 mjf { .db_cmd = db_machine_command_table };
172 1.114.6.2 mjf #endif
173 1.114.6.2 mjf
174 1.114.6.2 mjf /*
175 1.114.6.2 mjf * if 'ed' style: 'dot' is set at start of last item printed,
176 1.114.6.2 mjf * and '+' points to next line.
177 1.114.6.2 mjf * Otherwise: 'dot' points to next item, '..' points to last.
178 1.114.6.2 mjf */
179 1.114.6.2 mjf static bool db_ed_style = true;
180 1.114.6.2 mjf
181 1.114.6.2 mjf static void db_init_commands(void);
182 1.114.6.2 mjf static int db_register_tbl_entry(uint8_t type,
183 1.114.6.2 mjf struct db_cmd_tbl_en *list_ent);
184 1.114.6.2 mjf static void db_cmd_list(const struct db_cmd_tbl_en_head *);
185 1.114.6.2 mjf static int db_cmd_search(const char *, const struct db_command *,
186 1.114.6.2 mjf const struct db_command **);
187 1.114.6.2 mjf static void db_command(const struct db_command **);
188 1.114.6.2 mjf static void db_buf_print_cmd(db_expr_t, bool, db_expr_t, const char *);
189 1.114.6.2 mjf static void db_event_print_cmd(db_expr_t, bool, db_expr_t, const char *);
190 1.114.6.2 mjf static void db_fncall(db_expr_t, bool, db_expr_t, const char *);
191 1.114.6.2 mjf static int db_get_list_type(const char *);
192 1.114.6.2 mjf static void db_help_print_cmd(db_expr_t, bool, db_expr_t, const char *);
193 1.114.6.2 mjf static void db_lock_print_cmd(db_expr_t, bool, db_expr_t, const char *);
194 1.114.6.2 mjf static void db_mount_print_cmd(db_expr_t, bool, db_expr_t, const char *);
195 1.114.6.2 mjf static void db_mbuf_print_cmd(db_expr_t, bool, db_expr_t, const char *);
196 1.114.6.2 mjf static void db_malloc_print_cmd(db_expr_t, bool, db_expr_t, const char *);
197 1.114.6.2 mjf static void db_map_print_cmd(db_expr_t, bool, db_expr_t, const char *);
198 1.114.6.2 mjf static void db_namecache_print_cmd(db_expr_t, bool, db_expr_t,
199 1.114.6.2 mjf const char *);
200 1.114.6.2 mjf static void db_object_print_cmd(db_expr_t, bool, db_expr_t, const char *);
201 1.114.6.2 mjf static void db_page_print_cmd(db_expr_t, bool, db_expr_t, const char *);
202 1.114.6.2 mjf static void db_show_all_pages(db_expr_t, bool, db_expr_t, const char *);
203 1.114.6.2 mjf static void db_pool_print_cmd(db_expr_t, bool, db_expr_t, const char *);
204 1.114.6.2 mjf static void db_reboot_cmd(db_expr_t, bool, db_expr_t, const char *);
205 1.114.6.2 mjf static void db_sifting_cmd(db_expr_t, bool, db_expr_t, const char *);
206 1.114.6.2 mjf static void db_stack_trace_cmd(db_expr_t, bool, db_expr_t, const char *);
207 1.114.6.2 mjf static void db_sync_cmd(db_expr_t, bool, db_expr_t, const char *);
208 1.114.6.2 mjf static void db_whatis_cmd(db_expr_t, bool, db_expr_t, const char *);
209 1.114.6.2 mjf static void db_uvmexp_print_cmd(db_expr_t, bool, db_expr_t, const char *);
210 1.114.6.2 mjf static void db_vnode_print_cmd(db_expr_t, bool, db_expr_t, const char *);
211 1.114.6.2 mjf
212 1.114.6.2 mjf static const struct db_command db_show_cmds[] = {
213 1.114.6.2 mjf /*added from all sub cmds*/
214 1.114.6.2 mjf { DDB_ADD_CMD("callout", db_show_callout,
215 1.114.6.2 mjf 0 ,"List all used callout functions.",NULL,NULL) },
216 1.114.6.2 mjf { DDB_ADD_CMD("pages", db_show_all_pages,
217 1.114.6.2 mjf 0 ,"List all used memory pages.",NULL,NULL) },
218 1.114.6.2 mjf { DDB_ADD_CMD("procs", db_show_all_procs,
219 1.114.6.2 mjf 0 ,"List all processes.",NULL,NULL) },
220 1.114.6.2 mjf { DDB_ADD_CMD("pools", db_show_all_pools,
221 1.114.6.2 mjf 0 ,"Show all poolS",NULL,NULL) },
222 1.114.6.2 mjf /*added from all sub cmds*/
223 1.114.6.2 mjf { DDB_ADD_CMD("aio_jobs", db_show_aio_jobs, 0,
224 1.114.6.2 mjf "Show aio jobs",NULL,NULL) },
225 1.114.6.2 mjf { DDB_ADD_CMD("all", NULL,
226 1.114.6.2 mjf CS_COMPAT, NULL,NULL,NULL) },
227 1.114.6.2 mjf #if defined(INET) && (NARP > 0)
228 1.114.6.2 mjf { DDB_ADD_CMD("arptab", db_show_arptab, 0,NULL,NULL,NULL) },
229 1.114.6.2 mjf #endif
230 1.114.6.2 mjf { DDB_ADD_CMD("breaks", db_listbreak_cmd, 0,
231 1.114.6.2 mjf "Display all breaks.",NULL,NULL) },
232 1.114.6.2 mjf { DDB_ADD_CMD("buf", db_buf_print_cmd, 0,
233 1.114.6.2 mjf "Print the struct buf at address.", "[/f] address",NULL) },
234 1.114.6.2 mjf { DDB_ADD_CMD("event", db_event_print_cmd, 0,
235 1.114.6.2 mjf "Print all the non-zero evcnt(9) event counters.", "[/f]",NULL) },
236 1.114.6.2 mjf { DDB_ADD_CMD("lock", db_lock_print_cmd, 0,NULL,NULL,NULL) },
237 1.114.6.2 mjf { DDB_ADD_CMD("malloc", db_malloc_print_cmd,0,NULL,NULL,NULL) },
238 1.114.6.2 mjf { DDB_ADD_CMD("map", db_map_print_cmd, 0,
239 1.114.6.2 mjf "Print the vm_map at address.", "[/f] address",NULL) },
240 1.114.6.2 mjf { DDB_ADD_CMD("mount", db_mount_print_cmd, 0,
241 1.114.6.2 mjf "Print the mount structure at address.", "[/f] address",NULL) },
242 1.114.6.2 mjf { DDB_ADD_CMD("mbuf", db_mbuf_print_cmd, 0,NULL,NULL,
243 1.114.6.2 mjf "-c prints all mbuf chains") },
244 1.114.6.2 mjf { DDB_ADD_CMD("ncache", db_namecache_print_cmd, 0,
245 1.114.6.2 mjf "Dump the namecache list.", "address",NULL) },
246 1.114.6.2 mjf { DDB_ADD_CMD("object", db_object_print_cmd, 0,
247 1.114.6.2 mjf "Print the vm_object at address.", "[/f] address",NULL) },
248 1.114.6.2 mjf { DDB_ADD_CMD("page", db_page_print_cmd, 0,
249 1.114.6.2 mjf "Print the vm_page at address.", "[/f] address",NULL) },
250 1.114.6.2 mjf { DDB_ADD_CMD("pool", db_pool_print_cmd, 0,
251 1.114.6.2 mjf "Print the pool at address.", "[/clp] address",NULL) },
252 1.114.6.2 mjf { DDB_ADD_CMD("registers", db_show_regs, 0,
253 1.114.6.2 mjf "Display the register set.", "[/u]",NULL) },
254 1.114.6.2 mjf { DDB_ADD_CMD("sched_qs", db_show_sched_qs, 0,
255 1.114.6.2 mjf "Print the state of the scheduler's run queues.",
256 1.114.6.2 mjf NULL,NULL) },
257 1.114.6.2 mjf { DDB_ADD_CMD("uvmexp", db_uvmexp_print_cmd, 0,
258 1.114.6.2 mjf "Print a selection of UVM counters and statistics.",
259 1.114.6.2 mjf NULL,NULL) },
260 1.114.6.2 mjf { DDB_ADD_CMD("vnode", db_vnode_print_cmd, 0,
261 1.114.6.2 mjf "Print the vnode at address.", "[/f] address",NULL) },
262 1.114.6.2 mjf { DDB_ADD_CMD("watches", db_listwatch_cmd, 0,
263 1.114.6.2 mjf "Display all watchpoints.", NULL,NULL) },
264 1.114.6.2 mjf { DDB_ADD_CMD(NULL, NULL, 0,NULL,NULL,NULL) }
265 1.114.6.2 mjf };
266 1.114.6.2 mjf
267 1.114.6.2 mjf /* arch/<arch>/<arch>/db_interface.c */
268 1.114.6.2 mjf #ifdef DB_MACHINE_COMMANDS
269 1.114.6.2 mjf extern const struct db_command db_machine_command_table[];
270 1.114.6.2 mjf #endif
271 1.114.6.2 mjf
272 1.114.6.2 mjf static const struct db_command db_command_table[] = {
273 1.114.6.2 mjf { DDB_ADD_CMD("b", db_breakpoint_cmd, 0,
274 1.114.6.2 mjf "Set a breakpoint at address", "[/u] address[,count].",NULL) },
275 1.114.6.2 mjf { DDB_ADD_CMD("break", db_breakpoint_cmd, 0,
276 1.114.6.2 mjf "Set a breakpoint at address", "[/u] address[,count].",NULL) },
277 1.114.6.2 mjf { DDB_ADD_CMD("bt", db_stack_trace_cmd, 0,
278 1.114.6.2 mjf "Show backtrace.", "See help trace.",NULL) },
279 1.114.6.2 mjf { DDB_ADD_CMD("c", db_continue_cmd, 0,
280 1.114.6.2 mjf "Continue execution.", "[/c]",NULL) },
281 1.114.6.2 mjf { DDB_ADD_CMD("call", db_fncall, CS_OWN,
282 1.114.6.2 mjf "Call the function", "address[(expression[,...])]",NULL) },
283 1.114.6.2 mjf { DDB_ADD_CMD("callout", db_show_callout, 0, NULL,
284 1.114.6.2 mjf NULL,NULL ) },
285 1.114.6.2 mjf { DDB_ADD_CMD("continue", db_continue_cmd, 0,
286 1.114.6.2 mjf "Continue execution.", "[/c]",NULL) },
287 1.114.6.2 mjf { DDB_ADD_CMD("d", db_delete_cmd, 0,
288 1.114.6.2 mjf "Delete a breakpoint.", "address | #number",NULL) },
289 1.114.6.2 mjf { DDB_ADD_CMD("delete", db_delete_cmd, 0,
290 1.114.6.2 mjf "Delete a breakpoint.", "address | #number",NULL) },
291 1.114.6.2 mjf { DDB_ADD_CMD("dmesg", db_dmesg, 0,
292 1.114.6.2 mjf "Show kernel message buffer.", "[count]",NULL) },
293 1.114.6.2 mjf { DDB_ADD_CMD("dwatch", db_deletewatch_cmd, 0,
294 1.114.6.2 mjf "Delete the watchpoint.", "address",NULL) },
295 1.114.6.2 mjf { DDB_ADD_CMD("examine", db_examine_cmd, CS_SET_DOT,
296 1.114.6.2 mjf "Display the address locations.",
297 1.114.6.2 mjf "[/modifier] address[,count]",NULL) },
298 1.114.6.2 mjf { DDB_ADD_CMD("help", db_help_print_cmd, CS_OWN|CS_NOREPEAT,
299 1.114.6.2 mjf "Display help about commands",
300 1.114.6.2 mjf "Use other commands as arguments.",NULL) },
301 1.114.6.2 mjf { DDB_ADD_CMD("kill", db_kill_proc, CS_OWN,
302 1.114.6.2 mjf "Send a signal to the process","pid[,signal_number]",
303 1.114.6.2 mjf " pid:\t\t\tthe process id (may need 0t prefix for decimal)\n"
304 1.114.6.2 mjf " signal_number:\tthe signal to send") },
305 1.114.6.2 mjf #ifdef KGDB
306 1.114.6.2 mjf { DDB_ADD_CMD("kgdb", db_kgdb_cmd, 0, NULL,NULL,NULL) },
307 1.114.6.2 mjf #endif
308 1.114.6.2 mjf { DDB_ADD_CMD("machine",NULL,CS_MACH,
309 1.114.6.2 mjf "Architecture specific functions.",NULL,NULL) },
310 1.114.6.2 mjf { DDB_ADD_CMD("match", db_trace_until_matching_cmd,0,
311 1.114.6.2 mjf "Stop at the matching return instruction.","See help next",NULL) },
312 1.114.6.2 mjf { DDB_ADD_CMD("next", db_trace_until_matching_cmd,0,
313 1.114.6.2 mjf "Stop at the matching return instruction.","[/p]",NULL) },
314 1.114.6.2 mjf { DDB_ADD_CMD("p", db_print_cmd, 0,
315 1.114.6.2 mjf "Print address according to the format.",
316 1.114.6.2 mjf "[/axzodurc] address [address ...]",NULL) },
317 1.114.6.2 mjf { DDB_ADD_CMD("print", db_print_cmd, 0,
318 1.114.6.2 mjf "Print address according to the format.",
319 1.114.6.2 mjf "[/axzodurc] address [address ...]",NULL) },
320 1.114.6.2 mjf { DDB_ADD_CMD("ps", db_show_all_procs, 0,
321 1.114.6.2 mjf "Print all processes.","See show all procs",NULL) },
322 1.114.6.2 mjf { DDB_ADD_CMD("reboot", db_reboot_cmd, CS_OWN,
323 1.114.6.2 mjf "Reboot","0x1 RB_ASKNAME, 0x2 RB_SINGLE, 0x4 RB_NOSYNC, 0x8 RB_HALT,"
324 1.114.6.2 mjf "0x40 RB_KDB, 0x100 RB_DUMP, 0x808 RB_POWERDOWN",NULL) },
325 1.114.6.2 mjf { DDB_ADD_CMD("s", db_single_step_cmd, 0,
326 1.114.6.2 mjf "Single-step count times.","[/p] [,count]",NULL) },
327 1.114.6.2 mjf { DDB_ADD_CMD("search", db_search_cmd, CS_OWN|CS_SET_DOT,
328 1.114.6.2 mjf "Search memory from address for value.",
329 1.114.6.2 mjf "[/bhl] address value [mask] [,count]",NULL) },
330 1.114.6.2 mjf { DDB_ADD_CMD("set", db_set_cmd, CS_OWN,
331 1.114.6.2 mjf "Set the named variable","$variable [=] expression",NULL) },
332 1.114.6.2 mjf { DDB_ADD_CMD("show", NULL, CS_SHOW,
333 1.114.6.2 mjf "Show kernel stats.", NULL,NULL) },
334 1.114.6.2 mjf { DDB_ADD_CMD("sifting", db_sifting_cmd, CS_OWN,
335 1.114.6.2 mjf "Search the symbol tables ","[/F] string",NULL) },
336 1.114.6.2 mjf { DDB_ADD_CMD("step", db_single_step_cmd, 0,
337 1.114.6.2 mjf "Single-step count times.","[/p] [,count]",NULL) },
338 1.114.6.2 mjf { DDB_ADD_CMD("sync", db_sync_cmd, CS_OWN,
339 1.114.6.2 mjf "Force a crash dump, and then reboot.",NULL,NULL) },
340 1.114.6.2 mjf { DDB_ADD_CMD("trace", db_stack_trace_cmd, 0,
341 1.114.6.2 mjf "Stack trace from frame-address.",
342 1.114.6.2 mjf "[/u[l]] [frame-address][,count]",NULL) },
343 1.114.6.2 mjf { DDB_ADD_CMD("until", db_trace_until_call_cmd,0,
344 1.114.6.2 mjf "Stop at the next call or return instruction.","[/p]",NULL) },
345 1.114.6.2 mjf { DDB_ADD_CMD("w", db_write_cmd, CS_MORE|CS_SET_DOT,
346 1.114.6.2 mjf "Write the expressions at succeeding locations.",
347 1.114.6.2 mjf "[/bhl] address expression [expression ...]",NULL) },
348 1.114.6.2 mjf { DDB_ADD_CMD("watch", db_watchpoint_cmd, CS_MORE,
349 1.114.6.2 mjf "Set a watchpoint for a region. ","address[,size]",NULL) },
350 1.114.6.2 mjf { DDB_ADD_CMD("whatis", db_whatis_cmd, 0,
351 1.114.6.2 mjf "Describe what an address is", "address", NULL) },
352 1.114.6.2 mjf { DDB_ADD_CMD("write", db_write_cmd, CS_MORE|CS_SET_DOT,
353 1.114.6.2 mjf "Write the expressions at succeeding locations.",
354 1.114.6.2 mjf "[/bhl] address expression [expression ...]",NULL) },
355 1.114.6.2 mjf { DDB_ADD_CMD("x", db_examine_cmd, CS_SET_DOT,
356 1.114.6.2 mjf "Display the address locations.",
357 1.114.6.2 mjf "[/modifier] address[,count]",NULL) },
358 1.114.6.2 mjf { DDB_ADD_CMD(NULL, NULL, 0, NULL, NULL, NULL) }
359 1.114.6.2 mjf };
360 1.114.6.2 mjf
361 1.114.6.2 mjf static const struct db_command *db_last_command = NULL;
362 1.114.6.2 mjf #if defined(DDB_COMMANDONENTER)
363 1.114.6.2 mjf char db_cmd_on_enter[DB_LINE_MAXLEN + 1] = ___STRING(DDB_COMMANDONENTER);
364 1.114.6.2 mjf #else /* defined(DDB_COMMANDONENTER) */
365 1.114.6.2 mjf char db_cmd_on_enter[DB_LINE_MAXLEN + 1] = "";
366 1.114.6.2 mjf #endif /* defined(DDB_COMMANDONENTER) */
367 1.114.6.2 mjf #define DB_LINE_SEP ';'
368 1.114.6.2 mjf
369 1.114.6.2 mjf /*
370 1.114.6.2 mjf * Utility routine - discard tokens through end-of-line.
371 1.114.6.2 mjf */
372 1.114.6.2 mjf void
373 1.114.6.2 mjf db_skip_to_eol(void)
374 1.114.6.2 mjf {
375 1.114.6.2 mjf int t;
376 1.114.6.2 mjf
377 1.114.6.2 mjf do {
378 1.114.6.2 mjf t = db_read_token();
379 1.114.6.2 mjf } while (t != tEOL);
380 1.114.6.2 mjf }
381 1.114.6.2 mjf
382 1.114.6.2 mjf void
383 1.114.6.2 mjf db_error(const char *s)
384 1.114.6.2 mjf {
385 1.114.6.2 mjf
386 1.114.6.2 mjf if (s)
387 1.114.6.2 mjf db_printf("%s", s);
388 1.114.6.2 mjf db_flush_lex();
389 1.114.6.2 mjf longjmp(db_recover);
390 1.114.6.2 mjf }
391 1.114.6.2 mjf
392 1.114.6.2 mjf /*Execute commandlist after ddb start
393 1.114.6.2 mjf *This function goes through the command list created from commands and ';'
394 1.114.6.2 mjf */
395 1.114.6.2 mjf
396 1.114.6.2 mjf static void
397 1.114.6.2 mjf db_execute_commandlist(const char *cmdlist)
398 1.114.6.2 mjf {
399 1.114.6.2 mjf const char *cmd = cmdlist;
400 1.114.6.2 mjf const struct db_command *dummy = NULL;
401 1.114.6.2 mjf
402 1.114.6.2 mjf while (*cmd != '\0') {
403 1.114.6.2 mjf const char *ep = cmd;
404 1.114.6.2 mjf
405 1.114.6.2 mjf while (*ep != '\0' && *ep != DB_LINE_SEP) {
406 1.114.6.2 mjf ep++;
407 1.114.6.2 mjf }
408 1.114.6.2 mjf db_set_line(cmd, ep);
409 1.114.6.2 mjf db_command(&dummy);
410 1.114.6.2 mjf cmd = ep;
411 1.114.6.2 mjf if (*cmd == DB_LINE_SEP) {
412 1.114.6.2 mjf cmd++;
413 1.114.6.2 mjf }
414 1.114.6.2 mjf }
415 1.114.6.2 mjf }
416 1.114.6.2 mjf
417 1.114.6.2 mjf /*Initialize ddb command tables*/
418 1.114.6.2 mjf void
419 1.114.6.2 mjf db_init_commands(void)
420 1.114.6.2 mjf {
421 1.114.6.2 mjf static bool done = false;
422 1.114.6.2 mjf
423 1.114.6.2 mjf if (done) return;
424 1.114.6.2 mjf done = true;
425 1.114.6.2 mjf
426 1.114.6.2 mjf /* register command tables */
427 1.114.6.2 mjf (void)db_register_tbl_entry(DDB_BASE_CMD, &db_base_cmd_builtins);
428 1.114.6.2 mjf #ifdef DB_MACHINE_COMMANDS
429 1.114.6.2 mjf (void)db_register_tbl_entry(DDB_MACH_CMD, &db_mach_cmd_builtins);
430 1.114.6.2 mjf #endif
431 1.114.6.2 mjf (void)db_register_tbl_entry(DDB_SHOW_CMD, &db_show_cmd_builtins);
432 1.114.6.2 mjf }
433 1.114.6.2 mjf
434 1.114.6.2 mjf
435 1.114.6.2 mjf /*
436 1.114.6.2 mjf * Add command table to the specified list
437 1.114.6.2 mjf * Arg:
438 1.114.6.2 mjf * int type specifies type of command table DDB_SHOW_CMD|DDB_BASE_CMD|DDB_MAC_CMD
439 1.114.6.2 mjf * *cmd_tbl poiter to static allocated db_command table
440 1.114.6.2 mjf *
441 1.114.6.2 mjf *Command table must be NULL terminated array of struct db_command
442 1.114.6.2 mjf */
443 1.114.6.2 mjf int
444 1.114.6.2 mjf db_register_tbl(uint8_t type, const struct db_command *cmd_tbl)
445 1.114.6.2 mjf {
446 1.114.6.2 mjf struct db_cmd_tbl_en *list_ent;
447 1.114.6.2 mjf
448 1.114.6.2 mjf if (cmd_tbl->name == 0)
449 1.114.6.2 mjf /* empty list - ignore */
450 1.114.6.2 mjf return 0;
451 1.114.6.2 mjf
452 1.114.6.2 mjf /* force builtin commands to be registered first */
453 1.114.6.2 mjf db_init_commands();
454 1.114.6.2 mjf
455 1.114.6.2 mjf /* now create a list entry for this table */
456 1.114.6.2 mjf list_ent = malloc(sizeof(struct db_cmd_tbl_en), M_TEMP, M_ZERO);
457 1.114.6.2 mjf if (list_ent == NULL)
458 1.114.6.2 mjf return ENOMEM;
459 1.114.6.2 mjf list_ent->db_cmd=cmd_tbl;
460 1.114.6.2 mjf
461 1.114.6.2 mjf /* and register it */
462 1.114.6.2 mjf return db_register_tbl_entry(type, list_ent);
463 1.114.6.2 mjf }
464 1.114.6.2 mjf
465 1.114.6.2 mjf static int
466 1.114.6.2 mjf db_register_tbl_entry(uint8_t type, struct db_cmd_tbl_en *list_ent)
467 1.114.6.2 mjf {
468 1.114.6.2 mjf struct db_cmd_tbl_en_head *list;
469 1.114.6.2 mjf
470 1.114.6.2 mjf switch(type) {
471 1.114.6.2 mjf case DDB_BASE_CMD:
472 1.114.6.2 mjf list = &db_base_cmd_list;
473 1.114.6.2 mjf break;
474 1.114.6.2 mjf case DDB_SHOW_CMD:
475 1.114.6.2 mjf list = &db_show_cmd_list;
476 1.114.6.2 mjf break;
477 1.114.6.2 mjf case DDB_MACH_CMD:
478 1.114.6.2 mjf list = &db_mach_cmd_list;
479 1.114.6.2 mjf break;
480 1.114.6.2 mjf default:
481 1.114.6.2 mjf return ENOENT;
482 1.114.6.2 mjf }
483 1.114.6.2 mjf
484 1.114.6.2 mjf TAILQ_INSERT_TAIL(list, list_ent, db_cmd_next);
485 1.114.6.2 mjf
486 1.114.6.2 mjf return 0;
487 1.114.6.2 mjf }
488 1.114.6.2 mjf
489 1.114.6.2 mjf /*
490 1.114.6.2 mjf * Remove command table specified with db_cmd address == cmd_tbl
491 1.114.6.2 mjf */
492 1.114.6.2 mjf int
493 1.114.6.2 mjf db_unregister_tbl(uint8_t type,const struct db_command *cmd_tbl)
494 1.114.6.2 mjf {
495 1.114.6.2 mjf struct db_cmd_tbl_en *list_ent;
496 1.114.6.2 mjf struct db_cmd_tbl_en_head *list;
497 1.114.6.2 mjf
498 1.114.6.2 mjf /* find list on which the entry should live */
499 1.114.6.2 mjf switch (type) {
500 1.114.6.2 mjf case DDB_BASE_CMD:
501 1.114.6.2 mjf list=&db_base_cmd_list;
502 1.114.6.2 mjf break;
503 1.114.6.2 mjf case DDB_SHOW_CMD:
504 1.114.6.2 mjf list=&db_show_cmd_list;
505 1.114.6.2 mjf break;
506 1.114.6.2 mjf case DDB_MACH_CMD:
507 1.114.6.2 mjf list=&db_mach_cmd_list;
508 1.114.6.2 mjf break;
509 1.114.6.2 mjf default:
510 1.114.6.2 mjf return EINVAL;
511 1.114.6.2 mjf }
512 1.114.6.2 mjf
513 1.114.6.2 mjf TAILQ_FOREACH (list_ent,list,db_cmd_next) {
514 1.114.6.2 mjf if (list_ent->db_cmd == cmd_tbl){
515 1.114.6.2 mjf TAILQ_REMOVE(list,
516 1.114.6.2 mjf list_ent,db_cmd_next);
517 1.114.6.2 mjf free(list_ent,M_TEMP);
518 1.114.6.2 mjf return 0;
519 1.114.6.2 mjf }
520 1.114.6.2 mjf }
521 1.114.6.2 mjf return ENOENT;
522 1.114.6.2 mjf }
523 1.114.6.2 mjf
524 1.114.6.2 mjf /*This function is called from machine trap code.*/
525 1.114.6.2 mjf void
526 1.114.6.2 mjf db_command_loop(void)
527 1.114.6.2 mjf {
528 1.114.6.2 mjf
529 1.114.6.2 mjf label_t db_jmpbuf;
530 1.114.6.2 mjf label_t *savejmp;
531 1.114.6.2 mjf
532 1.114.6.2 mjf /*
533 1.114.6.2 mjf * Initialize 'prev' and 'next' to dot.
534 1.114.6.2 mjf */
535 1.114.6.2 mjf db_prev = db_dot;
536 1.114.6.2 mjf db_next = db_dot;
537 1.114.6.2 mjf
538 1.114.6.2 mjf db_cmd_loop_done = false;
539 1.114.6.2 mjf
540 1.114.6.2 mjf /*Init default command tables add machine, base,
541 1.114.6.2 mjf show command tables to the list*/
542 1.114.6.2 mjf db_init_commands();
543 1.114.6.2 mjf
544 1.114.6.2 mjf /*save context for return from ddb*/
545 1.114.6.2 mjf savejmp = db_recover;
546 1.114.6.2 mjf db_recover = &db_jmpbuf;
547 1.114.6.2 mjf (void) setjmp(&db_jmpbuf);
548 1.114.6.2 mjf
549 1.114.6.2 mjf /*Execute default ddb start commands*/
550 1.114.6.2 mjf db_execute_commandlist(db_cmd_on_enter);
551 1.114.6.2 mjf
552 1.114.6.2 mjf (void) setjmp(&db_jmpbuf);
553 1.114.6.2 mjf while (!db_cmd_loop_done) {
554 1.114.6.2 mjf if (db_print_position() != 0)
555 1.114.6.2 mjf db_printf("\n");
556 1.114.6.2 mjf db_output_line = 0;
557 1.114.6.2 mjf
558 1.114.6.2 mjf
559 1.114.6.2 mjf #ifdef MULTIPROCESSOR
560 1.114.6.2 mjf db_printf("db{%ld}> ", (long)cpu_number());
561 1.114.6.2 mjf #else
562 1.114.6.2 mjf db_printf("db> ");
563 1.114.6.2 mjf #endif
564 1.114.6.2 mjf (void) db_read_line();
565 1.114.6.2 mjf
566 1.114.6.2 mjf db_command(&db_last_command);
567 1.114.6.2 mjf }
568 1.114.6.2 mjf
569 1.114.6.2 mjf db_recover = savejmp;
570 1.114.6.2 mjf }
571 1.114.6.2 mjf
572 1.114.6.2 mjf /*
573 1.114.6.2 mjf * Search for command table for command prefix
574 1.114.6.2 mjf * ret: CMD_UNIQUE -> completely matches command
575 1.114.6.2 mjf * CMD_FOUND -> matches prefix of single command
576 1.114.6.2 mjf * CMD_AMBIGIOUS -> matches prefix of more than one command
577 1.114.6.2 mjf * CMD_NONE -> command not found
578 1.114.6.2 mjf */
579 1.114.6.2 mjf static int
580 1.114.6.2 mjf db_cmd_search(const char *name,const struct db_command *table,
581 1.114.6.2 mjf const struct db_command **cmdp)
582 1.114.6.2 mjf {
583 1.114.6.2 mjf
584 1.114.6.2 mjf const struct db_command *cmd;
585 1.114.6.2 mjf int result;
586 1.114.6.2 mjf
587 1.114.6.2 mjf result = CMD_NONE;
588 1.114.6.2 mjf *cmdp = NULL;
589 1.114.6.2 mjf for (cmd = table; cmd->name != 0; cmd++) {
590 1.114.6.2 mjf const char *lp;
591 1.114.6.2 mjf const char *rp;
592 1.114.6.2 mjf
593 1.114.6.2 mjf lp = name;
594 1.114.6.2 mjf rp = cmd->name;
595 1.114.6.2 mjf while (*lp != '\0' && *lp == *rp) {
596 1.114.6.2 mjf rp++;
597 1.114.6.2 mjf lp++;
598 1.114.6.2 mjf }
599 1.114.6.2 mjf
600 1.114.6.2 mjf if (*lp != '\0') /* mismatch or extra chars in name */
601 1.114.6.2 mjf continue;
602 1.114.6.2 mjf
603 1.114.6.2 mjf if (*rp == '\0') { /* complete match */
604 1.114.6.2 mjf *cmdp = cmd;
605 1.114.6.2 mjf return (CMD_UNIQUE);
606 1.114.6.2 mjf }
607 1.114.6.2 mjf
608 1.114.6.2 mjf /* prefix match: end of name, not end of command */
609 1.114.6.2 mjf if (result == CMD_NONE) {
610 1.114.6.2 mjf result = CMD_FOUND;
611 1.114.6.2 mjf *cmdp = cmd;
612 1.114.6.2 mjf }
613 1.114.6.2 mjf else if (result == CMD_FOUND) {
614 1.114.6.2 mjf result = CMD_AMBIGUOUS;
615 1.114.6.2 mjf *cmdp = NULL;
616 1.114.6.2 mjf }
617 1.114.6.2 mjf }
618 1.114.6.2 mjf
619 1.114.6.2 mjf return (result);
620 1.114.6.2 mjf }
621 1.114.6.2 mjf
622 1.114.6.2 mjf /*
623 1.114.6.2 mjf *List commands to the console.
624 1.114.6.2 mjf */
625 1.114.6.2 mjf static void
626 1.114.6.2 mjf db_cmd_list(const struct db_cmd_tbl_en_head *list)
627 1.114.6.2 mjf {
628 1.114.6.2 mjf
629 1.114.6.2 mjf struct db_cmd_tbl_en *list_ent;
630 1.114.6.2 mjf const struct db_command *table;
631 1.114.6.2 mjf size_t i, j, w, columns, lines, numcmds, width=0;
632 1.114.6.2 mjf const char *p;
633 1.114.6.2 mjf
634 1.114.6.2 mjf TAILQ_FOREACH(list_ent,list,db_cmd_next) {
635 1.114.6.2 mjf table = list_ent->db_cmd;
636 1.114.6.2 mjf for (i = 0; table[i].name != NULL; i++) {
637 1.114.6.2 mjf w = strlen(table[i].name);
638 1.114.6.2 mjf if (w > width)
639 1.114.6.2 mjf width = w;
640 1.114.6.2 mjf }
641 1.114.6.2 mjf }
642 1.114.6.2 mjf
643 1.114.6.2 mjf width = DB_NEXT_TAB(width);
644 1.114.6.2 mjf
645 1.114.6.2 mjf columns = db_max_width / width;
646 1.114.6.2 mjf if (columns == 0)
647 1.114.6.2 mjf columns = 1;
648 1.114.6.2 mjf
649 1.114.6.2 mjf TAILQ_FOREACH(list_ent,list,db_cmd_next) {
650 1.114.6.2 mjf table = list_ent->db_cmd;
651 1.114.6.2 mjf
652 1.114.6.2 mjf for (numcmds = 0; table[numcmds].name != NULL; numcmds++)
653 1.114.6.2 mjf ;
654 1.114.6.2 mjf lines = (numcmds + columns - 1) / columns;
655 1.114.6.2 mjf
656 1.114.6.2 mjf for (i = 0; i < lines; i++) {
657 1.114.6.2 mjf for (j = 0; j < columns; j++) {
658 1.114.6.2 mjf p = table[j * lines + i].name;
659 1.114.6.2 mjf if (p)
660 1.114.6.2 mjf db_printf("%s", p);
661 1.114.6.2 mjf if (j * lines + i + lines >= numcmds) {
662 1.114.6.2 mjf db_putchar('\n');
663 1.114.6.2 mjf break;
664 1.114.6.2 mjf }
665 1.114.6.2 mjf if (p) {
666 1.114.6.2 mjf w = strlen(p);
667 1.114.6.2 mjf while (w < width) {
668 1.114.6.2 mjf w = DB_NEXT_TAB(w);
669 1.114.6.2 mjf db_putchar('\t');
670 1.114.6.2 mjf }
671 1.114.6.2 mjf }
672 1.114.6.2 mjf }
673 1.114.6.2 mjf }
674 1.114.6.2 mjf }
675 1.114.6.2 mjf return;
676 1.114.6.2 mjf }
677 1.114.6.2 mjf
678 1.114.6.2 mjf /*
679 1.114.6.2 mjf *Returns type of list for command with name *name.
680 1.114.6.2 mjf */
681 1.114.6.2 mjf static int
682 1.114.6.2 mjf db_get_list_type(const char *name)
683 1.114.6.2 mjf {
684 1.114.6.2 mjf
685 1.114.6.2 mjf const struct db_command *cmd;
686 1.114.6.2 mjf struct db_cmd_tbl_en *list_ent;
687 1.114.6.2 mjf int error,ret=-1;
688 1.114.6.2 mjf
689 1.114.6.2 mjf /* search for the command name */
690 1.114.6.2 mjf TAILQ_FOREACH(list_ent,&db_base_cmd_list,db_cmd_next) {
691 1.114.6.2 mjf /*
692 1.114.6.2 mjf * cmd_search returns CMD_UNIQUE, CMD_FOUND ...
693 1.114.6.2 mjf * CMD_UNIQUE when name was completly matched to cmd->name
694 1.114.6.2 mjf * CMD_FOUND when name was only partially matched to cmd->name
695 1.114.6.2 mjf * CMD_NONE command not found in a list
696 1.114.6.2 mjf * CMD_AMBIGIOUS ->more partialy matches
697 1.114.6.2 mjf */
698 1.114.6.2 mjf
699 1.114.6.2 mjf error = db_cmd_search(name, list_ent->db_cmd, &cmd);
700 1.114.6.2 mjf
701 1.114.6.2 mjf if (error == CMD_UNIQUE) {
702 1.114.6.2 mjf /* exact match found */
703 1.114.6.2 mjf if (cmd->flag == CS_SHOW) {
704 1.114.6.2 mjf ret = DDB_SHOW_CMD;
705 1.114.6.2 mjf break;
706 1.114.6.2 mjf }
707 1.114.6.2 mjf if (cmd->flag == CS_MACH) {
708 1.114.6.2 mjf ret = DDB_MACH_CMD;
709 1.114.6.2 mjf break;
710 1.114.6.2 mjf } else {
711 1.114.6.2 mjf ret = DDB_BASE_CMD;
712 1.114.6.2 mjf break;
713 1.114.6.2 mjf }
714 1.114.6.2 mjf
715 1.114.6.2 mjf } else if (error == CMD_FOUND) {
716 1.114.6.2 mjf /*
717 1.114.6.2 mjf * partial match, search will continue, but
718 1.114.6.2 mjf * note current result in case we won't
719 1.114.6.2 mjf * find anything better.
720 1.114.6.2 mjf */
721 1.114.6.2 mjf if (cmd->flag == CS_SHOW)
722 1.114.6.2 mjf ret = DDB_SHOW_CMD;
723 1.114.6.2 mjf else if (cmd->flag == CS_MACH)
724 1.114.6.2 mjf ret = DDB_MACH_CMD;
725 1.114.6.2 mjf else
726 1.114.6.2 mjf ret = DDB_BASE_CMD;
727 1.114.6.2 mjf }
728 1.114.6.2 mjf }
729 1.114.6.2 mjf
730 1.114.6.2 mjf return ret;
731 1.114.6.2 mjf }
732 1.114.6.2 mjf
733 1.114.6.2 mjf /*
734 1.114.6.2 mjf *Parse command line and execute apropriate function.
735 1.114.6.2 mjf */
736 1.114.6.2 mjf static void
737 1.114.6.2 mjf db_command(const struct db_command **last_cmdp)
738 1.114.6.2 mjf {
739 1.114.6.2 mjf const struct db_command *command;
740 1.114.6.2 mjf struct db_cmd_tbl_en *list_ent;
741 1.114.6.2 mjf struct db_cmd_tbl_en_head *list;
742 1.114.6.2 mjf
743 1.114.6.2 mjf int t;
744 1.114.6.2 mjf int result;
745 1.114.6.2 mjf
746 1.114.6.2 mjf char modif[TOK_STRING_SIZE];
747 1.114.6.2 mjf db_expr_t addr, count;
748 1.114.6.2 mjf bool have_addr = false;
749 1.114.6.2 mjf
750 1.114.6.2 mjf static db_expr_t last_count = 0;
751 1.114.6.2 mjf
752 1.114.6.2 mjf command = NULL; /* XXX gcc */
753 1.114.6.2 mjf
754 1.114.6.2 mjf t = db_read_token();
755 1.114.6.2 mjf if ((t == tEOL) || (t == tCOMMA)) {
756 1.114.6.2 mjf /*
757 1.114.6.2 mjf * An empty line repeats last command, at 'next'.
758 1.114.6.2 mjf * Only a count repeats the last command with the new count.
759 1.114.6.2 mjf */
760 1.114.6.2 mjf command = *last_cmdp;
761 1.114.6.2 mjf
762 1.114.6.2 mjf if (!command)
763 1.114.6.2 mjf return;
764 1.114.6.2 mjf
765 1.114.6.2 mjf addr = (db_expr_t)db_next;
766 1.114.6.2 mjf if (t == tCOMMA) {
767 1.114.6.2 mjf if (!db_expression(&count)) {
768 1.114.6.2 mjf db_printf("Count missing\n");
769 1.114.6.2 mjf db_flush_lex();
770 1.114.6.2 mjf return;
771 1.114.6.2 mjf }
772 1.114.6.2 mjf } else
773 1.114.6.2 mjf count = last_count;
774 1.114.6.2 mjf have_addr = false;
775 1.114.6.2 mjf modif[0] = '\0';
776 1.114.6.2 mjf db_skip_to_eol();
777 1.114.6.2 mjf
778 1.114.6.2 mjf } else if (t == tEXCL) {
779 1.114.6.2 mjf db_fncall(0, 0, 0, NULL);
780 1.114.6.2 mjf return;
781 1.114.6.2 mjf
782 1.114.6.2 mjf } else if (t != tIDENT) {
783 1.114.6.2 mjf db_printf("?\n");
784 1.114.6.2 mjf db_flush_lex();
785 1.114.6.2 mjf return;
786 1.114.6.2 mjf
787 1.114.6.2 mjf } else {
788 1.114.6.2 mjf
789 1.114.6.2 mjf switch(db_get_list_type(db_tok_string)) {
790 1.114.6.2 mjf
791 1.114.6.2 mjf case DDB_BASE_CMD:
792 1.114.6.2 mjf list = &db_base_cmd_list;
793 1.114.6.2 mjf break;
794 1.114.6.2 mjf
795 1.114.6.2 mjf case DDB_SHOW_CMD:
796 1.114.6.2 mjf list = &db_show_cmd_list;
797 1.114.6.2 mjf /* need to read show subcommand if show command list
798 1.114.6.2 mjf is used. */
799 1.114.6.2 mjf t = db_read_token();
800 1.114.6.2 mjf
801 1.114.6.2 mjf if (t != tIDENT) {
802 1.114.6.2 mjf /* if only show command is executed, print
803 1.114.6.2 mjf all subcommands */
804 1.114.6.2 mjf db_cmd_list(list);
805 1.114.6.2 mjf db_flush_lex();
806 1.114.6.2 mjf return;
807 1.114.6.2 mjf }
808 1.114.6.2 mjf break;
809 1.114.6.2 mjf case DDB_MACH_CMD:
810 1.114.6.2 mjf list = &db_mach_cmd_list;
811 1.114.6.2 mjf /* need to read machine subcommand if
812 1.114.6.2 mjf machine level 2 command list is used. */
813 1.114.6.2 mjf t = db_read_token();
814 1.114.6.2 mjf
815 1.114.6.2 mjf if (t != tIDENT) {
816 1.114.6.2 mjf /* if only show command is executed, print
817 1.114.6.2 mjf all subcommands */
818 1.114.6.2 mjf db_cmd_list(list);
819 1.114.6.2 mjf db_flush_lex();
820 1.114.6.2 mjf return;
821 1.114.6.2 mjf }
822 1.114.6.2 mjf break;
823 1.114.6.2 mjf default:
824 1.114.6.2 mjf db_printf("No such command\n");
825 1.114.6.2 mjf db_flush_lex();
826 1.114.6.2 mjf return;
827 1.114.6.2 mjf }
828 1.114.6.2 mjf
829 1.114.6.2 mjf COMPAT_RET:
830 1.114.6.2 mjf TAILQ_FOREACH(list_ent, list, db_cmd_next) {
831 1.114.6.2 mjf result = db_cmd_search(db_tok_string, list_ent->db_cmd,
832 1.114.6.2 mjf &command);
833 1.114.6.2 mjf
834 1.114.6.2 mjf /* after CMD_UNIQUE in cmd_list only a single command
835 1.114.6.2 mjf name is possible */
836 1.114.6.2 mjf if (result == CMD_UNIQUE)
837 1.114.6.2 mjf break;
838 1.114.6.2 mjf
839 1.114.6.2 mjf }
840 1.114.6.2 mjf
841 1.114.6.2 mjf /* check compatibility flag */
842 1.114.6.2 mjf if (command && command->flag & CS_COMPAT){
843 1.114.6.2 mjf t = db_read_token();
844 1.114.6.2 mjf if (t != tIDENT) {
845 1.114.6.2 mjf db_cmd_list(list);
846 1.114.6.2 mjf db_flush_lex();
847 1.114.6.2 mjf return;
848 1.114.6.2 mjf }
849 1.114.6.2 mjf
850 1.114.6.2 mjf /* support only level 2 commands here */
851 1.114.6.2 mjf goto COMPAT_RET;
852 1.114.6.2 mjf }
853 1.114.6.2 mjf
854 1.114.6.2 mjf if (!command) {
855 1.114.6.2 mjf db_printf("No such command\n");
856 1.114.6.2 mjf db_flush_lex();
857 1.114.6.2 mjf return;
858 1.114.6.2 mjf }
859 1.114.6.2 mjf
860 1.114.6.2 mjf if ((command->flag & CS_OWN) == 0) {
861 1.114.6.2 mjf
862 1.114.6.2 mjf /*
863 1.114.6.2 mjf * Standard syntax:
864 1.114.6.2 mjf * command [/modifier] [addr] [,count]
865 1.114.6.2 mjf */
866 1.114.6.2 mjf t = db_read_token(); /* get modifier */
867 1.114.6.2 mjf if (t == tSLASH) {
868 1.114.6.2 mjf t = db_read_token();
869 1.114.6.2 mjf if (t != tIDENT) {
870 1.114.6.2 mjf db_printf("Bad modifier\n");
871 1.114.6.2 mjf db_flush_lex();
872 1.114.6.2 mjf return;
873 1.114.6.2 mjf }
874 1.114.6.2 mjf /* save modifier */
875 1.114.6.2 mjf strlcpy(modif, db_tok_string, sizeof(modif));
876 1.114.6.2 mjf
877 1.114.6.2 mjf } else {
878 1.114.6.2 mjf db_unread_token(t);
879 1.114.6.2 mjf modif[0] = '\0';
880 1.114.6.2 mjf }
881 1.114.6.2 mjf
882 1.114.6.2 mjf if (db_expression(&addr)) { /*get address*/
883 1.114.6.2 mjf db_dot = (db_addr_t) addr;
884 1.114.6.2 mjf db_last_addr = db_dot;
885 1.114.6.2 mjf have_addr = true;
886 1.114.6.2 mjf } else {
887 1.114.6.2 mjf addr = (db_expr_t) db_dot;
888 1.114.6.2 mjf have_addr = false;
889 1.114.6.2 mjf }
890 1.114.6.2 mjf
891 1.114.6.2 mjf t = db_read_token();
892 1.114.6.2 mjf if (t == tCOMMA) { /*Get count*/
893 1.114.6.2 mjf if (!db_expression(&count)) {
894 1.114.6.2 mjf db_printf("Count missing\n");
895 1.114.6.2 mjf db_flush_lex();
896 1.114.6.2 mjf return;
897 1.114.6.2 mjf }
898 1.114.6.2 mjf } else {
899 1.114.6.2 mjf db_unread_token(t);
900 1.114.6.2 mjf count = -1;
901 1.114.6.2 mjf }
902 1.114.6.2 mjf if ((command->flag & CS_MORE) == 0) {
903 1.114.6.2 mjf db_skip_to_eol();
904 1.114.6.2 mjf }
905 1.114.6.2 mjf }
906 1.114.6.2 mjf }
907 1.114.6.2 mjf
908 1.114.6.2 mjf if (command->flag & CS_NOREPEAT) {
909 1.114.6.2 mjf *last_cmdp = NULL;
910 1.114.6.2 mjf last_count = 0;
911 1.114.6.2 mjf } else {
912 1.114.6.2 mjf *last_cmdp = command;
913 1.114.6.2 mjf last_count = count;
914 1.114.6.2 mjf }
915 1.114.6.2 mjf
916 1.114.6.2 mjf if (command != NULL) {
917 1.114.6.2 mjf /*
918 1.114.6.2 mjf * Execute the command.
919 1.114.6.2 mjf */
920 1.114.6.2 mjf if (command->fcn != NULL)
921 1.114.6.2 mjf (*command->fcn)(addr, have_addr, count, modif);
922 1.114.6.2 mjf
923 1.114.6.2 mjf if (command->flag & CS_SET_DOT) {
924 1.114.6.2 mjf /*
925 1.114.6.2 mjf * If command changes dot, set dot to
926 1.114.6.2 mjf * previous address displayed (if 'ed' style).
927 1.114.6.2 mjf */
928 1.114.6.2 mjf if (db_ed_style)
929 1.114.6.2 mjf db_dot = db_prev;
930 1.114.6.2 mjf else
931 1.114.6.2 mjf db_dot = db_next;
932 1.114.6.2 mjf } else {
933 1.114.6.2 mjf /*
934 1.114.6.2 mjf * If command does not change dot,
935 1.114.6.2 mjf * set 'next' location to be the same.
936 1.114.6.2 mjf */
937 1.114.6.2 mjf db_next = db_dot;
938 1.114.6.2 mjf }
939 1.114.6.2 mjf }
940 1.114.6.2 mjf }
941 1.114.6.2 mjf
942 1.114.6.2 mjf /*
943 1.114.6.2 mjf * Print help for commands
944 1.114.6.2 mjf */
945 1.114.6.2 mjf static void
946 1.114.6.2 mjf db_help_print_cmd(db_expr_t addr, bool have_addr, db_expr_t count,
947 1.114.6.2 mjf const char *modif)
948 1.114.6.2 mjf {
949 1.114.6.2 mjf
950 1.114.6.2 mjf const struct db_cmd_tbl_en_head *list;
951 1.114.6.2 mjf const struct db_cmd_tbl_en *list_ent;
952 1.114.6.2 mjf const struct db_command *help = NULL;
953 1.114.6.2 mjf int t, result;
954 1.114.6.2 mjf
955 1.114.6.2 mjf t = db_read_token();
956 1.114.6.2 mjf /* is there another command after the "help"? */
957 1.114.6.2 mjf if (t == tIDENT){
958 1.114.6.2 mjf
959 1.114.6.2 mjf switch(db_get_list_type(db_tok_string)) {
960 1.114.6.2 mjf
961 1.114.6.2 mjf case DDB_BASE_CMD:
962 1.114.6.2 mjf list=&db_base_cmd_list;
963 1.114.6.2 mjf break;
964 1.114.6.2 mjf case DDB_SHOW_CMD:
965 1.114.6.2 mjf list=&db_show_cmd_list;
966 1.114.6.2 mjf /* read the show subcommand */
967 1.114.6.2 mjf t = db_read_token();
968 1.114.6.2 mjf
969 1.114.6.2 mjf if (t != tIDENT) {
970 1.114.6.2 mjf /* no subcommand, print the list */
971 1.114.6.2 mjf db_cmd_list(list);
972 1.114.6.2 mjf db_flush_lex();
973 1.114.6.2 mjf return;
974 1.114.6.2 mjf }
975 1.114.6.2 mjf
976 1.114.6.2 mjf break;
977 1.114.6.2 mjf case DDB_MACH_CMD:
978 1.114.6.2 mjf list=&db_mach_cmd_list;
979 1.114.6.2 mjf /* read machine subcommand */
980 1.114.6.2 mjf t = db_read_token();
981 1.114.6.2 mjf
982 1.114.6.2 mjf if (t != tIDENT) {
983 1.114.6.2 mjf /* no subcommand - just print the list */
984 1.114.6.2 mjf db_cmd_list(list);
985 1.114.6.2 mjf db_flush_lex();
986 1.114.6.2 mjf return;
987 1.114.6.2 mjf }
988 1.114.6.2 mjf break;
989 1.114.6.2 mjf
990 1.114.6.2 mjf default:
991 1.114.6.2 mjf db_printf("No such command\n");
992 1.114.6.2 mjf db_flush_lex();
993 1.114.6.2 mjf return;
994 1.114.6.2 mjf }
995 1.114.6.2 mjf COMPAT_RET:
996 1.114.6.2 mjf TAILQ_FOREACH(list_ent,list,db_cmd_next){
997 1.114.6.2 mjf result = db_cmd_search(db_tok_string, list_ent->db_cmd,
998 1.114.6.2 mjf &help);
999 1.114.6.2 mjf /* after CMD_UNIQUE only a single command
1000 1.114.6.2 mjf name is possible */
1001 1.114.6.2 mjf if (result == CMD_UNIQUE)
1002 1.114.6.2 mjf break;
1003 1.114.6.2 mjf }
1004 1.114.6.2 mjf #ifdef DDB_VERBOSE_HELP
1005 1.114.6.2 mjf /*print help*/
1006 1.114.6.2 mjf
1007 1.114.6.2 mjf db_printf("Command: %s\n",help->name);
1008 1.114.6.2 mjf
1009 1.114.6.2 mjf if (help->cmd_descr != NULL)
1010 1.114.6.2 mjf db_printf(" Description: %s\n",help->cmd_descr);
1011 1.114.6.2 mjf
1012 1.114.6.2 mjf if (help->cmd_arg != NULL)
1013 1.114.6.2 mjf db_printf(" Arguments: %s\n",help->cmd_arg);
1014 1.114.6.2 mjf
1015 1.114.6.2 mjf if (help->cmd_arg_help != NULL)
1016 1.114.6.2 mjf db_printf(" Arguments description:\n%s\n",
1017 1.114.6.2 mjf help->cmd_arg_help);
1018 1.114.6.2 mjf
1019 1.114.6.2 mjf if ((help->cmd_arg == NULL) && (help->cmd_descr == NULL))
1020 1.114.6.2 mjf db_printf("%s Doesn't have any help message included.\n",
1021 1.114.6.2 mjf help->name);
1022 1.114.6.2 mjf #endif
1023 1.114.6.2 mjf /* check compatibility flag */
1024 1.114.6.2 mjf /*
1025 1.114.6.2 mjf * The "show all" command table has been merged with the
1026 1.114.6.2 mjf * "show" command table - but we want to keep the old UI
1027 1.114.6.2 mjf * available. So if we find a CS_COMPAT entry, we read
1028 1.114.6.2 mjf * the next token and try again.
1029 1.114.6.2 mjf */
1030 1.114.6.2 mjf if (help->flag == CS_COMPAT){
1031 1.114.6.2 mjf t = db_read_token();
1032 1.114.6.2 mjf
1033 1.114.6.2 mjf if (t != tIDENT){
1034 1.114.6.2 mjf db_cmd_list(list);
1035 1.114.6.2 mjf db_flush_lex();
1036 1.114.6.2 mjf return;
1037 1.114.6.2 mjf }
1038 1.114.6.2 mjf
1039 1.114.6.2 mjf goto COMPAT_RET;
1040 1.114.6.2 mjf /* support only level 2 commands here */
1041 1.114.6.2 mjf } else {
1042 1.114.6.2 mjf db_skip_to_eol();
1043 1.114.6.2 mjf }
1044 1.114.6.2 mjf
1045 1.114.6.2 mjf } else /* t != tIDENT */
1046 1.114.6.2 mjf /* print base commands */
1047 1.114.6.2 mjf db_cmd_list(&db_base_cmd_list);
1048 1.114.6.2 mjf
1049 1.114.6.2 mjf return;
1050 1.114.6.2 mjf }
1051 1.114.6.2 mjf
1052 1.114.6.2 mjf /*ARGSUSED*/
1053 1.114.6.2 mjf static void
1054 1.114.6.2 mjf db_map_print_cmd(db_expr_t addr, bool have_addr, db_expr_t count,
1055 1.114.6.2 mjf const char *modif)
1056 1.114.6.2 mjf {
1057 1.114.6.2 mjf bool full = false;
1058 1.114.6.2 mjf
1059 1.114.6.2 mjf if (modif[0] == 'f')
1060 1.114.6.2 mjf full = true;
1061 1.114.6.2 mjf
1062 1.114.6.2 mjf if (have_addr == false)
1063 1.114.6.2 mjf addr = (db_expr_t)(intptr_t) kernel_map;
1064 1.114.6.2 mjf
1065 1.114.6.2 mjf uvm_map_printit((struct vm_map *)(intptr_t) addr, full, db_printf);
1066 1.114.6.2 mjf }
1067 1.114.6.2 mjf
1068 1.114.6.2 mjf /*ARGSUSED*/
1069 1.114.6.2 mjf static void
1070 1.114.6.2 mjf db_malloc_print_cmd(db_expr_t addr, bool have_addr,
1071 1.114.6.2 mjf db_expr_t count, const char *modif)
1072 1.114.6.2 mjf {
1073 1.114.6.2 mjf
1074 1.114.6.2 mjf #ifdef MALLOC_DEBUG
1075 1.114.6.2 mjf if (!have_addr)
1076 1.114.6.2 mjf addr = 0;
1077 1.114.6.2 mjf
1078 1.114.6.2 mjf debug_malloc_printit(db_printf, (vaddr_t) addr);
1079 1.114.6.2 mjf #else
1080 1.114.6.2 mjf db_printf("The kernel is not built with the MALLOC_DEBUG option.\n");
1081 1.114.6.2 mjf #endif /* MALLOC_DEBUG */
1082 1.114.6.2 mjf }
1083 1.114.6.2 mjf
1084 1.114.6.2 mjf /*ARGSUSED*/
1085 1.114.6.2 mjf static void
1086 1.114.6.2 mjf db_object_print_cmd(db_expr_t addr, bool have_addr,
1087 1.114.6.2 mjf db_expr_t count, const char *modif)
1088 1.114.6.2 mjf {
1089 1.114.6.2 mjf bool full = false;
1090 1.114.6.2 mjf
1091 1.114.6.2 mjf if (modif[0] == 'f')
1092 1.114.6.2 mjf full = true;
1093 1.114.6.2 mjf
1094 1.114.6.2 mjf uvm_object_printit((struct uvm_object *)(intptr_t) addr, full,
1095 1.114.6.2 mjf db_printf);
1096 1.114.6.2 mjf }
1097 1.114.6.2 mjf
1098 1.114.6.2 mjf /*ARGSUSED*/
1099 1.114.6.2 mjf static void
1100 1.114.6.2 mjf db_page_print_cmd(db_expr_t addr, bool have_addr,
1101 1.114.6.2 mjf db_expr_t count, const char *modif)
1102 1.114.6.2 mjf {
1103 1.114.6.2 mjf bool full = false;
1104 1.114.6.2 mjf
1105 1.114.6.2 mjf if (modif[0] == 'f')
1106 1.114.6.2 mjf full = true;
1107 1.114.6.2 mjf
1108 1.114.6.2 mjf uvm_page_printit((struct vm_page *)(intptr_t) addr, full, db_printf);
1109 1.114.6.2 mjf }
1110 1.114.6.2 mjf
1111 1.114.6.2 mjf /*ARGSUSED*/
1112 1.114.6.2 mjf static void
1113 1.114.6.2 mjf db_show_all_pages(db_expr_t addr, bool have_addr,
1114 1.114.6.2 mjf db_expr_t count, const char *modif)
1115 1.114.6.2 mjf {
1116 1.114.6.2 mjf
1117 1.114.6.2 mjf uvm_page_printall(db_printf);
1118 1.114.6.2 mjf }
1119 1.114.6.2 mjf
1120 1.114.6.2 mjf /*ARGSUSED*/
1121 1.114.6.2 mjf static void
1122 1.114.6.2 mjf db_buf_print_cmd(db_expr_t addr, bool have_addr,
1123 1.114.6.2 mjf db_expr_t count, const char *modif)
1124 1.114.6.2 mjf {
1125 1.114.6.2 mjf bool full = false;
1126 1.114.6.2 mjf
1127 1.114.6.2 mjf if (modif[0] == 'f')
1128 1.114.6.2 mjf full = true;
1129 1.114.6.2 mjf
1130 1.114.6.2 mjf vfs_buf_print((struct buf *)(intptr_t) addr, full, db_printf);
1131 1.114.6.2 mjf }
1132 1.114.6.2 mjf
1133 1.114.6.2 mjf /*ARGSUSED*/
1134 1.114.6.2 mjf static void
1135 1.114.6.2 mjf db_event_print_cmd(db_expr_t addr, bool have_addr,
1136 1.114.6.2 mjf db_expr_t count, const char *modif)
1137 1.114.6.2 mjf {
1138 1.114.6.2 mjf bool full = false;
1139 1.114.6.2 mjf
1140 1.114.6.2 mjf if (modif[0] == 'f')
1141 1.114.6.2 mjf full = true;
1142 1.114.6.2 mjf
1143 1.114.6.2 mjf event_print(full, db_printf);
1144 1.114.6.2 mjf }
1145 1.114.6.2 mjf
1146 1.114.6.2 mjf /*ARGSUSED*/
1147 1.114.6.2 mjf static void
1148 1.114.6.2 mjf db_vnode_print_cmd(db_expr_t addr, bool have_addr,
1149 1.114.6.2 mjf db_expr_t count, const char *modif)
1150 1.114.6.2 mjf {
1151 1.114.6.2 mjf bool full = false;
1152 1.114.6.2 mjf
1153 1.114.6.2 mjf if (modif[0] == 'f')
1154 1.114.6.2 mjf full = true;
1155 1.114.6.2 mjf
1156 1.114.6.2 mjf vfs_vnode_print((struct vnode *)(intptr_t) addr, full, db_printf);
1157 1.114.6.2 mjf }
1158 1.114.6.2 mjf
1159 1.114.6.2 mjf static void
1160 1.114.6.2 mjf db_mount_print_cmd(db_expr_t addr, bool have_addr,
1161 1.114.6.2 mjf db_expr_t count, const char *modif)
1162 1.114.6.2 mjf {
1163 1.114.6.2 mjf bool full = false;
1164 1.114.6.2 mjf
1165 1.114.6.2 mjf if (modif[0] == 'f')
1166 1.114.6.2 mjf full = true;
1167 1.114.6.2 mjf
1168 1.114.6.2 mjf vfs_mount_print((struct mount *)(intptr_t) addr, full, db_printf);
1169 1.114.6.2 mjf }
1170 1.114.6.2 mjf
1171 1.114.6.2 mjf /*ARGSUSED*/
1172 1.114.6.2 mjf static void
1173 1.114.6.2 mjf db_mbuf_print_cmd(db_expr_t addr, bool have_addr,
1174 1.114.6.2 mjf db_expr_t count, const char *modif)
1175 1.114.6.2 mjf {
1176 1.114.6.2 mjf
1177 1.114.6.2 mjf m_print((const struct mbuf *)(intptr_t) addr, modif, db_printf);
1178 1.114.6.2 mjf }
1179 1.114.6.2 mjf
1180 1.114.6.2 mjf /*ARGSUSED*/
1181 1.114.6.2 mjf static void
1182 1.114.6.2 mjf db_pool_print_cmd(db_expr_t addr, bool have_addr,
1183 1.114.6.2 mjf db_expr_t count, const char *modif)
1184 1.114.6.2 mjf {
1185 1.114.6.2 mjf
1186 1.114.6.2 mjf pool_printit((struct pool *)(intptr_t) addr, modif, db_printf);
1187 1.114.6.2 mjf }
1188 1.114.6.2 mjf
1189 1.114.6.2 mjf /*ARGSUSED*/
1190 1.114.6.2 mjf static void
1191 1.114.6.2 mjf db_namecache_print_cmd(db_expr_t addr, bool have_addr,
1192 1.114.6.2 mjf db_expr_t count, const char *modif)
1193 1.114.6.2 mjf {
1194 1.114.6.2 mjf
1195 1.114.6.2 mjf namecache_print((struct vnode *)(intptr_t) addr, db_printf);
1196 1.114.6.2 mjf }
1197 1.114.6.2 mjf
1198 1.114.6.2 mjf /*ARGSUSED*/
1199 1.114.6.2 mjf static void
1200 1.114.6.2 mjf db_uvmexp_print_cmd(db_expr_t addr, bool have_addr,
1201 1.114.6.2 mjf db_expr_t count, const char *modif)
1202 1.114.6.2 mjf {
1203 1.114.6.2 mjf
1204 1.114.6.2 mjf uvmexp_print(db_printf);
1205 1.114.6.2 mjf }
1206 1.114.6.2 mjf
1207 1.114.6.2 mjf /*ARGSUSED*/
1208 1.114.6.2 mjf static void
1209 1.114.6.2 mjf db_lock_print_cmd(db_expr_t addr, bool have_addr,
1210 1.114.6.2 mjf db_expr_t count, const char *modif)
1211 1.114.6.2 mjf {
1212 1.114.6.2 mjf
1213 1.114.6.2 mjf lockdebug_lock_print((void *)addr, db_printf);
1214 1.114.6.2 mjf }
1215 1.114.6.2 mjf
1216 1.114.6.2 mjf /*
1217 1.114.6.2 mjf * Call random function:
1218 1.114.6.2 mjf * !expr(arg,arg,arg)
1219 1.114.6.2 mjf */
1220 1.114.6.2 mjf /*ARGSUSED*/
1221 1.114.6.2 mjf static void
1222 1.114.6.2 mjf db_fncall(db_expr_t addr, bool have_addr,
1223 1.114.6.2 mjf db_expr_t count, const char *modif)
1224 1.114.6.2 mjf {
1225 1.114.6.2 mjf db_expr_t fn_addr;
1226 1.114.6.2 mjf #define MAXARGS 11
1227 1.114.6.2 mjf db_expr_t args[MAXARGS];
1228 1.114.6.2 mjf int nargs = 0;
1229 1.114.6.2 mjf db_expr_t retval;
1230 1.114.6.2 mjf db_expr_t (*func)(db_expr_t, ...);
1231 1.114.6.2 mjf int t;
1232 1.114.6.2 mjf
1233 1.114.6.2 mjf if (!db_expression(&fn_addr)) {
1234 1.114.6.2 mjf db_printf("Bad function\n");
1235 1.114.6.2 mjf db_flush_lex();
1236 1.114.6.2 mjf return;
1237 1.114.6.2 mjf }
1238 1.114.6.2 mjf func = (db_expr_t (*)(db_expr_t, ...))(intptr_t) fn_addr;
1239 1.114.6.2 mjf
1240 1.114.6.2 mjf t = db_read_token();
1241 1.114.6.2 mjf if (t == tLPAREN) {
1242 1.114.6.2 mjf if (db_expression(&args[0])) {
1243 1.114.6.2 mjf nargs++;
1244 1.114.6.2 mjf while ((t = db_read_token()) == tCOMMA) {
1245 1.114.6.2 mjf if (nargs == MAXARGS) {
1246 1.114.6.2 mjf db_printf("Too many arguments\n");
1247 1.114.6.2 mjf db_flush_lex();
1248 1.114.6.2 mjf return;
1249 1.114.6.2 mjf }
1250 1.114.6.2 mjf if (!db_expression(&args[nargs])) {
1251 1.114.6.2 mjf db_printf("Argument missing\n");
1252 1.114.6.2 mjf db_flush_lex();
1253 1.114.6.2 mjf return;
1254 1.114.6.2 mjf }
1255 1.114.6.2 mjf nargs++;
1256 1.114.6.2 mjf }
1257 1.114.6.2 mjf db_unread_token(t);
1258 1.114.6.2 mjf }
1259 1.114.6.2 mjf if (db_read_token() != tRPAREN) {
1260 1.114.6.2 mjf db_printf("?\n");
1261 1.114.6.2 mjf db_flush_lex();
1262 1.114.6.2 mjf return;
1263 1.114.6.2 mjf }
1264 1.114.6.2 mjf }
1265 1.114.6.2 mjf db_skip_to_eol();
1266 1.114.6.2 mjf
1267 1.114.6.2 mjf while (nargs < MAXARGS) {
1268 1.114.6.2 mjf args[nargs++] = 0;
1269 1.114.6.2 mjf }
1270 1.114.6.2 mjf
1271 1.114.6.2 mjf retval = (*func)(args[0], args[1], args[2], args[3], args[4],
1272 1.114.6.2 mjf args[5], args[6], args[7], args[8], args[9]);
1273 1.114.6.2 mjf db_printf("%s\n", db_num_to_str(retval));
1274 1.114.6.2 mjf }
1275 1.114.6.2 mjf
1276 1.114.6.2 mjf static void
1277 1.114.6.2 mjf db_reboot_cmd(db_expr_t addr, bool have_addr,
1278 1.114.6.2 mjf db_expr_t count, const char *modif)
1279 1.114.6.2 mjf {
1280 1.114.6.2 mjf db_expr_t bootflags;
1281 1.114.6.2 mjf
1282 1.114.6.2 mjf /* Flags, default to RB_AUTOBOOT */
1283 1.114.6.2 mjf if (!db_expression(&bootflags))
1284 1.114.6.2 mjf bootflags = (db_expr_t)RB_AUTOBOOT;
1285 1.114.6.2 mjf if (db_read_token() != tEOL) {
1286 1.114.6.2 mjf db_error("?\n");
1287 1.114.6.2 mjf /*NOTREACHED*/
1288 1.114.6.2 mjf }
1289 1.114.6.2 mjf /*
1290 1.114.6.2 mjf * We are leaving DDB, never to return upward.
1291 1.114.6.2 mjf * Clear db_recover so that we can debug faults in functions
1292 1.114.6.2 mjf * called from cpu_reboot.
1293 1.114.6.2 mjf */
1294 1.114.6.2 mjf db_recover = 0;
1295 1.114.6.2 mjf cpu_reboot((int)bootflags, NULL);
1296 1.114.6.2 mjf }
1297 1.114.6.2 mjf
1298 1.114.6.2 mjf static void
1299 1.114.6.2 mjf db_sifting_cmd(db_expr_t addr, bool have_addr,
1300 1.114.6.2 mjf db_expr_t count, const char *modif)
1301 1.114.6.2 mjf {
1302 1.114.6.2 mjf int mode, t;
1303 1.114.6.2 mjf
1304 1.114.6.2 mjf t = db_read_token();
1305 1.114.6.2 mjf if (t == tSLASH) {
1306 1.114.6.2 mjf t = db_read_token();
1307 1.114.6.2 mjf if (t != tIDENT) {
1308 1.114.6.2 mjf bad_modifier:
1309 1.114.6.2 mjf db_printf("Bad modifier\n");
1310 1.114.6.2 mjf db_flush_lex();
1311 1.114.6.2 mjf return;
1312 1.114.6.2 mjf }
1313 1.114.6.2 mjf if (!strcmp(db_tok_string, "F"))
1314 1.114.6.2 mjf mode = 'F';
1315 1.114.6.2 mjf else
1316 1.114.6.2 mjf goto bad_modifier;
1317 1.114.6.2 mjf t = db_read_token();
1318 1.114.6.2 mjf } else
1319 1.114.6.2 mjf mode = 0;
1320 1.114.6.2 mjf
1321 1.114.6.2 mjf if (t == tIDENT)
1322 1.114.6.2 mjf db_sifting(db_tok_string, mode);
1323 1.114.6.2 mjf else {
1324 1.114.6.2 mjf db_printf("Bad argument (non-string)\n");
1325 1.114.6.2 mjf db_flush_lex();
1326 1.114.6.2 mjf }
1327 1.114.6.2 mjf }
1328 1.114.6.2 mjf
1329 1.114.6.2 mjf static void
1330 1.114.6.2 mjf db_stack_trace_cmd(db_expr_t addr, bool have_addr, db_expr_t count, const char *modif)
1331 1.114.6.2 mjf {
1332 1.114.6.2 mjf register const char *cp = modif;
1333 1.114.6.2 mjf register char c;
1334 1.114.6.2 mjf void (*pr)(const char *, ...);
1335 1.114.6.2 mjf
1336 1.114.6.2 mjf pr = db_printf;
1337 1.114.6.2 mjf while ((c = *cp++) != 0)
1338 1.114.6.2 mjf if (c == 'l')
1339 1.114.6.2 mjf pr = printf;
1340 1.114.6.2 mjf
1341 1.114.6.2 mjf if (count == -1)
1342 1.114.6.2 mjf count = 65535;
1343 1.114.6.2 mjf
1344 1.114.6.2 mjf db_stack_trace_print(addr, have_addr, count, modif, pr);
1345 1.114.6.2 mjf }
1346 1.114.6.2 mjf
1347 1.114.6.2 mjf static void
1348 1.114.6.2 mjf db_sync_cmd(db_expr_t addr, bool have_addr,
1349 1.114.6.2 mjf db_expr_t count, const char *modif)
1350 1.114.6.2 mjf {
1351 1.114.6.2 mjf
1352 1.114.6.2 mjf /*
1353 1.114.6.2 mjf * We are leaving DDB, never to return upward.
1354 1.114.6.2 mjf * Clear db_recover so that we can debug faults in functions
1355 1.114.6.2 mjf * called from cpu_reboot.
1356 1.114.6.2 mjf */
1357 1.114.6.2 mjf db_recover = 0;
1358 1.114.6.2 mjf panicstr = "dump forced via kernel debugger";
1359 1.114.6.2 mjf cpu_reboot(RB_DUMP, NULL);
1360 1.114.6.2 mjf }
1361 1.114.6.2 mjf
1362 1.114.6.2 mjf /*
1363 1.114.6.2 mjf * Describe what an address is
1364 1.114.6.2 mjf */
1365 1.114.6.2 mjf void
1366 1.114.6.2 mjf db_whatis_cmd(db_expr_t address, bool have_addr,
1367 1.114.6.2 mjf db_expr_t count, const char *modif)
1368 1.114.6.2 mjf {
1369 1.114.6.2 mjf const uintptr_t addr = (uintptr_t)address;
1370 1.114.6.2 mjf
1371 1.114.6.2 mjf lwp_whatis(addr, db_printf);
1372 1.114.6.2 mjf pool_whatis(addr, db_printf);
1373 1.114.6.2 mjf vmem_whatis(addr, db_printf);
1374 1.114.6.2 mjf uvm_whatis(addr, db_printf);
1375 1.114.6.2 mjf }
1376