diff options
Diffstat (limited to 'gdb/gdbtk/generic/gdbtk-bp.c')
-rw-r--r-- | gdb/gdbtk/generic/gdbtk-bp.c | 992 |
1 files changed, 0 insertions, 992 deletions
diff --git a/gdb/gdbtk/generic/gdbtk-bp.c b/gdb/gdbtk/generic/gdbtk-bp.c deleted file mode 100644 index a40a21997c3..00000000000 --- a/gdb/gdbtk/generic/gdbtk-bp.c +++ /dev/null @@ -1,992 +0,0 @@ -/* Tcl/Tk command definitions for Insight - Breakpoints. - Copyright 2001, 2002 Free Software Foundation, Inc. - - This file is part of GDB. - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. */ - -#include "defs.h" -#include "symtab.h" -#include "symfile.h" -#include "linespec.h" -#include "breakpoint.h" -#include "tracepoint.h" -#include "gdb_string.h" -#include <tcl.h> -#include "gdbtk.h" -#include "gdbtk-cmds.h" - -/* From breakpoint.c */ -extern struct breakpoint *breakpoint_chain; - -/* From gdbtk-hooks.c */ -extern void report_error (void); - -/* These two lookup tables are used to translate the type & disposition fields - of the breakpoint structure (respectively) into something gdbtk understands. - They are also used in gdbtk-hooks.c */ - -char *bptypes[] = - {"none", "breakpoint", "hw breakpoint", "until", - "finish", "watchpoint", "hw watchpoint", - "read watchpoint", "acc watchpoint", - "longjmp", "longjmp resume", "step resume", - "sigtramp", "watchpoint scope", - "call dummy", "shlib events", "catch load", - "catch unload", "catch fork", "catch vfork", - "catch exec", "catch catch", "catch throw" - }; -char *bpdisp[] = - {"delete", "delstop", "disable", "donttouch"}; - -/* Is this breakpoint interesting to a user interface? */ -#define BREAKPOINT_IS_INTERESTING(bp) \ -((bp)->type == bp_breakpoint \ - || (bp)->type == bp_hardware_breakpoint \ - || (bp)->type == bp_watchpoint \ - || (bp)->type == bp_hardware_watchpoint \ - || (bp)->type == bp_read_watchpoint \ - || (bp)->type == bp_access_watchpoint) - -/* Is this breakpoint a watchpoint? */ -#define BREAKPOINT_IS_WATCHPOINT(bp) \ -((bp)->type == bp_watchpoint \ - || (bp)->type == bp_hardware_watchpoint \ - || (bp)->type == bp_read_watchpoint \ - || (bp)->type == bp_access_watchpoint) - -/* - * These are routines we need from breakpoint.c. - * at some point make these static in breakpoint.c and move GUI code there - */ - -extern struct breakpoint *set_raw_breakpoint (struct symtab_and_line sal, - enum bptype bp_type); -extern void set_breakpoint_count (int); -extern int breakpoint_count; - -/* Breakpoint/Tracepoint lists. Unfortunately, gdb forces us to - keep a list of breakpoints, too. Why couldn't it be done like - treacepoints? */ -#define DEFAULT_LIST_SIZE 32 -static struct breakpoint **breakpoint_list; -static int breakpoint_list_size = DEFAULT_LIST_SIZE; - -/* - * Forward declarations - */ - -/* Breakpoint-related functions */ -static int gdb_find_bp_at_addr (ClientData, Tcl_Interp *, int, - Tcl_Obj * CONST objv[]); -static int gdb_find_bp_at_line (ClientData, Tcl_Interp *, int, - Tcl_Obj * CONST objv[]); -static int gdb_get_breakpoint_info (ClientData, Tcl_Interp *, int, - Tcl_Obj * CONST[]); -static int gdb_get_breakpoint_list (ClientData, Tcl_Interp *, int, - Tcl_Obj * CONST[]); -static int gdb_set_bp (ClientData, Tcl_Interp *, int, Tcl_Obj * CONST objv[]); -static int gdb_set_bp_addr (ClientData, Tcl_Interp *, int, - Tcl_Obj * CONST objv[]); - -/* Tracepoint-related functions */ -static int gdb_actions_command (ClientData, Tcl_Interp *, int, - Tcl_Obj * CONST objv[]); -static int gdb_get_trace_frame_num (ClientData, Tcl_Interp *, int, - Tcl_Obj * CONST objv[]); -static int gdb_get_tracepoint_info (ClientData, Tcl_Interp *, int, - Tcl_Obj * CONST objv[]); -static int gdb_get_tracepoint_list (ClientData, Tcl_Interp *, int, - Tcl_Obj * CONST objv[]); -static int gdb_trace_status (ClientData, Tcl_Interp *, int, - Tcl_Obj * CONST[]); -static int gdb_tracepoint_exists_command (ClientData, Tcl_Interp *, - int, Tcl_Obj * CONST objv[]); -static Tcl_Obj *get_breakpoint_commands (struct command_line *cmd); - -static int tracepoint_exists (char *args); - -/* Breakpoint/tracepoint events and related functions */ - -void gdbtk_create_breakpoint (int); -void gdbtk_delete_breakpoint (int); -void gdbtk_modify_breakpoint (int); -void gdbtk_create_tracepoint (int); -void gdbtk_delete_tracepoint (int); -void gdbtk_modify_tracepoint (int); -static void breakpoint_notify (int, const char *); -static void tracepoint_notify (int, const char *); - -int -Gdbtk_Breakpoint_Init (Tcl_Interp *interp) -{ - /* Breakpoint commands */ - Tcl_CreateObjCommand (interp, "gdb_find_bp_at_addr", gdbtk_call_wrapper, - gdb_find_bp_at_addr, NULL); - Tcl_CreateObjCommand (interp, "gdb_find_bp_at_line", gdbtk_call_wrapper, - gdb_find_bp_at_line, NULL); - Tcl_CreateObjCommand (interp, "gdb_get_breakpoint_info", gdbtk_call_wrapper, - gdb_get_breakpoint_info, NULL); - Tcl_CreateObjCommand (interp, "gdb_get_breakpoint_list", gdbtk_call_wrapper, - gdb_get_breakpoint_list, NULL); - Tcl_CreateObjCommand (interp, "gdb_set_bp", gdbtk_call_wrapper, gdb_set_bp, NULL); - Tcl_CreateObjCommand (interp, "gdb_set_bp_addr", gdbtk_call_wrapper, - gdb_set_bp_addr, NULL); - - /* Tracepoint commands */ - Tcl_CreateObjCommand (interp, "gdb_actions", - gdbtk_call_wrapper, gdb_actions_command, NULL); - Tcl_CreateObjCommand (interp, "gdb_get_trace_frame_num", - gdbtk_call_wrapper, gdb_get_trace_frame_num, NULL); - Tcl_CreateObjCommand (interp, "gdb_get_tracepoint_info", - gdbtk_call_wrapper, gdb_get_tracepoint_info, NULL); - Tcl_CreateObjCommand (interp, "gdb_get_tracepoint_list", - gdbtk_call_wrapper, gdb_get_tracepoint_list, NULL); - Tcl_CreateObjCommand (interp, "gdb_is_tracing", - gdbtk_call_wrapper, gdb_trace_status, NULL); - Tcl_CreateObjCommand (interp, "gdb_tracepoint_exists", - gdbtk_call_wrapper, gdb_tracepoint_exists_command, NULL); - - /* Initialize our tables of BPs. */ - breakpoint_list = (struct breakpoint **) xmalloc (breakpoint_list_size * sizeof (struct breakpoint *)); - memset (breakpoint_list, 0, breakpoint_list_size * sizeof (struct breakpoint *)); - - return TCL_OK; -} - -/* - * This section contains commands for manipulation of breakpoints. - */ - -/* set a breakpoint by source file and line number - flags are as follows: - least significant 2 bits are disposition, rest is - type (normally 0). - - enum bptype { - bp_breakpoint, Normal breakpoint - bp_hardware_breakpoint, Hardware assisted breakpoint - } - - Disposition of breakpoint. Ie: what to do after hitting it. - enum bpdisp { - del, Delete it - del_at_next_stop, Delete at next stop, whether hit or not - disable, Disable it - donttouch Leave it alone - }; -*/ - - -/* This implements the tcl command "gdb_find_bp_at_addr" - -* Tcl Arguments: -* addr: CORE_ADDR -* Tcl Result: -* It returns a list of breakpoint numbers -*/ -static int -gdb_find_bp_at_addr (ClientData clientData, Tcl_Interp *interp, - int objc, Tcl_Obj *CONST objv[]) -{ - int i; - CORE_ADDR addr; - Tcl_WideInt waddr; - - if (objc != 2) - { - Tcl_WrongNumArgs (interp, 1, objv, "address"); - return TCL_ERROR; - } - - if (Tcl_GetWideIntFromObj (interp, objv[1], &waddr) != TCL_OK) - return TCL_ERROR; - addr = waddr; - - Tcl_SetListObj (result_ptr->obj_ptr, 0, NULL); - for (i = 0; i < breakpoint_list_size; i++) - { - if (breakpoint_list[i] != NULL - && breakpoint_list[i]->address == addr) - Tcl_ListObjAppendElement (NULL, result_ptr->obj_ptr, - Tcl_NewIntObj (i)); - } - - return TCL_OK; -} - -/* This implements the tcl command "gdb_find_bp_at_line" - -* Tcl Arguments: -* filename: the file in which to find the breakpoint -* line: the line number for the breakpoint -* Tcl Result: -* It returns a list of breakpoint numbers -*/ -static int -gdb_find_bp_at_line (ClientData clientData, Tcl_Interp *interp, - int objc, Tcl_Obj *CONST objv[]) - -{ - struct symtab *s; - int i, line; - - if (objc != 3) - { - Tcl_WrongNumArgs (interp, 1, objv, "filename line"); - return TCL_ERROR; - } - - s = lookup_symtab (Tcl_GetStringFromObj (objv[1], NULL)); - if (s == NULL) - return TCL_ERROR; - - if (Tcl_GetIntFromObj (interp, objv[2], &line) == TCL_ERROR) - { - result_ptr->flags = GDBTK_IN_TCL_RESULT; - return TCL_ERROR; - } - - Tcl_SetListObj (result_ptr->obj_ptr, 0, NULL); - for (i = 0; i < breakpoint_list_size; i++) - if (breakpoint_list[i] != NULL - && breakpoint_list[i]->line_number == line - && !strcmp (breakpoint_list[i]->source_file, s->filename)) - Tcl_ListObjAppendElement (NULL, result_ptr->obj_ptr, - Tcl_NewIntObj (i)); - - return TCL_OK; -} - -/* This implements the tcl command gdb_get_breakpoint_info - * - * Tcl Arguments: - * breakpoint_number - * Tcl Result: - * A list with {file, function, line_number, address, type, enabled?, - * disposition, ignore_count, {list_of_commands}, - * condition, thread, hit_count user_specification} - */ -static int -gdb_get_breakpoint_info (ClientData clientData, Tcl_Interp *interp, int objc, - Tcl_Obj *CONST objv[]) -{ - struct symtab_and_line sal; - int bpnum; - struct breakpoint *b; - char *funcname, *filename; - - Tcl_Obj *new_obj; - - if (objc != 2) - { - Tcl_WrongNumArgs (interp, 1, objv, "breakpoint"); - return TCL_ERROR; - } - - if (Tcl_GetIntFromObj (NULL, objv[1], &bpnum) != TCL_OK) - { - result_ptr->flags = GDBTK_IN_TCL_RESULT; - return TCL_ERROR; - } - - b = (bpnum <= breakpoint_list_size ? breakpoint_list[bpnum] : NULL); - if (!b || b->type != bp_breakpoint) - { - gdbtk_set_result (interp, "Breakpoint #%d does not exist.", bpnum); - return TCL_ERROR; - } - - sal = find_pc_line (b->address, 0); - - filename = symtab_to_filename (sal.symtab); - if (filename == NULL) - filename = ""; - - Tcl_SetListObj (result_ptr->obj_ptr, 0, NULL); - Tcl_ListObjAppendElement (NULL, result_ptr->obj_ptr, - Tcl_NewStringObj (filename, -1)); - - funcname = pc_function_name (b->address); - new_obj = Tcl_NewStringObj (funcname, -1); - Tcl_ListObjAppendElement (NULL, result_ptr->obj_ptr, new_obj); - - Tcl_ListObjAppendElement (NULL, result_ptr->obj_ptr, - Tcl_NewIntObj (b->line_number)); - Tcl_ListObjAppendElement (NULL, result_ptr->obj_ptr, - Tcl_NewStringObj (core_addr_to_string (b->address), -1)); - Tcl_ListObjAppendElement (NULL, result_ptr->obj_ptr, - Tcl_NewStringObj (bptypes[b->type], -1)); - Tcl_ListObjAppendElement (NULL, result_ptr->obj_ptr, - Tcl_NewBooleanObj (b->enable_state == bp_enabled)); - Tcl_ListObjAppendElement (NULL, result_ptr->obj_ptr, - Tcl_NewStringObj (bpdisp[b->disposition], -1)); - Tcl_ListObjAppendElement (NULL, result_ptr->obj_ptr, - Tcl_NewIntObj (b->ignore_count)); - - Tcl_ListObjAppendElement (NULL, result_ptr->obj_ptr, - get_breakpoint_commands (b->commands)); - - Tcl_ListObjAppendElement (NULL, result_ptr->obj_ptr, - Tcl_NewStringObj (b->cond_string, -1)); - - Tcl_ListObjAppendElement (NULL, result_ptr->obj_ptr, - Tcl_NewIntObj (b->thread)); - Tcl_ListObjAppendElement (NULL, result_ptr->obj_ptr, - Tcl_NewIntObj (b->hit_count)); - - Tcl_ListObjAppendElement (NULL, result_ptr->obj_ptr, - Tcl_NewStringObj (BREAKPOINT_IS_WATCHPOINT (b) - ? b->exp_string - : b->addr_string, -1)); - - return TCL_OK; -} - -/* Helper function for gdb_get_breakpoint_info, this function is - responsible for figuring out what to type at the "commands" command - in gdb's cli in order to get at the same command list passed here. */ - -static Tcl_Obj * -get_breakpoint_commands (struct command_line *cmd) -{ - Tcl_Obj *obj, *tmp; - - obj = Tcl_NewObj (); - while (cmd != NULL) - { - switch (cmd->control_type) - { - case simple_control: - /* A simple command. Just append it. */ - Tcl_ListObjAppendElement (NULL, obj, - Tcl_NewStringObj (cmd->line, -1)); - break; - - case break_control: - /* A loop_break */ - Tcl_ListObjAppendElement (NULL, obj, - Tcl_NewStringObj ("loop_break", -1)); - break; - - case continue_control: - /* A loop_continue */ - Tcl_ListObjAppendElement (NULL, obj, - Tcl_NewStringObj ("loop_continue", -1)); - break; - - case while_control: - /* A while loop. Must append "end" to the end of it. */ - tmp = Tcl_NewStringObj ("while ", -1); - Tcl_AppendToObj (tmp, cmd->line, -1); - Tcl_ListObjAppendElement (NULL, obj, tmp); - Tcl_ListObjAppendList (NULL, obj, - get_breakpoint_commands (*cmd->body_list)); - Tcl_ListObjAppendElement (NULL, obj, - Tcl_NewStringObj ("end", -1)); - break; - - case if_control: - /* An if statement. cmd->body_list[0] is the true part, - cmd->body_list[1] contains the "else" (false) part. */ - tmp = Tcl_NewStringObj ("if ", -1); - Tcl_AppendToObj (tmp, cmd->line, -1); - Tcl_ListObjAppendElement (NULL, obj, tmp); - Tcl_ListObjAppendList (NULL, obj, - get_breakpoint_commands (cmd->body_list[0])); - if (cmd->body_count == 2) - { - Tcl_ListObjAppendElement (NULL, obj, - Tcl_NewStringObj ("else", -1)); - Tcl_ListObjAppendList (NULL, obj, - get_breakpoint_commands(cmd->body_list[1])); - } - Tcl_ListObjAppendElement (NULL, obj, - Tcl_NewStringObj ("end", -1)); - break; - - case invalid_control: - /* Something invalid. Just skip it. */ - break; - } - - cmd = cmd->next; - } - - return obj; -} - -/* This implements the tcl command gdb_get_breakpoint_list - * It builds up a list of the current breakpoints. - * - * Tcl Arguments: - * None. - * Tcl Result: - * A list of breakpoint numbers. - */ -static int -gdb_get_breakpoint_list (ClientData clientData, Tcl_Interp *interp, - int objc, Tcl_Obj *CONST objv[]) -{ - int i; - Tcl_Obj *new_obj; - - if (objc != 1) - { - Tcl_WrongNumArgs (interp, 1, objv, NULL); - return TCL_ERROR; - } - - for (i = 0; i < breakpoint_list_size; i++) - { - if (breakpoint_list[i] != NULL - && breakpoint_list[i]->type == bp_breakpoint) - { - new_obj = Tcl_NewIntObj (i); - Tcl_ListObjAppendElement (NULL, result_ptr->obj_ptr, new_obj); - } - } - - return TCL_OK; -} - -/* This implements the tcl command "gdb_set_bp" - * It sets breakpoints, and notifies the GUI. - * - * Tcl Arguments: - * filename: the file in which to set the breakpoint - * line: the line number for the breakpoint - * type: the type of the breakpoint - * thread: optional thread number - * Tcl Result: - * The return value of the call to gdbtk_tcl_breakpoint. - */ -static int -gdb_set_bp (ClientData clientData, Tcl_Interp *interp, - int objc, Tcl_Obj *CONST objv[]) -{ - struct symtab_and_line sal; - int line, thread = -1; - struct breakpoint *b; - char *buf, *typestr; - enum bpdisp disp; - - if (objc != 4 && objc != 5) - { - Tcl_WrongNumArgs (interp, 1, objv, "filename line type ?thread?"); - return TCL_ERROR; - } - - sal.symtab = lookup_symtab (Tcl_GetStringFromObj (objv[1], NULL)); - if (sal.symtab == NULL) - return TCL_ERROR; - - if (Tcl_GetIntFromObj (interp, objv[2], &line) == TCL_ERROR) - { - result_ptr->flags = GDBTK_IN_TCL_RESULT; - return TCL_ERROR; - } - - typestr = Tcl_GetStringFromObj (objv[3], NULL); - if (strncmp (typestr, "temp", 4) == 0) - disp = disp_del; - else if (strncmp (typestr, "normal", 6) == 0) - disp = disp_donttouch; - else - { - gdbtk_set_result (interp, "type must be \"temp\" or \"normal\""); - return TCL_ERROR; - } - - if (objc == 5) - { - if (Tcl_GetIntFromObj (interp, objv[4], &thread) == TCL_ERROR) - { - result_ptr->flags = GDBTK_IN_TCL_RESULT; - return TCL_ERROR; - } - } - - sal.line = line; - if (!find_line_pc (sal.symtab, sal.line, &sal.pc)) - return TCL_ERROR; - - sal.section = find_pc_overlay (sal.pc); - b = set_raw_breakpoint (sal, bp_breakpoint); - set_breakpoint_count (breakpoint_count + 1); - b->number = breakpoint_count; - b->disposition = disp; - b->thread = thread; - - /* FIXME: this won't work for duplicate basenames! */ - xasprintf (&buf, "%s:%d", basename (Tcl_GetStringFromObj (objv[1], NULL)), - line); - b->addr_string = xstrdup (buf); - free(buf); - - /* now send notification command back to GUI */ - breakpoint_create_event (b->number); - return TCL_OK; -} - -/* This implements the tcl command "gdb_set_bp_addr" - * It sets breakpoints, and notifies the GUI. - * - * Tcl Arguments: - * addr: the CORE_ADDR at which to set the breakpoint - * type: the type of the breakpoint - * thread: optional thread number - * Tcl Result: - * The return value of the call to gdbtk_tcl_breakpoint. - */ -static int -gdb_set_bp_addr (ClientData clientData, Tcl_Interp *interp, int objc, - Tcl_Obj *CONST objv[]) - -{ - struct symtab_and_line sal; - int thread = -1; - CORE_ADDR addr; - Tcl_WideInt waddr; - struct breakpoint *b; - char *saddr, *typestr; - enum bpdisp disp; - - if (objc != 3 && objc != 4) - { - Tcl_WrongNumArgs (interp, 1, objv, "address type ?thread?"); - return TCL_ERROR; - } - - if (Tcl_GetWideIntFromObj (interp, objv[1], &waddr) != TCL_OK) - return TCL_ERROR; - addr = waddr; - saddr = Tcl_GetStringFromObj (objv[1], NULL); - - typestr = Tcl_GetStringFromObj (objv[2], NULL); - if (strncmp (typestr, "temp", 4) == 0) - disp = disp_del; - else if (strncmp (typestr, "normal", 6) == 0) - disp = disp_donttouch; - else - { - gdbtk_set_result (interp, "type must be \"temp\" or \"normal\""); - return TCL_ERROR; - } - - if (objc == 4) - { - if (Tcl_GetIntFromObj (interp, objv[3], &thread) == TCL_ERROR) - { - result_ptr->flags = GDBTK_IN_TCL_RESULT; - return TCL_ERROR; - } - } - - sal = find_pc_line (addr, 0); - sal.pc = addr; - b = set_raw_breakpoint (sal, bp_breakpoint); - set_breakpoint_count (breakpoint_count + 1); - b->number = breakpoint_count; - b->disposition = disp; - b->thread = thread; - b->addr_string = xstrdup (saddr); - - /* now send notification command back to GUI */ - breakpoint_create_event (b->number); - return TCL_OK; -} - -/* - * This section contains functions that deal with breakpoint - * events from gdb. - */ - -/* The next three functions use breakpoint_notify to allow the GUI - * to handle creating, deleting and modifying breakpoints. These three - * functions are put into the appropriate gdb hooks in gdbtk_init. - */ - -void -gdbtk_create_breakpoint (int num) -{ - struct breakpoint *b; - for (b = breakpoint_chain; b != NULL; b = b->next) - { - if (b->number == num) - break; - } - - if (b == NULL || !BREAKPOINT_IS_INTERESTING (b)) - return; - - /* Check if there is room to store it */ - if (num >= breakpoint_list_size) - { - int oldsize = breakpoint_list_size; - while (num >= breakpoint_list_size) - breakpoint_list_size += DEFAULT_LIST_SIZE; - breakpoint_list = (struct breakpoint **) xrealloc (breakpoint_list, breakpoint_list_size * sizeof (struct breakpoint *)); - memset (&(breakpoint_list[oldsize]), 0, (breakpoint_list_size - oldsize) * sizeof (struct breakpoint *)); - } - - breakpoint_list[num] = b; - breakpoint_notify (num, "create"); -} - -void -gdbtk_delete_breakpoint (int num) -{ - if (num >= 0 - && num <= breakpoint_list_size - && breakpoint_list[num] != NULL) - { - breakpoint_notify (num, "delete"); - breakpoint_list[num] = NULL; - } -} - -void -gdbtk_modify_breakpoint (int num) -{ - if (num >= 0) - breakpoint_notify (num, "modify"); -} - -/* This is the generic function for handling changes in - * a breakpoint. It routes the information to the Tcl - * command "gdbtk_tcl_breakpoint" in the form: - * gdbtk_tcl_breakpoint action b_number b_address b_line b_file - * On error, the error string is written to gdb_stdout. - */ -static void -breakpoint_notify (int num, const char *action) -{ - char *buf; - - if (num > breakpoint_list_size - || num < 0 - || breakpoint_list[num] == NULL - /* FIXME: should not be so restrictive... */ - || breakpoint_list[num]->type != bp_breakpoint) - return; - - /* We ensure that ACTION contains no special Tcl characters, so we - can do this. */ - xasprintf (&buf, "gdbtk_tcl_breakpoint %s %d", action, num); - - if (Tcl_Eval (gdbtk_interp, buf) != TCL_OK) - report_error (); - free(buf); -} - -/* - * This section contains the commands that deal with tracepoints: - */ - -/* This implements the tcl command gdb_actions - * It sets actions for a given tracepoint. - * - * Tcl Arguments: - * number: the tracepoint in question - * actions: the actions to add to this tracepoint - * Tcl Result: - * None. - */ - -static int -gdb_actions_command (ClientData clientData, Tcl_Interp *interp, - int objc, Tcl_Obj *CONST objv[]) -{ - struct tracepoint *tp; - Tcl_Obj **actions; - int nactions, i, len; - char *number, *args, *action; - long step_count; - struct action_line *next = NULL, *temp; - enum actionline_type linetype; - - if (objc != 3) - { - Tcl_WrongNumArgs (interp, 1, objv, "number actions"); - return TCL_ERROR; - } - - args = number = Tcl_GetStringFromObj (objv[1], NULL); - tp = get_tracepoint_by_number (&args, 0, 0); - if (tp == NULL) - { - Tcl_AppendStringsToObj (result_ptr->obj_ptr, "Tracepoint \"", - number, "\" does not exist", NULL); - return TCL_ERROR; - } - - /* Free any existing actions */ - if (tp->actions != NULL) - free_actions (tp); - - step_count = 0; - - Tcl_ListObjGetElements (interp, objv[2], &nactions, &actions); - - /* Add the actions to the tracepoint */ - for (i = 0; i < nactions; i++) - { - temp = xmalloc (sizeof (struct action_line)); - temp->next = NULL; - action = Tcl_GetStringFromObj (actions[i], &len); - temp->action = savestring (action, len); - - linetype = validate_actionline (&(temp->action), tp); - - if (linetype == BADLINE) - { - free (temp); - continue; - } - - if (next == NULL) - { - tp->actions = temp; - next = temp; - } - else - { - next->next = temp; - next = temp; - } - } - - return TCL_OK; -} - -static int -gdb_get_trace_frame_num (ClientData clientData, Tcl_Interp *interp, - int objc, Tcl_Obj *CONST objv[]) -{ - if (objc != 1) - { - Tcl_WrongNumArgs (interp, 1, objv, "linespec"); - return TCL_ERROR; - } - - Tcl_SetIntObj (result_ptr->obj_ptr, get_traceframe_number ()); - return TCL_OK; - -} - -static int -gdb_get_tracepoint_info (ClientData clientData, Tcl_Interp *interp, - int objc, Tcl_Obj *CONST objv[]) -{ - struct symtab_and_line sal; - int tpnum; - struct tracepoint *tp; - struct action_line *al; - Tcl_Obj *action_list; - char *filename, *funcname; - - if (objc != 2) - { - Tcl_WrongNumArgs (interp, 1, objv, "tpnum"); - return TCL_ERROR; - } - - if (Tcl_GetIntFromObj (NULL, objv[1], &tpnum) != TCL_OK) - { - result_ptr->flags |= GDBTK_IN_TCL_RESULT; - return TCL_ERROR; - } - - ALL_TRACEPOINTS (tp) - if (tp->number == tpnum) - break; - - if (tp == NULL) - { - gdbtk_set_result (interp, "Tracepoint #%d does not exist", tpnum); - return TCL_ERROR; - } - - Tcl_SetListObj (result_ptr->obj_ptr, 0, NULL); - sal = find_pc_line (tp->address, 0); - filename = symtab_to_filename (sal.symtab); - if (filename == NULL) - filename = "N/A"; - Tcl_ListObjAppendElement (interp, result_ptr->obj_ptr, - Tcl_NewStringObj (filename, -1)); - - funcname = pc_function_name (tp->address); - Tcl_ListObjAppendElement (interp, result_ptr->obj_ptr, Tcl_NewStringObj - (funcname, -1)); - - Tcl_ListObjAppendElement (interp, result_ptr->obj_ptr, - Tcl_NewIntObj (sal.line)); - Tcl_ListObjAppendElement (interp, result_ptr->obj_ptr, - Tcl_NewStringObj (core_addr_to_string (tp->address), -1)); - Tcl_ListObjAppendElement (interp, result_ptr->obj_ptr, - Tcl_NewIntObj (tp->enabled_p)); - Tcl_ListObjAppendElement (interp, result_ptr->obj_ptr, - Tcl_NewIntObj (tp->pass_count)); - Tcl_ListObjAppendElement (interp, result_ptr->obj_ptr, - Tcl_NewIntObj (tp->step_count)); - Tcl_ListObjAppendElement (interp, result_ptr->obj_ptr, - Tcl_NewIntObj (tp->thread)); - Tcl_ListObjAppendElement (interp, result_ptr->obj_ptr, - Tcl_NewIntObj (tp->hit_count)); - - /* Append a list of actions */ - action_list = Tcl_NewObj (); - for (al = tp->actions; al != NULL; al = al->next) - { - Tcl_ListObjAppendElement (interp, action_list, - Tcl_NewStringObj (al->action, -1)); - } - Tcl_ListObjAppendElement (interp, result_ptr->obj_ptr, action_list); - - return TCL_OK; -} - -/* return a list of all tracepoint numbers in interpreter */ -static int -gdb_get_tracepoint_list (ClientData clientData, - Tcl_Interp *interp, - int objc, - Tcl_Obj *CONST objv[]) -{ - struct tracepoint *tp; - - Tcl_SetListObj (result_ptr->obj_ptr, 0, NULL); - - ALL_TRACEPOINTS (tp) - Tcl_ListObjAppendElement (interp, result_ptr->obj_ptr, - Tcl_NewIntObj (tp->number)); - - return TCL_OK; -} - -static int -gdb_trace_status (ClientData clientData, - Tcl_Interp *interp, - int objc, - Tcl_Obj *CONST objv[]) -{ - int result = 0; - - if (trace_running_p) - result = 1; - - Tcl_SetIntObj (result_ptr->obj_ptr, result); - return TCL_OK; -} - -/* returns -1 if not found, tracepoint # if found */ -static int -tracepoint_exists (char *args) -{ - struct tracepoint *tp; - char **canonical; - struct symtabs_and_lines sals; - char *file = NULL; - int result = -1; - - sals = decode_line_1 (&args, 1, NULL, 0, &canonical); - if (sals.nelts == 1) - { - resolve_sal_pc (&sals.sals[0]); - file = xmalloc (strlen (sals.sals[0].symtab->dirname) - + strlen (sals.sals[0].symtab->filename) + 1); - if (file != NULL) - { - strcpy (file, sals.sals[0].symtab->dirname); - strcat (file, sals.sals[0].symtab->filename); - - ALL_TRACEPOINTS (tp) - { - if (tp->address == sals.sals[0].pc) - result = tp->number; -#if 0 - /* Why is this here? This messes up assembly traces */ - else if (tp->source_file != NULL - && strcmp (tp->source_file, file) == 0 - && sals.sals[0].line == tp->line_number) - result = tp->number; -#endif - } - } - } - if (file != NULL) - free (file); - return result; -} - -static int -gdb_tracepoint_exists_command (ClientData clientData, - Tcl_Interp *interp, - int objc, - Tcl_Obj *CONST objv[]) -{ - char *args; - - if (objc != 2) - { - Tcl_WrongNumArgs (interp, 1, objv, - "function:line|function|line|*addr"); - return TCL_ERROR; - } - - args = Tcl_GetStringFromObj (objv[1], NULL); - - Tcl_SetIntObj (result_ptr->obj_ptr, tracepoint_exists (args)); - return TCL_OK; -} - -/* - * This section contains functions which deal with tracepoint - * events from gdb. - */ - -void -gdbtk_create_tracepoint (int num) -{ - tracepoint_notify (num, "create"); -} - -void -gdbtk_delete_tracepoint (int num) -{ - tracepoint_notify (num, "delete"); -} - -void -gdbtk_modify_tracepoint (int num) -{ - tracepoint_notify (num, "modify"); -} - -static void -tracepoint_notify (int num, const char *action) -{ - char *buf; - - /* We ensure that ACTION contains no special Tcl characters, so we - can do this. */ - xasprintf (&buf, "gdbtk_tcl_tracepoint %s %d", action, num); - - if (Tcl_Eval (gdbtk_interp, buf) != TCL_OK) - report_error (); - free(buf); -} |