1 /* Tcl/Tk command definitions for Insight - Breakpoints.
2 Copyright (C) 2001, 2002, 2008 Free Software Foundation, Inc.
4 This file is part of GDB.
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.
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.
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., 51 Franklin Street, Fifth Floor,
19 Boston, MA 02110-1301, USA. */
26 #include "breakpoint.h"
27 #include "tracepoint.h"
28 #include "gdb_string.h"
31 #include "gdbtk-cmds.h"
34 /* From breakpoint.c */
35 extern struct breakpoint *breakpoint_chain;
37 /* From gdbtk-hooks.c */
38 extern void report_error (void);
40 /* These two lookup tables are used to translate the type & disposition fields
41 of the breakpoint structure (respectively) into something gdbtk understands.
42 They are also used in gdbtk-hooks.c */
45 {"none", "breakpoint", "hw breakpoint", "until",
46 "finish", "watchpoint", "hw watchpoint",
47 "read watchpoint", "acc watchpoint",
48 "longjmp", "longjmp resume", "step resume",
49 "sigtramp", "watchpoint scope",
50 "call dummy", "shlib events", "catch load",
51 "catch unload", "catch fork", "catch vfork",
52 "catch exec", "catch catch", "catch throw"
55 {"delete", "delstop", "disable", "donttouch"};
57 /* Is this breakpoint interesting to a user interface? */
58 #define BREAKPOINT_IS_INTERESTING(bp) \
59 ((bp)->type == bp_breakpoint \
60 || (bp)->type == bp_hardware_breakpoint \
61 || (bp)->type == bp_watchpoint \
62 || (bp)->type == bp_hardware_watchpoint \
63 || (bp)->type == bp_read_watchpoint \
64 || (bp)->type == bp_access_watchpoint)
66 /* Is this breakpoint a watchpoint? */
67 #define BREAKPOINT_IS_WATCHPOINT(bp) \
68 ((bp)->type == bp_watchpoint \
69 || (bp)->type == bp_hardware_watchpoint \
70 || (bp)->type == bp_read_watchpoint \
71 || (bp)->type == bp_access_watchpoint)
74 * These are routines we need from breakpoint.c.
75 * at some point make these static in breakpoint.c and move GUI code there
78 extern struct breakpoint *set_raw_breakpoint (struct symtab_and_line sal,
80 extern void set_breakpoint_count (int);
81 extern int breakpoint_count;
83 /* Breakpoint/Tracepoint lists. Unfortunately, gdb forces us to
84 keep a list of breakpoints, too. Why couldn't it be done like
86 #define DEFAULT_LIST_SIZE 32
87 static struct breakpoint **breakpoint_list;
88 static int breakpoint_list_size = DEFAULT_LIST_SIZE;
91 * Forward declarations
94 /* Breakpoint-related functions */
95 static int gdb_find_bp_at_addr (ClientData, Tcl_Interp *, int,
96 Tcl_Obj * CONST objv[]);
97 static int gdb_find_bp_at_line (ClientData, Tcl_Interp *, int,
98 Tcl_Obj * CONST objv[]);
99 static int gdb_get_breakpoint_info (ClientData, Tcl_Interp *, int,
101 static int gdb_get_breakpoint_list (ClientData, Tcl_Interp *, int,
103 static int gdb_set_bp (ClientData, Tcl_Interp *, int, Tcl_Obj * CONST objv[]);
104 static int gdb_set_bp_addr (ClientData, Tcl_Interp *, int,
105 Tcl_Obj * CONST objv[]);
107 /* Tracepoint-related functions */
108 static int gdb_actions_command (ClientData, Tcl_Interp *, int,
109 Tcl_Obj * CONST objv[]);
110 static int gdb_get_trace_frame_num (ClientData, Tcl_Interp *, int,
111 Tcl_Obj * CONST objv[]);
112 static int gdb_get_tracepoint_info (ClientData, Tcl_Interp *, int,
113 Tcl_Obj * CONST objv[]);
114 static int gdb_get_tracepoint_list (ClientData, Tcl_Interp *, int,
115 Tcl_Obj * CONST objv[]);
116 static int gdb_trace_status (ClientData, Tcl_Interp *, int,
118 static int gdb_tracepoint_exists_command (ClientData, Tcl_Interp *,
119 int, Tcl_Obj * CONST objv[]);
120 static Tcl_Obj *get_breakpoint_commands (struct command_line *cmd);
122 static int tracepoint_exists (char *args);
124 /* Breakpoint/tracepoint events and related functions */
126 void gdbtk_create_breakpoint (int);
127 void gdbtk_delete_breakpoint (int);
128 void gdbtk_modify_breakpoint (int);
129 void gdbtk_create_tracepoint (int);
130 void gdbtk_delete_tracepoint (int);
131 void gdbtk_modify_tracepoint (int);
132 static void breakpoint_notify (int, const char *);
133 static void tracepoint_notify (int, const char *);
136 Gdbtk_Breakpoint_Init (Tcl_Interp *interp)
138 /* Breakpoint commands */
139 Tcl_CreateObjCommand (interp, "gdb_find_bp_at_addr", gdbtk_call_wrapper,
140 gdb_find_bp_at_addr, NULL);
141 Tcl_CreateObjCommand (interp, "gdb_find_bp_at_line", gdbtk_call_wrapper,
142 gdb_find_bp_at_line, NULL);
143 Tcl_CreateObjCommand (interp, "gdb_get_breakpoint_info", gdbtk_call_wrapper,
144 gdb_get_breakpoint_info, NULL);
145 Tcl_CreateObjCommand (interp, "gdb_get_breakpoint_list", gdbtk_call_wrapper,
146 gdb_get_breakpoint_list, NULL);
147 Tcl_CreateObjCommand (interp, "gdb_set_bp", gdbtk_call_wrapper, gdb_set_bp, NULL);
148 Tcl_CreateObjCommand (interp, "gdb_set_bp_addr", gdbtk_call_wrapper,
149 gdb_set_bp_addr, NULL);
151 /* Tracepoint commands */
152 Tcl_CreateObjCommand (interp, "gdb_actions",
153 gdbtk_call_wrapper, gdb_actions_command, NULL);
154 Tcl_CreateObjCommand (interp, "gdb_get_trace_frame_num",
155 gdbtk_call_wrapper, gdb_get_trace_frame_num, NULL);
156 Tcl_CreateObjCommand (interp, "gdb_get_tracepoint_info",
157 gdbtk_call_wrapper, gdb_get_tracepoint_info, NULL);
158 Tcl_CreateObjCommand (interp, "gdb_get_tracepoint_list",
159 gdbtk_call_wrapper, gdb_get_tracepoint_list, NULL);
160 Tcl_CreateObjCommand (interp, "gdb_is_tracing",
161 gdbtk_call_wrapper, gdb_trace_status, NULL);
162 Tcl_CreateObjCommand (interp, "gdb_tracepoint_exists",
163 gdbtk_call_wrapper, gdb_tracepoint_exists_command, NULL);
165 /* Initialize our tables of BPs. */
166 breakpoint_list = (struct breakpoint **) xmalloc (breakpoint_list_size * sizeof (struct breakpoint *));
167 memset (breakpoint_list, 0, breakpoint_list_size * sizeof (struct breakpoint *));
173 * This section contains commands for manipulation of breakpoints.
176 /* set a breakpoint by source file and line number
177 flags are as follows:
178 least significant 2 bits are disposition, rest is
182 bp_breakpoint, Normal breakpoint
183 bp_hardware_breakpoint, Hardware assisted breakpoint
186 Disposition of breakpoint. Ie: what to do after hitting it.
189 del_at_next_stop, Delete at next stop, whether hit or not
191 donttouch Leave it alone
196 /* This implements the tcl command "gdb_find_bp_at_addr"
201 * It returns a list of breakpoint numbers
204 gdb_find_bp_at_addr (ClientData clientData, Tcl_Interp *interp,
205 int objc, Tcl_Obj *CONST objv[])
213 Tcl_WrongNumArgs (interp, 1, objv, "address");
217 if (Tcl_GetWideIntFromObj (interp, objv[1], &waddr) != TCL_OK)
221 Tcl_SetListObj (result_ptr->obj_ptr, 0, NULL);
222 for (i = 0; i < breakpoint_list_size; i++)
224 if (breakpoint_list[i] != NULL && breakpoint_list[i]->loc != NULL
225 && breakpoint_list[i]->loc->address == addr)
226 Tcl_ListObjAppendElement (NULL, result_ptr->obj_ptr,
233 /* This implements the tcl command "gdb_find_bp_at_line"
236 * filename: the file in which to find the breakpoint
237 * line: the line number for the breakpoint
239 * It returns a list of breakpoint numbers
242 gdb_find_bp_at_line (ClientData clientData, Tcl_Interp *interp,
243 int objc, Tcl_Obj *CONST objv[])
251 Tcl_WrongNumArgs (interp, 1, objv, "filename line");
255 s = lookup_symtab (Tcl_GetStringFromObj (objv[1], NULL));
259 if (Tcl_GetIntFromObj (interp, objv[2], &line) == TCL_ERROR)
261 result_ptr->flags = GDBTK_IN_TCL_RESULT;
265 Tcl_SetListObj (result_ptr->obj_ptr, 0, NULL);
266 for (i = 0; i < breakpoint_list_size; i++)
267 if (breakpoint_list[i] != NULL
268 && breakpoint_list[i]->line_number == line
269 && !strcmp (breakpoint_list[i]->source_file, s->filename))
270 Tcl_ListObjAppendElement (NULL, result_ptr->obj_ptr,
276 /* This implements the tcl command gdb_get_breakpoint_info
281 * A list with {file, function, line_number, address, type, enabled?,
282 * disposition, ignore_count, {list_of_commands},
283 * condition, thread, hit_count user_specification}
286 gdb_get_breakpoint_info (ClientData clientData, Tcl_Interp *interp, int objc,
287 Tcl_Obj *CONST objv[])
289 struct symtab_and_line sal;
291 struct breakpoint *b;
292 char *funcname, *filename;
299 Tcl_WrongNumArgs (interp, 1, objv, "breakpoint");
303 if (Tcl_GetIntFromObj (NULL, objv[1], &bpnum) != TCL_OK)
305 result_ptr->flags = GDBTK_IN_TCL_RESULT;
309 b = (bpnum <= breakpoint_list_size ? breakpoint_list[bpnum] : NULL);
310 if (!b || b->type != bp_breakpoint)
312 gdbtk_set_result (interp, "Breakpoint #%d does not exist.", bpnum);
316 isPending = (b->loc == NULL);
317 Tcl_SetListObj (result_ptr->obj_ptr, 0, NULL);
318 /* Pending breakpoints will display "<PENDING>" as the file name and the
319 user expression into the Function field of the breakpoint view.
320 "0" and "0" in the line number and address field. */
323 Tcl_ListObjAppendElement (NULL, result_ptr->obj_ptr,
324 Tcl_NewStringObj ("<PENDING>", -1));
325 Tcl_ListObjAppendElement (NULL, result_ptr->obj_ptr,
326 Tcl_NewStringObj (b->addr_string, -1));
327 Tcl_ListObjAppendElement (NULL, result_ptr->obj_ptr,
329 Tcl_ListObjAppendElement (NULL, result_ptr->obj_ptr,
334 sal = find_pc_line (b->loc->address, 0);
336 filename = symtab_to_filename (sal.symtab);
337 if (filename == NULL)
339 Tcl_ListObjAppendElement (NULL, result_ptr->obj_ptr,
340 Tcl_NewStringObj (filename, -1));
341 funcname = pc_function_name (b->loc->address);
342 Tcl_ListObjAppendElement (NULL, result_ptr->obj_ptr,
343 Tcl_NewStringObj (funcname, -1));
344 Tcl_ListObjAppendElement (NULL, result_ptr->obj_ptr,
345 Tcl_NewIntObj (b->line_number));
346 Tcl_ListObjAppendElement (NULL, result_ptr->obj_ptr,
347 Tcl_NewStringObj (core_addr_to_string
348 (b->loc->address), -1));
351 Tcl_ListObjAppendElement (NULL, result_ptr->obj_ptr,
352 Tcl_NewStringObj (bptypes[b->type], -1));
353 Tcl_ListObjAppendElement (NULL, result_ptr->obj_ptr,
354 Tcl_NewBooleanObj (b->enable_state == bp_enabled));
355 Tcl_ListObjAppendElement (NULL, result_ptr->obj_ptr,
356 Tcl_NewStringObj (bpdisp[b->disposition], -1));
357 Tcl_ListObjAppendElement (NULL, result_ptr->obj_ptr,
358 Tcl_NewIntObj (b->ignore_count));
360 Tcl_ListObjAppendElement (NULL, result_ptr->obj_ptr,
361 get_breakpoint_commands (b->commands));
363 Tcl_ListObjAppendElement (NULL, result_ptr->obj_ptr,
364 Tcl_NewStringObj (b->cond_string, -1));
366 Tcl_ListObjAppendElement (NULL, result_ptr->obj_ptr,
367 Tcl_NewIntObj (b->thread));
368 Tcl_ListObjAppendElement (NULL, result_ptr->obj_ptr,
369 Tcl_NewIntObj (b->hit_count));
371 Tcl_ListObjAppendElement (NULL, result_ptr->obj_ptr,
372 Tcl_NewStringObj (BREAKPOINT_IS_WATCHPOINT (b)
374 : b->addr_string, -1));
379 /* Helper function for gdb_get_breakpoint_info, this function is
380 responsible for figuring out what to type at the "commands" command
381 in gdb's cli in order to get at the same command list passed here. */
384 get_breakpoint_commands (struct command_line *cmd)
391 switch (cmd->control_type)
394 /* A simple command. Just append it. */
395 Tcl_ListObjAppendElement (NULL, obj,
396 Tcl_NewStringObj (cmd->line, -1));
401 Tcl_ListObjAppendElement (NULL, obj,
402 Tcl_NewStringObj ("loop_break", -1));
405 case continue_control:
406 /* A loop_continue */
407 Tcl_ListObjAppendElement (NULL, obj,
408 Tcl_NewStringObj ("loop_continue", -1));
412 /* A while loop. Must append "end" to the end of it. */
413 tmp = Tcl_NewStringObj ("while ", -1);
414 Tcl_AppendToObj (tmp, cmd->line, -1);
415 Tcl_ListObjAppendElement (NULL, obj, tmp);
416 Tcl_ListObjAppendList (NULL, obj,
417 get_breakpoint_commands (*cmd->body_list));
418 Tcl_ListObjAppendElement (NULL, obj,
419 Tcl_NewStringObj ("end", -1));
423 /* An if statement. cmd->body_list[0] is the true part,
424 cmd->body_list[1] contains the "else" (false) part. */
425 tmp = Tcl_NewStringObj ("if ", -1);
426 Tcl_AppendToObj (tmp, cmd->line, -1);
427 Tcl_ListObjAppendElement (NULL, obj, tmp);
428 Tcl_ListObjAppendList (NULL, obj,
429 get_breakpoint_commands (cmd->body_list[0]));
430 if (cmd->body_count == 2)
432 Tcl_ListObjAppendElement (NULL, obj,
433 Tcl_NewStringObj ("else", -1));
434 Tcl_ListObjAppendList (NULL, obj,
435 get_breakpoint_commands(cmd->body_list[1]));
437 Tcl_ListObjAppendElement (NULL, obj,
438 Tcl_NewStringObj ("end", -1));
441 case invalid_control:
442 /* Something invalid. Just skip it. */
452 /* This implements the tcl command gdb_get_breakpoint_list
453 * It builds up a list of the current breakpoints.
458 * A list of breakpoint numbers.
461 gdb_get_breakpoint_list (ClientData clientData, Tcl_Interp *interp,
462 int objc, Tcl_Obj *CONST objv[])
469 Tcl_WrongNumArgs (interp, 1, objv, NULL);
473 for (i = 0; i < breakpoint_list_size; i++)
475 if (breakpoint_list[i] != NULL
476 && breakpoint_list[i]->type == bp_breakpoint)
478 new_obj = Tcl_NewIntObj (i);
479 Tcl_ListObjAppendElement (NULL, result_ptr->obj_ptr, new_obj);
486 /* This implements the tcl command "gdb_set_bp"
487 * It sets breakpoints, and notifies the GUI.
490 * filename: the file in which to set the breakpoint
491 * line: the line number for the breakpoint
492 * type: the type of the breakpoint
493 * thread: optional thread number
495 * The return value of the call to gdbtk_tcl_breakpoint.
498 gdb_set_bp (ClientData clientData, Tcl_Interp *interp,
499 int objc, Tcl_Obj *CONST objv[])
501 struct symtab_and_line sal;
502 int line, thread = -1;
503 struct breakpoint *b;
507 if (objc != 4 && objc != 5)
509 Tcl_WrongNumArgs (interp, 1, objv, "filename line type ?thread?");
513 sal.symtab = lookup_symtab (Tcl_GetStringFromObj (objv[1], NULL));
514 if (sal.symtab == NULL)
517 if (Tcl_GetIntFromObj (interp, objv[2], &line) == TCL_ERROR)
519 result_ptr->flags = GDBTK_IN_TCL_RESULT;
523 typestr = Tcl_GetStringFromObj (objv[3], NULL);
524 if (strncmp (typestr, "temp", 4) == 0)
526 else if (strncmp (typestr, "normal", 6) == 0)
527 disp = disp_donttouch;
530 gdbtk_set_result (interp, "type must be \"temp\" or \"normal\"");
536 if (Tcl_GetIntFromObj (interp, objv[4], &thread) == TCL_ERROR)
538 result_ptr->flags = GDBTK_IN_TCL_RESULT;
544 if (!find_line_pc (sal.symtab, sal.line, &sal.pc))
547 sal.section = find_pc_overlay (sal.pc);
548 b = set_raw_breakpoint (sal, bp_breakpoint);
549 set_breakpoint_count (breakpoint_count + 1);
550 b->number = breakpoint_count;
551 b->disposition = disp;
554 /* FIXME: this won't work for duplicate basenames! */
555 buf = xstrprintf ("%s:%d", lbasename (Tcl_GetStringFromObj (objv[1], NULL)),
557 b->addr_string = xstrdup (buf);
560 /* now send notification command back to GUI */
561 observer_notify_breakpoint_created (b->number);
565 /* This implements the tcl command "gdb_set_bp_addr"
566 * It sets breakpoints, and notifies the GUI.
569 * addr: the CORE_ADDR at which to set the breakpoint
570 * type: the type of the breakpoint
571 * thread: optional thread number
573 * The return value of the call to gdbtk_tcl_breakpoint.
576 gdb_set_bp_addr (ClientData clientData, Tcl_Interp *interp, int objc,
577 Tcl_Obj *CONST objv[])
580 struct symtab_and_line sal;
584 struct breakpoint *b;
585 char *saddr, *typestr;
588 if (objc != 3 && objc != 4)
590 Tcl_WrongNumArgs (interp, 1, objv, "address type ?thread?");
594 if (Tcl_GetWideIntFromObj (interp, objv[1], &waddr) != TCL_OK)
597 saddr = Tcl_GetStringFromObj (objv[1], NULL);
599 typestr = Tcl_GetStringFromObj (objv[2], NULL);
600 if (strncmp (typestr, "temp", 4) == 0)
602 else if (strncmp (typestr, "normal", 6) == 0)
603 disp = disp_donttouch;
606 gdbtk_set_result (interp, "type must be \"temp\" or \"normal\"");
612 if (Tcl_GetIntFromObj (interp, objv[3], &thread) == TCL_ERROR)
614 result_ptr->flags = GDBTK_IN_TCL_RESULT;
619 sal = find_pc_line (addr, 0);
621 b = set_raw_breakpoint (sal, bp_breakpoint);
622 set_breakpoint_count (breakpoint_count + 1);
623 b->number = breakpoint_count;
624 b->disposition = disp;
626 b->addr_string = xstrdup (saddr);
628 /* now send notification command back to GUI */
629 observer_notify_breakpoint_created (b->number);
634 * This section contains functions that deal with breakpoint
638 /* The next three functions use breakpoint_notify to allow the GUI
639 * to handle creating, deleting and modifying breakpoints. These three
640 * functions are put into the appropriate gdb hooks in gdbtk_init.
644 gdbtk_create_breakpoint (int num)
646 struct breakpoint *b;
647 for (b = breakpoint_chain; b != NULL; b = b->next)
649 if (b->number == num)
653 if (b == NULL || !BREAKPOINT_IS_INTERESTING (b))
656 /* Check if there is room to store it */
657 if (num >= breakpoint_list_size)
659 int oldsize = breakpoint_list_size;
660 while (num >= breakpoint_list_size)
661 breakpoint_list_size += DEFAULT_LIST_SIZE;
662 breakpoint_list = (struct breakpoint **) xrealloc (breakpoint_list, breakpoint_list_size * sizeof (struct breakpoint *));
663 memset (&(breakpoint_list[oldsize]), 0, (breakpoint_list_size - oldsize) * sizeof (struct breakpoint *));
666 breakpoint_list[num] = b;
667 breakpoint_notify (num, "create");
671 gdbtk_delete_breakpoint (int num)
674 && num <= breakpoint_list_size
675 && breakpoint_list[num] != NULL)
677 breakpoint_notify (num, "delete");
678 breakpoint_list[num] = NULL;
683 gdbtk_modify_breakpoint (int num)
686 breakpoint_notify (num, "modify");
689 /* This is the generic function for handling changes in
690 * a breakpoint. It routes the information to the Tcl
691 * command "gdbtk_tcl_breakpoint" in the form:
692 * gdbtk_tcl_breakpoint action b_number b_address b_line b_file
693 * On error, the error string is written to gdb_stdout.
696 breakpoint_notify (int num, const char *action)
700 if (num > breakpoint_list_size
702 || breakpoint_list[num] == NULL
703 /* FIXME: should not be so restrictive... */
704 || breakpoint_list[num]->type != bp_breakpoint)
707 /* We ensure that ACTION contains no special Tcl characters, so we
709 buf = xstrprintf ("gdbtk_tcl_breakpoint %s %d", action, num);
711 if (Tcl_Eval (gdbtk_interp, buf) != TCL_OK)
717 * This section contains the commands that deal with tracepoints:
720 /* This implements the tcl command gdb_actions
721 * It sets actions for a given tracepoint.
724 * number: the tracepoint in question
725 * actions: the actions to add to this tracepoint
731 gdb_actions_command (ClientData clientData, Tcl_Interp *interp,
732 int objc, Tcl_Obj *CONST objv[])
734 struct breakpoint *tp;
736 int nactions, i, len;
737 char *number, *args, *action;
739 struct action_line *next = NULL, *temp;
740 enum actionline_type linetype;
744 Tcl_WrongNumArgs (interp, 1, objv, "number actions");
748 args = number = Tcl_GetStringFromObj (objv[1], NULL);
749 tp = get_tracepoint_by_number (&args, 0, 0);
752 Tcl_AppendStringsToObj (result_ptr->obj_ptr, "Tracepoint \"",
753 number, "\" does not exist", NULL);
757 /* Free any existing actions */
758 if (tp->actions != NULL)
763 Tcl_ListObjGetElements (interp, objv[2], &nactions, &actions);
765 /* Add the actions to the tracepoint */
766 for (i = 0; i < nactions; i++)
768 temp = xmalloc (sizeof (struct action_line));
770 action = Tcl_GetStringFromObj (actions[i], &len);
771 temp->action = savestring (action, len);
773 linetype = validate_actionline (&(temp->action), tp);
775 if (linetype == BADLINE)
797 gdb_get_trace_frame_num (ClientData clientData, Tcl_Interp *interp,
798 int objc, Tcl_Obj *CONST objv[])
802 Tcl_WrongNumArgs (interp, 1, objv, "linespec");
806 Tcl_SetIntObj (result_ptr->obj_ptr, get_traceframe_number ());
812 gdb_get_tracepoint_info (ClientData clientData, Tcl_Interp *interp,
813 int objc, Tcl_Obj *CONST objv[])
815 struct symtab_and_line sal;
817 struct breakpoint *tp;
818 struct action_line *al;
819 Tcl_Obj *action_list;
820 char *filename, *funcname;
824 Tcl_WrongNumArgs (interp, 1, objv, "tpnum");
828 if (Tcl_GetIntFromObj (NULL, objv[1], &tpnum) != TCL_OK)
830 result_ptr->flags |= GDBTK_IN_TCL_RESULT;
834 tp = get_tracepoint (tpnum);
838 gdbtk_set_result (interp, "Tracepoint #%d does not exist", tpnum);
842 Tcl_SetListObj (result_ptr->obj_ptr, 0, NULL);
843 sal = find_pc_line (tp->loc->address, 0);
844 filename = symtab_to_filename (sal.symtab);
845 if (filename == NULL)
847 Tcl_ListObjAppendElement (interp, result_ptr->obj_ptr,
848 Tcl_NewStringObj (filename, -1));
850 funcname = pc_function_name (tp->loc->address);
851 Tcl_ListObjAppendElement (interp, result_ptr->obj_ptr, Tcl_NewStringObj
854 Tcl_ListObjAppendElement (interp, result_ptr->obj_ptr,
855 Tcl_NewIntObj (sal.line));
856 Tcl_ListObjAppendElement (interp, result_ptr->obj_ptr,
857 Tcl_NewStringObj (core_addr_to_string (tp->loc->address), -1));
858 Tcl_ListObjAppendElement (interp, result_ptr->obj_ptr,
859 Tcl_NewIntObj (tp->enable_state == bp_enabled));
860 Tcl_ListObjAppendElement (interp, result_ptr->obj_ptr,
861 Tcl_NewIntObj (tp->pass_count));
862 Tcl_ListObjAppendElement (interp, result_ptr->obj_ptr,
863 Tcl_NewIntObj (tp->step_count));
864 Tcl_ListObjAppendElement (interp, result_ptr->obj_ptr,
865 Tcl_NewIntObj (tp->thread));
866 Tcl_ListObjAppendElement (interp, result_ptr->obj_ptr,
867 Tcl_NewIntObj (tp->hit_count));
869 /* Append a list of actions */
870 action_list = Tcl_NewObj ();
871 for (al = tp->actions; al != NULL; al = al->next)
873 Tcl_ListObjAppendElement (interp, action_list,
874 Tcl_NewStringObj (al->action, -1));
876 Tcl_ListObjAppendElement (interp, result_ptr->obj_ptr, action_list);
881 /* return a list of all tracepoint numbers in interpreter */
883 gdb_get_tracepoint_list (ClientData clientData,
886 Tcl_Obj *CONST objv[])
888 VEC(breakpoint_p) *tp_vec = NULL;
890 struct breakpoint *tp;
892 Tcl_SetListObj (result_ptr->obj_ptr, 0, NULL);
894 tp_vec = all_tracepoints ();
895 for (ix = 0; VEC_iterate (breakpoint_p, tp_vec, ix, tp); ix++)
896 Tcl_ListObjAppendElement (interp, result_ptr->obj_ptr,
897 Tcl_NewIntObj (tp->number));
898 VEC_free (breakpoint_p, tp_vec);
904 gdb_trace_status (ClientData clientData,
907 Tcl_Obj *CONST objv[])
914 Tcl_SetIntObj (result_ptr->obj_ptr, result);
918 /* returns -1 if not found, tracepoint # if found */
920 tracepoint_exists (char *args)
922 VEC(breakpoint_p) *tp_vec = NULL;
924 struct breakpoint *tp;
926 struct symtabs_and_lines sals;
930 sals = decode_line_1 (&args, 1, NULL, 0, &canonical, NULL);
933 resolve_sal_pc (&sals.sals[0]);
934 file = xmalloc (strlen (sals.sals[0].symtab->dirname)
935 + strlen (sals.sals[0].symtab->filename) + 1);
938 strcpy (file, sals.sals[0].symtab->dirname);
939 strcat (file, sals.sals[0].symtab->filename);
941 tp_vec = all_tracepoints ();
942 for (ix = 0; VEC_iterate (breakpoint_p, tp_vec, ix, tp); ix++)
944 if (tp->loc && tp->loc->address == sals.sals[0].pc)
947 /* Why is this here? This messes up assembly traces */
948 else if (tp->source_file != NULL
949 && strcmp (tp->source_file, file) == 0
950 && sals.sals[0].line == tp->line_number)
954 VEC_free (breakpoint_p, tp_vec);
963 gdb_tracepoint_exists_command (ClientData clientData,
966 Tcl_Obj *CONST objv[])
972 Tcl_WrongNumArgs (interp, 1, objv,
973 "function:line|function|line|*addr");
977 args = Tcl_GetStringFromObj (objv[1], NULL);
979 Tcl_SetIntObj (result_ptr->obj_ptr, tracepoint_exists (args));
984 * This section contains functions which deal with tracepoint
989 gdbtk_create_tracepoint (int num)
991 tracepoint_notify (num, "create");
995 gdbtk_delete_tracepoint (int num)
997 tracepoint_notify (num, "delete");
1001 gdbtk_modify_tracepoint (int num)
1003 tracepoint_notify (num, "modify");
1007 tracepoint_notify (int num, const char *action)
1011 /* We ensure that ACTION contains no special Tcl characters, so we
1013 buf = xstrprintf ("gdbtk_tcl_tracepoint %s %d", action, num);
1015 if (Tcl_Eval (gdbtk_interp, buf) != TCL_OK)