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