Wed Mar 4 16:50:18 1998 Jason Molenda (crash@bugshack.cygnus.com)
[deliverable/binutils-gdb.git] / gdb / tracepoint.c
1 /* Tracing functionality for remote targets in custom GDB protocol
2 Copyright 1997 Free Software Foundation, Inc.
3
4 This file is part of GDB.
5
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
10
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
19
20 #include "defs.h"
21 #include "symtab.h"
22 #include "frame.h"
23 #include "tracepoint.h"
24 #include "gdbtypes.h"
25 #include "expression.h"
26 #include "gdbcmd.h"
27 #include "value.h"
28 #include "target.h"
29 #include "language.h"
30 #include "gdb_string.h"
31
32 /* readline include files */
33 #include "readline.h"
34 #include "history.h"
35
36 /* readline defines this. */
37 #undef savestring
38
39 #ifdef HAVE_UNISTD_H
40 #include <unistd.h>
41 #endif
42
43 extern int info_verbose;
44 extern void (*readline_begin_hook) PARAMS ((char *, ...));
45 extern char * (*readline_hook) PARAMS ((char *));
46 extern void (*readline_end_hook) PARAMS ((void));
47 extern void x_command PARAMS ((char *, int));
48
49 /* If this definition isn't overridden by the header files, assume
50 that isatty and fileno exist on this system. */
51 #ifndef ISATTY
52 #define ISATTY(FP) (isatty (fileno (FP)))
53 #endif
54
55 /*
56 Tracepoint.c:
57
58 This module defines the following debugger commands:
59 trace : set a tracepoint on a function, line, or address.
60 info trace : list all debugger-defined tracepoints.
61 delete trace : delete one or more tracepoints.
62 enable trace : enable one or more tracepoints.
63 disable trace : disable one or more tracepoints.
64 actions : specify actions to be taken at a tracepoint.
65 passcount : specify a pass count for a tracepoint.
66 tstart : start a trace experiment.
67 tstop : stop a trace experiment.
68 tstatus : query the status of a trace experiment.
69 tfind : find a trace frame in the trace buffer.
70 tdump : print everything collected at the current tracepoint.
71 save-tracepoints : write tracepoint setup into a file.
72
73 This module defines the following user-visible debugger variables:
74 $trace_frame : sequence number of trace frame currently being debugged.
75 $trace_line : source line of trace frame currently being debugged.
76 $trace_file : source file of trace frame currently being debugged.
77 $tracepoint : tracepoint number of trace frame currently being debugged.
78 */
79
80
81 /* ======= Important global variables: ======= */
82
83 /* Chain of all tracepoints defined. */
84 struct tracepoint *tracepoint_chain;
85
86 /* Number of last tracepoint made. */
87 static int tracepoint_count;
88
89 /* Number of last traceframe collected. */
90 static int traceframe_number;
91
92 /* Tracepoint for last traceframe collected. */
93 static int tracepoint_number;
94
95 /* Symbol for function for last traceframe collected */
96 static struct symbol *traceframe_fun;
97
98 /* Symtab and line for last traceframe collected */
99 static struct symtab_and_line traceframe_sal;
100
101 /* Tracing command lists */
102 static struct cmd_list_element *tfindlist;
103
104 /* ======= Important command functions: ======= */
105 static void trace_command PARAMS ((char *, int));
106 static void tracepoints_info PARAMS ((char *, int));
107 static void delete_trace_command PARAMS ((char *, int));
108 static void enable_trace_command PARAMS ((char *, int));
109 static void disable_trace_command PARAMS ((char *, int));
110 static void trace_pass_command PARAMS ((char *, int));
111 static void trace_actions_command PARAMS ((char *, int));
112 static void trace_start_command PARAMS ((char *, int));
113 static void trace_stop_command PARAMS ((char *, int));
114 static void trace_status_command PARAMS ((char *, int));
115 static void trace_find_command PARAMS ((char *, int));
116 static void trace_find_pc_command PARAMS ((char *, int));
117 static void trace_find_tracepoint_command PARAMS ((char *, int));
118 static void trace_find_line_command PARAMS ((char *, int));
119 static void trace_find_range_command PARAMS ((char *, int));
120 static void trace_find_outside_command PARAMS ((char *, int));
121 static void tracepoint_save_command PARAMS ((char *, int));
122 static void trace_dump_command PARAMS ((char *, int));
123
124
125 /* Utility: returns true if "target remote" */
126 static int
127 target_is_remote ()
128 {
129 if (current_target.to_shortname &&
130 strcmp (current_target.to_shortname, "remote") == 0)
131 return 1;
132 else
133 return 0;
134 }
135
136 /* Utility: generate error from an incoming stub packet. */
137 static void
138 trace_error (buf)
139 char *buf;
140 {
141 if (*buf++ != 'E')
142 return; /* not an error msg */
143 switch (*buf)
144 {
145 case '1': /* malformed packet error */
146 if (*++buf == '0') /* general case: */
147 error ("tracepoint.c: error in outgoing packet.");
148 else
149 error ("tracepoint.c: error in outgoing packet at field #%d.",
150 strtol (buf, NULL, 16));
151 case '2':
152 error ("trace API error 0x%s.", ++buf);
153 default:
154 error ("Target returns error code '%s'.", buf);
155 }
156 }
157
158 /* Utility: wait for reply from stub, while accepting "O" packets */
159 static char *
160 remote_get_noisy_reply (buf)
161 char *buf;
162 {
163 do /* loop on reply from remote stub */
164 {
165 getpkt (buf, 0);
166 if (buf[0] == 0)
167 error ("Target does not support this command.");
168 else if (buf[0] == 'E')
169 trace_error (buf);
170 else if (buf[0] == 'O' &&
171 buf[1] != 'K')
172 remote_console_output (buf + 1); /* 'O' message from stub */
173 else
174 return buf; /* here's the actual reply */
175 } while (1);
176 }
177
178 /* Set tracepoint count to NUM. */
179 static void
180 set_tracepoint_count (num)
181 int num;
182 {
183 tracepoint_count = num;
184 set_internalvar (lookup_internalvar ("tpnum"),
185 value_from_longest (builtin_type_int, (LONGEST) num));
186 }
187
188 /* Set traceframe number to NUM. */
189 static void
190 set_traceframe_num (num)
191 int num;
192 {
193 traceframe_number = num;
194 set_internalvar (lookup_internalvar ("trace_frame"),
195 value_from_longest (builtin_type_int, (LONGEST) num));
196 }
197
198 /* Set tracepoint number to NUM. */
199 static void
200 set_tracepoint_num (num)
201 int num;
202 {
203 tracepoint_number = num;
204 set_internalvar (lookup_internalvar ("tracepoint"),
205 value_from_longest (builtin_type_int, (LONGEST) num));
206 }
207
208 /* Set externally visible debug variables for querying/printing
209 the traceframe context (line, function, file) */
210
211 static void
212 set_traceframe_context (trace_pc)
213 CORE_ADDR trace_pc;
214 {
215 static struct type *func_string, *file_string;
216 static struct type *func_range, *file_range;
217 static value_ptr func_val, file_val;
218 static struct type *charstar;
219 int len;
220
221 if (charstar == (struct type *) NULL)
222 charstar = lookup_pointer_type (builtin_type_char);
223
224 if (trace_pc == -1) /* cease debugging any trace buffers */
225 {
226 traceframe_fun = 0;
227 traceframe_sal.pc = traceframe_sal.line = 0;
228 traceframe_sal.symtab = NULL;
229 set_internalvar (lookup_internalvar ("trace_func"),
230 value_from_longest (charstar, (LONGEST) 0));
231 set_internalvar (lookup_internalvar ("trace_file"),
232 value_from_longest (charstar, (LONGEST) 0));
233 set_internalvar (lookup_internalvar ("trace_line"),
234 value_from_longest (builtin_type_int, (LONGEST) -1));
235 return;
236 }
237
238 /* save as globals for internal use */
239 traceframe_sal = find_pc_line (trace_pc, 0);
240 traceframe_fun = find_pc_function (trace_pc);
241
242 /* save linenumber as "$trace_line", a debugger variable visible to users */
243 set_internalvar (lookup_internalvar ("trace_line"),
244 value_from_longest (builtin_type_int,
245 (LONGEST) traceframe_sal.line));
246
247 /* save func name as "$trace_func", a debugger variable visible to users */
248 if (traceframe_fun == NULL ||
249 SYMBOL_NAME (traceframe_fun) == NULL)
250 set_internalvar (lookup_internalvar ("trace_func"),
251 value_from_longest (charstar, (LONGEST) 0));
252 else
253 {
254 len = strlen (SYMBOL_NAME (traceframe_fun));
255 func_range = create_range_type (func_range,
256 builtin_type_int, 0, len - 1);
257 func_string = create_array_type (func_string,
258 builtin_type_char, func_range);
259 func_val = allocate_value (func_string);
260 VALUE_TYPE (func_val) = func_string;
261 memcpy (VALUE_CONTENTS_RAW (func_val),
262 SYMBOL_NAME (traceframe_fun),
263 len);
264 func_val->modifiable = 0;
265 set_internalvar (lookup_internalvar ("trace_func"), func_val);
266 }
267
268 /* save file name as "$trace_file", a debugger variable visible to users */
269 if (traceframe_sal.symtab == NULL ||
270 traceframe_sal.symtab->filename == NULL)
271 set_internalvar (lookup_internalvar ("trace_file"),
272 value_from_longest (charstar, (LONGEST) 0));
273 else
274 {
275 len = strlen (traceframe_sal.symtab->filename);
276 file_range = create_range_type (file_range,
277 builtin_type_int, 0, len - 1);
278 file_string = create_array_type (file_string,
279 builtin_type_char, file_range);
280 file_val = allocate_value (file_string);
281 VALUE_TYPE (file_val) = file_string;
282 memcpy (VALUE_CONTENTS_RAW (file_val),
283 traceframe_sal.symtab->filename,
284 len);
285 file_val->modifiable = 0;
286 set_internalvar (lookup_internalvar ("trace_file"), file_val);
287 }
288 }
289
290 /* Low level routine to set a tracepoint.
291 Returns the tracepoint object so caller can set other things.
292 Does not set the tracepoint number!
293 Does not print anything.
294
295 ==> This routine should not be called if there is a chance of later
296 error(); otherwise it leaves a bogus tracepoint on the chain. Validate
297 your arguments BEFORE calling this routine! */
298
299 static struct tracepoint *
300 set_raw_tracepoint (sal)
301 struct symtab_and_line sal;
302 {
303 register struct tracepoint *t, *tc;
304 struct cleanup *old_chain;
305
306 t = (struct tracepoint *) xmalloc (sizeof (struct tracepoint));
307 old_chain = make_cleanup (free, t);
308 memset (t, 0, sizeof (*t));
309 t->address = sal.pc;
310 if (sal.symtab == NULL)
311 t->source_file = NULL;
312 else
313 {
314 char *p;
315
316 t->source_file = (char *) xmalloc (strlen (sal.symtab->filename) +
317 strlen (sal.symtab->dirname) + 2);
318
319 strcpy (t->source_file, sal.symtab->dirname);
320 p = t->source_file;
321 while (*p)
322 p++;
323 if (*(--p) != '/') /* Will this work on Windows? */
324 strcat (t->source_file, "/");
325 strcat (t->source_file, sal.symtab->filename);
326 }
327
328 t->language = current_language->la_language;
329 t->input_radix = input_radix;
330 t->line_number = sal.line;
331 t->enabled = enabled;
332 t->next = 0;
333 t->step_count = 0;
334 t->pass_count = 0;
335 t->addr_string = NULL;
336
337 /* Add this tracepoint to the end of the chain
338 so that a list of tracepoints will come out in order
339 of increasing numbers. */
340
341 tc = tracepoint_chain;
342 if (tc == 0)
343 tracepoint_chain = t;
344 else
345 {
346 while (tc->next)
347 tc = tc->next;
348 tc->next = t;
349 }
350 discard_cleanups (old_chain);
351 return t;
352 }
353
354 /* Set a tracepoint according to ARG (function, linenum or *address) */
355 static void
356 trace_command (arg, from_tty)
357 char *arg;
358 int from_tty;
359 {
360 char **canonical = (char **)NULL;
361 struct symtabs_and_lines sals;
362 struct symtab_and_line sal;
363 struct tracepoint *t;
364 char *addr_start = 0, *addr_end = 0;
365 int i;
366
367 if (!arg || !*arg)
368 error ("trace command requires an argument");
369
370 if (from_tty && info_verbose)
371 printf_filtered ("TRACE %s\n", arg);
372
373 if (arg[0] == '/')
374 {
375 return;
376 }
377
378 addr_start = arg;
379 sals = decode_line_1 (&arg, 1, (struct symtab *)NULL, 0, &canonical);
380 addr_end = arg;
381 if (! sals.nelts)
382 return; /* ??? Presumably decode_line_1 has already warned? */
383
384 /* Resolve all line numbers to PC's */
385 for (i = 0; i < sals.nelts; i++)
386 resolve_sal_pc (&sals.sals[i]);
387
388 /* Now set all the tracepoints. */
389 for (i = 0; i < sals.nelts; i++)
390 {
391 sal = sals.sals[i];
392
393 t = set_raw_tracepoint (sal);
394 set_tracepoint_count (tracepoint_count + 1);
395 t->number = tracepoint_count;
396
397 /* If a canonical line spec is needed use that instead of the
398 command string. */
399 if (canonical != (char **)NULL && canonical[i] != NULL)
400 t->addr_string = canonical[i];
401 else if (addr_start)
402 t->addr_string = savestring (addr_start, addr_end - addr_start);
403
404 /* Let the UI know of any additions */
405 if (create_tracepoint_hook)
406 create_tracepoint_hook (t);
407 }
408
409 if (sals.nelts > 1)
410 {
411 printf_filtered ("Multiple tracepoints were set.\n");
412 printf_filtered ("Use 'delete trace' to delete unwanted tracepoints.\n");
413 }
414 }
415
416 /* Print information on tracepoint number TPNUM_EXP, or all if omitted. */
417
418 static void
419 tracepoints_info (tpnum_exp, from_tty)
420 char *tpnum_exp;
421 int from_tty;
422 {
423 struct tracepoint *t;
424 struct action_line *action;
425 int found_a_tracepoint = 0;
426 char wrap_indent[80];
427 struct symbol *sym;
428 int tpnum = -1;
429 #if 0
430 char *i1 = "\t", *i2 = "\t ";
431 char *indent, *actionline;;
432 #endif
433
434 if (tpnum_exp)
435 tpnum = parse_and_eval_address (tpnum_exp);
436
437 ALL_TRACEPOINTS (t)
438 if (tpnum == -1 || tpnum == t->number)
439 {
440 extern int addressprint; /* print machine addresses? */
441
442 if (!found_a_tracepoint++)
443 {
444 printf_filtered ("Num Enb ");
445 if (addressprint)
446 printf_filtered ("Address ");
447 printf_filtered ("PassC StepC What\n");
448 }
449 strcpy (wrap_indent, " ");
450 if (addressprint)
451 strcat (wrap_indent, " ");
452
453 printf_filtered ("%-3d %-3s ", t->number,
454 t->enabled == enabled ? "y" : "n");
455 if (addressprint)
456 printf_filtered ("%s ",
457 local_hex_string_custom ((unsigned long) t->address,
458 "08l"));
459 printf_filtered ("%-5d %-5d ", t->pass_count, t->step_count);
460
461 if (t->source_file)
462 {
463 sym = find_pc_function (t->address);
464 if (sym)
465 {
466 fputs_filtered ("in ", gdb_stdout);
467 fputs_filtered (SYMBOL_SOURCE_NAME (sym), gdb_stdout);
468 wrap_here (wrap_indent);
469 fputs_filtered (" at ", gdb_stdout);
470 }
471 fputs_filtered (t->source_file, gdb_stdout);
472 printf_filtered (":%d", t->line_number);
473 }
474 else
475 print_address_symbolic (t->address, gdb_stdout, demangle, " ");
476
477 printf_filtered ("\n");
478 if (t->actions)
479 {
480 printf_filtered (" Actions for tracepoint %d: \n", t->number);
481 /* indent = i1; */
482 for (action = t->actions; action; action = action->next)
483 {
484 #if 0
485 actionline = action->action;
486 while (isspace(*actionline))
487 actionline++;
488
489 printf_filtered ("%s%s\n", indent, actionline);
490 if (0 == strncasecmp (actionline, "while-stepping", 14))
491 indent = i2;
492 else if (0 == strncasecmp (actionline, "end", 3))
493 indent = i1;
494 #else
495 printf_filtered ("\t%s\n", action->action);
496 #endif
497 }
498 }
499 }
500 if (!found_a_tracepoint)
501 {
502 if (tpnum == -1)
503 printf_filtered ("No tracepoints.\n");
504 else
505 printf_filtered ("No tracepoint number %d.\n", tpnum);
506 }
507 }
508
509 /* Optimization: the code to parse an enable, disable, or delete TP command
510 is virtually identical except for whether it performs an enable, disable,
511 or delete. Therefore I've combined them into one function with an opcode.
512 */
513 enum tracepoint_opcode
514 {
515 enable,
516 disable,
517 delete
518 };
519
520 /* This function implements enable, disable and delete. */
521 static void
522 tracepoint_operation (t, from_tty, opcode)
523 struct tracepoint *t;
524 int from_tty;
525 enum tracepoint_opcode opcode;
526 {
527 struct tracepoint *t2;
528
529 switch (opcode) {
530 case enable:
531 t->enabled = enabled;
532 if (modify_tracepoint_hook)
533 modify_tracepoint_hook (t);
534 break;
535 case disable:
536 t->enabled = disabled;
537 if (modify_tracepoint_hook)
538 modify_tracepoint_hook (t);
539 break;
540 case delete:
541 if (tracepoint_chain == t)
542 tracepoint_chain = t->next;
543
544 ALL_TRACEPOINTS (t2)
545 if (t2->next == t)
546 {
547 t2->next = t->next;
548 break;
549 }
550
551 /* Let the UI know of any deletions */
552 if (delete_tracepoint_hook)
553 delete_tracepoint_hook (t);
554
555 if (t->addr_string)
556 free (t->addr_string);
557 if (t->source_file)
558 free (t->source_file);
559 if (t->actions)
560 free_actions (t);
561
562 free (t);
563 break;
564 }
565 }
566
567 /* Utility: parse a tracepoint number and look it up in the list. */
568 struct tracepoint *
569 get_tracepoint_by_number (arg)
570 char **arg;
571 {
572 struct tracepoint *t;
573 char *end, *copy;
574 value_ptr val;
575 int tpnum;
576
577 if (arg == 0)
578 error ("Bad tracepoint argument");
579
580 if (*arg == 0 || **arg == 0) /* empty arg means refer to last tp */
581 tpnum = tracepoint_count;
582 else if (**arg == '$') /* handle convenience variable */
583 {
584 /* Make a copy of the name, so we can null-terminate it
585 to pass to lookup_internalvar(). */
586 end = *arg + 1;
587 while (isalnum(*end) || *end == '_')
588 end++;
589 copy = (char *) alloca (end - *arg);
590 strncpy (copy, *arg + 1, (end - *arg - 1));
591 copy[end - *arg - 1] = '\0';
592 *arg = end;
593
594 val = value_of_internalvar (lookup_internalvar (copy));
595 if (TYPE_CODE( VALUE_TYPE (val)) != TYPE_CODE_INT)
596 error ("Convenience variable must have integral type.");
597 tpnum = (int) value_as_long (val);
598 }
599 else /* handle tracepoint number */
600 {
601 tpnum = strtol (*arg, arg, 10);
602 }
603 ALL_TRACEPOINTS (t)
604 if (t->number == tpnum)
605 {
606 return t;
607 }
608 warning ("No tracepoint number %d.\n", tpnum);
609 return NULL;
610 }
611
612 /* Utility: parse a list of tracepoint numbers, and call a func for each. */
613 static void
614 map_args_over_tracepoints (args, from_tty, opcode)
615 char *args;
616 int from_tty;
617 enum tracepoint_opcode opcode;
618 {
619 struct tracepoint *t, *tmp;
620 int tpnum;
621 char *cp;
622
623 if (args == 0 || *args == 0) /* do them all */
624 ALL_TRACEPOINTS_SAFE (t, tmp)
625 tracepoint_operation (t, from_tty, opcode);
626 else
627 while (*args)
628 {
629 if (t = get_tracepoint_by_number (&args))
630 tracepoint_operation (t, from_tty, opcode);
631 while (*args == ' ' || *args == '\t')
632 args++;
633 }
634 }
635
636 /* The 'enable trace' command enables tracepoints. Not supported by all targets. */
637 static void
638 enable_trace_command (args, from_tty)
639 char *args;
640 int from_tty;
641 {
642 dont_repeat ();
643 map_args_over_tracepoints (args, from_tty, enable);
644 }
645
646 /* The 'disable trace' command enables tracepoints. Not supported by all targets. */
647 static void
648 disable_trace_command (args, from_tty)
649 char *args;
650 int from_tty;
651 {
652 dont_repeat ();
653 map_args_over_tracepoints (args, from_tty, disable);
654 }
655
656 /* Remove a tracepoint (or all if no argument) */
657 static void
658 delete_trace_command (args, from_tty)
659 char *args;
660 int from_tty;
661 {
662 dont_repeat ();
663 if (!args || !*args)
664 if (!query ("Delete all tracepoints? "))
665 return;
666
667 map_args_over_tracepoints (args, from_tty, delete);
668 }
669
670 /* Set passcount for tracepoint.
671
672 First command argument is passcount, second is tracepoint number.
673 If tracepoint number omitted, apply to most recently defined.
674 Also accepts special argument "all". */
675
676 static void
677 trace_pass_command (args, from_tty)
678 char *args;
679 int from_tty;
680 {
681 struct tracepoint *t1 = (struct tracepoint *) -1, *t2;
682 unsigned long count;
683
684 if (args == 0 || *args == 0)
685 error ("PASS command requires an argument (count + optional TP num)");
686
687 count = strtoul (args, &args, 10); /* count comes first, then TP num */
688
689 while (*args && isspace (*args))
690 args++;
691
692 if (*args && strncasecmp (args, "all", 3) == 0)
693 args += 3; /* skip special argument "all" */
694 else
695 t1 = get_tracepoint_by_number (&args);
696
697 if (t1 == NULL)
698 return; /* error, bad tracepoint number */
699
700 ALL_TRACEPOINTS (t2)
701 if (t1 == (struct tracepoint *) -1 || t1 == t2)
702 {
703 t2->pass_count = count;
704 if (from_tty)
705 printf_filtered ("Setting tracepoint %d's passcount to %d\n",
706 t2->number, count);
707 }
708 }
709
710 /* ACTIONS functions: */
711
712 /* Prototypes for action-parsing utility commands */
713 static void read_actions PARAMS((struct tracepoint *));
714 static char *parse_and_eval_memrange PARAMS ((char *,
715 CORE_ADDR,
716 long *,
717 bfd_signed_vma *,
718 long *));
719
720 /* The three functions:
721 collect_pseudocommand,
722 while_stepping_pseudocommand, and
723 end_actions_pseudocommand
724 are placeholders for "commands" that are actually ONLY to be used
725 within a tracepoint action list. If the actual function is ever called,
726 it means that somebody issued the "command" at the top level,
727 which is always an error. */
728
729 static void
730 end_actions_pseudocommand (args, from_tty)
731 char *args;
732 int from_tty;
733 {
734 error ("This command cannot be used at the top level.");
735 }
736
737 static void
738 while_stepping_pseudocommand (args, from_tty)
739 char *args;
740 int from_tty;
741 {
742 error ("This command can only be used in a tracepoint actions list.");
743 }
744
745 static void
746 collect_pseudocommand (args, from_tty)
747 char *args;
748 int from_tty;
749 {
750 error ("This command can only be used in a tracepoint actions list.");
751 }
752
753 /* Enter a list of actions for a tracepoint. */
754 static void
755 trace_actions_command (args, from_tty)
756 char *args;
757 int from_tty;
758 {
759 struct tracepoint *t;
760 char *actions;
761 char tmpbuf[128];
762 char *end_msg = "End with a line saying just \"end\".";
763
764 if (t = get_tracepoint_by_number (&args))
765 {
766 sprintf (tmpbuf, "Enter actions for tracepoint %d, one per line.",
767 t->number);
768
769 if (from_tty)
770 {
771 if (readline_begin_hook)
772 (*readline_begin_hook) ("%s %s\n", tmpbuf, end_msg);
773 else if (input_from_terminal_p ())
774 printf_filtered ("%s\n%s\n", tmpbuf, end_msg);
775 }
776
777 free_actions (t);
778 read_actions (t);
779
780 if (readline_end_hook)
781 (*readline_end_hook) ();
782
783 /* tracepoints_changed () */
784 }
785 /* else error, just return; */
786 }
787
788 enum actionline_type
789 {
790 BADLINE = -1,
791 GENERIC = 0,
792 END = 1,
793 STEPPING = 2,
794 };
795
796 static enum actionline_type validate_actionline PARAMS((char **,
797 struct tracepoint *));
798
799 /* worker function */
800 static void
801 read_actions (t)
802 struct tracepoint *t;
803 {
804 char *line;
805 char *prompt1 = "> ", *prompt2 = " > ";
806 char *prompt = prompt1;
807 enum actionline_type linetype;
808 extern FILE *instream;
809 struct action_line *next = NULL, *temp;
810 struct cleanup *old_chain;
811
812 /* Control-C quits instantly if typed while in this loop
813 since it should not wait until the user types a newline. */
814 immediate_quit++;
815 #ifdef STOP_SIGNAL
816 if (job_control)
817 signal (STOP_SIGNAL, stop_sig);
818 #endif
819 old_chain = make_cleanup (free_actions, (void *) t);
820 while (1)
821 {
822 /* Make sure that all output has been output. Some machines may let
823 you get away with leaving out some of the gdb_flush, but not all. */
824 wrap_here ("");
825 gdb_flush (gdb_stdout);
826 gdb_flush (gdb_stderr);
827
828 if (readline_hook && instream == NULL)
829 line = (*readline_hook) (prompt);
830 else if (instream == stdin && ISATTY (instream))
831 {
832 line = readline (prompt);
833 if (line && *line) /* add it to command history */
834 add_history (line);
835 }
836 else
837 line = gdb_readline (0);
838
839 linetype = validate_actionline (&line, t);
840 if (linetype == BADLINE)
841 continue; /* already warned -- collect another line */
842
843 temp = xmalloc (sizeof (struct action_line));
844 temp->next = NULL;
845 temp->action = line;
846
847 if (next == NULL) /* first action for this tracepoint? */
848 t->actions = next = temp;
849 else
850 {
851 next->next = temp;
852 next = temp;
853 }
854
855 if (linetype == STEPPING) /* begin "while-stepping" */
856 if (prompt == prompt2)
857 {
858 warning ("Already processing 'while-stepping'");
859 continue;
860 }
861 else
862 prompt = prompt2; /* change prompt for stepping actions */
863 else if (linetype == END)
864 if (prompt == prompt2)
865 prompt = prompt1; /* end of single-stepping actions */
866 else
867 break; /* end of actions */
868 }
869 #ifdef STOP_SIGNAL
870 if (job_control)
871 signal (STOP_SIGNAL, SIG_DFL);
872 #endif
873 immediate_quit = 0;
874 discard_cleanups (old_chain);
875 }
876
877 /* worker function */
878 static enum actionline_type
879 validate_actionline (line, t)
880 char **line;
881 struct tracepoint *t;
882 {
883 struct cmd_list_element *c;
884 struct expression *exp;
885 value_ptr temp, temp2;
886 char *p;
887
888 for (p = *line; isspace (*p); )
889 p++;
890
891 /* symbol lookup etc. */
892 if (*p == '\0') /* empty line: just prompt for another line. */
893 return BADLINE;
894
895 if (*p == '#') /* comment line */
896 return GENERIC;
897
898 c = lookup_cmd (&p, cmdlist, "", -1, 1);
899 if (c == 0)
900 {
901 warning ("'%s' is not an action that I know, or is ambiguous.", p);
902 return BADLINE;
903 }
904
905 if (c->function.cfunc == collect_pseudocommand)
906 {
907 do { /* repeat over a comma-separated list */
908 while (isspace (*p))
909 p++;
910
911 if (*p == '$') /* look for special pseudo-symbols */
912 {
913 long typecode, size;
914 bfd_signed_vma offset;
915
916 if ((0 == strncasecmp ("reg", p + 1, 3)) ||
917 (0 == strncasecmp ("arg", p + 1, 3)) ||
918 (0 == strncasecmp ("loc", p + 1, 3)))
919 p = strchr (p, ',');
920
921 else if (p[1] == '(') /* literal memrange */
922 {
923 char *temp, *newline;
924
925 newline = malloc (strlen (*line) + 32);
926 strcpy (newline, *line);
927 newline[p - *line] = '\0';
928 /* newline is now a copy of line, up to "p" (the memrange) */
929 temp = parse_and_eval_memrange (p, t->address,
930 &typecode, &offset, &size) + 1;
931 /* now compose the memrange as a literal value */
932 if (typecode == -1)
933 sprintf (newline + strlen (newline),
934 "$(0x%x, %d)",
935 offset, size);
936 else
937 sprintf (newline + strlen (newline),
938 "$($%s, 0x%x, %d)",
939 reg_names[typecode], offset, size);
940 /* now add the remainder of the old line to the new one */
941 p = newline + strlen (newline);
942 if (temp && *temp)
943 strcat (newline, temp);
944 free (*line);
945 *line = newline;
946 }
947 }
948 else
949 {
950 exp = parse_exp_1 (&p, block_for_pc (t->address), 1);
951
952 if (exp->elts[0].opcode != OP_VAR_VALUE &&
953 exp->elts[0].opcode != UNOP_MEMVAL &&
954 /*exp->elts[0].opcode != OP_LONG && */
955 /*exp->elts[0].opcode != UNOP_CAST && */
956 exp->elts[0].opcode != OP_REGISTER)
957 {
958 warning ("collect requires a variable or register name.\n");
959 return BADLINE;
960 }
961 if (exp->elts[0].opcode == OP_VAR_VALUE)
962 if (SYMBOL_CLASS (exp->elts[2].symbol) == LOC_CONST)
963 {
964 warning ("%s is constant (value %d): will not be collected.",
965 SYMBOL_NAME (exp->elts[2].symbol),
966 SYMBOL_VALUE (exp->elts[2].symbol));
967 return BADLINE;
968 }
969 else if (SYMBOL_CLASS (exp->elts[2].symbol) == LOC_OPTIMIZED_OUT)
970 {
971 warning ("%s is optimized away and cannot be collected.",
972 SYMBOL_NAME (exp->elts[2].symbol));
973 return BADLINE;
974 }
975 }
976 } while (p && *p++ == ',');
977 return GENERIC;
978 }
979 else if (c->function.cfunc == while_stepping_pseudocommand)
980 {
981 char *steparg; /* in case warning is necessary */
982
983 while (isspace (*p))
984 p++;
985 steparg = p;
986
987 if (*p)
988 {
989 t->step_count = strtol (p, &p, 0);
990 if (t->step_count == 0)
991 {
992 warning ("'%s' evaluates to zero -- command ignored.");
993 return BADLINE;
994 }
995 }
996 else
997 t->step_count = -1;
998 return STEPPING;
999 }
1000 else if (c->function.cfunc == end_actions_pseudocommand)
1001 return END;
1002 else
1003 {
1004 warning ("'%s' is not a supported tracepoint action.", *line);
1005 return BADLINE;
1006 }
1007 }
1008
1009 /* worker function */
1010 void
1011 free_actions (t)
1012 struct tracepoint *t;
1013 {
1014 struct action_line *line, *next;
1015
1016 for (line = t->actions; line; line = next)
1017 {
1018 next = line->next;
1019 if (line->action)
1020 free (line->action);
1021 free (line);
1022 }
1023 t->actions = NULL;
1024 }
1025
1026 struct memrange {
1027 int type; /* 0 for absolute memory range, else basereg number */
1028 bfd_signed_vma start;
1029 bfd_signed_vma end;
1030 };
1031
1032 struct collection_list {
1033 unsigned char regs_mask[8]; /* room for up to 256 regs */
1034 long listsize;
1035 long next_memrange;
1036 struct memrange *list;
1037 } tracepoint_list, stepping_list;
1038
1039 /* MEMRANGE functions: */
1040
1041 /* parse a memrange spec from command input */
1042 static char *
1043 parse_and_eval_memrange (arg, addr, typecode, offset, size)
1044 char *arg;
1045 CORE_ADDR addr;
1046 long *typecode, *size;
1047 bfd_signed_vma *offset;
1048 {
1049 char *start = arg;
1050 struct expression *exp;
1051 value_ptr val;
1052
1053 if (*arg++ != '$' || *arg++ != '(')
1054 error ("Internal: bad argument to parse_and_eval_memrange: %s", start);
1055
1056 if (*arg == '$') /* register for relative memrange? */
1057 {
1058 exp = parse_exp_1 (&arg, block_for_pc (addr), 1);
1059 if (exp->elts[0].opcode != OP_REGISTER)
1060 error ("Bad register operand for memrange: %s", start);
1061 if (*arg++ != ',')
1062 error ("missing comma for memrange: %s", start);
1063 *typecode = exp->elts[1].longconst;
1064 }
1065 else
1066 *typecode = -1; /* absolute memrange; */
1067
1068 exp = parse_exp_1 (&arg, 0, 1);
1069 *offset = value_as_pointer (evaluate_expression (exp));
1070
1071 /* now parse the size */
1072 if (*arg++ != ',')
1073 error ("missing comma for memrange: %s", start);
1074
1075 exp = parse_exp_1 (&arg, 0, 0);
1076 *size = value_as_long (evaluate_expression (exp));
1077
1078 if (info_verbose)
1079 printf_filtered ("Collecting memrange: (0x%x,0x%x,0x%x)\n",
1080 *typecode, *offset, *size);
1081
1082 return arg;
1083 }
1084
1085 /* compare memranges for qsort */
1086 static int
1087 memrange_cmp (a, b)
1088 struct memrange *a, *b;
1089 {
1090 if (a->type < b->type) return -1;
1091 if (a->type > b->type) return 1;
1092 if (a->type == 0)
1093 {
1094 if ((bfd_vma) a->start < (bfd_vma) b->start) return -1;
1095 if ((bfd_vma) a->start > (bfd_vma) b->start) return 1;
1096 }
1097 else
1098 {
1099 if (a->start < b->start) return -1;
1100 if (a->start > b->start) return 1;
1101 }
1102 return 0;
1103 }
1104
1105 /* Sort the memrange list using qsort, and merge adjacent memranges */
1106 static void
1107 memrange_sortmerge (memranges)
1108 struct collection_list *memranges;
1109 {
1110 int a, b;
1111
1112 qsort (memranges->list, memranges->next_memrange,
1113 sizeof (struct memrange), memrange_cmp);
1114 if (memranges->next_memrange > 0)
1115 {
1116 for (a = 0, b = 1; b < memranges->next_memrange; b++)
1117 {
1118 if (memranges->list[a].type == memranges->list[b].type &&
1119 memranges->list[b].start - memranges->list[a].end <=
1120 MAX_REGISTER_VIRTUAL_SIZE)
1121 {
1122 /* memrange b starts before memrange a ends; merge them. */
1123 if (memranges->list[b].end > memranges->list[a].end)
1124 memranges->list[a].end = memranges->list[b].end;
1125 continue; /* next b, same a */
1126 }
1127 a++; /* next a */
1128 if (a != b)
1129 memcpy (&memranges->list[a], &memranges->list[b],
1130 sizeof (struct memrange));
1131 }
1132 memranges->next_memrange = a + 1;
1133 }
1134 }
1135
1136 /* Add a register to a collection list */
1137 void
1138 add_register (collection, regno)
1139 struct collection_list *collection;
1140 unsigned long regno;
1141 {
1142 if (info_verbose)
1143 printf_filtered ("collect register %d\n", regno);
1144 if (regno > (8 * sizeof (collection->regs_mask)))
1145 error ("Internal: register number %d too large for tracepoint",
1146 regno);
1147 collection->regs_mask [regno / 8] |= 1 << (regno % 8);
1148 }
1149
1150 /* Add a memrange to a collection list */
1151 static void
1152 add_memrange (memranges, type, base, len)
1153 struct collection_list *memranges;
1154 int type;
1155 bfd_signed_vma base;
1156 unsigned long len;
1157 {
1158 if (info_verbose)
1159 printf_filtered ("(%d,0x%x,%d)\n", type, base, len);
1160 /* type: 0 == memory, n == basereg */
1161 memranges->list[memranges->next_memrange].type = type;
1162 /* base: addr if memory, offset if reg relative. */
1163 memranges->list[memranges->next_memrange].start = base;
1164 /* len: we actually save end (base + len) for convenience */
1165 memranges->list[memranges->next_memrange].end = base + len;
1166 memranges->next_memrange++;
1167 if (memranges->next_memrange >= memranges->listsize)
1168 {
1169 memranges->listsize *= 2;
1170 memranges->list = xrealloc (memranges->list,
1171 memranges->listsize);
1172 }
1173
1174 if (type != -1) /* better collect the base register! */
1175 add_register (memranges, type);
1176 }
1177
1178 /* Add a symbol to a collection list */
1179 static void
1180 collect_symbol (collect, sym)
1181 struct collection_list *collect;
1182 struct symbol *sym;
1183 {
1184 unsigned long len;
1185 unsigned long reg;
1186 bfd_signed_vma offset;
1187
1188 len = TYPE_LENGTH (check_typedef (SYMBOL_TYPE (sym)));
1189 switch (SYMBOL_CLASS (sym)) {
1190 default:
1191 printf_filtered ("%s: don't know symbol class %d\n",
1192 SYMBOL_NAME (sym), SYMBOL_CLASS (sym));
1193 break;
1194 case LOC_CONST:
1195 printf_filtered ("%s is constant, value is %d: will not be collected.\n",
1196 SYMBOL_NAME (sym), SYMBOL_VALUE (sym));
1197 break;
1198 case LOC_STATIC:
1199 offset = SYMBOL_VALUE_ADDRESS (sym);
1200 if (info_verbose)
1201 printf_filtered ("LOC_STATIC %s: collect %d bytes "
1202 "at 0x%08x\n",
1203 SYMBOL_NAME (sym), len, offset);
1204 add_memrange (collect, -1, offset, len); /* 0 == memory */
1205 break;
1206 case LOC_REGISTER:
1207 case LOC_REGPARM:
1208 reg = SYMBOL_VALUE (sym);
1209 if (info_verbose)
1210 printf_filtered ("LOC_REG[parm] %s: ", SYMBOL_NAME (sym));
1211 add_register (collect, reg);
1212 break;
1213 case LOC_ARG:
1214 case LOC_REF_ARG:
1215 printf_filtered ("Sorry, don't know how to do LOC_ARGs yet.\n");
1216 printf_filtered (" (will not collect %s)\n",
1217 SYMBOL_NAME (sym));
1218 break;
1219 case LOC_REGPARM_ADDR:
1220 reg = SYMBOL_VALUE (sym);
1221 offset = 0;
1222 if (info_verbose)
1223 {
1224 printf_filtered ("LOC_REGPARM_ADDR %s: Collect %d bytes at offset %d from reg %d\n",
1225 SYMBOL_NAME (sym), len, offset, reg);
1226 }
1227 add_memrange (collect, reg, offset, len);
1228 break;
1229 case LOC_LOCAL:
1230 case LOC_LOCAL_ARG:
1231 offset = SYMBOL_VALUE (sym);
1232 reg = FP_REGNUM;
1233 if (info_verbose)
1234 {
1235 printf_filtered ("LOC_LOCAL %s: Collect %d bytes at offset %d from frame ptr reg %d\n",
1236 SYMBOL_NAME (sym), len, offset, reg);
1237 }
1238 add_memrange (collect, reg, offset, len);
1239 break;
1240 case LOC_BASEREG:
1241 case LOC_BASEREG_ARG:
1242 reg = SYMBOL_BASEREG (sym);
1243 offset = SYMBOL_VALUE (sym);
1244 if (info_verbose)
1245 {
1246 printf_filtered ("LOC_BASEREG %s: collect %d bytes at offset %d from basereg %d\n",
1247 SYMBOL_NAME (sym), len, offset, reg);
1248 }
1249 add_memrange (collect, reg, offset, len);
1250 break;
1251 case LOC_UNRESOLVED:
1252 printf_filtered ("Don't know LOC_UNRESOLVED %s\n", SYMBOL_NAME (sym));
1253 break;
1254 case LOC_OPTIMIZED_OUT:
1255 printf_filtered ("%s has been optimized out of existance.\n",
1256 SYMBOL_NAME (sym));
1257 break;
1258 }
1259 }
1260
1261 /* Add all locals (or args) symbols to collection list */
1262 static void
1263 add_local_symbols (collect, pc, type)
1264 struct collection_list *collect;
1265 CORE_ADDR pc;
1266 char type;
1267 {
1268 struct symbol *sym;
1269 struct block *block;
1270 int i, nsyms, count = 0;
1271
1272 block = block_for_pc (pc);
1273 while (block != 0)
1274 {
1275 nsyms = BLOCK_NSYMS (block);
1276 for (i = 0; i < nsyms; i++)
1277 {
1278 sym = BLOCK_SYM (block, i);
1279 switch (SYMBOL_CLASS (sym)) {
1280 case LOC_LOCAL:
1281 case LOC_STATIC:
1282 case LOC_REGISTER:
1283 case LOC_BASEREG:
1284 if (type == 'L') /* collecting Locals */
1285 {
1286 count++;
1287 collect_symbol (collect, sym);
1288 }
1289 break;
1290 case LOC_ARG:
1291 case LOC_LOCAL_ARG:
1292 case LOC_REF_ARG:
1293 case LOC_REGPARM:
1294 case LOC_REGPARM_ADDR:
1295 case LOC_BASEREG_ARG:
1296 if (type == 'A') /* collecting Arguments */
1297 {
1298 count++;
1299 collect_symbol (collect, sym);
1300 }
1301 }
1302 }
1303 if (BLOCK_FUNCTION (block))
1304 break;
1305 else
1306 block = BLOCK_SUPERBLOCK (block);
1307 }
1308 if (count == 0)
1309 warning ("No %s found in scope.", type == 'L' ? "locals" : "args");
1310 }
1311
1312 /* worker function */
1313 static void
1314 clear_collection_list (list)
1315 struct collection_list *list;
1316 {
1317 list->next_memrange = 0;
1318 memset (list->regs_mask, 0, sizeof (list->regs_mask));
1319 }
1320
1321 /* reduce a collection list to string form (for gdb protocol) */
1322 static char *
1323 stringify_collection_list (list, string)
1324 struct collection_list *list;
1325 char *string;
1326 {
1327 char *end = string;
1328 long i;
1329
1330 for (i = sizeof (list->regs_mask) - 1; i > 0; i--)
1331 if (list->regs_mask[i] != 0) /* skip leading zeroes in regs_mask */
1332 break;
1333 if (list->regs_mask[i] != 0) /* prepare to send regs_mask to the stub */
1334 {
1335 if (info_verbose)
1336 printf_filtered ("\nCollecting registers (mask): 0x");
1337 *end++='R';
1338 for (; i >= 0; i--)
1339 {
1340 if (info_verbose)
1341 printf_filtered ("%02X", list->regs_mask[i]);
1342 sprintf (end, "%02X", list->regs_mask[i]);
1343 end += 2;
1344 }
1345 }
1346 if (info_verbose)
1347 printf_filtered ("\n");
1348 if (list->next_memrange > 0 && info_verbose)
1349 printf_filtered ("Collecting memranges: \n");
1350 for (i = 0; i < list->next_memrange; i++)
1351 {
1352 if (info_verbose)
1353 printf_filtered ("(%d, 0x%x, %d)\n",
1354 list->list[i].type,
1355 list->list[i].start,
1356 list->list[i].end - list->list[i].start);
1357 sprintf (end, "M%X,%X,%X",
1358 list->list[i].type,
1359 list->list[i].start,
1360 list->list[i].end - list->list[i].start);
1361 end += strlen (end);
1362 }
1363 if (end == string)
1364 return NULL;
1365 else
1366 return string;
1367 }
1368
1369 /* render all actions into gdb protocol */
1370 static void
1371 encode_actions (t, tdp_actions, step_count, stepping_actions)
1372 struct tracepoint *t;
1373 char **tdp_actions;
1374 unsigned long *step_count;
1375 char **stepping_actions;
1376 {
1377 static char tdp_buff[2048], step_buff[2048];
1378 char *action_exp;
1379 struct expression *exp;
1380 struct action_line *action;
1381 bfd_signed_vma offset;
1382 long i;
1383 value_ptr tempval;
1384 struct collection_list *collect;
1385 struct cmd_list_element *cmd;
1386
1387 clear_collection_list (&tracepoint_list);
1388 clear_collection_list (&stepping_list);
1389 collect = &tracepoint_list;
1390
1391 *tdp_actions = NULL;
1392 *stepping_actions = NULL;
1393
1394 for (action = t->actions; action; action = action->next)
1395 {
1396 action_exp = action->action;
1397 while (isspace (*action_exp))
1398 action_exp++;
1399
1400 if (*action_exp == '#') /* comment line */
1401 return;
1402
1403 cmd = lookup_cmd (&action_exp, cmdlist, "", -1, 1);
1404 if (cmd == 0)
1405 error ("Bad action list item: %s", action_exp);
1406
1407 if (cmd->function.cfunc == collect_pseudocommand)
1408 {
1409 do { /* repeat over a comma-separated list */
1410 while (isspace (*action_exp))
1411 action_exp++;
1412
1413 if (0 == strncasecmp ("$reg", action_exp, 4))
1414 {
1415 for (i = 0; i < NUM_REGS; i++)
1416 add_register (collect, i);
1417 action_exp = strchr (action_exp, ','); /* more? */
1418 }
1419 else if (0 == strncasecmp ("$arg", action_exp, 4))
1420 {
1421 add_local_symbols (collect, t->address, 'A');
1422 action_exp = strchr (action_exp, ','); /* more? */
1423 }
1424 else if (0 == strncasecmp ("$loc", action_exp, 4))
1425 {
1426 add_local_symbols (collect, t->address, 'L');
1427 action_exp = strchr (action_exp, ','); /* more? */
1428 }
1429 else if (action_exp[0] == '$' &&
1430 action_exp[1] == '(') /* literal memrange */
1431 {
1432 long typecode, size;
1433 bfd_signed_vma offset;
1434
1435 action_exp = parse_and_eval_memrange (action_exp,
1436 t->address,
1437 &typecode,
1438 &offset,
1439 &size);
1440 add_memrange (collect, typecode, offset, size);
1441 }
1442 else
1443 {
1444 unsigned long addr, len;
1445
1446 exp = parse_exp_1 (&action_exp, block_for_pc (t->address), 1);
1447 switch (exp->elts[0].opcode) {
1448 case OP_REGISTER:
1449 i = exp->elts[1].longconst;
1450 if (info_verbose)
1451 printf_filtered ("OP_REGISTER: ");
1452 add_register (collect, i);
1453 break;
1454
1455 case UNOP_MEMVAL:
1456 /* safe because we know it's a simple expression */
1457 tempval = evaluate_expression (exp);
1458 addr = VALUE_ADDRESS (tempval) + VALUE_OFFSET (tempval);
1459 len = TYPE_LENGTH (check_typedef (exp->elts[1].type));
1460 add_memrange (collect, -1, addr, len);
1461 break;
1462
1463 case OP_VAR_VALUE:
1464 collect_symbol (collect, exp->elts[2].symbol);
1465 break;
1466 #if 0
1467 case OP_LONG:
1468 addr = exp->elts[2].longconst;
1469 if (*action_exp == ':')
1470 {
1471 exp = parse_exp_1 (&action_exp,
1472 block_for_pc (t->address),
1473 1);
1474 if (exp->elts[0].opcode == OP_LONG)
1475 len = exp->elts[2].longconst;
1476 else
1477 error ("length field requires a literal long const");
1478 }
1479 else
1480 len = 4;
1481
1482 add_memrange (collect, -1, addr, len);
1483 break;
1484 #endif
1485 }
1486 }
1487 } while (action_exp && *action_exp++ == ',');
1488 }
1489 else if (cmd->function.cfunc == while_stepping_pseudocommand)
1490 {
1491 collect = &stepping_list;
1492 }
1493 else if (cmd->function.cfunc == end_actions_pseudocommand)
1494 {
1495 if (collect == &stepping_list) /* end stepping actions */
1496 collect = &tracepoint_list;
1497 else
1498 break; /* end tracepoint actions */
1499 }
1500 }
1501 memrange_sortmerge (&tracepoint_list);
1502 memrange_sortmerge (&stepping_list);
1503
1504 *tdp_actions = stringify_collection_list (&tracepoint_list, &tdp_buff);
1505 *stepping_actions = stringify_collection_list (&stepping_list, &step_buff);
1506 }
1507
1508 static char target_buf[2048];
1509
1510 /* tstart command:
1511
1512 Tell target to lear any previous trace experiment.
1513 Walk the list of tracepoints, and send them (and their actions)
1514 to the target. If no errors,
1515 Tell target to start a new trace experiment. */
1516
1517 static void
1518 trace_start_command (args, from_tty)
1519 char *args;
1520 int from_tty;
1521 { /* STUB_COMM MOSTLY_IMPLEMENTED */
1522 struct tracepoint *t;
1523 char buf[2048];
1524 char *tdp_actions;
1525 char *stepping_actions;
1526 unsigned long step_count;
1527
1528 dont_repeat (); /* like "run", dangerous to repeat accidentally */
1529
1530 if (target_is_remote ())
1531 {
1532 putpkt ("QTinit");
1533 remote_get_noisy_reply (target_buf);
1534 if (strcmp (target_buf, "OK"))
1535 error ("Target does not support this command.");
1536
1537 ALL_TRACEPOINTS (t)
1538 {
1539 int ss_count; /* if actions include singlestepping */
1540 int disable_mask; /* ??? */
1541 int enable_mask; /* ??? */
1542
1543 sprintf (buf, "QTDP:%x:%x:%c:%x:%x", t->number, t->address,
1544 t->enabled == enabled ? 'E' : 'D',
1545 t->step_count, t->pass_count);
1546 if (t->actions)
1547 {
1548 encode_actions (t, &tdp_actions, &step_count, &stepping_actions);
1549 /* do_single_steps (t); */
1550 if (tdp_actions)
1551 {
1552 if (strlen (buf) + strlen (tdp_actions) >= sizeof (buf))
1553 error ("Actions for tracepoint %d too complex; "
1554 "please simplify.", t->number);
1555 strcat (buf, tdp_actions);
1556 }
1557 if (stepping_actions)
1558 {
1559 strcat (buf, "S");
1560 if (strlen (buf) + strlen (stepping_actions) >= sizeof (buf))
1561 error ("Actions for tracepoint %d too complex; "
1562 "please simplify.", t->number);
1563 strcat (buf, stepping_actions);
1564 }
1565 }
1566 putpkt (buf);
1567 remote_get_noisy_reply (target_buf);
1568 if (strcmp (target_buf, "OK"))
1569 error ("Target does not support tracepoints.");
1570 }
1571 putpkt ("QTStart");
1572 remote_get_noisy_reply (target_buf);
1573 if (strcmp (target_buf, "OK"))
1574 error ("Bogus reply from target: %s", target_buf);
1575 set_traceframe_num (-1); /* all old traceframes invalidated */
1576 set_tracepoint_num (-1);
1577 set_traceframe_context(-1);
1578 }
1579 else
1580 printf_filtered ("Trace can only be run on remote targets.\n");
1581 }
1582
1583 /* tstop command */
1584 static void
1585 trace_stop_command (args, from_tty)
1586 char *args;
1587 int from_tty;
1588 { /* STUB_COMM IS_IMPLEMENTED */
1589 if (target_is_remote ())
1590 {
1591 putpkt ("QTStop");
1592 remote_get_noisy_reply (target_buf);
1593 if (strcmp (target_buf, "OK"))
1594 error ("Bogus reply from target: %s", target_buf);
1595 }
1596 else
1597 error ("Trace can only be run on remote targets.");
1598 }
1599
1600 /* tstatus command */
1601 static void
1602 trace_status_command (args, from_tty)
1603 char *args;
1604 int from_tty;
1605 { /* STUB_COMM IS_IMPLEMENTED */
1606 if (target_is_remote ())
1607 {
1608 putpkt ("qTStatus");
1609 remote_get_noisy_reply (target_buf);
1610 if (strcmp (target_buf, "OK"))
1611 error ("Bogus reply from target: %s", target_buf);
1612 }
1613 else
1614 error ("Trace can only be run on remote targets.");
1615 }
1616
1617 /* Worker function for the various flavors of the tfind command */
1618 static void
1619 finish_tfind_command (msg, from_tty)
1620 char *msg;
1621 int from_tty;
1622 {
1623 int target_frameno = -1, target_tracept = -1;
1624 CORE_ADDR old_frame_addr;
1625 struct symbol *old_func;
1626 char *reply;
1627
1628 old_frame_addr = FRAME_FP (get_current_frame ());
1629 old_func = find_pc_function (read_pc ());
1630
1631 putpkt (msg);
1632 reply = remote_get_noisy_reply (msg);
1633
1634 while (reply && *reply)
1635 switch (*reply) {
1636 case 'F':
1637 if ((target_frameno = strtol (++reply, &reply, 16)) == -1)
1638 {
1639 /* A request for a non-existant trace frame has failed.
1640 Our response will be different, depending on FROM_TTY:
1641
1642 If FROM_TTY is true, meaning that this command was
1643 typed interactively by the user, then give an error
1644 and DO NOT change the state of traceframe_number etc.
1645
1646 However if FROM_TTY is false, meaning that we're either
1647 in a script, a loop, or a user-defined command, then
1648 DON'T give an error, but DO change the state of
1649 traceframe_number etc. to invalid.
1650
1651 The rationalle is that if you typed the command, you
1652 might just have committed a typo or something, and you'd
1653 like to NOT lose your current debugging state. However
1654 if you're in a user-defined command or especially in a
1655 loop, then you need a way to detect that the command
1656 failed WITHOUT aborting. This allows you to write
1657 scripts that search thru the trace buffer until the end,
1658 and then continue on to do something else. */
1659
1660 if (from_tty)
1661 error ("Target failed to find requested trace frame.");
1662 else
1663 {
1664 if (info_verbose)
1665 printf_filtered ("End of trace buffer.\n");
1666 /* The following will not recurse, since it's special-cased */
1667 trace_find_command ("-1", from_tty);
1668 reply = NULL; /* break out of loop,
1669 (avoid recursive nonsense) */
1670 }
1671 }
1672 break;
1673 case 'T':
1674 if ((target_tracept = strtol (++reply, &reply, 16)) == -1)
1675 error ("Target failed to find requested trace frame.");
1676 break;
1677 case 'O': /* "OK"? */
1678 if (reply[1] == 'K' && reply[2] == '\0')
1679 reply += 2;
1680 else
1681 error ("Bogus reply from target: %s", reply);
1682 break;
1683 default:
1684 error ("Bogus reply from target: %s", reply);
1685 }
1686
1687 flush_cached_frames ();
1688 registers_changed ();
1689 select_frame (get_current_frame (), 0);
1690 set_traceframe_num (target_frameno);
1691 set_tracepoint_num (target_tracept);
1692 if (target_frameno == -1)
1693 set_traceframe_context (-1);
1694 else
1695 set_traceframe_context (read_pc ());
1696
1697 if (from_tty)
1698 {
1699 int source_only;
1700
1701 /* NOTE: in immitation of the step command, try to determine
1702 whether we have made a transition from one function to another.
1703 If so, we'll print the "stack frame" (ie. the new function and
1704 it's arguments) -- otherwise we'll just show the new source line.
1705
1706 This determination is made by checking (1) whether the current
1707 function has changed, and (2) whether the current FP has changed.
1708 Hack: if the FP wasn't collected, either at the current or the
1709 previous frame, assume that the FP has NOT changed. */
1710
1711 if (old_func == find_pc_function (read_pc ()) &&
1712 (old_frame_addr == 0 ||
1713 FRAME_FP (get_current_frame ()) == 0 ||
1714 old_frame_addr == FRAME_FP (get_current_frame ())))
1715 source_only = -1;
1716 else
1717 source_only = 1;
1718
1719 print_stack_frame (selected_frame, selected_frame_level, source_only);
1720 do_displays ();
1721 }
1722 }
1723
1724 /* trace_find_command takes a trace frame number n,
1725 sends "QTFrame:<n>" to the target,
1726 and accepts a reply that may contain several optional pieces
1727 of information: a frame number, a tracepoint number, and an
1728 indication of whether this is a trap frame or a stepping frame.
1729
1730 The minimal response is just "OK" (which indicates that the
1731 target does not give us a frame number or a tracepoint number).
1732 Instead of that, the target may send us a string containing
1733 any combination of:
1734 F<hexnum> (gives the selected frame number)
1735 T<hexnum> (gives the selected tracepoint number)
1736 */
1737
1738 /* tfind command */
1739 static void
1740 trace_find_command (args, from_tty)
1741 char *args;
1742 int from_tty;
1743 { /* STUB_COMM PART_IMPLEMENTED */
1744 /* this should only be called with a numeric argument */
1745 int frameno = -1;
1746 int target_frameno = -1, target_tracept = -1, target_stepfrm = 0;
1747 char *tmp;
1748
1749 if (target_is_remote ())
1750 {
1751 if (args == 0 || *args == 0)
1752 { /* TFIND with no args means find NEXT trace frame. */
1753 if (traceframe_number == -1)
1754 frameno = 0; /* "next" is first one */
1755 else
1756 frameno = traceframe_number + 1;
1757 }
1758 else if (0 == strcmp (args, "-"))
1759 {
1760 if (traceframe_number == -1)
1761 error ("not debugging trace buffer");
1762 else if (from_tty && traceframe_number == 0)
1763 error ("already at start of trace buffer");
1764
1765 frameno = traceframe_number - 1;
1766 }
1767 else
1768 frameno = parse_and_eval_address (args);
1769
1770 sprintf (target_buf, "QTFrame:%x", frameno);
1771 #if 0
1772 putpkt (target_buf);
1773 tmp = remote_get_noisy_reply (target_buf);
1774
1775 if (frameno == -1) /* end trace debugging */
1776 { /* hopefully the stub has complied! */
1777 if (0 != strcmp (tmp, "OK"))
1778 error ("Bogus response from target: %s", tmp);
1779
1780 finish_tfind_command (NULL, from_tty);
1781 }
1782 else
1783 finish_tfind_command (tmp, from_tty);
1784 #else
1785 finish_tfind_command (target_buf, from_tty);
1786 #endif
1787 }
1788 else
1789 error ("Trace can only be run on remote targets.");
1790 }
1791
1792 /* tfind end */
1793 static void
1794 trace_find_end_command (args, from_tty)
1795 char *args;
1796 int from_tty;
1797 {
1798 trace_find_command ("-1", from_tty);
1799 }
1800
1801 /* tfind none */
1802 static void
1803 trace_find_none_command (args, from_tty)
1804 char *args;
1805 int from_tty;
1806 {
1807 trace_find_command ("-1", from_tty);
1808 }
1809
1810 /* tfind start */
1811 static void
1812 trace_find_start_command (args, from_tty)
1813 char *args;
1814 int from_tty;
1815 {
1816 trace_find_command ("0", from_tty);
1817 }
1818
1819 /* tfind pc command */
1820 static void
1821 trace_find_pc_command (args, from_tty)
1822 char *args;
1823 int from_tty;
1824 { /* STUB_COMM PART_IMPLEMENTED */
1825 CORE_ADDR pc;
1826 int target_frameno;
1827 char *tmp;
1828
1829 if (target_is_remote ())
1830 {
1831 if (args == 0 || *args == 0)
1832 pc = read_pc (); /* default is current pc */
1833 else
1834 pc = parse_and_eval_address (args);
1835
1836 sprintf (target_buf, "QTFrame:pc:%x", pc);
1837 #if 0
1838 putpkt (target_buf);
1839 tmp = remote_get_noisy_reply (target_buf);
1840
1841 finish_tfind_command (tmp, from_tty);
1842 #else
1843 finish_tfind_command (target_buf, from_tty);
1844 #endif
1845 }
1846 else
1847 error ("Trace can only be run on remote targets.");
1848 }
1849
1850 /* tfind tracepoint command */
1851 static void
1852 trace_find_tracepoint_command (args, from_tty)
1853 char *args;
1854 int from_tty;
1855 { /* STUB_COMM PART_IMPLEMENTED */
1856 int target_frameno, tdp;
1857 char buf[40], *tmp;
1858
1859 if (target_is_remote ())
1860 {
1861 if (args == 0 || *args == 0)
1862 if (tracepoint_number == -1)
1863 error ("No current tracepoint -- please supply an argument.");
1864 else
1865 tdp = tracepoint_number; /* default is current TDP */
1866 else
1867 tdp = parse_and_eval_address (args);
1868
1869 sprintf (target_buf, "QTFrame:tdp:%x", tdp);
1870 #if 0
1871 putpkt (target_buf);
1872 tmp = remote_get_noisy_reply (target_buf);
1873
1874 finish_tfind_command (tmp, from_tty);
1875 #else
1876 finish_tfind_command (target_buf, from_tty);
1877 #endif
1878 }
1879 else
1880 error ("Trace can only be run on remote targets.");
1881 }
1882
1883 /* TFIND LINE command:
1884
1885 This command will take a sourceline for argument, just like BREAK
1886 or TRACE (ie. anything that "decode_line_1" can handle).
1887
1888 With no argument, this command will find the next trace frame
1889 corresponding to a source line OTHER THAN THE CURRENT ONE. */
1890
1891 static void
1892 trace_find_line_command (args, from_tty)
1893 char *args;
1894 int from_tty;
1895 { /* STUB_COMM PART_IMPLEMENTED */
1896 static CORE_ADDR start_pc, end_pc;
1897 struct symtabs_and_lines sals;
1898 struct symtab_and_line sal;
1899 int target_frameno;
1900 char *tmp;
1901 struct cleanup *old_chain;
1902
1903 if (target_is_remote ())
1904 {
1905 if (args == 0 || *args == 0)
1906 {
1907 sal = find_pc_line ((get_current_frame ())->pc, 0);
1908 sals.nelts = 1;
1909 sals.sals = (struct symtab_and_line *)
1910 xmalloc (sizeof (struct symtab_and_line));
1911 sals.sals[0] = sal;
1912 }
1913 else
1914 {
1915 sals = decode_line_spec (args, 1);
1916 sal = sals.sals[0];
1917 }
1918
1919 old_chain = make_cleanup (free, sals.sals);
1920 if (sal.symtab == 0)
1921 {
1922 printf_filtered ("TFIND: No line number information available");
1923 if (sal.pc != 0)
1924 {
1925 /* This is useful for "info line *0x7f34". If we can't tell the
1926 user about a source line, at least let them have the symbolic
1927 address. */
1928 printf_filtered (" for address ");
1929 wrap_here (" ");
1930 print_address (sal.pc, gdb_stdout);
1931 printf_filtered (";\n -- will attempt to find by PC. \n");
1932 }
1933 else
1934 {
1935 printf_filtered (".\n");
1936 return; /* no line, no PC; what can we do? */
1937 }
1938 }
1939 else if (sal.line > 0
1940 && find_line_pc_range (sal, &start_pc, &end_pc))
1941 {
1942 if (start_pc == end_pc)
1943 {
1944 printf_filtered ("Line %d of \"%s\"",
1945 sal.line, sal.symtab->filename);
1946 wrap_here (" ");
1947 printf_filtered (" is at address ");
1948 print_address (start_pc, gdb_stdout);
1949 wrap_here (" ");
1950 printf_filtered (" but contains no code.\n");
1951 sal = find_pc_line (start_pc, 0);
1952 if (sal.line > 0 &&
1953 find_line_pc_range (sal, &start_pc, &end_pc) &&
1954 start_pc != end_pc)
1955 printf_filtered ("Attempting to find line %d instead.\n",
1956 sal.line);
1957 else
1958 error ("Cannot find a good line.");
1959 }
1960 }
1961 else
1962 /* Is there any case in which we get here, and have an address
1963 which the user would want to see? If we have debugging symbols
1964 and no line numbers? */
1965 error ("Line number %d is out of range for \"%s\".\n",
1966 sal.line, sal.symtab->filename);
1967
1968 if (args && *args) /* find within range of stated line */
1969 sprintf (target_buf, "QTFrame:range:%x:%x", start_pc, end_pc - 1);
1970 else /* find OUTSIDE OF range of CURRENT line */
1971 sprintf (target_buf, "QTFrame:outside:%x:%x", start_pc, end_pc - 1);
1972 #if 0
1973 putpkt (target_buf);
1974 tmp = remote_get_noisy_reply (target_buf);
1975
1976 finish_tfind_command (tmp, from_tty);
1977 #else
1978 finish_tfind_command (target_buf, from_tty);
1979 #endif
1980 do_cleanups (old_chain);
1981 }
1982 else
1983 error ("Trace can only be run on remote targets.");
1984 }
1985
1986 /* tfind range command */
1987 static void
1988 trace_find_range_command (args, from_tty)
1989 char *args;
1990 int from_tty;
1991 { /* STUB_COMM PART_IMPLEMENTED */
1992 static CORE_ADDR start, stop;
1993 int target_frameno;
1994 char *tmp;
1995
1996 if (target_is_remote ())
1997 {
1998 if (args == 0 || *args == 0)
1999 { /* XXX FIXME: what should default behavior be? */
2000 printf_filtered ("Usage: tfind range <startaddr>,<endaddr>\n");
2001 return;
2002 }
2003
2004 if (0 != (tmp = strchr (args, ',' )))
2005 {
2006 *tmp++ = '\0'; /* terminate start address */
2007 while (isspace (*tmp))
2008 tmp++;
2009 start = parse_and_eval_address (args);
2010 stop = parse_and_eval_address (tmp);
2011 }
2012 else
2013 { /* no explicit end address? */
2014 start = parse_and_eval_address (args);
2015 stop = start + 1; /* ??? */
2016 }
2017
2018 sprintf (target_buf, "QTFrame:range:%x:%x", start, stop);
2019 #if 0
2020 putpkt (target_buf);
2021 tmp = remote_get_noisy_reply (target_buf);
2022
2023 finish_tfind_command (tmp, from_tty);
2024 #else
2025 finish_tfind_command (target_buf, from_tty);
2026 #endif
2027 }
2028 else
2029 error ("Trace can only be run on remote targets.");
2030 }
2031
2032 /* tfind outside command */
2033 static void
2034 trace_find_outside_command (args, from_tty)
2035 char *args;
2036 int from_tty;
2037 { /* STUB_COMM PART_IMPLEMENTED */
2038 CORE_ADDR start, stop;
2039 int target_frameno;
2040 char *tmp;
2041
2042 if (target_is_remote ())
2043 {
2044 if (args == 0 || *args == 0)
2045 { /* XXX FIXME: what should default behavior be? */
2046 printf_filtered ("Usage: tfind outside <startaddr>,<endaddr>\n");
2047 return;
2048 }
2049
2050 if (0 != (tmp = strchr (args, ',' )))
2051 {
2052 *tmp++ = '\0'; /* terminate start address */
2053 while (isspace (*tmp))
2054 tmp++;
2055 start = parse_and_eval_address (args);
2056 stop = parse_and_eval_address (tmp);
2057 }
2058 else
2059 { /* no explicit end address? */
2060 start = parse_and_eval_address (args);
2061 stop = start + 1; /* ??? */
2062 }
2063
2064 sprintf (target_buf, "QTFrame:outside:%x:%x", start, stop);
2065 #if 0
2066 putpkt (target_buf);
2067 tmp = remote_get_noisy_reply (target_buf);
2068
2069 finish_tfind_command (tmp, from_tty);
2070 #else
2071 finish_tfind_command (target_buf, from_tty);
2072 #endif
2073 }
2074 else
2075 error ("Trace can only be run on remote targets.");
2076 }
2077
2078 /* save-tracepoints command */
2079 static void
2080 tracepoint_save_command (args, from_tty)
2081 char *args;
2082 int from_tty;
2083 {
2084 struct tracepoint *tp;
2085 struct action_line *line;
2086 FILE *fp;
2087 char *i1 = " ", *i2 = " ";
2088 char *indent, *actionline;
2089
2090 if (args == 0 || *args == 0)
2091 error ("Argument required (file name in which to save tracepoints");
2092
2093 if (tracepoint_chain == 0)
2094 {
2095 warning ("save-tracepoints: no tracepoints to save.\n");
2096 return;
2097 }
2098
2099 if (!(fp = fopen (args, "w")))
2100 error ("Unable to open file '%s' for saving tracepoints");
2101
2102 ALL_TRACEPOINTS (tp)
2103 {
2104 if (tp->addr_string)
2105 fprintf (fp, "trace %s\n", tp->addr_string);
2106 else
2107 fprintf (fp, "trace *0x%x\n", tp->address);
2108
2109 if (tp->pass_count)
2110 fprintf (fp, " passcount %d\n", tp->pass_count);
2111
2112 if (tp->actions)
2113 {
2114 fprintf (fp, " actions\n");
2115 indent = i1;
2116 for (line = tp->actions; line; line = line->next)
2117 {
2118 struct cmd_list_element *cmd;
2119
2120 actionline = line->action;
2121 while (isspace(*actionline))
2122 actionline++;
2123
2124 fprintf (fp, "%s%s\n", indent, actionline);
2125 if (*actionline != '#') /* skip for comment lines */
2126 {
2127 cmd = lookup_cmd (&actionline, cmdlist, "", -1, 1);
2128 if (cmd == 0)
2129 error ("Bad action list item: %s", actionline);
2130 if (cmd->function.cfunc == while_stepping_pseudocommand)
2131 indent = i2;
2132 else if (cmd->function.cfunc == end_actions_pseudocommand)
2133 indent = i1;
2134 }
2135 }
2136 }
2137 }
2138 fclose (fp);
2139 if (from_tty)
2140 printf_filtered ("Tracepoints saved to file '%s'.\n", args);
2141 return;
2142 }
2143
2144 /* info scope command: list the locals for a scope. */
2145 static void
2146 scope_info (args, from_tty)
2147 char *args;
2148 int from_tty;
2149 {
2150 struct symtab_and_line sal;
2151 struct symtabs_and_lines sals;
2152 struct symbol *sym;
2153 struct minimal_symbol *msym;
2154 struct block *block;
2155 char **canonical, *symname, *save_args = args;
2156 int i, nsyms, count = 0;
2157
2158 if (args == 0 || *args == 0)
2159 error ("requires an argument (function, line or *addr) to define a scope");
2160
2161 sals = decode_line_1 (&args, 1, NULL, 0, &canonical);
2162 if (sals.nelts == 0)
2163 return; /* presumably decode_line_1 has already warned */
2164
2165 /* Resolve line numbers to PC */
2166 resolve_sal_pc (&sals.sals[0]);
2167 block = block_for_pc (sals.sals[0].pc);
2168
2169 while (block != 0)
2170 {
2171 nsyms = BLOCK_NSYMS (block);
2172 for (i = 0; i < nsyms; i++)
2173 {
2174 if (count == 0)
2175 printf_filtered ("Scope for %s:\n", save_args);
2176 count++;
2177 sym = BLOCK_SYM (block, i);
2178 symname = SYMBOL_NAME (sym);
2179 if (symname == NULL || *symname == '\0')
2180 continue; /* probably botched, certainly useless */
2181
2182 printf_filtered ("Symbol %s is ", symname);
2183 switch (SYMBOL_CLASS (sym)) {
2184 default:
2185 case LOC_UNDEF: /* messed up symbol? */
2186 printf_filtered ("a bogus symbol, class %d.\n",
2187 SYMBOL_CLASS (sym));
2188 count--; /* don't count this one */
2189 continue;
2190 case LOC_CONST:
2191 printf_filtered ("a constant with value %d (0x%x)",
2192 SYMBOL_VALUE (sym), SYMBOL_VALUE (sym));
2193 break;
2194 case LOC_CONST_BYTES:
2195 printf_filtered ("constant bytes: ");
2196 if (SYMBOL_TYPE (sym))
2197 for (i = 0; i < TYPE_LENGTH (SYMBOL_TYPE (sym)); i++)
2198 fprintf_filtered (gdb_stdout, " %02x",
2199 (unsigned) SYMBOL_VALUE_BYTES (sym) [i]);
2200 break;
2201 case LOC_STATIC:
2202 printf_filtered ("in static storage at address ");
2203 print_address_numeric (SYMBOL_VALUE_ADDRESS (sym), 1, gdb_stdout);
2204 break;
2205 case LOC_REGISTER:
2206 printf_filtered ("a local variable in register $%s",
2207 reg_names [SYMBOL_VALUE (sym)]);
2208 break;
2209 case LOC_ARG:
2210 case LOC_LOCAL_ARG:
2211 printf_filtered ("an argument at stack/frame offset %ld",
2212 SYMBOL_VALUE (sym));
2213 break;
2214 case LOC_LOCAL:
2215 printf_filtered ("a local variable at frame offset %ld",
2216 SYMBOL_VALUE (sym));
2217 break;
2218 case LOC_REF_ARG:
2219 printf_filtered ("a reference argument at offset %ld",
2220 SYMBOL_VALUE (sym));
2221 break;
2222 case LOC_REGPARM:
2223 printf_filtered ("an argument in register $%s",
2224 reg_names[SYMBOL_VALUE (sym)]);
2225 break;
2226 case LOC_REGPARM_ADDR:
2227 printf_filtered ("the address of an argument, in register $%s",
2228 reg_names[SYMBOL_VALUE (sym)]);
2229 break;
2230 case LOC_TYPEDEF:
2231 printf_filtered ("a typedef.\n");
2232 continue;
2233 case LOC_LABEL:
2234 printf_filtered ("a label at address ");
2235 print_address_numeric (SYMBOL_VALUE_ADDRESS (sym), 1, gdb_stdout);
2236 break;
2237 case LOC_BLOCK:
2238 printf_filtered ("a function at address ");
2239 print_address_numeric (BLOCK_START (SYMBOL_BLOCK_VALUE (sym)), 1,
2240 gdb_stdout);
2241 break;
2242 case LOC_BASEREG:
2243 printf_filtered ("a variable at offset %d from register $%s",
2244 SYMBOL_VALUE (sym),
2245 reg_names [SYMBOL_BASEREG (sym)]);
2246 break;
2247 case LOC_BASEREG_ARG:
2248 printf_filtered ("an argument at offset %d from register $%s",
2249 SYMBOL_VALUE (sym),
2250 reg_names [SYMBOL_BASEREG (sym)]);
2251 break;
2252 case LOC_UNRESOLVED:
2253 msym = lookup_minimal_symbol (SYMBOL_NAME (sym), NULL, NULL);
2254 if (msym == NULL)
2255 printf_filtered ("Unresolved Static");
2256 else
2257 {
2258 printf_filtered ("static storage at address ");
2259 print_address_numeric (SYMBOL_VALUE_ADDRESS (msym), 1,
2260 gdb_stdout);
2261 }
2262 break;
2263 case LOC_OPTIMIZED_OUT:
2264 printf_filtered ("optimized out.\n");
2265 continue;
2266 }
2267 if (SYMBOL_TYPE (sym))
2268 printf_filtered (", length %d.\n",
2269 TYPE_LENGTH (check_typedef (SYMBOL_TYPE (sym))));
2270 }
2271 if (BLOCK_FUNCTION (block))
2272 break;
2273 else
2274 block = BLOCK_SUPERBLOCK (block);
2275 }
2276 if (count <= 0)
2277 printf_filtered ("Scope for %s contains no locals or arguments.\n",
2278 save_args);
2279 }
2280
2281 /* worker function (cleanup) */
2282 static void
2283 replace_comma (comma)
2284 char *comma;
2285 {
2286 *comma = ',';
2287 }
2288
2289 /* tdump command */
2290 static void
2291 trace_dump_command (args, from_tty)
2292 char *args;
2293 int from_tty;
2294 {
2295 struct tracepoint *t;
2296 struct action_line *action;
2297 char *action_exp, *next_comma;
2298 struct cleanup *old_cleanups;
2299 int stepping_actions = 0;
2300 int stepping_frame = 0;
2301
2302 if (tracepoint_number == -1)
2303 {
2304 warning ("No current trace frame.");
2305 return;
2306 }
2307
2308 ALL_TRACEPOINTS (t)
2309 if (t->number == tracepoint_number)
2310 break;
2311
2312 if (t == NULL)
2313 error ("No known tracepoint matches 'current' tracepoint #%d.",
2314 tracepoint_number);
2315
2316 old_cleanups = make_cleanup (null_cleanup, NULL);
2317
2318 printf_filtered ("Data collected at tracepoint %d, trace frame %d:\n",
2319 tracepoint_number, traceframe_number);
2320
2321 /* The current frame is a trap frame if the frame PC is equal
2322 to the tracepoint PC. If not, then the current frame was
2323 collected during single-stepping. */
2324
2325 stepping_frame = (t->address != read_pc());
2326
2327 for (action = t->actions; action; action = action->next)
2328 {
2329 struct cmd_list_element *cmd;
2330
2331 action_exp = action->action;
2332 while (isspace (*action_exp))
2333 action_exp++;
2334
2335 /* The collection actions to be done while stepping are
2336 bracketed by the commands "while-stepping" and "end". */
2337
2338 if (*action_exp == '#') /* comment line */
2339 continue;
2340
2341 cmd = lookup_cmd (&action_exp, cmdlist, "", -1, 1);
2342 if (cmd == 0)
2343 error ("Bad action list item: %s", action_exp);
2344
2345 if (cmd->function.cfunc == while_stepping_pseudocommand)
2346 stepping_actions = 1;
2347 else if (cmd->function.cfunc == end_actions_pseudocommand)
2348 stepping_actions = 0;
2349 else if (cmd->function.cfunc == collect_pseudocommand)
2350 {
2351 /* Display the collected data.
2352 For the trap frame, display only what was collected at the trap.
2353 Likewise for stepping frames, display only what was collected
2354 while stepping. This means that the two boolean variables,
2355 STEPPING_FRAME and STEPPING_ACTIONS should be equal. */
2356 if (stepping_frame == stepping_actions)
2357 {
2358 do { /* repeat over a comma-separated list */
2359 QUIT;
2360 if (*action_exp == ',')
2361 action_exp++;
2362 while (isspace (*action_exp))
2363 action_exp++;
2364
2365 next_comma = strchr (action_exp, ',');
2366
2367 if (0 == strncasecmp (action_exp, "$reg", 4))
2368 registers_info (NULL, from_tty);
2369 else if (0 == strncasecmp (action_exp, "$loc", 4))
2370 locals_info (NULL, from_tty);
2371 else if (0 == strncasecmp (action_exp, "$arg", 4))
2372 args_info (NULL, from_tty);
2373 else if (action_exp[0] == '$' && action_exp[1] == '(')
2374 { /* memrange */
2375 long typecode, size;
2376 bfd_signed_vma offset;
2377 char fmt[40];
2378
2379 action_exp = parse_and_eval_memrange (action_exp,
2380 read_pc (),
2381 &typecode,
2382 &offset,
2383 &size);
2384 if (typecode != 0 && typecode != -1)
2385 offset += read_register (typecode);
2386 sprintf (fmt, "/%dxb 0x%x", size, offset);
2387 x_command (fmt, from_tty);
2388 next_comma = strchr (action_exp, ',');
2389 }
2390 else
2391 { /* variable */
2392 if (next_comma)
2393 {
2394 make_cleanup (replace_comma, next_comma);
2395 *next_comma = '\0';
2396 }
2397 printf_filtered ("%s = ", action_exp);
2398 output_command (action_exp, from_tty);
2399 printf_filtered ("\n");
2400 }
2401 if (next_comma)
2402 *next_comma = ',';
2403 action_exp = next_comma;
2404 } while (action_exp && *action_exp == ',');
2405 }
2406 }
2407 }
2408 discard_cleanups (old_cleanups);
2409 }
2410
2411 /* module initialization */
2412 void
2413 _initialize_tracepoint ()
2414 {
2415 tracepoint_chain = 0;
2416 tracepoint_count = 0;
2417 traceframe_number = -1;
2418 tracepoint_number = -1;
2419
2420 set_internalvar (lookup_internalvar ("tpnum"),
2421 value_from_longest (builtin_type_int, (LONGEST) 0));
2422 set_internalvar (lookup_internalvar ("trace_frame"),
2423 value_from_longest (builtin_type_int, (LONGEST) 0));
2424
2425 if (tracepoint_list.list == NULL)
2426 {
2427 tracepoint_list.listsize = 128;
2428 tracepoint_list.list = xmalloc
2429 (tracepoint_list.listsize * sizeof (struct memrange));
2430 }
2431 if (stepping_list.list == NULL)
2432 {
2433 stepping_list.listsize = 128;
2434 stepping_list.list = xmalloc
2435 (stepping_list.listsize * sizeof (struct memrange));
2436 }
2437
2438 add_info ("scope", scope_info,
2439 "List the variables local to a scope");
2440
2441 add_cmd ("tracepoints", class_trace, NO_FUNCTION,
2442 "Tracing of program execution without stopping the program.",
2443 &cmdlist);
2444
2445 add_info ("tracepoints", tracepoints_info,
2446 "Status of tracepoints, or tracepoint number NUMBER.\n\
2447 Convenience variable \"$tpnum\" contains the number of the\n\
2448 last tracepoint set.");
2449
2450 add_info_alias ("tp", "tracepoints", 1);
2451
2452 add_com ("save-tracepoints", class_trace, tracepoint_save_command,
2453 "Save current tracepoint definitions as a script.\n\
2454 Use the 'source' command in another debug session to restore them.");
2455
2456 add_com ("tdump", class_trace, trace_dump_command,
2457 "Print everything collected at the current tracepoint.");
2458
2459 add_prefix_cmd ("tfind", class_trace, trace_find_command,
2460 "Select a trace frame;\n\
2461 No argument means forward by one frame; '-' meand backward by one frame.",
2462 &tfindlist, "tfind ", 1, &cmdlist);
2463
2464 add_cmd ("outside", class_trace, trace_find_outside_command,
2465 "Select a trace frame whose PC is outside the given \
2466 range.\nUsage: tfind outside addr1, addr2",
2467 &tfindlist);
2468
2469 add_cmd ("range", class_trace, trace_find_range_command,
2470 "Select a trace frame whose PC is in the given range.\n\
2471 Usage: tfind range addr1,addr2",
2472 &tfindlist);
2473
2474 add_cmd ("line", class_trace, trace_find_line_command,
2475 "Select a trace frame by source line.\n\
2476 Argument can be a line number (with optional source file), \n\
2477 a function name, or '*' followed by an address.\n\
2478 Default argument is 'the next source line that was traced'.",
2479 &tfindlist);
2480
2481 add_cmd ("tracepoint", class_trace, trace_find_tracepoint_command,
2482 "Select a trace frame by tracepoint number.\n\
2483 Default is the tracepoint for the current trace frame.",
2484 &tfindlist);
2485
2486 add_cmd ("pc", class_trace, trace_find_pc_command,
2487 "Select a trace frame by PC.\n\
2488 Default is the current PC, or the PC of the current trace frame.",
2489 &tfindlist);
2490
2491 add_cmd ("end", class_trace, trace_find_end_command,
2492 "Synonym for 'none'.\n\
2493 De-select any trace frame and resume 'live' debugging.",
2494 &tfindlist);
2495
2496 add_cmd ("none", class_trace, trace_find_none_command,
2497 "De-select any trace frame and resume 'live' debugging.",
2498 &tfindlist);
2499
2500 add_cmd ("start", class_trace, trace_find_start_command,
2501 "Select the first trace frame in the trace buffer.",
2502 &tfindlist);
2503
2504 add_com ("tstatus", class_trace, trace_status_command,
2505 "Display the status of the current trace data collection.");
2506
2507 add_com ("tstop", class_trace, trace_stop_command,
2508 "Stop trace data collection.");
2509
2510 add_com ("tstart", class_trace, trace_start_command,
2511 "Start trace data collection.");
2512
2513 add_com ("passcount", class_trace, trace_pass_command,
2514 "Set the passcount for a tracepoint.\n\
2515 The trace will end when the tracepoint has been passed 'count' times.\n\
2516 Usage: passcount COUNT TPNUM, where TPNUM may also be \"all\";\n\
2517 if TPNUM is omitted, passcount refers to the last tracepoint defined.");
2518
2519 add_com ("end", class_trace, end_actions_pseudocommand,
2520 "Ends a list of commands or actions.\n\
2521 Several GDB commands allow you to enter a list of commands or actions.\n\
2522 Entering \"end\" on a line by itself is the normal way to terminate\n\
2523 such a list.\n\n\
2524 Note: the \"end\" command cannot be used at the gdb prompt.");
2525
2526 add_com ("while-stepping", class_trace, while_stepping_pseudocommand,
2527 "Specify single-stepping behavior at a tracepoint.\n\
2528 Argument is number of instructions to trace in single-step mode\n\
2529 following the tracepoint. This command is normally followed by\n\
2530 one or more \"collect\" commands, to specify what to collect\n\
2531 while single-stepping.\n\n\
2532 Note: this command can only be used in a tracepoint \"actions\" list.");
2533
2534 add_com_alias ("ws", "while-stepping", class_alias, 0);
2535 add_com_alias ("stepping", "while-stepping", class_alias, 0);
2536
2537 add_com ("collect", class_trace, collect_pseudocommand,
2538 "Specify one or more data items to be collected at a tracepoint.\n\
2539 Accepts a comma-separated list of (one or more) arguments.\n\
2540 Things that may be collected include registers, variables, plus\n\
2541 the following special arguments:\n\
2542 $regs -- all registers.\n\
2543 $args -- all function arguments.\n\
2544 $locals -- all variables local to the block/function scope.\n\
2545 $(addr,len) -- a literal memory range.\n\
2546 $($reg,addr,len) -- a register-relative literal memory range.\n\n\
2547 Note: this command can only be used in a tracepoint \"actions\" list.");
2548
2549 add_com ("actions", class_trace, trace_actions_command,
2550 "Specify the actions to be taken at a tracepoint.\n\
2551 Tracepoint actions may include collecting of specified data, \n\
2552 single-stepping, or enabling/disabling other tracepoints, \n\
2553 depending on target's capabilities.");
2554
2555 add_cmd ("tracepoints", class_trace, delete_trace_command,
2556 "Delete specified tracepoints.\n\
2557 Arguments are tracepoint numbers, separated by spaces.\n\
2558 No argument means delete all tracepoints.",
2559 &deletelist);
2560
2561 add_cmd ("tracepoints", class_trace, disable_trace_command,
2562 "Disable specified tracepoints.\n\
2563 Arguments are tracepoint numbers, separated by spaces.\n\
2564 No argument means disable all tracepoints.",
2565 &disablelist);
2566
2567 add_cmd ("tracepoints", class_trace, enable_trace_command,
2568 "Enable specified tracepoints.\n\
2569 Arguments are tracepoint numbers, separated by spaces.\n\
2570 No argument means enable all tracepoints.",
2571 &enablelist);
2572
2573 add_com ("trace", class_trace, trace_command,
2574 "Set a tracepoint at a specified line or function or address.\n\
2575 Argument may be a line number, function name, or '*' plus an address.\n\
2576 For a line number or function, trace at the start of its code.\n\
2577 If an address is specified, trace at that exact address.\n\n\
2578 Do \"help tracepoints\" for info on other tracepoint commands.");
2579
2580 add_com_alias ("tp", "trace", class_alias, 0);
2581 add_com_alias ("tr", "trace", class_alias, 1);
2582 add_com_alias ("tra", "trace", class_alias, 1);
2583 add_com_alias ("trac", "trace", class_alias, 1);
2584 }
2585
This page took 0.084737 seconds and 4 git commands to generate.