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.
This commit is contained in:
Jim Wilson 2018-11-01 17:25:15 -07:00
parent c175004a53
commit 3ba2ee38a6
2 changed files with 30 additions and 8 deletions

View File

@ -1,3 +1,9 @@
2018-11-01 Jim Wilson <jimw@sifive.com>
* 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 <brobecker@adacore.com>
* ada-lang.c (ada_watch_location_expression): New function.

View File

@ -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;