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