aboutsummaryrefslogtreecommitdiff
path: root/gdb
diff options
context:
space:
mode:
Diffstat (limited to 'gdb')
-rw-r--r--gdb/gdbserver/ChangeLog8
-rw-r--r--gdb/gdbserver/mem-break.c105
-rw-r--r--gdb/gdbserver/mem-break.h6
3 files changed, 119 insertions, 0 deletions
diff --git a/gdb/gdbserver/ChangeLog b/gdb/gdbserver/ChangeLog
index a37051d..73788ec 100644
--- a/gdb/gdbserver/ChangeLog
+++ b/gdb/gdbserver/ChangeLog
@@ -1,5 +1,13 @@
2015-05-12 Don Breazeal <donb@codesourcery.com>
+ * mem-break.c (APPEND_TO_LIST): Define macro.
+ (clone_agent_expr): New function.
+ (clone_one_breakpoint): New function.
+ (clone_all_breakpoints): New function.
+ * mem-break.h: Declare new functions.
+
+2015-05-12 Don Breazeal <donb@codesourcery.com>
+
* linux-low.c (linux_supports_fork_events): New function.
(linux_supports_vfork_events): New function.
(linux_target_ops): Initialize new structure members.
diff --git a/gdb/gdbserver/mem-break.c b/gdb/gdbserver/mem-break.c
index 70fab2e..d1b66bf 100644
--- a/gdb/gdbserver/mem-break.c
+++ b/gdb/gdbserver/mem-break.c
@@ -28,6 +28,24 @@ int breakpoint_len;
#define MAX_BREAKPOINT_LEN 8
+/* Helper macro used in loops that append multiple items to a singly-linked
+ list instead of inserting items at the head of the list, as, say, in the
+ breakpoint lists. LISTPP is a pointer to the pointer that is the head of
+ the new list. ITEMP is a pointer to the item to be added to the list.
+ TAILP must be defined to be the same type as ITEMP, and initialized to
+ NULL. */
+
+#define APPEND_TO_LIST(listpp, itemp, tailp) \
+ do \
+ { \
+ if ((tailp) == NULL) \
+ *(listpp) = (itemp); \
+ else \
+ (tailp)->next = (itemp); \
+ (tailp) = (itemp); \
+ } \
+ while (0)
+
/* GDB will never try to install multiple breakpoints at the same
address. However, we can see GDB requesting to insert a breakpoint
at an address is had already inserted one previously in a few
@@ -1913,3 +1931,90 @@ free_all_breakpoints (struct process_info *proc)
while (proc->breakpoints)
delete_breakpoint_1 (proc, proc->breakpoints);
}
+
+/* Clone an agent expression. */
+
+static struct agent_expr *
+clone_agent_expr (const struct agent_expr *src_ax)
+{
+ struct agent_expr *ax;
+
+ ax = xcalloc (1, sizeof (*ax));
+ ax->length = src_ax->length;
+ ax->bytes = xcalloc (ax->length, 1);
+ memcpy (ax->bytes, src_ax->bytes, ax->length);
+ return ax;
+}
+
+/* Deep-copy the contents of one breakpoint to another. */
+
+static struct breakpoint *
+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 = xcalloc (1, sizeof (*dest_raw));
+ dest_raw->raw_type = src->raw->raw_type;
+ dest_raw->refcount = src->raw->refcount;
+ dest_raw->pc = src->raw->pc;
+ dest_raw->size = src->raw->size;
+ memcpy (dest_raw->old_data, src->raw->old_data, MAX_BREAKPOINT_LEN);
+ dest_raw->inserted = src->raw->inserted;
+
+ /* Clone the high-level breakpoint. */
+ dest = xcalloc (1, sizeof (*dest));
+ 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)
+ {
+ new_cond = xcalloc (1, sizeof (*new_cond));
+ new_cond->cond = clone_agent_expr (current_cond->cond);
+ APPEND_TO_LIST (&dest->cond_list, new_cond, cond_tail);
+ }
+
+ /* Clone the command list. */
+ for (current_cmd = src->command_list; current_cmd != NULL;
+ current_cmd = current_cmd->next)
+ {
+ new_cmd = xcalloc (1, sizeof (*new_cmd));
+ 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);
+ }
+
+ return dest;
+}
+
+/* Create a new breakpoint list NEW_LIST that is a copy of the
+ list starting at SRC_LIST. Create the corresponding new
+ raw_breakpoint list NEW_RAW_LIST as well. */
+
+void
+clone_all_breakpoints (struct breakpoint **new_list,
+ struct raw_breakpoint **new_raw_list,
+ const struct breakpoint *src_list)
+{
+ const struct breakpoint *bp;
+ struct breakpoint *new_bkpt;
+ struct breakpoint *bkpt_tail = NULL;
+ struct raw_breakpoint *raw_bkpt_tail = NULL;
+
+ for (bp = src_list; bp != NULL; bp = bp->next)
+ {
+ new_bkpt = clone_one_breakpoint (bp);
+ APPEND_TO_LIST (new_list, new_bkpt, bkpt_tail);
+ APPEND_TO_LIST (new_raw_list, new_bkpt->raw, raw_bkpt_tail);
+ }
+}
diff --git a/gdb/gdbserver/mem-break.h b/gdb/gdbserver/mem-break.h
index 8b010c1..b5a3208 100644
--- a/gdb/gdbserver/mem-break.h
+++ b/gdb/gdbserver/mem-break.h
@@ -253,4 +253,10 @@ int insert_memory_breakpoint (struct raw_breakpoint *bp);
int remove_memory_breakpoint (struct raw_breakpoint *bp);
+/* Create a new breakpoint list NEW_BKPT_LIST that is a copy of SRC. */
+
+void clone_all_breakpoints (struct breakpoint **new_bkpt_list,
+ struct raw_breakpoint **new_raw_bkpt_list,
+ const struct breakpoint *src);
+
#endif /* MEM_BREAK_H */