Branch data Line data Source code
1 : : // Support routines to help deal with Bro debugging commands and
2 : : // implementation of most commands.
3 : :
4 : : #include "config.h"
5 : :
6 : : #include <sys/types.h>
7 : :
8 : : #include <regex.h>
9 : : #include <string.h>
10 : : #include <assert.h>
11 : :
12 : : #include "Debug.h"
13 : : #include "DebugCmds.h"
14 : : #include "DebugCmdInfoConstants.cc"
15 : : #include "DbgBreakpoint.h"
16 : : #include "Func.h"
17 : : #include "Stmt.h"
18 : : #include "Scope.h"
19 : : #include "PolicyFile.h"
20 : : #include "util.h"
21 : :
22 : : //
23 : : // Helper routines
24 : : //
25 : 0 : bool string_is_regex(string s)
26 : : {
27 : 0 : return strpbrk(s.c_str(), "?*\\+");
28 : : }
29 : :
30 : : void lookup_global_symbols_regex(const string& orig_regex, vector<ID*>& matches,
31 : 0 : bool func_only = false)
32 : : {
33 [ # # ]: 0 : if ( streq(orig_regex.c_str(), "") )
34 : 0 : return;
35 : :
36 : 0 : string regex = "^";
37 : 0 : int len = orig_regex.length();
38 [ # # ]: 0 : for ( int i = 0; i < len; ++i )
39 : : {
40 [ # # ]: 0 : if ( orig_regex[i] == '*' )
41 : 0 : regex.push_back('.');
42 : 0 : regex.push_back(orig_regex[i]);
43 : : }
44 : 0 : regex.push_back('$');
45 : :
46 : : regex_t re;
47 [ # # ]: 0 : if ( regcomp(&re, regex.c_str(), REG_EXTENDED|REG_NOSUB) )
48 : : {
49 : 0 : debug_msg("Invalid regular expression: %s\n", regex.c_str());
50 : 0 : return;
51 : : }
52 : :
53 : 0 : Scope* global = global_scope();
54 : 0 : PDict(ID)* syms = global->Vars();
55 : :
56 : : ID* nextid;
57 : 0 : IterCookie* cookie = syms->InitForIteration();
58 [ # # ]: 0 : while ( (nextid = syms->NextEntry( cookie )) )
59 [ # # ][ # # ]: 0 : if ( ! func_only || nextid->Type()->Tag() == TYPE_FUNC )
[ # # ]
60 [ # # ]: 0 : if ( ! regexec (&re, nextid->Name(), 0, 0, 0) )
61 [ # # ]: 0 : matches.push_back(nextid);
62 : : }
63 : :
64 : : void choose_global_symbols_regex(const string& regex, vector<ID*>& choices,
65 : 0 : bool func_only = false)
66 : : {
67 : 0 : lookup_global_symbols_regex(regex, choices, func_only);
68 : :
69 [ # # ]: 0 : if ( choices.size() <= 1 )
70 : 0 : return;
71 : :
72 [ # # ]: 0 : while ( 1 )
73 : : {
74 : 0 : debug_msg("There were multiple matches, please choose:\n");
75 : :
76 [ # # ]: 0 : for ( unsigned int i = 0; i < choices.size(); ++i )
77 : 0 : debug_msg("[%d] %s\n", i+1, choices[i]->Name());
78 : :
79 : 0 : debug_msg("[a] All of the above\n");
80 : 0 : debug_msg("[n] None of the above\n");
81 : 0 : debug_msg("Enter your choice: ");
82 : :
83 : : char charinput[256];
84 [ # # ]: 0 : if ( ! fgets(charinput, sizeof(charinput) - 1, stdin) )
85 : : {
86 : 0 : choices.clear();
87 : 0 : return;
88 : : }
89 [ # # ]: 0 : if ( charinput[strlen(charinput) - 1] == '\n' )
90 : 0 : charinput[strlen(charinput) - 1] = 0;
91 : :
92 : 0 : string input = charinput;
93 [ # # ]: 0 : if ( input == "a" )
94 : 0 : return;
95 : :
96 [ # # ]: 0 : if ( input == "n" )
97 : : {
98 : 0 : choices.clear();
99 : : return;
100 : : }
101 : 0 : int option = atoi(input.c_str());
102 [ # # # # ]: 0 : if ( option > 0 && option <= (int) choices.size() )
[ # # ]
103 : : {
104 : 0 : ID* choice = choices[option - 1];
105 : 0 : choices.clear();
106 : 0 : choices.push_back(choice);
107 : : return;
108 : : }
109 : : }
110 : : }
111 : :
112 : :
113 : : //
114 : : // DebugCmdInfo implementation
115 : : //
116 : :
117 : 6 : PQueue(DebugCmdInfo) g_DebugCmdInfos;
118 : :
119 : 0 : DebugCmdInfo::DebugCmdInfo(const DebugCmdInfo& info)
120 : 0 : : cmd(info.cmd), helpstring(0)
121 : : {
122 : 0 : num_names = info.num_names;
123 : 0 : names = info.names;
124 : 0 : resume_execution = info.resume_execution;
125 : 0 : repeatable = info.repeatable;
126 : 0 : }
127 : :
128 : : DebugCmdInfo::DebugCmdInfo(DebugCmd arg_cmd, const char* const* arg_names,
129 : : int arg_num_names, bool arg_resume_execution,
130 : : const char* const arg_helpstring,
131 : 0 : bool arg_repeatable)
132 : 0 : : cmd(arg_cmd), helpstring(arg_helpstring)
133 : : {
134 : 0 : num_names = arg_num_names;
135 : 0 : resume_execution = arg_resume_execution;
136 : 0 : repeatable = arg_repeatable;
137 : :
138 [ # # ][ # # ]: 0 : for ( int i = 0; i < num_names; ++i )
139 : 0 : names.push_back(arg_names[i]);
140 : 0 : }
141 : :
142 : :
143 : 0 : const DebugCmdInfo* get_debug_cmd_info(DebugCmd cmd)
144 : : {
145 [ # # ]: 0 : if ( (int) cmd < g_DebugCmdInfos.length() )
146 : 0 : return g_DebugCmdInfos[(int) cmd];
147 : : else
148 : 0 : return 0;
149 : : }
150 : :
151 : 0 : int find_all_matching_cmds(const string& prefix, const char* array_of_matches[])
152 : : {
153 : : // Trivial implementation for now (### use hashing later).
154 : :
155 : 0 : unsigned int arglen = prefix.length();
156 : 0 : int matches = 0;
157 : :
158 [ # # ]: 0 : for ( int i = 0; i < num_debug_cmds(); ++i )
159 : : {
160 : 0 : array_of_matches[g_DebugCmdInfos[i]->Cmd()] = 0;
161 : :
162 [ # # ]: 0 : for ( int j = 0; j < g_DebugCmdInfos[i]->NumNames(); ++j )
163 : : {
164 : 0 : const char* curr_name = g_DebugCmdInfos[i]->Names()[j];
165 [ # # ]: 0 : if ( strncmp(curr_name, prefix.c_str(), arglen) )
166 : 0 : continue;
167 : :
168 : : // If exact match, then only return that one.
169 [ # # ]: 0 : if ( ! prefix.compare(curr_name) )
170 : : {
171 [ # # ]: 0 : for ( int k = 0; k < num_debug_cmds(); ++k )
172 : 0 : array_of_matches[k] = 0;
173 : :
174 : 0 : array_of_matches[g_DebugCmdInfos[i]->Cmd()] = curr_name;
175 : 0 : return 1;
176 : : }
177 : :
178 : 0 : array_of_matches[g_DebugCmdInfos[i]->Cmd()] = curr_name;
179 : 0 : ++matches;
180 : : }
181 : : }
182 : :
183 : 0 : return matches;
184 : : }
185 : :
186 : : //
187 : : // ------------------------------------------------------------
188 : : // Implementation of some debugger commands
189 : :
190 : :
191 : : // Start, end bounds of which frame numbers to print
192 : 0 : static int dbg_backtrace_internal(int start, int end)
193 : : {
194 [ # # ][ # # ]: 0 : if ( start < 0 || end < 0 ||
[ # # ][ # # ]
[ # # ]
195 : : (unsigned) start >= g_frame_stack.size() ||
196 : : (unsigned) end >= g_frame_stack.size() )
197 : 0 : internal_error("Invalid stack frame index in DbgBacktraceInternal\n");
198 : :
199 [ # # ]: 0 : if ( start < end )
200 : : {
201 : 0 : int temp = start;
202 : 0 : start = end;
203 : 0 : end = temp;
204 : : }
205 : :
206 [ # # ]: 0 : for ( int i = start; i >= end; --i )
207 : : {
208 : 0 : const Frame* f = g_frame_stack[i];
209 [ # # ]: 0 : const Stmt* stmt = f ? f->GetNextStmt() : 0;
210 : :
211 : 0 : string context = get_context_description(stmt, f);
212 : : debug_msg("#%d %s\n",
213 : 0 : int(g_frame_stack.size() - 1 - i), context.c_str());
214 : : };
215 : :
216 : 0 : return 1;
217 : : }
218 : :
219 : :
220 : : // Returns 0 for illegal arguments, or 1 on success.
221 : 0 : int dbg_cmd_backtrace(DebugCmd cmd, const vector<string>& args)
222 : : {
223 [ # # ]: 0 : assert(cmd == dcBacktrace);
224 [ # # ]: 0 : assert(g_frame_stack.size() > 0);
225 : :
226 : : unsigned int start_iter;
227 : : int end_iter;
228 : :
229 [ # # ]: 0 : if ( args.size() > 0 )
230 : : {
231 : : int how_many; // determines how we traverse the frames
232 : 0 : int valid_arg = sscanf(args[0].c_str(), "%i", &how_many);
233 [ # # ]: 0 : if ( ! valid_arg )
234 : : {
235 : 0 : debug_msg("Argument to backtrace '%s' invalid: must be an integer\n", args[0].c_str());
236 : 0 : return 0;
237 : : }
238 : :
239 [ # # ]: 0 : if ( how_many > 0 )
240 : : { // innermost N frames
241 : 0 : start_iter = g_frame_stack.size() - 1;
242 : 0 : end_iter = start_iter - how_many + 1;
243 [ # # ]: 0 : if ( end_iter < 0 )
244 : 0 : end_iter = 0;
245 : : }
246 : : else
247 : : { // outermost N frames
248 : 0 : start_iter = how_many - 1;
249 [ # # ]: 0 : if ( start_iter + 1 > g_frame_stack.size() )
250 : 0 : start_iter = g_frame_stack.size() - 1;
251 : 0 : end_iter = 0;
252 : : }
253 : : }
254 : : else
255 : : {
256 : 0 : start_iter = g_frame_stack.size() - 1;
257 : 0 : end_iter = 0;
258 : : }
259 : :
260 : 0 : return dbg_backtrace_internal(start_iter, end_iter);
261 : : }
262 : :
263 : :
264 : : // Returns 0 if invalid args, else 1.
265 : 0 : int dbg_cmd_frame(DebugCmd cmd, const vector<string>& args)
266 : : {
267 [ # # ][ # # ]: 0 : assert(cmd == dcFrame || cmd == dcUp || cmd == dcDown);
[ # # ][ # # ]
268 : :
269 [ # # ]: 0 : if ( cmd == dcFrame )
270 : : {
271 : 0 : int idx = 0;
272 : :
273 [ # # ]: 0 : if ( args.size() > 0 )
274 : : {
275 [ # # ]: 0 : if ( args.size() > 1 )
276 : : {
277 : 0 : debug_msg("Too many arguments: expecting frame number 'n'\n");
278 : 0 : return 0;
279 : : }
280 : :
281 [ # # ]: 0 : if ( ! sscanf(args[0].c_str(), "%d", &idx) )
282 : : {
283 : 0 : debug_msg("Argument to frame must be a positive integer\n");
284 : 0 : return 0;
285 : : }
286 : :
287 [ # # ][ # # ]: 0 : if ( idx < 0 ||
[ # # ]
288 : : (unsigned int) idx >= g_frame_stack.size() )
289 : : {
290 : 0 : debug_msg("No frame %d", idx);
291 : 0 : return 0;
292 : : }
293 : : }
294 : :
295 : 0 : g_debugger_state.curr_frame_idx = idx;
296 : : }
297 : :
298 [ # # ]: 0 : else if ( cmd == dcDown )
299 : : {
300 [ # # ]: 0 : if ( g_debugger_state.curr_frame_idx == 0 )
301 : : {
302 : 0 : debug_msg("Innermost frame already selected\n");
303 : 0 : return 0;
304 : : }
305 : :
306 : 0 : g_debugger_state.curr_frame_idx--;
307 : : }
308 : :
309 [ # # ]: 0 : else if ( cmd == dcUp )
310 : : {
311 [ # # ]: 0 : if ( (unsigned int)(g_debugger_state.curr_frame_idx + 1) ==
312 : : g_frame_stack.size() )
313 : : {
314 : 0 : debug_msg("Outermost frame already selected\n");
315 : 0 : return 0;
316 : : }
317 : :
318 : 0 : ++g_debugger_state.curr_frame_idx;
319 : : }
320 : :
321 : : int user_frame_number =
322 : 0 : g_frame_stack.size() - 1 - g_debugger_state.curr_frame_idx;
323 : :
324 : : // Set the current location to the new frame being looked at
325 : : // for 'list', 'break', etc.
326 : 0 : const Stmt* stmt = g_frame_stack[user_frame_number]->GetNextStmt();
327 [ # # ]: 0 : if ( ! stmt )
328 : 0 : internal_error("Assertion failed: %s", "stmt != 0");
329 : :
330 : 0 : const Location loc = *stmt->GetLocationInfo();
331 : 0 : g_debugger_state.last_loc = loc;
332 : 0 : g_debugger_state.already_did_list = false;
333 : :
334 : 0 : return dbg_backtrace_internal(user_frame_number, user_frame_number);
335 : : }
336 : :
337 : 0 : int dbg_cmd_help(DebugCmd cmd, const vector<string>& args)
338 : : {
339 [ # # ]: 0 : assert(cmd == dcHelp);
340 : :
341 : 0 : debug_msg("Help summary: \n\n");
342 [ # # ]: 0 : for ( int i = 1; i < num_debug_cmds(); ++i )
343 : : {
344 : 0 : const DebugCmdInfo* info = get_debug_cmd_info (DebugCmd(i));
345 : 0 : debug_msg("%s -- %s\n", info->Names()[0], info->Helpstring());
346 : : }
347 : :
348 : 0 : return -1;
349 : : }
350 : :
351 : :
352 : 0 : int dbg_cmd_break(DebugCmd cmd, const vector<string>& args)
353 : : {
354 [ # # ]: 0 : assert(cmd == dcBreak);
355 : :
356 : 0 : vector<DbgBreakpoint*> bps;
357 : :
358 : 0 : int cond_index = -1; // at which argument pos. does bp condition start?
359 : :
360 [ # # # # ]: 0 : if ( args.size() == 0 || args[0] == "if" )
[ # # ]
361 : : { // break on next stmt
362 : : int user_frame_number =
363 : : g_frame_stack.size() - 1 -
364 : 0 : g_debugger_state.curr_frame_idx;
365 : :
366 : 0 : Stmt* stmt = g_frame_stack[user_frame_number]->GetNextStmt();
367 [ # # ]: 0 : if ( ! stmt )
368 : 0 : internal_error("Assertion failed: %s", "stmt != 0");
369 : :
370 : 0 : DbgBreakpoint* bp = new DbgBreakpoint();
371 : 0 : bp->SetID(g_debugger_state.NextBPID());
372 : :
373 [ # # ]: 0 : if ( ! bp->SetLocation(stmt) )
374 : : {
375 : 0 : debug_msg("Breakpoint not set.\n");
376 [ # # ]: 0 : delete bp;
377 : 0 : return 0;
378 : : }
379 : :
380 [ # # ][ # # ]: 0 : if ( args.size() > 0 && args[0] == "if" )
[ # # ]
381 : 0 : cond_index = 1;
382 : :
383 : 0 : bps.push_back(bp);
384 : : }
385 : :
386 : : else
387 : : {
388 : 0 : vector<string> locstrings;
389 [ # # ]: 0 : if ( string_is_regex(args[0]) )
390 : : {
391 : 0 : vector<ID*> choices;
392 : 0 : choose_global_symbols_regex(args[0], choices, true);
393 [ # # ]: 0 : for ( unsigned int i = 0; i < choices.size(); ++i )
394 : 0 : locstrings.push_back(choices[i]->Name());
395 : : }
396 : : else
397 : 0 : locstrings.push_back(args[0].c_str());
398 : :
399 [ # # ]: 0 : for ( unsigned int strindex = 0; strindex < locstrings.size();
400 : : ++strindex )
401 : : {
402 : : debug_msg("Setting breakpoint on %s:\n",
403 : 0 : locstrings[strindex].c_str());
404 : : vector<ParseLocationRec> plrs =
405 : 0 : parse_location_string(locstrings[strindex]);
406 [ # # ]: 0 : for ( unsigned int i = 0; i < plrs.size(); ++i )
407 : : {
408 : 0 : DbgBreakpoint* bp = new DbgBreakpoint();
409 : 0 : bp->SetID(g_debugger_state.NextBPID());
410 [ # # ]: 0 : if ( ! bp->SetLocation(plrs[i], locstrings[strindex]) )
411 : : {
412 : 0 : debug_msg("Breakpoint not set.\n");
413 [ # # ]: 0 : delete bp;
414 : : }
415 : : else
416 : 0 : bps.push_back(bp);
417 : : }
418 : : }
419 : :
420 [ # # ][ # # ]: 0 : if ( args.size() > 1 && args[1] == "if" )
[ # # ]
421 : 0 : cond_index = 2;
422 : : }
423 : :
424 : : // Is there a condition specified?
425 [ # # ][ # # ]: 0 : if ( cond_index >= 0 && bps.size() )
[ # # ]
426 : : {
427 : : // ### Implement conditions
428 : 0 : string cond;
429 [ # # ]: 0 : for ( int i = cond_index; i < int(args.size()); ++i )
430 : : {
431 : 0 : cond += args[i];
432 : 0 : cond += " ";
433 : : }
434 : 0 : bps[0]->SetCondition(cond);
435 : : }
436 : :
437 [ # # ]: 0 : for ( unsigned int i = 0; i < bps.size(); ++i )
438 : : {
439 : 0 : bps[i]->SetTemporary(false);
440 : 0 : g_debugger_state.breakpoints[bps[i]->GetID()] = bps[i];
441 : : }
442 : :
443 : 0 : return 0;
444 : : }
445 : :
446 : : // Set a condition on an existing breakpoint.
447 : 0 : int dbg_cmd_break_condition(DebugCmd cmd, const vector<string>& args)
448 : : {
449 [ # # ]: 0 : assert(cmd == dcBreakCondition);
450 : :
451 [ # # ]: 0 : if ( args.size() < 2 )
452 : : {
453 : 0 : debug_msg("Arguments must specify breakpoint number and condition.\n");
454 : 0 : return 0;
455 : : }
456 : :
457 : 0 : int idx = atoi(args[0].c_str());
458 : 0 : DbgBreakpoint* bp = g_debugger_state.breakpoints[idx];
459 : :
460 : 0 : string expr;
461 [ # # ]: 0 : for ( int i = 1; i < int(args.size()); ++i )
462 : : {
463 : 0 : expr += args[i];
464 : 0 : expr += " ";
465 : : }
466 : 0 : bp->SetCondition(expr);
467 : :
468 : 0 : return 1;
469 : : }
470 : :
471 : : // Change the state of a breakpoint.
472 : 0 : int dbg_cmd_break_set_state(DebugCmd cmd, const vector<string>& args)
473 : : {
474 [ # # ][ # # ]: 0 : assert(cmd == dcDeleteBreak || cmd == dcClearBreak ||
[ # # ][ # # ]
[ # # ][ # # ]
475 : : cmd == dcDisableBreak || cmd == dcEnableBreak ||
476 : : cmd == dcIgnoreBreak);
477 : :
478 [ # # ][ # # ]: 0 : if ( cmd == dcClearBreak || cmd == dcIgnoreBreak )
479 : : {
480 : 0 : debug_msg("'clear' and 'ignore' commands not currently supported\n");
481 : 0 : return 0;
482 : : }
483 : :
484 [ # # ]: 0 : if ( g_debugger_state.breakpoints.size() == 0 )
485 : : {
486 : 0 : debug_msg ("No breakpoints currently set.\n");
487 : 0 : return -1;
488 : : }
489 : :
490 : 0 : vector<int> bps_to_change;
491 : :
492 [ # # ]: 0 : if ( args.size() == 0 )
493 : : {
494 : 0 : BPIDMapType::iterator iter;
495 [ # # ]: 0 : for ( iter = g_debugger_state.breakpoints.begin();
496 : : iter != g_debugger_state.breakpoints.end(); ++iter )
497 : 0 : bps_to_change.push_back(iter->second->GetID());
498 : : }
499 : : else
500 : : {
501 [ # # ]: 0 : for ( unsigned int i = 0; i < args.size(); ++i )
502 [ # # ]: 0 : if ( int idx = atoi(args[i].c_str()) )
503 : 0 : bps_to_change.push_back(idx);
504 : : }
505 : :
506 [ # # ]: 0 : for ( unsigned int i = 0; i < bps_to_change.size(); ++i )
507 : : {
508 : 0 : int bp_change = bps_to_change[i];
509 : :
510 : : BPIDMapType::iterator result =
511 : 0 : g_debugger_state.breakpoints.find(bp_change);
512 : :
513 [ # # ]: 0 : if ( result != g_debugger_state.breakpoints.end() )
514 : : {
515 [ # # # # ]: 0 : switch ( cmd ) {
516 : : case dcDisableBreak:
517 : 0 : g_debugger_state.breakpoints[bp_change]->SetEnable(false);
518 : 0 : debug_msg("Breakpoint %d disabled\n", bp_change);
519 : 0 : break;
520 : :
521 : : case dcEnableBreak:
522 : 0 : g_debugger_state.breakpoints[bp_change]->SetEnable(true);
523 : 0 : debug_msg("Breakpoint %d enabled\n", bp_change);
524 : 0 : break;
525 : :
526 : : case dcDeleteBreak:
527 [ # # ]: 0 : delete g_debugger_state.breakpoints[bp_change];
528 : 0 : g_debugger_state.breakpoints.erase(bp_change);
529 : 0 : debug_msg("Breakpoint %d deleted\n", bp_change);
530 : 0 : break;
531 : :
532 : : default:
533 : 0 : internal_error("Invalid command in DbgCmdBreakSetState\n");
534 : : }
535 : : }
536 : :
537 : : else
538 : 0 : debug_msg("Breakpoint %d does not exist\n", bp_change);
539 : : }
540 : :
541 : 0 : return -1;
542 : : }
543 : :
544 : : // Evaluate an expression and print the result.
545 : 0 : int dbg_cmd_print(DebugCmd cmd, const vector<string>& args)
546 : : {
547 [ # # ]: 0 : assert(cmd == dcPrint);
548 : :
549 : : // ### TODO: add support for formats
550 : :
551 : : // Just concatenate all the 'args' into one expression.
552 : 0 : string expr;
553 [ # # ]: 0 : for ( int i = 0; i < int(args.size()); ++i )
554 : : {
555 : 0 : expr += args[i];
556 : 0 : expr += " ";
557 : : }
558 : :
559 : 0 : Val* val = dbg_eval_expr(expr.c_str());
560 : :
561 [ # # ]: 0 : if ( val )
562 : : {
563 : 0 : ODesc d;
564 : 0 : val->Describe(&d);
565 : 0 : debug_msg("%s\n", d.Description());
566 : : }
567 : : else
568 : : {
569 : : // ### Print something?
570 : : // debug_msg("<expression has no value>\n");
571 : : }
572 : :
573 : 0 : return 1;
574 : : }
575 : :
576 : :
577 : : // Get the debugger's state.
578 : : // Allowed arguments are: break (breakpoints), watch, display, source.
579 : 0 : int dbg_cmd_info(DebugCmd cmd, const vector<string>& args)
580 : : {
581 [ # # ]: 0 : assert(cmd == dcInfo);
582 : :
583 [ # # ]: 0 : if ( ! args.size() )
584 : : {
585 : 0 : debug_msg("Syntax: info info-command\n");
586 : 0 : debug_msg("List of info-commands:\n");
587 : 0 : debug_msg("info breakpoints -- List of breakpoints and watches\n");
588 : 0 : return 1;
589 : : }
590 : :
591 [ # # ][ # # ]: 0 : if ( ! strncmp(args[0].c_str(), "breakpoints", args[0].size()) ||
[ # # ]
592 : : ! strncmp(args[0].c_str(), "watch", args[0].size()) )
593 : : {
594 : 0 : debug_msg("Num Type Disp Enb What\n");
595 : :
596 : 0 : BPIDMapType::iterator iter;
597 [ # # ]: 0 : for ( iter = g_debugger_state.breakpoints.begin();
598 : : iter != g_debugger_state.breakpoints.end();
599 : : ++iter )
600 : : {
601 : 0 : DbgBreakpoint* bp = (*iter).second;
602 : : debug_msg("%-4d%-15s%-5s%-4s%s\n",
603 : : bp->GetID(),
604 : : "breakpoint",
605 : : bp->IsTemporary() ? "del" : "keep",
606 : : bp->IsEnabled() ? "y" : "n",
607 [ # # ][ # # ]: 0 : bp->Description());
608 : : }
609 : : }
610 : :
611 : : else
612 : 0 : debug_msg("I don't have info for that yet.\n");
613 : :
614 : 0 : return 1;
615 : : }
616 : :
617 : 0 : int dbg_cmd_list(DebugCmd cmd, const vector<string>& args)
618 : : {
619 [ # # ]: 0 : assert(cmd == dcList);
620 : :
621 : : // The constant 4 is to match the GDB behavior.
622 : 0 : const unsigned int CENTER_IDX = 4; // 5th line is the 'interesting' one
623 : :
624 : 0 : int pre_offset = 0;
625 [ # # ]: 0 : if ( args.size() > 1 )
626 : : {
627 : 0 : debug_msg("Syntax: list [file:]line OR list function_name\n");
628 : 0 : return 0;
629 : : }
630 : :
631 [ # # ]: 0 : if ( args.size() == 0 )
632 : : {
633 : : // Special case: if we just hit a breakpoint, then show
634 : : // that line without advancing first.
635 [ # # ]: 0 : if ( g_debugger_state.already_did_list )
636 : 0 : pre_offset = 10;
637 : : }
638 : :
639 [ # # ]: 0 : else if ( args[0] == "-" )
640 : : // Why -10 ? Because that's what GDB does.
641 : 0 : pre_offset = -10;
642 : :
643 [ # # ][ # # ]: 0 : else if ( args[0][0] == '-' || args[0][0] == '+' )
[ # # ]
644 : : {
645 : : int offset;
646 [ # # ]: 0 : if ( ! sscanf(args[0].c_str(), "%d", &offset) )
647 : : {
648 : 0 : debug_msg("Offset must be a number\n");
649 : 0 : return false;
650 : : }
651 : :
652 : 0 : pre_offset = offset;
653 : : }
654 : :
655 : : else
656 : : {
657 : 0 : vector<ParseLocationRec> plrs = parse_location_string(args[0]);
658 : 0 : ParseLocationRec plr = plrs[0];
659 [ # # ]: 0 : if ( plr.type == plrUnknown )
660 : : {
661 : 0 : debug_msg("Invalid location specifier\n");
662 : 0 : return false;
663 : : }
664 : :
665 : 0 : g_debugger_state.last_loc.filename = plr.filename;
666 : 0 : g_debugger_state.last_loc.first_line = plr.line;
667 [ # # ]: 0 : pre_offset = 0;
668 : : }
669 : :
670 [ # # ]: 0 : if ( (int) pre_offset +
671 : : (int) g_debugger_state.last_loc.first_line -
672 : : (int) CENTER_IDX < 0 )
673 : 0 : pre_offset = CENTER_IDX - g_debugger_state.last_loc.first_line;
674 : :
675 : 0 : g_debugger_state.last_loc.first_line += pre_offset;
676 : :
677 : : int last_line_in_file =
678 : 0 : how_many_lines_in(g_debugger_state.last_loc.filename);
679 : :
680 [ # # ]: 0 : if ( g_debugger_state.last_loc.first_line > last_line_in_file )
681 : 0 : g_debugger_state.last_loc.first_line = last_line_in_file;
682 : :
683 : : PrintLines(g_debugger_state.last_loc.filename,
684 : : g_debugger_state.last_loc.first_line - CENTER_IDX,
685 : 0 : 10, true);
686 : :
687 : 0 : g_debugger_state.already_did_list = true;
688 : :
689 : 0 : return 1;
690 : : }
691 : :
692 : 0 : int dbg_cmd_trace(DebugCmd cmd, const vector<string>& args)
693 : : {
694 [ # # ]: 0 : assert(cmd == dcTrace);
695 : :
696 [ # # ]: 0 : if ( args.size() == 0 )
697 : : {
698 : : debug_msg("Execution tracing is %s.\n",
699 [ # # ]: 0 : g_trace_state.DoTrace() ? "on" : "off" );
700 : 0 : return 1;
701 : : }
702 : :
703 [ # # ]: 0 : if ( args[0] == "on" )
704 : : {
705 : 0 : g_trace_state.TraceOn();
706 : 0 : return 1;
707 : : }
708 : :
709 [ # # ]: 0 : if ( args[0] == "off" )
710 : : {
711 : 0 : g_trace_state.TraceOff();
712 : 0 : return 1;
713 : : }
714 : :
715 : 0 : debug_msg("Invalid argument");
716 : 0 : return 0;
717 [ + - ][ + - ]: 6 : }
|