* As suggested by crash, made --with-sim-gpu2 option active only on -sky- target.
[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;
704 if (from_tty)
705 printf_filtered ("Setting tracepoint %d's passcount to %d\n",
706 t2->number, count);
707 }
708}
709
8b9c29f5
MS
710/* ACTIONS functions: */
711
712/* Prototypes for action-parsing utility commands */
713static void read_actions PARAMS((struct tracepoint *));
8b9c29f5
MS
714static char *parse_and_eval_memrange PARAMS ((char *,
715 CORE_ADDR,
716 long *,
717 bfd_signed_vma *,
718 long *));
719
720/* The three functions:
728c7f37
MS
721 collect_pseudocommand,
722 while_stepping_pseudocommand, and
723 end_actions_pseudocommand
8b9c29f5
MS
724 are placeholders for "commands" that are actually ONLY to be used
725 within a tracepoint action list. If the actual function is ever called,
726 it means that somebody issued the "command" at the top level,
727 which is always an error. */
6a02d201 728
6156728b 729static void
728c7f37 730end_actions_pseudocommand (args, from_tty)
5d187fd3
MS
731 char *args;
732 int from_tty;
6156728b
MS
733{
734 error ("This command cannot be used at the top level.");
735}
736
737static void
728c7f37 738while_stepping_pseudocommand (args, from_tty)
5d187fd3
MS
739 char *args;
740 int from_tty;
6156728b
MS
741{
742 error ("This command can only be used in a tracepoint actions list.");
743}
744
745static void
728c7f37 746collect_pseudocommand (args, from_tty)
5d187fd3
MS
747 char *args;
748 int from_tty;
6156728b
MS
749{
750 error ("This command can only be used in a tracepoint actions list.");
751}
752
8b9c29f5 753/* Enter a list of actions for a tracepoint. */
6a02d201
MS
754static void
755trace_actions_command (args, from_tty)
756 char *args;
757 int from_tty;
758{
759 struct tracepoint *t;
760 char *actions;
6c3908db
KS
761 char tmpbuf[128];
762 char *end_msg = "End with a line saying just \"end\".";
6a02d201
MS
763
764 if (t = get_tracepoint_by_number (&args))
765 {
6c3908db
KS
766 sprintf (tmpbuf, "Enter actions for tracepoint %d, one per line.",
767 t->number);
768
7a880bf3
MS
769 if (from_tty)
770 {
771 if (readline_begin_hook)
772 (*readline_begin_hook) ("%s %s\n", tmpbuf, end_msg);
773 else if (input_from_terminal_p ())
774 printf_filtered ("%s\n%s\n", tmpbuf, end_msg);
775 }
6c3908db 776
6a02d201
MS
777 free_actions (t);
778 read_actions (t);
6c3908db
KS
779
780 if (readline_end_hook)
781 (*readline_end_hook) ();
782
6a02d201
MS
783 /* tracepoints_changed () */
784 }
785 /* else error, just return; */
786}
787
788enum actionline_type
789{
790 BADLINE = -1,
791 GENERIC = 0,
792 END = 1,
793 STEPPING = 2,
794};
795
d9ba1c3f 796static enum actionline_type validate_actionline PARAMS((char **,
2b146fa0
MS
797 struct tracepoint *));
798
8b9c29f5 799/* worker function */
6a02d201
MS
800static void
801read_actions (t)
802 struct tracepoint *t;
803{
804 char *line;
805 char *prompt1 = "> ", *prompt2 = " > ";
806 char *prompt = prompt1;
807 enum actionline_type linetype;
808 extern FILE *instream;
809 struct action_line *next = NULL, *temp;
810 struct cleanup *old_chain;
811
812 /* Control-C quits instantly if typed while in this loop
813 since it should not wait until the user types a newline. */
814 immediate_quit++;
815#ifdef STOP_SIGNAL
816 if (job_control)
817 signal (STOP_SIGNAL, stop_sig);
818#endif
819 old_chain = make_cleanup (free_actions, (void *) t);
820 while (1)
821 {
822 /* Make sure that all output has been output. Some machines may let
823 you get away with leaving out some of the gdb_flush, but not all. */
824 wrap_here ("");
825 gdb_flush (gdb_stdout);
826 gdb_flush (gdb_stderr);
6c3908db
KS
827
828 if (readline_hook && instream == NULL)
829 line = (*readline_hook) (prompt);
830 else if (instream == stdin && ISATTY (instream))
99fa2de0
MS
831 {
832 line = readline (prompt);
833 if (line && *line) /* add it to command history */
834 add_history (line);
835 }
6a02d201
MS
836 else
837 line = gdb_readline (0);
838
d9ba1c3f 839 linetype = validate_actionline (&line, t);
6a02d201
MS
840 if (linetype == BADLINE)
841 continue; /* already warned -- collect another line */
842
843 temp = xmalloc (sizeof (struct action_line));
844 temp->next = NULL;
845 temp->action = line;
846
847 if (next == NULL) /* first action for this tracepoint? */
848 t->actions = next = temp;
849 else
850 {
851 next->next = temp;
852 next = temp;
853 }
854
855 if (linetype == STEPPING) /* begin "while-stepping" */
856 if (prompt == prompt2)
857 {
858 warning ("Already processing 'while-stepping'");
859 continue;
860 }
861 else
862 prompt = prompt2; /* change prompt for stepping actions */
863 else if (linetype == END)
864 if (prompt == prompt2)
865 prompt = prompt1; /* end of single-stepping actions */
866 else
867 break; /* end of actions */
868 }
869#ifdef STOP_SIGNAL
870 if (job_control)
871 signal (STOP_SIGNAL, SIG_DFL);
872#endif
873 immediate_quit = 0;
874 discard_cleanups (old_chain);
875}
876
8b9c29f5 877/* worker function */
6a02d201
MS
878static enum actionline_type
879validate_actionline (line, t)
d9ba1c3f 880 char **line;
6a02d201
MS
881 struct tracepoint *t;
882{
728c7f37 883 struct cmd_list_element *c;
6a02d201
MS
884 struct expression *exp;
885 value_ptr temp, temp2;
728c7f37 886 char *p;
6a02d201 887
d9ba1c3f 888 for (p = *line; isspace (*p); )
6a02d201
MS
889 p++;
890
891 /* symbol lookup etc. */
892 if (*p == '\0') /* empty line: just prompt for another line. */
893 return BADLINE;
728c7f37 894
5d187fd3
MS
895 if (*p == '#') /* comment line */
896 return GENERIC;
897
728c7f37
MS
898 c = lookup_cmd (&p, cmdlist, "", -1, 1);
899 if (c == 0)
900 {
901 warning ("'%s' is not an action that I know, or is ambiguous.", p);
902 return BADLINE;
903 }
904
905 if (c->function.cfunc == collect_pseudocommand)
6a02d201 906 {
6a02d201
MS
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 */
d9ba1c3f
MS
922 {
923 char *temp, *newline;
924
925 newline = malloc (strlen (*line) + 32);
926 strcpy (newline, *line);
927 newline[p - *line] = '\0';
928 /* newline is now a copy of line, up to "p" (the memrange) */
929 temp = parse_and_eval_memrange (p, t->address,
930 &typecode, &offset, &size) + 1;
931 /* now compose the memrange as a literal value */
932 if (typecode == -1)
933 sprintf (newline + strlen (newline),
934 "$(0x%x, %d)",
935 offset, size);
936 else
937 sprintf (newline + strlen (newline),
938 "$($%s, 0x%x, %d)",
939 reg_names[typecode], offset, size);
940 /* now add the remainder of the old line to the new one */
941 p = newline + strlen (newline);
942 if (temp && *temp)
943 strcat (newline, temp);
944 free (*line);
945 *line = newline;
946 }
6156728b 947 }
6a02d201
MS
948 else
949 {
950 exp = parse_exp_1 (&p, block_for_pc (t->address), 1);
6156728b 951
6a02d201 952 if (exp->elts[0].opcode != OP_VAR_VALUE &&
d9ba1c3f 953 exp->elts[0].opcode != UNOP_MEMVAL &&
6a02d201
MS
954 /*exp->elts[0].opcode != OP_LONG && */
955 /*exp->elts[0].opcode != UNOP_CAST && */
956 exp->elts[0].opcode != OP_REGISTER)
957 {
728c7f37 958 warning ("collect requires a variable or register name.\n");
6a02d201
MS
959 return BADLINE;
960 }
961 if (exp->elts[0].opcode == OP_VAR_VALUE)
962 if (SYMBOL_CLASS (exp->elts[2].symbol) == LOC_CONST)
963 {
964 warning ("%s is constant (value %d): will not be collected.",
965 SYMBOL_NAME (exp->elts[2].symbol),
966 SYMBOL_VALUE (exp->elts[2].symbol));
967 return BADLINE;
968 }
969 else if (SYMBOL_CLASS (exp->elts[2].symbol) == LOC_OPTIMIZED_OUT)
970 {
971 warning ("%s is optimized away and cannot be collected.",
972 SYMBOL_NAME (exp->elts[2].symbol));
973 return BADLINE;
974 }
975 }
976 } while (p && *p++ == ',');
977 return GENERIC;
978 }
728c7f37 979 else if (c->function.cfunc == while_stepping_pseudocommand)
6a02d201
MS
980 {
981 char *steparg; /* in case warning is necessary */
982
6a02d201
MS
983 while (isspace (*p))
984 p++;
985 steparg = p;
986
987 if (*p)
988 {
989 t->step_count = strtol (p, &p, 0);
990 if (t->step_count == 0)
991 {
992 warning ("'%s' evaluates to zero -- command ignored.");
993 return BADLINE;
994 }
995 }
996 else
997 t->step_count = -1;
998 return STEPPING;
999 }
728c7f37 1000 else if (c->function.cfunc == end_actions_pseudocommand)
6a02d201
MS
1001 return END;
1002 else
1003 {
d9ba1c3f 1004 warning ("'%s' is not a supported tracepoint action.", *line);
6a02d201
MS
1005 return BADLINE;
1006 }
1007}
1008
8b9c29f5 1009/* worker function */
a5f4fbff 1010void
6a02d201
MS
1011free_actions (t)
1012 struct tracepoint *t;
1013{
1014 struct action_line *line, *next;
1015
1016 for (line = t->actions; line; line = next)
1017 {
1018 next = line->next;
d9ba1c3f
MS
1019 if (line->action)
1020 free (line->action);
6a02d201
MS
1021 free (line);
1022 }
1023 t->actions = NULL;
1024}
1025
1026struct memrange {
1027 int type; /* 0 for absolute memory range, else basereg number */
1028 bfd_signed_vma start;
1029 bfd_signed_vma end;
1030};
1031
1032struct collection_list {
1033 unsigned char regs_mask[8]; /* room for up to 256 regs */
1034 long listsize;
1035 long next_memrange;
1036 struct memrange *list;
1037} tracepoint_list, stepping_list;
1038
8b9c29f5
MS
1039/* MEMRANGE functions: */
1040
1041/* parse a memrange spec from command input */
1042static char *
1043parse_and_eval_memrange (arg, addr, typecode, offset, size)
1044 char *arg;
1045 CORE_ADDR addr;
1046 long *typecode, *size;
1047 bfd_signed_vma *offset;
1048{
d9ba1c3f 1049 char *start = arg;
8b9c29f5 1050 struct expression *exp;
d9ba1c3f 1051 value_ptr val;
8b9c29f5
MS
1052
1053 if (*arg++ != '$' || *arg++ != '(')
d9ba1c3f 1054 error ("Internal: bad argument to parse_and_eval_memrange: %s", start);
8b9c29f5
MS
1055
1056 if (*arg == '$') /* register for relative memrange? */
1057 {
1058 exp = parse_exp_1 (&arg, block_for_pc (addr), 1);
1059 if (exp->elts[0].opcode != OP_REGISTER)
1060 error ("Bad register operand for memrange: %s", start);
1061 if (*arg++ != ',')
1062 error ("missing comma for memrange: %s", start);
1063 *typecode = exp->elts[1].longconst;
1064 }
1065 else
d9ba1c3f 1066 *typecode = -1; /* absolute memrange; */
8b9c29f5 1067
d9ba1c3f
MS
1068 exp = parse_exp_1 (&arg, 0, 1);
1069 *offset = value_as_pointer (evaluate_expression (exp));
8b9c29f5 1070
d9ba1c3f 1071 /* now parse the size */
8b9c29f5
MS
1072 if (*arg++ != ',')
1073 error ("missing comma for memrange: %s", start);
1074
d9ba1c3f
MS
1075 exp = parse_exp_1 (&arg, 0, 0);
1076 *size = value_as_long (evaluate_expression (exp));
8b9c29f5 1077
8b9c29f5
MS
1078 if (info_verbose)
1079 printf_filtered ("Collecting memrange: (0x%x,0x%x,0x%x)\n",
1080 *typecode, *offset, *size);
1081
1082 return arg;
1083}
1084
1085/* compare memranges for qsort */
6a02d201
MS
1086static int
1087memrange_cmp (a, b)
1088 struct memrange *a, *b;
1089{
1090 if (a->type < b->type) return -1;
1091 if (a->type > b->type) return 1;
1092 if (a->type == 0)
1093 {
1094 if ((bfd_vma) a->start < (bfd_vma) b->start) return -1;
1095 if ((bfd_vma) a->start > (bfd_vma) b->start) return 1;
1096 }
1097 else
1098 {
1099 if (a->start < b->start) return -1;
1100 if (a->start > b->start) return 1;
1101 }
1102 return 0;
1103}
1104
8b9c29f5 1105/* Sort the memrange list using qsort, and merge adjacent memranges */
6a02d201
MS
1106static void
1107memrange_sortmerge (memranges)
1108 struct collection_list *memranges;
1109{
1110 int a, b;
1111
1112 qsort (memranges->list, memranges->next_memrange,
1113 sizeof (struct memrange), memrange_cmp);
1114 if (memranges->next_memrange > 0)
1115 {
1116 for (a = 0, b = 1; b < memranges->next_memrange; b++)
1117 {
1118 if (memranges->list[a].type == memranges->list[b].type &&
1119 memranges->list[b].start - memranges->list[a].end <=
1120 MAX_REGISTER_VIRTUAL_SIZE)
1121 {
5d187fd3
MS
1122 /* memrange b starts before memrange a ends; merge them. */
1123 if (memranges->list[b].end > memranges->list[a].end)
1124 memranges->list[a].end = memranges->list[b].end;
6a02d201
MS
1125 continue; /* next b, same a */
1126 }
1127 a++; /* next a */
1128 if (a != b)
1129 memcpy (&memranges->list[a], &memranges->list[b],
1130 sizeof (struct memrange));
1131 }
1132 memranges->next_memrange = a + 1;
1133 }
1134}
1135
8b9c29f5 1136/* Add a register to a collection list */
6a02d201
MS
1137void
1138add_register (collection, regno)
1139 struct collection_list *collection;
1140 unsigned long regno;
1141{
1142 if (info_verbose)
1143 printf_filtered ("collect register %d\n", regno);
1144 if (regno > (8 * sizeof (collection->regs_mask)))
1145 error ("Internal: register number %d too large for tracepoint",
1146 regno);
1147 collection->regs_mask [regno / 8] |= 1 << (regno % 8);
1148}
1149
8b9c29f5 1150/* Add a memrange to a collection list */
6a02d201
MS
1151static void
1152add_memrange (memranges, type, base, len)
1153 struct collection_list *memranges;
1154 int type;
1155 bfd_signed_vma base;
1156 unsigned long len;
1157{
1158 if (info_verbose)
1159 printf_filtered ("(%d,0x%x,%d)\n", type, base, len);
1160 /* type: 0 == memory, n == basereg */
1161 memranges->list[memranges->next_memrange].type = type;
1162 /* base: addr if memory, offset if reg relative. */
1163 memranges->list[memranges->next_memrange].start = base;
1164 /* len: we actually save end (base + len) for convenience */
1165 memranges->list[memranges->next_memrange].end = base + len;
1166 memranges->next_memrange++;
1167 if (memranges->next_memrange >= memranges->listsize)
1168 {
1169 memranges->listsize *= 2;
1170 memranges->list = xrealloc (memranges->list,
1171 memranges->listsize);
1172 }
1173
d9ba1c3f 1174 if (type != -1) /* better collect the base register! */
6a02d201
MS
1175 add_register (memranges, type);
1176}
1177
8b9c29f5 1178/* Add a symbol to a collection list */
6a02d201
MS
1179static void
1180collect_symbol (collect, sym)
1181 struct collection_list *collect;
1182 struct symbol *sym;
1183{
1184 unsigned long len;
1185 unsigned long reg;
1186 bfd_signed_vma offset;
1187
1188 len = TYPE_LENGTH (check_typedef (SYMBOL_TYPE (sym)));
1189 switch (SYMBOL_CLASS (sym)) {
1190 default:
1191 printf_filtered ("%s: don't know symbol class %d\n",
1192 SYMBOL_NAME (sym), SYMBOL_CLASS (sym));
1193 break;
1194 case LOC_CONST:
1195 printf_filtered ("%s is constant, value is %d: will not be collected.\n",
1196 SYMBOL_NAME (sym), SYMBOL_VALUE (sym));
1197 break;
1198 case LOC_STATIC:
1199 offset = SYMBOL_VALUE_ADDRESS (sym);
1200 if (info_verbose)
60c7c376 1201 printf_filtered ("LOC_STATIC %s: collect %d bytes at 0x%08x\n",
6a02d201 1202 SYMBOL_NAME (sym), len, offset);
d9ba1c3f 1203 add_memrange (collect, -1, offset, len); /* 0 == memory */
6a02d201
MS
1204 break;
1205 case LOC_REGISTER:
1206 case LOC_REGPARM:
1207 reg = SYMBOL_VALUE (sym);
1208 if (info_verbose)
1209 printf_filtered ("LOC_REG[parm] %s: ", SYMBOL_NAME (sym));
1210 add_register (collect, reg);
1211 break;
1212 case LOC_ARG:
1213 case LOC_REF_ARG:
1214 printf_filtered ("Sorry, don't know how to do LOC_ARGs yet.\n");
1215 printf_filtered (" (will not collect %s)\n",
1216 SYMBOL_NAME (sym));
1217 break;
1218 case LOC_REGPARM_ADDR:
1219 reg = SYMBOL_VALUE (sym);
1220 offset = 0;
1221 if (info_verbose)
1222 {
1223 printf_filtered ("LOC_REGPARM_ADDR %s: Collect %d bytes at offset %d from reg %d\n",
1224 SYMBOL_NAME (sym), len, offset, reg);
1225 }
1226 add_memrange (collect, reg, offset, len);
1227 break;
1228 case LOC_LOCAL:
1229 case LOC_LOCAL_ARG:
1230 offset = SYMBOL_VALUE (sym);
1231 reg = FP_REGNUM;
1232 if (info_verbose)
1233 {
1234 printf_filtered ("LOC_LOCAL %s: Collect %d bytes at offset %d from frame ptr reg %d\n",
1235 SYMBOL_NAME (sym), len, offset, reg);
1236 }
1237 add_memrange (collect, reg, offset, len);
1238 break;
1239 case LOC_BASEREG:
1240 case LOC_BASEREG_ARG:
1241 reg = SYMBOL_BASEREG (sym);
1242 offset = SYMBOL_VALUE (sym);
1243 if (info_verbose)
1244 {
1245 printf_filtered ("LOC_BASEREG %s: collect %d bytes at offset %d from basereg %d\n",
1246 SYMBOL_NAME (sym), len, offset, reg);
1247 }
1248 add_memrange (collect, reg, offset, len);
1249 break;
1250 case LOC_UNRESOLVED:
1251 printf_filtered ("Don't know LOC_UNRESOLVED %s\n", SYMBOL_NAME (sym));
1252 break;
1253 case LOC_OPTIMIZED_OUT:
1254 printf_filtered ("%s has been optimized out of existance.\n",
1255 SYMBOL_NAME (sym));
1256 break;
1257 }
1258}
1259
8b9c29f5 1260/* Add all locals (or args) symbols to collection list */
6a02d201
MS
1261static void
1262add_local_symbols (collect, pc, type)
1263 struct collection_list *collect;
1264 CORE_ADDR pc;
1265 char type;
1266{
1267 struct symbol *sym;
1268 struct block *block;
1269 int i, nsyms, count = 0;
1270
1271 block = block_for_pc (pc);
1272 while (block != 0)
1273 {
1274 nsyms = BLOCK_NSYMS (block);
1275 for (i = 0; i < nsyms; i++)
1276 {
1277 sym = BLOCK_SYM (block, i);
1278 switch (SYMBOL_CLASS (sym)) {
1279 case LOC_LOCAL:
1280 case LOC_STATIC:
1281 case LOC_REGISTER:
1282 case LOC_BASEREG:
1283 if (type == 'L') /* collecting Locals */
1284 {
1285 count++;
1286 collect_symbol (collect, sym);
1287 }
1288 break;
1289 case LOC_ARG:
1290 case LOC_LOCAL_ARG:
1291 case LOC_REF_ARG:
1292 case LOC_REGPARM:
1293 case LOC_REGPARM_ADDR:
1294 case LOC_BASEREG_ARG:
1295 if (type == 'A') /* collecting Arguments */
1296 {
1297 count++;
1298 collect_symbol (collect, sym);
1299 }
1300 }
1301 }
1302 if (BLOCK_FUNCTION (block))
1303 break;
1304 else
1305 block = BLOCK_SUPERBLOCK (block);
1306 }
1307 if (count == 0)
1308 warning ("No %s found in scope.", type == 'L' ? "locals" : "args");
1309}
1310
8b9c29f5 1311/* worker function */
6a02d201
MS
1312static void
1313clear_collection_list (list)
1314 struct collection_list *list;
1315{
1316 list->next_memrange = 0;
1317 memset (list->regs_mask, 0, sizeof (list->regs_mask));
1318}
1319
8b9c29f5 1320/* reduce a collection list to string form (for gdb protocol) */
6a02d201
MS
1321static char *
1322stringify_collection_list (list, string)
1323 struct collection_list *list;
1324 char *string;
1325{
1326 char *end = string;
1327 long i;
1328
1329 for (i = sizeof (list->regs_mask) - 1; i > 0; i--)
1330 if (list->regs_mask[i] != 0) /* skip leading zeroes in regs_mask */
1331 break;
1332 if (list->regs_mask[i] != 0) /* prepare to send regs_mask to the stub */
1333 {
1334 if (info_verbose)
1335 printf_filtered ("\nCollecting registers (mask): 0x");
1336 *end++='R';
1337 for (; i >= 0; i--)
1338 {
1339 if (info_verbose)
1340 printf_filtered ("%02X", list->regs_mask[i]);
1341 sprintf (end, "%02X", list->regs_mask[i]);
1342 end += 2;
1343 }
1344 }
1345 if (info_verbose)
1346 printf_filtered ("\n");
1347 if (list->next_memrange > 0 && info_verbose)
1348 printf_filtered ("Collecting memranges: \n");
1349 for (i = 0; i < list->next_memrange; i++)
1350 {
1351 if (info_verbose)
1352 printf_filtered ("(%d, 0x%x, %d)\n",
1353 list->list[i].type,
1354 list->list[i].start,
1355 list->list[i].end - list->list[i].start);
1356 sprintf (end, "M%X,%X,%X",
1357 list->list[i].type,
1358 list->list[i].start,
1359 list->list[i].end - list->list[i].start);
1360 end += strlen (end);
1361 }
1362 if (end == string)
1363 return NULL;
1364 else
1365 return string;
1366}
1367
8b9c29f5 1368/* render all actions into gdb protocol */
6a02d201
MS
1369static void
1370encode_actions (t, tdp_actions, step_count, stepping_actions)
1371 struct tracepoint *t;
1372 char **tdp_actions;
1373 unsigned long *step_count;
1374 char **stepping_actions;
1375{
6a02d201 1376 static char tdp_buff[2048], step_buff[2048];
6a02d201 1377 char *action_exp;
728c7f37
MS
1378 struct expression *exp;
1379 struct action_line *action;
6a02d201
MS
1380 bfd_signed_vma offset;
1381 long i;
d9ba1c3f 1382 value_ptr tempval;
728c7f37
MS
1383 struct collection_list *collect;
1384 struct cmd_list_element *cmd;
6a02d201
MS
1385
1386 clear_collection_list (&tracepoint_list);
1387 clear_collection_list (&stepping_list);
1388 collect = &tracepoint_list;
1389
1390 *tdp_actions = NULL;
1391 *stepping_actions = NULL;
1392
1393 for (action = t->actions; action; action = action->next)
1394 {
1395 action_exp = action->action;
1396 while (isspace (*action_exp))
1397 action_exp++;
1398
5d187fd3
MS
1399 if (*action_exp == '#') /* comment line */
1400 return;
1401
728c7f37
MS
1402 cmd = lookup_cmd (&action_exp, cmdlist, "", -1, 1);
1403 if (cmd == 0)
1404 error ("Bad action list item: %s", action_exp);
1405
1406 if (cmd->function.cfunc == collect_pseudocommand)
6a02d201 1407 {
6a02d201
MS
1408 do { /* repeat over a comma-separated list */
1409 while (isspace (*action_exp))
1410 action_exp++;
1411
1412 if (0 == strncasecmp ("$reg", action_exp, 4))
1413 {
1414 for (i = 0; i < NUM_REGS; i++)
1415 add_register (collect, i);
6156728b 1416 action_exp = strchr (action_exp, ','); /* more? */
6a02d201
MS
1417 }
1418 else if (0 == strncasecmp ("$arg", action_exp, 4))
1419 {
1420 add_local_symbols (collect, t->address, 'A');
6156728b 1421 action_exp = strchr (action_exp, ','); /* more? */
6a02d201
MS
1422 }
1423 else if (0 == strncasecmp ("$loc", action_exp, 4))
1424 {
1425 add_local_symbols (collect, t->address, 'L');
6156728b
MS
1426 action_exp = strchr (action_exp, ','); /* more? */
1427 }
1428 else if (action_exp[0] == '$' &&
1429 action_exp[1] == '(') /* literal memrange */
1430 {
1431 long typecode, size;
1432 bfd_signed_vma offset;
1433
1434 action_exp = parse_and_eval_memrange (action_exp,
1435 t->address,
1436 &typecode,
1437 &offset,
1438 &size);
1439 add_memrange (collect, typecode, offset, size);
6a02d201
MS
1440 }
1441 else
1442 {
1443 unsigned long addr, len;
1444
1445 exp = parse_exp_1 (&action_exp, block_for_pc (t->address), 1);
1446 switch (exp->elts[0].opcode) {
1447 case OP_REGISTER:
1448 i = exp->elts[1].longconst;
1449 if (info_verbose)
1450 printf_filtered ("OP_REGISTER: ");
1451 add_register (collect, i);
1452 break;
d9ba1c3f
MS
1453
1454 case UNOP_MEMVAL:
1455 /* safe because we know it's a simple expression */
1456 tempval = evaluate_expression (exp);
1457 addr = VALUE_ADDRESS (tempval) + VALUE_OFFSET (tempval);
1458 len = TYPE_LENGTH (check_typedef (exp->elts[1].type));
1459 add_memrange (collect, -1, addr, len);
1460 break;
1461
6a02d201
MS
1462 case OP_VAR_VALUE:
1463 collect_symbol (collect, exp->elts[2].symbol);
1464 break;
1465#if 0
1466 case OP_LONG:
1467 addr = exp->elts[2].longconst;
1468 if (*action_exp == ':')
1469 {
1470 exp = parse_exp_1 (&action_exp,
1471 block_for_pc (t->address),
1472 1);
1473 if (exp->elts[0].opcode == OP_LONG)
1474 len = exp->elts[2].longconst;
1475 else
1476 error ("length field requires a literal long const");
1477 }
1478 else
1479 len = 4;
1480
d9ba1c3f 1481 add_memrange (collect, -1, addr, len);
6a02d201
MS
1482 break;
1483#endif
1484 }
1485 }
1486 } while (action_exp && *action_exp++ == ',');
1487 }
728c7f37 1488 else if (cmd->function.cfunc == while_stepping_pseudocommand)
6a02d201
MS
1489 {
1490 collect = &stepping_list;
1491 }
728c7f37 1492 else if (cmd->function.cfunc == end_actions_pseudocommand)
6a02d201
MS
1493 {
1494 if (collect == &stepping_list) /* end stepping actions */
1495 collect = &tracepoint_list;
1496 else
1497 break; /* end tracepoint actions */
1498 }
1499 }
1500 memrange_sortmerge (&tracepoint_list);
1501 memrange_sortmerge (&stepping_list);
1502
1503 *tdp_actions = stringify_collection_list (&tracepoint_list, &tdp_buff);
1504 *stepping_actions = stringify_collection_list (&stepping_list, &step_buff);
1505}
1506
1507static char target_buf[2048];
1508
8b9c29f5
MS
1509/* tstart command:
1510
1511 Tell target to lear any previous trace experiment.
1512 Walk the list of tracepoints, and send them (and their actions)
1513 to the target. If no errors,
1514 Tell target to start a new trace experiment. */
1515
6a02d201
MS
1516static void
1517trace_start_command (args, from_tty)
1518 char *args;
1519 int from_tty;
1520{ /* STUB_COMM MOSTLY_IMPLEMENTED */
1521 struct tracepoint *t;
1522 char buf[2048];
1523 char *tdp_actions;
1524 char *stepping_actions;
1525 unsigned long step_count;
1526
1527 dont_repeat (); /* like "run", dangerous to repeat accidentally */
1528
1529 if (target_is_remote ())
1530 {
1531 putpkt ("QTinit");
1532 remote_get_noisy_reply (target_buf);
1533 if (strcmp (target_buf, "OK"))
1534 error ("Target does not support this command.");
1535
1536 ALL_TRACEPOINTS (t)
1537 {
1538 int ss_count; /* if actions include singlestepping */
1539 int disable_mask; /* ??? */
1540 int enable_mask; /* ??? */
1541
1542 sprintf (buf, "QTDP:%x:%x:%c:%x:%x", t->number, t->address,
1543 t->enabled == enabled ? 'E' : 'D',
1544 t->step_count, t->pass_count);
1545 if (t->actions)
1546 {
1547 encode_actions (t, &tdp_actions, &step_count, &stepping_actions);
1548 /* do_single_steps (t); */
1549 if (tdp_actions)
1550 {
1551 if (strlen (buf) + strlen (tdp_actions) >= sizeof (buf))
60c7c376
JM
1552 error ("Actions for tracepoint %d too complex; please simplify.",
1553 t->number);
6a02d201
MS
1554 strcat (buf, tdp_actions);
1555 }
1556 if (stepping_actions)
1557 {
1558 strcat (buf, "S");
1559 if (strlen (buf) + strlen (stepping_actions) >= sizeof (buf))
60c7c376
JM
1560 error ("Actions for tracepoint %d too complex; please simplify.",
1561 t->number);
6a02d201
MS
1562 strcat (buf, stepping_actions);
1563 }
1564 }
1565 putpkt (buf);
1566 remote_get_noisy_reply (target_buf);
1567 if (strcmp (target_buf, "OK"))
1568 error ("Target does not support tracepoints.");
1569 }
1570 putpkt ("QTStart");
1571 remote_get_noisy_reply (target_buf);
1572 if (strcmp (target_buf, "OK"))
1573 error ("Bogus reply from target: %s", target_buf);
6156728b
MS
1574 set_traceframe_num (-1); /* all old traceframes invalidated */
1575 set_tracepoint_num (-1);
1576 set_traceframe_context(-1);
6a02d201
MS
1577 }
1578 else
1579 printf_filtered ("Trace can only be run on remote targets.\n");
1580}
1581
8b9c29f5 1582/* tstop command */
6a02d201
MS
1583static void
1584trace_stop_command (args, from_tty)
1585 char *args;
1586 int from_tty;
1587{ /* STUB_COMM IS_IMPLEMENTED */
1588 if (target_is_remote ())
1589 {
1590 putpkt ("QTStop");
1591 remote_get_noisy_reply (target_buf);
1592 if (strcmp (target_buf, "OK"))
1593 error ("Bogus reply from target: %s", target_buf);
1594 }
1595 else
1596 error ("Trace can only be run on remote targets.");
1597}
1598
8b9c29f5 1599/* tstatus command */
6a02d201
MS
1600static void
1601trace_status_command (args, from_tty)
1602 char *args;
1603 int from_tty;
1604{ /* STUB_COMM IS_IMPLEMENTED */
1605 if (target_is_remote ())
1606 {
1607 putpkt ("qTStatus");
1608 remote_get_noisy_reply (target_buf);
1609 if (strcmp (target_buf, "OK"))
1610 error ("Bogus reply from target: %s", target_buf);
1611 }
1612 else
1613 error ("Trace can only be run on remote targets.");
1614}
1615
8b9c29f5 1616/* Worker function for the various flavors of the tfind command */
6156728b 1617static void
c677110c
MS
1618finish_tfind_command (msg, from_tty)
1619 char *msg;
6156728b
MS
1620 int from_tty;
1621{
1622 int target_frameno = -1, target_tracept = -1;
c677110c
MS
1623 CORE_ADDR old_frame_addr;
1624 struct symbol *old_func;
1625 char *reply;
1626
1627 old_frame_addr = FRAME_FP (get_current_frame ());
1628 old_func = find_pc_function (read_pc ());
1629
1630 putpkt (msg);
1631 reply = remote_get_noisy_reply (msg);
6156728b
MS
1632
1633 while (reply && *reply)
1634 switch (*reply) {
1635 case 'F':
1636 if ((target_frameno = strtol (++reply, &reply, 16)) == -1)
8b9c29f5
MS
1637 {
1638 /* A request for a non-existant trace frame has failed.
1639 Our response will be different, depending on FROM_TTY:
1640
1641 If FROM_TTY is true, meaning that this command was
1642 typed interactively by the user, then give an error
1643 and DO NOT change the state of traceframe_number etc.
1644
1645 However if FROM_TTY is false, meaning that we're either
1646 in a script, a loop, or a user-defined command, then
1647 DON'T give an error, but DO change the state of
1648 traceframe_number etc. to invalid.
1649
1650 The rationalle is that if you typed the command, you
1651 might just have committed a typo or something, and you'd
1652 like to NOT lose your current debugging state. However
1653 if you're in a user-defined command or especially in a
1654 loop, then you need a way to detect that the command
1655 failed WITHOUT aborting. This allows you to write
1656 scripts that search thru the trace buffer until the end,
1657 and then continue on to do something else. */
1658
1659 if (from_tty)
1660 error ("Target failed to find requested trace frame.");
1661 else
1662 {
1663 if (info_verbose)
1664 printf_filtered ("End of trace buffer.\n");
1665 /* The following will not recurse, since it's special-cased */
1666 trace_find_command ("-1", from_tty);
c677110c
MS
1667 reply = NULL; /* break out of loop,
1668 (avoid recursive nonsense) */
8b9c29f5
MS
1669 }
1670 }
6156728b
MS
1671 break;
1672 case 'T':
1673 if ((target_tracept = strtol (++reply, &reply, 16)) == -1)
1674 error ("Target failed to find requested trace frame.");
1675 break;
1676 case 'O': /* "OK"? */
1677 if (reply[1] == 'K' && reply[2] == '\0')
1678 reply += 2;
1679 else
1680 error ("Bogus reply from target: %s", reply);
1681 break;
1682 default:
1683 error ("Bogus reply from target: %s", reply);
1684 }
1685
1686 flush_cached_frames ();
1687 registers_changed ();
1688 select_frame (get_current_frame (), 0);
1689 set_traceframe_num (target_frameno);
1690 set_tracepoint_num (target_tracept);
c677110c
MS
1691 if (target_frameno == -1)
1692 set_traceframe_context (-1);
1693 else
1694 set_traceframe_context (read_pc ());
6156728b
MS
1695
1696 if (from_tty)
c677110c
MS
1697 {
1698 int source_only;
1699
99fa2de0
MS
1700 /* NOTE: in immitation of the step command, try to determine
1701 whether we have made a transition from one function to another.
1702 If so, we'll print the "stack frame" (ie. the new function and
1703 it's arguments) -- otherwise we'll just show the new source line.
1704
1705 This determination is made by checking (1) whether the current
1706 function has changed, and (2) whether the current FP has changed.
1707 Hack: if the FP wasn't collected, either at the current or the
1708 previous frame, assume that the FP has NOT changed. */
1709
1710 if (old_func == find_pc_function (read_pc ()) &&
1711 (old_frame_addr == 0 ||
1712 FRAME_FP (get_current_frame ()) == 0 ||
1713 old_frame_addr == FRAME_FP (get_current_frame ())))
c677110c
MS
1714 source_only = -1;
1715 else
1716 source_only = 1;
1717
1718 print_stack_frame (selected_frame, selected_frame_level, source_only);
1719 do_displays ();
1720 }
6156728b
MS
1721}
1722
1723/* trace_find_command takes a trace frame number n,
1724 sends "QTFrame:<n>" to the target,
1725 and accepts a reply that may contain several optional pieces
1726 of information: a frame number, a tracepoint number, and an
1727 indication of whether this is a trap frame or a stepping frame.
1728
1729 The minimal response is just "OK" (which indicates that the
1730 target does not give us a frame number or a tracepoint number).
1731 Instead of that, the target may send us a string containing
1732 any combination of:
1733 F<hexnum> (gives the selected frame number)
1734 T<hexnum> (gives the selected tracepoint number)
1735 */
1736
8b9c29f5 1737/* tfind command */
6a02d201
MS
1738static void
1739trace_find_command (args, from_tty)
1740 char *args;
1741 int from_tty;
1742{ /* STUB_COMM PART_IMPLEMENTED */
1743 /* this should only be called with a numeric argument */
6156728b
MS
1744 int frameno = -1;
1745 int target_frameno = -1, target_tracept = -1, target_stepfrm = 0;
1746 char *tmp;
1747
6a02d201
MS
1748 if (target_is_remote ())
1749 {
1750 if (args == 0 || *args == 0)
6156728b
MS
1751 { /* TFIND with no args means find NEXT trace frame. */
1752 if (traceframe_number == -1)
1753 frameno = 0; /* "next" is first one */
1754 else
1755 frameno = traceframe_number + 1;
1756 }
1757 else if (0 == strcmp (args, "-"))
1758 {
1759 if (traceframe_number == -1)
1760 error ("not debugging trace buffer");
bf1aae13 1761 else if (from_tty && traceframe_number == 0)
6156728b
MS
1762 error ("already at start of trace buffer");
1763
1764 frameno = traceframe_number - 1;
1765 }
6a02d201 1766 else
6156728b 1767 frameno = parse_and_eval_address (args);
6a02d201 1768
6156728b 1769 sprintf (target_buf, "QTFrame:%x", frameno);
c677110c 1770#if 0
6156728b
MS
1771 putpkt (target_buf);
1772 tmp = remote_get_noisy_reply (target_buf);
6a02d201 1773
6156728b
MS
1774 if (frameno == -1) /* end trace debugging */
1775 { /* hopefully the stub has complied! */
c677110c 1776 if (0 != strcmp (tmp, "OK"))
6156728b
MS
1777 error ("Bogus response from target: %s", tmp);
1778
c677110c 1779 finish_tfind_command (NULL, from_tty);
6156728b
MS
1780 }
1781 else
1782 finish_tfind_command (tmp, from_tty);
c677110c
MS
1783#else
1784 finish_tfind_command (target_buf, from_tty);
1785#endif
6a02d201
MS
1786 }
1787 else
1788 error ("Trace can only be run on remote targets.");
1789}
1790
8b9c29f5 1791/* tfind end */
6156728b
MS
1792static void
1793trace_find_end_command (args, from_tty)
1794 char *args;
1795 int from_tty;
1796{
1797 trace_find_command ("-1", from_tty);
1798}
1799
8b9c29f5 1800/* tfind none */
6156728b
MS
1801static void
1802trace_find_none_command (args, from_tty)
1803 char *args;
1804 int from_tty;
1805{
1806 trace_find_command ("-1", from_tty);
1807}
1808
8b9c29f5 1809/* tfind start */
6156728b
MS
1810static void
1811trace_find_start_command (args, from_tty)
1812 char *args;
1813 int from_tty;
1814{
1815 trace_find_command ("0", from_tty);
1816}
1817
8b9c29f5 1818/* tfind pc command */
6a02d201
MS
1819static void
1820trace_find_pc_command (args, from_tty)
1821 char *args;
1822 int from_tty;
1823{ /* STUB_COMM PART_IMPLEMENTED */
1824 CORE_ADDR pc;
1825 int target_frameno;
6156728b 1826 char *tmp;
6a02d201
MS
1827
1828 if (target_is_remote ())
1829 {
1830 if (args == 0 || *args == 0)
6156728b
MS
1831 pc = read_pc (); /* default is current pc */
1832 else
1833 pc = parse_and_eval_address (args);
6a02d201 1834
6156728b 1835 sprintf (target_buf, "QTFrame:pc:%x", pc);
c677110c 1836#if 0
6156728b
MS
1837 putpkt (target_buf);
1838 tmp = remote_get_noisy_reply (target_buf);
6a02d201 1839
6156728b 1840 finish_tfind_command (tmp, from_tty);
c677110c
MS
1841#else
1842 finish_tfind_command (target_buf, from_tty);
1843#endif
6a02d201
MS
1844 }
1845 else
1846 error ("Trace can only be run on remote targets.");
1847}
1848
8b9c29f5 1849/* tfind tracepoint command */
6a02d201 1850static void
6156728b 1851trace_find_tracepoint_command (args, from_tty)
6a02d201
MS
1852 char *args;
1853 int from_tty;
1854{ /* STUB_COMM PART_IMPLEMENTED */
1855 int target_frameno, tdp;
1856 char buf[40], *tmp;
1857
1858 if (target_is_remote ())
1859 {
1860 if (args == 0 || *args == 0)
6156728b
MS
1861 if (tracepoint_number == -1)
1862 error ("No current tracepoint -- please supply an argument.");
1863 else
1864 tdp = tracepoint_number; /* default is current TDP */
1865 else
1866 tdp = parse_and_eval_address (args);
6a02d201 1867
6156728b 1868 sprintf (target_buf, "QTFrame:tdp:%x", tdp);
c677110c 1869#if 0
6156728b
MS
1870 putpkt (target_buf);
1871 tmp = remote_get_noisy_reply (target_buf);
6a02d201 1872
6156728b 1873 finish_tfind_command (tmp, from_tty);
c677110c
MS
1874#else
1875 finish_tfind_command (target_buf, from_tty);
1876#endif
6a02d201
MS
1877 }
1878 else
1879 error ("Trace can only be run on remote targets.");
1880}
1881
6156728b 1882/* TFIND LINE command:
8b9c29f5
MS
1883
1884 This command will take a sourceline for argument, just like BREAK
1885 or TRACE (ie. anything that "decode_line_1" can handle).
1886
1887 With no argument, this command will find the next trace frame
1888 corresponding to a source line OTHER THAN THE CURRENT ONE. */
6156728b 1889
6a02d201 1890static void
6156728b 1891trace_find_line_command (args, from_tty)
6a02d201
MS
1892 char *args;
1893 int from_tty;
1894{ /* STUB_COMM PART_IMPLEMENTED */
6156728b
MS
1895 static CORE_ADDR start_pc, end_pc;
1896 struct symtabs_and_lines sals;
1897 struct symtab_and_line sal;
6a02d201 1898 int target_frameno;
6156728b
MS
1899 char *tmp;
1900 struct cleanup *old_chain;
6a02d201
MS
1901
1902 if (target_is_remote ())
1903 {
6156728b
MS
1904 if (args == 0 || *args == 0)
1905 {
1906 sal = find_pc_line ((get_current_frame ())->pc, 0);
1907 sals.nelts = 1;
1908 sals.sals = (struct symtab_and_line *)
1909 xmalloc (sizeof (struct symtab_and_line));
1910 sals.sals[0] = sal;
6a02d201 1911 }
6156728b 1912 else
6a02d201 1913 {
6156728b
MS
1914 sals = decode_line_spec (args, 1);
1915 sal = sals.sals[0];
6a02d201
MS
1916 }
1917
6156728b
MS
1918 old_chain = make_cleanup (free, sals.sals);
1919 if (sal.symtab == 0)
1920 {
1921 printf_filtered ("TFIND: No line number information available");
1922 if (sal.pc != 0)
1923 {
1924 /* This is useful for "info line *0x7f34". If we can't tell the
1925 user about a source line, at least let them have the symbolic
1926 address. */
1927 printf_filtered (" for address ");
1928 wrap_here (" ");
1929 print_address (sal.pc, gdb_stdout);
1930 printf_filtered (";\n -- will attempt to find by PC. \n");
1931 }
1932 else
1933 {
1934 printf_filtered (".\n");
1935 return; /* no line, no PC; what can we do? */
1936 }
1937 }
1938 else if (sal.line > 0
1939 && find_line_pc_range (sal, &start_pc, &end_pc))
1940 {
1941 if (start_pc == end_pc)
1942 {
1943 printf_filtered ("Line %d of \"%s\"",
1944 sal.line, sal.symtab->filename);
1945 wrap_here (" ");
1946 printf_filtered (" is at address ");
1947 print_address (start_pc, gdb_stdout);
1948 wrap_here (" ");
1949 printf_filtered (" but contains no code.\n");
1950 sal = find_pc_line (start_pc, 0);
1951 if (sal.line > 0 &&
1952 find_line_pc_range (sal, &start_pc, &end_pc) &&
1953 start_pc != end_pc)
1954 printf_filtered ("Attempting to find line %d instead.\n",
1955 sal.line);
1956 else
1957 error ("Cannot find a good line.");
1958 }
1959 }
1960 else
1961 /* Is there any case in which we get here, and have an address
1962 which the user would want to see? If we have debugging symbols
1963 and no line numbers? */
1964 error ("Line number %d is out of range for \"%s\".\n",
1965 sal.line, sal.symtab->filename);
1966
1967 if (args && *args) /* find within range of stated line */
1968 sprintf (target_buf, "QTFrame:range:%x:%x", start_pc, end_pc - 1);
1969 else /* find OUTSIDE OF range of CURRENT line */
1970 sprintf (target_buf, "QTFrame:outside:%x:%x", start_pc, end_pc - 1);
c677110c 1971#if 0
6156728b
MS
1972 putpkt (target_buf);
1973 tmp = remote_get_noisy_reply (target_buf);
1974
1975 finish_tfind_command (tmp, from_tty);
c677110c
MS
1976#else
1977 finish_tfind_command (target_buf, from_tty);
1978#endif
6156728b 1979 do_cleanups (old_chain);
6a02d201
MS
1980 }
1981 else
1982 error ("Trace can only be run on remote targets.");
1983}
1984
8b9c29f5 1985/* tfind range command */
6a02d201 1986static void
6156728b 1987trace_find_range_command (args, from_tty)
6a02d201
MS
1988 char *args;
1989 int from_tty;
1990{ /* STUB_COMM PART_IMPLEMENTED */
6156728b 1991 static CORE_ADDR start, stop;
6a02d201 1992 int target_frameno;
6156728b 1993 char *tmp;
6a02d201
MS
1994
1995 if (target_is_remote ())
1996 {
6156728b 1997 if (args == 0 || *args == 0)
6a02d201 1998 { /* XXX FIXME: what should default behavior be? */
6156728b 1999 printf_filtered ("Usage: tfind range <startaddr>,<endaddr>\n");
6a02d201
MS
2000 return;
2001 }
2002
6156728b 2003 if (0 != (tmp = strchr (args, ',' )))
6a02d201 2004 {
6156728b
MS
2005 *tmp++ = '\0'; /* terminate start address */
2006 while (isspace (*tmp))
2007 tmp++;
2008 start = parse_and_eval_address (args);
2009 stop = parse_and_eval_address (tmp);
2010 }
2011 else
2012 { /* no explicit end address? */
2013 start = parse_and_eval_address (args);
2014 stop = start + 1; /* ??? */
6a02d201
MS
2015 }
2016
6156728b 2017 sprintf (target_buf, "QTFrame:range:%x:%x", start, stop);
c677110c 2018#if 0
6156728b
MS
2019 putpkt (target_buf);
2020 tmp = remote_get_noisy_reply (target_buf);
6a02d201 2021
6156728b 2022 finish_tfind_command (tmp, from_tty);
c677110c
MS
2023#else
2024 finish_tfind_command (target_buf, from_tty);
2025#endif
6a02d201
MS
2026 }
2027 else
2028 error ("Trace can only be run on remote targets.");
2029}
2030
8b9c29f5 2031/* tfind outside command */
6a02d201 2032static void
6156728b 2033trace_find_outside_command (args, from_tty)
6a02d201
MS
2034 char *args;
2035 int from_tty;
6156728b
MS
2036{ /* STUB_COMM PART_IMPLEMENTED */
2037 CORE_ADDR start, stop;
2038 int target_frameno;
2039 char *tmp;
2040
2041 if (target_is_remote ())
6a02d201 2042 {
6156728b
MS
2043 if (args == 0 || *args == 0)
2044 { /* XXX FIXME: what should default behavior be? */
2045 printf_filtered ("Usage: tfind outside <startaddr>,<endaddr>\n");
2046 return;
2047 }
6a02d201 2048
6156728b
MS
2049 if (0 != (tmp = strchr (args, ',' )))
2050 {
2051 *tmp++ = '\0'; /* terminate start address */
2052 while (isspace (*tmp))
2053 tmp++;
2054 start = parse_and_eval_address (args);
2055 stop = parse_and_eval_address (tmp);
2056 }
2057 else
2058 { /* no explicit end address? */
2059 start = parse_and_eval_address (args);
2060 stop = start + 1; /* ??? */
2061 }
2062
2063 sprintf (target_buf, "QTFrame:outside:%x:%x", start, stop);
c677110c 2064#if 0
6156728b
MS
2065 putpkt (target_buf);
2066 tmp = remote_get_noisy_reply (target_buf);
2067
2068 finish_tfind_command (tmp, from_tty);
c677110c
MS
2069#else
2070 finish_tfind_command (target_buf, from_tty);
2071#endif
6156728b 2072 }
6a02d201 2073 else
6156728b 2074 error ("Trace can only be run on remote targets.");
6a02d201
MS
2075}
2076
8b9c29f5 2077/* save-tracepoints command */
6a02d201
MS
2078static void
2079tracepoint_save_command (args, from_tty)
2080 char *args;
2081 int from_tty;
2082{
2083 struct tracepoint *tp;
2084 struct action_line *line;
2085 FILE *fp;
2086 char *i1 = " ", *i2 = " ";
2087 char *indent, *actionline;
2088
2089 if (args == 0 || *args == 0)
2090 error ("Argument required (file name in which to save tracepoints");
2091
2092 if (tracepoint_chain == 0)
2093 {
2094 warning ("save-tracepoints: no tracepoints to save.\n");
2095 return;
2096 }
2097
2098 if (!(fp = fopen (args, "w")))
2099 error ("Unable to open file '%s' for saving tracepoints");
2100
2101 ALL_TRACEPOINTS (tp)
2102 {
2103 if (tp->addr_string)
2104 fprintf (fp, "trace %s\n", tp->addr_string);
2105 else
2106 fprintf (fp, "trace *0x%x\n", tp->address);
2107
2108 if (tp->pass_count)
2109 fprintf (fp, " passcount %d\n", tp->pass_count);
2110
2111 if (tp->actions)
2112 {
2113 fprintf (fp, " actions\n");
2114 indent = i1;
2115 for (line = tp->actions; line; line = line->next)
2116 {
728c7f37
MS
2117 struct cmd_list_element *cmd;
2118
6a02d201
MS
2119 actionline = line->action;
2120 while (isspace(*actionline))
2121 actionline++;
2122
2123 fprintf (fp, "%s%s\n", indent, actionline);
5d187fd3
MS
2124 if (*actionline != '#') /* skip for comment lines */
2125 {
2126 cmd = lookup_cmd (&actionline, cmdlist, "", -1, 1);
2127 if (cmd == 0)
2128 error ("Bad action list item: %s", actionline);
2129 if (cmd->function.cfunc == while_stepping_pseudocommand)
2130 indent = i2;
2131 else if (cmd->function.cfunc == end_actions_pseudocommand)
2132 indent = i1;
2133 }
6a02d201
MS
2134 }
2135 }
2136 }
2137 fclose (fp);
2138 if (from_tty)
2139 printf_filtered ("Tracepoints saved to file '%s'.\n", args);
2140 return;
2141}
2142
8b9c29f5 2143/* info scope command: list the locals for a scope. */
6a02d201
MS
2144static void
2145scope_info (args, from_tty)
2146 char *args;
2147 int from_tty;
2148{
2149 struct symtab_and_line sal;
2150 struct symtabs_and_lines sals;
2151 struct symbol *sym;
6156728b 2152 struct minimal_symbol *msym;
6a02d201 2153 struct block *block;
6156728b 2154 char **canonical, *symname, *save_args = args;
6a02d201 2155 int i, nsyms, count = 0;
6a02d201
MS
2156
2157 if (args == 0 || *args == 0)
2158 error ("requires an argument (function, line or *addr) to define a scope");
2159
2160 sals = decode_line_1 (&args, 1, NULL, 0, &canonical);
2161 if (sals.nelts == 0)
2162 return; /* presumably decode_line_1 has already warned */
2163
6156728b
MS
2164 /* Resolve line numbers to PC */
2165 resolve_sal_pc (&sals.sals[0]);
6a02d201 2166 block = block_for_pc (sals.sals[0].pc);
6156728b 2167
6a02d201
MS
2168 while (block != 0)
2169 {
2170 nsyms = BLOCK_NSYMS (block);
2171 for (i = 0; i < nsyms; i++)
2172 {
6156728b
MS
2173 if (count == 0)
2174 printf_filtered ("Scope for %s:\n", save_args);
6a02d201
MS
2175 count++;
2176 sym = BLOCK_SYM (block, i);
6156728b
MS
2177 symname = SYMBOL_NAME (sym);
2178 if (symname == NULL || *symname == '\0')
2179 continue; /* probably botched, certainly useless */
2180
2181 printf_filtered ("Symbol %s is ", symname);
6a02d201
MS
2182 switch (SYMBOL_CLASS (sym)) {
2183 default:
2184 case LOC_UNDEF: /* messed up symbol? */
6156728b
MS
2185 printf_filtered ("a bogus symbol, class %d.\n",
2186 SYMBOL_CLASS (sym));
6a02d201
MS
2187 count--; /* don't count this one */
2188 continue;
6156728b
MS
2189 case LOC_CONST:
2190 printf_filtered ("a constant with value %d (0x%x)",
2191 SYMBOL_VALUE (sym), SYMBOL_VALUE (sym));
2192 break;
2193 case LOC_CONST_BYTES:
2194 printf_filtered ("constant bytes: ");
2195 if (SYMBOL_TYPE (sym))
2196 for (i = 0; i < TYPE_LENGTH (SYMBOL_TYPE (sym)); i++)
2197 fprintf_filtered (gdb_stdout, " %02x",
2198 (unsigned) SYMBOL_VALUE_BYTES (sym) [i]);
2199 break;
2200 case LOC_STATIC:
2201 printf_filtered ("in static storage at address ");
2202 print_address_numeric (SYMBOL_VALUE_ADDRESS (sym), 1, gdb_stdout);
2203 break;
2204 case LOC_REGISTER:
2205 printf_filtered ("a local variable in register $%s",
2206 reg_names [SYMBOL_VALUE (sym)]);
2207 break;
2208 case LOC_ARG:
2209 case LOC_LOCAL_ARG:
2210 printf_filtered ("an argument at stack/frame offset %ld",
2211 SYMBOL_VALUE (sym));
2212 break;
2213 case LOC_LOCAL:
2214 printf_filtered ("a local variable at frame offset %ld",
2215 SYMBOL_VALUE (sym));
2216 break;
2217 case LOC_REF_ARG:
2218 printf_filtered ("a reference argument at offset %ld",
2219 SYMBOL_VALUE (sym));
2220 break;
2221 case LOC_REGPARM:
2222 printf_filtered ("an argument in register $%s",
2223 reg_names[SYMBOL_VALUE (sym)]);
2224 break;
6a02d201 2225 case LOC_REGPARM_ADDR:
6156728b
MS
2226 printf_filtered ("the address of an argument, in register $%s",
2227 reg_names[SYMBOL_VALUE (sym)]);
2228 break;
2229 case LOC_TYPEDEF:
2230 printf_filtered ("a typedef.\n");
2231 continue;
2232 case LOC_LABEL:
2233 printf_filtered ("a label at address ");
2234 print_address_numeric (SYMBOL_VALUE_ADDRESS (sym), 1, gdb_stdout);
2235 break;
2236 case LOC_BLOCK:
2237 printf_filtered ("a function at address ");
2238 print_address_numeric (BLOCK_START (SYMBOL_BLOCK_VALUE (sym)), 1,
2239 gdb_stdout);
2240 break;
2241 case LOC_BASEREG:
2242 printf_filtered ("a variable at offset %d from register $%s",
2243 SYMBOL_VALUE (sym),
2244 reg_names [SYMBOL_BASEREG (sym)]);
2245 break;
2246 case LOC_BASEREG_ARG:
2247 printf_filtered ("an argument at offset %d from register $%s",
2248 SYMBOL_VALUE (sym),
2249 reg_names [SYMBOL_BASEREG (sym)]);
2250 break;
6a02d201 2251 case LOC_UNRESOLVED:
6156728b
MS
2252 msym = lookup_minimal_symbol (SYMBOL_NAME (sym), NULL, NULL);
2253 if (msym == NULL)
2254 printf_filtered ("Unresolved Static");
2255 else
2256 {
2257 printf_filtered ("static storage at address ");
2258 print_address_numeric (SYMBOL_VALUE_ADDRESS (msym), 1,
2259 gdb_stdout);
2260 }
2261 break;
2262 case LOC_OPTIMIZED_OUT:
2263 printf_filtered ("optimized out.\n");
2264 continue;
6a02d201 2265 }
6156728b
MS
2266 if (SYMBOL_TYPE (sym))
2267 printf_filtered (", length %d.\n",
2268 TYPE_LENGTH (check_typedef (SYMBOL_TYPE (sym))));
6a02d201
MS
2269 }
2270 if (BLOCK_FUNCTION (block))
2271 break;
2272 else
2273 block = BLOCK_SUPERBLOCK (block);
2274 }
2275 if (count <= 0)
6156728b
MS
2276 printf_filtered ("Scope for %s contains no locals or arguments.\n",
2277 save_args);
6a02d201
MS
2278}
2279
8b9c29f5 2280/* worker function (cleanup) */
6156728b
MS
2281static void
2282replace_comma (comma)
2283 char *comma;
2284{
2285 *comma = ',';
2286}
2287
8b9c29f5 2288/* tdump command */
6156728b
MS
2289static void
2290trace_dump_command (args, from_tty)
2291 char *args;
2292 int from_tty;
2293{
2294 struct tracepoint *t;
2295 struct action_line *action;
2296 char *action_exp, *next_comma;
2297 struct cleanup *old_cleanups;
2298 int stepping_actions = 0;
2299 int stepping_frame = 0;
2300
2301 if (tracepoint_number == -1)
2302 {
2303 warning ("No current trace frame.");
2304 return;
2305 }
2306
2307 ALL_TRACEPOINTS (t)
2308 if (t->number == tracepoint_number)
2309 break;
2310
2311 if (t == NULL)
2312 error ("No known tracepoint matches 'current' tracepoint #%d.",
2313 tracepoint_number);
2314
2315 old_cleanups = make_cleanup (null_cleanup, NULL);
2316
2317 printf_filtered ("Data collected at tracepoint %d, trace frame %d:\n",
2318 tracepoint_number, traceframe_number);
2319
2320 /* The current frame is a trap frame if the frame PC is equal
2321 to the tracepoint PC. If not, then the current frame was
2322 collected during single-stepping. */
2323
2324 stepping_frame = (t->address != read_pc());
2325
2326 for (action = t->actions; action; action = action->next)
2327 {
728c7f37
MS
2328 struct cmd_list_element *cmd;
2329
6156728b
MS
2330 action_exp = action->action;
2331 while (isspace (*action_exp))
2332 action_exp++;
2333
2334 /* The collection actions to be done while stepping are
2335 bracketed by the commands "while-stepping" and "end". */
2336
5d187fd3
MS
2337 if (*action_exp == '#') /* comment line */
2338 continue;
2339
728c7f37
MS
2340 cmd = lookup_cmd (&action_exp, cmdlist, "", -1, 1);
2341 if (cmd == 0)
2342 error ("Bad action list item: %s", action_exp);
2343
2344 if (cmd->function.cfunc == while_stepping_pseudocommand)
6156728b 2345 stepping_actions = 1;
728c7f37 2346 else if (cmd->function.cfunc == end_actions_pseudocommand)
6156728b 2347 stepping_actions = 0;
728c7f37 2348 else if (cmd->function.cfunc == collect_pseudocommand)
6156728b
MS
2349 {
2350 /* Display the collected data.
2351 For the trap frame, display only what was collected at the trap.
2352 Likewise for stepping frames, display only what was collected
2353 while stepping. This means that the two boolean variables,
2354 STEPPING_FRAME and STEPPING_ACTIONS should be equal. */
2355 if (stepping_frame == stepping_actions)
2356 {
6156728b
MS
2357 do { /* repeat over a comma-separated list */
2358 QUIT;
2359 if (*action_exp == ',')
2360 action_exp++;
2361 while (isspace (*action_exp))
2362 action_exp++;
2363
2364 next_comma = strchr (action_exp, ',');
6156728b
MS
2365
2366 if (0 == strncasecmp (action_exp, "$reg", 4))
2367 registers_info (NULL, from_tty);
2368 else if (0 == strncasecmp (action_exp, "$loc", 4))
2369 locals_info (NULL, from_tty);
2370 else if (0 == strncasecmp (action_exp, "$arg", 4))
2371 args_info (NULL, from_tty);
28ad0632
MS
2372 else if (action_exp[0] == '$' && action_exp[1] == '(')
2373 { /* memrange */
2374 long typecode, size;
2375 bfd_signed_vma offset;
2376 char fmt[40];
2377
2378 action_exp = parse_and_eval_memrange (action_exp,
2379 read_pc (),
2380 &typecode,
2381 &offset,
2382 &size);
2383 if (typecode != 0 && typecode != -1)
2384 offset += read_register (typecode);
2385 sprintf (fmt, "/%dxb 0x%x", size, offset);
2386 x_command (fmt, from_tty);
2387 next_comma = strchr (action_exp, ',');
2388 }
6156728b 2389 else
28ad0632
MS
2390 { /* variable */
2391 if (next_comma)
2392 {
2393 make_cleanup (replace_comma, next_comma);
2394 *next_comma = '\0';
2395 }
6156728b
MS
2396 printf_filtered ("%s = ", action_exp);
2397 output_command (action_exp, from_tty);
2398 printf_filtered ("\n");
2399 }
2400 if (next_comma)
2401 *next_comma = ',';
2402 action_exp = next_comma;
2403 } while (action_exp && *action_exp == ',');
2404 }
2405 }
2406 }
2407 discard_cleanups (old_cleanups);
2408}
2409
8b9c29f5 2410/* module initialization */
6a02d201
MS
2411void
2412_initialize_tracepoint ()
2413{
2414 tracepoint_chain = 0;
2415 tracepoint_count = 0;
6156728b
MS
2416 traceframe_number = -1;
2417 tracepoint_number = -1;
6a02d201
MS
2418
2419 set_internalvar (lookup_internalvar ("tpnum"),
2420 value_from_longest (builtin_type_int, (LONGEST) 0));
2421 set_internalvar (lookup_internalvar ("trace_frame"),
2422 value_from_longest (builtin_type_int, (LONGEST) 0));
2423
2424 if (tracepoint_list.list == NULL)
2425 {
2426 tracepoint_list.listsize = 128;
2427 tracepoint_list.list = xmalloc
2428 (tracepoint_list.listsize * sizeof (struct memrange));
2429 }
2430 if (stepping_list.list == NULL)
2431 {
2432 stepping_list.listsize = 128;
2433 stepping_list.list = xmalloc
2434 (stepping_list.listsize * sizeof (struct memrange));
2435 }
2436
2437 add_info ("scope", scope_info,
2438 "List the variables local to a scope");
2439
6a02d201 2440 add_cmd ("tracepoints", class_trace, NO_FUNCTION,
6156728b 2441 "Tracing of program execution without stopping the program.",
6a02d201
MS
2442 &cmdlist);
2443
2444 add_info ("tracepoints", tracepoints_info,
6156728b
MS
2445 "Status of tracepoints, or tracepoint number NUMBER.\n\
2446Convenience variable \"$tpnum\" contains the number of the\n\
2447last tracepoint set.");
6a02d201
MS
2448
2449 add_info_alias ("tp", "tracepoints", 1);
2450
2451 add_com ("save-tracepoints", class_trace, tracepoint_save_command,
6156728b
MS
2452 "Save current tracepoint definitions as a script.\n\
2453Use the 'source' command in another debug session to restore them.");
6a02d201 2454
6156728b
MS
2455 add_com ("tdump", class_trace, trace_dump_command,
2456 "Print everything collected at the current tracepoint.");
6a02d201 2457
6156728b
MS
2458 add_prefix_cmd ("tfind", class_trace, trace_find_command,
2459 "Select a trace frame;\n\
2460No argument means forward by one frame; '-' meand backward by one frame.",
6a02d201
MS
2461 &tfindlist, "tfind ", 1, &cmdlist);
2462
2463 add_cmd ("outside", class_trace, trace_find_outside_command,
6156728b
MS
2464 "Select a trace frame whose PC is outside the given \
2465range.\nUsage: tfind outside addr1, addr2",
6a02d201
MS
2466 &tfindlist);
2467
2468 add_cmd ("range", class_trace, trace_find_range_command,
6156728b
MS
2469 "Select a trace frame whose PC is in the given range.\n\
2470Usage: tfind range addr1,addr2",
2471 &tfindlist);
6a02d201 2472
6156728b
MS
2473 add_cmd ("line", class_trace, trace_find_line_command,
2474 "Select a trace frame by source line.\n\
2475Argument can be a line number (with optional source file), \n\
2476a function name, or '*' followed by an address.\n\
2477Default argument is 'the next source line that was traced'.",
2478 &tfindlist);
2479
2480 add_cmd ("tracepoint", class_trace, trace_find_tracepoint_command,
2481 "Select a trace frame by tracepoint number.\n\
2482Default is the tracepoint for the current trace frame.",
2483 &tfindlist);
6a02d201
MS
2484
2485 add_cmd ("pc", class_trace, trace_find_pc_command,
6156728b
MS
2486 "Select a trace frame by PC.\n\
2487Default is the current PC, or the PC of the current trace frame.",
2488 &tfindlist);
6a02d201 2489
6156728b
MS
2490 add_cmd ("end", class_trace, trace_find_end_command,
2491 "Synonym for 'none'.\n\
2492De-select any trace frame and resume 'live' debugging.",
2493 &tfindlist);
2494
2495 add_cmd ("none", class_trace, trace_find_none_command,
2496 "De-select any trace frame and resume 'live' debugging.",
2497 &tfindlist);
2498
2499 add_cmd ("start", class_trace, trace_find_start_command,
2500 "Select the first trace frame in the trace buffer.",
2501 &tfindlist);
6a02d201
MS
2502
2503 add_com ("tstatus", class_trace, trace_status_command,
6156728b 2504 "Display the status of the current trace data collection.");
6a02d201
MS
2505
2506 add_com ("tstop", class_trace, trace_stop_command,
2507 "Stop trace data collection.");
2508
2509 add_com ("tstart", class_trace, trace_start_command,
2510 "Start trace data collection.");
2511
2512 add_com ("passcount", class_trace, trace_pass_command,
6156728b
MS
2513 "Set the passcount for a tracepoint.\n\
2514The trace will end when the tracepoint has been passed 'count' times.\n\
2515Usage: passcount COUNT TPNUM, where TPNUM may also be \"all\";\n\
2516if TPNUM is omitted, passcount refers to the last tracepoint defined.");
2517
728c7f37 2518 add_com ("end", class_trace, end_actions_pseudocommand,
6156728b
MS
2519 "Ends a list of commands or actions.\n\
2520Several GDB commands allow you to enter a list of commands or actions.\n\
2521Entering \"end\" on a line by itself is the normal way to terminate\n\
2522such a list.\n\n\
2523Note: the \"end\" command cannot be used at the gdb prompt.");
2524
728c7f37 2525 add_com ("while-stepping", class_trace, while_stepping_pseudocommand,
6156728b
MS
2526 "Specify single-stepping behavior at a tracepoint.\n\
2527Argument is number of instructions to trace in single-step mode\n\
2528following the tracepoint. This command is normally followed by\n\
2529one or more \"collect\" commands, to specify what to collect\n\
2530while single-stepping.\n\n\
2531Note: this command can only be used in a tracepoint \"actions\" list.");
2532
728c7f37
MS
2533 add_com_alias ("ws", "while-stepping", class_alias, 0);
2534 add_com_alias ("stepping", "while-stepping", class_alias, 0);
2535
2536 add_com ("collect", class_trace, collect_pseudocommand,
6156728b
MS
2537 "Specify one or more data items to be collected at a tracepoint.\n\
2538Accepts a comma-separated list of (one or more) arguments.\n\
2539Things that may be collected include registers, variables, plus\n\
2540the following special arguments:\n\
2541 $regs -- all registers.\n\
2542 $args -- all function arguments.\n\
2543 $locals -- all variables local to the block/function scope.\n\
2544 $(addr,len) -- a literal memory range.\n\
2545 $($reg,addr,len) -- a register-relative literal memory range.\n\n\
2546Note: this command can only be used in a tracepoint \"actions\" list.");
6a02d201
MS
2547
2548 add_com ("actions", class_trace, trace_actions_command,
6156728b
MS
2549 "Specify the actions to be taken at a tracepoint.\n\
2550Tracepoint actions may include collecting of specified data, \n\
2551single-stepping, or enabling/disabling other tracepoints, \n\
2552depending on target's capabilities.");
6a02d201
MS
2553
2554 add_cmd ("tracepoints", class_trace, delete_trace_command,
6156728b
MS
2555 "Delete specified tracepoints.\n\
2556Arguments are tracepoint numbers, separated by spaces.\n\
2557No argument means delete all tracepoints.",
6a02d201
MS
2558 &deletelist);
2559
2560 add_cmd ("tracepoints", class_trace, disable_trace_command,
6156728b
MS
2561 "Disable specified tracepoints.\n\
2562Arguments are tracepoint numbers, separated by spaces.\n\
2563No argument means disable all tracepoints.",
6a02d201
MS
2564 &disablelist);
2565
2566 add_cmd ("tracepoints", class_trace, enable_trace_command,
6156728b
MS
2567 "Enable specified tracepoints.\n\
2568Arguments are tracepoint numbers, separated by spaces.\n\
2569No argument means enable all tracepoints.",
6a02d201
MS
2570 &enablelist);
2571
2572 add_com ("trace", class_trace, trace_command,
6156728b
MS
2573 "Set a tracepoint at a specified line or function or address.\n\
2574Argument may be a line number, function name, or '*' plus an address.\n\
2575For a line number or function, trace at the start of its code.\n\
2576If an address is specified, trace at that exact address.\n\n\
2577Do \"help tracepoints\" for info on other tracepoint commands.");
6a02d201
MS
2578
2579 add_com_alias ("tp", "trace", class_alias, 0);
2580 add_com_alias ("tr", "trace", class_alias, 1);
2581 add_com_alias ("tra", "trace", class_alias, 1);
2582 add_com_alias ("trac", "trace", class_alias, 1);
6a02d201 2583}
6156728b 2584
This page took 0.152819 seconds and 4 git commands to generate.