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