OSDN Git Service

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