This source file includes following definitions.
- db_stop_at_pc
- db_restart_at_pc
- db_single_step
- db_single_step_cmd
- db_trace_until_call_cmd
- db_trace_until_matching_cmd
- db_continue_cmd
- db_set_single_step
- db_clear_single_step
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36 #include <sys/param.h>
37 #include <sys/proc.h>
38
39 #include <uvm/uvm_extern.h>
40
41 #include <machine/db_machdep.h>
42
43 #include <ddb/db_run.h>
44 #include <ddb/db_break.h>
45 #include <ddb/db_access.h>
46
47 #ifdef SOFTWARE_SSTEP
48 db_breakpoint_t db_not_taken_bkpt = 0;
49 db_breakpoint_t db_taken_bkpt = 0;
50 #endif
51
52 int db_inst_count;
53 int db_load_count;
54 int db_store_count;
55
56 #ifndef KGDB
57
58 #include <ddb/db_lex.h>
59 #include <ddb/db_watch.h>
60 #include <ddb/db_output.h>
61 #include <ddb/db_sym.h>
62 #include <ddb/db_extern.h>
63
64 int db_run_mode;
65 #define STEP_NONE 0
66 #define STEP_ONCE 1
67 #define STEP_RETURN 2
68 #define STEP_CALLT 3
69 #define STEP_CONTINUE 4
70 #define STEP_INVISIBLE 5
71 #define STEP_COUNT 6
72
73 boolean_t db_sstep_print;
74 int db_loop_count;
75 int db_call_depth;
76
77 boolean_t
78 db_stop_at_pc(db_regs_t *regs, boolean_t *is_breakpoint)
79 {
80 db_addr_t pc, old_pc;
81 db_breakpoint_t bkpt;
82
83 db_clear_breakpoints();
84 db_clear_watchpoints();
85 old_pc = pc = PC_REGS(regs);
86
87 #ifdef FIXUP_PC_AFTER_BREAK
88 if (*is_breakpoint) {
89
90
91
92
93 FIXUP_PC_AFTER_BREAK(regs);
94 pc = PC_REGS(regs);
95 }
96 #endif
97
98
99
100
101 bkpt = db_find_breakpoint_here(pc);
102 if (bkpt) {
103 if (--bkpt->count == 0) {
104 db_clear_single_step(regs);
105 bkpt->count = bkpt->init_count;
106 *is_breakpoint = TRUE;
107 return (TRUE);
108 }
109 } else if (*is_breakpoint
110 #ifdef SOFTWARE_SSTEP
111 && !((db_taken_bkpt && db_taken_bkpt->address == pc) ||
112 (db_not_taken_bkpt && db_not_taken_bkpt->address == pc))
113 #endif
114 ) {
115 #ifdef PC_ADVANCE
116 PC_ADVANCE(regs);
117 #else
118 # ifdef SET_PC_REGS
119 SET_PC_REGS(regs, old_pc);
120 # else
121 PC_REGS(regs) = old_pc;
122 # endif
123 #endif
124 }
125 db_clear_single_step(regs);
126
127 *is_breakpoint = FALSE;
128
129 if (db_run_mode == STEP_INVISIBLE) {
130 db_run_mode = STEP_CONTINUE;
131 return (FALSE);
132 }
133 if (db_run_mode == STEP_COUNT) {
134 return (FALSE);
135 }
136 if (db_run_mode == STEP_ONCE) {
137 if (--db_loop_count > 0) {
138 if (db_sstep_print) {
139 db_printf("\t\t");
140 db_print_loc_and_inst(pc);
141 db_printf("\n");
142 }
143 return (FALSE);
144 }
145 }
146 if (db_run_mode == STEP_RETURN) {
147 db_expr_t ins = db_get_value(pc, sizeof(int), FALSE);
148
149
150
151 if (!inst_trap_return(ins) &&
152 (!inst_return(ins) || --db_call_depth != 0)) {
153 if (db_sstep_print) {
154 if (inst_call(ins) || inst_return(ins)) {
155 int i;
156
157 db_printf("[after %6d] ", db_inst_count);
158 for (i = db_call_depth; --i > 0; )
159 db_printf(" ");
160 db_print_loc_and_inst(pc);
161 db_printf("\n");
162 }
163 }
164 if (inst_call(ins))
165 db_call_depth++;
166 return (FALSE);
167 }
168 }
169 if (db_run_mode == STEP_CALLT) {
170 db_expr_t ins = db_get_value(pc, sizeof(int), FALSE);
171
172
173
174 if (!inst_call(ins) && !inst_return(ins) &&
175 !inst_trap_return(ins)) {
176 return (FALSE);
177 }
178 }
179 db_run_mode = STEP_NONE;
180 return (TRUE);
181 }
182
183 void
184 db_restart_at_pc(db_regs_t *regs, boolean_t watchpt)
185 {
186 db_addr_t pc = PC_REGS(regs);
187
188 if ((db_run_mode == STEP_COUNT) || (db_run_mode == STEP_RETURN) ||
189 (db_run_mode == STEP_CALLT)) {
190 db_expr_t ins;
191
192
193
194
195
196 ins = db_get_value(pc, sizeof(int), FALSE);
197 db_inst_count++;
198 db_load_count += inst_load(ins);
199 db_store_count += inst_store(ins);
200 #ifdef SOFTWARE_SSTEP
201
202 if (inst_branch(ins) || inst_call(ins)) {
203 ins = db_get_value(next_instr_address(pc, 1),
204 sizeof(int), FALSE);
205 db_inst_count++;
206 db_load_count += inst_load(ins);
207 db_store_count += inst_store(ins);
208 }
209 #endif
210 }
211
212 if (db_run_mode == STEP_CONTINUE) {
213 if (watchpt || db_find_breakpoint_here(pc)) {
214
215
216
217 db_run_mode = STEP_INVISIBLE;
218 db_set_single_step(regs);
219 } else {
220 db_set_breakpoints();
221 db_set_watchpoints();
222 }
223 } else {
224 db_set_single_step(regs);
225 }
226 }
227
228 void
229 db_single_step(db_regs_t *regs)
230 {
231 if (db_run_mode == STEP_CONTINUE) {
232 db_run_mode = STEP_INVISIBLE;
233 db_set_single_step(regs);
234 }
235 }
236
237 extern int db_cmd_loop_done;
238
239
240
241 void
242 db_single_step_cmd(db_expr_t addr, int have_addr, db_expr_t count, char *modif)
243 {
244 boolean_t print = FALSE;
245
246 if (count == -1)
247 count = 1;
248
249 if (modif[0] == 'p')
250 print = TRUE;
251
252 db_run_mode = STEP_ONCE;
253 db_loop_count = count;
254 db_sstep_print = print;
255 db_inst_count = 0;
256 db_load_count = 0;
257 db_store_count = 0;
258
259 db_cmd_loop_done = 1;
260 }
261
262
263
264 void
265 db_trace_until_call_cmd(db_expr_t addr, int have_addr, db_expr_t count,
266 char *modif)
267 {
268 boolean_t print = FALSE;
269
270 if (modif[0] == 'p')
271 print = TRUE;
272
273 db_run_mode = STEP_CALLT;
274 db_sstep_print = print;
275 db_inst_count = 0;
276 db_load_count = 0;
277 db_store_count = 0;
278
279 db_cmd_loop_done = 1;
280 }
281
282
283 void
284 db_trace_until_matching_cmd(db_expr_t addr, int have_addr, db_expr_t count,
285 char *modif)
286 {
287 boolean_t print = FALSE;
288
289 if (modif[0] == 'p')
290 print = TRUE;
291
292 db_run_mode = STEP_RETURN;
293 db_call_depth = 1;
294 db_sstep_print = print;
295 db_inst_count = 0;
296 db_load_count = 0;
297 db_store_count = 0;
298
299 db_cmd_loop_done = 1;
300 }
301
302
303
304 void
305 db_continue_cmd(db_expr_t addr, int have_addr, db_expr_t count, char *modif)
306 {
307 if (modif[0] == 'c')
308 db_run_mode = STEP_COUNT;
309 else
310 db_run_mode = STEP_CONTINUE;
311 db_inst_count = 0;
312 db_load_count = 0;
313 db_store_count = 0;
314
315 db_cmd_loop_done = 1;
316 }
317 #endif
318
319 #ifdef SOFTWARE_SSTEP
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351 void
352 db_set_single_step(db_regs_t *regs)
353 {
354 db_addr_t pc = PC_REGS(regs);
355 #ifndef SOFTWARE_SSTEP_EMUL
356 db_addr_t brpc;
357 u_int inst;
358
359
360
361
362
363 inst = db_get_value(pc, sizeof(int), FALSE);
364 if (inst_branch(inst) || inst_call(inst) || inst_return(inst)) {
365 brpc = branch_taken(inst, pc, getreg_val, regs);
366 if (brpc != pc) {
367 db_taken_bkpt = db_set_temp_breakpoint(brpc);
368 }
369 #if 0
370
371 pc = next_instr_address(pc, 1);
372 #endif
373 }
374 #endif
375 pc = next_instr_address(pc, 0);
376 db_not_taken_bkpt = db_set_temp_breakpoint(pc);
377 }
378
379 void
380 db_clear_single_step(db_regs_t *regs)
381 {
382 if (db_taken_bkpt != 0) {
383 db_delete_temp_breakpoint(db_taken_bkpt);
384 db_taken_bkpt = 0;
385 }
386 if (db_not_taken_bkpt != 0) {
387 db_delete_temp_breakpoint(db_not_taken_bkpt);
388 db_not_taken_bkpt = 0;
389 }
390 }
391
392 #endif