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