Add C_THUMBEXT etc.
[deliverable/binutils-gdb.git] / gdb / tracepoint.c
CommitLineData
6a02d201
MS
1/* Tracing functionality for remote targets in custom GDB protocol
2 Copyright 1997 Free Software Foundation, Inc.
3
4This file is part of GDB.
5
6This program is free software; you can redistribute it and/or modify
7it under the terms of the GNU General Public License as published by
8the Free Software Foundation; either version 2 of the License, or
9(at your option) any later version.
10
11This program is distributed in the hope that it will be useful,
12but WITHOUT ANY WARRANTY; without even the implied warranty of
13MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14GNU General Public License for more details.
15
16You should have received a copy of the GNU General Public License
17along with this program; if not, write to the Free Software
18Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
19
20#include "defs.h"
21#include "symtab.h"
22#include "frame.h"
23#include "tracepoint.h"
24#include "gdbtypes.h"
25#include "expression.h"
26#include "gdbcmd.h"
27#include "value.h"
28#include "target.h"
29#include "language.h"
6156728b 30#include "gdb_string.h"
6a02d201
MS
31
32/* readline include files */
33#include "readline.h"
34#include "history.h"
35
36/* readline defines this. */
37#undef savestring
38
39#ifdef HAVE_UNISTD_H
40#include <unistd.h>
41#endif
42
43extern int info_verbose;
44
45/* If this definition isn't overridden by the header files, assume
46 that isatty and fileno exist on this system. */
47#ifndef ISATTY
48#define ISATTY(FP) (isatty (fileno (FP)))
49#endif
50
6a02d201
MS
51/* Chain of all tracepoints defined. */
52struct tracepoint *tracepoint_chain;
53
54/* Number of last tracepoint made. */
55static int tracepoint_count;
56
57/* Number of last traceframe collected. */
58static int traceframe_number;
59
6156728b
MS
60/* Tracepoint for last traceframe collected. */
61static int tracepoint_number;
62
63/* Symbol for function for last traceframe collected */
64static struct symbol *traceframe_fun;
65
66/* Symtab and line for last traceframe collected */
67static struct symtab_and_line traceframe_sal;
68
6a02d201
MS
69/* Utility: returns true if "target remote" */
70static int
71target_is_remote ()
72{
73 if (current_target.to_shortname &&
74 strcmp (current_target.to_shortname, "remote") == 0)
75 return 1;
76 else
77 return 0;
78}
79
80/* Utility: generate error from an incoming stub packet. */
81static void
82trace_error (buf)
83 char *buf;
84{
85 if (*buf++ != 'E')
86 return; /* not an error msg */
87 switch (*buf)
88 {
89 case '1': /* malformed packet error */
90 if (*++buf == '0') /* general case: */
6156728b 91 error ("tracepoint.c: error in outgoing packet.");
6a02d201 92 else
6156728b
MS
93 error ("tracepoint.c: error in outgoing packet at field #%d.",
94 strtol (buf, NULL, 16));
6a02d201 95 case '2':
6156728b 96 error ("trace API error 0x%s.", ++buf);
6a02d201
MS
97 default:
98 error ("Target returns error code '%s'.", buf);
99 }
100}
101
102/* Obsolete: collect regs from a trace frame */
103static void
104trace_receive_regs (buf)
105 char *buf;
106{
107 long regno, i;
108 char regbuf[MAX_REGISTER_RAW_SIZE], *tmp, *p = buf;
109
110 while (*p)
111 {
112 regno = strtol (p, &tmp, 16);
113 if (p == tmp || *tmp++ != ':')
114 error ("tracepoint.c: malformed 'R' packet");
115 else p = tmp;
116
117 for (i = 0; i < REGISTER_RAW_SIZE (regno); i++)
118 {
119 if (p[0] == 0 || p[1] == 0)
120 warning ("Remote reply is too short: %s", buf);
121 regbuf[i] = fromhex (p[0]) * 16 + fromhex (p[1]);
122 p += 2;
123 }
124
125 if (*p++ != ';')
126 error ("tracepoint.c: malformed 'R' packet");
127
128 supply_register (regno, regbuf);
129 }
130}
131
132/* Utility: wait for reply from stub, while accepting "O" packets */
6156728b 133static char *
6a02d201
MS
134remote_get_noisy_reply (buf)
135 char *buf;
136{
137 do /* loop on reply from remote stub */
138 {
139 getpkt (buf, 0);
140 if (buf[0] == 0)
141 error ("Target does not support this command.");
142 else if (buf[0] == 'E')
143 trace_error (buf);
144 else if (buf[0] == 'R')
145 {
146 flush_cached_frames ();
147 registers_changed ();
148 select_frame (get_current_frame (), 0);
149 trace_receive_regs (buf);
150 }
151 else if (buf[0] == 'O' &&
152 buf[1] != 'K')
153 remote_console_output (buf + 1); /* 'O' message from stub */
154 else
6156728b 155 return buf; /* here's the actual reply */
6a02d201
MS
156 } while (1);
157}
158
159/* Set tracepoint count to NUM. */
160static void
161set_tracepoint_count (num)
162 int num;
163{
164 tracepoint_count = num;
165 set_internalvar (lookup_internalvar ("tpnum"),
166 value_from_longest (builtin_type_int, (LONGEST) num));
167}
168
169/* Set traceframe number to NUM. */
170static void
171set_traceframe_num (num)
172 int num;
173{
174 traceframe_number = num;
175 set_internalvar (lookup_internalvar ("trace_frame"),
176 value_from_longest (builtin_type_int, (LONGEST) num));
177}
178
6156728b
MS
179/* Set tracepoint number to NUM. */
180static void
181set_tracepoint_num (num)
182 int num;
183{
184 tracepoint_number = num;
185 set_internalvar (lookup_internalvar ("tracepoint"),
186 value_from_longest (builtin_type_int, (LONGEST) num));
187}
188
189/* Set externally visible debug variables for querying/printing
190 the traceframe context (line, function, file) */
191
192static void
193set_traceframe_context (trace_pc)
194 CORE_ADDR trace_pc;
195{
196 static struct type *func_string, *file_string;
197 static struct type *func_range, *file_range;
198 static value_ptr func_val, file_val;
199 static struct type *charstar;
200 int len;
201
202 if (charstar == (struct type *) NULL)
203 charstar = lookup_pointer_type (builtin_type_char);
204
205 if (trace_pc == -1) /* cease debugging any trace buffers */
206 {
207 traceframe_fun = 0;
208 traceframe_sal.pc = traceframe_sal.line = 0;
209 traceframe_sal.symtab = NULL;
210 set_internalvar (lookup_internalvar ("trace_func"),
211 value_from_longest (charstar, (LONGEST) 0));
212 set_internalvar (lookup_internalvar ("trace_file"),
213 value_from_longest (charstar, (LONGEST) 0));
214 set_internalvar (lookup_internalvar ("trace_line"),
215 value_from_longest (builtin_type_int, (LONGEST) -1));
216 return;
217 }
218
219 /* save as globals for internal use */
220 traceframe_sal = find_pc_line (trace_pc, 0);
221 traceframe_fun = find_pc_function (trace_pc);
222
223 /* save linenumber as "$trace_line", a debugger variable visible to users */
224 set_internalvar (lookup_internalvar ("trace_line"),
225 value_from_longest (builtin_type_int,
226 (LONGEST) traceframe_sal.line));
227
228 /* save func name as "$trace_func", a debugger variable visible to users */
229 if (traceframe_fun == NULL ||
230 SYMBOL_NAME (traceframe_fun) == NULL)
231 set_internalvar (lookup_internalvar ("trace_func"),
232 value_from_longest (charstar, (LONGEST) 0));
233 else
234 {
235 len = strlen (SYMBOL_NAME (traceframe_fun));
236 func_range = create_range_type (func_range,
237 builtin_type_int, 0, len - 1);
238 func_string = create_array_type (func_string,
239 builtin_type_char, func_range);
240 func_val = allocate_value (func_string);
241 VALUE_TYPE (func_val) = func_string;
242 memcpy (VALUE_CONTENTS_RAW (func_val),
243 SYMBOL_NAME (traceframe_fun),
244 len);
245 func_val->modifiable = 0;
246 set_internalvar (lookup_internalvar ("trace_func"), func_val);
247 }
248
249 /* save file name as "$trace_file", a debugger variable visible to users */
250 if (traceframe_sal.symtab == NULL ||
251 traceframe_sal.symtab->filename == NULL)
252 set_internalvar (lookup_internalvar ("trace_file"),
253 value_from_longest (charstar, (LONGEST) 0));
254 else
255 {
256 len = strlen (traceframe_sal.symtab->filename);
257 file_range = create_range_type (file_range,
258 builtin_type_int, 0, len - 1);
259 file_string = create_array_type (file_string,
260 builtin_type_char, file_range);
261 file_val = allocate_value (file_string);
262 VALUE_TYPE (file_val) = file_string;
263 memcpy (VALUE_CONTENTS_RAW (file_val),
264 traceframe_sal.symtab->filename,
265 len);
266 file_val->modifiable = 0;
267 set_internalvar (lookup_internalvar ("trace_file"), file_val);
268 }
269}
270
6a02d201
MS
271/* Low level routine to set a tracepoint.
272 Returns the tracepoint object so caller can set other things.
273 Does not set the tracepoint number!
274 Does not print anything.
275
276 ==> This routine should not be called if there is a chance of later
277 error(); otherwise it leaves a bogus tracepoint on the chain. Validate
278 your arguments BEFORE calling this routine! */
279
280static struct tracepoint *
281set_raw_tracepoint (sal)
282 struct symtab_and_line sal;
283{
284 register struct tracepoint *t, *tc;
285 struct cleanup *old_chain;
286
287 t = (struct tracepoint *) xmalloc (sizeof (struct tracepoint));
288 old_chain = make_cleanup (free, t);
289 memset (t, 0, sizeof (*t));
290 t->address = sal.pc;
291 if (sal.symtab == NULL)
292 t->source_file = NULL;
293 else
57c0b026
MS
294 {
295 t->source_file = (char *) xmalloc (strlen (sal.symtab->filename) +
296 strlen (sal.symtab->dirname) + 1);
297
298 strcpy (t->source_file, sal.symtab->dirname);
299 strcat (t->source_file, sal.symtab->filename);
300 }
301
6a02d201
MS
302 t->language = current_language->la_language;
303 t->input_radix = input_radix;
304 t->line_number = sal.line;
305 t->enabled = enabled;
306 t->next = 0;
307 t->step_count = 0;
308 t->pass_count = 0;
309
310 /* Add this tracepoint to the end of the chain
311 so that a list of tracepoints will come out in order
312 of increasing numbers. */
313
314 tc = tracepoint_chain;
315 if (tc == 0)
316 tracepoint_chain = t;
317 else
318 {
319 while (tc->next)
320 tc = tc->next;
321 tc->next = t;
322 }
323 discard_cleanups (old_chain);
324 return t;
325}
326
327static void
328trace_command (arg, from_tty)
329 char *arg;
330 int from_tty;
331{
332 char **canonical = (char **)NULL;
333 struct symtabs_and_lines sals;
334 struct symtab_and_line sal;
335 struct tracepoint *t;
336 char *addr_start = 0, *addr_end = 0, *cond_start = 0, *cond_end = 0;
337 int i;
338
339 if (!arg || !*arg)
340 error ("trace command requires an argument");
341
342 if (from_tty && info_verbose)
343 printf_filtered ("TRACE %s\n", arg);
344
345 if (arg[0] == '/')
346 {
347 return;
348 }
349
350 addr_start = arg;
351 sals = decode_line_1 (&arg, 1, (struct symtab *)NULL, 0, &canonical);
352 addr_end = arg;
353 if (! sals.nelts)
354 return; /* ??? Presumably decode_line_1 has already warned? */
355
356 /* Resolve all line numbers to PC's */
357 for (i = 0; i < sals.nelts; i++)
358 resolve_sal_pc (&sals.sals[i]);
359
360 /* Now set all the tracepoints. */
361 for (i = 0; i < sals.nelts; i++)
362 {
363 sal = sals.sals[i];
364
365 t = set_raw_tracepoint (sal);
366 set_tracepoint_count (tracepoint_count + 1);
367 t->number = tracepoint_count;
368
369 /* If a canonical line spec is needed use that instead of the
6156728b 370 command string. */
6a02d201 371 if (canonical != (char **)NULL && canonical[i] != NULL)
6156728b 372 t->addr_string = canonical[i];
6a02d201 373 else if (addr_start)
6156728b 374 t->addr_string = savestring (addr_start, addr_end - addr_start);
6a02d201 375 if (cond_start)
6156728b 376 t->cond_string = savestring (cond_start, cond_end - cond_start);
57c0b026
MS
377
378 /* Let the UI know of any additions */
379 if (create_tracepoint_hook)
6156728b 380 create_tracepoint_hook (t);
6a02d201
MS
381 }
382
383 if (sals.nelts > 1)
384 {
385 printf_filtered ("Multiple tracepoints were set.\n");
386 printf_filtered ("Use the \"delete\" command to delete unwanted tracepoints.\n");
387 }
388}
389
390static void
391tracepoints_info (tpnum_exp, from_tty)
392 char *tpnum_exp;
393 int from_tty;
394{
395 struct tracepoint *t;
396 struct action_line *action;
397 int found_a_tracepoint = 0;
398 char wrap_indent[80];
399 struct symbol *sym;
400 int tpnum = -1;
401#if 0
402 char *i1 = "\t", *i2 = "\t ";
403 char *indent, *actionline;;
404#endif
405
406 if (tpnum_exp)
407 tpnum = parse_and_eval_address (tpnum_exp);
408
409 ALL_TRACEPOINTS (t)
410 if (tpnum == -1 || tpnum == t->number)
411 {
412 extern int addressprint; /* print machine addresses? */
413
414 if (!found_a_tracepoint++)
6156728b
MS
415 {
416 printf_filtered ("Num Enb ");
417 if (addressprint)
418 printf_filtered ("Address ");
419 printf_filtered ("PassC StepC What\n");
420 }
6a02d201
MS
421 strcpy (wrap_indent, " ");
422 if (addressprint)
423 strcat (wrap_indent, " ");
424
6156728b
MS
425 printf_filtered ("%-3d %-3s ", t->number,
426 t->enabled == enabled ? "y" : "n");
6a02d201 427 if (addressprint)
6156728b
MS
428 printf_filtered ("%s ",
429 local_hex_string_custom ((unsigned long) t->address,
430 "08l"));
431 printf_filtered ("%-5d %-5d ", t->pass_count, t->step_count);
432
6a02d201
MS
433 if (t->source_file)
434 {
435 sym = find_pc_function (t->address);
436 if (sym)
437 {
438 fputs_filtered ("in ", gdb_stdout);
439 fputs_filtered (SYMBOL_SOURCE_NAME (sym), gdb_stdout);
440 wrap_here (wrap_indent);
441 fputs_filtered (" at ", gdb_stdout);
442 }
443 fputs_filtered (t->source_file, gdb_stdout);
444 printf_filtered (":%d", t->line_number);
445 }
446 else
447 print_address_symbolic (t->address, gdb_stdout, demangle, " ");
448
6a02d201
MS
449 printf_filtered ("\n");
450 if (t->actions)
451 {
452 printf_filtered (" Actions for tracepoint %d: \n", t->number);
453/* indent = i1; */
454 for (action = t->actions; action; action = action->next)
455 {
456#if 0
457 actionline = action->action;
458 while (isspace(*actionline))
459 actionline++;
460
461 printf_filtered ("%s%s\n", indent, actionline);
462 if (0 == strncasecmp (actionline, "while-stepping", 14))
463 indent = i2;
464 else if (0 == strncasecmp (actionline, "end", 3))
465 indent = i1;
466#else
467 printf_filtered ("\t%s\n", action->action);
468#endif
469 }
470 }
471 }
472 if (!found_a_tracepoint)
473 {
474 if (tpnum == -1)
475 printf_filtered ("No tracepoints.\n");
476 else
477 printf_filtered ("No tracepoint number %d.\n", tpnum);
478 }
479}
480
481/* Optimization: the code to parse an enable, disable, or delete TP command
482 is virtually identical except for whether it performs an enable, disable,
483 or delete. Therefore I've combined them into one function with an opcode.
484 */
485enum tracepoint_opcode
486{
487 enable,
488 disable,
489 delete
490};
491
492/* This function implements enable, disable and delete. */
493static void
494tracepoint_operation (t, from_tty, opcode)
495 struct tracepoint *t;
496 int from_tty;
497 enum tracepoint_opcode opcode;
498{
499 struct tracepoint *t2;
500 struct action_line *action, *next;
501
502 switch (opcode) {
503 case enable:
504 t->enabled = enabled;
505 break;
506 case disable:
507 t->enabled = disabled;
508 break;
509 case delete:
510 if (tracepoint_chain == t)
511 tracepoint_chain = t->next;
512
513 ALL_TRACEPOINTS (t2)
514 if (t2->next == t)
515 {
516 t2->next = t->next;
517 break;
518 }
57c0b026
MS
519
520 /* Let the UI know of any deletions */
521 if (delete_tracepoint_hook)
522 delete_tracepoint_hook (t);
523
6a02d201
MS
524 if (t->cond_string)
525 free (t->cond_string);
526 if (t->addr_string)
527 free (t->addr_string);
528 if (t->source_file)
529 free (t->source_file);
530 for (action = t->actions; action; action = next)
531 {
532 next = action->next;
533 if (action->action)
534 free (action->action);
535 free (action);
536 }
537 free (t);
538 break;
539 }
540}
541
542/* Utility: parse a tracepoint number and look it up in the list. */
57c0b026 543struct tracepoint *
6a02d201
MS
544get_tracepoint_by_number (arg)
545 char **arg;
546{
547 struct tracepoint *t;
6156728b 548 char *end, *copy;
6a02d201
MS
549 value_ptr val;
550 int tpnum;
551
552 if (arg == 0)
553 error ("Bad tracepoint argument");
554
555 if (*arg == 0 || **arg == 0) /* empty arg means refer to last tp */
556 tpnum = tracepoint_count;
557 else if (**arg == '$') /* handle convenience variable */
558 {
6156728b
MS
559 /* Make a copy of the name, so we can null-terminate it
560 to pass to lookup_internalvar(). */
561 end = *arg + 1;
562 while (isalnum(*end) || *end == '_')
563 end++;
564 copy = (char *) alloca (end - *arg);
565 strncpy (copy, *arg + 1, (end - *arg - 1));
566 copy[end - *arg - 1] = '\0';
567 *arg = end;
568
569 val = value_of_internalvar (lookup_internalvar (copy));
6a02d201
MS
570 if (TYPE_CODE( VALUE_TYPE (val)) != TYPE_CODE_INT)
571 error ("Convenience variable must have integral type.");
572 tpnum = (int) value_as_long (val);
573 }
574 else /* handle tracepoint number */
575 {
576 tpnum = strtol (*arg, arg, 10);
577 }
578 ALL_TRACEPOINTS (t)
579 if (t->number == tpnum)
580 {
581 return t;
582 }
583 warning ("No tracepoint number %d.\n", tpnum);
584 return NULL;
585}
586
587/* Utility: parse a list of tracepoint numbers, and call a func for each. */
588static void
589map_args_over_tracepoints (args, from_tty, opcode)
590 char *args;
591 int from_tty;
592 enum tracepoint_opcode opcode;
593{
594 struct tracepoint *t;
595 int tpnum;
596 char *cp;
597
598 if (args == 0 || *args == 0) /* do them all */
599 ALL_TRACEPOINTS (t)
600 tracepoint_operation (t, from_tty, opcode);
601 else
602 while (*args)
603 {
604 if (t = get_tracepoint_by_number (&args))
605 tracepoint_operation (t, from_tty, opcode);
606 while (*args == ' ' || *args == '\t')
607 args++;
608 }
609}
610
611static void
612enable_trace_command (args, from_tty)
613 char *args;
614 int from_tty;
615{
616 dont_repeat ();
617 map_args_over_tracepoints (args, from_tty, enable);
618}
619
620static void
621disable_trace_command (args, from_tty)
622 char *args;
623 int from_tty;
624{
625 dont_repeat ();
626 map_args_over_tracepoints (args, from_tty, disable);
627}
628
629static void
630delete_trace_command (args, from_tty)
631 char *args;
632 int from_tty;
633{
634 dont_repeat ();
635 if (!args || !*args)
636 if (!query ("Delete all tracepoints? "))
637 return;
638
639 map_args_over_tracepoints (args, from_tty, delete);
640}
641
642static void
643trace_pass_command (args, from_tty)
644 char *args;
645 int from_tty;
646{
647 struct tracepoint *t1 = (struct tracepoint *) -1, *t2;
648 unsigned long count;
649
650 if (args == 0 || *args == 0)
651 error ("PASS command requires an argument (count + optional TP num)");
652
653 count = strtoul (args, &args, 10); /* count comes first, then TP num */
654
655 while (*args && isspace (*args))
656 args++;
657
658 if (*args && strncasecmp (args, "all", 3) == 0)
659 args += 3; /* skip special argument "all" */
660 else
661 t1 = get_tracepoint_by_number (&args);
662
663 if (t1 == NULL)
664 return; /* error, bad tracepoint number */
665
666 ALL_TRACEPOINTS (t2)
667 if (t1 == (struct tracepoint *) -1 || t1 == t2)
668 {
669 t2->pass_count = count;
670 if (from_tty)
671 printf_filtered ("Setting tracepoint %d's passcount to %d\n",
672 t2->number, count);
673 }
674}
675
676/* ACTIONS ACTIONS ACTIONS */
677
678static void read_actions PARAMS((struct tracepoint *));
679static void free_actions PARAMS((struct tracepoint *));
680static int validate_actionline PARAMS((char *, struct tracepoint *));
681
6156728b
MS
682static void
683end_pseudocom (args, from_tty)
684{
685 error ("This command cannot be used at the top level.");
686}
687
688static void
689while_stepping_pseudocom (args, from_tty)
690{
691 error ("This command can only be used in a tracepoint actions list.");
692}
693
694static void
695collect_pseudocom (args, from_tty)
696{
697 error ("This command can only be used in a tracepoint actions list.");
698}
699
6a02d201
MS
700static void
701trace_actions_command (args, from_tty)
702 char *args;
703 int from_tty;
704{
705 struct tracepoint *t;
706 char *actions;
707
708 if (t = get_tracepoint_by_number (&args))
709 {
710 if (from_tty)
711 printf_filtered ("Enter actions for tracepoint %d, one per line.\n",
712 t->number);
713 free_actions (t);
714 read_actions (t);
715 /* tracepoints_changed () */
716 }
717 /* else error, just return; */
718}
719
720enum actionline_type
721{
722 BADLINE = -1,
723 GENERIC = 0,
724 END = 1,
725 STEPPING = 2,
726};
727
728static void
729read_actions (t)
730 struct tracepoint *t;
731{
732 char *line;
733 char *prompt1 = "> ", *prompt2 = " > ";
734 char *prompt = prompt1;
735 enum actionline_type linetype;
736 extern FILE *instream;
737 struct action_line *next = NULL, *temp;
738 struct cleanup *old_chain;
739
740 /* Control-C quits instantly if typed while in this loop
741 since it should not wait until the user types a newline. */
742 immediate_quit++;
743#ifdef STOP_SIGNAL
744 if (job_control)
745 signal (STOP_SIGNAL, stop_sig);
746#endif
747 old_chain = make_cleanup (free_actions, (void *) t);
748 while (1)
749 {
750 /* Make sure that all output has been output. Some machines may let
751 you get away with leaving out some of the gdb_flush, but not all. */
752 wrap_here ("");
753 gdb_flush (gdb_stdout);
754 gdb_flush (gdb_stderr);
755 if (instream == stdin && ISATTY (instream))
756 line = readline (prompt);
757 else
758 line = gdb_readline (0);
759
760 linetype = validate_actionline (line, t);
761 if (linetype == BADLINE)
762 continue; /* already warned -- collect another line */
763
764 temp = xmalloc (sizeof (struct action_line));
765 temp->next = NULL;
766 temp->action = line;
767
768 if (next == NULL) /* first action for this tracepoint? */
769 t->actions = next = temp;
770 else
771 {
772 next->next = temp;
773 next = temp;
774 }
775
776 if (linetype == STEPPING) /* begin "while-stepping" */
777 if (prompt == prompt2)
778 {
779 warning ("Already processing 'while-stepping'");
780 continue;
781 }
782 else
783 prompt = prompt2; /* change prompt for stepping actions */
784 else if (linetype == END)
785 if (prompt == prompt2)
786 prompt = prompt1; /* end of single-stepping actions */
787 else
788 break; /* end of actions */
789 }
790#ifdef STOP_SIGNAL
791 if (job_control)
792 signal (STOP_SIGNAL, SIG_DFL);
793#endif
794 immediate_quit = 0;
795 discard_cleanups (old_chain);
796}
797
6156728b
MS
798static char *
799parse_and_eval_memrange (arg, addr, typecode, offset, size)
800 char *arg;
801 CORE_ADDR addr;
802 long *typecode, *size;
803 bfd_signed_vma *offset;
804{
805 char *start = arg;
806 struct expression *exp;
807
808 if (*arg++ != '$' || *arg++ != '(')
809 error ("Internal: bad argument to validate_memrange: %s", start);
810
811 if (*arg == '$') /* register for relative memrange? */
812 {
813 exp = parse_exp_1 (&arg, block_for_pc (addr), 1);
814 if (exp->elts[0].opcode != OP_REGISTER)
815 error ("Bad register operand for memrange: %s", start);
816 if (*arg++ != ',')
817 error ("missing comma for memrange: %s", start);
818 *typecode = exp->elts[1].longconst;
819 }
820 else
821 *typecode = 0;
822
823#if 0
824 /* While attractive, this fails for a number of reasons:
825 1) parse_and_eval_address does not deal with trailing commas,
826 close-parens etc.
827 2) There is no safeguard against the user trying to use
828 an out-of-scope variable in an address expression (for instance).
829 2.5) If you are going to allow semi-arbitrary expressions, you
830 would need to explain which expressions are allowed, and
831 which are not (which would provoke endless questions).
832 3) If you are going to allow semi-arbitrary expressions in the
833 offset and size fields, then the leading "$" of a register
834 name no longer disambiguates the typecode field.
835 */
836
837 *offset = parse_and_eval_address (arg);
838 if ((arg = strchr (arg, ',')) == NULL)
839 error ("missing comma for memrange: %s", start);
840 else
841 arg++;
842
843 *size = parse_and_eval_address (arg);
844 if ((arg = strchr (arg, ')')) == NULL)
845 error ("missing close-parenthesis for memrange: %s", start);
846 else
847 arg++;
848#else
849#if 0
850 /* This, on the other hand, doesn't work because "-1" is an
851 expression, not an OP_LONG! Fall back to using strtol for now. */
852
853 exp = parse_exp_1 (&arg, block_for_pc (addr), 1);
854 if (exp->elts[0].opcode != OP_LONG)
855 error ("Bad offset operand for memrange: %s", start);
856 *offset = exp->elts[2].longconst;
857
858 if (*arg++ != ',')
859 error ("missing comma for memrange: %s", start);
860
861 exp = parse_exp_1 (&arg, block_for_pc (addr), 1);
862 if (exp->elts[0].opcode != OP_LONG)
863 error ("Bad size operand for memrange: %s", start);
864 *size = exp->elts[2].longconst;
865
866 if (*size <= 0)
867 error ("invalid size in memrange: %s", start);
868
869 if (*arg++ != ')')
870 error ("missing close-parenthesis for memrange: %s", start);
871#else
872 *offset = strtol (arg, &arg, 0);
873 if (*arg++ != ',')
874 error ("missing comma for memrange: %s", start);
875 *size = strtol (arg, &arg, 0);
876 if (*size <= 0)
877 error ("invalid size in memrange: %s", start);
878 if (*arg++ != ')')
879 error ("missing close-parenthesis for memrange: %s", start);
880#endif
881#endif
882 if (info_verbose)
883 printf_filtered ("Collecting memrange: (0x%x,0x%x,0x%x)\n",
884 *typecode, *offset, *size);
885
886 return arg;
887}
888
6a02d201
MS
889static enum actionline_type
890validate_actionline (line, t)
891 char *line;
892 struct tracepoint *t;
893{
894 char *p;
895 struct expression *exp;
896 value_ptr temp, temp2;
897
898 for (p = line; isspace (*p); )
899 p++;
900
901 /* symbol lookup etc. */
902 if (*p == '\0') /* empty line: just prompt for another line. */
903 return BADLINE;
904 else if (0 == strncasecmp (p, "collect", 7))
905 {
906 p += 7;
907 do { /* repeat over a comma-separated list */
908 while (isspace (*p))
909 p++;
910
6156728b
MS
911 if (*p == '$') /* look for special pseudo-symbols */
912 {
913 long typecode, size;
914 bfd_signed_vma offset;
915
916 if ((0 == strncasecmp ("reg", p + 1, 3)) ||
917 (0 == strncasecmp ("arg", p + 1, 3)) ||
918 (0 == strncasecmp ("loc", p + 1, 3)))
919 p = strchr (p, ',');
920
921 else if (p[1] == '(') /* literal memrange */
922 p = parse_and_eval_memrange (p, t->address,
923 &typecode, &offset, &size);
924 }
6a02d201
MS
925 else
926 {
927 exp = parse_exp_1 (&p, block_for_pc (t->address), 1);
6156728b 928
6a02d201
MS
929 if (exp->elts[0].opcode != OP_VAR_VALUE &&
930 /*exp->elts[0].opcode != OP_LONG && */
931 /*exp->elts[0].opcode != UNOP_CAST && */
932 exp->elts[0].opcode != OP_REGISTER)
933 {
934 warning ("collect: enter variable name or register.\n");
935 return BADLINE;
936 }
937 if (exp->elts[0].opcode == OP_VAR_VALUE)
938 if (SYMBOL_CLASS (exp->elts[2].symbol) == LOC_CONST)
939 {
940 warning ("%s is constant (value %d): will not be collected.",
941 SYMBOL_NAME (exp->elts[2].symbol),
942 SYMBOL_VALUE (exp->elts[2].symbol));
943 return BADLINE;
944 }
945 else if (SYMBOL_CLASS (exp->elts[2].symbol) == LOC_OPTIMIZED_OUT)
946 {
947 warning ("%s is optimized away and cannot be collected.",
948 SYMBOL_NAME (exp->elts[2].symbol));
949 return BADLINE;
950 }
951 }
952 } while (p && *p++ == ',');
953 return GENERIC;
954 }
955 else if (0 == strncasecmp (p, "while-stepping", 14))
956 {
957 char *steparg; /* in case warning is necessary */
958
959 p += 14;
960 while (isspace (*p))
961 p++;
962 steparg = p;
963
964 if (*p)
965 {
966 t->step_count = strtol (p, &p, 0);
967 if (t->step_count == 0)
968 {
969 warning ("'%s' evaluates to zero -- command ignored.");
970 return BADLINE;
971 }
972 }
973 else
974 t->step_count = -1;
975 return STEPPING;
976 }
977 else if (0 == strncasecmp (p, "end", 3))
978 return END;
979 else
980 {
981 warning ("'%s' is not a supported tracepoint action.", p);
982 return BADLINE;
983 }
984}
985
986static void
987free_actions (t)
988 struct tracepoint *t;
989{
990 struct action_line *line, *next;
991
992 for (line = t->actions; line; line = next)
993 {
994 next = line->next;
995 free (line);
996 }
997 t->actions = NULL;
998}
999
1000struct memrange {
1001 int type; /* 0 for absolute memory range, else basereg number */
1002 bfd_signed_vma start;
1003 bfd_signed_vma end;
1004};
1005
1006struct collection_list {
1007 unsigned char regs_mask[8]; /* room for up to 256 regs */
1008 long listsize;
1009 long next_memrange;
1010 struct memrange *list;
1011} tracepoint_list, stepping_list;
1012
1013static int
1014memrange_cmp (a, b)
1015 struct memrange *a, *b;
1016{
1017 if (a->type < b->type) return -1;
1018 if (a->type > b->type) return 1;
1019 if (a->type == 0)
1020 {
1021 if ((bfd_vma) a->start < (bfd_vma) b->start) return -1;
1022 if ((bfd_vma) a->start > (bfd_vma) b->start) return 1;
1023 }
1024 else
1025 {
1026 if (a->start < b->start) return -1;
1027 if (a->start > b->start) return 1;
1028 }
1029 return 0;
1030}
1031
1032static void
1033memrange_sortmerge (memranges)
1034 struct collection_list *memranges;
1035{
1036 int a, b;
1037
1038 qsort (memranges->list, memranges->next_memrange,
1039 sizeof (struct memrange), memrange_cmp);
1040 if (memranges->next_memrange > 0)
1041 {
1042 for (a = 0, b = 1; b < memranges->next_memrange; b++)
1043 {
1044 if (memranges->list[a].type == memranges->list[b].type &&
1045 memranges->list[b].start - memranges->list[a].end <=
1046 MAX_REGISTER_VIRTUAL_SIZE)
1047 {
1048 memranges->list[a].end = memranges->list[b].end;
1049 continue; /* next b, same a */
1050 }
1051 a++; /* next a */
1052 if (a != b)
1053 memcpy (&memranges->list[a], &memranges->list[b],
1054 sizeof (struct memrange));
1055 }
1056 memranges->next_memrange = a + 1;
1057 }
1058}
1059
1060void
1061add_register (collection, regno)
1062 struct collection_list *collection;
1063 unsigned long regno;
1064{
1065 if (info_verbose)
1066 printf_filtered ("collect register %d\n", regno);
1067 if (regno > (8 * sizeof (collection->regs_mask)))
1068 error ("Internal: register number %d too large for tracepoint",
1069 regno);
1070 collection->regs_mask [regno / 8] |= 1 << (regno % 8);
1071}
1072
1073static void
1074add_memrange (memranges, type, base, len)
1075 struct collection_list *memranges;
1076 int type;
1077 bfd_signed_vma base;
1078 unsigned long len;
1079{
1080 if (info_verbose)
1081 printf_filtered ("(%d,0x%x,%d)\n", type, base, len);
1082 /* type: 0 == memory, n == basereg */
1083 memranges->list[memranges->next_memrange].type = type;
1084 /* base: addr if memory, offset if reg relative. */
1085 memranges->list[memranges->next_memrange].start = base;
1086 /* len: we actually save end (base + len) for convenience */
1087 memranges->list[memranges->next_memrange].end = base + len;
1088 memranges->next_memrange++;
1089 if (memranges->next_memrange >= memranges->listsize)
1090 {
1091 memranges->listsize *= 2;
1092 memranges->list = xrealloc (memranges->list,
1093 memranges->listsize);
1094 }
1095
1096 if (type != 0) /* better collect the base register! */
1097 add_register (memranges, type);
1098}
1099
1100static void
1101collect_symbol (collect, sym)
1102 struct collection_list *collect;
1103 struct symbol *sym;
1104{
1105 unsigned long len;
1106 unsigned long reg;
1107 bfd_signed_vma offset;
1108
1109 len = TYPE_LENGTH (check_typedef (SYMBOL_TYPE (sym)));
1110 switch (SYMBOL_CLASS (sym)) {
1111 default:
1112 printf_filtered ("%s: don't know symbol class %d\n",
1113 SYMBOL_NAME (sym), SYMBOL_CLASS (sym));
1114 break;
1115 case LOC_CONST:
1116 printf_filtered ("%s is constant, value is %d: will not be collected.\n",
1117 SYMBOL_NAME (sym), SYMBOL_VALUE (sym));
1118 break;
1119 case LOC_STATIC:
1120 offset = SYMBOL_VALUE_ADDRESS (sym);
1121 if (info_verbose)
1122 printf_filtered ("LOC_STATIC %s: collect %d bytes "
1123 "at 0x%08x\n",
1124 SYMBOL_NAME (sym), len, offset);
1125 add_memrange (collect, 0, offset, len); /* 0 == memory */
1126 break;
1127 case LOC_REGISTER:
1128 case LOC_REGPARM:
1129 reg = SYMBOL_VALUE (sym);
1130 if (info_verbose)
1131 printf_filtered ("LOC_REG[parm] %s: ", SYMBOL_NAME (sym));
1132 add_register (collect, reg);
1133 break;
1134 case LOC_ARG:
1135 case LOC_REF_ARG:
1136 printf_filtered ("Sorry, don't know how to do LOC_ARGs yet.\n");
1137 printf_filtered (" (will not collect %s)\n",
1138 SYMBOL_NAME (sym));
1139 break;
1140 case LOC_REGPARM_ADDR:
1141 reg = SYMBOL_VALUE (sym);
1142 offset = 0;
1143 if (info_verbose)
1144 {
1145 printf_filtered ("LOC_REGPARM_ADDR %s: Collect %d bytes at offset %d from reg %d\n",
1146 SYMBOL_NAME (sym), len, offset, reg);
1147 }
1148 add_memrange (collect, reg, offset, len);
1149 break;
1150 case LOC_LOCAL:
1151 case LOC_LOCAL_ARG:
1152 offset = SYMBOL_VALUE (sym);
1153 reg = FP_REGNUM;
1154 if (info_verbose)
1155 {
1156 printf_filtered ("LOC_LOCAL %s: Collect %d bytes at offset %d from frame ptr reg %d\n",
1157 SYMBOL_NAME (sym), len, offset, reg);
1158 }
1159 add_memrange (collect, reg, offset, len);
1160 break;
1161 case LOC_BASEREG:
1162 case LOC_BASEREG_ARG:
1163 reg = SYMBOL_BASEREG (sym);
1164 offset = SYMBOL_VALUE (sym);
1165 if (info_verbose)
1166 {
1167 printf_filtered ("LOC_BASEREG %s: collect %d bytes at offset %d from basereg %d\n",
1168 SYMBOL_NAME (sym), len, offset, reg);
1169 }
1170 add_memrange (collect, reg, offset, len);
1171 break;
1172 case LOC_UNRESOLVED:
1173 printf_filtered ("Don't know LOC_UNRESOLVED %s\n", SYMBOL_NAME (sym));
1174 break;
1175 case LOC_OPTIMIZED_OUT:
1176 printf_filtered ("%s has been optimized out of existance.\n",
1177 SYMBOL_NAME (sym));
1178 break;
1179 }
1180}
1181
1182static void
1183add_local_symbols (collect, pc, type)
1184 struct collection_list *collect;
1185 CORE_ADDR pc;
1186 char type;
1187{
1188 struct symbol *sym;
1189 struct block *block;
1190 int i, nsyms, count = 0;
1191
1192 block = block_for_pc (pc);
1193 while (block != 0)
1194 {
1195 nsyms = BLOCK_NSYMS (block);
1196 for (i = 0; i < nsyms; i++)
1197 {
1198 sym = BLOCK_SYM (block, i);
1199 switch (SYMBOL_CLASS (sym)) {
1200 case LOC_LOCAL:
1201 case LOC_STATIC:
1202 case LOC_REGISTER:
1203 case LOC_BASEREG:
1204 if (type == 'L') /* collecting Locals */
1205 {
1206 count++;
1207 collect_symbol (collect, sym);
1208 }
1209 break;
1210 case LOC_ARG:
1211 case LOC_LOCAL_ARG:
1212 case LOC_REF_ARG:
1213 case LOC_REGPARM:
1214 case LOC_REGPARM_ADDR:
1215 case LOC_BASEREG_ARG:
1216 if (type == 'A') /* collecting Arguments */
1217 {
1218 count++;
1219 collect_symbol (collect, sym);
1220 }
1221 }
1222 }
1223 if (BLOCK_FUNCTION (block))
1224 break;
1225 else
1226 block = BLOCK_SUPERBLOCK (block);
1227 }
1228 if (count == 0)
1229 warning ("No %s found in scope.", type == 'L' ? "locals" : "args");
1230}
1231
1232static void
1233clear_collection_list (list)
1234 struct collection_list *list;
1235{
1236 list->next_memrange = 0;
1237 memset (list->regs_mask, 0, sizeof (list->regs_mask));
1238}
1239
1240static char *
1241stringify_collection_list (list, string)
1242 struct collection_list *list;
1243 char *string;
1244{
1245 char *end = string;
1246 long i;
1247
1248 for (i = sizeof (list->regs_mask) - 1; i > 0; i--)
1249 if (list->regs_mask[i] != 0) /* skip leading zeroes in regs_mask */
1250 break;
1251 if (list->regs_mask[i] != 0) /* prepare to send regs_mask to the stub */
1252 {
1253 if (info_verbose)
1254 printf_filtered ("\nCollecting registers (mask): 0x");
1255 *end++='R';
1256 for (; i >= 0; i--)
1257 {
1258 if (info_verbose)
1259 printf_filtered ("%02X", list->regs_mask[i]);
1260 sprintf (end, "%02X", list->regs_mask[i]);
1261 end += 2;
1262 }
1263 }
1264 if (info_verbose)
1265 printf_filtered ("\n");
1266 if (list->next_memrange > 0 && info_verbose)
1267 printf_filtered ("Collecting memranges: \n");
1268 for (i = 0; i < list->next_memrange; i++)
1269 {
1270 if (info_verbose)
1271 printf_filtered ("(%d, 0x%x, %d)\n",
1272 list->list[i].type,
1273 list->list[i].start,
1274 list->list[i].end - list->list[i].start);
1275 sprintf (end, "M%X,%X,%X",
1276 list->list[i].type,
1277 list->list[i].start,
1278 list->list[i].end - list->list[i].start);
1279 end += strlen (end);
1280 }
1281 if (end == string)
1282 return NULL;
1283 else
1284 return string;
1285}
1286
1287static void
1288encode_actions (t, tdp_actions, step_count, stepping_actions)
1289 struct tracepoint *t;
1290 char **tdp_actions;
1291 unsigned long *step_count;
1292 char **stepping_actions;
1293{
1294 struct expression *exp;
1295 static char tdp_buff[2048], step_buff[2048];
1296 struct action_line *action;
1297 char *action_exp;
1298 bfd_signed_vma offset;
1299 long i;
1300 struct collection_list *collect;
1301
1302 clear_collection_list (&tracepoint_list);
1303 clear_collection_list (&stepping_list);
1304 collect = &tracepoint_list;
1305
1306 *tdp_actions = NULL;
1307 *stepping_actions = NULL;
1308
1309 for (action = t->actions; action; action = action->next)
1310 {
1311 action_exp = action->action;
1312 while (isspace (*action_exp))
1313 action_exp++;
1314
1315 if (0 == strncasecmp (action_exp, "collect", 7))
1316 {
1317 action_exp = action_exp + 7;
1318 do { /* repeat over a comma-separated list */
1319 while (isspace (*action_exp))
1320 action_exp++;
1321
1322 if (0 == strncasecmp ("$reg", action_exp, 4))
1323 {
1324 for (i = 0; i < NUM_REGS; i++)
1325 add_register (collect, i);
6156728b 1326 action_exp = strchr (action_exp, ','); /* more? */
6a02d201
MS
1327 }
1328 else if (0 == strncasecmp ("$arg", action_exp, 4))
1329 {
1330 add_local_symbols (collect, t->address, 'A');
6156728b 1331 action_exp = strchr (action_exp, ','); /* more? */
6a02d201
MS
1332 }
1333 else if (0 == strncasecmp ("$loc", action_exp, 4))
1334 {
1335 add_local_symbols (collect, t->address, 'L');
6156728b
MS
1336 action_exp = strchr (action_exp, ','); /* more? */
1337 }
1338 else if (action_exp[0] == '$' &&
1339 action_exp[1] == '(') /* literal memrange */
1340 {
1341 long typecode, size;
1342 bfd_signed_vma offset;
1343
1344 action_exp = parse_and_eval_memrange (action_exp,
1345 t->address,
1346 &typecode,
1347 &offset,
1348 &size);
1349 add_memrange (collect, typecode, offset, size);
6a02d201
MS
1350 }
1351 else
1352 {
1353 unsigned long addr, len;
1354
1355 exp = parse_exp_1 (&action_exp, block_for_pc (t->address), 1);
1356 switch (exp->elts[0].opcode) {
1357 case OP_REGISTER:
1358 i = exp->elts[1].longconst;
1359 if (info_verbose)
1360 printf_filtered ("OP_REGISTER: ");
1361 add_register (collect, i);
1362 break;
1363 case OP_VAR_VALUE:
1364 collect_symbol (collect, exp->elts[2].symbol);
1365 break;
1366#if 0
1367 case OP_LONG:
1368 addr = exp->elts[2].longconst;
1369 if (*action_exp == ':')
1370 {
1371 exp = parse_exp_1 (&action_exp,
1372 block_for_pc (t->address),
1373 1);
1374 if (exp->elts[0].opcode == OP_LONG)
1375 len = exp->elts[2].longconst;
1376 else
1377 error ("length field requires a literal long const");
1378 }
1379 else
1380 len = 4;
1381
1382 add_memrange (collect, 0, addr, len);
1383 break;
1384#endif
1385 }
1386 }
1387 } while (action_exp && *action_exp++ == ',');
1388 }
1389 else if (0 == strncasecmp (action_exp, "while-stepping", 14))
1390 {
1391 collect = &stepping_list;
1392 }
1393 else if (0 == strncasecmp (action_exp, "end", 3))
1394 {
1395 if (collect == &stepping_list) /* end stepping actions */
1396 collect = &tracepoint_list;
1397 else
1398 break; /* end tracepoint actions */
1399 }
1400 }
1401 memrange_sortmerge (&tracepoint_list);
1402 memrange_sortmerge (&stepping_list);
1403
1404 *tdp_actions = stringify_collection_list (&tracepoint_list, &tdp_buff);
1405 *stepping_actions = stringify_collection_list (&stepping_list, &step_buff);
1406}
1407
1408static char target_buf[2048];
1409
1410static void
1411trace_start_command (args, from_tty)
1412 char *args;
1413 int from_tty;
1414{ /* STUB_COMM MOSTLY_IMPLEMENTED */
1415 struct tracepoint *t;
1416 char buf[2048];
1417 char *tdp_actions;
1418 char *stepping_actions;
1419 unsigned long step_count;
1420
1421 dont_repeat (); /* like "run", dangerous to repeat accidentally */
1422
1423 if (target_is_remote ())
1424 {
1425 putpkt ("QTinit");
1426 remote_get_noisy_reply (target_buf);
1427 if (strcmp (target_buf, "OK"))
1428 error ("Target does not support this command.");
1429
1430 ALL_TRACEPOINTS (t)
1431 {
1432 int ss_count; /* if actions include singlestepping */
1433 int disable_mask; /* ??? */
1434 int enable_mask; /* ??? */
1435
1436 sprintf (buf, "QTDP:%x:%x:%c:%x:%x", t->number, t->address,
1437 t->enabled == enabled ? 'E' : 'D',
1438 t->step_count, t->pass_count);
1439 if (t->actions)
1440 {
1441 encode_actions (t, &tdp_actions, &step_count, &stepping_actions);
1442 /* do_single_steps (t); */
1443 if (tdp_actions)
1444 {
1445 if (strlen (buf) + strlen (tdp_actions) >= sizeof (buf))
1446 error ("Actions for tracepoint %d too complex; "
1447 "please simplify.", t->number);
1448 strcat (buf, tdp_actions);
1449 }
1450 if (stepping_actions)
1451 {
1452 strcat (buf, "S");
1453 if (strlen (buf) + strlen (stepping_actions) >= sizeof (buf))
1454 error ("Actions for tracepoint %d too complex; "
1455 "please simplify.", t->number);
1456 strcat (buf, stepping_actions);
1457 }
1458 }
1459 putpkt (buf);
1460 remote_get_noisy_reply (target_buf);
1461 if (strcmp (target_buf, "OK"))
1462 error ("Target does not support tracepoints.");
1463 }
1464 putpkt ("QTStart");
1465 remote_get_noisy_reply (target_buf);
1466 if (strcmp (target_buf, "OK"))
1467 error ("Bogus reply from target: %s", target_buf);
6156728b
MS
1468 set_traceframe_num (-1); /* all old traceframes invalidated */
1469 set_tracepoint_num (-1);
1470 set_traceframe_context(-1);
6a02d201
MS
1471 }
1472 else
1473 printf_filtered ("Trace can only be run on remote targets.\n");
1474}
1475
1476static void
1477trace_stop_command (args, from_tty)
1478 char *args;
1479 int from_tty;
1480{ /* STUB_COMM IS_IMPLEMENTED */
1481 if (target_is_remote ())
1482 {
1483 putpkt ("QTStop");
1484 remote_get_noisy_reply (target_buf);
1485 if (strcmp (target_buf, "OK"))
1486 error ("Bogus reply from target: %s", target_buf);
1487 }
1488 else
1489 error ("Trace can only be run on remote targets.");
1490}
1491
1492static void
1493trace_status_command (args, from_tty)
1494 char *args;
1495 int from_tty;
1496{ /* STUB_COMM IS_IMPLEMENTED */
1497 if (target_is_remote ())
1498 {
1499 putpkt ("qTStatus");
1500 remote_get_noisy_reply (target_buf);
1501 if (strcmp (target_buf, "OK"))
1502 error ("Bogus reply from target: %s", target_buf);
1503 }
1504 else
1505 error ("Trace can only be run on remote targets.");
1506}
1507
1508static void
1509trace_buff_command (args, from_tty)
1510 char *args;
1511 int from_tty;
1512{ /* STUB_COMM NOT_IMPLEMENTED */
1513 if (args == 0 || *args == 0)
1514 printf_filtered ("TBUFFER command requires argument (on or off)\n");
1515 else if (strcasecmp (args, "on") == 0)
1516 printf_filtered ("tbuffer overflow on.\n");
1517 else if (strcasecmp (args, "off") == 0)
1518 printf_filtered ("tbuffer overflow off.\n");
1519 else
1520 printf_filtered ("TBUFFER: unknown argument (use on or off)\n");
1521}
1522
1523static void
1524trace_limit_command (args, from_tty)
1525 char *args;
1526 int from_tty;
1527{ /* STUB_COMM NOT_IMPLEMENTED */
1528 printf_filtered ("Limit it to what?\n");
1529}
1530
6156728b
MS
1531static void
1532finish_tfind_command (reply, from_tty)
1533 char *reply;
1534 int from_tty;
1535{
1536 int target_frameno = -1, target_tracept = -1;
1537
1538 while (reply && *reply)
1539 switch (*reply) {
1540 case 'F':
1541 if ((target_frameno = strtol (++reply, &reply, 16)) == -1)
1542 error ("Target failed to find requested trace frame.");
1543 break;
1544 case 'T':
1545 if ((target_tracept = strtol (++reply, &reply, 16)) == -1)
1546 error ("Target failed to find requested trace frame.");
1547 break;
1548 case 'O': /* "OK"? */
1549 if (reply[1] == 'K' && reply[2] == '\0')
1550 reply += 2;
1551 else
1552 error ("Bogus reply from target: %s", reply);
1553 break;
1554 default:
1555 error ("Bogus reply from target: %s", reply);
1556 }
1557
1558 flush_cached_frames ();
1559 registers_changed ();
1560 select_frame (get_current_frame (), 0);
1561 set_traceframe_num (target_frameno);
1562 set_tracepoint_num (target_tracept);
1563 set_traceframe_context ((get_current_frame ())->pc);
1564
1565 if (from_tty)
1566 print_stack_frame (selected_frame, selected_frame_level, 1);
1567}
1568
1569/* trace_find_command takes a trace frame number n,
1570 sends "QTFrame:<n>" to the target,
1571 and accepts a reply that may contain several optional pieces
1572 of information: a frame number, a tracepoint number, and an
1573 indication of whether this is a trap frame or a stepping frame.
1574
1575 The minimal response is just "OK" (which indicates that the
1576 target does not give us a frame number or a tracepoint number).
1577 Instead of that, the target may send us a string containing
1578 any combination of:
1579 F<hexnum> (gives the selected frame number)
1580 T<hexnum> (gives the selected tracepoint number)
1581 */
1582
6a02d201
MS
1583static void
1584trace_find_command (args, from_tty)
1585 char *args;
1586 int from_tty;
1587{ /* STUB_COMM PART_IMPLEMENTED */
1588 /* this should only be called with a numeric argument */
6156728b
MS
1589 int frameno = -1;
1590 int target_frameno = -1, target_tracept = -1, target_stepfrm = 0;
1591 char *tmp;
1592
6a02d201
MS
1593 if (target_is_remote ())
1594 {
1595 if (args == 0 || *args == 0)
6156728b
MS
1596 { /* TFIND with no args means find NEXT trace frame. */
1597 if (traceframe_number == -1)
1598 frameno = 0; /* "next" is first one */
1599 else
1600 frameno = traceframe_number + 1;
1601 }
1602 else if (0 == strcmp (args, "-"))
1603 {
1604 if (traceframe_number == -1)
1605 error ("not debugging trace buffer");
1606 else if (traceframe_number == 0)
1607 error ("already at start of trace buffer");
1608
1609 frameno = traceframe_number - 1;
1610 }
1611#if 0
1612 else if (0 == strcasecmp (args, "start"))
1613 frameno = 0;
1614 else if (0 == strcasecmp (args, "none") ||
1615 0 == strcasecmp (args, "end"))
1616 frameno = -1;
1617#endif
6a02d201 1618 else
6156728b 1619 frameno = parse_and_eval_address (args);
6a02d201 1620
6156728b
MS
1621 sprintf (target_buf, "QTFrame:%x", frameno);
1622 putpkt (target_buf);
1623 tmp = remote_get_noisy_reply (target_buf);
6a02d201 1624
6156728b
MS
1625 if (frameno == -1) /* end trace debugging */
1626 { /* hopefully the stub has complied! */
1627 if (0 != strcmp (tmp, "F-1"))
1628 error ("Bogus response from target: %s", tmp);
1629
1630 flush_cached_frames ();
1631 registers_changed ();
1632 select_frame (get_current_frame (), 0);
1633 set_traceframe_num (-1);
1634 set_tracepoint_num (-1);
1635 set_traceframe_context (-1);
1636
1637 if (from_tty)
1638 print_stack_frame (selected_frame, selected_frame_level, 1);
1639 }
1640 else
1641 finish_tfind_command (tmp, from_tty);
6a02d201
MS
1642 }
1643 else
1644 error ("Trace can only be run on remote targets.");
1645}
1646
6156728b
MS
1647static void
1648trace_find_end_command (args, from_tty)
1649 char *args;
1650 int from_tty;
1651{
1652 trace_find_command ("-1", from_tty);
1653}
1654
1655static void
1656trace_find_none_command (args, from_tty)
1657 char *args;
1658 int from_tty;
1659{
1660 trace_find_command ("-1", from_tty);
1661}
1662
1663static void
1664trace_find_start_command (args, from_tty)
1665 char *args;
1666 int from_tty;
1667{
1668 trace_find_command ("0", from_tty);
1669}
1670
6a02d201
MS
1671static void
1672trace_find_pc_command (args, from_tty)
1673 char *args;
1674 int from_tty;
1675{ /* STUB_COMM PART_IMPLEMENTED */
1676 CORE_ADDR pc;
1677 int target_frameno;
6156728b 1678 char *tmp;
6a02d201
MS
1679
1680 if (target_is_remote ())
1681 {
1682 if (args == 0 || *args == 0)
6156728b
MS
1683 pc = read_pc (); /* default is current pc */
1684 else
1685 pc = parse_and_eval_address (args);
6a02d201 1686
6156728b
MS
1687 sprintf (target_buf, "QTFrame:pc:%x", pc);
1688 putpkt (target_buf);
1689 tmp = remote_get_noisy_reply (target_buf);
6a02d201 1690
6156728b 1691 finish_tfind_command (tmp, from_tty);
6a02d201
MS
1692 }
1693 else
1694 error ("Trace can only be run on remote targets.");
1695}
1696
1697static void
6156728b 1698trace_find_tracepoint_command (args, from_tty)
6a02d201
MS
1699 char *args;
1700 int from_tty;
1701{ /* STUB_COMM PART_IMPLEMENTED */
1702 int target_frameno, tdp;
1703 char buf[40], *tmp;
1704
1705 if (target_is_remote ())
1706 {
1707 if (args == 0 || *args == 0)
6156728b
MS
1708 if (tracepoint_number == -1)
1709 error ("No current tracepoint -- please supply an argument.");
1710 else
1711 tdp = tracepoint_number; /* default is current TDP */
1712 else
1713 tdp = parse_and_eval_address (args);
6a02d201 1714
6156728b
MS
1715 sprintf (target_buf, "QTFrame:tdp:%x", tdp);
1716 putpkt (target_buf);
1717 tmp = remote_get_noisy_reply (target_buf);
6a02d201 1718
6156728b 1719 finish_tfind_command (tmp, from_tty);
6a02d201
MS
1720 }
1721 else
1722 error ("Trace can only be run on remote targets.");
1723}
1724
6156728b
MS
1725/* TFIND LINE command:
1726 *
1727 * This command will take a sourceline for argument, just like BREAK
1728 * or TRACE (ie. anything that "decode_line_1" can handle).
1729 *
1730 * With no argument, this command will find the next trace frame
1731 * corresponding to a source line OTHER THAN THE CURRENT ONE.
1732 */
1733
6a02d201 1734static void
6156728b 1735trace_find_line_command (args, from_tty)
6a02d201
MS
1736 char *args;
1737 int from_tty;
1738{ /* STUB_COMM PART_IMPLEMENTED */
6156728b
MS
1739 static CORE_ADDR start_pc, end_pc;
1740 struct symtabs_and_lines sals;
1741 struct symtab_and_line sal;
6a02d201 1742 int target_frameno;
6156728b
MS
1743 char *tmp;
1744 struct cleanup *old_chain;
6a02d201
MS
1745
1746 if (target_is_remote ())
1747 {
6156728b
MS
1748 if (args == 0 || *args == 0)
1749 {
1750 sal = find_pc_line ((get_current_frame ())->pc, 0);
1751 sals.nelts = 1;
1752 sals.sals = (struct symtab_and_line *)
1753 xmalloc (sizeof (struct symtab_and_line));
1754 sals.sals[0] = sal;
6a02d201 1755 }
6156728b 1756 else
6a02d201 1757 {
6156728b
MS
1758 sals = decode_line_spec (args, 1);
1759 sal = sals.sals[0];
6a02d201
MS
1760 }
1761
6156728b
MS
1762 old_chain = make_cleanup (free, sals.sals);
1763 if (sal.symtab == 0)
1764 {
1765 printf_filtered ("TFIND: No line number information available");
1766 if (sal.pc != 0)
1767 {
1768 /* This is useful for "info line *0x7f34". If we can't tell the
1769 user about a source line, at least let them have the symbolic
1770 address. */
1771 printf_filtered (" for address ");
1772 wrap_here (" ");
1773 print_address (sal.pc, gdb_stdout);
1774 printf_filtered (";\n -- will attempt to find by PC. \n");
1775 }
1776 else
1777 {
1778 printf_filtered (".\n");
1779 return; /* no line, no PC; what can we do? */
1780 }
1781 }
1782 else if (sal.line > 0
1783 && find_line_pc_range (sal, &start_pc, &end_pc))
1784 {
1785 if (start_pc == end_pc)
1786 {
1787 printf_filtered ("Line %d of \"%s\"",
1788 sal.line, sal.symtab->filename);
1789 wrap_here (" ");
1790 printf_filtered (" is at address ");
1791 print_address (start_pc, gdb_stdout);
1792 wrap_here (" ");
1793 printf_filtered (" but contains no code.\n");
1794 sal = find_pc_line (start_pc, 0);
1795 if (sal.line > 0 &&
1796 find_line_pc_range (sal, &start_pc, &end_pc) &&
1797 start_pc != end_pc)
1798 printf_filtered ("Attempting to find line %d instead.\n",
1799 sal.line);
1800 else
1801 error ("Cannot find a good line.");
1802 }
1803 }
1804 else
1805 /* Is there any case in which we get here, and have an address
1806 which the user would want to see? If we have debugging symbols
1807 and no line numbers? */
1808 error ("Line number %d is out of range for \"%s\".\n",
1809 sal.line, sal.symtab->filename);
1810
1811 if (args && *args) /* find within range of stated line */
1812 sprintf (target_buf, "QTFrame:range:%x:%x", start_pc, end_pc - 1);
1813 else /* find OUTSIDE OF range of CURRENT line */
1814 sprintf (target_buf, "QTFrame:outside:%x:%x", start_pc, end_pc - 1);
1815 putpkt (target_buf);
1816 tmp = remote_get_noisy_reply (target_buf);
1817
1818 finish_tfind_command (tmp, from_tty);
1819 do_cleanups (old_chain);
6a02d201
MS
1820 }
1821 else
1822 error ("Trace can only be run on remote targets.");
1823}
1824
1825static void
6156728b 1826trace_find_range_command (args, from_tty)
6a02d201
MS
1827 char *args;
1828 int from_tty;
1829{ /* STUB_COMM PART_IMPLEMENTED */
6156728b 1830 static CORE_ADDR start, stop;
6a02d201 1831 int target_frameno;
6156728b 1832 char *tmp;
6a02d201
MS
1833
1834 if (target_is_remote ())
1835 {
6156728b 1836 if (args == 0 || *args == 0)
6a02d201 1837 { /* XXX FIXME: what should default behavior be? */
6156728b 1838 printf_filtered ("Usage: tfind range <startaddr>,<endaddr>\n");
6a02d201
MS
1839 return;
1840 }
1841
6156728b 1842 if (0 != (tmp = strchr (args, ',' )))
6a02d201 1843 {
6156728b
MS
1844 *tmp++ = '\0'; /* terminate start address */
1845 while (isspace (*tmp))
1846 tmp++;
1847 start = parse_and_eval_address (args);
1848 stop = parse_and_eval_address (tmp);
1849 }
1850 else
1851 { /* no explicit end address? */
1852 start = parse_and_eval_address (args);
1853 stop = start + 1; /* ??? */
6a02d201
MS
1854 }
1855
6156728b
MS
1856 sprintf (target_buf, "QTFrame:range:%x:%x", start, stop);
1857 putpkt (target_buf);
1858 tmp = remote_get_noisy_reply (target_buf);
6a02d201 1859
6156728b 1860 finish_tfind_command (tmp, from_tty);
6a02d201
MS
1861 }
1862 else
1863 error ("Trace can only be run on remote targets.");
1864}
1865
1866static void
6156728b 1867trace_find_outside_command (args, from_tty)
6a02d201
MS
1868 char *args;
1869 int from_tty;
6156728b
MS
1870{ /* STUB_COMM PART_IMPLEMENTED */
1871 CORE_ADDR start, stop;
1872 int target_frameno;
1873 char *tmp;
1874
1875 if (target_is_remote ())
6a02d201 1876 {
6156728b
MS
1877 if (args == 0 || *args == 0)
1878 { /* XXX FIXME: what should default behavior be? */
1879 printf_filtered ("Usage: tfind outside <startaddr>,<endaddr>\n");
1880 return;
1881 }
6a02d201 1882
6156728b
MS
1883 if (0 != (tmp = strchr (args, ',' )))
1884 {
1885 *tmp++ = '\0'; /* terminate start address */
1886 while (isspace (*tmp))
1887 tmp++;
1888 start = parse_and_eval_address (args);
1889 stop = parse_and_eval_address (tmp);
1890 }
1891 else
1892 { /* no explicit end address? */
1893 start = parse_and_eval_address (args);
1894 stop = start + 1; /* ??? */
1895 }
1896
1897 sprintf (target_buf, "QTFrame:outside:%x:%x", start, stop);
1898 putpkt (target_buf);
1899 tmp = remote_get_noisy_reply (target_buf);
1900
1901 finish_tfind_command (tmp, from_tty);
1902 }
6a02d201 1903 else
6156728b 1904 error ("Trace can only be run on remote targets.");
6a02d201
MS
1905}
1906
1907static void
1908tracepoint_save_command (args, from_tty)
1909 char *args;
1910 int from_tty;
1911{
1912 struct tracepoint *tp;
1913 struct action_line *line;
1914 FILE *fp;
1915 char *i1 = " ", *i2 = " ";
1916 char *indent, *actionline;
1917
1918 if (args == 0 || *args == 0)
1919 error ("Argument required (file name in which to save tracepoints");
1920
1921 if (tracepoint_chain == 0)
1922 {
1923 warning ("save-tracepoints: no tracepoints to save.\n");
1924 return;
1925 }
1926
1927 if (!(fp = fopen (args, "w")))
1928 error ("Unable to open file '%s' for saving tracepoints");
1929
1930 ALL_TRACEPOINTS (tp)
1931 {
1932 if (tp->addr_string)
1933 fprintf (fp, "trace %s\n", tp->addr_string);
1934 else
1935 fprintf (fp, "trace *0x%x\n", tp->address);
1936
1937 if (tp->pass_count)
1938 fprintf (fp, " passcount %d\n", tp->pass_count);
1939
1940 if (tp->actions)
1941 {
1942 fprintf (fp, " actions\n");
1943 indent = i1;
1944 for (line = tp->actions; line; line = line->next)
1945 {
1946 actionline = line->action;
1947 while (isspace(*actionline))
1948 actionline++;
1949
1950 fprintf (fp, "%s%s\n", indent, actionline);
1951 if (0 == strncasecmp (actionline, "while-stepping", 14))
1952 indent = i2;
1953 else if (0 == strncasecmp (actionline, "end", 3))
1954 indent = i1;
1955 }
1956 }
1957 }
1958 fclose (fp);
1959 if (from_tty)
1960 printf_filtered ("Tracepoints saved to file '%s'.\n", args);
1961 return;
1962}
1963
1964static void
1965scope_info (args, from_tty)
1966 char *args;
1967 int from_tty;
1968{
1969 struct symtab_and_line sal;
1970 struct symtabs_and_lines sals;
1971 struct symbol *sym;
6156728b 1972 struct minimal_symbol *msym;
6a02d201 1973 struct block *block;
6156728b 1974 char **canonical, *symname, *save_args = args;
6a02d201 1975 int i, nsyms, count = 0;
6a02d201
MS
1976
1977 if (args == 0 || *args == 0)
1978 error ("requires an argument (function, line or *addr) to define a scope");
1979
1980 sals = decode_line_1 (&args, 1, NULL, 0, &canonical);
1981 if (sals.nelts == 0)
1982 return; /* presumably decode_line_1 has already warned */
1983
6156728b
MS
1984 /* Resolve line numbers to PC */
1985 resolve_sal_pc (&sals.sals[0]);
6a02d201 1986 block = block_for_pc (sals.sals[0].pc);
6156728b 1987
6a02d201
MS
1988 while (block != 0)
1989 {
1990 nsyms = BLOCK_NSYMS (block);
1991 for (i = 0; i < nsyms; i++)
1992 {
6156728b
MS
1993 if (count == 0)
1994 printf_filtered ("Scope for %s:\n", save_args);
6a02d201
MS
1995 count++;
1996 sym = BLOCK_SYM (block, i);
6156728b
MS
1997 symname = SYMBOL_NAME (sym);
1998 if (symname == NULL || *symname == '\0')
1999 continue; /* probably botched, certainly useless */
2000
2001 printf_filtered ("Symbol %s is ", symname);
6a02d201
MS
2002 switch (SYMBOL_CLASS (sym)) {
2003 default:
2004 case LOC_UNDEF: /* messed up symbol? */
6156728b
MS
2005 printf_filtered ("a bogus symbol, class %d.\n",
2006 SYMBOL_CLASS (sym));
6a02d201
MS
2007 count--; /* don't count this one */
2008 continue;
6156728b
MS
2009 case LOC_CONST:
2010 printf_filtered ("a constant with value %d (0x%x)",
2011 SYMBOL_VALUE (sym), SYMBOL_VALUE (sym));
2012 break;
2013 case LOC_CONST_BYTES:
2014 printf_filtered ("constant bytes: ");
2015 if (SYMBOL_TYPE (sym))
2016 for (i = 0; i < TYPE_LENGTH (SYMBOL_TYPE (sym)); i++)
2017 fprintf_filtered (gdb_stdout, " %02x",
2018 (unsigned) SYMBOL_VALUE_BYTES (sym) [i]);
2019 break;
2020 case LOC_STATIC:
2021 printf_filtered ("in static storage at address ");
2022 print_address_numeric (SYMBOL_VALUE_ADDRESS (sym), 1, gdb_stdout);
2023 break;
2024 case LOC_REGISTER:
2025 printf_filtered ("a local variable in register $%s",
2026 reg_names [SYMBOL_VALUE (sym)]);
2027 break;
2028 case LOC_ARG:
2029 case LOC_LOCAL_ARG:
2030 printf_filtered ("an argument at stack/frame offset %ld",
2031 SYMBOL_VALUE (sym));
2032 break;
2033 case LOC_LOCAL:
2034 printf_filtered ("a local variable at frame offset %ld",
2035 SYMBOL_VALUE (sym));
2036 break;
2037 case LOC_REF_ARG:
2038 printf_filtered ("a reference argument at offset %ld",
2039 SYMBOL_VALUE (sym));
2040 break;
2041 case LOC_REGPARM:
2042 printf_filtered ("an argument in register $%s",
2043 reg_names[SYMBOL_VALUE (sym)]);
2044 break;
6a02d201 2045 case LOC_REGPARM_ADDR:
6156728b
MS
2046 printf_filtered ("the address of an argument, in register $%s",
2047 reg_names[SYMBOL_VALUE (sym)]);
2048 break;
2049 case LOC_TYPEDEF:
2050 printf_filtered ("a typedef.\n");
2051 continue;
2052 case LOC_LABEL:
2053 printf_filtered ("a label at address ");
2054 print_address_numeric (SYMBOL_VALUE_ADDRESS (sym), 1, gdb_stdout);
2055 break;
2056 case LOC_BLOCK:
2057 printf_filtered ("a function at address ");
2058 print_address_numeric (BLOCK_START (SYMBOL_BLOCK_VALUE (sym)), 1,
2059 gdb_stdout);
2060 break;
2061 case LOC_BASEREG:
2062 printf_filtered ("a variable at offset %d from register $%s",
2063 SYMBOL_VALUE (sym),
2064 reg_names [SYMBOL_BASEREG (sym)]);
2065 break;
2066 case LOC_BASEREG_ARG:
2067 printf_filtered ("an argument at offset %d from register $%s",
2068 SYMBOL_VALUE (sym),
2069 reg_names [SYMBOL_BASEREG (sym)]);
2070 break;
6a02d201 2071 case LOC_UNRESOLVED:
6156728b
MS
2072 msym = lookup_minimal_symbol (SYMBOL_NAME (sym), NULL, NULL);
2073 if (msym == NULL)
2074 printf_filtered ("Unresolved Static");
2075 else
2076 {
2077 printf_filtered ("static storage at address ");
2078 print_address_numeric (SYMBOL_VALUE_ADDRESS (msym), 1,
2079 gdb_stdout);
2080 }
2081 break;
2082 case LOC_OPTIMIZED_OUT:
2083 printf_filtered ("optimized out.\n");
2084 continue;
6a02d201 2085 }
6156728b
MS
2086 if (SYMBOL_TYPE (sym))
2087 printf_filtered (", length %d.\n",
2088 TYPE_LENGTH (check_typedef (SYMBOL_TYPE (sym))));
6a02d201
MS
2089 }
2090 if (BLOCK_FUNCTION (block))
2091 break;
2092 else
2093 block = BLOCK_SUPERBLOCK (block);
2094 }
2095 if (count <= 0)
6156728b
MS
2096 printf_filtered ("Scope for %s contains no locals or arguments.\n",
2097 save_args);
6a02d201
MS
2098}
2099
6156728b
MS
2100static void
2101replace_comma (comma)
2102 char *comma;
2103{
2104 *comma = ',';
2105}
2106
2107static void
2108trace_dump_command (args, from_tty)
2109 char *args;
2110 int from_tty;
2111{
2112 struct tracepoint *t;
2113 struct action_line *action;
2114 char *action_exp, *next_comma;
2115 struct cleanup *old_cleanups;
2116 int stepping_actions = 0;
2117 int stepping_frame = 0;
2118
2119 if (tracepoint_number == -1)
2120 {
2121 warning ("No current trace frame.");
2122 return;
2123 }
2124
2125 ALL_TRACEPOINTS (t)
2126 if (t->number == tracepoint_number)
2127 break;
2128
2129 if (t == NULL)
2130 error ("No known tracepoint matches 'current' tracepoint #%d.",
2131 tracepoint_number);
2132
2133 old_cleanups = make_cleanup (null_cleanup, NULL);
2134
2135 printf_filtered ("Data collected at tracepoint %d, trace frame %d:\n",
2136 tracepoint_number, traceframe_number);
2137
2138 /* The current frame is a trap frame if the frame PC is equal
2139 to the tracepoint PC. If not, then the current frame was
2140 collected during single-stepping. */
2141
2142 stepping_frame = (t->address != read_pc());
2143
2144 for (action = t->actions; action; action = action->next)
2145 {
2146 action_exp = action->action;
2147 while (isspace (*action_exp))
2148 action_exp++;
2149
2150 /* The collection actions to be done while stepping are
2151 bracketed by the commands "while-stepping" and "end". */
2152
2153 if (0 == strncasecmp (action_exp, "while-stepping", 14))
2154 stepping_actions = 1;
2155 else if (0 == strncasecmp (action_exp, "end", 3))
2156 stepping_actions = 0;
2157 else if (0 == strncasecmp (action_exp, "collect", 7))
2158 {
2159 /* Display the collected data.
2160 For the trap frame, display only what was collected at the trap.
2161 Likewise for stepping frames, display only what was collected
2162 while stepping. This means that the two boolean variables,
2163 STEPPING_FRAME and STEPPING_ACTIONS should be equal. */
2164 if (stepping_frame == stepping_actions)
2165 {
2166 action_exp += 7;
2167 do { /* repeat over a comma-separated list */
2168 QUIT;
2169 if (*action_exp == ',')
2170 action_exp++;
2171 while (isspace (*action_exp))
2172 action_exp++;
2173
2174 next_comma = strchr (action_exp, ',');
2175 if (next_comma)
2176 {
2177 make_cleanup (replace_comma, next_comma);
2178 *next_comma = '\0';
2179 }
2180
2181 if (0 == strncasecmp (action_exp, "$reg", 4))
2182 registers_info (NULL, from_tty);
2183 else if (0 == strncasecmp (action_exp, "$loc", 4))
2184 locals_info (NULL, from_tty);
2185 else if (0 == strncasecmp (action_exp, "$arg", 4))
2186 args_info (NULL, from_tty);
2187 else
2188 {
2189 printf_filtered ("%s = ", action_exp);
2190 output_command (action_exp, from_tty);
2191 printf_filtered ("\n");
2192 }
2193 if (next_comma)
2194 *next_comma = ',';
2195 action_exp = next_comma;
2196 } while (action_exp && *action_exp == ',');
2197 }
2198 }
2199 }
2200 discard_cleanups (old_cleanups);
2201}
2202
2203
2204
6a02d201
MS
2205static struct cmd_list_element *tfindlist;
2206static struct cmd_list_element *tracelist;
2207
2208void
2209_initialize_tracepoint ()
2210{
2211 tracepoint_chain = 0;
2212 tracepoint_count = 0;
6156728b
MS
2213 traceframe_number = -1;
2214 tracepoint_number = -1;
6a02d201
MS
2215
2216 set_internalvar (lookup_internalvar ("tpnum"),
2217 value_from_longest (builtin_type_int, (LONGEST) 0));
2218 set_internalvar (lookup_internalvar ("trace_frame"),
2219 value_from_longest (builtin_type_int, (LONGEST) 0));
2220
2221 if (tracepoint_list.list == NULL)
2222 {
2223 tracepoint_list.listsize = 128;
2224 tracepoint_list.list = xmalloc
2225 (tracepoint_list.listsize * sizeof (struct memrange));
2226 }
2227 if (stepping_list.list == NULL)
2228 {
2229 stepping_list.listsize = 128;
2230 stepping_list.list = xmalloc
2231 (stepping_list.listsize * sizeof (struct memrange));
2232 }
2233
2234 add_info ("scope", scope_info,
2235 "List the variables local to a scope");
2236
6a02d201 2237 add_cmd ("tracepoints", class_trace, NO_FUNCTION,
6156728b 2238 "Tracing of program execution without stopping the program.",
6a02d201
MS
2239 &cmdlist);
2240
2241 add_info ("tracepoints", tracepoints_info,
6156728b
MS
2242 "Status of tracepoints, or tracepoint number NUMBER.\n\
2243Convenience variable \"$tpnum\" contains the number of the\n\
2244last tracepoint set.");
6a02d201
MS
2245
2246 add_info_alias ("tp", "tracepoints", 1);
2247
2248 add_com ("save-tracepoints", class_trace, tracepoint_save_command,
6156728b
MS
2249 "Save current tracepoint definitions as a script.\n\
2250Use the 'source' command in another debug session to restore them.");
6a02d201 2251
6156728b
MS
2252 add_com ("tdump", class_trace, trace_dump_command,
2253 "Print everything collected at the current tracepoint.");
6a02d201 2254
6156728b
MS
2255 add_prefix_cmd ("tfind", class_trace, trace_find_command,
2256 "Select a trace frame;\n\
2257No argument means forward by one frame; '-' meand backward by one frame.",
6a02d201
MS
2258 &tfindlist, "tfind ", 1, &cmdlist);
2259
2260 add_cmd ("outside", class_trace, trace_find_outside_command,
6156728b
MS
2261 "Select a trace frame whose PC is outside the given \
2262range.\nUsage: tfind outside addr1, addr2",
6a02d201
MS
2263 &tfindlist);
2264
2265 add_cmd ("range", class_trace, trace_find_range_command,
6156728b
MS
2266 "Select a trace frame whose PC is in the given range.\n\
2267Usage: tfind range addr1,addr2",
2268 &tfindlist);
6a02d201 2269
6156728b
MS
2270 add_cmd ("line", class_trace, trace_find_line_command,
2271 "Select a trace frame by source line.\n\
2272Argument can be a line number (with optional source file), \n\
2273a function name, or '*' followed by an address.\n\
2274Default argument is 'the next source line that was traced'.",
2275 &tfindlist);
2276
2277 add_cmd ("tracepoint", class_trace, trace_find_tracepoint_command,
2278 "Select a trace frame by tracepoint number.\n\
2279Default is the tracepoint for the current trace frame.",
2280 &tfindlist);
6a02d201
MS
2281
2282 add_cmd ("pc", class_trace, trace_find_pc_command,
6156728b
MS
2283 "Select a trace frame by PC.\n\
2284Default is the current PC, or the PC of the current trace frame.",
2285 &tfindlist);
6a02d201 2286
6156728b
MS
2287 add_cmd ("end", class_trace, trace_find_end_command,
2288 "Synonym for 'none'.\n\
2289De-select any trace frame and resume 'live' debugging.",
2290 &tfindlist);
2291
2292 add_cmd ("none", class_trace, trace_find_none_command,
2293 "De-select any trace frame and resume 'live' debugging.",
2294 &tfindlist);
2295
2296 add_cmd ("start", class_trace, trace_find_start_command,
2297 "Select the first trace frame in the trace buffer.",
2298 &tfindlist);
6a02d201
MS
2299
2300 add_com ("tstatus", class_trace, trace_status_command,
6156728b 2301 "Display the status of the current trace data collection.");
6a02d201
MS
2302
2303 add_com ("tstop", class_trace, trace_stop_command,
2304 "Stop trace data collection.");
2305
2306 add_com ("tstart", class_trace, trace_start_command,
2307 "Start trace data collection.");
2308
2309 add_com ("passcount", class_trace, trace_pass_command,
6156728b
MS
2310 "Set the passcount for a tracepoint.\n\
2311The trace will end when the tracepoint has been passed 'count' times.\n\
2312Usage: passcount COUNT TPNUM, where TPNUM may also be \"all\";\n\
2313if TPNUM is omitted, passcount refers to the last tracepoint defined.");
2314
2315 add_com ("end", class_trace, end_pseudocom,
2316 "Ends a list of commands or actions.\n\
2317Several GDB commands allow you to enter a list of commands or actions.\n\
2318Entering \"end\" on a line by itself is the normal way to terminate\n\
2319such a list.\n\n\
2320Note: the \"end\" command cannot be used at the gdb prompt.");
2321
2322 add_com ("while-stepping", class_trace, while_stepping_pseudocom,
2323 "Specify single-stepping behavior at a tracepoint.\n\
2324Argument is number of instructions to trace in single-step mode\n\
2325following the tracepoint. This command is normally followed by\n\
2326one or more \"collect\" commands, to specify what to collect\n\
2327while single-stepping.\n\n\
2328Note: this command can only be used in a tracepoint \"actions\" list.");
2329
2330 add_com ("collect", class_trace, collect_pseudocom,
2331 "Specify one or more data items to be collected at a tracepoint.\n\
2332Accepts a comma-separated list of (one or more) arguments.\n\
2333Things that may be collected include registers, variables, plus\n\
2334the following special arguments:\n\
2335 $regs -- all registers.\n\
2336 $args -- all function arguments.\n\
2337 $locals -- all variables local to the block/function scope.\n\
2338 $(addr,len) -- a literal memory range.\n\
2339 $($reg,addr,len) -- a register-relative literal memory range.\n\n\
2340Note: this command can only be used in a tracepoint \"actions\" list.");
6a02d201
MS
2341
2342 add_com ("actions", class_trace, trace_actions_command,
6156728b
MS
2343 "Specify the actions to be taken at a tracepoint.\n\
2344Tracepoint actions may include collecting of specified data, \n\
2345single-stepping, or enabling/disabling other tracepoints, \n\
2346depending on target's capabilities.");
6a02d201
MS
2347
2348 add_cmd ("tracepoints", class_trace, delete_trace_command,
6156728b
MS
2349 "Delete specified tracepoints.\n\
2350Arguments are tracepoint numbers, separated by spaces.\n\
2351No argument means delete all tracepoints.",
6a02d201
MS
2352 &deletelist);
2353
2354 add_cmd ("tracepoints", class_trace, disable_trace_command,
6156728b
MS
2355 "Disable specified tracepoints.\n\
2356Arguments are tracepoint numbers, separated by spaces.\n\
2357No argument means disable all tracepoints.",
6a02d201
MS
2358 &disablelist);
2359
2360 add_cmd ("tracepoints", class_trace, enable_trace_command,
6156728b
MS
2361 "Enable specified tracepoints.\n\
2362Arguments are tracepoint numbers, separated by spaces.\n\
2363No argument means enable all tracepoints.",
6a02d201
MS
2364 &enablelist);
2365
2366 add_com ("trace", class_trace, trace_command,
6156728b
MS
2367 "Set a tracepoint at a specified line or function or address.\n\
2368Argument may be a line number, function name, or '*' plus an address.\n\
2369For a line number or function, trace at the start of its code.\n\
2370If an address is specified, trace at that exact address.\n\n\
2371Do \"help tracepoints\" for info on other tracepoint commands.");
6a02d201
MS
2372
2373 add_com_alias ("tp", "trace", class_alias, 0);
2374 add_com_alias ("tr", "trace", class_alias, 1);
2375 add_com_alias ("tra", "trace", class_alias, 1);
2376 add_com_alias ("trac", "trace", class_alias, 1);
6a02d201 2377}
6156728b 2378
This page took 0.117859 seconds and 4 git commands to generate.