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