Sat Nov 21 17:15:40 1998 Philippe De Muyter <phdm@macqel.be>
[deliverable/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.h"
37 #include "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(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)
1161 struct collection_list *collect;
1162 struct symbol *sym;
1163 {
1164 unsigned long len;
1165 unsigned long reg;
1166 bfd_signed_vma offset;
1167
1168 len = TYPE_LENGTH (check_typedef (SYMBOL_TYPE (sym)));
1169 switch (SYMBOL_CLASS (sym)) {
1170 default:
1171 printf_filtered ("%s: don't know symbol class %d\n",
1172 SYMBOL_NAME (sym), SYMBOL_CLASS (sym));
1173 break;
1174 case LOC_CONST:
1175 printf_filtered ("%s is constant, value is %d: will not be collected.\n",
1176 SYMBOL_NAME (sym), SYMBOL_VALUE (sym));
1177 break;
1178 case LOC_STATIC:
1179 offset = SYMBOL_VALUE_ADDRESS (sym);
1180 if (info_verbose)
1181 printf_filtered ("LOC_STATIC %s: collect %d bytes at 0x%08x\n",
1182 SYMBOL_NAME (sym), len, offset);
1183 add_memrange (collect, -1, offset, len); /* 0 == memory */
1184 break;
1185 case LOC_REGISTER:
1186 case LOC_REGPARM:
1187 reg = SYMBOL_VALUE (sym);
1188 if (info_verbose)
1189 printf_filtered ("LOC_REG[parm] %s: ", SYMBOL_NAME (sym));
1190 add_register (collect, reg);
1191 /* check for doubles stored in two registers */
1192 /* FIXME: how about larger types stored in 3 or more regs? */
1193 if (TYPE_CODE (SYMBOL_TYPE (sym)) == TYPE_CODE_FLT &&
1194 len > REGISTER_RAW_SIZE (reg))
1195 add_register (collect, reg + 1);
1196 break;
1197 case LOC_REF_ARG:
1198 printf_filtered ("Sorry, don't know how to do LOC_REF_ARG yet.\n");
1199 printf_filtered (" (will not collect %s)\n",
1200 SYMBOL_NAME (sym));
1201 break;
1202 case LOC_ARG:
1203 offset = SYMBOL_VALUE (sym);
1204 reg = FP_REGNUM;
1205 if (info_verbose)
1206 {
1207 printf_filtered ("LOC_LOCAL %s: Collect %d bytes at offset",
1208 SYMBOL_NAME (sym), len);
1209 printf_filtered (" %d from frame ptr reg %d\n", offset, reg);
1210 }
1211 add_memrange (collect, reg, offset, len);
1212 break;
1213 case LOC_REGPARM_ADDR:
1214 reg = SYMBOL_VALUE (sym);
1215 offset = 0;
1216 if (info_verbose)
1217 {
1218 printf_filtered ("LOC_REGPARM_ADDR %s: Collect %d bytes at offset",
1219 SYMBOL_NAME (sym), len);
1220 printf_filtered (" %d from reg %d\n", offset, reg);
1221 }
1222 add_memrange (collect, reg, offset, len);
1223 break;
1224 case LOC_LOCAL:
1225 case LOC_LOCAL_ARG:
1226 offset = SYMBOL_VALUE (sym);
1227 reg = FP_REGNUM;
1228 if (info_verbose)
1229 {
1230 printf_filtered ("LOC_LOCAL %s: Collect %d bytes at offset",
1231 SYMBOL_NAME (sym), len);
1232 printf_filtered (" %d from frame ptr reg %d\n", offset, reg);
1233 }
1234 add_memrange (collect, reg, offset, len);
1235 break;
1236 case LOC_BASEREG:
1237 case LOC_BASEREG_ARG:
1238 reg = SYMBOL_BASEREG (sym);
1239 offset = SYMBOL_VALUE (sym);
1240 if (info_verbose)
1241 {
1242 printf_filtered ("LOC_BASEREG %s: collect %d bytes at offset %d from basereg %d\n",
1243 SYMBOL_NAME (sym), len, offset, reg);
1244 }
1245 add_memrange (collect, reg, offset, len);
1246 break;
1247 case LOC_UNRESOLVED:
1248 printf_filtered ("Don't know LOC_UNRESOLVED %s\n", SYMBOL_NAME (sym));
1249 break;
1250 case LOC_OPTIMIZED_OUT:
1251 printf_filtered ("%s has been optimized out of existance.\n",
1252 SYMBOL_NAME (sym));
1253 break;
1254 }
1255 }
1256
1257 /* Add all locals (or args) symbols to collection list */
1258 static void
1259 add_local_symbols (collect, pc, type)
1260 struct collection_list *collect;
1261 CORE_ADDR pc;
1262 int type;
1263 {
1264 struct symbol *sym;
1265 struct block *block;
1266 int i, nsyms, count = 0;
1267
1268 block = block_for_pc (pc);
1269 while (block != 0)
1270 {
1271 QUIT; /* allow user to bail out with ^C */
1272 nsyms = BLOCK_NSYMS (block);
1273 for (i = 0; i < nsyms; i++)
1274 {
1275 sym = BLOCK_SYM (block, i);
1276 switch (SYMBOL_CLASS (sym)) {
1277 case LOC_LOCAL:
1278 case LOC_STATIC:
1279 case LOC_REGISTER:
1280 case LOC_BASEREG:
1281 if (type == 'L') /* collecting Locals */
1282 {
1283 count++;
1284 collect_symbol (collect, sym);
1285 }
1286 break;
1287 case LOC_ARG:
1288 case LOC_LOCAL_ARG:
1289 case LOC_REF_ARG:
1290 case LOC_REGPARM:
1291 case LOC_REGPARM_ADDR:
1292 case LOC_BASEREG_ARG:
1293 if (type == 'A') /* collecting Arguments */
1294 {
1295 count++;
1296 collect_symbol (collect, sym);
1297 }
1298 }
1299 }
1300 if (BLOCK_FUNCTION (block))
1301 break;
1302 else
1303 block = BLOCK_SUPERBLOCK (block);
1304 }
1305 if (count == 0)
1306 warning ("No %s found in scope.", type == 'L' ? "locals" : "args");
1307 }
1308
1309 /* worker function */
1310 static void
1311 clear_collection_list (list)
1312 struct collection_list *list;
1313 {
1314 int ndx;
1315
1316 list->next_memrange = 0;
1317 for (ndx = 0; ndx < list->next_aexpr_elt; ndx++)
1318 {
1319 free_agent_expr(list->aexpr_list[ndx]);
1320 list->aexpr_list[ndx] = NULL;
1321 }
1322 list->next_aexpr_elt = 0;
1323 memset (list->regs_mask, 0, sizeof (list->regs_mask));
1324 }
1325
1326 /* reduce a collection list to string form (for gdb protocol) */
1327 static char **
1328 stringify_collection_list (list, string)
1329 struct collection_list *list;
1330 char *string;
1331 {
1332 char temp_buf[2048];
1333 int count;
1334 int ndx = 0;
1335 char *(*str_list)[];
1336 char *end;
1337 long i;
1338
1339 count = 1 + list->next_memrange + list->next_aexpr_elt + 1;
1340 str_list = (char *(*)[])xmalloc(count * sizeof (char *));
1341
1342 for (i = sizeof (list->regs_mask) - 1; i > 0; i--)
1343 if (list->regs_mask[i] != 0) /* skip leading zeroes in regs_mask */
1344 break;
1345 if (list->regs_mask[i] != 0) /* prepare to send regs_mask to the stub */
1346 {
1347 if (info_verbose)
1348 printf_filtered ("\nCollecting registers (mask): 0x");
1349 end = temp_buf;
1350 *end++='R';
1351 for (; i >= 0; i--)
1352 {
1353 QUIT; /* allow user to bail out with ^C */
1354 if (info_verbose)
1355 printf_filtered ("%02X", list->regs_mask[i]);
1356 sprintf (end, "%02X", list->regs_mask[i]);
1357 end += 2;
1358 }
1359 (*str_list)[ndx] = savestring(temp_buf, end - temp_buf);
1360 ndx++;
1361 }
1362 if (info_verbose)
1363 printf_filtered ("\n");
1364 if (list->next_memrange > 0 && info_verbose)
1365 printf_filtered ("Collecting memranges: \n");
1366 for (i = 0, count = 0, end = temp_buf; i < list->next_memrange; i++)
1367 {
1368 QUIT; /* allow user to bail out with ^C */
1369 if (info_verbose)
1370 printf_filtered ("(%d, 0x%x, %d)\n",
1371 list->list[i].type,
1372 list->list[i].start,
1373 list->list[i].end - list->list[i].start);
1374 if (count + 27 > MAX_AGENT_EXPR_LEN)
1375 {
1376 (*str_list)[ndx] = savestring(temp_buf, count);
1377 ndx++;
1378 count = 0;
1379 end = temp_buf;
1380 }
1381 sprintf (end, "M%X,%X,%X",
1382 list->list[i].type,
1383 list->list[i].start,
1384 list->list[i].end - list->list[i].start);
1385 count += strlen (end);
1386 end += strlen (end);
1387 }
1388
1389 for (i = 0; i < list->next_aexpr_elt; i++)
1390 {
1391 QUIT; /* allow user to bail out with ^C */
1392 if ((count + 10 + 2 * list->aexpr_list[i]->len) > MAX_AGENT_EXPR_LEN)
1393 {
1394 (*str_list)[ndx] = savestring(temp_buf, count);
1395 ndx++;
1396 count = 0;
1397 end = temp_buf;
1398 }
1399 sprintf (end, "X%08X,", list->aexpr_list[i]->len);
1400 end += 10; /* 'X' + 8 hex digits + ',' */
1401 count += 10;
1402
1403 end = mem2hex(list->aexpr_list[i]->buf, end, list->aexpr_list[i]->len);
1404 count += 2 * list->aexpr_list[i]->len;
1405 }
1406
1407 if (count != 0)
1408 {
1409 (*str_list)[ndx] = savestring(temp_buf, count);
1410 ndx++;
1411 count = 0;
1412 end = temp_buf;
1413 }
1414 (*str_list)[ndx] = NULL;
1415
1416 if (ndx == 0)
1417 return NULL;
1418 else
1419 return *str_list;
1420 }
1421
1422 void
1423 free_actions_list(actions_list)
1424 char **actions_list;
1425 {
1426 int ndx;
1427
1428 if (actions_list == 0)
1429 return;
1430
1431 for (ndx = 0; actions_list[ndx]; ndx++)
1432 free(actions_list[ndx]);
1433
1434 free(actions_list);
1435 }
1436
1437 /* render all actions into gdb protocol */
1438 static void
1439 encode_actions (t, tdp_actions, stepping_actions)
1440 struct tracepoint *t;
1441 char ***tdp_actions;
1442 char ***stepping_actions;
1443 {
1444 static char tdp_buff[2048], step_buff[2048];
1445 char *action_exp;
1446 struct expression *exp = NULL;
1447 struct action_line *action;
1448 bfd_signed_vma offset;
1449 long i;
1450 value_ptr tempval;
1451 struct collection_list *collect;
1452 struct cmd_list_element *cmd;
1453 struct agent_expr *aexpr;
1454
1455 clear_collection_list (&tracepoint_list);
1456 clear_collection_list (&stepping_list);
1457 collect = &tracepoint_list;
1458
1459 *tdp_actions = NULL;
1460 *stepping_actions = NULL;
1461
1462 for (action = t->actions; action; action = action->next)
1463 {
1464 QUIT; /* allow user to bail out with ^C */
1465 action_exp = action->action;
1466 while (isspace (*action_exp))
1467 action_exp++;
1468
1469 if (*action_exp == '#') /* comment line */
1470 return;
1471
1472 cmd = lookup_cmd (&action_exp, cmdlist, "", -1, 1);
1473 if (cmd == 0)
1474 error ("Bad action list item: %s", action_exp);
1475
1476 if (cmd->function.cfunc == collect_pseudocommand)
1477 {
1478 do { /* repeat over a comma-separated list */
1479 QUIT; /* allow user to bail out with ^C */
1480 while (isspace (*action_exp))
1481 action_exp++;
1482
1483 if (0 == strncasecmp ("$reg", action_exp, 4))
1484 {
1485 for (i = 0; i < NUM_REGS; i++)
1486 add_register (collect, i);
1487 action_exp = strchr (action_exp, ','); /* more? */
1488 }
1489 else if (0 == strncasecmp ("$arg", action_exp, 4))
1490 {
1491 add_local_symbols (collect, t->address, 'A');
1492 action_exp = strchr (action_exp, ','); /* more? */
1493 }
1494 else if (0 == strncasecmp ("$loc", action_exp, 4))
1495 {
1496 add_local_symbols (collect, t->address, 'L');
1497 action_exp = strchr (action_exp, ','); /* more? */
1498 }
1499 else
1500 {
1501 unsigned long addr, len;
1502 struct cleanup *old_chain = NULL;
1503 struct cleanup *old_chain1 = NULL;
1504 struct agent_reqs areqs;
1505
1506 exp = parse_exp_1 (&action_exp, block_for_pc (t->address), 1);
1507 old_chain = make_cleanup ((make_cleanup_func)
1508 free_current_contents, &exp);
1509
1510 switch (exp->elts[0].opcode) {
1511 case OP_REGISTER:
1512 i = exp->elts[1].longconst;
1513 if (info_verbose)
1514 printf_filtered ("OP_REGISTER: ");
1515 add_register (collect, i);
1516 break;
1517
1518 case UNOP_MEMVAL:
1519 /* safe because we know it's a simple expression */
1520 tempval = evaluate_expression (exp);
1521 addr = VALUE_ADDRESS (tempval) + VALUE_OFFSET (tempval);
1522 len = TYPE_LENGTH (check_typedef (exp->elts[1].type));
1523 add_memrange (collect, -1, addr, len);
1524 break;
1525
1526 case OP_VAR_VALUE:
1527 collect_symbol (collect, exp->elts[2].symbol);
1528 break;
1529
1530 default: /* full-fledged expression */
1531 aexpr = gen_trace_for_expr (exp);
1532
1533 old_chain1 = make_cleanup ((make_cleanup_func)
1534 free_agent_expr, aexpr);
1535
1536 ax_reqs (aexpr, &areqs);
1537 if (areqs.flaw != agent_flaw_none)
1538 error ("malformed expression");
1539
1540 if (areqs.min_height < 0)
1541 error ("gdb: Internal error: expression has min height < 0");
1542 if (areqs.max_height > 20)
1543 error ("expression too complicated, try simplifying");
1544
1545 discard_cleanups (old_chain1);
1546 add_aexpr (collect, aexpr);
1547
1548 /* take care of the registers */
1549 if (areqs.reg_mask_len > 0)
1550 {
1551 int ndx1;
1552 int ndx2;
1553
1554 for (ndx1 = 0; ndx1 < areqs.reg_mask_len; ndx1++)
1555 {
1556 QUIT; /* allow user to bail out with ^C */
1557 if (areqs.reg_mask[ndx1] != 0)
1558 {
1559 /* assume chars have 8 bits */
1560 for (ndx2 = 0; ndx2 < 8; ndx2++)
1561 if (areqs.reg_mask[ndx1] & (1 << ndx2))
1562 /* it's used -- record it */
1563 add_register (collect, ndx1 * 8 + ndx2);
1564 }
1565 }
1566 }
1567 break;
1568 } /* switch */
1569 do_cleanups (old_chain);
1570 } /* do */
1571 } while (action_exp && *action_exp++ == ',');
1572 } /* if */
1573 else if (cmd->function.cfunc == while_stepping_pseudocommand)
1574 {
1575 collect = &stepping_list;
1576 }
1577 else if (cmd->function.cfunc == end_actions_pseudocommand)
1578 {
1579 if (collect == &stepping_list) /* end stepping actions */
1580 collect = &tracepoint_list;
1581 else
1582 break; /* end tracepoint actions */
1583 }
1584 } /* for */
1585 memrange_sortmerge (&tracepoint_list);
1586 memrange_sortmerge (&stepping_list);
1587
1588 *tdp_actions = stringify_collection_list (&tracepoint_list, &tdp_buff);
1589 *stepping_actions = stringify_collection_list (&stepping_list, &step_buff);
1590 }
1591
1592 static void
1593 add_aexpr(collect, aexpr)
1594 struct collection_list *collect;
1595 struct agent_expr *aexpr;
1596 {
1597 if (collect->next_aexpr_elt >= collect->aexpr_listsize)
1598 {
1599 collect->aexpr_list =
1600 xrealloc (collect->aexpr_list,
1601 2 * collect->aexpr_listsize * sizeof (struct agent_expr *));
1602 collect->aexpr_listsize *= 2;
1603 }
1604 collect->aexpr_list[collect->next_aexpr_elt] = aexpr;
1605 collect->next_aexpr_elt++;
1606 }
1607
1608 static char target_buf[2048];
1609
1610 /* Set "transparent" memory ranges
1611
1612 Allow trace mechanism to treat text-like sections
1613 (and perhaps all read-only sections) transparently,
1614 i.e. don't reject memory requests from these address ranges
1615 just because they haven't been collected. */
1616
1617 static void
1618 remote_set_transparent_ranges (void)
1619 {
1620 extern bfd *exec_bfd;
1621 asection *s;
1622 bfd_size_type size;
1623 bfd_vma lma;
1624 int anysecs = 0;
1625
1626 if (!exec_bfd)
1627 return; /* no information to give. */
1628
1629 strcpy (target_buf, "QTro");
1630 for (s = exec_bfd->sections; s; s = s->next)
1631 {
1632 char tmp[40];
1633
1634 if ((s->flags & SEC_LOAD) == 0 ||
1635 /* (s->flags & SEC_CODE) == 0 || */
1636 (s->flags & SEC_READONLY) == 0)
1637 continue;
1638
1639 anysecs = 1;
1640 lma = s->lma;
1641 size = bfd_get_section_size_before_reloc (s);
1642 sprintf (tmp, ":%x,%x", lma, lma + size);
1643 strcat (target_buf, tmp);
1644 }
1645 if (anysecs)
1646 {
1647 putpkt (target_buf);
1648 getpkt (target_buf, 0);
1649 }
1650 }
1651
1652 /* tstart command:
1653
1654 Tell target to clear any previous trace experiment.
1655 Walk the list of tracepoints, and send them (and their actions)
1656 to the target. If no errors,
1657 Tell target to start a new trace experiment. */
1658
1659 static void
1660 trace_start_command (args, from_tty)
1661 char *args;
1662 int from_tty;
1663 { /* STUB_COMM MOSTLY_IMPLEMENTED */
1664 struct tracepoint *t;
1665 char buf[2048];
1666 char **tdp_actions;
1667 char **stepping_actions;
1668 int ndx;
1669 struct cleanup *old_chain = NULL;
1670
1671 dont_repeat (); /* like "run", dangerous to repeat accidentally */
1672
1673 if (target_is_remote ())
1674 {
1675 putpkt ("QTinit");
1676 remote_get_noisy_reply (target_buf);
1677 if (strcmp (target_buf, "OK"))
1678 error ("Target does not support this command.");
1679
1680 ALL_TRACEPOINTS (t)
1681 {
1682 int ss_count; /* if actions include singlestepping */
1683 int disable_mask; /* ??? */
1684 int enable_mask; /* ??? */
1685
1686 sprintf (buf, "QTDP:%x:%x:%c:%x:%x", t->number, t->address,
1687 t->enabled == enabled ? 'E' : 'D',
1688 t->step_count, t->pass_count);
1689
1690 if (t->actions)
1691 strcat (buf, "-");
1692 putpkt (buf);
1693 remote_get_noisy_reply (target_buf);
1694 if (strcmp (target_buf, "OK"))
1695 error ("Target does not support tracepoints.");
1696
1697 if (t->actions)
1698 {
1699 encode_actions (t, &tdp_actions, &stepping_actions);
1700 old_chain = make_cleanup (free_actions_list, tdp_actions);
1701 (void) make_cleanup (free_actions_list, stepping_actions);
1702
1703 /* do_single_steps (t); */
1704 if (tdp_actions)
1705 {
1706 for (ndx = 0; tdp_actions[ndx]; ndx++)
1707 {
1708 QUIT; /* allow user to bail out with ^C */
1709 sprintf (buf, "QTDP:-%x:%x:%s%c",
1710 t->number, t->address,
1711 tdp_actions[ndx],
1712 ((tdp_actions[ndx+1] || stepping_actions)
1713 ? '-' : 0));
1714 putpkt (buf);
1715 remote_get_noisy_reply (target_buf);
1716 if (strcmp (target_buf, "OK"))
1717 error ("Error on target while setting tracepoints.");
1718 }
1719 }
1720 if (stepping_actions)
1721 {
1722 for (ndx = 0; stepping_actions[ndx]; ndx++)
1723 {
1724 QUIT; /* allow user to bail out with ^C */
1725 sprintf (buf, "QTDP:-%x:%x:%s%s%s",
1726 t->number, t->address,
1727 ((ndx == 0) ? "S" : ""),
1728 stepping_actions[ndx],
1729 (stepping_actions[ndx+1] ? "-" : ""));
1730 putpkt (buf);
1731 remote_get_noisy_reply (target_buf);
1732 if (strcmp (target_buf, "OK"))
1733 error ("Error on target while setting tracepoints.");
1734 }
1735 }
1736
1737 do_cleanups (old_chain);
1738 }
1739 }
1740 /* Tell target to treat text-like sections as transparent */
1741 remote_set_transparent_ranges ();
1742 /* Now insert traps and begin collecting data */
1743 putpkt ("QTStart");
1744 remote_get_noisy_reply (target_buf);
1745 if (strcmp (target_buf, "OK"))
1746 error ("Bogus reply from target: %s", target_buf);
1747 set_traceframe_num (-1); /* all old traceframes invalidated */
1748 set_tracepoint_num (-1);
1749 set_traceframe_context(-1);
1750 trace_running_p = 1;
1751 if (trace_start_stop_hook)
1752 trace_start_stop_hook(1, from_tty);
1753
1754 }
1755 else
1756 error ("Trace can only be run on remote targets.");
1757 }
1758
1759 /* tstop command */
1760 static void
1761 trace_stop_command (args, from_tty)
1762 char *args;
1763 int from_tty;
1764 { /* STUB_COMM IS_IMPLEMENTED */
1765 if (target_is_remote ())
1766 {
1767 putpkt ("QTStop");
1768 remote_get_noisy_reply (target_buf);
1769 if (strcmp (target_buf, "OK"))
1770 error ("Bogus reply from target: %s", target_buf);
1771 trace_running_p = 0;
1772 if (trace_start_stop_hook)
1773 trace_start_stop_hook(0, from_tty);
1774 }
1775 else
1776 error ("Trace can only be run on remote targets.");
1777 }
1778
1779 unsigned long trace_running_p;
1780
1781 /* tstatus command */
1782 static void
1783 trace_status_command (args, from_tty)
1784 char *args;
1785 int from_tty;
1786 { /* STUB_COMM IS_IMPLEMENTED */
1787 if (target_is_remote ())
1788 {
1789 putpkt ("qTStatus");
1790 remote_get_noisy_reply (target_buf);
1791
1792 if (target_buf[0] != 'T' ||
1793 (target_buf[1] != '0' && target_buf[1] != '1'))
1794 error ("Bogus reply from target: %s", target_buf);
1795
1796 /* exported for use by the GUI */
1797 trace_running_p = (target_buf[1] == '1');
1798 }
1799 else
1800 error ("Trace can only be run on remote targets.");
1801 }
1802
1803 /* Worker function for the various flavors of the tfind command */
1804 static void
1805 finish_tfind_command (msg, from_tty)
1806 char *msg;
1807 int from_tty;
1808 {
1809 int target_frameno = -1, target_tracept = -1;
1810 CORE_ADDR old_frame_addr;
1811 struct symbol *old_func;
1812 char *reply;
1813
1814 old_frame_addr = FRAME_FP (get_current_frame ());
1815 old_func = find_pc_function (read_pc ());
1816
1817 putpkt (msg);
1818 reply = remote_get_noisy_reply (msg);
1819
1820 while (reply && *reply)
1821 switch (*reply) {
1822 case 'F':
1823 if ((target_frameno = (int) strtol (++reply, &reply, 16)) == -1)
1824 {
1825 /* A request for a non-existant trace frame has failed.
1826 Our response will be different, depending on FROM_TTY:
1827
1828 If FROM_TTY is true, meaning that this command was
1829 typed interactively by the user, then give an error
1830 and DO NOT change the state of traceframe_number etc.
1831
1832 However if FROM_TTY is false, meaning that we're either
1833 in a script, a loop, or a user-defined command, then
1834 DON'T give an error, but DO change the state of
1835 traceframe_number etc. to invalid.
1836
1837 The rationalle is that if you typed the command, you
1838 might just have committed a typo or something, and you'd
1839 like to NOT lose your current debugging state. However
1840 if you're in a user-defined command or especially in a
1841 loop, then you need a way to detect that the command
1842 failed WITHOUT aborting. This allows you to write
1843 scripts that search thru the trace buffer until the end,
1844 and then continue on to do something else. */
1845
1846 if (from_tty)
1847 error ("Target failed to find requested trace frame.");
1848 else
1849 {
1850 if (info_verbose)
1851 printf_filtered ("End of trace buffer.\n");
1852 /* The following will not recurse, since it's special-cased */
1853 trace_find_command ("-1", from_tty);
1854 reply = NULL; /* break out of loop,
1855 (avoid recursive nonsense) */
1856 }
1857 }
1858 break;
1859 case 'T':
1860 if ((target_tracept = (int) strtol (++reply, &reply, 16)) == -1)
1861 error ("Target failed to find requested trace frame.");
1862 break;
1863 case 'O': /* "OK"? */
1864 if (reply[1] == 'K' && reply[2] == '\0')
1865 reply += 2;
1866 else
1867 error ("Bogus reply from target: %s", reply);
1868 break;
1869 default:
1870 error ("Bogus reply from target: %s", reply);
1871 }
1872
1873 flush_cached_frames ();
1874 registers_changed ();
1875 select_frame (get_current_frame (), 0);
1876 set_traceframe_num (target_frameno);
1877 set_tracepoint_num (target_tracept);
1878 if (target_frameno == -1)
1879 set_traceframe_context (-1);
1880 else
1881 set_traceframe_context (read_pc ());
1882
1883 if (from_tty)
1884 {
1885 int source_only;
1886
1887 /* NOTE: in immitation of the step command, try to determine
1888 whether we have made a transition from one function to another.
1889 If so, we'll print the "stack frame" (ie. the new function and
1890 it's arguments) -- otherwise we'll just show the new source line.
1891
1892 This determination is made by checking (1) whether the current
1893 function has changed, and (2) whether the current FP has changed.
1894 Hack: if the FP wasn't collected, either at the current or the
1895 previous frame, assume that the FP has NOT changed. */
1896
1897 if (old_func == find_pc_function (read_pc ()) &&
1898 (old_frame_addr == 0 ||
1899 FRAME_FP (get_current_frame ()) == 0 ||
1900 old_frame_addr == FRAME_FP (get_current_frame ())))
1901 source_only = -1;
1902 else
1903 source_only = 1;
1904
1905 print_stack_frame (selected_frame, selected_frame_level, source_only);
1906 do_displays ();
1907 }
1908 }
1909
1910 /* trace_find_command takes a trace frame number n,
1911 sends "QTFrame:<n>" to the target,
1912 and accepts a reply that may contain several optional pieces
1913 of information: a frame number, a tracepoint number, and an
1914 indication of whether this is a trap frame or a stepping frame.
1915
1916 The minimal response is just "OK" (which indicates that the
1917 target does not give us a frame number or a tracepoint number).
1918 Instead of that, the target may send us a string containing
1919 any combination of:
1920 F<hexnum> (gives the selected frame number)
1921 T<hexnum> (gives the selected tracepoint number)
1922 */
1923
1924 /* tfind command */
1925 static void
1926 trace_find_command (args, from_tty)
1927 char *args;
1928 int from_tty;
1929 { /* STUB_COMM PART_IMPLEMENTED */
1930 /* this should only be called with a numeric argument */
1931 int frameno = -1;
1932 char *tmp;
1933
1934 if (target_is_remote ())
1935 {
1936 if (trace_find_hook)
1937 trace_find_hook (args, from_tty);
1938
1939 if (args == 0 || *args == 0)
1940 { /* TFIND with no args means find NEXT trace frame. */
1941 if (traceframe_number == -1)
1942 frameno = 0; /* "next" is first one */
1943 else
1944 frameno = traceframe_number + 1;
1945 }
1946 else if (0 == strcmp (args, "-"))
1947 {
1948 if (traceframe_number == -1)
1949 error ("not debugging trace buffer");
1950 else if (from_tty && traceframe_number == 0)
1951 error ("already at start of trace buffer");
1952
1953 frameno = traceframe_number - 1;
1954 }
1955 else
1956 frameno = parse_and_eval_address (args);
1957
1958 if (frameno < -1)
1959 error ("invalid input (%d is less than zero)", frameno);
1960
1961 sprintf (target_buf, "QTFrame:%x", frameno);
1962 finish_tfind_command (target_buf, from_tty);
1963 }
1964 else
1965 error ("Trace can only be run on remote targets.");
1966 }
1967
1968 /* tfind end */
1969 static void
1970 trace_find_end_command (args, from_tty)
1971 char *args;
1972 int from_tty;
1973 {
1974 trace_find_command ("-1", from_tty);
1975 }
1976
1977 /* tfind none */
1978 static void
1979 trace_find_none_command (args, from_tty)
1980 char *args;
1981 int from_tty;
1982 {
1983 trace_find_command ("-1", from_tty);
1984 }
1985
1986 /* tfind start */
1987 static void
1988 trace_find_start_command (args, from_tty)
1989 char *args;
1990 int from_tty;
1991 {
1992 trace_find_command ("0", from_tty);
1993 }
1994
1995 /* tfind pc command */
1996 static void
1997 trace_find_pc_command (args, from_tty)
1998 char *args;
1999 int from_tty;
2000 { /* STUB_COMM PART_IMPLEMENTED */
2001 CORE_ADDR pc;
2002 char *tmp;
2003
2004 if (target_is_remote ())
2005 {
2006 if (args == 0 || *args == 0)
2007 pc = read_pc (); /* default is current pc */
2008 else
2009 pc = parse_and_eval_address (args);
2010
2011 sprintf (target_buf, "QTFrame:pc:%x", pc);
2012 finish_tfind_command (target_buf, from_tty);
2013 }
2014 else
2015 error ("Trace can only be run on remote targets.");
2016 }
2017
2018 /* tfind tracepoint command */
2019 static void
2020 trace_find_tracepoint_command (args, from_tty)
2021 char *args;
2022 int from_tty;
2023 { /* STUB_COMM PART_IMPLEMENTED */
2024 int tdp;
2025 char buf[40], *tmp;
2026
2027 if (target_is_remote ())
2028 {
2029 if (args == 0 || *args == 0)
2030 if (tracepoint_number == -1)
2031 error ("No current tracepoint -- please supply an argument.");
2032 else
2033 tdp = tracepoint_number; /* default is current TDP */
2034 else
2035 tdp = parse_and_eval_address (args);
2036
2037 sprintf (target_buf, "QTFrame:tdp:%x", tdp);
2038 finish_tfind_command (target_buf, from_tty);
2039 }
2040 else
2041 error ("Trace can only be run on remote targets.");
2042 }
2043
2044 /* TFIND LINE command:
2045
2046 This command will take a sourceline for argument, just like BREAK
2047 or TRACE (ie. anything that "decode_line_1" can handle).
2048
2049 With no argument, this command will find the next trace frame
2050 corresponding to a source line OTHER THAN THE CURRENT ONE. */
2051
2052 static void
2053 trace_find_line_command (args, from_tty)
2054 char *args;
2055 int from_tty;
2056 { /* STUB_COMM PART_IMPLEMENTED */
2057 static CORE_ADDR start_pc, end_pc;
2058 struct symtabs_and_lines sals;
2059 struct symtab_and_line sal;
2060 char *tmp;
2061 struct cleanup *old_chain;
2062
2063 if (target_is_remote ())
2064 {
2065 if (args == 0 || *args == 0)
2066 {
2067 sal = find_pc_line ((get_current_frame ())->pc, 0);
2068 sals.nelts = 1;
2069 sals.sals = (struct symtab_and_line *)
2070 xmalloc (sizeof (struct symtab_and_line));
2071 sals.sals[0] = sal;
2072 }
2073 else
2074 {
2075 sals = decode_line_spec (args, 1);
2076 sal = sals.sals[0];
2077 }
2078
2079 old_chain = make_cleanup (free, sals.sals);
2080 if (sal.symtab == 0)
2081 {
2082 printf_filtered ("TFIND: No line number information available");
2083 if (sal.pc != 0)
2084 {
2085 /* This is useful for "info line *0x7f34". If we can't tell the
2086 user about a source line, at least let them have the symbolic
2087 address. */
2088 printf_filtered (" for address ");
2089 wrap_here (" ");
2090 print_address (sal.pc, gdb_stdout);
2091 printf_filtered (";\n -- will attempt to find by PC. \n");
2092 }
2093 else
2094 {
2095 printf_filtered (".\n");
2096 return; /* no line, no PC; what can we do? */
2097 }
2098 }
2099 else if (sal.line > 0
2100 && find_line_pc_range (sal, &start_pc, &end_pc))
2101 {
2102 if (start_pc == end_pc)
2103 {
2104 printf_filtered ("Line %d of \"%s\"",
2105 sal.line, sal.symtab->filename);
2106 wrap_here (" ");
2107 printf_filtered (" is at address ");
2108 print_address (start_pc, gdb_stdout);
2109 wrap_here (" ");
2110 printf_filtered (" but contains no code.\n");
2111 sal = find_pc_line (start_pc, 0);
2112 if (sal.line > 0 &&
2113 find_line_pc_range (sal, &start_pc, &end_pc) &&
2114 start_pc != end_pc)
2115 printf_filtered ("Attempting to find line %d instead.\n",
2116 sal.line);
2117 else
2118 error ("Cannot find a good line.");
2119 }
2120 }
2121 else
2122 /* Is there any case in which we get here, and have an address
2123 which the user would want to see? If we have debugging symbols
2124 and no line numbers? */
2125 error ("Line number %d is out of range for \"%s\".\n",
2126 sal.line, sal.symtab->filename);
2127
2128 if (args && *args) /* find within range of stated line */
2129 sprintf (target_buf, "QTFrame:range:%x:%x", start_pc, end_pc - 1);
2130 else /* find OUTSIDE OF range of CURRENT line */
2131 sprintf (target_buf, "QTFrame:outside:%x:%x", start_pc, end_pc - 1);
2132 finish_tfind_command (target_buf, from_tty);
2133 do_cleanups (old_chain);
2134 }
2135 else
2136 error ("Trace can only be run on remote targets.");
2137 }
2138
2139 /* tfind range command */
2140 static void
2141 trace_find_range_command (args, from_tty)
2142 char *args;
2143 int from_tty;
2144 { /* STUB_COMM PART_IMPLEMENTED */
2145 static CORE_ADDR start, stop;
2146 char *tmp;
2147
2148 if (target_is_remote ())
2149 {
2150 if (args == 0 || *args == 0)
2151 { /* XXX FIXME: what should default behavior be? */
2152 printf_filtered ("Usage: tfind range <startaddr>,<endaddr>\n");
2153 return;
2154 }
2155
2156 if (0 != (tmp = strchr (args, ',' )))
2157 {
2158 *tmp++ = '\0'; /* terminate start address */
2159 while (isspace (*tmp))
2160 tmp++;
2161 start = parse_and_eval_address (args);
2162 stop = parse_and_eval_address (tmp);
2163 }
2164 else
2165 { /* no explicit end address? */
2166 start = parse_and_eval_address (args);
2167 stop = start + 1; /* ??? */
2168 }
2169
2170 sprintf (target_buf, "QTFrame:range:%x:%x", start, stop);
2171 finish_tfind_command (target_buf, from_tty);
2172 }
2173 else
2174 error ("Trace can only be run on remote targets.");
2175 }
2176
2177 /* tfind outside command */
2178 static void
2179 trace_find_outside_command (args, from_tty)
2180 char *args;
2181 int from_tty;
2182 { /* STUB_COMM PART_IMPLEMENTED */
2183 CORE_ADDR start, stop;
2184 char *tmp;
2185
2186 if (target_is_remote ())
2187 {
2188 if (args == 0 || *args == 0)
2189 { /* XXX FIXME: what should default behavior be? */
2190 printf_filtered ("Usage: tfind outside <startaddr>,<endaddr>\n");
2191 return;
2192 }
2193
2194 if (0 != (tmp = strchr (args, ',' )))
2195 {
2196 *tmp++ = '\0'; /* terminate start address */
2197 while (isspace (*tmp))
2198 tmp++;
2199 start = parse_and_eval_address (args);
2200 stop = parse_and_eval_address (tmp);
2201 }
2202 else
2203 { /* no explicit end address? */
2204 start = parse_and_eval_address (args);
2205 stop = start + 1; /* ??? */
2206 }
2207
2208 sprintf (target_buf, "QTFrame:outside:%x:%x", start, stop);
2209 finish_tfind_command (target_buf, from_tty);
2210 }
2211 else
2212 error ("Trace can only be run on remote targets.");
2213 }
2214
2215 /* save-tracepoints command */
2216 static void
2217 tracepoint_save_command (args, from_tty)
2218 char *args;
2219 int from_tty;
2220 {
2221 struct tracepoint *tp;
2222 struct action_line *line;
2223 FILE *fp;
2224 char *i1 = " ", *i2 = " ";
2225 char *indent, *actionline;
2226
2227 if (args == 0 || *args == 0)
2228 error ("Argument required (file name in which to save tracepoints");
2229
2230 if (tracepoint_chain == 0)
2231 {
2232 warning ("save-tracepoints: no tracepoints to save.\n");
2233 return;
2234 }
2235
2236 if (!(fp = fopen (args, "w")))
2237 error ("Unable to open file '%s' for saving tracepoints");
2238
2239 ALL_TRACEPOINTS (tp)
2240 {
2241 if (tp->addr_string)
2242 fprintf (fp, "trace %s\n", tp->addr_string);
2243 else
2244 fprintf (fp, "trace *0x%x\n", tp->address);
2245
2246 if (tp->pass_count)
2247 fprintf (fp, " passcount %d\n", tp->pass_count);
2248
2249 if (tp->actions)
2250 {
2251 fprintf (fp, " actions\n");
2252 indent = i1;
2253 for (line = tp->actions; line; line = line->next)
2254 {
2255 struct cmd_list_element *cmd;
2256
2257 QUIT; /* allow user to bail out with ^C */
2258 actionline = line->action;
2259 while (isspace(*actionline))
2260 actionline++;
2261
2262 fprintf (fp, "%s%s\n", indent, actionline);
2263 if (*actionline != '#') /* skip for comment lines */
2264 {
2265 cmd = lookup_cmd (&actionline, cmdlist, "", -1, 1);
2266 if (cmd == 0)
2267 error ("Bad action list item: %s", actionline);
2268 if (cmd->function.cfunc == while_stepping_pseudocommand)
2269 indent = i2;
2270 else if (cmd->function.cfunc == end_actions_pseudocommand)
2271 indent = i1;
2272 }
2273 }
2274 }
2275 }
2276 fclose (fp);
2277 if (from_tty)
2278 printf_filtered ("Tracepoints saved to file '%s'.\n", args);
2279 return;
2280 }
2281
2282 /* info scope command: list the locals for a scope. */
2283 static void
2284 scope_info (args, from_tty)
2285 char *args;
2286 int from_tty;
2287 {
2288 struct symtab_and_line sal;
2289 struct symtabs_and_lines sals;
2290 struct symbol *sym;
2291 struct minimal_symbol *msym;
2292 struct block *block;
2293 char **canonical, *symname, *save_args = args;
2294 int i, nsyms, count = 0;
2295
2296 if (args == 0 || *args == 0)
2297 error ("requires an argument (function, line or *addr) to define a scope");
2298
2299 sals = decode_line_1 (&args, 1, NULL, 0, &canonical);
2300 if (sals.nelts == 0)
2301 return; /* presumably decode_line_1 has already warned */
2302
2303 /* Resolve line numbers to PC */
2304 resolve_sal_pc (&sals.sals[0]);
2305 block = block_for_pc (sals.sals[0].pc);
2306
2307 while (block != 0)
2308 {
2309 QUIT; /* allow user to bail out with ^C */
2310 nsyms = BLOCK_NSYMS (block);
2311 for (i = 0; i < nsyms; i++)
2312 {
2313 QUIT; /* allow user to bail out with ^C */
2314 if (count == 0)
2315 printf_filtered ("Scope for %s:\n", save_args);
2316 count++;
2317 sym = BLOCK_SYM (block, i);
2318 symname = SYMBOL_NAME (sym);
2319 if (symname == NULL || *symname == '\0')
2320 continue; /* probably botched, certainly useless */
2321
2322 printf_filtered ("Symbol %s is ", symname);
2323 switch (SYMBOL_CLASS (sym)) {
2324 default:
2325 case LOC_UNDEF: /* messed up symbol? */
2326 printf_filtered ("a bogus symbol, class %d.\n",
2327 SYMBOL_CLASS (sym));
2328 count--; /* don't count this one */
2329 continue;
2330 case LOC_CONST:
2331 printf_filtered ("a constant with value %d (0x%x)",
2332 SYMBOL_VALUE (sym), SYMBOL_VALUE (sym));
2333 break;
2334 case LOC_CONST_BYTES:
2335 printf_filtered ("constant bytes: ");
2336 if (SYMBOL_TYPE (sym))
2337 for (i = 0; i < TYPE_LENGTH (SYMBOL_TYPE (sym)); i++)
2338 fprintf_filtered (gdb_stdout, " %02x",
2339 (unsigned) SYMBOL_VALUE_BYTES (sym) [i]);
2340 break;
2341 case LOC_STATIC:
2342 printf_filtered ("in static storage at address ");
2343 print_address_numeric (SYMBOL_VALUE_ADDRESS (sym), 1, gdb_stdout);
2344 break;
2345 case LOC_REGISTER:
2346 printf_filtered ("a local variable in register $%s",
2347 reg_names [SYMBOL_VALUE (sym)]);
2348 break;
2349 case LOC_ARG:
2350 case LOC_LOCAL_ARG:
2351 printf_filtered ("an argument at stack/frame offset %ld",
2352 SYMBOL_VALUE (sym));
2353 break;
2354 case LOC_LOCAL:
2355 printf_filtered ("a local variable at frame offset %ld",
2356 SYMBOL_VALUE (sym));
2357 break;
2358 case LOC_REF_ARG:
2359 printf_filtered ("a reference argument at offset %ld",
2360 SYMBOL_VALUE (sym));
2361 break;
2362 case LOC_REGPARM:
2363 printf_filtered ("an argument in register $%s",
2364 reg_names[SYMBOL_VALUE (sym)]);
2365 break;
2366 case LOC_REGPARM_ADDR:
2367 printf_filtered ("the address of an argument, in register $%s",
2368 reg_names[SYMBOL_VALUE (sym)]);
2369 break;
2370 case LOC_TYPEDEF:
2371 printf_filtered ("a typedef.\n");
2372 continue;
2373 case LOC_LABEL:
2374 printf_filtered ("a label at address ");
2375 print_address_numeric (SYMBOL_VALUE_ADDRESS (sym), 1, gdb_stdout);
2376 break;
2377 case LOC_BLOCK:
2378 printf_filtered ("a function at address ");
2379 print_address_numeric (BLOCK_START (SYMBOL_BLOCK_VALUE (sym)), 1,
2380 gdb_stdout);
2381 break;
2382 case LOC_BASEREG:
2383 printf_filtered ("a variable at offset %d from register $%s",
2384 SYMBOL_VALUE (sym),
2385 reg_names [SYMBOL_BASEREG (sym)]);
2386 break;
2387 case LOC_BASEREG_ARG:
2388 printf_filtered ("an argument at offset %d from register $%s",
2389 SYMBOL_VALUE (sym),
2390 reg_names [SYMBOL_BASEREG (sym)]);
2391 break;
2392 case LOC_UNRESOLVED:
2393 msym = lookup_minimal_symbol (SYMBOL_NAME (sym), NULL, NULL);
2394 if (msym == NULL)
2395 printf_filtered ("Unresolved Static");
2396 else
2397 {
2398 printf_filtered ("static storage at address ");
2399 print_address_numeric (SYMBOL_VALUE_ADDRESS (msym), 1,
2400 gdb_stdout);
2401 }
2402 break;
2403 case LOC_OPTIMIZED_OUT:
2404 printf_filtered ("optimized out.\n");
2405 continue;
2406 }
2407 if (SYMBOL_TYPE (sym))
2408 printf_filtered (", length %d.\n",
2409 TYPE_LENGTH (check_typedef (SYMBOL_TYPE (sym))));
2410 }
2411 if (BLOCK_FUNCTION (block))
2412 break;
2413 else
2414 block = BLOCK_SUPERBLOCK (block);
2415 }
2416 if (count <= 0)
2417 printf_filtered ("Scope for %s contains no locals or arguments.\n",
2418 save_args);
2419 }
2420
2421 /* worker function (cleanup) */
2422 static void
2423 replace_comma (comma)
2424 char *comma;
2425 {
2426 *comma = ',';
2427 }
2428
2429 /* tdump command */
2430 static void
2431 trace_dump_command (args, from_tty)
2432 char *args;
2433 int from_tty;
2434 {
2435 struct tracepoint *t;
2436 struct action_line *action;
2437 char *action_exp, *next_comma;
2438 struct cleanup *old_cleanups;
2439 int stepping_actions = 0;
2440 int stepping_frame = 0;
2441
2442 if (!target_is_remote ())
2443 {
2444 error ("Trace can only be run on remote targets.");
2445 return;
2446 }
2447
2448 if (tracepoint_number == -1)
2449 {
2450 warning ("No current trace frame.");
2451 return;
2452 }
2453
2454 ALL_TRACEPOINTS (t)
2455 if (t->number == tracepoint_number)
2456 break;
2457
2458 if (t == NULL)
2459 error ("No known tracepoint matches 'current' tracepoint #%d.",
2460 tracepoint_number);
2461
2462 old_cleanups = make_cleanup (null_cleanup, NULL);
2463
2464 printf_filtered ("Data collected at tracepoint %d, trace frame %d:\n",
2465 tracepoint_number, traceframe_number);
2466
2467 /* The current frame is a trap frame if the frame PC is equal
2468 to the tracepoint PC. If not, then the current frame was
2469 collected during single-stepping. */
2470
2471 stepping_frame = (t->address != read_pc());
2472
2473 for (action = t->actions; action; action = action->next)
2474 {
2475 struct cmd_list_element *cmd;
2476
2477 QUIT; /* allow user to bail out with ^C */
2478 action_exp = action->action;
2479 while (isspace (*action_exp))
2480 action_exp++;
2481
2482 /* The collection actions to be done while stepping are
2483 bracketed by the commands "while-stepping" and "end". */
2484
2485 if (*action_exp == '#') /* comment line */
2486 continue;
2487
2488 cmd = lookup_cmd (&action_exp, cmdlist, "", -1, 1);
2489 if (cmd == 0)
2490 error ("Bad action list item: %s", action_exp);
2491
2492 if (cmd->function.cfunc == while_stepping_pseudocommand)
2493 stepping_actions = 1;
2494 else if (cmd->function.cfunc == end_actions_pseudocommand)
2495 stepping_actions = 0;
2496 else if (cmd->function.cfunc == collect_pseudocommand)
2497 {
2498 /* Display the collected data.
2499 For the trap frame, display only what was collected at the trap.
2500 Likewise for stepping frames, display only what was collected
2501 while stepping. This means that the two boolean variables,
2502 STEPPING_FRAME and STEPPING_ACTIONS should be equal. */
2503 if (stepping_frame == stepping_actions)
2504 {
2505 do { /* repeat over a comma-separated list */
2506 QUIT; /* allow user to bail out with ^C */
2507 if (*action_exp == ',')
2508 action_exp++;
2509 while (isspace (*action_exp))
2510 action_exp++;
2511
2512 next_comma = strchr (action_exp, ',');
2513
2514 if (0 == strncasecmp (action_exp, "$reg", 4))
2515 registers_info (NULL, from_tty);
2516 else if (0 == strncasecmp (action_exp, "$loc", 4))
2517 locals_info (NULL, from_tty);
2518 else if (0 == strncasecmp (action_exp, "$arg", 4))
2519 args_info (NULL, from_tty);
2520 else
2521 { /* variable */
2522 if (next_comma)
2523 {
2524 make_cleanup (replace_comma, next_comma);
2525 *next_comma = '\0';
2526 }
2527 printf_filtered ("%s = ", action_exp);
2528 output_command (action_exp, from_tty);
2529 printf_filtered ("\n");
2530 }
2531 if (next_comma)
2532 *next_comma = ',';
2533 action_exp = next_comma;
2534 } while (action_exp && *action_exp == ',');
2535 }
2536 }
2537 }
2538 discard_cleanups (old_cleanups);
2539 }
2540
2541 /* Convert the memory pointed to by mem into hex, placing result in buf.
2542 * Return a pointer to the last char put in buf (null)
2543 * "stolen" from sparc-stub.c
2544 */
2545
2546 static const char hexchars[]="0123456789abcdef";
2547
2548 static unsigned char *
2549 mem2hex(mem, buf, count)
2550 unsigned char *mem;
2551 unsigned char *buf;
2552 int count;
2553 {
2554 unsigned char ch;
2555
2556 while (count-- > 0)
2557 {
2558 ch = *mem++;
2559
2560 *buf++ = hexchars[ch >> 4];
2561 *buf++ = hexchars[ch & 0xf];
2562 }
2563
2564 *buf = 0;
2565
2566 return buf;
2567 }
2568
2569 int get_traceframe_number()
2570 {
2571 return traceframe_number;
2572 }
2573
2574
2575 /* module initialization */
2576 void
2577 _initialize_tracepoint ()
2578 {
2579 tracepoint_chain = 0;
2580 tracepoint_count = 0;
2581 traceframe_number = -1;
2582 tracepoint_number = -1;
2583
2584 set_internalvar (lookup_internalvar ("tpnum"),
2585 value_from_longest (builtin_type_int, (LONGEST) 0));
2586 set_internalvar (lookup_internalvar ("trace_frame"),
2587 value_from_longest (builtin_type_int, (LONGEST) -1));
2588
2589 if (tracepoint_list.list == NULL)
2590 {
2591 tracepoint_list.listsize = 128;
2592 tracepoint_list.list = xmalloc
2593 (tracepoint_list.listsize * sizeof (struct memrange));
2594 }
2595 if (tracepoint_list.aexpr_list == NULL)
2596 {
2597 tracepoint_list.aexpr_listsize = 128;
2598 tracepoint_list.aexpr_list = xmalloc
2599 (tracepoint_list.aexpr_listsize * sizeof (struct agent_expr *));
2600 }
2601
2602 if (stepping_list.list == NULL)
2603 {
2604 stepping_list.listsize = 128;
2605 stepping_list.list = xmalloc
2606 (stepping_list.listsize * sizeof (struct memrange));
2607 }
2608
2609 if (stepping_list.aexpr_list == NULL)
2610 {
2611 stepping_list.aexpr_listsize = 128;
2612 stepping_list.aexpr_list = xmalloc
2613 (stepping_list.aexpr_listsize * sizeof (struct agent_expr *));
2614 }
2615
2616 add_info ("scope", scope_info,
2617 "List the variables local to a scope");
2618
2619 add_cmd ("tracepoints", class_trace, NO_FUNCTION,
2620 "Tracing of program execution without stopping the program.",
2621 &cmdlist);
2622
2623 add_info ("tracepoints", tracepoints_info,
2624 "Status of tracepoints, or tracepoint number NUMBER.\n\
2625 Convenience variable \"$tpnum\" contains the number of the\n\
2626 last tracepoint set.");
2627
2628 add_info_alias ("tp", "tracepoints", 1);
2629
2630 add_com ("save-tracepoints", class_trace, tracepoint_save_command,
2631 "Save current tracepoint definitions as a script.\n\
2632 Use the 'source' command in another debug session to restore them.");
2633
2634 add_com ("tdump", class_trace, trace_dump_command,
2635 "Print everything collected at the current tracepoint.");
2636
2637 add_prefix_cmd ("tfind", class_trace, trace_find_command,
2638 "Select a trace frame;\n\
2639 No argument means forward by one frame; '-' meand backward by one frame.",
2640 &tfindlist, "tfind ", 1, &cmdlist);
2641
2642 add_cmd ("outside", class_trace, trace_find_outside_command,
2643 "Select a trace frame whose PC is outside the given \
2644 range.\nUsage: tfind outside addr1, addr2",
2645 &tfindlist);
2646
2647 add_cmd ("range", class_trace, trace_find_range_command,
2648 "Select a trace frame whose PC is in the given range.\n\
2649 Usage: tfind range addr1,addr2",
2650 &tfindlist);
2651
2652 add_cmd ("line", class_trace, trace_find_line_command,
2653 "Select a trace frame by source line.\n\
2654 Argument can be a line number (with optional source file), \n\
2655 a function name, or '*' followed by an address.\n\
2656 Default argument is 'the next source line that was traced'.",
2657 &tfindlist);
2658
2659 add_cmd ("tracepoint", class_trace, trace_find_tracepoint_command,
2660 "Select a trace frame by tracepoint number.\n\
2661 Default is the tracepoint for the current trace frame.",
2662 &tfindlist);
2663
2664 add_cmd ("pc", class_trace, trace_find_pc_command,
2665 "Select a trace frame by PC.\n\
2666 Default is the current PC, or the PC of the current trace frame.",
2667 &tfindlist);
2668
2669 add_cmd ("end", class_trace, trace_find_end_command,
2670 "Synonym for 'none'.\n\
2671 De-select any trace frame and resume 'live' debugging.",
2672 &tfindlist);
2673
2674 add_cmd ("none", class_trace, trace_find_none_command,
2675 "De-select any trace frame and resume 'live' debugging.",
2676 &tfindlist);
2677
2678 add_cmd ("start", class_trace, trace_find_start_command,
2679 "Select the first trace frame in the trace buffer.",
2680 &tfindlist);
2681
2682 add_com ("tstatus", class_trace, trace_status_command,
2683 "Display the status of the current trace data collection.");
2684
2685 add_com ("tstop", class_trace, trace_stop_command,
2686 "Stop trace data collection.");
2687
2688 add_com ("tstart", class_trace, trace_start_command,
2689 "Start trace data collection.");
2690
2691 add_com ("passcount", class_trace, trace_pass_command,
2692 "Set the passcount for a tracepoint.\n\
2693 The trace will end when the tracepoint has been passed 'count' times.\n\
2694 Usage: passcount COUNT TPNUM, where TPNUM may also be \"all\";\n\
2695 if TPNUM is omitted, passcount refers to the last tracepoint defined.");
2696
2697 add_com ("end", class_trace, end_actions_pseudocommand,
2698 "Ends a list of commands or actions.\n\
2699 Several GDB commands allow you to enter a list of commands or actions.\n\
2700 Entering \"end\" on a line by itself is the normal way to terminate\n\
2701 such a list.\n\n\
2702 Note: the \"end\" command cannot be used at the gdb prompt.");
2703
2704 add_com ("while-stepping", class_trace, while_stepping_pseudocommand,
2705 "Specify single-stepping behavior at a tracepoint.\n\
2706 Argument is number of instructions to trace in single-step mode\n\
2707 following the tracepoint. This command is normally followed by\n\
2708 one or more \"collect\" commands, to specify what to collect\n\
2709 while single-stepping.\n\n\
2710 Note: this command can only be used in a tracepoint \"actions\" list.");
2711
2712 add_com_alias ("ws", "while-stepping", class_alias, 0);
2713 add_com_alias ("stepping", "while-stepping", class_alias, 0);
2714
2715 add_com ("collect", class_trace, collect_pseudocommand,
2716 "Specify one or more data items to be collected at a tracepoint.\n\
2717 Accepts a comma-separated list of (one or more) expressions. GDB will\n\
2718 collect all data (variables, registers) referenced by that expression.\n\
2719 Also accepts the following special arguments:\n\
2720 $regs -- all registers.\n\
2721 $args -- all function arguments.\n\
2722 $locals -- all variables local to the block/function scope.\n\
2723 Note: this command can only be used in a tracepoint \"actions\" list.");
2724
2725 add_com ("actions", class_trace, trace_actions_command,
2726 "Specify the actions to be taken at a tracepoint.\n\
2727 Tracepoint actions may include collecting of specified data, \n\
2728 single-stepping, or enabling/disabling other tracepoints, \n\
2729 depending on target's capabilities.");
2730
2731 add_cmd ("tracepoints", class_trace, delete_trace_command,
2732 "Delete specified tracepoints.\n\
2733 Arguments are tracepoint numbers, separated by spaces.\n\
2734 No argument means delete all tracepoints.",
2735 &deletelist);
2736
2737 add_cmd ("tracepoints", class_trace, disable_trace_command,
2738 "Disable specified tracepoints.\n\
2739 Arguments are tracepoint numbers, separated by spaces.\n\
2740 No argument means disable all tracepoints.",
2741 &disablelist);
2742
2743 add_cmd ("tracepoints", class_trace, enable_trace_command,
2744 "Enable specified tracepoints.\n\
2745 Arguments are tracepoint numbers, separated by spaces.\n\
2746 No argument means enable all tracepoints.",
2747 &enablelist);
2748
2749 add_com ("trace", class_trace, trace_command,
2750 "Set a tracepoint at a specified line or function or address.\n\
2751 Argument may be a line number, function name, or '*' plus an address.\n\
2752 For a line number or function, trace at the start of its code.\n\
2753 If an address is specified, trace at that exact address.\n\n\
2754 Do \"help tracepoints\" for info on other tracepoint commands.");
2755
2756 add_com_alias ("tp", "trace", class_alias, 0);
2757 add_com_alias ("tr", "trace", class_alias, 1);
2758 add_com_alias ("tra", "trace", class_alias, 1);
2759 add_com_alias ("trac", "trace", class_alias, 1);
2760 }
2761
This page took 0.08743 seconds and 4 git commands to generate.