Bug Summary

File:src/gnu/usr.bin/binutils/gdb/tracepoint.c
Warning:line 1442, column 7
Value stored to 'count' is never read

Annotated Source Code

Press '?' to see keyboard shortcuts

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