aboutsummaryrefslogtreecommitdiff
path: root/gdb/nat
diff options
context:
space:
mode:
authorYao Qi <yao.qi@linaro.org>2015-10-15 15:05:10 +0100
committerYao Qi <yao.qi@linaro.org>2015-10-15 15:05:10 +0100
commit8d689ee570e7c4c61231b919d5b6a34c20414c43 (patch)
treea59fd53387fcfe5b81d4a89e52b6f4441cbd1f08 /gdb/nat
parent21c40443ce8b12faa085149ba8a30b33193f6cc7 (diff)
downloadgdb-8d689ee570e7c4c61231b919d5b6a34c20414c43.zip
gdb-8d689ee570e7c4c61231b919d5b6a34c20414c43.tar.gz
gdb-8d689ee570e7c4c61231b919d5b6a34c20414c43.tar.bz2
aarch64 multi-arch part 6: HW breakpoint on unaligned address
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-15 Yao Qi <yao.qi@linaro.org> * aarch64-linux-nat.c (aarch64_linux_insert_hw_breakpoint): Call gdbarch_breakpoint_from_pc to instruction length. (aarch64_linux_remove_hw_breakpoint): Likewise. * common/common-regcache.h (regcache_register_size): Declare. * nat/aarch64-linux-hw-point.c: Include "common-regcache.h". (aarch64_point_is_aligned): Set alignment to 2 for breakpoint if the process is 32bit, otherwise set alignment to 4. (aarch64_handle_breakpoint): Update comments. * regcache.c (regcache_register_size): New function. gdb/gdbserver: 2015-10-15 Yao Qi <yao.qi@linaro.org> * linux-aarch64-low.c (aarch64_insert_point): Set len to 2 if it is 3. (aarch64_remove_point): Likewise. * regcache.c (regcache_register_size): New function.
Diffstat (limited to 'gdb/nat')
-rw-r--r--gdb/nat/aarch64-linux-hw-point.c22
1 files changed, 19 insertions, 3 deletions
diff --git a/gdb/nat/aarch64-linux-hw-point.c b/gdb/nat/aarch64-linux-hw-point.c
index bca6ec1..1a5fa6a 100644
--- a/gdb/nat/aarch64-linux-hw-point.c
+++ b/gdb/nat/aarch64-linux-hw-point.c
@@ -18,6 +18,7 @@
#include "common-defs.h"
#include "break-common.h"
+#include "common-regcache.h"
#include "nat/linux-nat.h"
#include "aarch64-linux-hw-point.h"
@@ -112,8 +113,23 @@ 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
+ {
+ struct regcache *regcache
+ = get_thread_regcache_for_ptid (current_lwp_ptid ());
+
+ /* 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. */
+ if (regcache_register_size (regcache, 0) == 8)
+ alignment = AARCH64_HBP_ALIGNMENT;
+ else
+ alignment = 2;
+ }
if (addr & (alignment - 1))
return 0;
@@ -445,7 +461,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;