From 3ba2ee38a648b7f52e77700325b26137f6332fe2 Mon Sep 17 00:00:00 2001 From: Jim Wilson Date: Thu, 1 Nov 2018 17:25:15 -0700 Subject: [PATCH] RISC-V: Don't allow unaligned breakpoints. Some hardware doesn't support unaligned accesses, and a bare metal target may not have an unaligned access trap handler. So if the PC is 2-byte aligned, then use a 2-byte breakpoint to avoid unaligned accesses. Tested on native RV64GC Linux with gdb testsuite and cross on spike simulator and openocd with riscv-tests/debug. gdb/ * riscv-tdep.c (riscv_breakpoint_kind_from_pc): New local unaligned_p. Set if pcptr if unaligned. Return 2 if unaligned_p true. Update debugging messages. --- gdb/ChangeLog | 6 ++++++ gdb/riscv-tdep.c | 32 ++++++++++++++++++++++++-------- 2 files changed, 30 insertions(+), 8 deletions(-) diff --git a/gdb/ChangeLog b/gdb/ChangeLog index a3271cccc0..8e40537aaf 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,9 @@ +2018-11-01 Jim Wilson + + * riscv-tdep.c (riscv_breakpoint_kind_from_pc): New local unaligned_p. + Set if pcptr if unaligned. Return 2 if unaligned_p true. Update + debugging messages. + 2018-11-01 Joel Brobecker * ada-lang.c (ada_watch_location_expression): New function. diff --git a/gdb/riscv-tdep.c b/gdb/riscv-tdep.c index 4b5f38a877..db372e2163 100644 --- a/gdb/riscv-tdep.c +++ b/gdb/riscv-tdep.c @@ -415,18 +415,34 @@ riscv_breakpoint_kind_from_pc (struct gdbarch *gdbarch, CORE_ADDR *pcptr) { if (use_compressed_breakpoints == AUTO_BOOLEAN_AUTO) { + bool unaligned_p = false; gdb_byte buf[1]; - /* Read the opcode byte to determine the instruction length. */ - read_code (*pcptr, buf, 1); + /* Some targets don't support unaligned reads. The address can only + be unaligned if the C extension is supported. So it is safe to + use a compressed breakpoint in this case. */ + if (*pcptr & 0x2) + unaligned_p = true; + else + { + /* Read the opcode byte to determine the instruction length. */ + read_code (*pcptr, buf, 1); + } if (riscv_debug_breakpoints) - fprintf_unfiltered - (gdb_stdlog, - "Using %s for breakpoint at %s (instruction length %d)\n", - riscv_insn_length (buf[0]) == 2 ? "C.EBREAK" : "EBREAK", - paddress (gdbarch, *pcptr), riscv_insn_length (buf[0])); - if (riscv_insn_length (buf[0]) == 2) + { + const char *bp = (unaligned_p || riscv_insn_length (buf[0]) == 2 + ? "C.EBREAK" : "EBREAK"); + + fprintf_unfiltered (gdb_stdlog, "Using %s for breakpoint at %s ", + bp, paddress (gdbarch, *pcptr)); + if (unaligned_p) + fprintf_unfiltered (gdb_stdlog, "(unaligned address)\n"); + else + fprintf_unfiltered (gdb_stdlog, "(instruction length %d)\n", + riscv_insn_length (buf[0])); + } + if (unaligned_p || riscv_insn_length (buf[0]) == 2) return 2; else return 4;