From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 121948 invoked by alias); 18 Sep 2015 12:03:09 -0000 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 Received: (qmail 121865 invoked by uid 89); 18 Sep 2015 12:03:09 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-1.6 required=5.0 tests=AWL,BAYES_00,SPF_PASS autolearn=ham version=3.3.2 X-HELO: usevmg20.ericsson.net Received: from usevmg20.ericsson.net (HELO usevmg20.ericsson.net) (198.24.6.45) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with (AES256-SHA encrypted) ESMTPS; Fri, 18 Sep 2015 12:02:58 +0000 Received: from EUSAAHC004.ericsson.se (Unknown_Domain [147.117.188.84]) by usevmg20.ericsson.net (Symantec Mail Security) with SMTP id 9F.48.32596.38E9BF55; Fri, 18 Sep 2015 07:17:56 +0200 (CEST) Received: from elxa4wqvvz1.dyn.mo.ca.am.ericsson.se (147.117.188.8) by smtps-am.internal.ericsson.com (147.117.188.84) with Microsoft SMTP Server (TLS) id 14.3.248.2; Fri, 18 Sep 2015 08:02:47 -0400 From: Antoine Tremblay To: CC: Antoine Tremblay Subject: [PATCH 4/5] Handle breakpoint kinds for software breakpoints in GDBServer. Date: Fri, 18 Sep 2015 12:03:00 -0000 Message-ID: <1442577749-6650-5-git-send-email-antoine.tremblay@ericsson.com> In-Reply-To: <1442577749-6650-1-git-send-email-antoine.tremblay@ericsson.com> References: <1442577749-6650-1-git-send-email-antoine.tremblay@ericsson.com> MIME-Version: 1.0 Content-Type: text/plain X-IsSubscribed: yes X-SW-Source: 2015-09/txt/msg00450.txt.bz2 In order to enable software breakpoints kinds, GDBServer needs to make use of the kind parameter sent by the Z0 packet. Using this kind parameter, GDBServer is able to write the right breakpoint by asking the new operation called breakpoint_from_length to return the breakpoint data for a specific kind. Also, GDBServer always needs to handle that the software breakpoint size as it can be coded as a kind field and thus always decode this to the real length of the breakpoint when doing memory operations on the breakpoint using check_breakpoint_from_length. No regressions, tested on ubuntu 14.04 ARMv7 and x86. With gdbserver-{native,extended} / { -marm -mthumb } gdb/gdbserver/ChangeLog: * linux-low.c (linux_breakpoint_from_length): New function. * linux-low.h: Add breakpoint_from_length operation. * mem-break.c (check_breakpoint_from_length): New function. (insert_memory_breakpoint): Call check_breakpoint_from_length. (remove_memory_breakpoint): Likewise. (validate_inserted_breakpoint): Call check_breakpoint_from_length. (check_mem_read): Likewise. (check_mem_write): Likewise. * target.h (struct target_ops): Add breakpoint_from_length operation. --- gdb/gdbserver/linux-low.c | 12 +++++++++ gdb/gdbserver/linux-low.h | 4 +++ gdb/gdbserver/mem-break.c | 68 ++++++++++++++++++++++++++++++++++++++++------- gdb/gdbserver/target.h | 4 +++ 4 files changed, 78 insertions(+), 10 deletions(-) diff --git a/gdb/gdbserver/linux-low.c b/gdb/gdbserver/linux-low.c index 06387a0..8e8b7c0 100644 --- a/gdb/gdbserver/linux-low.c +++ b/gdb/gdbserver/linux-low.c @@ -5965,6 +5965,17 @@ linux_supports_range_stepping (void) return (*the_low_target.supports_range_stepping) (); } +static const unsigned char* +linux_breakpoint_from_length (int *len) +{ + if (*the_low_target.breakpoint_from_length != NULL) + { + return (*the_low_target.breakpoint_from_length) (len); + } + else + return NULL; + +} /* Enumerate spufs IDs for process PID. */ static int spu_enumerate_spu_ids (long pid, unsigned char *buf, CORE_ADDR offset, int len) @@ -7042,6 +7053,7 @@ static struct target_ops linux_target_ops = { linux_mntns_unlink, linux_mntns_readlink, linux_breakpoint_from_pc, + linux_breakpoint_from_length }; static void diff --git a/gdb/gdbserver/linux-low.h b/gdb/gdbserver/linux-low.h index c623150..bb56584 100644 --- a/gdb/gdbserver/linux-low.h +++ b/gdb/gdbserver/linux-low.h @@ -228,6 +228,10 @@ struct linux_target_ops /* Returns true if the low target supports range stepping. */ int (*supports_range_stepping) (void); + + /* Returns the proper breakpoint from size, the length can have target + specific meaning like the z0 kind parameter */ + const unsigned char *(*breakpoint_from_length) (int *length); }; extern struct linux_target_ops the_low_target; diff --git a/gdb/gdbserver/mem-break.c b/gdb/gdbserver/mem-break.c index 68e14c3..dca228c 100644 --- a/gdb/gdbserver/mem-break.c +++ b/gdb/gdbserver/mem-break.c @@ -295,6 +295,38 @@ find_raw_breakpoint_at (CORE_ADDR addr, enum raw_bkpt_type type, int size) return NULL; } +/* Check if if we can insert the breakpoint of size, try to resolve the real + breakpoint size from an architecture specific encoded size if needed. */ + +static int +check_breakpoint_from_length (struct raw_breakpoint *bp, + const unsigned char **breakpoint_data, + int *breakpoint_len) +{ + /* If the architecture treats the size field of Z packets as a + 'kind' field, then we'll need to be able to know which is the + breakpoint instruction too. */ + if (bp->size != *breakpoint_len) + { + /* Get the arch dependent breakpoint */ + if (*the_target->breakpoint_from_length != NULL) + { + /* Update magic coded size to the right size if needed. */ + int size = bp->size; + *breakpoint_data = + (*the_target->breakpoint_from_length) (&size); + *breakpoint_len = size; + } + else { + if (debug_threads) + debug_printf ("Don't know breakpoints of size %d.\n", + bp->size); + return -1; + } + } + + return 1; +} /* See mem-break.h. */ int @@ -312,16 +344,9 @@ insert_memory_breakpoint (struct raw_breakpoint *bp) if (breakpoint_data == NULL) return 1; - /* If the architecture treats the size field of Z packets as a - 'kind' field, then we'll need to be able to know which is the - breakpoint instruction too. */ - if (bp->size != breakpoint_len) - { - if (debug_threads) - debug_printf ("Don't know how to insert breakpoints of size %d.\n", - bp->size); - return -1; - } + if ((err = check_breakpoint_from_length (bp, &breakpoint_data, + &breakpoint_len)) < 0) + return err; /* Note that there can be fast tracepoint jumps installed in the same memory range, so to get at the original memory, we need to @@ -356,6 +381,7 @@ int remove_memory_breakpoint (struct raw_breakpoint *bp) { unsigned char buf[MAX_BREAKPOINT_LEN]; + const unsigned char* breakpoint_data; int err; int breakpoint_len; CORE_ADDR pc; @@ -363,6 +389,10 @@ remove_memory_breakpoint (struct raw_breakpoint *bp) pc = bp->pcfull; the_target->breakpoint_from_pc (&pc, &breakpoint_len); + if ((err = check_breakpoint_from_length (bp, &breakpoint_data, + &breakpoint_len)) < 0) + return err; + /* Since there can be trap breakpoints inserted in the same address range, we use `write_inferior_memory', which takes care of layering breakpoints on top of fast tracepoints, and on top of @@ -1693,6 +1723,14 @@ validate_inserted_breakpoint (struct raw_breakpoint *bp) breakpoint_data = the_target->breakpoint_from_pc (&raw_pc, &breakpoint_len); + if ((err = check_breakpoint_from_length (bp, &breakpoint_data, + &breakpoint_len)) < 0) + { + /* Tag it as gone. */ + bp->inserted = -1; + return 0; + } + gdb_assert (bp->inserted); gdb_assert (bp->raw_type == raw_bkpt_type_sw); @@ -1791,11 +1829,16 @@ check_mem_read (CORE_ADDR mem_addr, unsigned char *buf, int mem_len) { int breakpoint_len; CORE_ADDR raw_pc; + const unsigned char* breakpoint_data; CORE_ADDR bp_end, start, end; int copy_offset, copy_len, buf_offset; raw_pc = bp->pcfull; + the_target->breakpoint_from_pc (&raw_pc, &breakpoint_len); + check_breakpoint_from_length (bp, &breakpoint_data, + &breakpoint_len); + bp_end = bp->pc + breakpoint_len; if (bp->raw_type != raw_bkpt_type_sw) @@ -1890,8 +1933,13 @@ check_mem_write (CORE_ADDR mem_addr, unsigned char *buf, int copy_offset, copy_len, buf_offset; raw_pc = bp->pcfull; + breakpoint_data = the_target->breakpoint_from_pc (&raw_pc, &breakpoint_len); + + check_breakpoint_from_length (bp, &breakpoint_data, + &breakpoint_len); + bp_end = bp->pc + breakpoint_len; if (bp->raw_type != raw_bkpt_type_sw) diff --git a/gdb/gdbserver/target.h b/gdb/gdbserver/target.h index 603819e..bf4c3c7 100644 --- a/gdb/gdbserver/target.h +++ b/gdb/gdbserver/target.h @@ -446,6 +446,10 @@ struct target_ops can be NULL, the default breakpoint for the target should be returned in this case. */ const unsigned char *(*breakpoint_from_pc) (CORE_ADDR *pcptr, int *lenptr); + + /* Returns a breakpoint from a length, the length can have target specific + meaning like the z0 kind parameter. */ + const unsigned char *(*breakpoint_from_length) (int *len); }; extern struct target_ops *the_target; -- 1.9.1