]> Git Repo - binutils.git/blame - gdb/tracepoint.c
* config/tc-hppa.c (pa_ip): Fix thinkos in recent cleanup
[binutils.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"
c906108c
SS
33
34#include "ax.h"
35#include "ax-gdb.h"
36
37/* readline include files */
38#include <readline/readline.h>
39#include <readline/history.h>
40
41/* readline defines this. */
42#undef savestring
43
44#ifdef HAVE_UNISTD_H
45#include <unistd.h>
46#endif
47
48/* maximum length of an agent aexpression.
49 this accounts for the fact that packets are limited to 400 bytes
50 (which includes everything -- including the checksum), and assumes
51 the worst case of maximum length for each of the pieces of a
52 continuation packet.
c5aa993b 53
c906108c
SS
54 NOTE: expressions get mem2hex'ed otherwise this would be twice as
55 large. (400 - 31)/2 == 184 */
56#define MAX_AGENT_EXPR_LEN 184
57
58
59extern int info_verbose;
c5aa993b
JM
60extern void (*readline_begin_hook) PARAMS ((char *,...));
61extern char *(*readline_hook) PARAMS ((char *));
c906108c
SS
62extern void (*readline_end_hook) PARAMS ((void));
63extern void x_command PARAMS ((char *, int));
c5aa993b 64extern int addressprint; /* Print machine addresses? */
c906108c 65
104c1213
JM
66/* GDB commands implemented in other modules:
67 */
68
69extern void output_command PARAMS ((char *, int));
70extern void registers_info PARAMS ((char *, int));
71extern void args_info PARAMS ((char *, int));
72extern void locals_info PARAMS ((char *, int));
73
74
c906108c
SS
75/* If this definition isn't overridden by the header files, assume
76 that isatty and fileno exist on this system. */
77#ifndef ISATTY
78#define ISATTY(FP) (isatty (fileno (FP)))
79#endif
80
81/*
82 Tracepoint.c:
83
84 This module defines the following debugger commands:
85 trace : set a tracepoint on a function, line, or address.
86 info trace : list all debugger-defined tracepoints.
87 delete trace : delete one or more tracepoints.
88 enable trace : enable one or more tracepoints.
89 disable trace : disable one or more tracepoints.
90 actions : specify actions to be taken at a tracepoint.
91 passcount : specify a pass count for a tracepoint.
92 tstart : start a trace experiment.
93 tstop : stop a trace experiment.
94 tstatus : query the status of a trace experiment.
95 tfind : find a trace frame in the trace buffer.
96 tdump : print everything collected at the current tracepoint.
97 save-tracepoints : write tracepoint setup into a file.
98
99 This module defines the following user-visible debugger variables:
100 $trace_frame : sequence number of trace frame currently being debugged.
101 $trace_line : source line of trace frame currently being debugged.
102 $trace_file : source file of trace frame currently being debugged.
103 $tracepoint : tracepoint number of trace frame currently being debugged.
c5aa993b 104 */
c906108c
SS
105
106
107/* ======= Important global variables: ======= */
108
109/* Chain of all tracepoints defined. */
110struct tracepoint *tracepoint_chain;
111
112/* Number of last tracepoint made. */
113static int tracepoint_count;
114
115/* Number of last traceframe collected. */
116static int traceframe_number;
117
118/* Tracepoint for last traceframe collected. */
119static int tracepoint_number;
120
121/* Symbol for function for last traceframe collected */
122static struct symbol *traceframe_fun;
123
124/* Symtab and line for last traceframe collected */
125static struct symtab_and_line traceframe_sal;
126
127/* Tracing command lists */
128static struct cmd_list_element *tfindlist;
129
130/* ======= Important command functions: ======= */
c5aa993b
JM
131static void trace_command PARAMS ((char *, int));
132static void tracepoints_info PARAMS ((char *, int));
133static void delete_trace_command PARAMS ((char *, int));
134static void enable_trace_command PARAMS ((char *, int));
135static void disable_trace_command PARAMS ((char *, int));
136static void trace_pass_command PARAMS ((char *, int));
137static void trace_actions_command PARAMS ((char *, int));
138static void trace_start_command PARAMS ((char *, int));
139static void trace_stop_command PARAMS ((char *, int));
140static void trace_status_command PARAMS ((char *, int));
141static void trace_find_command PARAMS ((char *, int));
142static void trace_find_pc_command PARAMS ((char *, int));
c906108c 143static void trace_find_tracepoint_command PARAMS ((char *, int));
c5aa993b
JM
144static void trace_find_line_command PARAMS ((char *, int));
145static void trace_find_range_command PARAMS ((char *, int));
146static void trace_find_outside_command PARAMS ((char *, int));
147static void tracepoint_save_command PARAMS ((char *, int));
148static void trace_dump_command PARAMS ((char *, int));
c906108c
SS
149
150/* support routines */
c5aa993b 151static void trace_mention PARAMS ((struct tracepoint *));
c906108c
SS
152
153struct collection_list;
154static void add_aexpr PARAMS ((struct collection_list *, struct agent_expr *));
c5aa993b 155static unsigned char *mem2hex (unsigned char *, unsigned char *, int);
104c1213
JM
156static void add_register PARAMS ((struct collection_list * collection,
157 unsigned int regno));
392a587b 158static void free_actions_list PARAMS ((char **actions_list));
c5aa993b 159static void free_actions_list_cleanup_wrapper PARAMS ((void *));
392a587b
JM
160
161extern void _initialize_tracepoint PARAMS ((void));
c906108c
SS
162
163/* Utility: returns true if "target remote" */
164static int
165target_is_remote ()
166{
167 if (current_target.to_shortname &&
168 strcmp (current_target.to_shortname, "remote") == 0)
169 return 1;
170 else
171 return 0;
172}
173
174/* Utility: generate error from an incoming stub packet. */
c5aa993b 175static void
c906108c
SS
176trace_error (buf)
177 char *buf;
178{
179 if (*buf++ != 'E')
180 return; /* not an error msg */
c5aa993b 181 switch (*buf)
c906108c
SS
182 {
183 case '1': /* malformed packet error */
184 if (*++buf == '0') /* general case: */
185 error ("tracepoint.c: error in outgoing packet.");
186 else
c5aa993b 187 error ("tracepoint.c: error in outgoing packet at field #%d.",
c906108c
SS
188 strtol (buf, NULL, 16));
189 case '2':
190 error ("trace API error 0x%s.", ++buf);
191 default:
192 error ("Target returns error code '%s'.", buf);
193 }
194}
195
104c1213
JM
196/* Entry points into remote.c (FIXME: move this interface down to tgt vector)
197 */
198
199extern int putpkt PARAMS ((char *));
200extern void getpkt PARAMS ((char *, int));
201extern void remote_console_output PARAMS ((char *));
202
c906108c
SS
203/* Utility: wait for reply from stub, while accepting "O" packets */
204static char *
205remote_get_noisy_reply (buf)
206 char *buf;
207{
c5aa993b 208 do /* loop on reply from remote stub */
c906108c 209 {
c5aa993b 210 QUIT; /* allow user to bail out with ^C */
c906108c
SS
211 getpkt (buf, 0);
212 if (buf[0] == 0)
213 error ("Target does not support this command.");
214 else if (buf[0] == 'E')
215 trace_error (buf);
216 else if (buf[0] == 'O' &&
217 buf[1] != 'K')
218 remote_console_output (buf + 1); /* 'O' message from stub */
219 else
c5aa993b
JM
220 return buf; /* here's the actual reply */
221 }
222 while (1);
c906108c
SS
223}
224
225/* Set tracepoint count to NUM. */
226static void
227set_tracepoint_count (num)
228 int num;
229{
230 tracepoint_count = num;
231 set_internalvar (lookup_internalvar ("tpnum"),
232 value_from_longest (builtin_type_int, (LONGEST) num));
233}
234
235/* Set traceframe number to NUM. */
236static void
237set_traceframe_num (num)
238 int num;
239{
240 traceframe_number = num;
241 set_internalvar (lookup_internalvar ("trace_frame"),
242 value_from_longest (builtin_type_int, (LONGEST) num));
243}
244
245/* Set tracepoint number to NUM. */
246static void
247set_tracepoint_num (num)
248 int num;
249{
250 tracepoint_number = num;
251 set_internalvar (lookup_internalvar ("tracepoint"),
252 value_from_longest (builtin_type_int, (LONGEST) num));
253}
254
255/* Set externally visible debug variables for querying/printing
256 the traceframe context (line, function, file) */
257
258static void
259set_traceframe_context (trace_pc)
260 CORE_ADDR trace_pc;
261{
262 static struct type *func_string, *file_string;
c5aa993b
JM
263 static struct type *func_range, *file_range;
264 static value_ptr func_val, file_val;
c906108c
SS
265 static struct type *charstar;
266 int len;
267
268 if (charstar == (struct type *) NULL)
269 charstar = lookup_pointer_type (builtin_type_char);
270
c5aa993b 271 if (trace_pc == -1) /* cease debugging any trace buffers */
c906108c
SS
272 {
273 traceframe_fun = 0;
274 traceframe_sal.pc = traceframe_sal.line = 0;
275 traceframe_sal.symtab = NULL;
c5aa993b 276 set_internalvar (lookup_internalvar ("trace_func"),
c906108c 277 value_from_longest (charstar, (LONGEST) 0));
c5aa993b 278 set_internalvar (lookup_internalvar ("trace_file"),
c906108c
SS
279 value_from_longest (charstar, (LONGEST) 0));
280 set_internalvar (lookup_internalvar ("trace_line"),
c5aa993b 281 value_from_longest (builtin_type_int, (LONGEST) - 1));
c906108c
SS
282 return;
283 }
284
285 /* save as globals for internal use */
286 traceframe_sal = find_pc_line (trace_pc, 0);
287 traceframe_fun = find_pc_function (trace_pc);
288
289 /* save linenumber as "$trace_line", a debugger variable visible to users */
290 set_internalvar (lookup_internalvar ("trace_line"),
c5aa993b 291 value_from_longest (builtin_type_int,
c906108c
SS
292 (LONGEST) traceframe_sal.line));
293
294 /* save func name as "$trace_func", a debugger variable visible to users */
c5aa993b 295 if (traceframe_fun == NULL ||
c906108c 296 SYMBOL_NAME (traceframe_fun) == NULL)
c5aa993b 297 set_internalvar (lookup_internalvar ("trace_func"),
c906108c
SS
298 value_from_longest (charstar, (LONGEST) 0));
299 else
300 {
301 len = strlen (SYMBOL_NAME (traceframe_fun));
c5aa993b
JM
302 func_range = create_range_type (func_range,
303 builtin_type_int, 0, len - 1);
304 func_string = create_array_type (func_string,
c906108c
SS
305 builtin_type_char, func_range);
306 func_val = allocate_value (func_string);
307 VALUE_TYPE (func_val) = func_string;
c5aa993b
JM
308 memcpy (VALUE_CONTENTS_RAW (func_val),
309 SYMBOL_NAME (traceframe_fun),
c906108c
SS
310 len);
311 func_val->modifiable = 0;
312 set_internalvar (lookup_internalvar ("trace_func"), func_val);
313 }
314
315 /* save file name as "$trace_file", a debugger variable visible to users */
c5aa993b 316 if (traceframe_sal.symtab == NULL ||
c906108c 317 traceframe_sal.symtab->filename == NULL)
c5aa993b 318 set_internalvar (lookup_internalvar ("trace_file"),
c906108c
SS
319 value_from_longest (charstar, (LONGEST) 0));
320 else
321 {
322 len = strlen (traceframe_sal.symtab->filename);
c5aa993b
JM
323 file_range = create_range_type (file_range,
324 builtin_type_int, 0, len - 1);
325 file_string = create_array_type (file_string,
c906108c
SS
326 builtin_type_char, file_range);
327 file_val = allocate_value (file_string);
328 VALUE_TYPE (file_val) = file_string;
c5aa993b
JM
329 memcpy (VALUE_CONTENTS_RAW (file_val),
330 traceframe_sal.symtab->filename,
c906108c
SS
331 len);
332 file_val->modifiable = 0;
333 set_internalvar (lookup_internalvar ("trace_file"), file_val);
334 }
335}
336
337/* Low level routine to set a tracepoint.
338 Returns the tracepoint object so caller can set other things.
339 Does not set the tracepoint number!
340 Does not print anything.
341
342 ==> This routine should not be called if there is a chance of later
343 error(); otherwise it leaves a bogus tracepoint on the chain. Validate
344 your arguments BEFORE calling this routine! */
345
346static struct tracepoint *
347set_raw_tracepoint (sal)
348 struct symtab_and_line sal;
349{
350 register struct tracepoint *t, *tc;
351 struct cleanup *old_chain;
352
353 t = (struct tracepoint *) xmalloc (sizeof (struct tracepoint));
354 old_chain = make_cleanup (free, t);
355 memset (t, 0, sizeof (*t));
356 t->address = sal.pc;
357 if (sal.symtab == NULL)
358 t->source_file = NULL;
359 else
c5aa993b 360 t->source_file = savestring (sal.symtab->filename,
c906108c
SS
361 strlen (sal.symtab->filename));
362
c5aa993b
JM
363 t->section = sal.section;
364 t->language = current_language->la_language;
c906108c
SS
365 t->input_radix = input_radix;
366 t->line_number = sal.line;
c5aa993b
JM
367 t->enabled = enabled;
368 t->next = 0;
369 t->step_count = 0;
370 t->pass_count = 0;
c906108c
SS
371 t->addr_string = NULL;
372
373 /* Add this tracepoint to the end of the chain
374 so that a list of tracepoints will come out in order
375 of increasing numbers. */
376
377 tc = tracepoint_chain;
378 if (tc == 0)
379 tracepoint_chain = t;
380 else
381 {
382 while (tc->next)
383 tc = tc->next;
384 tc->next = t;
385 }
386 discard_cleanups (old_chain);
387 return t;
388}
389
390/* Set a tracepoint according to ARG (function, linenum or *address) */
391static void
392trace_command (arg, from_tty)
393 char *arg;
394 int from_tty;
395{
c5aa993b 396 char **canonical = (char **) NULL;
c906108c
SS
397 struct symtabs_and_lines sals;
398 struct symtab_and_line sal;
399 struct tracepoint *t;
400 char *addr_start = 0, *addr_end = 0;
401 int i;
402
403 if (!arg || !*arg)
404 error ("trace command requires an argument");
405
406 if (from_tty && info_verbose)
407 printf_filtered ("TRACE %s\n", arg);
408
409 addr_start = arg;
c5aa993b
JM
410 sals = decode_line_1 (&arg, 1, (struct symtab *) NULL, 0, &canonical);
411 addr_end = arg;
412 if (!sals.nelts)
413 return; /* ??? Presumably decode_line_1 has already warned? */
c906108c
SS
414
415 /* Resolve all line numbers to PC's */
416 for (i = 0; i < sals.nelts; i++)
417 resolve_sal_pc (&sals.sals[i]);
418
419 /* Now set all the tracepoints. */
420 for (i = 0; i < sals.nelts; i++)
421 {
422 sal = sals.sals[i];
423
424 t = set_raw_tracepoint (sal);
425 set_tracepoint_count (tracepoint_count + 1);
426 t->number = tracepoint_count;
427
428 /* If a canonical line spec is needed use that instead of the
c5aa993b
JM
429 command string. */
430 if (canonical != (char **) NULL && canonical[i] != NULL)
c906108c
SS
431 t->addr_string = canonical[i];
432 else if (addr_start)
433 t->addr_string = savestring (addr_start, addr_end - addr_start);
434
435 trace_mention (t);
436
437 /* Let the UI know of any additions */
438 if (create_tracepoint_hook)
439 create_tracepoint_hook (t);
440 }
441
442 if (sals.nelts > 1)
443 {
444 printf_filtered ("Multiple tracepoints were set.\n");
445 printf_filtered ("Use 'delete trace' to delete unwanted tracepoints.\n");
446 }
447}
448
449/* Tell the user we have just set a tracepoint TP. */
450
451static void
452trace_mention (tp)
453 struct tracepoint *tp;
454{
455 printf_filtered ("Tracepoint %d", tp->number);
456
457 if (addressprint || (tp->source_file == NULL))
458 {
459 printf_filtered (" at ");
460 print_address_numeric (tp->address, 1, gdb_stdout);
461 }
462 if (tp->source_file)
463 printf_filtered (": file %s, line %d.",
464 tp->source_file, tp->line_number);
465
466 printf_filtered ("\n");
467}
468
469/* Print information on tracepoint number TPNUM_EXP, or all if omitted. */
470
471static void
472tracepoints_info (tpnum_exp, from_tty)
473 char *tpnum_exp;
474 int from_tty;
475{
476 struct tracepoint *t;
477 struct action_line *action;
478 int found_a_tracepoint = 0;
479 char wrap_indent[80];
480 struct symbol *sym;
481 int tpnum = -1;
482
483 if (tpnum_exp)
484 tpnum = parse_and_eval_address (tpnum_exp);
485
486 ALL_TRACEPOINTS (t)
487 if (tpnum == -1 || tpnum == t->number)
c5aa993b
JM
488 {
489 extern int addressprint; /* print machine addresses? */
c906108c 490
c5aa993b
JM
491 if (!found_a_tracepoint++)
492 {
493 printf_filtered ("Num Enb ");
494 if (addressprint)
495 printf_filtered ("Address ");
496 printf_filtered ("PassC StepC What\n");
497 }
498 strcpy (wrap_indent, " ");
499 if (addressprint)
500 strcat (wrap_indent, " ");
501
502 printf_filtered ("%-3d %-3s ", t->number,
503 t->enabled == enabled ? "y" : "n");
504 if (addressprint)
505 printf_filtered ("%s ",
506 local_hex_string_custom ((unsigned long) t->address,
507 "08l"));
508 printf_filtered ("%-5d %-5d ", t->pass_count, t->step_count);
509
510 if (t->source_file)
511 {
512 sym = find_pc_sect_function (t->address, t->section);
513 if (sym)
514 {
515 fputs_filtered ("in ", gdb_stdout);
516 fputs_filtered (SYMBOL_SOURCE_NAME (sym), gdb_stdout);
517 wrap_here (wrap_indent);
518 fputs_filtered (" at ", gdb_stdout);
519 }
520 fputs_filtered (t->source_file, gdb_stdout);
521 printf_filtered (":%d", t->line_number);
522 }
523 else
524 print_address_symbolic (t->address, gdb_stdout, demangle, " ");
c906108c 525
c5aa993b
JM
526 printf_filtered ("\n");
527 if (t->actions)
528 {
529 printf_filtered (" Actions for tracepoint %d: \n", t->number);
530 for (action = t->actions; action; action = action->next)
531 {
532 printf_filtered ("\t%s\n", action->action);
533 }
534 }
535 }
c906108c
SS
536 if (!found_a_tracepoint)
537 {
538 if (tpnum == -1)
c5aa993b 539 printf_filtered ("No tracepoints.\n");
c906108c 540 else
c5aa993b 541 printf_filtered ("No tracepoint number %d.\n", tpnum);
c906108c
SS
542 }
543}
544
545/* Optimization: the code to parse an enable, disable, or delete TP command
546 is virtually identical except for whether it performs an enable, disable,
547 or delete. Therefore I've combined them into one function with an opcode.
c5aa993b
JM
548 */
549enum tracepoint_opcode
c906108c 550{
104c1213
JM
551 enable_op,
552 disable_op,
553 delete_op
c906108c
SS
554};
555
104c1213 556/* This function implements enable, disable and delete commands. */
c906108c
SS
557static void
558tracepoint_operation (t, from_tty, opcode)
559 struct tracepoint *t;
560 int from_tty;
561 enum tracepoint_opcode opcode;
562{
563 struct tracepoint *t2;
564
c5aa993b
JM
565 switch (opcode)
566 {
104c1213 567 case enable_op:
c5aa993b
JM
568 t->enabled = enabled;
569 if (modify_tracepoint_hook)
570 modify_tracepoint_hook (t);
571 break;
104c1213 572 case disable_op:
c5aa993b
JM
573 t->enabled = disabled;
574 if (modify_tracepoint_hook)
575 modify_tracepoint_hook (t);
576 break;
104c1213 577 case delete_op:
c5aa993b
JM
578 if (tracepoint_chain == t)
579 tracepoint_chain = t->next;
c906108c 580
c5aa993b
JM
581 ALL_TRACEPOINTS (t2)
582 if (t2->next == t)
c906108c
SS
583 {
584 t2->next = t->next;
585 break;
586 }
587
c5aa993b
JM
588 /* Let the UI know of any deletions */
589 if (delete_tracepoint_hook)
590 delete_tracepoint_hook (t);
c906108c 591
c5aa993b
JM
592 if (t->addr_string)
593 free (t->addr_string);
594 if (t->source_file)
595 free (t->source_file);
596 if (t->actions)
597 free_actions (t);
c906108c 598
c5aa993b
JM
599 free (t);
600 break;
601 }
c906108c
SS
602}
603
604/* Utility: parse a tracepoint number and look it up in the list. */
605struct tracepoint *
606get_tracepoint_by_number (arg)
607 char **arg;
608{
609 struct tracepoint *t;
610 char *end, *copy;
611 value_ptr val;
612 int tpnum;
613
614 if (arg == 0)
615 error ("Bad tracepoint argument");
616
617 if (*arg == 0 || **arg == 0) /* empty arg means refer to last tp */
618 tpnum = tracepoint_count;
619 else if (**arg == '$') /* handle convenience variable */
620 {
621 /* Make a copy of the name, so we can null-terminate it
c5aa993b 622 to pass to lookup_internalvar(). */
c906108c 623 end = *arg + 1;
104c1213 624 while (isalnum ((int) *end) || *end == '_')
c906108c
SS
625 end++;
626 copy = (char *) alloca (end - *arg);
627 strncpy (copy, *arg + 1, (end - *arg - 1));
628 copy[end - *arg - 1] = '\0';
629 *arg = end;
630
631 val = value_of_internalvar (lookup_internalvar (copy));
c5aa993b 632 if (TYPE_CODE (VALUE_TYPE (val)) != TYPE_CODE_INT)
c906108c
SS
633 error ("Convenience variable must have integral type.");
634 tpnum = (int) value_as_long (val);
635 }
c5aa993b
JM
636 else
637 /* handle tracepoint number */
c906108c
SS
638 {
639 tpnum = strtol (*arg, arg, 0);
640 if (tpnum == 0) /* possible strtol failure */
104c1213 641 while (**arg && !isspace ((int) **arg))
c906108c
SS
642 (*arg)++; /* advance to next white space, if any */
643 }
644 ALL_TRACEPOINTS (t)
645 if (t->number == tpnum)
c5aa993b
JM
646 {
647 return t;
648 }
c906108c
SS
649 printf_unfiltered ("No tracepoint number %d.\n", tpnum);
650 return NULL;
651}
652
653/* Utility: parse a list of tracepoint numbers, and call a func for each. */
654static void
655map_args_over_tracepoints (args, from_tty, opcode)
656 char *args;
657 int from_tty;
658 enum tracepoint_opcode opcode;
659{
660 struct tracepoint *t, *tmp;
c906108c
SS
661
662 if (args == 0 || *args == 0) /* do them all */
663 ALL_TRACEPOINTS_SAFE (t, tmp)
664 tracepoint_operation (t, from_tty, opcode);
665 else
666 while (*args)
667 {
c5aa993b 668 QUIT; /* give user option to bail out with ^C */
7a292a7a
SS
669 t = get_tracepoint_by_number (&args);
670 if (t)
c906108c
SS
671 tracepoint_operation (t, from_tty, opcode);
672 while (*args == ' ' || *args == '\t')
673 args++;
674 }
675}
676
677/* The 'enable trace' command enables tracepoints. Not supported by all targets. */
678static void
679enable_trace_command (args, from_tty)
680 char *args;
681 int from_tty;
682{
683 dont_repeat ();
104c1213 684 map_args_over_tracepoints (args, from_tty, enable_op);
c906108c
SS
685}
686
687/* The 'disable trace' command enables tracepoints. Not supported by all targets. */
688static void
689disable_trace_command (args, from_tty)
690 char *args;
691 int from_tty;
692{
693 dont_repeat ();
104c1213 694 map_args_over_tracepoints (args, from_tty, disable_op);
c906108c
SS
695}
696
697/* Remove a tracepoint (or all if no argument) */
698static void
699delete_trace_command (args, from_tty)
700 char *args;
701 int from_tty;
702{
703 dont_repeat ();
704 if (!args || !*args) /* No args implies all tracepoints; */
705 if (from_tty) /* confirm only if from_tty... */
c5aa993b 706 if (tracepoint_chain) /* and if there are tracepoints to delete! */
c906108c
SS
707 if (!query ("Delete all tracepoints? "))
708 return;
709
104c1213 710 map_args_over_tracepoints (args, from_tty, delete_op);
c906108c
SS
711}
712
713/* Set passcount for tracepoint.
714
715 First command argument is passcount, second is tracepoint number.
716 If tracepoint number omitted, apply to most recently defined.
717 Also accepts special argument "all". */
718
719static void
720trace_pass_command (args, from_tty)
721 char *args;
722 int from_tty;
723{
724 struct tracepoint *t1 = (struct tracepoint *) -1, *t2;
104c1213 725 unsigned int count;
c906108c
SS
726
727 if (args == 0 || *args == 0)
728 error ("PASS command requires an argument (count + optional TP num)");
729
730 count = strtoul (args, &args, 10); /* count comes first, then TP num */
731
104c1213 732 while (*args && isspace ((int) *args))
c906108c
SS
733 args++;
734
735 if (*args && strncasecmp (args, "all", 3) == 0)
c5aa993b 736 args += 3; /* skip special argument "all" */
c906108c
SS
737 else
738 t1 = get_tracepoint_by_number (&args);
739
740 if (*args)
741 error ("Junk at end of arguments.");
742
743 if (t1 == NULL)
c5aa993b 744 return; /* error, bad tracepoint number */
c906108c
SS
745
746 ALL_TRACEPOINTS (t2)
747 if (t1 == (struct tracepoint *) -1 || t1 == t2)
c5aa993b
JM
748 {
749 t2->pass_count = count;
750 if (modify_tracepoint_hook)
751 modify_tracepoint_hook (t2);
752 if (from_tty)
753 printf_filtered ("Setting tracepoint %d's passcount to %d\n",
754 t2->number, count);
755 }
c906108c
SS
756}
757
758/* ACTIONS functions: */
759
760/* Prototypes for action-parsing utility commands */
c5aa993b 761static void read_actions PARAMS ((struct tracepoint *));
c906108c
SS
762
763/* The three functions:
c5aa993b
JM
764 collect_pseudocommand,
765 while_stepping_pseudocommand, and
766 end_actions_pseudocommand
c906108c
SS
767 are placeholders for "commands" that are actually ONLY to be used
768 within a tracepoint action list. If the actual function is ever called,
769 it means that somebody issued the "command" at the top level,
770 which is always an error. */
771
c5aa993b 772static void
c906108c
SS
773end_actions_pseudocommand (args, from_tty)
774 char *args;
775 int from_tty;
776{
777 error ("This command cannot be used at the top level.");
778}
779
780static void
781while_stepping_pseudocommand (args, from_tty)
782 char *args;
783 int from_tty;
784{
785 error ("This command can only be used in a tracepoint actions list.");
786}
787
788static void
789collect_pseudocommand (args, from_tty)
790 char *args;
791 int from_tty;
792{
793 error ("This command can only be used in a tracepoint actions list.");
794}
795
796/* Enter a list of actions for a tracepoint. */
797static void
798trace_actions_command (args, from_tty)
799 char *args;
800 int from_tty;
801{
802 struct tracepoint *t;
c906108c
SS
803 char tmpbuf[128];
804 char *end_msg = "End with a line saying just \"end\".";
805
7a292a7a
SS
806 t = get_tracepoint_by_number (&args);
807 if (t)
c906108c
SS
808 {
809 sprintf (tmpbuf, "Enter actions for tracepoint %d, one per line.",
810 t->number);
811
812 if (from_tty)
813 {
814 if (readline_begin_hook)
815 (*readline_begin_hook) ("%s %s\n", tmpbuf, end_msg);
816 else if (input_from_terminal_p ())
817 printf_filtered ("%s\n%s\n", tmpbuf, end_msg);
818 }
819
820 free_actions (t);
821 t->step_count = 0; /* read_actions may set this */
822 read_actions (t);
823
824 if (readline_end_hook)
825 (*readline_end_hook) ();
826
827 /* tracepoints_changed () */
828 }
829 /* else error, just return; */
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
JM
850 {
851 if (async_p)
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);
1739 getpkt (target_buf, 0);
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");
1767 remote_get_noisy_reply (target_buf);
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);
1783 remote_get_noisy_reply (target_buf);
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);
1807 remote_get_noisy_reply (target_buf);
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);
1823 remote_get_noisy_reply (target_buf);
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");
1836 remote_get_noisy_reply (target_buf);
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");
1860 remote_get_noisy_reply (target_buf);
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");
1882 remote_get_noisy_reply (target_buf);
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
1897finish_tfind_command (msg, from_tty)
1898 char *msg;
1899 int from_tty;
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);
1910 reply = remote_get_noisy_reply (msg);
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);
2054 finish_tfind_command (target_buf, from_tty);
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);
c906108c
SS
2105 finish_tfind_command (target_buf, from_tty);
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);
2130 finish_tfind_command (target_buf, from_tty);
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);
c906108c
SS
2226 finish_tfind_command (target_buf, from_tty);
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);
c906108c
SS
2268 finish_tfind_command (target_buf, from_tty);
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);
c906108c
SS
2309 finish_tfind_command (target_buf, from_tty);
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}
This page took 0.41039 seconds and 4 git commands to generate.