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