1 /* Tracing functionality for remote targets in custom GDB protocol
2 Copyright 1997 Free Software Foundation, Inc.
4 This file is part of GDB.
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.
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.
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. */
23 #include "tracepoint.h"
25 #include "expression.h"
30 #include "gdb_string.h"
32 /* readline include files */
36 /* readline defines this. */
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));
49 /* If this definition isn't overridden by the header files, assume
50 that isatty and fileno exist on this system. */
52 #define ISATTY(FP) (isatty (fileno (FP)))
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.
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.
81 /* ======= Important global variables: ======= */
83 /* Chain of all tracepoints defined. */
84 struct tracepoint
*tracepoint_chain
;
86 /* Number of last tracepoint made. */
87 static int tracepoint_count
;
89 /* Number of last traceframe collected. */
90 static int traceframe_number
;
92 /* Tracepoint for last traceframe collected. */
93 static int tracepoint_number
;
95 /* Symbol for function for last traceframe collected */
96 static struct symbol
*traceframe_fun
;
98 /* Symtab and line for last traceframe collected */
99 static struct symtab_and_line traceframe_sal
;
101 /* Tracing command lists */
102 static struct cmd_list_element
*tfindlist
;
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));
125 /* Utility: returns true if "target remote" */
129 if (current_target
.to_shortname
&&
130 strcmp (current_target
.to_shortname
, "remote") == 0)
136 /* Utility: generate error from an incoming stub packet. */
142 return; /* not an error msg */
145 case '1': /* malformed packet error */
146 if (*++buf
== '0') /* general case: */
147 error ("tracepoint.c: error in outgoing packet.");
149 error ("tracepoint.c: error in outgoing packet at field #%d.",
150 strtol (buf
, NULL
, 16));
152 error ("trace API error 0x%s.", ++buf
);
154 error ("Target returns error code '%s'.", buf
);
158 /* Utility: wait for reply from stub, while accepting "O" packets */
160 remote_get_noisy_reply (buf
)
163 do /* loop on reply from remote stub */
167 error ("Target does not support this command.");
168 else if (buf
[0] == 'E')
170 else if (buf
[0] == 'O' &&
172 remote_console_output (buf
+ 1); /* 'O' message from stub */
174 return buf
; /* here's the actual reply */
178 /* Set tracepoint count to NUM. */
180 set_tracepoint_count (num
)
183 tracepoint_count
= num
;
184 set_internalvar (lookup_internalvar ("tpnum"),
185 value_from_longest (builtin_type_int
, (LONGEST
) num
));
188 /* Set traceframe number to NUM. */
190 set_traceframe_num (num
)
193 traceframe_number
= num
;
194 set_internalvar (lookup_internalvar ("trace_frame"),
195 value_from_longest (builtin_type_int
, (LONGEST
) num
));
198 /* Set tracepoint number to NUM. */
200 set_tracepoint_num (num
)
203 tracepoint_number
= num
;
204 set_internalvar (lookup_internalvar ("tracepoint"),
205 value_from_longest (builtin_type_int
, (LONGEST
) num
));
208 /* Set externally visible debug variables for querying/printing
209 the traceframe context (line, function, file) */
212 set_traceframe_context (trace_pc
)
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
;
221 if (charstar
== (struct type
*) NULL
)
222 charstar
= lookup_pointer_type (builtin_type_char
);
224 if (trace_pc
== -1) /* cease debugging any trace buffers */
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));
238 /* save as globals for internal use */
239 traceframe_sal
= find_pc_line (trace_pc
, 0);
240 traceframe_fun
= find_pc_function (trace_pc
);
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
));
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));
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
),
264 func_val
->modifiable
= 0;
265 set_internalvar (lookup_internalvar ("trace_func"), func_val
);
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));
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
,
285 file_val
->modifiable
= 0;
286 set_internalvar (lookup_internalvar ("trace_file"), file_val
);
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.
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! */
299 static struct tracepoint
*
300 set_raw_tracepoint (sal
)
301 struct symtab_and_line sal
;
303 register struct tracepoint
*t
, *tc
;
304 struct cleanup
*old_chain
;
306 t
= (struct tracepoint
*) xmalloc (sizeof (struct tracepoint
));
307 old_chain
= make_cleanup (free
, t
);
308 memset (t
, 0, sizeof (*t
));
310 if (sal
.symtab
== NULL
)
311 t
->source_file
= NULL
;
316 t
->source_file
= (char *) xmalloc (strlen (sal
.symtab
->filename
) +
317 strlen (sal
.symtab
->dirname
) + 2);
319 strcpy (t
->source_file
, sal
.symtab
->dirname
);
323 if (*(--p
) != '/') /* Will this work on Windows? */
324 strcat (t
->source_file
, "/");
325 strcat (t
->source_file
, sal
.symtab
->filename
);
328 t
->language
= current_language
->la_language
;
329 t
->input_radix
= input_radix
;
330 t
->line_number
= sal
.line
;
331 t
->enabled
= enabled
;
335 t
->addr_string
= NULL
;
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. */
341 tc
= tracepoint_chain
;
343 tracepoint_chain
= t
;
350 discard_cleanups (old_chain
);
354 /* Set a tracepoint according to ARG (function, linenum or *address) */
356 trace_command (arg
, from_tty
)
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;
368 error ("trace command requires an argument");
370 if (from_tty
&& info_verbose
)
371 printf_filtered ("TRACE %s\n", arg
);
379 sals
= decode_line_1 (&arg
, 1, (struct symtab
*)NULL
, 0, &canonical
);
382 return; /* ??? Presumably decode_line_1 has already warned? */
384 /* Resolve all line numbers to PC's */
385 for (i
= 0; i
< sals
.nelts
; i
++)
386 resolve_sal_pc (&sals
.sals
[i
]);
388 /* Now set all the tracepoints. */
389 for (i
= 0; i
< sals
.nelts
; i
++)
393 t
= set_raw_tracepoint (sal
);
394 set_tracepoint_count (tracepoint_count
+ 1);
395 t
->number
= tracepoint_count
;
397 /* If a canonical line spec is needed use that instead of the
399 if (canonical
!= (char **)NULL
&& canonical
[i
] != NULL
)
400 t
->addr_string
= canonical
[i
];
402 t
->addr_string
= savestring (addr_start
, addr_end
- addr_start
);
404 /* Let the UI know of any additions */
405 if (create_tracepoint_hook
)
406 create_tracepoint_hook (t
);
411 printf_filtered ("Multiple tracepoints were set.\n");
412 printf_filtered ("Use 'delete trace' to delete unwanted tracepoints.\n");
416 /* Print information on tracepoint number TPNUM_EXP, or all if omitted. */
419 tracepoints_info (tpnum_exp
, from_tty
)
423 struct tracepoint
*t
;
424 struct action_line
*action
;
425 int found_a_tracepoint
= 0;
426 char wrap_indent
[80];
430 char *i1
= "\t", *i2
= "\t ";
431 char *indent
, *actionline
;;
435 tpnum
= parse_and_eval_address (tpnum_exp
);
438 if (tpnum
== -1 || tpnum
== t
->number
)
440 extern int addressprint
; /* print machine addresses? */
442 if (!found_a_tracepoint
++)
444 printf_filtered ("Num Enb ");
446 printf_filtered ("Address ");
447 printf_filtered ("PassC StepC What\n");
449 strcpy (wrap_indent
, " ");
451 strcat (wrap_indent
, " ");
453 printf_filtered ("%-3d %-3s ", t
->number
,
454 t
->enabled
== enabled
? "y" : "n");
456 printf_filtered ("%s ",
457 local_hex_string_custom ((unsigned long) t
->address
,
459 printf_filtered ("%-5d %-5d ", t
->pass_count
, t
->step_count
);
463 sym
= find_pc_function (t
->address
);
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
);
471 fputs_filtered (t
->source_file
, gdb_stdout
);
472 printf_filtered (":%d", t
->line_number
);
475 print_address_symbolic (t
->address
, gdb_stdout
, demangle
, " ");
477 printf_filtered ("\n");
480 printf_filtered (" Actions for tracepoint %d: \n", t
->number
);
482 for (action
= t
->actions
; action
; action
= action
->next
)
485 actionline
= action
->action
;
486 while (isspace(*actionline
))
489 printf_filtered ("%s%s\n", indent
, actionline
);
490 if (0 == strncasecmp (actionline
, "while-stepping", 14))
492 else if (0 == strncasecmp (actionline
, "end", 3))
495 printf_filtered ("\t%s\n", action
->action
);
500 if (!found_a_tracepoint
)
503 printf_filtered ("No tracepoints.\n");
505 printf_filtered ("No tracepoint number %d.\n", tpnum
);
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.
513 enum tracepoint_opcode
520 /* This function implements enable, disable and delete. */
522 tracepoint_operation (t
, from_tty
, opcode
)
523 struct tracepoint
*t
;
525 enum tracepoint_opcode opcode
;
527 struct tracepoint
*t2
;
531 t
->enabled
= enabled
;
532 if (modify_tracepoint_hook
)
533 modify_tracepoint_hook (t
);
536 t
->enabled
= disabled
;
537 if (modify_tracepoint_hook
)
538 modify_tracepoint_hook (t
);
541 if (tracepoint_chain
== t
)
542 tracepoint_chain
= t
->next
;
551 /* Let the UI know of any deletions */
552 if (delete_tracepoint_hook
)
553 delete_tracepoint_hook (t
);
556 free (t
->addr_string
);
558 free (t
->source_file
);
567 /* Utility: parse a tracepoint number and look it up in the list. */
569 get_tracepoint_by_number (arg
)
572 struct tracepoint
*t
;
578 error ("Bad tracepoint argument");
580 if (*arg
== 0 || **arg
== 0) /* empty arg means refer to last tp */
581 tpnum
= tracepoint_count
;
582 else if (**arg
== '$') /* handle convenience variable */
584 /* Make a copy of the name, so we can null-terminate it
585 to pass to lookup_internalvar(). */
587 while (isalnum(*end
) || *end
== '_')
589 copy
= (char *) alloca (end
- *arg
);
590 strncpy (copy
, *arg
+ 1, (end
- *arg
- 1));
591 copy
[end
- *arg
- 1] = '\0';
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
);
599 else /* handle tracepoint number */
601 tpnum
= strtol (*arg
, arg
, 10);
604 if (t
->number
== tpnum
)
608 warning ("No tracepoint number %d.\n", tpnum
);
612 /* Utility: parse a list of tracepoint numbers, and call a func for each. */
614 map_args_over_tracepoints (args
, from_tty
, opcode
)
617 enum tracepoint_opcode opcode
;
619 struct tracepoint
*t
, *tmp
;
623 if (args
== 0 || *args
== 0) /* do them all */
624 ALL_TRACEPOINTS_SAFE (t
, tmp
)
625 tracepoint_operation (t
, from_tty
, opcode
);
629 if (t
= get_tracepoint_by_number (&args
))
630 tracepoint_operation (t
, from_tty
, opcode
);
631 while (*args
== ' ' || *args
== '\t')
636 /* The 'enable trace' command enables tracepoints. Not supported by all targets. */
638 enable_trace_command (args
, from_tty
)
643 map_args_over_tracepoints (args
, from_tty
, enable
);
646 /* The 'disable trace' command enables tracepoints. Not supported by all targets. */
648 disable_trace_command (args
, from_tty
)
653 map_args_over_tracepoints (args
, from_tty
, disable
);
656 /* Remove a tracepoint (or all if no argument) */
658 delete_trace_command (args
, from_tty
)
664 if (!query ("Delete all tracepoints? "))
667 map_args_over_tracepoints (args
, from_tty
, delete);
670 /* Set passcount for tracepoint.
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". */
677 trace_pass_command (args
, from_tty
)
681 struct tracepoint
*t1
= (struct tracepoint
*) -1, *t2
;
684 if (args
== 0 || *args
== 0)
685 error ("PASS command requires an argument (count + optional TP num)");
687 count
= strtoul (args
, &args
, 10); /* count comes first, then TP num */
689 while (*args
&& isspace (*args
))
692 if (*args
&& strncasecmp (args
, "all", 3) == 0)
693 args
+= 3; /* skip special argument "all" */
695 t1
= get_tracepoint_by_number (&args
);
698 return; /* error, bad tracepoint number */
701 if (t1
== (struct tracepoint
*) -1 || t1
== t2
)
703 t2
->pass_count
= count
;
704 if (modify_tracepoint_hook
)
705 modify_tracepoint_hook (t2
);
707 printf_filtered ("Setting tracepoint %d's passcount to %d\n",
712 /* ACTIONS functions: */
714 /* Prototypes for action-parsing utility commands */
715 static void read_actions
PARAMS((struct tracepoint
*));
716 static char *parse_and_eval_memrange
PARAMS ((char *,
722 /* The three functions:
723 collect_pseudocommand,
724 while_stepping_pseudocommand, and
725 end_actions_pseudocommand
726 are placeholders for "commands" that are actually ONLY to be used
727 within a tracepoint action list. If the actual function is ever called,
728 it means that somebody issued the "command" at the top level,
729 which is always an error. */
732 end_actions_pseudocommand (args
, from_tty
)
736 error ("This command cannot be used at the top level.");
740 while_stepping_pseudocommand (args
, from_tty
)
744 error ("This command can only be used in a tracepoint actions list.");
748 collect_pseudocommand (args
, from_tty
)
752 error ("This command can only be used in a tracepoint actions list.");
755 /* Enter a list of actions for a tracepoint. */
757 trace_actions_command (args
, from_tty
)
761 struct tracepoint
*t
;
764 char *end_msg
= "End with a line saying just \"end\".";
766 if (t
= get_tracepoint_by_number (&args
))
768 sprintf (tmpbuf
, "Enter actions for tracepoint %d, one per line.",
773 if (readline_begin_hook
)
774 (*readline_begin_hook
) ("%s %s\n", tmpbuf
, end_msg
);
775 else if (input_from_terminal_p ())
776 printf_filtered ("%s\n%s\n", tmpbuf
, end_msg
);
782 if (readline_end_hook
)
783 (*readline_end_hook
) ();
785 /* tracepoints_changed () */
787 /* else error, just return; */
798 static enum actionline_type validate_actionline
PARAMS((char **,
799 struct tracepoint
*));
801 /* worker function */
804 struct tracepoint
*t
;
807 char *prompt1
= "> ", *prompt2
= " > ";
808 char *prompt
= prompt1
;
809 enum actionline_type linetype
;
810 extern FILE *instream
;
811 struct action_line
*next
= NULL
, *temp
;
812 struct cleanup
*old_chain
;
814 /* Control-C quits instantly if typed while in this loop
815 since it should not wait until the user types a newline. */
819 signal (STOP_SIGNAL
, stop_sig
);
821 old_chain
= make_cleanup (free_actions
, (void *) t
);
824 /* Make sure that all output has been output. Some machines may let
825 you get away with leaving out some of the gdb_flush, but not all. */
827 gdb_flush (gdb_stdout
);
828 gdb_flush (gdb_stderr
);
830 if (readline_hook
&& instream
== NULL
)
831 line
= (*readline_hook
) (prompt
);
832 else if (instream
== stdin
&& ISATTY (instream
))
834 line
= readline (prompt
);
835 if (line
&& *line
) /* add it to command history */
839 line
= gdb_readline (0);
841 linetype
= validate_actionline (&line
, t
);
842 if (linetype
== BADLINE
)
843 continue; /* already warned -- collect another line */
845 temp
= xmalloc (sizeof (struct action_line
));
849 if (next
== NULL
) /* first action for this tracepoint? */
850 t
->actions
= next
= temp
;
857 if (linetype
== STEPPING
) /* begin "while-stepping" */
858 if (prompt
== prompt2
)
860 warning ("Already processing 'while-stepping'");
864 prompt
= prompt2
; /* change prompt for stepping actions */
865 else if (linetype
== END
)
866 if (prompt
== prompt2
)
867 prompt
= prompt1
; /* end of single-stepping actions */
869 break; /* end of actions */
873 signal (STOP_SIGNAL
, SIG_DFL
);
876 discard_cleanups (old_chain
);
879 /* worker function */
880 static enum actionline_type
881 validate_actionline (line
, t
)
883 struct tracepoint
*t
;
885 struct cmd_list_element
*c
;
886 struct expression
*exp
;
887 value_ptr temp
, temp2
;
890 for (p
= *line
; isspace (*p
); )
893 /* symbol lookup etc. */
894 if (*p
== '\0') /* empty line: just prompt for another line. */
897 if (*p
== '#') /* comment line */
900 c
= lookup_cmd (&p
, cmdlist
, "", -1, 1);
903 warning ("'%s' is not an action that I know, or is ambiguous.", p
);
907 if (c
->function
.cfunc
== collect_pseudocommand
)
909 do { /* repeat over a comma-separated list */
913 if (*p
== '$') /* look for special pseudo-symbols */
916 bfd_signed_vma offset
;
918 if ((0 == strncasecmp ("reg", p
+ 1, 3)) ||
919 (0 == strncasecmp ("arg", p
+ 1, 3)) ||
920 (0 == strncasecmp ("loc", p
+ 1, 3)))
923 else if (p
[1] == '(') /* literal memrange */
925 char *temp
, *newline
;
927 newline
= malloc (strlen (*line
) + 32);
928 strcpy (newline
, *line
);
929 newline
[p
- *line
] = '\0';
930 /* newline is now a copy of line, up to "p" (the memrange) */
931 temp
= parse_and_eval_memrange (p
, t
->address
,
932 &typecode
, &offset
, &size
) + 1;
933 /* now compose the memrange as a literal value */
935 sprintf (newline
+ strlen (newline
),
939 sprintf (newline
+ strlen (newline
),
941 reg_names
[typecode
], offset
, size
);
942 /* now add the remainder of the old line to the new one */
943 p
= newline
+ strlen (newline
);
945 strcat (newline
, temp
);
952 exp
= parse_exp_1 (&p
, block_for_pc (t
->address
), 1);
954 if (exp
->elts
[0].opcode
!= OP_VAR_VALUE
&&
955 exp
->elts
[0].opcode
!= UNOP_MEMVAL
&&
956 /*exp->elts[0].opcode != OP_LONG && */
957 /*exp->elts[0].opcode != UNOP_CAST && */
958 exp
->elts
[0].opcode
!= OP_REGISTER
)
960 warning ("collect requires a variable or register name.\n");
963 if (exp
->elts
[0].opcode
== OP_VAR_VALUE
)
964 if (SYMBOL_CLASS (exp
->elts
[2].symbol
) == LOC_CONST
)
966 warning ("%s is constant (value %d): will not be collected.",
967 SYMBOL_NAME (exp
->elts
[2].symbol
),
968 SYMBOL_VALUE (exp
->elts
[2].symbol
));
971 else if (SYMBOL_CLASS (exp
->elts
[2].symbol
) == LOC_OPTIMIZED_OUT
)
973 warning ("%s is optimized away and cannot be collected.",
974 SYMBOL_NAME (exp
->elts
[2].symbol
));
978 } while (p
&& *p
++ == ',');
981 else if (c
->function
.cfunc
== while_stepping_pseudocommand
)
983 char *steparg
; /* in case warning is necessary */
991 t
->step_count
= strtol (p
, &p
, 0);
992 if (t
->step_count
== 0)
994 warning ("'%s' evaluates to zero -- command ignored.");
1002 else if (c
->function
.cfunc
== end_actions_pseudocommand
)
1006 warning ("'%s' is not a supported tracepoint action.", *line
);
1011 /* worker function */
1014 struct tracepoint
*t
;
1016 struct action_line
*line
, *next
;
1018 for (line
= t
->actions
; line
; line
= next
)
1022 free (line
->action
);
1029 int type
; /* 0 for absolute memory range, else basereg number */
1030 bfd_signed_vma start
;
1034 struct collection_list
{
1035 unsigned char regs_mask
[8]; /* room for up to 256 regs */
1038 struct memrange
*list
;
1039 } tracepoint_list
, stepping_list
;
1041 /* MEMRANGE functions: */
1043 /* parse a memrange spec from command input */
1045 parse_and_eval_memrange (arg
, addr
, typecode
, offset
, size
)
1048 long *typecode
, *size
;
1049 bfd_signed_vma
*offset
;
1052 struct expression
*exp
;
1055 if (*arg
++ != '$' || *arg
++ != '(')
1056 error ("Internal: bad argument to parse_and_eval_memrange: %s", start
);
1058 if (*arg
== '$') /* register for relative memrange? */
1060 exp
= parse_exp_1 (&arg
, block_for_pc (addr
), 1);
1061 if (exp
->elts
[0].opcode
!= OP_REGISTER
)
1062 error ("Bad register operand for memrange: %s", start
);
1064 error ("missing comma for memrange: %s", start
);
1065 *typecode
= exp
->elts
[1].longconst
;
1068 *typecode
= -1; /* absolute memrange; */
1070 exp
= parse_exp_1 (&arg
, 0, 1);
1071 *offset
= value_as_pointer (evaluate_expression (exp
));
1073 /* now parse the size */
1075 error ("missing comma for memrange: %s", start
);
1077 exp
= parse_exp_1 (&arg
, 0, 0);
1078 *size
= value_as_long (evaluate_expression (exp
));
1081 printf_filtered ("Collecting memrange: (0x%x,0x%x,0x%x)\n",
1082 *typecode
, *offset
, *size
);
1087 /* compare memranges for qsort */
1090 struct memrange
*a
, *b
;
1092 if (a
->type
< b
->type
) return -1;
1093 if (a
->type
> b
->type
) return 1;
1096 if ((bfd_vma
) a
->start
< (bfd_vma
) b
->start
) return -1;
1097 if ((bfd_vma
) a
->start
> (bfd_vma
) b
->start
) return 1;
1101 if (a
->start
< b
->start
) return -1;
1102 if (a
->start
> b
->start
) return 1;
1107 /* Sort the memrange list using qsort, and merge adjacent memranges */
1109 memrange_sortmerge (memranges
)
1110 struct collection_list
*memranges
;
1114 qsort (memranges
->list
, memranges
->next_memrange
,
1115 sizeof (struct memrange
), memrange_cmp
);
1116 if (memranges
->next_memrange
> 0)
1118 for (a
= 0, b
= 1; b
< memranges
->next_memrange
; b
++)
1120 if (memranges
->list
[a
].type
== memranges
->list
[b
].type
&&
1121 memranges
->list
[b
].start
- memranges
->list
[a
].end
<=
1122 MAX_REGISTER_VIRTUAL_SIZE
)
1124 /* memrange b starts before memrange a ends; merge them. */
1125 if (memranges
->list
[b
].end
> memranges
->list
[a
].end
)
1126 memranges
->list
[a
].end
= memranges
->list
[b
].end
;
1127 continue; /* next b, same a */
1131 memcpy (&memranges
->list
[a
], &memranges
->list
[b
],
1132 sizeof (struct memrange
));
1134 memranges
->next_memrange
= a
+ 1;
1138 /* Add a register to a collection list */
1140 add_register (collection
, regno
)
1141 struct collection_list
*collection
;
1142 unsigned long regno
;
1145 printf_filtered ("collect register %d\n", regno
);
1146 if (regno
> (8 * sizeof (collection
->regs_mask
)))
1147 error ("Internal: register number %d too large for tracepoint",
1149 collection
->regs_mask
[regno
/ 8] |= 1 << (regno
% 8);
1152 /* Add a memrange to a collection list */
1154 add_memrange (memranges
, type
, base
, len
)
1155 struct collection_list
*memranges
;
1157 bfd_signed_vma base
;
1161 printf_filtered ("(%d,0x%x,%d)\n", type
, base
, len
);
1162 /* type: 0 == memory, n == basereg */
1163 memranges
->list
[memranges
->next_memrange
].type
= type
;
1164 /* base: addr if memory, offset if reg relative. */
1165 memranges
->list
[memranges
->next_memrange
].start
= base
;
1166 /* len: we actually save end (base + len) for convenience */
1167 memranges
->list
[memranges
->next_memrange
].end
= base
+ len
;
1168 memranges
->next_memrange
++;
1169 if (memranges
->next_memrange
>= memranges
->listsize
)
1171 memranges
->listsize
*= 2;
1172 memranges
->list
= xrealloc (memranges
->list
,
1173 memranges
->listsize
);
1176 if (type
!= -1) /* better collect the base register! */
1177 add_register (memranges
, type
);
1180 /* Add a symbol to a collection list */
1182 collect_symbol (collect
, sym
)
1183 struct collection_list
*collect
;
1188 bfd_signed_vma offset
;
1190 len
= TYPE_LENGTH (check_typedef (SYMBOL_TYPE (sym
)));
1191 switch (SYMBOL_CLASS (sym
)) {
1193 printf_filtered ("%s: don't know symbol class %d\n",
1194 SYMBOL_NAME (sym
), SYMBOL_CLASS (sym
));
1197 printf_filtered ("%s is constant, value is %d: will not be collected.\n",
1198 SYMBOL_NAME (sym
), SYMBOL_VALUE (sym
));
1201 offset
= SYMBOL_VALUE_ADDRESS (sym
);
1203 printf_filtered ("LOC_STATIC %s: collect %d bytes at 0x%08x\n",
1204 SYMBOL_NAME (sym
), len
, offset
);
1205 add_memrange (collect
, -1, offset
, len
); /* 0 == memory */
1209 reg
= SYMBOL_VALUE (sym
);
1211 printf_filtered ("LOC_REG[parm] %s: ", SYMBOL_NAME (sym
));
1212 add_register (collect
, reg
);
1216 printf_filtered ("Sorry, don't know how to do LOC_ARGs yet.\n");
1217 printf_filtered (" (will not collect %s)\n",
1220 case LOC_REGPARM_ADDR
:
1221 reg
= SYMBOL_VALUE (sym
);
1225 printf_filtered ("LOC_REGPARM_ADDR %s: Collect %d bytes at offset %d from reg %d\n",
1226 SYMBOL_NAME (sym
), len
, offset
, reg
);
1228 add_memrange (collect
, reg
, offset
, len
);
1232 offset
= SYMBOL_VALUE (sym
);
1236 printf_filtered ("LOC_LOCAL %s: Collect %d bytes at offset %d from frame ptr reg %d\n",
1237 SYMBOL_NAME (sym
), len
, offset
, reg
);
1239 add_memrange (collect
, reg
, offset
, len
);
1242 case LOC_BASEREG_ARG
:
1243 reg
= SYMBOL_BASEREG (sym
);
1244 offset
= SYMBOL_VALUE (sym
);
1247 printf_filtered ("LOC_BASEREG %s: collect %d bytes at offset %d from basereg %d\n",
1248 SYMBOL_NAME (sym
), len
, offset
, reg
);
1250 add_memrange (collect
, reg
, offset
, len
);
1252 case LOC_UNRESOLVED
:
1253 printf_filtered ("Don't know LOC_UNRESOLVED %s\n", SYMBOL_NAME (sym
));
1255 case LOC_OPTIMIZED_OUT
:
1256 printf_filtered ("%s has been optimized out of existance.\n",
1262 /* Add all locals (or args) symbols to collection list */
1264 add_local_symbols (collect
, pc
, type
)
1265 struct collection_list
*collect
;
1270 struct block
*block
;
1271 int i
, nsyms
, count
= 0;
1273 block
= block_for_pc (pc
);
1276 nsyms
= BLOCK_NSYMS (block
);
1277 for (i
= 0; i
< nsyms
; i
++)
1279 sym
= BLOCK_SYM (block
, i
);
1280 switch (SYMBOL_CLASS (sym
)) {
1285 if (type
== 'L') /* collecting Locals */
1288 collect_symbol (collect
, sym
);
1295 case LOC_REGPARM_ADDR
:
1296 case LOC_BASEREG_ARG
:
1297 if (type
== 'A') /* collecting Arguments */
1300 collect_symbol (collect
, sym
);
1304 if (BLOCK_FUNCTION (block
))
1307 block
= BLOCK_SUPERBLOCK (block
);
1310 warning ("No %s found in scope.", type
== 'L' ? "locals" : "args");
1313 /* worker function */
1315 clear_collection_list (list
)
1316 struct collection_list
*list
;
1318 list
->next_memrange
= 0;
1319 memset (list
->regs_mask
, 0, sizeof (list
->regs_mask
));
1322 /* reduce a collection list to string form (for gdb protocol) */
1324 stringify_collection_list (list
, string
)
1325 struct collection_list
*list
;
1331 for (i
= sizeof (list
->regs_mask
) - 1; i
> 0; i
--)
1332 if (list
->regs_mask
[i
] != 0) /* skip leading zeroes in regs_mask */
1334 if (list
->regs_mask
[i
] != 0) /* prepare to send regs_mask to the stub */
1337 printf_filtered ("\nCollecting registers (mask): 0x");
1342 printf_filtered ("%02X", list
->regs_mask
[i
]);
1343 sprintf (end
, "%02X", list
->regs_mask
[i
]);
1348 printf_filtered ("\n");
1349 if (list
->next_memrange
> 0 && info_verbose
)
1350 printf_filtered ("Collecting memranges: \n");
1351 for (i
= 0; i
< list
->next_memrange
; i
++)
1354 printf_filtered ("(%d, 0x%x, %d)\n",
1356 list
->list
[i
].start
,
1357 list
->list
[i
].end
- list
->list
[i
].start
);
1358 sprintf (end
, "M%X,%X,%X",
1360 list
->list
[i
].start
,
1361 list
->list
[i
].end
- list
->list
[i
].start
);
1362 end
+= strlen (end
);
1370 /* render all actions into gdb protocol */
1372 encode_actions (t
, tdp_actions
, step_count
, stepping_actions
)
1373 struct tracepoint
*t
;
1375 unsigned long *step_count
;
1376 char **stepping_actions
;
1378 static char tdp_buff
[2048], step_buff
[2048];
1380 struct expression
*exp
;
1381 struct action_line
*action
;
1382 bfd_signed_vma offset
;
1385 struct collection_list
*collect
;
1386 struct cmd_list_element
*cmd
;
1388 clear_collection_list (&tracepoint_list
);
1389 clear_collection_list (&stepping_list
);
1390 collect
= &tracepoint_list
;
1392 *tdp_actions
= NULL
;
1393 *stepping_actions
= NULL
;
1395 for (action
= t
->actions
; action
; action
= action
->next
)
1397 action_exp
= action
->action
;
1398 while (isspace (*action_exp
))
1401 if (*action_exp
== '#') /* comment line */
1404 cmd
= lookup_cmd (&action_exp
, cmdlist
, "", -1, 1);
1406 error ("Bad action list item: %s", action_exp
);
1408 if (cmd
->function
.cfunc
== collect_pseudocommand
)
1410 do { /* repeat over a comma-separated list */
1411 while (isspace (*action_exp
))
1414 if (0 == strncasecmp ("$reg", action_exp
, 4))
1416 for (i
= 0; i
< NUM_REGS
; i
++)
1417 add_register (collect
, i
);
1418 action_exp
= strchr (action_exp
, ','); /* more? */
1420 else if (0 == strncasecmp ("$arg", action_exp
, 4))
1422 add_local_symbols (collect
, t
->address
, 'A');
1423 action_exp
= strchr (action_exp
, ','); /* more? */
1425 else if (0 == strncasecmp ("$loc", action_exp
, 4))
1427 add_local_symbols (collect
, t
->address
, 'L');
1428 action_exp
= strchr (action_exp
, ','); /* more? */
1430 else if (action_exp
[0] == '$' &&
1431 action_exp
[1] == '(') /* literal memrange */
1433 long typecode
, size
;
1434 bfd_signed_vma offset
;
1436 action_exp
= parse_and_eval_memrange (action_exp
,
1441 add_memrange (collect
, typecode
, offset
, size
);
1445 unsigned long addr
, len
;
1447 exp
= parse_exp_1 (&action_exp
, block_for_pc (t
->address
), 1);
1448 switch (exp
->elts
[0].opcode
) {
1450 i
= exp
->elts
[1].longconst
;
1452 printf_filtered ("OP_REGISTER: ");
1453 add_register (collect
, i
);
1457 /* safe because we know it's a simple expression */
1458 tempval
= evaluate_expression (exp
);
1459 addr
= VALUE_ADDRESS (tempval
) + VALUE_OFFSET (tempval
);
1460 len
= TYPE_LENGTH (check_typedef (exp
->elts
[1].type
));
1461 add_memrange (collect
, -1, addr
, len
);
1465 collect_symbol (collect
, exp
->elts
[2].symbol
);
1469 addr
= exp
->elts
[2].longconst
;
1470 if (*action_exp
== ':')
1472 exp
= parse_exp_1 (&action_exp
,
1473 block_for_pc (t
->address
),
1475 if (exp
->elts
[0].opcode
== OP_LONG
)
1476 len
= exp
->elts
[2].longconst
;
1478 error ("length field requires a literal long const");
1483 add_memrange (collect
, -1, addr
, len
);
1488 } while (action_exp
&& *action_exp
++ == ',');
1490 else if (cmd
->function
.cfunc
== while_stepping_pseudocommand
)
1492 collect
= &stepping_list
;
1494 else if (cmd
->function
.cfunc
== end_actions_pseudocommand
)
1496 if (collect
== &stepping_list
) /* end stepping actions */
1497 collect
= &tracepoint_list
;
1499 break; /* end tracepoint actions */
1502 memrange_sortmerge (&tracepoint_list
);
1503 memrange_sortmerge (&stepping_list
);
1505 *tdp_actions
= stringify_collection_list (&tracepoint_list
, &tdp_buff
);
1506 *stepping_actions
= stringify_collection_list (&stepping_list
, &step_buff
);
1509 static char target_buf
[2048];
1513 Tell target to lear any previous trace experiment.
1514 Walk the list of tracepoints, and send them (and their actions)
1515 to the target. If no errors,
1516 Tell target to start a new trace experiment. */
1519 trace_start_command (args
, from_tty
)
1522 { /* STUB_COMM MOSTLY_IMPLEMENTED */
1523 struct tracepoint
*t
;
1526 char *stepping_actions
;
1527 unsigned long step_count
;
1529 dont_repeat (); /* like "run", dangerous to repeat accidentally */
1531 if (target_is_remote ())
1534 remote_get_noisy_reply (target_buf
);
1535 if (strcmp (target_buf
, "OK"))
1536 error ("Target does not support this command.");
1540 int ss_count
; /* if actions include singlestepping */
1541 int disable_mask
; /* ??? */
1542 int enable_mask
; /* ??? */
1544 sprintf (buf
, "QTDP:%x:%x:%c:%x:%x", t
->number
, t
->address
,
1545 t
->enabled
== enabled
? 'E' : 'D',
1546 t
->step_count
, t
->pass_count
);
1549 encode_actions (t
, &tdp_actions
, &step_count
, &stepping_actions
);
1550 /* do_single_steps (t); */
1553 if (strlen (buf
) + strlen (tdp_actions
) >= sizeof (buf
))
1554 error ("Actions for tracepoint %d too complex; please simplify.",
1556 strcat (buf
, tdp_actions
);
1558 if (stepping_actions
)
1561 if (strlen (buf
) + strlen (stepping_actions
) >= sizeof (buf
))
1562 error ("Actions for tracepoint %d too complex; please simplify.",
1564 strcat (buf
, stepping_actions
);
1568 remote_get_noisy_reply (target_buf
);
1569 if (strcmp (target_buf
, "OK"))
1570 error ("Target does not support tracepoints.");
1573 remote_get_noisy_reply (target_buf
);
1574 if (strcmp (target_buf
, "OK"))
1575 error ("Bogus reply from target: %s", target_buf
);
1576 set_traceframe_num (-1); /* all old traceframes invalidated */
1577 set_tracepoint_num (-1);
1578 set_traceframe_context(-1);
1579 trace_running_p
= 1;
1582 printf_filtered ("Trace can only be run on remote targets.\n");
1587 trace_stop_command (args
, from_tty
)
1590 { /* STUB_COMM IS_IMPLEMENTED */
1591 if (target_is_remote ())
1594 remote_get_noisy_reply (target_buf
);
1595 if (strcmp (target_buf
, "OK"))
1596 error ("Bogus reply from target: %s", target_buf
);
1597 trace_running_p
= 0;
1600 error ("Trace can only be run on remote targets.");
1603 unsigned long trace_running_p
;
1605 /* tstatus command */
1607 trace_status_command (args
, from_tty
)
1610 { /* STUB_COMM IS_IMPLEMENTED */
1611 if (target_is_remote ())
1613 putpkt ("qTStatus");
1614 remote_get_noisy_reply (target_buf
);
1616 if (target_buf
[0] != 'T' ||
1617 (target_buf
[1] != '0' && target_buf
[1] != '1'))
1618 error ("Bogus reply from target: %s", target_buf
);
1620 /* exported for use by the GUI */
1621 trace_running_p
= (target_buf
[1] == '1');
1624 error ("Trace can only be run on remote targets.");
1627 /* Worker function for the various flavors of the tfind command */
1629 finish_tfind_command (msg
, from_tty
)
1633 int target_frameno
= -1, target_tracept
= -1;
1634 CORE_ADDR old_frame_addr
;
1635 struct symbol
*old_func
;
1638 old_frame_addr
= FRAME_FP (get_current_frame ());
1639 old_func
= find_pc_function (read_pc ());
1642 reply
= remote_get_noisy_reply (msg
);
1644 while (reply
&& *reply
)
1647 if ((target_frameno
= strtol (++reply
, &reply
, 16)) == -1)
1649 /* A request for a non-existant trace frame has failed.
1650 Our response will be different, depending on FROM_TTY:
1652 If FROM_TTY is true, meaning that this command was
1653 typed interactively by the user, then give an error
1654 and DO NOT change the state of traceframe_number etc.
1656 However if FROM_TTY is false, meaning that we're either
1657 in a script, a loop, or a user-defined command, then
1658 DON'T give an error, but DO change the state of
1659 traceframe_number etc. to invalid.
1661 The rationalle is that if you typed the command, you
1662 might just have committed a typo or something, and you'd
1663 like to NOT lose your current debugging state. However
1664 if you're in a user-defined command or especially in a
1665 loop, then you need a way to detect that the command
1666 failed WITHOUT aborting. This allows you to write
1667 scripts that search thru the trace buffer until the end,
1668 and then continue on to do something else. */
1671 error ("Target failed to find requested trace frame.");
1675 printf_filtered ("End of trace buffer.\n");
1676 /* The following will not recurse, since it's special-cased */
1677 trace_find_command ("-1", from_tty
);
1678 reply
= NULL
; /* break out of loop,
1679 (avoid recursive nonsense) */
1684 if ((target_tracept
= strtol (++reply
, &reply
, 16)) == -1)
1685 error ("Target failed to find requested trace frame.");
1687 case 'O': /* "OK"? */
1688 if (reply
[1] == 'K' && reply
[2] == '\0')
1691 error ("Bogus reply from target: %s", reply
);
1694 error ("Bogus reply from target: %s", reply
);
1697 flush_cached_frames ();
1698 registers_changed ();
1699 select_frame (get_current_frame (), 0);
1700 set_traceframe_num (target_frameno
);
1701 set_tracepoint_num (target_tracept
);
1702 if (target_frameno
== -1)
1703 set_traceframe_context (-1);
1705 set_traceframe_context (read_pc ());
1711 /* NOTE: in immitation of the step command, try to determine
1712 whether we have made a transition from one function to another.
1713 If so, we'll print the "stack frame" (ie. the new function and
1714 it's arguments) -- otherwise we'll just show the new source line.
1716 This determination is made by checking (1) whether the current
1717 function has changed, and (2) whether the current FP has changed.
1718 Hack: if the FP wasn't collected, either at the current or the
1719 previous frame, assume that the FP has NOT changed. */
1721 if (old_func
== find_pc_function (read_pc ()) &&
1722 (old_frame_addr
== 0 ||
1723 FRAME_FP (get_current_frame ()) == 0 ||
1724 old_frame_addr
== FRAME_FP (get_current_frame ())))
1729 print_stack_frame (selected_frame
, selected_frame_level
, source_only
);
1734 /* trace_find_command takes a trace frame number n,
1735 sends "QTFrame:<n>" to the target,
1736 and accepts a reply that may contain several optional pieces
1737 of information: a frame number, a tracepoint number, and an
1738 indication of whether this is a trap frame or a stepping frame.
1740 The minimal response is just "OK" (which indicates that the
1741 target does not give us a frame number or a tracepoint number).
1742 Instead of that, the target may send us a string containing
1744 F<hexnum> (gives the selected frame number)
1745 T<hexnum> (gives the selected tracepoint number)
1750 trace_find_command (args
, from_tty
)
1753 { /* STUB_COMM PART_IMPLEMENTED */
1754 /* this should only be called with a numeric argument */
1756 int target_frameno
= -1, target_tracept
= -1, target_stepfrm
= 0;
1759 if (target_is_remote ())
1761 if (args
== 0 || *args
== 0)
1762 { /* TFIND with no args means find NEXT trace frame. */
1763 if (traceframe_number
== -1)
1764 frameno
= 0; /* "next" is first one */
1766 frameno
= traceframe_number
+ 1;
1768 else if (0 == strcmp (args
, "-"))
1770 if (traceframe_number
== -1)
1771 error ("not debugging trace buffer");
1772 else if (from_tty
&& traceframe_number
== 0)
1773 error ("already at start of trace buffer");
1775 frameno
= traceframe_number
- 1;
1778 frameno
= parse_and_eval_address (args
);
1780 sprintf (target_buf
, "QTFrame:%x", frameno
);
1782 putpkt (target_buf
);
1783 tmp
= remote_get_noisy_reply (target_buf
);
1785 if (frameno
== -1) /* end trace debugging */
1786 { /* hopefully the stub has complied! */
1787 if (0 != strcmp (tmp
, "OK"))
1788 error ("Bogus response from target: %s", tmp
);
1790 finish_tfind_command (NULL
, from_tty
);
1793 finish_tfind_command (tmp
, from_tty
);
1795 finish_tfind_command (target_buf
, from_tty
);
1799 error ("Trace can only be run on remote targets.");
1804 trace_find_end_command (args
, from_tty
)
1808 trace_find_command ("-1", from_tty
);
1813 trace_find_none_command (args
, from_tty
)
1817 trace_find_command ("-1", from_tty
);
1822 trace_find_start_command (args
, from_tty
)
1826 trace_find_command ("0", from_tty
);
1829 /* tfind pc command */
1831 trace_find_pc_command (args
, from_tty
)
1834 { /* STUB_COMM PART_IMPLEMENTED */
1839 if (target_is_remote ())
1841 if (args
== 0 || *args
== 0)
1842 pc
= read_pc (); /* default is current pc */
1844 pc
= parse_and_eval_address (args
);
1846 sprintf (target_buf
, "QTFrame:pc:%x", pc
);
1848 putpkt (target_buf
);
1849 tmp
= remote_get_noisy_reply (target_buf
);
1851 finish_tfind_command (tmp
, from_tty
);
1853 finish_tfind_command (target_buf
, from_tty
);
1857 error ("Trace can only be run on remote targets.");
1860 /* tfind tracepoint command */
1862 trace_find_tracepoint_command (args
, from_tty
)
1865 { /* STUB_COMM PART_IMPLEMENTED */
1866 int target_frameno
, tdp
;
1869 if (target_is_remote ())
1871 if (args
== 0 || *args
== 0)
1872 if (tracepoint_number
== -1)
1873 error ("No current tracepoint -- please supply an argument.");
1875 tdp
= tracepoint_number
; /* default is current TDP */
1877 tdp
= parse_and_eval_address (args
);
1879 sprintf (target_buf
, "QTFrame:tdp:%x", tdp
);
1881 putpkt (target_buf
);
1882 tmp
= remote_get_noisy_reply (target_buf
);
1884 finish_tfind_command (tmp
, from_tty
);
1886 finish_tfind_command (target_buf
, from_tty
);
1890 error ("Trace can only be run on remote targets.");
1893 /* TFIND LINE command:
1895 This command will take a sourceline for argument, just like BREAK
1896 or TRACE (ie. anything that "decode_line_1" can handle).
1898 With no argument, this command will find the next trace frame
1899 corresponding to a source line OTHER THAN THE CURRENT ONE. */
1902 trace_find_line_command (args
, from_tty
)
1905 { /* STUB_COMM PART_IMPLEMENTED */
1906 static CORE_ADDR start_pc
, end_pc
;
1907 struct symtabs_and_lines sals
;
1908 struct symtab_and_line sal
;
1911 struct cleanup
*old_chain
;
1913 if (target_is_remote ())
1915 if (args
== 0 || *args
== 0)
1917 sal
= find_pc_line ((get_current_frame ())->pc
, 0);
1919 sals
.sals
= (struct symtab_and_line
*)
1920 xmalloc (sizeof (struct symtab_and_line
));
1925 sals
= decode_line_spec (args
, 1);
1929 old_chain
= make_cleanup (free
, sals
.sals
);
1930 if (sal
.symtab
== 0)
1932 printf_filtered ("TFIND: No line number information available");
1935 /* This is useful for "info line *0x7f34". If we can't tell the
1936 user about a source line, at least let them have the symbolic
1938 printf_filtered (" for address ");
1940 print_address (sal
.pc
, gdb_stdout
);
1941 printf_filtered (";\n -- will attempt to find by PC. \n");
1945 printf_filtered (".\n");
1946 return; /* no line, no PC; what can we do? */
1949 else if (sal
.line
> 0
1950 && find_line_pc_range (sal
, &start_pc
, &end_pc
))
1952 if (start_pc
== end_pc
)
1954 printf_filtered ("Line %d of \"%s\"",
1955 sal
.line
, sal
.symtab
->filename
);
1957 printf_filtered (" is at address ");
1958 print_address (start_pc
, gdb_stdout
);
1960 printf_filtered (" but contains no code.\n");
1961 sal
= find_pc_line (start_pc
, 0);
1963 find_line_pc_range (sal
, &start_pc
, &end_pc
) &&
1965 printf_filtered ("Attempting to find line %d instead.\n",
1968 error ("Cannot find a good line.");
1972 /* Is there any case in which we get here, and have an address
1973 which the user would want to see? If we have debugging symbols
1974 and no line numbers? */
1975 error ("Line number %d is out of range for \"%s\".\n",
1976 sal
.line
, sal
.symtab
->filename
);
1978 if (args
&& *args
) /* find within range of stated line */
1979 sprintf (target_buf
, "QTFrame:range:%x:%x", start_pc
, end_pc
- 1);
1980 else /* find OUTSIDE OF range of CURRENT line */
1981 sprintf (target_buf
, "QTFrame:outside:%x:%x", start_pc
, end_pc
- 1);
1983 putpkt (target_buf
);
1984 tmp
= remote_get_noisy_reply (target_buf
);
1986 finish_tfind_command (tmp
, from_tty
);
1988 finish_tfind_command (target_buf
, from_tty
);
1990 do_cleanups (old_chain
);
1993 error ("Trace can only be run on remote targets.");
1996 /* tfind range command */
1998 trace_find_range_command (args
, from_tty
)
2001 { /* STUB_COMM PART_IMPLEMENTED */
2002 static CORE_ADDR start
, stop
;
2006 if (target_is_remote ())
2008 if (args
== 0 || *args
== 0)
2009 { /* XXX FIXME: what should default behavior be? */
2010 printf_filtered ("Usage: tfind range <startaddr>,<endaddr>\n");
2014 if (0 != (tmp
= strchr (args
, ',' )))
2016 *tmp
++ = '\0'; /* terminate start address */
2017 while (isspace (*tmp
))
2019 start
= parse_and_eval_address (args
);
2020 stop
= parse_and_eval_address (tmp
);
2023 { /* no explicit end address? */
2024 start
= parse_and_eval_address (args
);
2025 stop
= start
+ 1; /* ??? */
2028 sprintf (target_buf
, "QTFrame:range:%x:%x", start
, stop
);
2030 putpkt (target_buf
);
2031 tmp
= remote_get_noisy_reply (target_buf
);
2033 finish_tfind_command (tmp
, from_tty
);
2035 finish_tfind_command (target_buf
, from_tty
);
2039 error ("Trace can only be run on remote targets.");
2042 /* tfind outside command */
2044 trace_find_outside_command (args
, from_tty
)
2047 { /* STUB_COMM PART_IMPLEMENTED */
2048 CORE_ADDR start
, stop
;
2052 if (target_is_remote ())
2054 if (args
== 0 || *args
== 0)
2055 { /* XXX FIXME: what should default behavior be? */
2056 printf_filtered ("Usage: tfind outside <startaddr>,<endaddr>\n");
2060 if (0 != (tmp
= strchr (args
, ',' )))
2062 *tmp
++ = '\0'; /* terminate start address */
2063 while (isspace (*tmp
))
2065 start
= parse_and_eval_address (args
);
2066 stop
= parse_and_eval_address (tmp
);
2069 { /* no explicit end address? */
2070 start
= parse_and_eval_address (args
);
2071 stop
= start
+ 1; /* ??? */
2074 sprintf (target_buf
, "QTFrame:outside:%x:%x", start
, stop
);
2076 putpkt (target_buf
);
2077 tmp
= remote_get_noisy_reply (target_buf
);
2079 finish_tfind_command (tmp
, from_tty
);
2081 finish_tfind_command (target_buf
, from_tty
);
2085 error ("Trace can only be run on remote targets.");
2088 /* save-tracepoints command */
2090 tracepoint_save_command (args
, from_tty
)
2094 struct tracepoint
*tp
;
2095 struct action_line
*line
;
2097 char *i1
= " ", *i2
= " ";
2098 char *indent
, *actionline
;
2100 if (args
== 0 || *args
== 0)
2101 error ("Argument required (file name in which to save tracepoints");
2103 if (tracepoint_chain
== 0)
2105 warning ("save-tracepoints: no tracepoints to save.\n");
2109 if (!(fp
= fopen (args
, "w")))
2110 error ("Unable to open file '%s' for saving tracepoints");
2112 ALL_TRACEPOINTS (tp
)
2114 if (tp
->addr_string
)
2115 fprintf (fp
, "trace %s\n", tp
->addr_string
);
2117 fprintf (fp
, "trace *0x%x\n", tp
->address
);
2120 fprintf (fp
, " passcount %d\n", tp
->pass_count
);
2124 fprintf (fp
, " actions\n");
2126 for (line
= tp
->actions
; line
; line
= line
->next
)
2128 struct cmd_list_element
*cmd
;
2130 actionline
= line
->action
;
2131 while (isspace(*actionline
))
2134 fprintf (fp
, "%s%s\n", indent
, actionline
);
2135 if (*actionline
!= '#') /* skip for comment lines */
2137 cmd
= lookup_cmd (&actionline
, cmdlist
, "", -1, 1);
2139 error ("Bad action list item: %s", actionline
);
2140 if (cmd
->function
.cfunc
== while_stepping_pseudocommand
)
2142 else if (cmd
->function
.cfunc
== end_actions_pseudocommand
)
2150 printf_filtered ("Tracepoints saved to file '%s'.\n", args
);
2154 /* info scope command: list the locals for a scope. */
2156 scope_info (args
, from_tty
)
2160 struct symtab_and_line sal
;
2161 struct symtabs_and_lines sals
;
2163 struct minimal_symbol
*msym
;
2164 struct block
*block
;
2165 char **canonical
, *symname
, *save_args
= args
;
2166 int i
, nsyms
, count
= 0;
2168 if (args
== 0 || *args
== 0)
2169 error ("requires an argument (function, line or *addr) to define a scope");
2171 sals
= decode_line_1 (&args
, 1, NULL
, 0, &canonical
);
2172 if (sals
.nelts
== 0)
2173 return; /* presumably decode_line_1 has already warned */
2175 /* Resolve line numbers to PC */
2176 resolve_sal_pc (&sals
.sals
[0]);
2177 block
= block_for_pc (sals
.sals
[0].pc
);
2181 nsyms
= BLOCK_NSYMS (block
);
2182 for (i
= 0; i
< nsyms
; i
++)
2185 printf_filtered ("Scope for %s:\n", save_args
);
2187 sym
= BLOCK_SYM (block
, i
);
2188 symname
= SYMBOL_NAME (sym
);
2189 if (symname
== NULL
|| *symname
== '\0')
2190 continue; /* probably botched, certainly useless */
2192 printf_filtered ("Symbol %s is ", symname
);
2193 switch (SYMBOL_CLASS (sym
)) {
2195 case LOC_UNDEF
: /* messed up symbol? */
2196 printf_filtered ("a bogus symbol, class %d.\n",
2197 SYMBOL_CLASS (sym
));
2198 count
--; /* don't count this one */
2201 printf_filtered ("a constant with value %d (0x%x)",
2202 SYMBOL_VALUE (sym
), SYMBOL_VALUE (sym
));
2204 case LOC_CONST_BYTES
:
2205 printf_filtered ("constant bytes: ");
2206 if (SYMBOL_TYPE (sym
))
2207 for (i
= 0; i
< TYPE_LENGTH (SYMBOL_TYPE (sym
)); i
++)
2208 fprintf_filtered (gdb_stdout
, " %02x",
2209 (unsigned) SYMBOL_VALUE_BYTES (sym
) [i
]);
2212 printf_filtered ("in static storage at address ");
2213 print_address_numeric (SYMBOL_VALUE_ADDRESS (sym
), 1, gdb_stdout
);
2216 printf_filtered ("a local variable in register $%s",
2217 reg_names
[SYMBOL_VALUE (sym
)]);
2221 printf_filtered ("an argument at stack/frame offset %ld",
2222 SYMBOL_VALUE (sym
));
2225 printf_filtered ("a local variable at frame offset %ld",
2226 SYMBOL_VALUE (sym
));
2229 printf_filtered ("a reference argument at offset %ld",
2230 SYMBOL_VALUE (sym
));
2233 printf_filtered ("an argument in register $%s",
2234 reg_names
[SYMBOL_VALUE (sym
)]);
2236 case LOC_REGPARM_ADDR
:
2237 printf_filtered ("the address of an argument, in register $%s",
2238 reg_names
[SYMBOL_VALUE (sym
)]);
2241 printf_filtered ("a typedef.\n");
2244 printf_filtered ("a label at address ");
2245 print_address_numeric (SYMBOL_VALUE_ADDRESS (sym
), 1, gdb_stdout
);
2248 printf_filtered ("a function at address ");
2249 print_address_numeric (BLOCK_START (SYMBOL_BLOCK_VALUE (sym
)), 1,
2253 printf_filtered ("a variable at offset %d from register $%s",
2255 reg_names
[SYMBOL_BASEREG (sym
)]);
2257 case LOC_BASEREG_ARG
:
2258 printf_filtered ("an argument at offset %d from register $%s",
2260 reg_names
[SYMBOL_BASEREG (sym
)]);
2262 case LOC_UNRESOLVED
:
2263 msym
= lookup_minimal_symbol (SYMBOL_NAME (sym
), NULL
, NULL
);
2265 printf_filtered ("Unresolved Static");
2268 printf_filtered ("static storage at address ");
2269 print_address_numeric (SYMBOL_VALUE_ADDRESS (msym
), 1,
2273 case LOC_OPTIMIZED_OUT
:
2274 printf_filtered ("optimized out.\n");
2277 if (SYMBOL_TYPE (sym
))
2278 printf_filtered (", length %d.\n",
2279 TYPE_LENGTH (check_typedef (SYMBOL_TYPE (sym
))));
2281 if (BLOCK_FUNCTION (block
))
2284 block
= BLOCK_SUPERBLOCK (block
);
2287 printf_filtered ("Scope for %s contains no locals or arguments.\n",
2291 /* worker function (cleanup) */
2293 replace_comma (comma
)
2301 trace_dump_command (args
, from_tty
)
2305 struct tracepoint
*t
;
2306 struct action_line
*action
;
2307 char *action_exp
, *next_comma
;
2308 struct cleanup
*old_cleanups
;
2309 int stepping_actions
= 0;
2310 int stepping_frame
= 0;
2312 if (tracepoint_number
== -1)
2314 warning ("No current trace frame.");
2319 if (t
->number
== tracepoint_number
)
2323 error ("No known tracepoint matches 'current' tracepoint #%d.",
2326 old_cleanups
= make_cleanup (null_cleanup
, NULL
);
2328 printf_filtered ("Data collected at tracepoint %d, trace frame %d:\n",
2329 tracepoint_number
, traceframe_number
);
2331 /* The current frame is a trap frame if the frame PC is equal
2332 to the tracepoint PC. If not, then the current frame was
2333 collected during single-stepping. */
2335 stepping_frame
= (t
->address
!= read_pc());
2337 for (action
= t
->actions
; action
; action
= action
->next
)
2339 struct cmd_list_element
*cmd
;
2341 action_exp
= action
->action
;
2342 while (isspace (*action_exp
))
2345 /* The collection actions to be done while stepping are
2346 bracketed by the commands "while-stepping" and "end". */
2348 if (*action_exp
== '#') /* comment line */
2351 cmd
= lookup_cmd (&action_exp
, cmdlist
, "", -1, 1);
2353 error ("Bad action list item: %s", action_exp
);
2355 if (cmd
->function
.cfunc
== while_stepping_pseudocommand
)
2356 stepping_actions
= 1;
2357 else if (cmd
->function
.cfunc
== end_actions_pseudocommand
)
2358 stepping_actions
= 0;
2359 else if (cmd
->function
.cfunc
== collect_pseudocommand
)
2361 /* Display the collected data.
2362 For the trap frame, display only what was collected at the trap.
2363 Likewise for stepping frames, display only what was collected
2364 while stepping. This means that the two boolean variables,
2365 STEPPING_FRAME and STEPPING_ACTIONS should be equal. */
2366 if (stepping_frame
== stepping_actions
)
2368 do { /* repeat over a comma-separated list */
2370 if (*action_exp
== ',')
2372 while (isspace (*action_exp
))
2375 next_comma
= strchr (action_exp
, ',');
2377 if (0 == strncasecmp (action_exp
, "$reg", 4))
2378 registers_info (NULL
, from_tty
);
2379 else if (0 == strncasecmp (action_exp
, "$loc", 4))
2380 locals_info (NULL
, from_tty
);
2381 else if (0 == strncasecmp (action_exp
, "$arg", 4))
2382 args_info (NULL
, from_tty
);
2383 else if (action_exp
[0] == '$' && action_exp
[1] == '(')
2385 long typecode
, size
;
2386 bfd_signed_vma offset
;
2389 action_exp
= parse_and_eval_memrange (action_exp
,
2394 if (typecode
!= 0 && typecode
!= -1)
2395 offset
+= read_register (typecode
);
2396 sprintf (fmt
, "/%dxb 0x%x", size
, offset
);
2397 x_command (fmt
, from_tty
);
2398 next_comma
= strchr (action_exp
, ',');
2404 make_cleanup (replace_comma
, next_comma
);
2407 printf_filtered ("%s = ", action_exp
);
2408 output_command (action_exp
, from_tty
);
2409 printf_filtered ("\n");
2413 action_exp
= next_comma
;
2414 } while (action_exp
&& *action_exp
== ',');
2418 discard_cleanups (old_cleanups
);
2421 /* module initialization */
2423 _initialize_tracepoint ()
2425 tracepoint_chain
= 0;
2426 tracepoint_count
= 0;
2427 traceframe_number
= -1;
2428 tracepoint_number
= -1;
2430 set_internalvar (lookup_internalvar ("tpnum"),
2431 value_from_longest (builtin_type_int
, (LONGEST
) 0));
2432 set_internalvar (lookup_internalvar ("trace_frame"),
2433 value_from_longest (builtin_type_int
, (LONGEST
) 0));
2435 if (tracepoint_list
.list
== NULL
)
2437 tracepoint_list
.listsize
= 128;
2438 tracepoint_list
.list
= xmalloc
2439 (tracepoint_list
.listsize
* sizeof (struct memrange
));
2441 if (stepping_list
.list
== NULL
)
2443 stepping_list
.listsize
= 128;
2444 stepping_list
.list
= xmalloc
2445 (stepping_list
.listsize
* sizeof (struct memrange
));
2448 add_info ("scope", scope_info
,
2449 "List the variables local to a scope");
2451 add_cmd ("tracepoints", class_trace
, NO_FUNCTION
,
2452 "Tracing of program execution without stopping the program.",
2455 add_info ("tracepoints", tracepoints_info
,
2456 "Status of tracepoints, or tracepoint number NUMBER.\n\
2457 Convenience variable \"$tpnum\" contains the number of the\n\
2458 last tracepoint set.");
2460 add_info_alias ("tp", "tracepoints", 1);
2462 add_com ("save-tracepoints", class_trace
, tracepoint_save_command
,
2463 "Save current tracepoint definitions as a script.\n\
2464 Use the 'source' command in another debug session to restore them.");
2466 add_com ("tdump", class_trace
, trace_dump_command
,
2467 "Print everything collected at the current tracepoint.");
2469 add_prefix_cmd ("tfind", class_trace
, trace_find_command
,
2470 "Select a trace frame;\n\
2471 No argument means forward by one frame; '-' meand backward by one frame.",
2472 &tfindlist
, "tfind ", 1, &cmdlist
);
2474 add_cmd ("outside", class_trace
, trace_find_outside_command
,
2475 "Select a trace frame whose PC is outside the given \
2476 range.\nUsage: tfind outside addr1, addr2",
2479 add_cmd ("range", class_trace
, trace_find_range_command
,
2480 "Select a trace frame whose PC is in the given range.\n\
2481 Usage: tfind range addr1,addr2",
2484 add_cmd ("line", class_trace
, trace_find_line_command
,
2485 "Select a trace frame by source line.\n\
2486 Argument can be a line number (with optional source file), \n\
2487 a function name, or '*' followed by an address.\n\
2488 Default argument is 'the next source line that was traced'.",
2491 add_cmd ("tracepoint", class_trace
, trace_find_tracepoint_command
,
2492 "Select a trace frame by tracepoint number.\n\
2493 Default is the tracepoint for the current trace frame.",
2496 add_cmd ("pc", class_trace
, trace_find_pc_command
,
2497 "Select a trace frame by PC.\n\
2498 Default is the current PC, or the PC of the current trace frame.",
2501 add_cmd ("end", class_trace
, trace_find_end_command
,
2502 "Synonym for 'none'.\n\
2503 De-select any trace frame and resume 'live' debugging.",
2506 add_cmd ("none", class_trace
, trace_find_none_command
,
2507 "De-select any trace frame and resume 'live' debugging.",
2510 add_cmd ("start", class_trace
, trace_find_start_command
,
2511 "Select the first trace frame in the trace buffer.",
2514 add_com ("tstatus", class_trace
, trace_status_command
,
2515 "Display the status of the current trace data collection.");
2517 add_com ("tstop", class_trace
, trace_stop_command
,
2518 "Stop trace data collection.");
2520 add_com ("tstart", class_trace
, trace_start_command
,
2521 "Start trace data collection.");
2523 add_com ("passcount", class_trace
, trace_pass_command
,
2524 "Set the passcount for a tracepoint.\n\
2525 The trace will end when the tracepoint has been passed 'count' times.\n\
2526 Usage: passcount COUNT TPNUM, where TPNUM may also be \"all\";\n\
2527 if TPNUM is omitted, passcount refers to the last tracepoint defined.");
2529 add_com ("end", class_trace
, end_actions_pseudocommand
,
2530 "Ends a list of commands or actions.\n\
2531 Several GDB commands allow you to enter a list of commands or actions.\n\
2532 Entering \"end\" on a line by itself is the normal way to terminate\n\
2534 Note: the \"end\" command cannot be used at the gdb prompt.");
2536 add_com ("while-stepping", class_trace
, while_stepping_pseudocommand
,
2537 "Specify single-stepping behavior at a tracepoint.\n\
2538 Argument is number of instructions to trace in single-step mode\n\
2539 following the tracepoint. This command is normally followed by\n\
2540 one or more \"collect\" commands, to specify what to collect\n\
2541 while single-stepping.\n\n\
2542 Note: this command can only be used in a tracepoint \"actions\" list.");
2544 add_com_alias ("ws", "while-stepping", class_alias
, 0);
2545 add_com_alias ("stepping", "while-stepping", class_alias
, 0);
2547 add_com ("collect", class_trace
, collect_pseudocommand
,
2548 "Specify one or more data items to be collected at a tracepoint.\n\
2549 Accepts a comma-separated list of (one or more) arguments.\n\
2550 Things that may be collected include registers, variables, plus\n\
2551 the following special arguments:\n\
2552 $regs -- all registers.\n\
2553 $args -- all function arguments.\n\
2554 $locals -- all variables local to the block/function scope.\n\
2555 $(addr,len) -- a literal memory range.\n\
2556 $($reg,addr,len) -- a register-relative literal memory range.\n\n\
2557 Note: this command can only be used in a tracepoint \"actions\" list.");
2559 add_com ("actions", class_trace
, trace_actions_command
,
2560 "Specify the actions to be taken at a tracepoint.\n\
2561 Tracepoint actions may include collecting of specified data, \n\
2562 single-stepping, or enabling/disabling other tracepoints, \n\
2563 depending on target's capabilities.");
2565 add_cmd ("tracepoints", class_trace
, delete_trace_command
,
2566 "Delete specified tracepoints.\n\
2567 Arguments are tracepoint numbers, separated by spaces.\n\
2568 No argument means delete all tracepoints.",
2571 add_cmd ("tracepoints", class_trace
, disable_trace_command
,
2572 "Disable specified tracepoints.\n\
2573 Arguments are tracepoint numbers, separated by spaces.\n\
2574 No argument means disable all tracepoints.",
2577 add_cmd ("tracepoints", class_trace
, enable_trace_command
,
2578 "Enable specified tracepoints.\n\
2579 Arguments are tracepoint numbers, separated by spaces.\n\
2580 No argument means enable all tracepoints.",
2583 add_com ("trace", class_trace
, trace_command
,
2584 "Set a tracepoint at a specified line or function or address.\n\
2585 Argument may be a line number, function name, or '*' plus an address.\n\
2586 For a line number or function, trace at the start of its code.\n\
2587 If an address is specified, trace at that exact address.\n\n\
2588 Do \"help tracepoints\" for info on other tracepoint commands.");
2590 add_com_alias ("tp", "trace", class_alias
, 0);
2591 add_com_alias ("tr", "trace", class_alias
, 1);
2592 add_com_alias ("tra", "trace", class_alias
, 1);
2593 add_com_alias ("trac", "trace", class_alias
, 1);