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