From patchwork Fri May 20 15:12:37 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Yao Qi X-Patchwork-Id: 12420 Received: (qmail 68415 invoked by alias); 20 May 2016 15:13:09 -0000 Mailing-List: contact gdb-patches-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner@sourceware.org Delivered-To: mailing list gdb-patches@sourceware.org Received: (qmail 68005 invoked by uid 89); 20 May 2016 15:13:07 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-2.6 required=5.0 tests=AWL, BAYES_00, FREEMAIL_FROM, RCVD_IN_DNSWL_LOW, SPF_PASS autolearn=ham version=3.3.2 spammy=12407, 1240, 7, evaluated, 25, 6 X-HELO: mail-pa0-f66.google.com Received: from mail-pa0-f66.google.com (HELO mail-pa0-f66.google.com) (209.85.220.66) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with (AES128-GCM-SHA256 encrypted) ESMTPS; Fri, 20 May 2016 15:12:59 +0000 Received: by mail-pa0-f66.google.com with SMTP id rw9so11215493pab.2 for ; Fri, 20 May 2016 08:12:59 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:from:to:subject:date:message-id:in-reply-to :references; bh=v5vKoULbJFYky29s8kziHAC78kSGcLFdXrKv+0m8w7M=; b=XZcwhVBGfbfJ6UHul1fcMEXpMj1JFvWD7lVlwKzzcD1kZVrLbjpjeyLtmRgpIuYTEc bt+B/ZalrQYR8p0Zn6vFbR9EcxngEhsE2e3GOPXaxQ76RMevuNigRtZhJMNk5hLVHy34 5vpibyQy8rPsGlYQrtEZzHO3a9XF86Q9Pk2QuvbD2Jyn3sXFSt0oSNDe8I3cteB7Ys0p JrDwJ5Wi60mfIyr/VuhQw+3GMatEDnsDiGQ50q1gPqFijCqEkfHj50RNDhmou5jiW+fY Oh/cbA1DW2Nu7cJVdlM1ClBCWvKnGz2Ox3Z7IkHfbG8IHLMpL7nLujE9UJwePxl0rcj1 QeRw== X-Gm-Message-State: AOPr4FXVChgF14Ax2+zPkKxtxAZk4DzijTugub+PD7oWPjaRGKEYX0pTHv7EDXO5sS3Rmg== X-Received: by 10.66.190.131 with SMTP id gq3mr5682146pac.42.1463757177187; Fri, 20 May 2016 08:12:57 -0700 (PDT) Received: from E107787-LIN.cambridge.arm.com (gcc113.osuosl.org. [140.211.9.71]) by smtp.gmail.com with ESMTPSA id p80sm27985272pfj.58.2016.05.20.08.12.55 for (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Fri, 20 May 2016 08:12:56 -0700 (PDT) From: Yao Qi X-Google-Original-From: Yao Qi To: gdb-patches@sourceware.org Subject: [PATCH 4/8] Create sub classes of 'struct breakpoint' Date: Fri, 20 May 2016 16:12:37 +0100 Message-Id: <1463757161-25850-5-git-send-email-yao.qi@linaro.org> In-Reply-To: <1463757161-25850-1-git-send-email-yao.qi@linaro.org> References: <1463757161-25850-1-git-send-email-yao.qi@linaro.org> X-IsSubscribed: yes Nowadays, there are three types of breakpoint in GDBserver, - gdb breakpoints, - reinsert breakpoints, used for software single step, - other breakpoints, used for tracepoint, but we only have one 'struct breakpoint' for all of them. Some fields are only useful to one type of breakpoint. For example, cond_list and command_list are only used by gdb breakpoints, while handler is only used by other breakpoints. This patch changes 'struct breakpoint' to a base class, which has fields needed by all breakpoint types, also add three sub-classes to 'struct breakpoint' to these three types of breakpoints. gdb/gdbserver: 2016-05-20 Yao Qi * mem-break.c (struct breakpoint) : Remove. : Remove. (struct gdb_breakpoint): New. (struct other_breakpoint): New. (struct reinsert_breakpoint): New. (is_gdb_breakpoint): New function. (any_persistent_commands): Update command_list if is_gdb_breakpoint returns true. (set_breakpoint): Create breakpoints according to their types. (find_gdb_breakpoint): Return 'struct gdb_breakpoint *'. (set_gdb_breakpoint_1): Likewise. (set_gdb_breakpoint): Likewise. (clear_breakpoint_conditions): Change parameter type to 'struct gdb_breakpoint *'. (clear_breakpoint_commands): Likewise. (clear_breakpoint_conditions_and_commands): Likewise. (add_condition_to_breakpoint): Likewise. (add_breakpoint_condition): Likewise. (add_commands_to_breakpoint): Likewise. (check_breakpoints): Check other_breakpoint. (clone_one_breakpoint): Clone breakpopint according to its type. * mem-break.h (struct gdb_breakpoint): Declare. (set_gdb_breakpoint): Update declaration. (clear_breakpoint_conditions_and_commands): Likewise. (add_breakpoint_condition): Likewise. (add_breakpoint_commands): Likewise. * server.c (process_point_options): Change parameter type to 'struct gdb_breakpoint *'. --- gdb/gdbserver/mem-break.c | 209 +++++++++++++++++++++++++++++++++------------- gdb/gdbserver/mem-break.h | 11 +-- gdb/gdbserver/server.c | 4 +- 3 files changed, 157 insertions(+), 67 deletions(-) diff --git a/gdb/gdbserver/mem-break.c b/gdb/gdbserver/mem-break.c index 3e3be8b..1fe1d20 100644 --- a/gdb/gdbserver/mem-break.c +++ b/gdb/gdbserver/mem-break.c @@ -173,6 +173,17 @@ struct breakpoint /* The breakpoint's type. */ enum bkpt_type type; + /* Link to this breakpoint's raw breakpoint. This is always + non-NULL. */ + struct raw_breakpoint *raw; +}; + +/* Breakpoint requested by GDB. */ + +struct gdb_breakpoint +{ + struct breakpoint base; + /* Pointer to the condition list that should be evaluated on the target or NULL if the breakpoint is unconditional or if GDB doesn't want us to evaluate the conditionals on the @@ -181,10 +192,13 @@ struct breakpoint /* Point to the list of commands to run when this is hit. */ struct point_command_list *command_list; +}; - /* Link to this breakpoint's raw breakpoint. This is always - non-NULL. */ - struct raw_breakpoint *raw; +/* Breakpoint used by GDBserver. */ + +struct other_breakpoint +{ + struct breakpoint base; /* Function to call when we hit this breakpoint. If it returns 1, the breakpoint shall be deleted; 0 or if this callback is NULL, @@ -192,6 +206,13 @@ struct breakpoint int (*handler) (CORE_ADDR); }; +/* Reinsert breakpoint. */ + +struct reinsert_breakpoint +{ + struct breakpoint base; +}; + /* Return the breakpoint size from its kind. */ static int @@ -266,6 +287,18 @@ Z_packet_to_raw_bkpt_type (char z_type) } } +/* Return true if breakpoint TYPE is a GDB breakpoint. */ + +static int +is_gdb_breakpoint (enum bkpt_type type) +{ + return (type == gdb_breakpoint_Z0 + || type == gdb_breakpoint_Z1 + || type == gdb_breakpoint_Z2 + || type == gdb_breakpoint_Z3 + || type == gdb_breakpoint_Z4); +} + int any_persistent_commands (void) { @@ -275,9 +308,14 @@ any_persistent_commands (void) for (bp = proc->breakpoints; bp != NULL; bp = bp->next) { - for (cl = bp->command_list; cl != NULL; cl = cl->next) - if (cl->persistence) - return 1; + if (is_gdb_breakpoint (bp->type)) + { + struct gdb_breakpoint *gdb_bp = (struct gdb_breakpoint *) bp; + + for (cl = gdb_bp->command_list; cl != NULL; cl = cl->next) + if (cl->persistence) + return 1; + } } return 0; @@ -773,11 +811,32 @@ set_breakpoint (enum bkpt_type type, enum raw_bkpt_type raw_type, return NULL; } - bp = XCNEW (struct breakpoint); - bp->type = type; + if (is_gdb_breakpoint (type)) + { + struct gdb_breakpoint *gdb_bp = XCNEW (struct gdb_breakpoint); + + bp = (struct breakpoint *) gdb_bp; + gdb_assert (handler == NULL); + } + else if (type == other_breakpoint) + { + struct other_breakpoint *other_bp = XCNEW (struct other_breakpoint); + + other_bp->handler = handler; + bp = (struct breakpoint *) other_bp; + } + else if (type == reinsert_breakpoint) + { + struct reinsert_breakpoint *reinsert_bp + = XCNEW (struct reinsert_breakpoint); + bp = (struct breakpoint *) reinsert_bp; + } + else + gdb_assert_not_reached ("unhandled breakpoint type"); + + bp->type = type; bp->raw = raw; - bp->handler = handler; bp->next = proc->breakpoints; proc->breakpoints = bp; @@ -924,7 +983,7 @@ delete_breakpoint (struct breakpoint *todel) address ADDR and return a pointer to its structure. If KIND is -1, the breakpoint's kind is ignored. */ -static struct breakpoint * +static struct gdb_breakpoint * find_gdb_breakpoint (char z_type, CORE_ADDR addr, int kind) { struct process_info *proc = current_process (); @@ -934,7 +993,7 @@ find_gdb_breakpoint (char z_type, CORE_ADDR addr, int kind) for (bp = proc->breakpoints; bp != NULL; bp = bp->next) if (bp->type == type && bp->raw->pc == addr && (kind == -1 || bp->raw->kind == kind)) - return bp; + return (gdb_breakpoint *) bp; return NULL; } @@ -952,10 +1011,10 @@ z_type_supported (char z_type) failure returns NULL and sets *ERR to either -1 for error, or 1 if Z_TYPE breakpoints are not supported on this target. */ -static struct breakpoint * +static struct gdb_breakpoint * set_gdb_breakpoint_1 (char z_type, CORE_ADDR addr, int kind, int *err) { - struct breakpoint *bp; + struct gdb_breakpoint *bp; enum bkpt_type type; enum raw_bkpt_type raw_type; @@ -981,12 +1040,12 @@ set_gdb_breakpoint_1 (char z_type, CORE_ADDR addr, int kind, int *err) if (bp != NULL) { - if (bp->raw->kind != kind) + if (bp->base.raw->kind != kind) { /* A different kind than previously seen. The previous breakpoint must be gone then. */ - bp->raw->inserted = -1; - delete_breakpoint (bp); + bp->base.raw->inserted = -1; + delete_breakpoint ((struct breakpoint *) bp); bp = NULL; } else if (z_type == Z_PACKET_SW_BP) @@ -1022,7 +1081,8 @@ set_gdb_breakpoint_1 (char z_type, CORE_ADDR addr, int kind, int *err) raw_type = Z_packet_to_raw_bkpt_type (z_type); type = Z_packet_to_bkpt_type (z_type); - return set_breakpoint (type, raw_type, addr, kind, NULL, err); + return (struct gdb_breakpoint *) set_breakpoint (type, raw_type, addr, + kind, NULL, err); } static int @@ -1047,10 +1107,10 @@ check_gdb_bp_preconditions (char z_type, int *err) /* See mem-break.h. This is a wrapper for set_gdb_breakpoint_1 that knows to prepare to access memory for Z0 breakpoints. */ -struct breakpoint * +struct gdb_breakpoint * set_gdb_breakpoint (char z_type, CORE_ADDR addr, int kind, int *err) { - struct breakpoint *bp; + struct gdb_breakpoint *bp; if (!check_gdb_bp_preconditions (z_type, err)) return NULL; @@ -1082,7 +1142,7 @@ set_gdb_breakpoint (char z_type, CORE_ADDR addr, int kind, int *err) static int delete_gdb_breakpoint_1 (char z_type, CORE_ADDR addr, int kind) { - struct breakpoint *bp; + struct gdb_breakpoint *bp; int err; bp = find_gdb_breakpoint (z_type, addr, kind); @@ -1092,7 +1152,7 @@ delete_gdb_breakpoint_1 (char z_type, CORE_ADDR addr, int kind) /* Before deleting the breakpoint, make sure to free its condition and command lists. */ clear_breakpoint_conditions_and_commands (bp); - err = delete_breakpoint (bp); + err = delete_breakpoint ((struct breakpoint *) bp); if (err != 0) return -1; @@ -1132,7 +1192,7 @@ delete_gdb_breakpoint (char z_type, CORE_ADDR addr, int kind) /* Clear all conditions associated with a breakpoint. */ static void -clear_breakpoint_conditions (struct breakpoint *bp) +clear_breakpoint_conditions (struct gdb_breakpoint *bp) { struct point_cond_list *cond; @@ -1157,7 +1217,7 @@ clear_breakpoint_conditions (struct breakpoint *bp) /* Clear all commands associated with a breakpoint. */ static void -clear_breakpoint_commands (struct breakpoint *bp) +clear_breakpoint_commands (struct gdb_breakpoint *bp) { struct point_command_list *cmd; @@ -1180,7 +1240,7 @@ clear_breakpoint_commands (struct breakpoint *bp) } void -clear_breakpoint_conditions_and_commands (struct breakpoint *bp) +clear_breakpoint_conditions_and_commands (struct gdb_breakpoint *bp) { clear_breakpoint_conditions (bp); clear_breakpoint_commands (bp); @@ -1189,7 +1249,7 @@ clear_breakpoint_conditions_and_commands (struct breakpoint *bp) /* Add condition CONDITION to GDBserver's breakpoint BP. */ static void -add_condition_to_breakpoint (struct breakpoint *bp, +add_condition_to_breakpoint (struct gdb_breakpoint *bp, struct agent_expr *condition) { struct point_cond_list *new_cond; @@ -1206,7 +1266,7 @@ add_condition_to_breakpoint (struct breakpoint *bp, /* Add a target-side condition CONDITION to a breakpoint. */ int -add_breakpoint_condition (struct breakpoint *bp, char **condition) +add_breakpoint_condition (struct gdb_breakpoint *bp, char **condition) { char *actparm = *condition; struct agent_expr *cond; @@ -1240,7 +1300,7 @@ static int gdb_condition_true_at_breakpoint_z_type (char z_type, CORE_ADDR addr) { /* Fetch registers for the current inferior. */ - struct breakpoint *bp = find_gdb_breakpoint (z_type, addr, -1); + struct gdb_breakpoint *bp = find_gdb_breakpoint (z_type, addr, -1); ULONGEST value = 0; struct point_cond_list *cl; int err = 0; @@ -1287,7 +1347,7 @@ gdb_condition_true_at_breakpoint (CORE_ADDR where) /* Add commands COMMANDS to GDBserver's breakpoint BP. */ static void -add_commands_to_breakpoint (struct breakpoint *bp, +add_commands_to_breakpoint (struct gdb_breakpoint *bp, struct agent_expr *commands, int persist) { struct point_command_list *new_cmd; @@ -1305,7 +1365,7 @@ add_commands_to_breakpoint (struct breakpoint *bp, /* Add a target-side command COMMAND to the breakpoint at ADDR. */ int -add_breakpoint_commands (struct breakpoint *bp, char **command, +add_breakpoint_commands (struct gdb_breakpoint *bp, char **command, int persist) { char *actparm = *command; @@ -1339,7 +1399,7 @@ add_breakpoint_commands (struct breakpoint *bp, char **command, static int gdb_no_commands_at_breakpoint_z_type (char z_type, CORE_ADDR addr) { - struct breakpoint *bp = find_gdb_breakpoint (z_type, addr, -1); + struct gdb_breakpoint *bp = find_gdb_breakpoint (z_type, addr, -1); if (bp == NULL) return 1; @@ -1369,7 +1429,7 @@ static int run_breakpoint_commands_z_type (char z_type, CORE_ADDR addr) { /* Fetch registers for the current inferior. */ - struct breakpoint *bp = find_gdb_breakpoint (z_type, addr, -1); + struct gdb_breakpoint *bp = find_gdb_breakpoint (z_type, addr, -1); ULONGEST value = 0; struct point_command_list *cl; int err = 0; @@ -1619,14 +1679,20 @@ check_breakpoints (CORE_ADDR stop_pc) return; } - if (bp->handler != NULL && (*bp->handler) (stop_pc)) + if (bp->type == other_breakpoint) { - *bp_link = bp->next; + struct other_breakpoint *other_bp + = (struct other_breakpoint *) bp; + + if (other_bp->handler != NULL && (*other_bp->handler) (stop_pc)) + { + *bp_link = bp->next; - release_breakpoint (proc, bp); + release_breakpoint (proc, bp); - bp = *bp_link; - continue; + bp = *bp_link; + continue; + } } } @@ -2008,12 +2074,6 @@ clone_one_breakpoint (const struct breakpoint *src) { struct breakpoint *dest; struct raw_breakpoint *dest_raw; - struct point_cond_list *current_cond; - struct point_cond_list *new_cond; - struct point_cond_list *cond_tail = NULL; - struct point_command_list *current_cmd; - struct point_command_list *new_cmd; - struct point_command_list *cmd_tail = NULL; /* Clone the raw breakpoint. */ dest_raw = XCNEW (struct raw_breakpoint); @@ -2025,29 +2085,58 @@ clone_one_breakpoint (const struct breakpoint *src) dest_raw->inserted = src->raw->inserted; /* Clone the high-level breakpoint. */ - dest = XCNEW (struct breakpoint); - dest->type = src->type; - dest->raw = dest_raw; - dest->handler = src->handler; - - /* Clone the condition list. */ - for (current_cond = src->cond_list; current_cond != NULL; - current_cond = current_cond->next) + if (is_gdb_breakpoint (src->type)) { - new_cond = XCNEW (struct point_cond_list); - new_cond->cond = clone_agent_expr (current_cond->cond); - APPEND_TO_LIST (&dest->cond_list, new_cond, cond_tail); + struct gdb_breakpoint *gdb_dest = XCNEW (struct gdb_breakpoint); + struct point_cond_list *current_cond; + struct point_cond_list *new_cond; + struct point_cond_list *cond_tail = NULL; + struct point_command_list *current_cmd; + struct point_command_list *new_cmd; + struct point_command_list *cmd_tail = NULL; + + /* Clone the condition list. */ + for (current_cond = ((struct gdb_breakpoint *) src)->cond_list; + current_cond != NULL; + current_cond = current_cond->next) + { + new_cond = XCNEW (struct point_cond_list); + new_cond->cond = clone_agent_expr (current_cond->cond); + APPEND_TO_LIST (&gdb_dest->cond_list, new_cond, cond_tail); + } + + /* Clone the command list. */ + for (current_cmd = ((struct gdb_breakpoint *) src)->command_list; + current_cmd != NULL; + current_cmd = current_cmd->next) + { + new_cmd = XCNEW (struct point_command_list); + new_cmd->cmd = clone_agent_expr (current_cmd->cmd); + new_cmd->persistence = current_cmd->persistence; + APPEND_TO_LIST (&gdb_dest->command_list, new_cmd, cmd_tail); + } + + dest = (struct breakpoint *) gdb_dest; } + else if (src->type == other_breakpoint) + { + struct other_breakpoint *other_dest = XCNEW (struct other_breakpoint); - /* Clone the command list. */ - for (current_cmd = src->command_list; current_cmd != NULL; - current_cmd = current_cmd->next) + other_dest->handler = ((struct other_breakpoint *) src)->handler; + dest = (struct breakpoint *) other_dest; + } + else if (src->type == reinsert_breakpoint) { - new_cmd = XCNEW (struct point_command_list); - new_cmd->cmd = clone_agent_expr (current_cmd->cmd); - new_cmd->persistence = current_cmd->persistence; - APPEND_TO_LIST (&dest->command_list, new_cmd, cmd_tail); + struct reinsert_breakpoint *reinsert_dest + = XCNEW (struct reinsert_breakpoint); + + dest = (struct breakpoint *) reinsert_dest; } + else + gdb_assert_not_reached ("unhandled breakpoint type"); + + dest->type = src->type; + dest->raw = dest_raw; return dest; } diff --git a/gdb/gdbserver/mem-break.h b/gdb/gdbserver/mem-break.h index f6c9631..280e4f8 100644 --- a/gdb/gdbserver/mem-break.h +++ b/gdb/gdbserver/mem-break.h @@ -25,6 +25,7 @@ /* Breakpoints are opaque. */ struct breakpoint; +struct gdb_breakpoint; struct fast_tracepoint_jump; struct raw_breakpoint; struct process_info; @@ -70,8 +71,8 @@ enum target_hw_bp_type raw_bkpt_type_to_target_hw_bp_type failure returns NULL and sets *ERR to either -1 for error, or 1 if Z_TYPE breakpoints are not supported on this target. */ -struct breakpoint *set_gdb_breakpoint (char z_type, CORE_ADDR addr, int kind, - int *err); +struct gdb_breakpoint *set_gdb_breakpoint (char z_type, CORE_ADDR addr, + int kind, int *err); /* Delete a GDB breakpoint of type Z_TYPE and kind KIND previously inserted at ADDR with set_gdb_breakpoint_at. Returns 0 on success, @@ -107,20 +108,20 @@ int reinsert_breakpoint_inserted_here (CORE_ADDR addr); /* Clear all breakpoint conditions and commands associated with a breakpoint. */ -void clear_breakpoint_conditions_and_commands (struct breakpoint *bp); +void clear_breakpoint_conditions_and_commands (struct gdb_breakpoint *bp); /* Set target-side condition CONDITION to the breakpoint at ADDR. Returns false on failure. On success, advances CONDITION pointer past the condition and returns true. */ -int add_breakpoint_condition (struct breakpoint *bp, char **condition); +int add_breakpoint_condition (struct gdb_breakpoint *bp, char **condition); /* Set target-side commands COMMANDS to the breakpoint at ADDR. Returns false on failure. On success, advances COMMANDS past the commands and returns true. If PERSIST, the commands should run even while GDB is disconnected. */ -int add_breakpoint_commands (struct breakpoint *bp, char **commands, +int add_breakpoint_commands (struct gdb_breakpoint *bp, char **commands, int persist); int any_persistent_commands (void); diff --git a/gdb/gdbserver/server.c b/gdb/gdbserver/server.c index 9c50929..18517bc 100644 --- a/gdb/gdbserver/server.c +++ b/gdb/gdbserver/server.c @@ -3825,7 +3825,7 @@ main (int argc, char *argv[]) after the last processed option. */ static void -process_point_options (struct breakpoint *bp, char **packet) +process_point_options (struct gdb_breakpoint *bp, char **packet) { char *dataptr = *packet; int persist; @@ -4197,7 +4197,7 @@ process_serial_event (void) if (insert) { - struct breakpoint *bp; + struct gdb_breakpoint *bp; bp = set_gdb_breakpoint (type, addr, kind, &res); if (bp != NULL)