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