From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 18533 invoked by alias); 25 Apr 2010 15:56:15 -0000 Received: (qmail 18491 invoked by uid 22791); 25 Apr 2010 15:56:07 -0000 X-SWARE-Spam-Status: No, hits=-1.8 required=5.0 tests=BAYES_00,TW_WT,T_RP_MATCHES_RCVD X-Spam-Check-By: sourceware.org Received: from rock.gnat.com (HELO rock.gnat.com) (205.232.38.15) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Sun, 25 Apr 2010 15:56:00 +0000 Received: from localhost (localhost.localdomain [127.0.0.1]) by filtered-rock.gnat.com (Postfix) with ESMTP id 885522BAC55 for ; Sun, 25 Apr 2010 11:47:48 -0400 (EDT) Received: from rock.gnat.com ([127.0.0.1]) by localhost (rock.gnat.com [127.0.0.1]) (amavisd-new, port 10024) with LMTP id vL0Rft8I2oJb for ; Sun, 25 Apr 2010 11:47:48 -0400 (EDT) Received: from joel.gnat.com (localhost.localdomain [127.0.0.1]) by rock.gnat.com (Postfix) with ESMTP id 4FB772BAC8C for ; Sun, 25 Apr 2010 11:47:48 -0400 (EDT) Received: by joel.gnat.com (Postfix, from userid 1000) id E3FCBF5896; Sun, 25 Apr 2010 11:47:47 -0400 (EDT) From: Joel Brobecker To: gdb-patches@sourceware.org Subject: [vxworks 06/14] VxWorks breakpoint-handling module. Date: Sun, 25 Apr 2010 15:56:00 -0000 Message-Id: <1272210447-13895-7-git-send-email-brobecker@adacore.com> In-Reply-To: <1272210447-13895-1-git-send-email-brobecker@adacore.com> References: <1272210447-13895-1-git-send-email-brobecker@adacore.com> Mailing-List: contact gdb-patches-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner@sourceware.org X-SW-Source: 2010-04/txt/msg00848.txt.bz2 This unit provides a set of routines that allow us to insert/remove breakpoints and watchpoints on the target. The target takes care of the insertion/removal, but we need to keep track of respective IDs... 2010-04-24 Joel Brobecker * remote-wtx-bp.h, remote-wtx-bp.c: New files. --- gdb/remote-wtx-bp.c | 235 +++++++++++++++++++++++++++++++++++++++++++++++++++ gdb/remote-wtx-bp.h | 159 ++++++++++++++++++++++++++++++++++ 2 files changed, 394 insertions(+), 0 deletions(-) create mode 100644 gdb/remote-wtx-bp.c create mode 100644 gdb/remote-wtx-bp.h diff --git a/gdb/remote-wtx-bp.c b/gdb/remote-wtx-bp.c new file mode 100644 index 0000000..25bb92a --- /dev/null +++ b/gdb/remote-wtx-bp.c @@ -0,0 +1,235 @@ +/* WTX backend for GDB. + + Copyright 2007, 2010 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 3 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, see . */ + +#include "defs.h" +#include "remote-wtx-bp.h" + +static enum wtx_breakpoint_action break_command_action = action_task; + +void +set_break_command_action (enum wtx_breakpoint_action action) +{ + break_command_action = action; +} + +enum wtx_breakpoint_action +get_break_command_action (void) +{ + return break_command_action; +} + +/* Handling of breakpoint command call routine. */ + +static CORE_ADDR break_command_call_rtn = 0; + +void +set_break_command_call_rtn (CORE_ADDR call_rtn) +{ + break_command_call_rtn = call_rtn; +} + +CORE_ADDR +get_break_command_call_rtn (void) +{ + return break_command_call_rtn; +} + +/* -------------------------- + -- Breakpoint support -- + -------------------------- */ + +/* Handling of eventpoint IDs. + + VxWorks provides eventpoints for breakpoints and watchpoints. For each + inserted breakpoint, the target server returns an evenpoint ID that we + need to record, because we will need this ID to remove this breakpoint. */ + +struct eventpoint_info +{ + struct bp_target_info *target_info; + evtpt_id_t id; + WTX_CONTEXT_TYPE context_type; + WTX_CONTEXT_ID_T context_id; + + struct eventpoint_info *next; +}; + +struct eventpoint_info *eventpoints; + +/* Create an new eventpoint_info structure with the given parameters, + and insert it at the head of our EVENTPOINTS list. */ + +void +wtx_bp_register_eventpoint_id (evtpt_id_t id, + struct bp_target_info *target_info, + WTX_CONTEXT_TYPE context_type, + WTX_CONTEXT_ID_T context_id) +{ + struct eventpoint_info *new_info = + xmalloc (sizeof (struct eventpoint_info)); + + new_info->target_info = target_info; + new_info->id = id; + new_info->context_type = context_type; + new_info->context_id = context_id; + + /* Insert at the head of our EVENTPOINTS list. */ + new_info->next = eventpoints; + eventpoints = new_info; +} + +/* Return the eventpoint ID associated to the given TARGET_INFO, + and remove its entry in our EVENTPOINTS list. Return the + associated context in CONTEXT_TYPE and CONTEXT_ID. + + Return invalid_evtpt_id if the target_info is unknown to us. */ + +evtpt_id_t +wtx_bp_pop_eventpoint_id (struct bp_target_info *target_info, + WTX_CONTEXT_TYPE *context_type, + WTX_CONTEXT_ID_T *context_id) +{ + struct eventpoint_info *info = eventpoints; + struct eventpoint_info *prev_info = NULL; + evtpt_id_t evtpt_id = invalid_evtpt_id; + + while (info != NULL) + { + if (info->target_info == target_info) + { + evtpt_id = info->id; + *context_type = info->context_type; + *context_id = info->context_id; + + /* Delete this node. */ + if (prev_info != NULL) + prev_info->next = info->next; + else + eventpoints = info->next; + xfree (info); + + break; + } + prev_info = info; + info = info->next; + } + + return evtpt_id; +} + +/* -------------------------- + -- Watchpoint support -- + -------------------------- */ + +/* A structure to do the mapping between a GDB watchpoint and the associated + eventpoint ID created by the target. We use this mapping in order to + be able to remove a watchpoint. */ + +struct watchpoint_info +{ + CORE_ADDR data_addr; + int data_len; + int type; + evtpt_id_t watchpoint_id; + + struct watchpoint_info *next; +}; + +/* The list of watchpoints we inserted in the target. */ +static struct watchpoint_info *watchpoint_list = NULL; + +/* Return non-zero if INFO matches (DATA_ADDR, DATA_LEN, TYPE). + In other words, return non-zero if INFO is the watchpont_info + object that corresponds to a GDB watchpoint. */ + +static int +watchpoint_info_matches (struct watchpoint_info *info, + CORE_ADDR data_addr, int data_len, int type) +{ + return (info->data_addr == data_addr + && info->data_len == data_len + && info->type == type); +} + +/* Record in our watchpoint list the fact that we just inserted a watchpoint + on the target. */ + +void +wtx_bp_register_watchpoint_id (evtpt_id_t watchpoint_id, CORE_ADDR data_addr, + int data_len, int type) +{ + struct watchpoint_info *info = xmalloc (sizeof (struct watchpoint_info)); + + info->data_addr = data_addr; + info->data_len = data_len; + info->type = type; + info->watchpoint_id = watchpoint_id; + + /* Now insert this new node at the head. */ + info->next = watchpoint_list; + watchpoint_list = info; +} + +/* Search our list of watchpoint_info objects, and pop the entry + that matches the watchpoint corresponding to (DATA_ADDR, DATA_LEN, + TYPE). Return the associated eventpoint ID. + + Return invalid_evtpt_id if no match was found. */ + +evtpt_id_t +wtx_bp_pop_watchpoint_id (CORE_ADDR data_addr, int data_len, int type) +{ + struct watchpoint_info *info = watchpoint_list; + evtpt_id_t watchpoint_id; + + /* Check to see if the node at the head of the watchpoint list matches + the description. If yes, then destroy that node. Given that on certain + architectures, we only have access to one watchpoints, this condition + should be true most of the time. */ + + if (info != NULL + && watchpoint_info_matches (info, data_addr, data_len, type)) + { + watchpoint_id = info->watchpoint_id; + watchpoint_list = info->next; + free (info); + return watchpoint_id; + } + + /* If not, then look for the node that is immediately preceding the node + we're looking for. Then do the freeing and reconnecting. */ + while (info != NULL) + { + if (info->next != NULL + && watchpoint_info_matches (info->next, data_addr, data_len, type)) + { + struct watchpoint_info *tmp = info->next; + + watchpoint_id = tmp->watchpoint_id; + info->next = tmp->next; + free (tmp); + return watchpoint_id; + } + info = info->next; + } + + /* No corresponding watchpoint eventpoint found. */ + return invalid_evtpt_id; +} + diff --git a/gdb/remote-wtx-bp.h b/gdb/remote-wtx-bp.h new file mode 100644 index 0000000..3e241e0 --- /dev/null +++ b/gdb/remote-wtx-bp.h @@ -0,0 +1,159 @@ +/* WTX backend for GDB. + + Copyright 2007, 2010 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 3 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, see . */ + +#ifndef REMOTE_WTX_BP_H +#define REMOTE_WTX_BP_H + +#include "remote-wtxapi.h" + +/* A note about breakpoint command "scope" and "action" settings: + -------------------------------------------------------------- + + These as concepts that were introduced in VxWorks AE, but no longer + make much sense in VxWorks 653. On 653, the user will debug either: + + 1. A task inside the kernel partition; + + 2. An entire partition, which in pratice is exactly similar to (1), + since it is done by debugging the task associated to that partition; + + 3. The entire system in "system-mode". + + This means that are are actually realy only debugging modes available + to the user: + a. The single-task mode + b. The system-mode. + + In system-mode, the scope and action are, by design from the system, + irrelevant. Breakpoints will stop the entire system when any task + hits them. + + In single-task mode, we user is debugging his task independently + of the rest of the system. This means that the scope of breakpoints + in that mode will be that task and only that task. Similarly, we + are forcing the action to that task as well. + + As a result, the scope and actions can be implicitly determined + from the debugging context, and thus do not require user input. + This is why there is no longer a "set" command that allows the + user to change it anymore. + + Also, this also means that the context and action can no longer + change during a debugging session. As a consequence, although + the system does allow tools to use independent scope and action + settings for every breakpoints, the debugger will be using + consistent settings, thus avoiding the need to track what + breakpoint uses what setting. This knowledge is important + when resuming breakpoints, because if a breakpoint stopped + all tasks, then we need to resume all tasks when doing a + "continue" for instance. + + brobecker/2007-09-25: It is conceivable that some users might + find that have the choice of setting the action to "all" for + their debugging session would be helpful, or even necessary. + In that case, the system-mode might be more approriate to their + needs. However, the system-mode does have some limitations that + might not be acceptable either. This code has been designed in + such a way that adding that feature, this extra choice, should + just be a matter of adding a "set" command to let the user change + the action. */ + +/* Advance declarations. */ + +struct bp_target_info; + +/* The following enum defines the various actions that can be taken + when a breakpoint is hit. */ + +enum wtx_breakpoint_action +{ + action_task, /* Stop the current task. */ + action_all, /* Stop all breakable tasks in all partitions. */ + action_call /* Stop the current task and call a stop function on the + target, if this function is defined. */ +}; + +/* Exported routines. */ + +void wtx_bp_register_eventpoint_id (evtpt_id_t id, + struct bp_target_info *target_info, + WTX_CONTEXT_TYPE context_type, + WTX_CONTEXT_ID_T context_id); + +evtpt_id_t wtx_bp_pop_eventpoint_id (struct bp_target_info *target_info, + WTX_CONTEXT_TYPE *context_type, + WTX_CONTEXT_ID_T *context_id); + +void set_break_command_call_rtn (CORE_ADDR call_rtn); + +CORE_ADDR get_break_command_call_rtn (void); + +void set_break_command_action (enum wtx_breakpoint_action); + +enum wtx_breakpoint_action get_break_command_action (void); + +/* Watchpoint support. */ + +/* HARDWARE WATCHPOINT SUPPORT: + ============================ + + Strictly speaking, the only systems that support hardware watchpoints + are the targets that implement BoDA (Break on Data Access) events. + This functionality was introduced in a limited number of versions + of VxWorks 653 which can be identified once we're connected to + the system (see wtxapi_target_has_BoDA). + + For systems that do not support BoDA, there is another type of + watchpoint event (WTX_EVENT_DATA_ACCESS) which, according to + WindRiver is not strictly speaking a hardware watchpoint because + it doesn't use the features of the target hardware to implement it. + However, from the debugger's perspective, these watchpoint events + are still viewed as hardware, because they do not require us to + emulate watchpoint support at the debugger level. Although not as + fast as strict hardware watchpoint support, these events are still + faster than having to emulate them at the debugger level, since it + avoids a very large amount of interaction between the debugger and + the target. Experimentations on VxWorks 5.5 and VxWorks 653 have + revealed that only one such event can be used at the same time: + - On VxWorks 5.5, the system lets you insert the events, but + somehow then fails to notify the tools for any of the watchpoints + - On VxWorks 653, the system returns an error when trying to + insert the second data-access event. + + For systems supporting BoDA, there is one and only one watchpoint + available. Any other watchpoints must be emulated at the debugger + level. */ + +/* brobecker/2007-10-05: For some reason, I remembered that hardware-assisted + watchpoints do not stop at the instruction that caused the watchpoint + trigger, but rather stops at the next instruction. So single-stepping + of one instruction in order to get the new value is not necessary for + WTX_EVENT_HW_BP and WTX_EVENT_BODA. But a previous implementation + seems to contradict my memory. So for now, we do not adjust + GDBARCH_HAVE_NONSTEPPABLE_WATCHPOINT. We will worry about this when + we actually encounter a problem. */ + +void wtx_bp_register_watchpoint_id (evtpt_id_t watchpoint_id, + CORE_ADDR data_addr, + int data_len, int type); + +evtpt_id_t wtx_bp_pop_watchpoint_id (CORE_ADDR data_addr, int data_len, + int type); + +#endif -- 1.6.3.3