1 /* $NetBSD: db_variables.c,v 1.41 2009/03/07 22:02:17 ad Exp $ */
4 * Mach Operating System
5 * Copyright (c) 1991,1990 Carnegie Mellon University
8 * Permission to use, copy, modify and distribute this software and its
9 * documentation is hereby granted, provided that both the copyright
10 * notice and this permission notice appear in all copies of the
11 * software, derivative works or modified versions, and any portions
12 * thereof, and that both notices appear in supporting documentation.
14 * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
15 * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
16 * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
18 * Carnegie Mellon requests users of this software to return to
20 * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
21 * School of Computer Science
22 * Carnegie Mellon University
23 * Pittsburgh PA 15213-3890
25 * any improvements or extensions that they make and grant Carnegie the
26 * rights to redistribute these changes.
29 #include <sys/cdefs.h>
30 __KERNEL_RCSID(0, "$NetBSD: db_variables.c,v 1.41 2009/03/07 22:02:17 ad Exp $");
33 #include "opt_ddbparam.h"
36 #include <sys/param.h>
38 #include <uvm/uvm_extern.h>
39 #include <sys/sysctl.h>
42 #include <ddb/ddbvar.h>
45 * If this is non-zero, the DDB will be entered when the system
46 * panics. Initialize it so that it's patchable.
51 int db_onpanic
= DDB_ONPANIC
;
54 * Can DDB can be entered from the console?
56 #ifndef DDB_FROMCONSOLE
57 #define DDB_FROMCONSOLE 1
59 int db_fromconsole
= DDB_FROMCONSOLE
;
62 * Output DDB output to the message buffer?
64 #ifndef DDB_TEE_MSGBUF
65 #define DDB_TEE_MSGBUF 0
67 int db_tee_msgbuf
= DDB_TEE_MSGBUF
;
70 static int db_rw_internal_variable(const struct db_variable
*, db_expr_t
*,
72 static int db_find_variable(const struct db_variable
**);
74 /* XXX must all be ints for sysctl. */
75 const struct db_variable db_vars
[] = {
76 { "radix", (void *)&db_radix
, db_rw_internal_variable
, NULL
},
77 { "maxoff", (void *)&db_maxoff
, db_rw_internal_variable
, NULL
},
78 { "maxwidth", (void *)&db_max_width
, db_rw_internal_variable
, NULL
},
79 { "tabstops", (void *)&db_tab_stop_width
, db_rw_internal_variable
, NULL
},
80 { "lines", (void *)&db_max_line
, db_rw_internal_variable
, NULL
},
81 { "onpanic", (void *)&db_onpanic
, db_rw_internal_variable
, NULL
},
82 { "fromconsole", (void *)&db_fromconsole
, db_rw_internal_variable
, NULL
},
83 { "tee_msgbuf", (void *)&db_tee_msgbuf
, db_rw_internal_variable
, NULL
},
85 const struct db_variable
* const db_evars
= db_vars
+ sizeof(db_vars
)/sizeof(db_vars
[0]);
88 * ddb command line access to the DDB variables defined above.
91 db_rw_internal_variable(const struct db_variable
*vp
, db_expr_t
*valp
, int rw
)
95 *valp
= *(int *)vp
->valuep
;
97 *(int *)vp
->valuep
= *valp
;
102 * sysctl(3) access to the DDB variables defined above.
105 SYSCTL_SETUP(sysctl_ddb_setup
, "sysctl ddb subtree setup")
108 sysctl_createv(clog
, 0, NULL
, NULL
,
110 CTLTYPE_NODE
, "ddb", NULL
,
114 sysctl_createv(clog
, 0, NULL
, NULL
,
115 CTLFLAG_PERMANENT
|CTLFLAG_READWRITE
,
116 CTLTYPE_INT
, "radix",
117 SYSCTL_DESCR("Input and output radix"),
118 NULL
, 0, &db_radix
, 0,
119 CTL_DDB
, DDBCTL_RADIX
, CTL_EOL
);
120 sysctl_createv(clog
, 0, NULL
, NULL
,
121 CTLFLAG_PERMANENT
|CTLFLAG_READWRITE
,
122 CTLTYPE_INT
, "maxoff",
123 SYSCTL_DESCR("Maximum symbol offset"),
124 NULL
, 0, &db_maxoff
, 0,
125 CTL_DDB
, DDBCTL_MAXOFF
, CTL_EOL
);
126 sysctl_createv(clog
, 0, NULL
, NULL
,
127 CTLFLAG_PERMANENT
|CTLFLAG_READWRITE
,
128 CTLTYPE_INT
, "maxwidth",
129 SYSCTL_DESCR("Maximum output line width"),
130 NULL
, 0, &db_max_width
, 0,
131 CTL_DDB
, DDBCTL_MAXWIDTH
, CTL_EOL
);
132 sysctl_createv(clog
, 0, NULL
, NULL
,
133 CTLFLAG_PERMANENT
|CTLFLAG_READWRITE
,
134 CTLTYPE_INT
, "lines",
135 SYSCTL_DESCR("Number of display lines"),
136 NULL
, 0, &db_max_line
, 0,
137 CTL_DDB
, DDBCTL_LINES
, CTL_EOL
);
138 sysctl_createv(clog
, 0, NULL
, NULL
,
139 CTLFLAG_PERMANENT
|CTLFLAG_READWRITE
,
140 CTLTYPE_INT
, "tabstops",
141 SYSCTL_DESCR("Output tab width"),
142 NULL
, 0, &db_tab_stop_width
, 0,
143 CTL_DDB
, DDBCTL_TABSTOPS
, CTL_EOL
);
144 sysctl_createv(clog
, 0, NULL
, NULL
,
145 CTLFLAG_PERMANENT
|CTLFLAG_READWRITE
,
146 CTLTYPE_INT
, "onpanic",
147 SYSCTL_DESCR("Whether to enter ddb on a kernel panic"),
148 NULL
, 0, &db_onpanic
, 0,
149 CTL_DDB
, DDBCTL_ONPANIC
, CTL_EOL
);
150 sysctl_createv(clog
, 0, NULL
, NULL
,
151 CTLFLAG_PERMANENT
|CTLFLAG_READWRITE
,
152 CTLTYPE_INT
, "fromconsole",
153 SYSCTL_DESCR("Whether ddb can be entered from the "
155 NULL
, 0, &db_fromconsole
, 0,
156 CTL_DDB
, DDBCTL_FROMCONSOLE
, CTL_EOL
);
157 sysctl_createv(clog
, 0, NULL
, NULL
,
158 CTLFLAG_PERMANENT
|CTLFLAG_READWRITE
,
159 CTLTYPE_INT
, "tee_msgbuf",
160 SYSCTL_DESCR("Whether to tee ddb output to the msgbuf"),
161 NULL
, 0, &db_tee_msgbuf
, 0,
162 CTL_DDB
, CTL_CREATE
, CTL_EOL
);
164 sysctl_createv(clog
, 0, NULL
, NULL
,
165 CTLFLAG_PERMANENT
|CTLFLAG_READWRITE
,
166 CTLTYPE_STRING
, "commandonenter",
167 SYSCTL_DESCR("Command to be executed on each ddb enter"),
168 NULL
, 0, &db_cmd_on_enter
, DB_LINE_MAXLEN
,
169 CTL_DDB
, CTL_CREATE
, CTL_EOL
);
174 db_find_variable(const struct db_variable
**varp
)
177 const struct db_variable
*vp
;
181 for (vp
= db_vars
; vp
< db_evars
; vp
++) {
182 if (!strcmp(db_tok_string
, vp
->name
)) {
187 for (vp
= db_regs
; vp
< db_eregs
; vp
++) {
188 if (!strcmp(db_tok_string
, vp
->name
)) {
194 db_error("Unknown variable\n");
200 db_get_variable(db_expr_t
*valuep
)
202 const struct db_variable
*vp
;
204 if (!db_find_variable(&vp
))
207 db_read_variable(vp
, valuep
);
213 db_set_variable(db_expr_t value
)
215 const struct db_variable
*vp
;
217 if (!db_find_variable(&vp
))
220 db_write_variable(vp
, &value
);
227 db_read_variable(const struct db_variable
*vp
, db_expr_t
*valuep
)
229 int (*func
)(const struct db_variable
*, db_expr_t
*, int) = vp
->fcn
;
231 if (func
== FCN_NULL
)
232 *valuep
= *(vp
->valuep
);
234 (*func
)(vp
, valuep
, DB_VAR_GET
);
238 db_write_variable(const struct db_variable
*vp
, db_expr_t
*valuep
)
240 int (*func
)(const struct db_variable
*, db_expr_t
*, int) = vp
->fcn
;
242 if (func
== FCN_NULL
)
243 *(vp
->valuep
) = *valuep
;
245 (*func
)(vp
, valuep
, DB_VAR_SET
);
250 db_set_cmd(db_expr_t addr
, bool have_addr
,
251 db_expr_t count
, const char *modif
)
255 const struct db_variable
*vp
= NULL
; /* XXX: GCC */
260 db_error("Unknown variable\n");
263 if (!db_find_variable(&vp
)) {
264 db_error("Unknown variable\n");
272 if (!db_expression(&value
)) {
273 db_error("No value\n");
276 if (db_read_token() != tEOL
) {
281 db_read_variable(vp
, &old_value
);
282 db_printf("$%s\t\t%s = ", vp
->name
, db_num_to_str(old_value
));
283 db_printf("%s\n", db_num_to_str(value
));
284 db_write_variable(vp
, &value
);