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