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