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