From patchwork Tue Oct 13 10:11:00 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Yao Qi X-Patchwork-Id: 9073 Received: (qmail 97537 invoked by alias); 13 Oct 2015 10:11:22 -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 97416 invoked by uid 89); 13 Oct 2015 10:11:20 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-2.2 required=5.0 tests=AWL, BAYES_00, FREEMAIL_FROM, RCVD_IN_DNSWL_LOW, SPF_PASS autolearn=ham version=3.3.2 X-HELO: mail-pa0-f54.google.com Received: from mail-pa0-f54.google.com (HELO mail-pa0-f54.google.com) (209.85.220.54) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with (AES128-GCM-SHA256 encrypted) ESMTPS; Tue, 13 Oct 2015 10:11:13 +0000 Received: by pacex6 with SMTP id ex6so17338969pac.3 for ; Tue, 13 Oct 2015 03:11:11 -0700 (PDT) X-Received: by 10.68.104.66 with SMTP id gc2mr39204106pbb.21.1444731071029; Tue, 13 Oct 2015 03:11:11 -0700 (PDT) Received: from E107787-LIN.cambridge.arm.com (power-aix.osuosl.org. [140.211.15.154]) by smtp.gmail.com with ESMTPSA id gd2sm2952317pbb.41.2015.10.13.03.11.09 for (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Tue, 13 Oct 2015 03:11:10 -0700 (PDT) From: Yao Qi X-Google-Original-From: Yao Qi To: gdb-patches@sourceware.org Subject: [PATCH] aarch64 multi-arch part 6: HW breakpoint on unaligned address Date: Tue, 13 Oct 2015 11:11:00 +0100 Message-Id: <1444731060-16237-1-git-send-email-yao.qi@linaro.org> X-IsSubscribed: yes Nowadays, both aarch64 GDB and linux kernel assumes that address for setting breakpoint should be 4-byte aligned. However that is not true after we support multi-arch, because thumb instruction can be at 2-byte aligned address. Patch http://lists.infradead.org/pipermail/linux-arm-kernel/2015-October/375141.html to linux kernel is to teach kernel to handle 2-byte aligned address for HW breakpoint, while this patch is to teach aarch64 GDB handle 2-byte aligned address. First of all, we call gdbarch_breakpoint_from_pc to get the instruction length rather than using hard-coded 4. Secondly, in GDBserver, we set length back to 2 if it is 3, because GDB encode 3 in it to indicate it is a 32-bit thumb breakpoint. Then we relax the address alignment check from 4-byte aligned to 2-byte aligned. This patch enables some tests (such as gdb.base/break-idempotent.exp, gdb.base/cond-eval-mode.exp, gdb.base/watchpoint-reuse-slot.exp,) and fixes many fails (such as gdb.base/hbreak2.exp) when the program is compiled in thumb mode on aarch64. Regression tested on aarch64-linux, both native and gdbserver. This is the last patch of multi-arch work. gdb: 2015-10-13 Yao Qi * aarch64-linux-nat.c (aarch64_linux_insert_hw_breakpoint): Call gdbarch_breakpoint_from_pc to instruction length. (aarch64_linux_remove_hw_breakpoint): Likewise. * nat/aarch64-linux-hw-point.c (aarch64_point_is_aligned): Set alignment to 2 for breakpoint. (aarch64_handle_breakpoint): Update comments. gdb/gdbserver: 2015-10-13 Yao Qi * linux-aarch64-low.c (aarch64_insert_point): Set len to 2 if it is 3. (aarch64_remove_point): Likewise. --- gdb/aarch64-linux-nat.c | 8 ++++++-- gdb/gdbserver/linux-aarch64-low.c | 18 ++++++++++++------ gdb/nat/aarch64-linux-hw-point.c | 15 ++++++++++++--- 3 files changed, 30 insertions(+), 11 deletions(-) diff --git a/gdb/aarch64-linux-nat.c b/gdb/aarch64-linux-nat.c index c9f439f..4d3d55a 100644 --- a/gdb/aarch64-linux-nat.c +++ b/gdb/aarch64-linux-nat.c @@ -608,11 +608,13 @@ aarch64_linux_insert_hw_breakpoint (struct target_ops *self, { int ret; CORE_ADDR addr = bp_tgt->placed_address = bp_tgt->reqstd_address; - const int len = 4; + int len; const enum target_hw_bp_type type = hw_execute; struct aarch64_debug_reg_state *state = aarch64_get_debug_reg_state (ptid_get_pid (inferior_ptid)); + gdbarch_breakpoint_from_pc (gdbarch, &addr, &len); + if (show_debug_regs) fprintf_unfiltered (gdb_stdlog, @@ -640,11 +642,13 @@ aarch64_linux_remove_hw_breakpoint (struct target_ops *self, { int ret; CORE_ADDR addr = bp_tgt->placed_address; - const int len = 4; + int len = 4; const enum target_hw_bp_type type = hw_execute; struct aarch64_debug_reg_state *state = aarch64_get_debug_reg_state (ptid_get_pid (inferior_ptid)); + gdbarch_breakpoint_from_pc (gdbarch, &addr, &len); + if (show_debug_regs) fprintf_unfiltered (gdb_stdlog, "remove_hw_breakpoint on entry (addr=0x%08lx, len=%d))\n", diff --git a/gdb/gdbserver/linux-aarch64-low.c b/gdb/gdbserver/linux-aarch64-low.c index 9cefdda..f1ea5a4 100644 --- a/gdb/gdbserver/linux-aarch64-low.c +++ b/gdb/gdbserver/linux-aarch64-low.c @@ -315,9 +315,12 @@ aarch64_insert_point (enum raw_bkpt_type type, CORE_ADDR addr, ret = -1; } else - ret = - aarch64_handle_breakpoint (targ_type, addr, len, 1 /* is_insert */, - state); + { + if (len == 3) + len = 2; + ret = aarch64_handle_breakpoint (targ_type, addr, len, + 1 /* is_insert */, state); + } if (show_debug_regs) aarch64_show_debug_reg_state (state, "insert_point", addr, len, @@ -353,9 +356,12 @@ aarch64_remove_point (enum raw_bkpt_type type, CORE_ADDR addr, aarch64_handle_watchpoint (targ_type, addr, len, 0 /* is_insert */, state); else - ret = - aarch64_handle_breakpoint (targ_type, addr, len, 0 /* is_insert */, - state); + { + if (len == 3) + len = 2; + ret = aarch64_handle_breakpoint (targ_type, addr, len, + 0 /* is_insert */, state); + } if (show_debug_regs) aarch64_show_debug_reg_state (state, "remove_point", addr, len, diff --git a/gdb/nat/aarch64-linux-hw-point.c b/gdb/nat/aarch64-linux-hw-point.c index bca6ec1..d15e518 100644 --- a/gdb/nat/aarch64-linux-hw-point.c +++ b/gdb/nat/aarch64-linux-hw-point.c @@ -112,8 +112,17 @@ aarch64_point_encode_ctrl_reg (enum target_hw_bp_type type, int len) static int aarch64_point_is_aligned (int is_watchpoint, CORE_ADDR addr, int len) { - unsigned int alignment = is_watchpoint ? AARCH64_HWP_ALIGNMENT - : AARCH64_HBP_ALIGNMENT; + unsigned int alignment = 0; + + if (is_watchpoint) + alignment = AARCH64_HWP_ALIGNMENT; + else + { + /* Set alignment to 2 only if the current process is 32-bit, + since thumb instruction can be 2-byte aligned. Otherwise, set + alignment to AARCH64_HBP_ALIGNMENT. */ + alignment = 2; + } if (addr & (alignment - 1)) return 0; @@ -445,7 +454,7 @@ aarch64_handle_breakpoint (enum target_hw_bp_type type, CORE_ADDR addr, struct aarch64_debug_reg_state *state) { /* The hardware breakpoint on AArch64 should always be 4-byte - aligned. */ + aligned, but on AArch32, it can be 2-byte aligned. */ if (!aarch64_point_is_aligned (0 /* is_watchpoint */ , addr, len)) return -1;