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