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