]> Git Repo - binutils.git/blob - gdb/tracepoint.c
Thu Jul 23 17:01:17 1998 Michael Snyder <[email protected]>
[binutils.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.172037 seconds and 4 git commands to generate.