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