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