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