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
= (struct action_line
*) 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 */
1089 memrange_cmp (voidpa
, voidpbb
)
1090 void *voidpa
, *voidpb
;
1092 struct memrange
*a
, *b
;
1094 a
= (struct memrange
*) voidpa
;
1095 b
= (struct memrbnge
*) voidpb
;
1097 if (a
->type
< b
->type
) return -1;
1098 if (a
->type
> b
->type
) return 1;
1101 if ((bfd_vma
) a
->start
< (bfd_vma
) b
->start
) return -1;
1102 if ((bfd_vma
) a
->start
> (bfd_vma
) b
->start
) return 1;
1106 if (a
->start
< b
->start
) return -1;
1107 if (a
->start
> b
->start
) return 1;
1112 /* Sort the memrange list using qsort, and merge adjacent memranges */
1114 memrange_sortmerge (memranges
)
1115 struct collection_list
*memranges
;
1119 qsort (memranges
->list
, memranges
->next_memrange
,
1120 sizeof (struct memrange
), memrange_cmp
);
1121 if (memranges
->next_memrange
> 0)
1123 for (a
= 0, b
= 1; b
< memranges
->next_memrange
; b
++)
1125 if (memranges
->list
[a
].type
== memranges
->list
[b
].type
&&
1126 memranges
->list
[b
].start
- memranges
->list
[a
].end
<=
1127 MAX_REGISTER_VIRTUAL_SIZE
)
1129 /* memrange b starts before memrange a ends; merge them. */
1130 if (memranges
->list
[b
].end
> memranges
->list
[a
].end
)
1131 memranges
->list
[a
].end
= memranges
->list
[b
].end
;
1132 continue; /* next b, same a */
1136 memcpy (&memranges
->list
[a
], &memranges
->list
[b
],
1137 sizeof (struct memrange
));
1139 memranges
->next_memrange
= a
+ 1;
1143 /* Add a register to a collection list */
1145 add_register (collection
, regno
)
1146 struct collection_list
*collection
;
1147 unsigned long regno
;
1150 printf_filtered ("collect register %d\n", regno
);
1151 if (regno
> (8 * sizeof (collection
->regs_mask
)))
1152 error ("Internal: register number %d too large for tracepoint",
1154 collection
->regs_mask
[regno
/ 8] |= 1 << (regno
% 8);
1157 /* Add a memrange to a collection list */
1159 add_memrange (memranges
, type
, base
, len
)
1160 struct collection_list
*memranges
;
1162 bfd_signed_vma base
;
1166 printf_filtered ("(%d,0x%x,%d)\n", type
, base
, len
);
1167 /* type: 0 == memory, n == basereg */
1168 memranges
->list
[memranges
->next_memrange
].type
= type
;
1169 /* base: addr if memory, offset if reg relative. */
1170 memranges
->list
[memranges
->next_memrange
].start
= base
;
1171 /* len: we actually save end (base + len) for convenience */
1172 memranges
->list
[memranges
->next_memrange
].end
= base
+ len
;
1173 memranges
->next_memrange
++;
1174 if (memranges
->next_memrange
>= memranges
->listsize
)
1176 memranges
->listsize
*= 2;
1177 memranges
->list
= (struct memrange
*) xrealloc (memranges
->list
,
1178 memranges
->listsize
);
1181 if (type
!= -1) /* better collect the base register! */
1182 add_register (memranges
, type
);
1185 /* Add a symbol to a collection list */
1187 collect_symbol (collect
, sym
)
1188 struct collection_list
*collect
;
1193 bfd_signed_vma offset
;
1195 len
= TYPE_LENGTH (check_typedef (SYMBOL_TYPE (sym
)));
1196 switch (SYMBOL_CLASS (sym
)) {
1198 printf_filtered ("%s: don't know symbol class %d\n",
1199 SYMBOL_NAME (sym
), SYMBOL_CLASS (sym
));
1202 printf_filtered ("%s is constant, value is %d: will not be collected.\n",
1203 SYMBOL_NAME (sym
), SYMBOL_VALUE (sym
));
1206 offset
= SYMBOL_VALUE_ADDRESS (sym
);
1208 printf_filtered ("LOC_STATIC %s: collect %d bytes at 0x%08x\n",
1209 SYMBOL_NAME (sym
), len
, offset
);
1210 add_memrange (collect
, -1, offset
, len
); /* 0 == memory */
1214 reg
= SYMBOL_VALUE (sym
);
1216 printf_filtered ("LOC_REG[parm] %s: ", SYMBOL_NAME (sym
));
1217 add_register (collect
, reg
);
1221 printf_filtered ("Sorry, don't know how to do LOC_ARGs yet.\n");
1222 printf_filtered (" (will not collect %s)\n",
1225 case LOC_REGPARM_ADDR
:
1226 reg
= SYMBOL_VALUE (sym
);
1230 printf_filtered ("LOC_REGPARM_ADDR %s: Collect %d bytes at offset %d from reg %d\n",
1231 SYMBOL_NAME (sym
), len
, offset
, reg
);
1233 add_memrange (collect
, reg
, offset
, len
);
1237 offset
= SYMBOL_VALUE (sym
);
1241 printf_filtered ("LOC_LOCAL %s: Collect %d bytes at offset %d from frame ptr reg %d\n",
1242 SYMBOL_NAME (sym
), len
, offset
, reg
);
1244 add_memrange (collect
, reg
, offset
, len
);
1247 case LOC_BASEREG_ARG
:
1248 reg
= SYMBOL_BASEREG (sym
);
1249 offset
= SYMBOL_VALUE (sym
);
1252 printf_filtered ("LOC_BASEREG %s: collect %d bytes at offset %d from basereg %d\n",
1253 SYMBOL_NAME (sym
), len
, offset
, reg
);
1255 add_memrange (collect
, reg
, offset
, len
);
1257 case LOC_UNRESOLVED
:
1258 printf_filtered ("Don't know LOC_UNRESOLVED %s\n", SYMBOL_NAME (sym
));
1260 case LOC_OPTIMIZED_OUT
:
1261 printf_filtered ("%s has been optimized out of existance.\n",
1267 /* Add all locals (or args) symbols to collection list */
1269 add_local_symbols (collect
, pc
, type
)
1270 struct collection_list
*collect
;
1275 struct block
*block
;
1276 int i
, nsyms
, count
= 0;
1278 block
= block_for_pc (pc
);
1281 nsyms
= BLOCK_NSYMS (block
);
1282 for (i
= 0; i
< nsyms
; i
++)
1284 sym
= BLOCK_SYM (block
, i
);
1285 switch (SYMBOL_CLASS (sym
)) {
1290 if (type
== 'L') /* collecting Locals */
1293 collect_symbol (collect
, sym
);
1300 case LOC_REGPARM_ADDR
:
1301 case LOC_BASEREG_ARG
:
1302 if (type
== 'A') /* collecting Arguments */
1305 collect_symbol (collect
, sym
);
1309 if (BLOCK_FUNCTION (block
))
1312 block
= BLOCK_SUPERBLOCK (block
);
1315 warning ("No %s found in scope.", type
== 'L' ? "locals" : "args");
1318 /* worker function */
1320 clear_collection_list (list
)
1321 struct collection_list
*list
;
1323 list
->next_memrange
= 0;
1324 memset (list
->regs_mask
, 0, sizeof (list
->regs_mask
));
1327 /* reduce a collection list to string form (for gdb protocol) */
1329 stringify_collection_list (list
, string
)
1330 struct collection_list
*list
;
1336 for (i
= sizeof (list
->regs_mask
) - 1; i
> 0; i
--)
1337 if (list
->regs_mask
[i
] != 0) /* skip leading zeroes in regs_mask */
1339 if (list
->regs_mask
[i
] != 0) /* prepare to send regs_mask to the stub */
1342 printf_filtered ("\nCollecting registers (mask): 0x");
1347 printf_filtered ("%02X", list
->regs_mask
[i
]);
1348 sprintf (end
, "%02X", list
->regs_mask
[i
]);
1353 printf_filtered ("\n");
1354 if (list
->next_memrange
> 0 && info_verbose
)
1355 printf_filtered ("Collecting memranges: \n");
1356 for (i
= 0; i
< list
->next_memrange
; i
++)
1359 printf_filtered ("(%d, 0x%x, %d)\n",
1361 list
->list
[i
].start
,
1362 list
->list
[i
].end
- list
->list
[i
].start
);
1363 sprintf (end
, "M%X,%X,%X",
1365 list
->list
[i
].start
,
1366 list
->list
[i
].end
- list
->list
[i
].start
);
1367 end
+= strlen (end
);
1375 /* render all actions into gdb protocol */
1377 encode_actions (t
, tdp_actions
, step_count
, stepping_actions
)
1378 struct tracepoint
*t
;
1380 unsigned long *step_count
;
1381 char **stepping_actions
;
1383 static char tdp_buff
[2048], step_buff
[2048];
1385 struct expression
*exp
;
1386 struct action_line
*action
;
1387 bfd_signed_vma offset
;
1390 struct collection_list
*collect
;
1391 struct cmd_list_element
*cmd
;
1393 clear_collection_list (&tracepoint_list
);
1394 clear_collection_list (&stepping_list
);
1395 collect
= &tracepoint_list
;
1397 *tdp_actions
= NULL
;
1398 *stepping_actions
= NULL
;
1400 for (action
= t
->actions
; action
; action
= action
->next
)
1402 action_exp
= action
->action
;
1403 while (isspace (*action_exp
))
1406 if (*action_exp
== '#') /* comment line */
1409 cmd
= lookup_cmd (&action_exp
, cmdlist
, "", -1, 1);
1411 error ("Bad action list item: %s", action_exp
);
1413 if (cmd
->function
.cfunc
== collect_pseudocommand
)
1415 do { /* repeat over a comma-separated list */
1416 while (isspace (*action_exp
))
1419 if (0 == strncasecmp ("$reg", action_exp
, 4))
1421 for (i
= 0; i
< NUM_REGS
; i
++)
1422 add_register (collect
, i
);
1423 action_exp
= strchr (action_exp
, ','); /* more? */
1425 else if (0 == strncasecmp ("$arg", action_exp
, 4))
1427 add_local_symbols (collect
, t
->address
, 'A');
1428 action_exp
= strchr (action_exp
, ','); /* more? */
1430 else if (0 == strncasecmp ("$loc", action_exp
, 4))
1432 add_local_symbols (collect
, t
->address
, 'L');
1433 action_exp
= strchr (action_exp
, ','); /* more? */
1435 else if (action_exp
[0] == '$' &&
1436 action_exp
[1] == '(') /* literal memrange */
1438 long typecode
, size
;
1439 bfd_signed_vma offset
;
1441 action_exp
= parse_and_eval_memrange (action_exp
,
1446 add_memrange (collect
, typecode
, offset
, size
);
1450 unsigned long addr
, len
;
1452 exp
= parse_exp_1 (&action_exp
, block_for_pc (t
->address
), 1);
1453 switch (exp
->elts
[0].opcode
) {
1455 i
= exp
->elts
[1].longconst
;
1457 printf_filtered ("OP_REGISTER: ");
1458 add_register (collect
, i
);
1462 /* safe because we know it's a simple expression */
1463 tempval
= evaluate_expression (exp
);
1464 addr
= VALUE_ADDRESS (tempval
) + VALUE_OFFSET (tempval
);
1465 len
= TYPE_LENGTH (check_typedef (exp
->elts
[1].type
));
1466 add_memrange (collect
, -1, addr
, len
);
1470 collect_symbol (collect
, exp
->elts
[2].symbol
);
1474 addr
= exp
->elts
[2].longconst
;
1475 if (*action_exp
== ':')
1477 exp
= parse_exp_1 (&action_exp
,
1478 block_for_pc (t
->address
),
1480 if (exp
->elts
[0].opcode
== OP_LONG
)
1481 len
= exp
->elts
[2].longconst
;
1483 error ("length field requires a literal long const");
1488 add_memrange (collect
, -1, addr
, len
);
1493 } while (action_exp
&& *action_exp
++ == ',');
1495 else if (cmd
->function
.cfunc
== while_stepping_pseudocommand
)
1497 collect
= &stepping_list
;
1499 else if (cmd
->function
.cfunc
== end_actions_pseudocommand
)
1501 if (collect
== &stepping_list
) /* end stepping actions */
1502 collect
= &tracepoint_list
;
1504 break; /* end tracepoint actions */
1507 memrange_sortmerge (&tracepoint_list
);
1508 memrange_sortmerge (&stepping_list
);
1510 *tdp_actions
= stringify_collection_list (&tracepoint_list
, tdp_buff
);
1511 *stepping_actions
= stringify_collection_list (&stepping_list
, step_buff
);
1514 static char target_buf
[2048];
1518 Tell target to lear any previous trace experiment.
1519 Walk the list of tracepoints, and send them (and their actions)
1520 to the target. If no errors,
1521 Tell target to start a new trace experiment. */
1524 trace_start_command (args
, from_tty
)
1527 { /* STUB_COMM MOSTLY_IMPLEMENTED */
1528 struct tracepoint
*t
;
1531 char *stepping_actions
;
1532 unsigned long step_count
;
1534 dont_repeat (); /* like "run", dangerous to repeat accidentally */
1536 if (target_is_remote ())
1539 remote_get_noisy_reply (target_buf
);
1540 if (strcmp (target_buf
, "OK"))
1541 error ("Target does not support this command.");
1545 int ss_count
; /* if actions include singlestepping */
1546 int disable_mask
; /* ??? */
1547 int enable_mask
; /* ??? */
1549 sprintf (buf
, "QTDP:%x:%x:%c:%x:%x", t
->number
, t
->address
,
1550 t
->enabled
== enabled
? 'E' : 'D',
1551 t
->step_count
, t
->pass_count
);
1554 encode_actions (t
, &tdp_actions
, &step_count
, &stepping_actions
);
1555 /* do_single_steps (t); */
1558 if (strlen (buf
) + strlen (tdp_actions
) >= sizeof (buf
))
1559 error ("Actions for tracepoint %d too complex; please simplify.",
1561 strcat (buf
, tdp_actions
);
1563 if (stepping_actions
)
1566 if (strlen (buf
) + strlen (stepping_actions
) >= sizeof (buf
))
1567 error ("Actions for tracepoint %d too complex; please simplify.",
1569 strcat (buf
, stepping_actions
);
1573 remote_get_noisy_reply (target_buf
);
1574 if (strcmp (target_buf
, "OK"))
1575 error ("Target does not support tracepoints.");
1578 remote_get_noisy_reply (target_buf
);
1579 if (strcmp (target_buf
, "OK"))
1580 error ("Bogus reply from target: %s", target_buf
);
1581 set_traceframe_num (-1); /* all old traceframes invalidated */
1582 set_tracepoint_num (-1);
1583 set_traceframe_context(-1);
1584 trace_running_p
= 1;
1587 printf_filtered ("Trace can only be run on remote targets.\n");
1592 trace_stop_command (args
, from_tty
)
1595 { /* STUB_COMM IS_IMPLEMENTED */
1596 if (target_is_remote ())
1599 remote_get_noisy_reply (target_buf
);
1600 if (strcmp (target_buf
, "OK"))
1601 error ("Bogus reply from target: %s", target_buf
);
1602 trace_running_p
= 0;
1605 error ("Trace can only be run on remote targets.");
1608 unsigned long trace_running_p
;
1610 /* tstatus command */
1612 trace_status_command (args
, from_tty
)
1615 { /* STUB_COMM IS_IMPLEMENTED */
1616 if (target_is_remote ())
1618 putpkt ("qTStatus");
1619 remote_get_noisy_reply (target_buf
);
1621 if (target_buf
[0] != 'T' ||
1622 (target_buf
[1] != '0' && target_buf
[1] != '1'))
1623 error ("Bogus reply from target: %s", target_buf
);
1625 /* exported for use by the GUI */
1626 trace_running_p
= (target_buf
[1] == '1');
1629 error ("Trace can only be run on remote targets.");
1632 /* Worker function for the various flavors of the tfind command */
1634 finish_tfind_command (msg
, from_tty
)
1638 int target_frameno
= -1, target_tracept
= -1;
1639 CORE_ADDR old_frame_addr
;
1640 struct symbol
*old_func
;
1643 old_frame_addr
= FRAME_FP (get_current_frame ());
1644 old_func
= find_pc_function (read_pc ());
1647 reply
= remote_get_noisy_reply (msg
);
1649 while (reply
&& *reply
)
1652 if ((target_frameno
= strtol (++reply
, &reply
, 16)) == -1)
1654 /* A request for a non-existant trace frame has failed.
1655 Our response will be different, depending on FROM_TTY:
1657 If FROM_TTY is true, meaning that this command was
1658 typed interactively by the user, then give an error
1659 and DO NOT change the state of traceframe_number etc.
1661 However if FROM_TTY is false, meaning that we're either
1662 in a script, a loop, or a user-defined command, then
1663 DON'T give an error, but DO change the state of
1664 traceframe_number etc. to invalid.
1666 The rationalle is that if you typed the command, you
1667 might just have committed a typo or something, and you'd
1668 like to NOT lose your current debugging state. However
1669 if you're in a user-defined command or especially in a
1670 loop, then you need a way to detect that the command
1671 failed WITHOUT aborting. This allows you to write
1672 scripts that search thru the trace buffer until the end,
1673 and then continue on to do something else. */
1676 error ("Target failed to find requested trace frame.");
1680 printf_filtered ("End of trace buffer.\n");
1681 /* The following will not recurse, since it's special-cased */
1682 trace_find_command ("-1", from_tty
);
1683 reply
= NULL
; /* break out of loop,
1684 (avoid recursive nonsense) */
1689 if ((target_tracept
= strtol (++reply
, &reply
, 16)) == -1)
1690 error ("Target failed to find requested trace frame.");
1692 case 'O': /* "OK"? */
1693 if (reply
[1] == 'K' && reply
[2] == '\0')
1696 error ("Bogus reply from target: %s", reply
);
1699 error ("Bogus reply from target: %s", reply
);
1702 flush_cached_frames ();
1703 registers_changed ();
1704 select_frame (get_current_frame (), 0);
1705 set_traceframe_num (target_frameno
);
1706 set_tracepoint_num (target_tracept
);
1707 if (target_frameno
== -1)
1708 set_traceframe_context (-1);
1710 set_traceframe_context (read_pc ());
1716 /* NOTE: in immitation of the step command, try to determine
1717 whether we have made a transition from one function to another.
1718 If so, we'll print the "stack frame" (ie. the new function and
1719 it's arguments) -- otherwise we'll just show the new source line.
1721 This determination is made by checking (1) whether the current
1722 function has changed, and (2) whether the current FP has changed.
1723 Hack: if the FP wasn't collected, either at the current or the
1724 previous frame, assume that the FP has NOT changed. */
1726 if (old_func
== find_pc_function (read_pc ()) &&
1727 (old_frame_addr
== 0 ||
1728 FRAME_FP (get_current_frame ()) == 0 ||
1729 old_frame_addr
== FRAME_FP (get_current_frame ())))
1734 print_stack_frame (selected_frame
, selected_frame_level
, source_only
);
1739 /* trace_find_command takes a trace frame number n,
1740 sends "QTFrame:<n>" to the target,
1741 and accepts a reply that may contain several optional pieces
1742 of information: a frame number, a tracepoint number, and an
1743 indication of whether this is a trap frame or a stepping frame.
1745 The minimal response is just "OK" (which indicates that the
1746 target does not give us a frame number or a tracepoint number).
1747 Instead of that, the target may send us a string containing
1749 F<hexnum> (gives the selected frame number)
1750 T<hexnum> (gives the selected tracepoint number)
1755 trace_find_command (args
, from_tty
)
1758 { /* STUB_COMM PART_IMPLEMENTED */
1759 /* this should only be called with a numeric argument */
1761 int target_frameno
= -1, target_tracept
= -1, target_stepfrm
= 0;
1764 if (target_is_remote ())
1766 if (args
== 0 || *args
== 0)
1767 { /* TFIND with no args means find NEXT trace frame. */
1768 if (traceframe_number
== -1)
1769 frameno
= 0; /* "next" is first one */
1771 frameno
= traceframe_number
+ 1;
1773 else if (0 == strcmp (args
, "-"))
1775 if (traceframe_number
== -1)
1776 error ("not debugging trace buffer");
1777 else if (from_tty
&& traceframe_number
== 0)
1778 error ("already at start of trace buffer");
1780 frameno
= traceframe_number
- 1;
1783 frameno
= parse_and_eval_address (args
);
1785 sprintf (target_buf
, "QTFrame:%x", frameno
);
1787 putpkt (target_buf
);
1788 tmp
= remote_get_noisy_reply (target_buf
);
1790 if (frameno
== -1) /* end trace debugging */
1791 { /* hopefully the stub has complied! */
1792 if (0 != strcmp (tmp
, "OK"))
1793 error ("Bogus response from target: %s", tmp
);
1795 finish_tfind_command (NULL
, from_tty
);
1798 finish_tfind_command (tmp
, from_tty
);
1800 finish_tfind_command (target_buf
, from_tty
);
1804 error ("Trace can only be run on remote targets.");
1809 trace_find_end_command (args
, from_tty
)
1813 trace_find_command ("-1", from_tty
);
1818 trace_find_none_command (args
, from_tty
)
1822 trace_find_command ("-1", from_tty
);
1827 trace_find_start_command (args
, from_tty
)
1831 trace_find_command ("0", from_tty
);
1834 /* tfind pc command */
1836 trace_find_pc_command (args
, from_tty
)
1839 { /* STUB_COMM PART_IMPLEMENTED */
1844 if (target_is_remote ())
1846 if (args
== 0 || *args
== 0)
1847 pc
= read_pc (); /* default is current pc */
1849 pc
= parse_and_eval_address (args
);
1851 sprintf (target_buf
, "QTFrame:pc:%x", pc
);
1853 putpkt (target_buf
);
1854 tmp
= remote_get_noisy_reply (target_buf
);
1856 finish_tfind_command (tmp
, from_tty
);
1858 finish_tfind_command (target_buf
, from_tty
);
1862 error ("Trace can only be run on remote targets.");
1865 /* tfind tracepoint command */
1867 trace_find_tracepoint_command (args
, from_tty
)
1870 { /* STUB_COMM PART_IMPLEMENTED */
1871 int target_frameno
, tdp
;
1874 if (target_is_remote ())
1876 if (args
== 0 || *args
== 0)
1877 if (tracepoint_number
== -1)
1878 error ("No current tracepoint -- please supply an argument.");
1880 tdp
= tracepoint_number
; /* default is current TDP */
1882 tdp
= parse_and_eval_address (args
);
1884 sprintf (target_buf
, "QTFrame:tdp:%x", tdp
);
1886 putpkt (target_buf
);
1887 tmp
= remote_get_noisy_reply (target_buf
);
1889 finish_tfind_command (tmp
, from_tty
);
1891 finish_tfind_command (target_buf
, from_tty
);
1895 error ("Trace can only be run on remote targets.");
1898 /* TFIND LINE command:
1900 This command will take a sourceline for argument, just like BREAK
1901 or TRACE (ie. anything that "decode_line_1" can handle).
1903 With no argument, this command will find the next trace frame
1904 corresponding to a source line OTHER THAN THE CURRENT ONE. */
1907 trace_find_line_command (args
, from_tty
)
1910 { /* STUB_COMM PART_IMPLEMENTED */
1911 static CORE_ADDR start_pc
, end_pc
;
1912 struct symtabs_and_lines sals
;
1913 struct symtab_and_line sal
;
1916 struct cleanup
*old_chain
;
1918 if (target_is_remote ())
1920 if (args
== 0 || *args
== 0)
1922 sal
= find_pc_line ((get_current_frame ())->pc
, 0);
1924 sals
.sals
= (struct symtab_and_line
*)
1925 xmalloc (sizeof (struct symtab_and_line
));
1930 sals
= decode_line_spec (args
, 1);
1934 old_chain
= make_cleanup (free
, sals
.sals
);
1935 if (sal
.symtab
== 0)
1937 printf_filtered ("TFIND: No line number information available");
1940 /* This is useful for "info line *0x7f34". If we can't tell the
1941 user about a source line, at least let them have the symbolic
1943 printf_filtered (" for address ");
1945 print_address (sal
.pc
, gdb_stdout
);
1946 printf_filtered (";\n -- will attempt to find by PC. \n");
1950 printf_filtered (".\n");
1951 return; /* no line, no PC; what can we do? */
1954 else if (sal
.line
> 0
1955 && find_line_pc_range (sal
, &start_pc
, &end_pc
))
1957 if (start_pc
== end_pc
)
1959 printf_filtered ("Line %d of \"%s\"",
1960 sal
.line
, sal
.symtab
->filename
);
1962 printf_filtered (" is at address ");
1963 print_address (start_pc
, gdb_stdout
);
1965 printf_filtered (" but contains no code.\n");
1966 sal
= find_pc_line (start_pc
, 0);
1968 find_line_pc_range (sal
, &start_pc
, &end_pc
) &&
1970 printf_filtered ("Attempting to find line %d instead.\n",
1973 error ("Cannot find a good line.");
1977 /* Is there any case in which we get here, and have an address
1978 which the user would want to see? If we have debugging symbols
1979 and no line numbers? */
1980 error ("Line number %d is out of range for \"%s\".\n",
1981 sal
.line
, sal
.symtab
->filename
);
1983 if (args
&& *args
) /* find within range of stated line */
1984 sprintf (target_buf
, "QTFrame:range:%x:%x", start_pc
, end_pc
- 1);
1985 else /* find OUTSIDE OF range of CURRENT line */
1986 sprintf (target_buf
, "QTFrame:outside:%x:%x", start_pc
, end_pc
- 1);
1988 putpkt (target_buf
);
1989 tmp
= remote_get_noisy_reply (target_buf
);
1991 finish_tfind_command (tmp
, from_tty
);
1993 finish_tfind_command (target_buf
, from_tty
);
1995 do_cleanups (old_chain
);
1998 error ("Trace can only be run on remote targets.");
2001 /* tfind range command */
2003 trace_find_range_command (args
, from_tty
)
2006 { /* STUB_COMM PART_IMPLEMENTED */
2007 static CORE_ADDR start
, stop
;
2011 if (target_is_remote ())
2013 if (args
== 0 || *args
== 0)
2014 { /* XXX FIXME: what should default behavior be? */
2015 printf_filtered ("Usage: tfind range <startaddr>,<endaddr>\n");
2019 if (0 != (tmp
= strchr (args
, ',' )))
2021 *tmp
++ = '\0'; /* terminate start address */
2022 while (isspace (*tmp
))
2024 start
= parse_and_eval_address (args
);
2025 stop
= parse_and_eval_address (tmp
);
2028 { /* no explicit end address? */
2029 start
= parse_and_eval_address (args
);
2030 stop
= start
+ 1; /* ??? */
2033 sprintf (target_buf
, "QTFrame:range:%x:%x", start
, stop
);
2035 putpkt (target_buf
);
2036 tmp
= remote_get_noisy_reply (target_buf
);
2038 finish_tfind_command (tmp
, from_tty
);
2040 finish_tfind_command (target_buf
, from_tty
);
2044 error ("Trace can only be run on remote targets.");
2047 /* tfind outside command */
2049 trace_find_outside_command (args
, from_tty
)
2052 { /* STUB_COMM PART_IMPLEMENTED */
2053 CORE_ADDR start
, stop
;
2057 if (target_is_remote ())
2059 if (args
== 0 || *args
== 0)
2060 { /* XXX FIXME: what should default behavior be? */
2061 printf_filtered ("Usage: tfind outside <startaddr>,<endaddr>\n");
2065 if (0 != (tmp
= strchr (args
, ',' )))
2067 *tmp
++ = '\0'; /* terminate start address */
2068 while (isspace (*tmp
))
2070 start
= parse_and_eval_address (args
);
2071 stop
= parse_and_eval_address (tmp
);
2074 { /* no explicit end address? */
2075 start
= parse_and_eval_address (args
);
2076 stop
= start
+ 1; /* ??? */
2079 sprintf (target_buf
, "QTFrame:outside:%x:%x", start
, stop
);
2081 putpkt (target_buf
);
2082 tmp
= remote_get_noisy_reply (target_buf
);
2084 finish_tfind_command (tmp
, from_tty
);
2086 finish_tfind_command (target_buf
, from_tty
);
2090 error ("Trace can only be run on remote targets.");
2093 /* save-tracepoints command */
2095 tracepoint_save_command (args
, from_tty
)
2099 struct tracepoint
*tp
;
2100 struct action_line
*line
;
2102 char *i1
= " ", *i2
= " ";
2103 char *indent
, *actionline
;
2105 if (args
== 0 || *args
== 0)
2106 error ("Argument required (file name in which to save tracepoints");
2108 if (tracepoint_chain
== 0)
2110 warning ("save-tracepoints: no tracepoints to save.\n");
2114 if (!(fp
= fopen (args
, "w")))
2115 error ("Unable to open file '%s' for saving tracepoints");
2117 ALL_TRACEPOINTS (tp
)
2119 if (tp
->addr_string
)
2120 fprintf (fp
, "trace %s\n", tp
->addr_string
);
2122 fprintf (fp
, "trace *0x%x\n", tp
->address
);
2125 fprintf (fp
, " passcount %d\n", tp
->pass_count
);
2129 fprintf (fp
, " actions\n");
2131 for (line
= tp
->actions
; line
; line
= line
->next
)
2133 struct cmd_list_element
*cmd
;
2135 actionline
= line
->action
;
2136 while (isspace(*actionline
))
2139 fprintf (fp
, "%s%s\n", indent
, actionline
);
2140 if (*actionline
!= '#') /* skip for comment lines */
2142 cmd
= lookup_cmd (&actionline
, cmdlist
, "", -1, 1);
2144 error ("Bad action list item: %s", actionline
);
2145 if (cmd
->function
.cfunc
== while_stepping_pseudocommand
)
2147 else if (cmd
->function
.cfunc
== end_actions_pseudocommand
)
2155 printf_filtered ("Tracepoints saved to file '%s'.\n", args
);
2159 /* info scope command: list the locals for a scope. */
2161 scope_info (args
, from_tty
)
2165 struct symtab_and_line sal
;
2166 struct symtabs_and_lines sals
;
2168 struct minimal_symbol
*msym
;
2169 struct block
*block
;
2170 char **canonical
, *symname
, *save_args
= args
;
2171 int i
, nsyms
, count
= 0;
2173 if (args
== 0 || *args
== 0)
2174 error ("requires an argument (function, line or *addr) to define a scope");
2176 sals
= decode_line_1 (&args
, 1, NULL
, 0, &canonical
);
2177 if (sals
.nelts
== 0)
2178 return; /* presumably decode_line_1 has already warned */
2180 /* Resolve line numbers to PC */
2181 resolve_sal_pc (&sals
.sals
[0]);
2182 block
= block_for_pc (sals
.sals
[0].pc
);
2186 nsyms
= BLOCK_NSYMS (block
);
2187 for (i
= 0; i
< nsyms
; i
++)
2190 printf_filtered ("Scope for %s:\n", save_args
);
2192 sym
= BLOCK_SYM (block
, i
);
2193 symname
= SYMBOL_NAME (sym
);
2194 if (symname
== NULL
|| *symname
== '\0')
2195 continue; /* probably botched, certainly useless */
2197 printf_filtered ("Symbol %s is ", symname
);
2198 switch (SYMBOL_CLASS (sym
)) {
2200 case LOC_UNDEF
: /* messed up symbol? */
2201 printf_filtered ("a bogus symbol, class %d.\n",
2202 SYMBOL_CLASS (sym
));
2203 count
--; /* don't count this one */
2206 printf_filtered ("a constant with value %d (0x%x)",
2207 SYMBOL_VALUE (sym
), SYMBOL_VALUE (sym
));
2209 case LOC_CONST_BYTES
:
2210 printf_filtered ("constant bytes: ");
2211 if (SYMBOL_TYPE (sym
))
2212 for (i
= 0; i
< TYPE_LENGTH (SYMBOL_TYPE (sym
)); i
++)
2213 fprintf_filtered (gdb_stdout
, " %02x",
2214 (unsigned) SYMBOL_VALUE_BYTES (sym
) [i
]);
2217 printf_filtered ("in static storage at address ");
2218 print_address_numeric (SYMBOL_VALUE_ADDRESS (sym
), 1, gdb_stdout
);
2221 printf_filtered ("a local variable in register $%s",
2222 reg_names
[SYMBOL_VALUE (sym
)]);
2226 printf_filtered ("an argument at stack/frame offset %ld",
2227 SYMBOL_VALUE (sym
));
2230 printf_filtered ("a local variable at frame offset %ld",
2231 SYMBOL_VALUE (sym
));
2234 printf_filtered ("a reference argument at offset %ld",
2235 SYMBOL_VALUE (sym
));
2238 printf_filtered ("an argument in register $%s",
2239 reg_names
[SYMBOL_VALUE (sym
)]);
2241 case LOC_REGPARM_ADDR
:
2242 printf_filtered ("the address of an argument, in register $%s",
2243 reg_names
[SYMBOL_VALUE (sym
)]);
2246 printf_filtered ("a typedef.\n");
2249 printf_filtered ("a label at address ");
2250 print_address_numeric (SYMBOL_VALUE_ADDRESS (sym
), 1, gdb_stdout
);
2253 printf_filtered ("a function at address ");
2254 print_address_numeric (BLOCK_START (SYMBOL_BLOCK_VALUE (sym
)), 1,
2258 printf_filtered ("a variable at offset %d from register $%s",
2260 reg_names
[SYMBOL_BASEREG (sym
)]);
2262 case LOC_BASEREG_ARG
:
2263 printf_filtered ("an argument at offset %d from register $%s",
2265 reg_names
[SYMBOL_BASEREG (sym
)]);
2267 case LOC_UNRESOLVED
:
2268 msym
= lookup_minimal_symbol (SYMBOL_NAME (sym
), NULL
, NULL
);
2270 printf_filtered ("Unresolved Static");
2273 printf_filtered ("static storage at address ");
2274 print_address_numeric (SYMBOL_VALUE_ADDRESS (msym
), 1,
2278 case LOC_OPTIMIZED_OUT
:
2279 printf_filtered ("optimized out.\n");
2282 if (SYMBOL_TYPE (sym
))
2283 printf_filtered (", length %d.\n",
2284 TYPE_LENGTH (check_typedef (SYMBOL_TYPE (sym
))));
2286 if (BLOCK_FUNCTION (block
))
2289 block
= BLOCK_SUPERBLOCK (block
);
2292 printf_filtered ("Scope for %s contains no locals or arguments.\n",
2296 /* worker function (cleanup) */
2298 replace_comma (comma
)
2306 trace_dump_command (args
, from_tty
)
2310 struct tracepoint
*t
;
2311 struct action_line
*action
;
2312 char *action_exp
, *next_comma
;
2313 struct cleanup
*old_cleanups
;
2314 int stepping_actions
= 0;
2315 int stepping_frame
= 0;
2317 if (tracepoint_number
== -1)
2319 warning ("No current trace frame.");
2324 if (t
->number
== tracepoint_number
)
2328 error ("No known tracepoint matches 'current' tracepoint #%d.",
2331 old_cleanups
= make_cleanup (null_cleanup
, NULL
);
2333 printf_filtered ("Data collected at tracepoint %d, trace frame %d:\n",
2334 tracepoint_number
, traceframe_number
);
2336 /* The current frame is a trap frame if the frame PC is equal
2337 to the tracepoint PC. If not, then the current frame was
2338 collected during single-stepping. */
2340 stepping_frame
= (t
->address
!= read_pc());
2342 for (action
= t
->actions
; action
; action
= action
->next
)
2344 struct cmd_list_element
*cmd
;
2346 action_exp
= action
->action
;
2347 while (isspace (*action_exp
))
2350 /* The collection actions to be done while stepping are
2351 bracketed by the commands "while-stepping" and "end". */
2353 if (*action_exp
== '#') /* comment line */
2356 cmd
= lookup_cmd (&action_exp
, cmdlist
, "", -1, 1);
2358 error ("Bad action list item: %s", action_exp
);
2360 if (cmd
->function
.cfunc
== while_stepping_pseudocommand
)
2361 stepping_actions
= 1;
2362 else if (cmd
->function
.cfunc
== end_actions_pseudocommand
)
2363 stepping_actions
= 0;
2364 else if (cmd
->function
.cfunc
== collect_pseudocommand
)
2366 /* Display the collected data.
2367 For the trap frame, display only what was collected at the trap.
2368 Likewise for stepping frames, display only what was collected
2369 while stepping. This means that the two boolean variables,
2370 STEPPING_FRAME and STEPPING_ACTIONS should be equal. */
2371 if (stepping_frame
== stepping_actions
)
2373 do { /* repeat over a comma-separated list */
2375 if (*action_exp
== ',')
2377 while (isspace (*action_exp
))
2380 next_comma
= strchr (action_exp
, ',');
2382 if (0 == strncasecmp (action_exp
, "$reg", 4))
2383 registers_info (NULL
, from_tty
);
2384 else if (0 == strncasecmp (action_exp
, "$loc", 4))
2385 locals_info (NULL
, from_tty
);
2386 else if (0 == strncasecmp (action_exp
, "$arg", 4))
2387 args_info (NULL
, from_tty
);
2388 else if (action_exp
[0] == '$' && action_exp
[1] == '(')
2390 long typecode
, size
;
2391 bfd_signed_vma offset
;
2394 action_exp
= parse_and_eval_memrange (action_exp
,
2399 if (typecode
!= 0 && typecode
!= -1)
2400 offset
+= read_register (typecode
);
2401 sprintf (fmt
, "/%dxb 0x%x", size
, offset
);
2402 x_command (fmt
, from_tty
);
2403 next_comma
= strchr (action_exp
, ',');
2409 make_cleanup (replace_comma
, next_comma
);
2412 printf_filtered ("%s = ", action_exp
);
2413 output_command (action_exp
, from_tty
);
2414 printf_filtered ("\n");
2418 action_exp
= next_comma
;
2419 } while (action_exp
&& *action_exp
== ',');
2423 discard_cleanups (old_cleanups
);
2426 /* module initialization */
2428 _initialize_tracepoint ()
2430 tracepoint_chain
= 0;
2431 tracepoint_count
= 0;
2432 traceframe_number
= -1;
2433 tracepoint_number
= -1;
2435 set_internalvar (lookup_internalvar ("tpnum"),
2436 value_from_longest (builtin_type_int
, (LONGEST
) 0));
2437 set_internalvar (lookup_internalvar ("trace_frame"),
2438 value_from_longest (builtin_type_int
, (LONGEST
) 0));
2440 if (tracepoint_list
.list
== NULL
)
2442 tracepoint_list
.listsize
= 128;
2443 tracepoint_list
.list
= (struct memrange
*) xmalloc
2444 (tracepoint_list
.listsize
* sizeof (struct memrange
));
2446 if (stepping_list
.list
== NULL
)
2448 stepping_list
.listsize
= 128;
2449 stepping_list
.list
= (struct memrange
*) xmalloc
2450 (stepping_list
.listsize
* sizeof (struct memrange
));
2453 add_info ("scope", scope_info
,
2454 "List the variables local to a scope");
2456 add_cmd ("tracepoints", class_trace
, NO_FUNCTION
,
2457 "Tracing of program execution without stopping the program.",
2460 add_info ("tracepoints", tracepoints_info
,
2461 "Status of tracepoints, or tracepoint number NUMBER.\n\
2462 Convenience variable \"$tpnum\" contains the number of the\n\
2463 last tracepoint set.");
2465 add_info_alias ("tp", "tracepoints", 1);
2467 add_com ("save-tracepoints", class_trace
, tracepoint_save_command
,
2468 "Save current tracepoint definitions as a script.\n\
2469 Use the 'source' command in another debug session to restore them.");
2471 add_com ("tdump", class_trace
, trace_dump_command
,
2472 "Print everything collected at the current tracepoint.");
2474 add_prefix_cmd ("tfind", class_trace
, trace_find_command
,
2475 "Select a trace frame;\n\
2476 No argument means forward by one frame; '-' meand backward by one frame.",
2477 &tfindlist
, "tfind ", 1, &cmdlist
);
2479 add_cmd ("outside", class_trace
, trace_find_outside_command
,
2480 "Select a trace frame whose PC is outside the given \
2481 range.\nUsage: tfind outside addr1, addr2",
2484 add_cmd ("range", class_trace
, trace_find_range_command
,
2485 "Select a trace frame whose PC is in the given range.\n\
2486 Usage: tfind range addr1,addr2",
2489 add_cmd ("line", class_trace
, trace_find_line_command
,
2490 "Select a trace frame by source line.\n\
2491 Argument can be a line number (with optional source file), \n\
2492 a function name, or '*' followed by an address.\n\
2493 Default argument is 'the next source line that was traced'.",
2496 add_cmd ("tracepoint", class_trace
, trace_find_tracepoint_command
,
2497 "Select a trace frame by tracepoint number.\n\
2498 Default is the tracepoint for the current trace frame.",
2501 add_cmd ("pc", class_trace
, trace_find_pc_command
,
2502 "Select a trace frame by PC.\n\
2503 Default is the current PC, or the PC of the current trace frame.",
2506 add_cmd ("end", class_trace
, trace_find_end_command
,
2507 "Synonym for 'none'.\n\
2508 De-select any trace frame and resume 'live' debugging.",
2511 add_cmd ("none", class_trace
, trace_find_none_command
,
2512 "De-select any trace frame and resume 'live' debugging.",
2515 add_cmd ("start", class_trace
, trace_find_start_command
,
2516 "Select the first trace frame in the trace buffer.",
2519 add_com ("tstatus", class_trace
, trace_status_command
,
2520 "Display the status of the current trace data collection.");
2522 add_com ("tstop", class_trace
, trace_stop_command
,
2523 "Stop trace data collection.");
2525 add_com ("tstart", class_trace
, trace_start_command
,
2526 "Start trace data collection.");
2528 add_com ("passcount", class_trace
, trace_pass_command
,
2529 "Set the passcount for a tracepoint.\n\
2530 The trace will end when the tracepoint has been passed 'count' times.\n\
2531 Usage: passcount COUNT TPNUM, where TPNUM may also be \"all\";\n\
2532 if TPNUM is omitted, passcount refers to the last tracepoint defined.");
2534 add_com ("end", class_trace
, end_actions_pseudocommand
,
2535 "Ends a list of commands or actions.\n\
2536 Several GDB commands allow you to enter a list of commands or actions.\n\
2537 Entering \"end\" on a line by itself is the normal way to terminate\n\
2539 Note: the \"end\" command cannot be used at the gdb prompt.");
2541 add_com ("while-stepping", class_trace
, while_stepping_pseudocommand
,
2542 "Specify single-stepping behavior at a tracepoint.\n\
2543 Argument is number of instructions to trace in single-step mode\n\
2544 following the tracepoint. This command is normally followed by\n\
2545 one or more \"collect\" commands, to specify what to collect\n\
2546 while single-stepping.\n\n\
2547 Note: this command can only be used in a tracepoint \"actions\" list.");
2549 add_com_alias ("ws", "while-stepping", class_alias
, 0);
2550 add_com_alias ("stepping", "while-stepping", class_alias
, 0);
2552 add_com ("collect", class_trace
, collect_pseudocommand
,
2553 "Specify one or more data items to be collected at a tracepoint.\n\
2554 Accepts a comma-separated list of (one or more) arguments.\n\
2555 Things that may be collected include registers, variables, plus\n\
2556 the following special arguments:\n\
2557 $regs -- all registers.\n\
2558 $args -- all function arguments.\n\
2559 $locals -- all variables local to the block/function scope.\n\
2560 $(addr,len) -- a literal memory range.\n\
2561 $($reg,addr,len) -- a register-relative literal memory range.\n\n\
2562 Note: this command can only be used in a tracepoint \"actions\" list.");
2564 add_com ("actions", class_trace
, trace_actions_command
,
2565 "Specify the actions to be taken at a tracepoint.\n\
2566 Tracepoint actions may include collecting of specified data, \n\
2567 single-stepping, or enabling/disabling other tracepoints, \n\
2568 depending on target's capabilities.");
2570 add_cmd ("tracepoints", class_trace
, delete_trace_command
,
2571 "Delete specified tracepoints.\n\
2572 Arguments are tracepoint numbers, separated by spaces.\n\
2573 No argument means delete all tracepoints.",
2576 add_cmd ("tracepoints", class_trace
, disable_trace_command
,
2577 "Disable specified tracepoints.\n\
2578 Arguments are tracepoint numbers, separated by spaces.\n\
2579 No argument means disable all tracepoints.",
2582 add_cmd ("tracepoints", class_trace
, enable_trace_command
,
2583 "Enable specified tracepoints.\n\
2584 Arguments are tracepoint numbers, separated by spaces.\n\
2585 No argument means enable all tracepoints.",
2588 add_com ("trace", class_trace
, trace_command
,
2589 "Set a tracepoint at a specified line or function or address.\n\
2590 Argument may be a line number, function name, or '*' plus an address.\n\
2591 For a line number or function, trace at the start of its code.\n\
2592 If an address is specified, trace at that exact address.\n\n\
2593 Do \"help tracepoints\" for info on other tracepoint commands.");
2595 add_com_alias ("tp", "trace", class_alias
, 0);
2596 add_com_alias ("tr", "trace", class_alias
, 1);
2597 add_com_alias ("tra", "trace", class_alias
, 1);
2598 add_com_alias ("trac", "trace", class_alias
, 1);