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

Subversion Repositories or1k

[/] [or1k/] [trunk/] [insight/] [gdb/] [gdbtk/] [generic/] [gdbtk-bp.c] - Blame information for rev 578

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

Line No. Rev Author Line
1 578 markom
/* Tcl/Tk command definitions for Insight - Breakpoints.
2
   Copyright 2001 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 "symfile.h"
24
#include "linespec.h"
25
#include "breakpoint.h"
26
#include "tracepoint.h"
27
#include "gdb-events.h"
28
 
29
#include <tcl.h>
30
#include "gdbtk.h"
31
#include "gdbtk-cmds.h"
32
 
33
/* From breakpoint.c */
34
extern struct breakpoint *breakpoint_chain;
35
 
36
/* From gdbtk-hooks.c */
37
extern void report_error (void);
38
 
39
/* These two lookup tables are used to translate the type & disposition fields
40
   of the breakpoint structure (respectively) into something gdbtk understands.
41
   They are also used in gdbtk-hooks.c */
42
 
43
char *bptypes[] =
44
{"none", "breakpoint", "hw breakpoint", "until",
45
 "finish", "watchpoint", "hw watchpoint",
46
 "read watchpoint", "acc watchpoint",
47
 "longjmp", "longjmp resume", "step resume",
48
 "sigtramp", "watchpoint scope",
49
 "call dummy", "shlib events", "catch load",
50
 "catch unload", "catch fork", "catch vfork",
51
 "catch exec", "catch catch", "catch throw"
52
};
53
char *bpdisp[] =
54
{"delete", "delstop", "disable", "donttouch"};
55
 
56
/* Is this breakpoint interesting to a user interface? */
57
#define BREAKPOINT_IS_INTERESTING(bp) \
58
((bp)->type == bp_breakpoint             \
59
 || (bp)->type == bp_hardware_breakpoint \
60
 || (bp)->type == bp_watchpoint          \
61
 || (bp)->type == bp_hardware_watchpoint \
62
 || (bp)->type == bp_read_watchpoint     \
63
 || (bp)->type == bp_access_watchpoint)
64
 
65
/* Is this breakpoint a watchpoint?  */
66
#define BREAKPOINT_IS_WATCHPOINT(bp)                                          \
67
((bp)->type == bp_watchpoint                                                  \
68
 || (bp)->type == bp_hardware_watchpoint                                      \
69
 || (bp)->type == bp_read_watchpoint                                          \
70
 || (bp)->type == bp_access_watchpoint)
71
 
72
/*
73
 * These are routines we need from breakpoint.c.
74
 * at some point make these static in breakpoint.c and move GUI code there
75
 */
76
 
77
extern struct breakpoint *set_raw_breakpoint (struct symtab_and_line sal,
78
                                              enum bptype bp_type);
79
extern void set_breakpoint_count (int);
80
extern int breakpoint_count;
81
 
82
/* Breakpoint/Tracepoint lists. Unfortunately, gdb forces us to
83
   keep a list of breakpoints, too. Why couldn't it be done like
84
   treacepoints? */
85
#define DEFAULT_LIST_SIZE 32
86
static struct breakpoint **breakpoint_list;
87
static int breakpoint_list_size = DEFAULT_LIST_SIZE;
88
 
89
/*
90
 * Forward declarations
91
 */
92
 
93
/* Breakpoint-related functions */
94
static int gdb_find_bp_at_addr (ClientData, Tcl_Interp *, int,
95
                                Tcl_Obj * CONST objv[]);
96
static int gdb_find_bp_at_line (ClientData, Tcl_Interp *, int,
97
                                Tcl_Obj * CONST objv[]);
98
static int gdb_get_breakpoint_info (ClientData, Tcl_Interp *, int,
99
                                    Tcl_Obj * CONST[]);
100
static int gdb_get_breakpoint_list (ClientData, Tcl_Interp *, int,
101
                                    Tcl_Obj * CONST[]);
102
static int gdb_set_bp (ClientData, Tcl_Interp *, int, Tcl_Obj * CONST objv[]);
103
static int gdb_set_bp_addr (ClientData, Tcl_Interp *, int,
104
                            Tcl_Obj * CONST objv[]);
105
 
106
/* Tracepoint-related functions */
107
static int gdb_actions_command (ClientData, Tcl_Interp *, int,
108
                                Tcl_Obj * CONST objv[]);
109
static int gdb_get_trace_frame_num (ClientData, Tcl_Interp *, int,
110
                                    Tcl_Obj * CONST objv[]);
111
static int gdb_get_tracepoint_info (ClientData, Tcl_Interp *, int,
112
                                    Tcl_Obj * CONST objv[]);
113
static int gdb_get_tracepoint_list (ClientData, Tcl_Interp *, int,
114
                                    Tcl_Obj * CONST objv[]);
115
static int gdb_trace_status (ClientData, Tcl_Interp *, int,
116
                             Tcl_Obj * CONST[]);
117
static int gdb_tracepoint_exists_command (ClientData, Tcl_Interp *,
118
                                          int, Tcl_Obj * CONST objv[]);
119
static int tracepoint_exists (char *args);
120
 
121
/* Breakpoint/tracepoint events and related functions */
122
 
123
void gdbtk_create_breakpoint (int);
124
void gdbtk_delete_breakpoint (int);
125
void gdbtk_modify_breakpoint (int);
126
void gdbtk_create_tracepoint (int);
127
void gdbtk_delete_tracepoint (int);
128
void gdbtk_modify_tracepoint (int);
129
static void breakpoint_notify (int, const char *);
130
static void tracepoint_notify (int, const char *);
131
 
132
int
133
Gdbtk_Breakpoint_Init (Tcl_Interp *interp)
134
{
135
  /* Breakpoint commands */
136
  Tcl_CreateObjCommand (interp, "gdb_find_bp_at_addr", gdbtk_call_wrapper,
137
                        gdb_find_bp_at_addr, NULL);
138
  Tcl_CreateObjCommand (interp, "gdb_find_bp_at_line", gdbtk_call_wrapper,
139
                        gdb_find_bp_at_line, NULL);
140
  Tcl_CreateObjCommand (interp, "gdb_get_breakpoint_info", gdbtk_call_wrapper,
141
                        gdb_get_breakpoint_info, NULL);
142
  Tcl_CreateObjCommand (interp, "gdb_get_breakpoint_list", gdbtk_call_wrapper,
143
                        gdb_get_breakpoint_list, NULL);
144
  Tcl_CreateObjCommand (interp, "gdb_set_bp", gdbtk_call_wrapper, gdb_set_bp, NULL);
145
  Tcl_CreateObjCommand (interp, "gdb_set_bp_addr", gdbtk_call_wrapper,
146
                        gdb_set_bp_addr, NULL);
147
 
148
  /* Tracepoint commands */
149
  Tcl_CreateObjCommand (interp, "gdb_actions",
150
                        gdbtk_call_wrapper, gdb_actions_command, NULL);
151
  Tcl_CreateObjCommand (interp, "gdb_get_trace_frame_num",
152
                        gdbtk_call_wrapper, gdb_get_trace_frame_num, NULL);
153
  Tcl_CreateObjCommand (interp, "gdb_get_tracepoint_info",
154
                        gdbtk_call_wrapper, gdb_get_tracepoint_info, NULL);
155
  Tcl_CreateObjCommand (interp, "gdb_get_tracepoint_list",
156
                        gdbtk_call_wrapper, gdb_get_tracepoint_list, NULL);
157
  Tcl_CreateObjCommand (interp, "gdb_is_tracing",
158
                        gdbtk_call_wrapper, gdb_trace_status,   NULL);
159
  Tcl_CreateObjCommand (interp, "gdb_tracepoint_exists",
160
                        gdbtk_call_wrapper, gdb_tracepoint_exists_command, NULL);
161
 
162
  /* Initialize our tables of BPs. */
163
  breakpoint_list = (struct breakpoint **) xmalloc (breakpoint_list_size * sizeof (struct breakpoint *));
164
  memset (breakpoint_list, 0, breakpoint_list_size * sizeof (struct breakpoint *));
165
 
166
  return TCL_OK;
167
}
168
 
169
/*
170
 *  This section contains commands for manipulation of breakpoints.
171
 */
172
 
173
/* set a breakpoint by source file and line number
174
   flags are as follows:
175
   least significant 2 bits are disposition, rest is
176
   type (normally 0).
177
 
178
   enum bptype {
179
   bp_breakpoint,                Normal breakpoint
180
   bp_hardware_breakpoint,      Hardware assisted breakpoint
181
   }
182
 
183
   Disposition of breakpoint.  Ie: what to do after hitting it.
184
   enum bpdisp {
185
   del,                         Delete it
186
   del_at_next_stop,            Delete at next stop, whether hit or not
187
   disable,                     Disable it
188
   donttouch                    Leave it alone
189
   };
190
 */
191
 
192
 
193
/* This implements the tcl command "gdb_find_bp_at_addr"
194
 
195
 * Tcl Arguments:
196
 *    addr:     address
197
 * Tcl Result:
198
 *    It returns a list of breakpoint numbers
199
 */
200
static int
201
gdb_find_bp_at_addr (clientData, interp, objc, objv)
202
     ClientData clientData;
203
     Tcl_Interp *interp;
204
     int objc;
205
     Tcl_Obj *CONST objv[];
206
 
207
{
208
  int i;
209
  long addr;
210
 
211
  if (objc != 2)
212
    {
213
      Tcl_WrongNumArgs (interp, 1, objv, "address");
214
      return TCL_ERROR;
215
    }
216
 
217
  if (Tcl_GetLongFromObj (interp, objv[1], &addr) == TCL_ERROR)
218
    {
219
      result_ptr->flags = GDBTK_IN_TCL_RESULT;
220
      return TCL_ERROR;
221
    }
222
 
223
  Tcl_SetListObj (result_ptr->obj_ptr, 0, NULL);
224
  for (i = 0; i < breakpoint_list_size; i++)
225
    {
226
      if (breakpoint_list[i] != NULL
227
          && breakpoint_list[i]->address == (CORE_ADDR) addr)
228
        Tcl_ListObjAppendElement (NULL, result_ptr->obj_ptr,
229
                                  Tcl_NewIntObj (i));
230
    }
231
 
232
  return TCL_OK;
233
}
234
 
235
/* This implements the tcl command "gdb_find_bp_at_line"
236
 
237
 * Tcl Arguments:
238
 *    filename: the file in which to find the breakpoint
239
 *    line:     the line number for the breakpoint
240
 * Tcl Result:
241
 *    It returns a list of breakpoint numbers
242
 */
243
static int
244
gdb_find_bp_at_line (clientData, interp, objc, objv)
245
     ClientData clientData;
246
     Tcl_Interp *interp;
247
     int objc;
248
     Tcl_Obj *CONST objv[];
249
 
250
{
251
  struct symtab *s;
252
  int line;
253
  int i;
254
 
255
  if (objc != 3)
256
    {
257
      Tcl_WrongNumArgs (interp, 1, objv, "filename line");
258
      return TCL_ERROR;
259
    }
260
 
261
  s = full_lookup_symtab (Tcl_GetStringFromObj (objv[1], NULL));
262
  if (s == NULL)
263
    return TCL_ERROR;
264
 
265
  if (Tcl_GetIntFromObj (interp, objv[2], &line) == TCL_ERROR)
266
    {
267
      result_ptr->flags = GDBTK_IN_TCL_RESULT;
268
      return TCL_ERROR;
269
    }
270
 
271
  Tcl_SetListObj (result_ptr->obj_ptr, 0, NULL);
272
  for (i = 0; i < breakpoint_list_size; i++)
273
    if (breakpoint_list[i] != NULL
274
        && breakpoint_list[i]->line_number == line
275
        && !strcmp (breakpoint_list[i]->source_file, s->filename))
276
      Tcl_ListObjAppendElement (NULL, result_ptr->obj_ptr,
277
                                Tcl_NewIntObj (i));
278
 
279
  return TCL_OK;
280
}
281
 
282
/* This implements the tcl command gdb_get_breakpoint_info
283
 *
284
 * Tcl Arguments:
285
 *   breakpoint_number
286
 * Tcl Result:
287
 *   A list with {file, function, line_number, address, type, enabled?,
288
 *                disposition, ignore_count, {list_of_commands},
289
 *                condition, thread, hit_count user_specification}
290
 */
291
static int
292
gdb_get_breakpoint_info (ClientData clientData, Tcl_Interp *interp, int objc,
293
                         Tcl_Obj *CONST objv[])
294
{
295
  struct symtab_and_line sal;
296
  struct command_line *cmd;
297
  int bpnum;
298
  struct breakpoint *b;
299
  char *funcname, *filename;
300
 
301
  Tcl_Obj *new_obj;
302
 
303
  if (objc != 2)
304
    {
305
      Tcl_WrongNumArgs (interp, 1, objv, "breakpoint");
306
      return TCL_ERROR;
307
    }
308
 
309
  if (Tcl_GetIntFromObj (NULL, objv[1], &bpnum) != TCL_OK)
310
    {
311
      result_ptr->flags = GDBTK_IN_TCL_RESULT;
312
      return TCL_ERROR;
313
    }
314
 
315
  b = (bpnum <= breakpoint_list_size ? breakpoint_list[bpnum] : NULL);
316
  if (!b || b->type != bp_breakpoint)
317
    {
318
      char *err_buf;
319
      xasprintf (&err_buf, "Breakpoint #%d does not exist.", bpnum);
320
      Tcl_SetStringObj (result_ptr->obj_ptr, err_buf, -1);
321
      free(err_buf);
322
      return TCL_ERROR;
323
    }
324
 
325
  sal = find_pc_line (b->address, 0);
326
 
327
  filename = symtab_to_filename (sal.symtab);
328
  if (filename == NULL)
329
    filename = "";
330
 
331
  Tcl_SetListObj (result_ptr->obj_ptr, 0, NULL);
332
  Tcl_ListObjAppendElement (NULL, result_ptr->obj_ptr,
333
                            Tcl_NewStringObj (filename, -1));
334
 
335
  funcname = pc_function_name (b->address);
336
  new_obj = Tcl_NewStringObj (funcname, -1);
337
  Tcl_ListObjAppendElement (NULL, result_ptr->obj_ptr, new_obj);
338
 
339
  Tcl_ListObjAppendElement (NULL, result_ptr->obj_ptr,
340
                            Tcl_NewIntObj (b->line_number));
341
  sprintf_append_element_to_obj (result_ptr->obj_ptr, "0x%s",
342
                                 paddr_nz (b->address));
343
  Tcl_ListObjAppendElement (NULL, result_ptr->obj_ptr,
344
                            Tcl_NewStringObj (bptypes[b->type], -1));
345
  Tcl_ListObjAppendElement (NULL, result_ptr->obj_ptr,
346
                            Tcl_NewBooleanObj (b->enable == enabled));
347
  Tcl_ListObjAppendElement (NULL, result_ptr->obj_ptr,
348
                            Tcl_NewStringObj (bpdisp[b->disposition], -1));
349
  Tcl_ListObjAppendElement (NULL, result_ptr->obj_ptr,
350
                            Tcl_NewIntObj (b->ignore_count));
351
 
352
  new_obj = Tcl_NewObj ();
353
  for (cmd = b->commands; cmd; cmd = cmd->next)
354
    Tcl_ListObjAppendElement (NULL, new_obj,
355
                              Tcl_NewStringObj (cmd->line, -1));
356
  Tcl_ListObjAppendElement (NULL, result_ptr->obj_ptr, new_obj);
357
 
358
  Tcl_ListObjAppendElement (NULL, result_ptr->obj_ptr,
359
                            Tcl_NewStringObj (b->cond_string, -1));
360
 
361
  Tcl_ListObjAppendElement (NULL, result_ptr->obj_ptr,
362
                            Tcl_NewIntObj (b->thread));
363
  Tcl_ListObjAppendElement (NULL, result_ptr->obj_ptr,
364
                            Tcl_NewIntObj (b->hit_count));
365
 
366
  Tcl_ListObjAppendElement (NULL, result_ptr->obj_ptr,
367
                            Tcl_NewStringObj (BREAKPOINT_IS_WATCHPOINT (b)
368
                                              ? b->exp_string
369
                                              : b->addr_string, -1));
370
 
371
  return TCL_OK;
372
}
373
 
374
 
375
/* This implements the tcl command gdb_get_breakpoint_list
376
 * It builds up a list of the current breakpoints.
377
 *
378
 * Tcl Arguments:
379
 *    None.
380
 * Tcl Result:
381
 *    A list of breakpoint numbers.
382
 */
383
static int
384
gdb_get_breakpoint_list (clientData, interp, objc, objv)
385
     ClientData clientData;
386
     Tcl_Interp *interp;
387
     int objc;
388
     Tcl_Obj *CONST objv[];
389
{
390
  int i;
391
  Tcl_Obj *new_obj;
392
 
393
  if (objc != 1)
394
    {
395
      Tcl_WrongNumArgs (interp, 1, objv, NULL);
396
      return TCL_ERROR;
397
    }
398
 
399
  for (i = 0; i < breakpoint_list_size; i++)
400
    {
401
      if (breakpoint_list[i] != NULL
402
          && breakpoint_list[i]->type == bp_breakpoint)
403
        {
404
          new_obj = Tcl_NewIntObj (i);
405
          Tcl_ListObjAppendElement (NULL, result_ptr->obj_ptr, new_obj);
406
        }
407
    }
408
 
409
  return TCL_OK;
410
}
411
 
412
/* This implements the tcl command "gdb_set_bp"
413
 * It sets breakpoints, and notifies the GUI.
414
 *
415
 * Tcl Arguments:
416
 *    filename: the file in which to set the breakpoint
417
 *    line:     the line number for the breakpoint
418
 *    type:     the type of the breakpoint
419
 *    thread:   optional thread number
420
 * Tcl Result:
421
 *    The return value of the call to gdbtk_tcl_breakpoint.
422
 */
423
static int
424
gdb_set_bp (clientData, interp, objc, objv)
425
     ClientData clientData;
426
     Tcl_Interp *interp;
427
     int objc;
428
     Tcl_Obj *CONST objv[];
429
{
430
  struct symtab_and_line sal;
431
  int line, thread = -1;
432
  struct breakpoint *b;
433
  char *buf, *typestr;
434
  enum bpdisp disp;
435
 
436
  if (objc != 4 && objc != 5)
437
    {
438
      Tcl_WrongNumArgs (interp, 1, objv, "filename line type ?thread?");
439
      return TCL_ERROR;
440
    }
441
 
442
  sal.symtab = full_lookup_symtab (Tcl_GetStringFromObj (objv[1], NULL));
443
  if (sal.symtab == NULL)
444
    return TCL_ERROR;
445
 
446
  if (Tcl_GetIntFromObj (interp, objv[2], &line) == TCL_ERROR)
447
    {
448
      result_ptr->flags = GDBTK_IN_TCL_RESULT;
449
      return TCL_ERROR;
450
    }
451
 
452
  typestr = Tcl_GetStringFromObj (objv[3], NULL);
453
  if (typestr == NULL)
454
    {
455
      result_ptr->flags = GDBTK_IN_TCL_RESULT;
456
      return TCL_ERROR;
457
    }
458
  if (strncmp (typestr, "temp", 4) == 0)
459
    disp = del;
460
  else if (strncmp (typestr, "normal", 6) == 0)
461
    disp = donttouch;
462
  else
463
    {
464
      Tcl_SetStringObj (result_ptr->obj_ptr,
465
                        "type must be \"temp\" or \"normal\"", -1);
466
      return TCL_ERROR;
467
    }
468
 
469
  if (objc == 5)
470
    {
471
      if (Tcl_GetIntFromObj (interp, objv[4], &thread) == TCL_ERROR)
472
        {
473
          result_ptr->flags = GDBTK_IN_TCL_RESULT;
474
          return TCL_ERROR;
475
        }
476
    }
477
 
478
  sal.line = line;
479
  if (!find_line_pc (sal.symtab, sal.line, &sal.pc))
480
    return TCL_ERROR;
481
 
482
  sal.section = find_pc_overlay (sal.pc);
483
  b = set_raw_breakpoint (sal, bp_breakpoint);
484
  set_breakpoint_count (breakpoint_count + 1);
485
  b->number = breakpoint_count;
486
  b->disposition = disp;
487
  b->thread = thread;
488
 
489
  /* FIXME: this won't work for duplicate basenames! */
490
  xasprintf (&buf, "%s:%d", basename (Tcl_GetStringFromObj (objv[1], NULL)),
491
           line);
492
  b->addr_string = xstrdup (buf);
493
  free(buf);
494
 
495
  /* now send notification command back to GUI */
496
  breakpoint_create_event (b->number);
497
  return TCL_OK;
498
}
499
 
500
/* This implements the tcl command "gdb_set_bp_addr"
501
 * It sets breakpoints, and notifies the GUI.
502
 *
503
 * Tcl Arguments:
504
 *    addr: the address at which to set the breakpoint
505
 *    type:     the type of the breakpoint
506
 *    thread:   optional thread number
507
 * Tcl Result:
508
 *    The return value of the call to gdbtk_tcl_breakpoint.
509
 */
510
static int
511
gdb_set_bp_addr (ClientData clientData, Tcl_Interp *interp, int objc,
512
                 Tcl_Obj *CONST objv[])
513
 
514
{
515
  struct symtab_and_line sal;
516
  int thread = -1;
517
  long addr;
518
  struct breakpoint *b;
519
  char *typestr, *buf;
520
  enum bpdisp disp;
521
 
522
  if (objc != 3 && objc != 4)
523
    {
524
      Tcl_WrongNumArgs (interp, 1, objv, "address type ?thread?");
525
      return TCL_ERROR;
526
    }
527
 
528
  if (Tcl_GetLongFromObj (interp, objv[1], &addr) == TCL_ERROR)
529
    {
530
      result_ptr->flags = GDBTK_IN_TCL_RESULT;
531
      return TCL_ERROR;
532
    }
533
 
534
  typestr = Tcl_GetStringFromObj (objv[2], NULL);
535
  if (typestr == NULL)
536
    {
537
      result_ptr->flags = GDBTK_IN_TCL_RESULT;
538
      return TCL_ERROR;
539
    }
540
  if (strncmp (typestr, "temp", 4) == 0)
541
    disp = del;
542
  else if (strncmp (typestr, "normal", 6) == 0)
543
    disp = donttouch;
544
  else
545
    {
546
      Tcl_SetStringObj (result_ptr->obj_ptr,
547
                        "type must be \"temp\" or \"normal\"", -1);
548
      return TCL_ERROR;
549
    }
550
 
551
  if (objc == 4)
552
    {
553
      if (Tcl_GetIntFromObj (interp, objv[3], &thread) == TCL_ERROR)
554
        {
555
          result_ptr->flags = GDBTK_IN_TCL_RESULT;
556
          return TCL_ERROR;
557
        }
558
    }
559
 
560
  sal = find_pc_line (addr, 0);
561
  sal.pc = addr;
562
  b = set_raw_breakpoint (sal, bp_breakpoint);
563
  set_breakpoint_count (breakpoint_count + 1);
564
  b->number = breakpoint_count;
565
  b->disposition = disp;
566
  b->thread = thread;
567
 
568
  xasprintf (&buf, "*(0x%lx)", addr);
569
  b->addr_string = xstrdup (buf);
570
 
571
  /* now send notification command back to GUI */
572
  breakpoint_create_event (b->number);
573
  return TCL_OK;
574
}
575
 
576
/*
577
 * This section contains functions that deal with breakpoint
578
 * events from gdb.
579
 */
580
 
581
/* The next three functions use breakpoint_notify to allow the GUI
582
 * to handle creating, deleting and modifying breakpoints.  These three
583
 * functions are put into the appropriate gdb hooks in gdbtk_init.
584
 */
585
 
586
void
587
gdbtk_create_breakpoint (int num)
588
{
589
  struct breakpoint *b;
590
  for (b = breakpoint_chain; b != NULL; b = b->next)
591
    {
592
      if (b->number == num)
593
        break;
594
    }
595
 
596
  if (b == NULL || !BREAKPOINT_IS_INTERESTING (b))
597
    return;
598
 
599
  /* Check if there is room to store it */
600
  if (num >= breakpoint_list_size)
601
    {
602
      int oldsize = breakpoint_list_size;
603
      while (num >= breakpoint_list_size)
604
        breakpoint_list_size += DEFAULT_LIST_SIZE;
605
      breakpoint_list = (struct breakpoint **) xrealloc (breakpoint_list, breakpoint_list_size * sizeof (struct breakpoint *));
606
      memset (&(breakpoint_list[oldsize]), 0, (breakpoint_list_size - oldsize) * sizeof (struct breakpoint *));
607
    }
608
 
609
  breakpoint_list[num] = b;
610
  breakpoint_notify (num, "create");
611
}
612
 
613
void
614
gdbtk_delete_breakpoint (int num)
615
{
616
  if (num >= 0
617
      && num <= breakpoint_list_size
618
      && breakpoint_list[num] != NULL)
619
    {
620
      breakpoint_notify (num, "delete");
621
      breakpoint_list[num] = NULL;
622
    }
623
}
624
 
625
void
626
gdbtk_modify_breakpoint (int num)
627
{
628
  if (num >= 0)
629
    breakpoint_notify (num, "modify");
630
}
631
 
632
/* This is the generic function for handling changes in
633
 * a breakpoint.  It routes the information to the Tcl
634
 * command "gdbtk_tcl_breakpoint" in the form:
635
 *   gdbtk_tcl_breakpoint action b_number b_address b_line b_file
636
 * On error, the error string is written to gdb_stdout.
637
 */
638
static void
639
breakpoint_notify (num, action)
640
     int num;
641
     const char *action;
642
{
643
  char *buf;
644
 
645
  if (num > breakpoint_list_size
646
      || num < 0
647
      || breakpoint_list[num] == NULL
648
      /* FIXME: should not be so restrictive... */
649
      || breakpoint_list[num]->type != bp_breakpoint)
650
    return;
651
 
652
  /* We ensure that ACTION contains no special Tcl characters, so we
653
     can do this.  */
654
  xasprintf (&buf, "gdbtk_tcl_breakpoint %s %d", action, num);
655
 
656
  if (Tcl_Eval (gdbtk_interp, buf) != TCL_OK)
657
    report_error ();
658
  free(buf);
659
}
660
 
661
/*
662
 * This section contains the commands that deal with tracepoints:
663
 */
664
 
665
/* This implements the tcl command gdb_actions
666
 * It sets actions for a given tracepoint.
667
 *
668
 * Tcl Arguments:
669
 *    number: the tracepoint in question
670
 *    actions: the actions to add to this tracepoint
671
 * Tcl Result:
672
 *    None.
673
 */
674
 
675
static int
676
gdb_actions_command (clientData, interp, objc, objv)
677
     ClientData clientData;
678
     Tcl_Interp *interp;
679
     int objc;
680
     Tcl_Obj *CONST objv[];
681
{
682
  struct tracepoint *tp;
683
  Tcl_Obj **actions;
684
  int nactions, i, len;
685
  char *number, *args, *action;
686
  long step_count;
687
  struct action_line *next = NULL, *temp;
688
  enum actionline_type linetype;
689
 
690
  if (objc != 3)
691
    {
692
      Tcl_WrongNumArgs (interp, 1, objv, "number actions");
693
      return TCL_ERROR;
694
    }
695
 
696
  args = number = Tcl_GetStringFromObj (objv[1], NULL);
697
  tp = get_tracepoint_by_number (&args, 0, 0);
698
  if (tp == NULL)
699
    {
700
      Tcl_AppendStringsToObj (result_ptr->obj_ptr, "Tracepoint \"",
701
                              number, "\" does not exist", NULL);
702
      return TCL_ERROR;
703
    }
704
 
705
  /* Free any existing actions */
706
  if (tp->actions != NULL)
707
    free_actions (tp);
708
 
709
  step_count = 0;
710
 
711
  Tcl_ListObjGetElements (interp, objv[2], &nactions, &actions);
712
 
713
  /* Add the actions to the tracepoint */
714
  for (i = 0; i < nactions; i++)
715
    {
716
      temp = xmalloc (sizeof (struct action_line));
717
      temp->next = NULL;
718
      action = Tcl_GetStringFromObj (actions[i], &len);
719
      temp->action = savestring (action, len);
720
 
721
      linetype = validate_actionline (&(temp->action), tp);
722
 
723
      if (linetype == BADLINE)
724
        {
725
          free (temp);
726
          continue;
727
        }
728
 
729
      if (next == NULL)
730
        {
731
          tp->actions = temp;
732
          next = temp;
733
        }
734
      else
735
        {
736
          next->next = temp;
737
          next = temp;
738
        }
739
    }
740
 
741
  return TCL_OK;
742
}
743
 
744
static int
745
gdb_get_trace_frame_num (clientData, interp, objc, objv)
746
     ClientData clientData;
747
     Tcl_Interp *interp;
748
     int objc;
749
     Tcl_Obj *CONST objv[];
750
{
751
  if (objc != 1)
752
    {
753
      Tcl_WrongNumArgs (interp, 1, objv, "linespec");
754
      return TCL_ERROR;
755
    }
756
 
757
  Tcl_SetIntObj (result_ptr->obj_ptr, get_traceframe_number ());
758
  return TCL_OK;
759
 
760
}
761
 
762
static int
763
gdb_get_tracepoint_info (ClientData clientData, Tcl_Interp *interp,
764
                         int objc, Tcl_Obj *CONST objv[])
765
{
766
  struct symtab_and_line sal;
767
  int tpnum;
768
  struct tracepoint *tp;
769
  struct action_line *al;
770
  Tcl_Obj *action_list;
771
  char *filename, *funcname;
772
 
773
  if (objc != 2)
774
    {
775
      Tcl_WrongNumArgs (interp, 1, objv, "tpnum");
776
      return TCL_ERROR;
777
    }
778
 
779
  if (Tcl_GetIntFromObj (NULL, objv[1], &tpnum) != TCL_OK)
780
    {
781
      result_ptr->flags |= GDBTK_IN_TCL_RESULT;
782
      return TCL_ERROR;
783
    }
784
 
785
  ALL_TRACEPOINTS (tp)
786
    if (tp->number == tpnum)
787
    break;
788
 
789
  if (tp == NULL)
790
    {
791
      char *buff;
792
      xasprintf (&buff, "Tracepoint #%d does not exist", tpnum);
793
      Tcl_SetStringObj (result_ptr->obj_ptr, buff, -1);
794
      free(buff);
795
      return TCL_ERROR;
796
    }
797
 
798
  Tcl_SetListObj (result_ptr->obj_ptr, 0, NULL);
799
  sal = find_pc_line (tp->address, 0);
800
  filename = symtab_to_filename (sal.symtab);
801
  if (filename == NULL)
802
    filename = "N/A";
803
  Tcl_ListObjAppendElement (interp, result_ptr->obj_ptr,
804
                            Tcl_NewStringObj (filename, -1));
805
 
806
  funcname = pc_function_name (tp->address);
807
  Tcl_ListObjAppendElement (interp, result_ptr->obj_ptr, Tcl_NewStringObj
808
                            (funcname, -1));
809
 
810
  Tcl_ListObjAppendElement (interp, result_ptr->obj_ptr,
811
                            Tcl_NewIntObj (sal.line));
812
  {
813
    char *tmp;
814
    xasprintf (&tmp, "0x%s", paddr_nz (tp->address));
815
    Tcl_ListObjAppendElement (interp, result_ptr->obj_ptr,
816
                              Tcl_NewStringObj (tmp, -1));
817
    free (tmp);
818
  }
819
  Tcl_ListObjAppendElement (interp, result_ptr->obj_ptr,
820
                            Tcl_NewIntObj (tp->enabled));
821
  Tcl_ListObjAppendElement (interp, result_ptr->obj_ptr,
822
                            Tcl_NewIntObj (tp->pass_count));
823
  Tcl_ListObjAppendElement (interp, result_ptr->obj_ptr,
824
                            Tcl_NewIntObj (tp->step_count));
825
  Tcl_ListObjAppendElement (interp, result_ptr->obj_ptr,
826
                            Tcl_NewIntObj (tp->thread));
827
  Tcl_ListObjAppendElement (interp, result_ptr->obj_ptr,
828
                            Tcl_NewIntObj (tp->hit_count));
829
 
830
  /* Append a list of actions */
831
  action_list = Tcl_NewObj ();
832
  for (al = tp->actions; al != NULL; al = al->next)
833
    {
834
      Tcl_ListObjAppendElement (interp, action_list,
835
                                Tcl_NewStringObj (al->action, -1));
836
    }
837
  Tcl_ListObjAppendElement (interp, result_ptr->obj_ptr, action_list);
838
 
839
  return TCL_OK;
840
}
841
 
842
/* return a list of all tracepoint numbers in interpreter */
843
static int
844
gdb_get_tracepoint_list (clientData, interp, objc, objv)
845
     ClientData clientData;
846
     Tcl_Interp *interp;
847
     int objc;
848
     Tcl_Obj *CONST objv[];
849
{
850
  struct tracepoint *tp;
851
 
852
  Tcl_SetListObj (result_ptr->obj_ptr, 0, NULL);
853
 
854
  ALL_TRACEPOINTS (tp)
855
    Tcl_ListObjAppendElement (interp, result_ptr->obj_ptr,
856
                              Tcl_NewIntObj (tp->number));
857
 
858
  return TCL_OK;
859
}
860
 
861
static int
862
gdb_trace_status (clientData, interp, objc, objv)
863
     ClientData clientData;
864
     Tcl_Interp *interp;
865
     int objc;
866
     Tcl_Obj *CONST objv[];
867
{
868
  int result = 0;
869
 
870
  if (trace_running_p)
871
    result = 1;
872
 
873
  Tcl_SetIntObj (result_ptr->obj_ptr, result);
874
  return TCL_OK;
875
}
876
 
877
/* returns -1 if not found, tracepoint # if found */
878
static int
879
tracepoint_exists (char *args)
880
{
881
  struct tracepoint *tp;
882
  char **canonical;
883
  struct symtabs_and_lines sals;
884
  char *file = NULL;
885
  int result = -1;
886
 
887
  sals = decode_line_1 (&args, 1, NULL, 0, &canonical);
888
  if (sals.nelts == 1)
889
    {
890
      resolve_sal_pc (&sals.sals[0]);
891
      file = xmalloc (strlen (sals.sals[0].symtab->dirname)
892
                      + strlen (sals.sals[0].symtab->filename) + 1);
893
      if (file != NULL)
894
        {
895
          strcpy (file, sals.sals[0].symtab->dirname);
896
          strcat (file, sals.sals[0].symtab->filename);
897
 
898
          ALL_TRACEPOINTS (tp)
899
          {
900
            if (tp->address == sals.sals[0].pc)
901
              result = tp->number;
902
#if 0
903
            /* Why is this here? This messes up assembly traces */
904
            else if (tp->source_file != NULL
905
                     && strcmp (tp->source_file, file) == 0
906
                     && sals.sals[0].line == tp->line_number)
907
              result = tp->number;
908
#endif
909
          }
910
        }
911
    }
912
  if (file != NULL)
913
    free (file);
914
  return result;
915
}
916
 
917
static int
918
gdb_tracepoint_exists_command (clientData, interp, objc, objv)
919
     ClientData clientData;
920
     Tcl_Interp *interp;
921
     int objc;
922
     Tcl_Obj *CONST objv[];
923
{
924
  char *args;
925
 
926
  if (objc != 2)
927
    {
928
      Tcl_WrongNumArgs (interp, 1, objv,
929
                        "function:line|function|line|*addr");
930
      return TCL_ERROR;
931
    }
932
 
933
  args = Tcl_GetStringFromObj (objv[1], NULL);
934
 
935
  Tcl_SetIntObj (result_ptr->obj_ptr, tracepoint_exists (args));
936
  return TCL_OK;
937
}
938
 
939
/*
940
 * This section contains functions which deal with tracepoint
941
 * events from gdb.
942
 */
943
 
944
void
945
gdbtk_create_tracepoint (int num)
946
{
947
  tracepoint_notify (num, "create");
948
}
949
 
950
void
951
gdbtk_delete_tracepoint (int num)
952
{
953
  tracepoint_notify (num, "delete");
954
}
955
 
956
void
957
gdbtk_modify_tracepoint (int num)
958
{
959
  tracepoint_notify (num, "modify");
960
}
961
 
962
static void
963
tracepoint_notify (num, action)
964
     int num;
965
     const char *action;
966
{
967
  char *buf;
968
 
969
  /* We ensure that ACTION contains no special Tcl characters, so we
970
     can do this.  */
971
  xasprintf (&buf, "gdbtk_tcl_tracepoint %s %d", action, num);
972
 
973
  if (Tcl_Eval (gdbtk_interp, buf) != TCL_OK)
974
    report_error ();
975
  free(buf);
976
}

powered by: WebSVN 2.1.0

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