db_variables.c revision 1.19 1 /* $NetBSD: db_variables.c,v 1.19 2000/07/05 16:29:25 jhawk Exp $ */
2
3 /*
4 * Mach Operating System
5 * Copyright (c) 1991,1990 Carnegie Mellon University
6 * All Rights Reserved.
7 *
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.
13 *
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.
17 *
18 * Carnegie Mellon requests users of this software to return to
19 *
20 * Software Distribution Coordinator or Software.Distribution (at) CS.CMU.EDU
21 * School of Computer Science
22 * Carnegie Mellon University
23 * Pittsburgh PA 15213-3890
24 *
25 * any improvements or extensions that they make and grant Carnegie the
26 * rights to redistribute these changes.
27 */
28
29 #include "opt_ddb.h" /* for sysctl.h */
30 #include "opt_ddbparam.h"
31
32 #include <sys/param.h>
33 #include <sys/proc.h>
34 #include <uvm/uvm_extern.h>
35 #include <sys/sysctl.h>
36
37 #include <machine/db_machdep.h>
38
39 #include <ddb/ddbvar.h>
40
41 #include <ddb/db_lex.h>
42 #include <ddb/db_variables.h>
43 #include <ddb/db_command.h>
44 #include <ddb/db_sym.h>
45 #include <ddb/db_extern.h>
46 #include <ddb/db_output.h>
47
48
49 /*
50 * If this is non-zero, the DDB will be entered when the system
51 * panics. Initialize it so that it's patchable.
52 */
53 #ifndef DDB_ONPANIC
54 #define DDB_ONPANIC 1
55 #endif
56 int db_onpanic = DDB_ONPANIC;
57
58 /*
59 * Can DDB can be entered from the console?
60 */
61 #ifndef DDB_FROMCONSOLE
62 #define DDB_FROMCONSOLE 1
63 #endif
64 int db_fromconsole = DDB_FROMCONSOLE;
65
66
67 static int db_rw_internal_variable __P((struct db_variable *, db_expr_t *,
68 int));
69
70 /* XXX must all be ints for sysctl. */
71 struct db_variable db_vars[] = {
72 { "radix", (long *)&db_radix, db_rw_internal_variable },
73 { "maxoff", (long *)&db_maxoff, db_rw_internal_variable },
74 { "maxwidth", (long *)&db_max_width, db_rw_internal_variable },
75 { "tabstops", (long *)&db_tab_stop_width, db_rw_internal_variable },
76 { "lines", (long *)&db_max_line, db_rw_internal_variable },
77 { "onpanic", (long *)&db_onpanic, db_rw_internal_variable },
78 { "fromconsole", (long *)&db_onpanic, db_rw_internal_variable },
79 };
80 struct db_variable *db_evars = db_vars + sizeof(db_vars)/sizeof(db_vars[0]);
81
82 /*
83 * ddb command line access to the DDB variables defined above.
84 */
85 static int
86 db_rw_internal_variable(vp, valp, rw)
87 struct db_variable *vp;
88 db_expr_t *valp;
89 int rw;
90 {
91
92 if (rw == DB_VAR_GET) {
93 *valp = *(int *)vp->valuep;
94 } else {
95 *(int *)vp->valuep = *valp;
96 }
97 return (0);
98 }
99
100 /*
101 * sysctl(3) access to the DDB variables defined above.
102 */
103 int
104 ddb_sysctl(name, namelen, oldp, oldlenp, newp, newlen, p)
105 int *name;
106 u_int namelen;
107 void *oldp;
108 size_t *oldlenp;
109 void *newp;
110 size_t newlen;
111 struct proc *p;
112 {
113
114 /* All sysctl names at this level are terminal. */
115 if (namelen != 1)
116 return (ENOTDIR);
117
118 switch (name[0]) {
119 case DDBCTL_RADIX:
120 return (sysctl_int(oldp, oldlenp, newp, newlen, &db_radix));
121
122 case DDBCTL_MAXOFF:
123 return (sysctl_int(oldp, oldlenp, newp, newlen, &db_maxoff));
124
125 case DDBCTL_MAXWIDTH:
126 return (sysctl_int(oldp, oldlenp, newp, newlen,
127 &db_max_width));
128
129 case DDBCTL_TABSTOPS:
130 return (sysctl_int(oldp, oldlenp, newp, newlen,
131 &db_tab_stop_width));
132
133 case DDBCTL_LINES:
134 return (sysctl_int(oldp, oldlenp, newp, newlen, &db_max_line));
135
136 case DDBCTL_ONPANIC:
137 return (sysctl_int(oldp, oldlenp, newp, newlen, &db_onpanic));
138 case DDBCTL_FROMCONSOLE:
139 return (sysctl_int(oldp, oldlenp, newp, newlen,
140 &db_fromconsole));
141 }
142
143 return (EOPNOTSUPP);
144 }
145
146 int
147 db_find_variable(varp)
148 struct db_variable **varp;
149 {
150 int t;
151 struct db_variable *vp;
152
153 t = db_read_token();
154 if (t == tIDENT) {
155 for (vp = db_vars; vp < db_evars; vp++) {
156 if (!strcmp(db_tok_string, vp->name)) {
157 *varp = vp;
158 return (1);
159 }
160 }
161 for (vp = db_regs; vp < db_eregs; vp++) {
162 if (!strcmp(db_tok_string, vp->name)) {
163 *varp = vp;
164 return (1);
165 }
166 }
167 }
168 db_error("Unknown variable\n");
169 /*NOTREACHED*/
170 return 0;
171 }
172
173 int
174 db_get_variable(valuep)
175 db_expr_t *valuep;
176 {
177 struct db_variable *vp;
178
179 if (!db_find_variable(&vp))
180 return (0);
181
182 db_read_variable(vp, valuep);
183
184 return (1);
185 }
186
187 int
188 db_set_variable(value)
189 db_expr_t value;
190 {
191 struct db_variable *vp;
192
193 if (!db_find_variable(&vp))
194 return (0);
195
196 db_write_variable(vp, &value);
197
198 return (1);
199 }
200
201
202 void
203 db_read_variable(vp, valuep)
204 struct db_variable *vp;
205 db_expr_t *valuep;
206 {
207 int (*func) __P((struct db_variable *, db_expr_t *, int)) = vp->fcn;
208
209 if (func == FCN_NULL)
210 *valuep = *(vp->valuep);
211 else
212 (*func)(vp, valuep, DB_VAR_GET);
213 }
214
215 void
216 db_write_variable(vp, valuep)
217 struct db_variable *vp;
218 db_expr_t *valuep;
219 {
220 int (*func) __P((struct db_variable *, db_expr_t *, int)) = vp->fcn;
221
222 if (func == FCN_NULL)
223 *(vp->valuep) = *valuep;
224 else
225 (*func)(vp, valuep, DB_VAR_SET);
226 }
227
228 /*ARGSUSED*/
229 void
230 db_set_cmd(addr, have_addr, count, modif)
231 db_expr_t addr;
232 int have_addr;
233 db_expr_t count;
234 char * modif;
235 {
236 db_expr_t value;
237 db_expr_t old_value;
238 struct db_variable *vp;
239 int t;
240
241 t = db_read_token();
242 if (t != tDOLLAR) {
243 db_error("Unknown variable\n");
244 /*NOTREACHED*/
245 }
246 if (!db_find_variable(&vp)) {
247 db_error("Unknown variable\n");
248 /*NOTREACHED*/
249 }
250
251 t = db_read_token();
252 if (t != tEQ)
253 db_unread_token(t);
254
255 if (!db_expression(&value)) {
256 db_error("No value\n");
257 /*NOTREACHED*/
258 }
259 if (db_read_token() != tEOL) {
260 db_error("?\n");
261 /*NOTREACHED*/
262 }
263
264 db_read_variable(vp, &old_value);
265 db_printf("$%s\t\t%s = ", vp->name, db_num_to_str(old_value));
266 db_printf("%s\n", db_num_to_str(value));
267 db_write_variable(vp, &value);
268 }
269