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