summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohn Baldwin <jhb@FreeBSD.org>2022-10-11 16:21:58 -0700
committerJohn Baldwin <jhb@FreeBSD.org>2022-10-13 11:25:32 -0700
commite8662fc9c8b8b8ce6643af3576a8c8b6c2fe1918 (patch)
tree906067917836ce3a073bf56d4fda6d58aaf9087b
parent2be1bc103fab216d2188f89628f84e688f5c9b14 (diff)
downloadbinutils-gdb-e8662fc9c8b8b8ce6643af3576a8c8b6c2fe1918.tar.gz
CHERI-RISC-V: Add basic hybrid and purecap support.
-rw-r--r--gdb/riscv-tdep.c89
1 files changed, 86 insertions, 3 deletions
diff --git a/gdb/riscv-tdep.c b/gdb/riscv-tdep.c
index 822e18b651f..49f6fe8cb8c 100644
--- a/gdb/riscv-tdep.c
+++ b/gdb/riscv-tdep.c
@@ -3684,6 +3684,64 @@ riscv_dwarf_reg_to_regnum (struct gdbarch *gdbarch, int reg)
return -1;
}
+static CORE_ADDR
+riscv_cheri_pointer_to_address (struct gdbarch *gdbarch, struct type *type,
+ const gdb_byte *buf)
+{
+ enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
+ int xlen = riscv_isa_xlen (gdbarch);
+
+ if (type->length <= xlen)
+ {
+ if (type->is_unsigned ())
+ return unsigned_pointer_to_address (gdbarch, type, buf);
+ else
+ return signed_pointer_to_address (gdbarch, type, buf);
+ }
+ else
+ {
+ if (type->is_unsigned ())
+ return extract_unsigned_integer (buf, xlen, byte_order);
+ else
+ return extract_signed_integer (buf, xlen, byte_order);
+ }
+}
+
+/* XXX: This does not generate a valid capability. However, a
+ round-trip that converts an address to a pointer back to an address
+ will work with this implementation. */
+
+static void
+riscv_cheri_address_to_pointer (struct gdbarch *gdbarch, struct type *type,
+ gdb_byte *buf, CORE_ADDR addr)
+{
+ enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
+ int xlen = riscv_isa_xlen (gdbarch);
+
+ if (type->length <= xlen)
+ {
+ if (type->is_unsigned ())
+ unsigned_address_to_pointer (gdbarch, type, buf, addr);
+ else
+ address_to_signed_pointer (gdbarch, type, buf, addr);
+ }
+ else
+ {
+ memset (buf, 0, type->length);
+ if (type->is_unsigned ())
+ store_unsigned_integer (buf, xlen, byte_order, addr);
+ else
+ store_signed_integer (buf, xlen, byte_order, addr);
+ }
+}
+
+static CORE_ADDR
+riscv_cheri_integer_to_address (struct gdbarch *gdbarch,
+ struct type *type, const gdb_byte *buf)
+{
+ return riscv_cheri_pointer_to_address (gdbarch, type, buf);
+}
+
/* Implement the gcc_target_options method. We have to select the arch and abi
from the feature info. We have enough feature info to select the abi, but
not enough info for the arch given all of the possible architecture
@@ -3929,7 +3987,16 @@ riscv_gdbarch_init (struct gdbarch_info info,
set_gdbarch_double_bit (gdbarch, 64);
set_gdbarch_long_double_bit (gdbarch, 128);
set_gdbarch_long_double_format (gdbarch, floatformats_ia64_quad);
- set_gdbarch_ptr_bit (gdbarch, riscv_isa_xlen (gdbarch) * 8);
+ if (riscv_has_cheri (gdbarch))
+ set_gdbarch_capability_bit (gdbarch, riscv_isa_clen (gdbarch) * 8);
+ if (riscv_has_cheriabi (gdbarch))
+ {
+ set_gdbarch_ptr_bit (gdbarch, riscv_abi_clen (gdbarch) * 8);
+ set_gdbarch_addr_bit (gdbarch, riscv_isa_xlen (gdbarch) * 8);
+ set_gdbarch_dwarf2_addr_size (gdbarch, riscv_isa_xlen (gdbarch));
+ }
+ else
+ set_gdbarch_ptr_bit (gdbarch, riscv_isa_xlen (gdbarch) * 8);
set_gdbarch_char_signed (gdbarch, 0);
set_gdbarch_type_align (gdbarch, riscv_type_align);
@@ -3957,6 +4024,14 @@ riscv_gdbarch_init (struct gdbarch_info info,
/* Register architecture. */
riscv_add_reggroups (gdbarch);
+ /* Settings for CHERI processors. */
+ if (riscv_has_cheri (gdbarch))
+ {
+ set_gdbarch_pointer_to_address (gdbarch, riscv_cheri_pointer_to_address);
+ set_gdbarch_address_to_pointer (gdbarch, riscv_cheri_address_to_pointer);
+ set_gdbarch_integer_to_address (gdbarch, riscv_cheri_integer_to_address);
+ }
+
/* Internal <-> external register number maps. */
set_gdbarch_dwarf2_reg_to_regnum (gdbarch, riscv_dwarf_reg_to_regnum);
@@ -3972,8 +4047,16 @@ riscv_gdbarch_init (struct gdbarch_info info,
set_gdbarch_num_pseudo_regs (gdbarch, 0);
/* Some specific register numbers GDB likes to know about. */
- set_gdbarch_sp_regnum (gdbarch, RISCV_SP_REGNUM);
- set_gdbarch_pc_regnum (gdbarch, RISCV_PC_REGNUM);
+ if (riscv_has_cheriabi (gdbarch))
+ {
+ set_gdbarch_sp_regnum (gdbarch, RISCV_CSP_REGNUM);
+ set_gdbarch_pc_regnum (gdbarch, RISCV_PCC_REGNUM);
+ }
+ else
+ {
+ set_gdbarch_sp_regnum (gdbarch, RISCV_SP_REGNUM);
+ set_gdbarch_pc_regnum (gdbarch, RISCV_PC_REGNUM);
+ }
set_gdbarch_print_registers_info (gdbarch, riscv_print_registers_info);