OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [gdb-5.0/] [gdb/] [tracepoint.c] - Blame information for rev 104

Go to most recent revision | Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.