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