From ddd1b56a1dcec42f549b140dfeee394c93599072 Mon Sep 17 00:00:00 2001 From: John Baldwin Date: Thu, 13 Oct 2022 17:58:00 -0700 Subject: [PATCH] CHERI-RISC-V: Improve handling of hybrid binaries. - Add CHERI to the RISC-V ISA features if an ELF file contains the "xcheri" attribute. This is set in both hybrid and purecap ELF files. This isn't needed for purecap ELF files but does enable capability types and the "__capability" keyword on hybrid binaries and libraries. - Add address_class gdbarch methods so that capability pointer types are tagged as capabilities in hybrid binaries. This is a bit gross. Ideally riscv_address_class_type_flags would only enable the TYPE_INSTANCE_FLAG_CAPABILITY if the passed in byte_size (from DW_ATTR_byte_size) was equal to riscv_isa_clen() (aka gdbarch_capability_bit()). However, for some reason this gdbarch method doesn't take the gdbarch member. For now, rely on the fact that it is only called if either there is a DW_ATTR_address_space attribute on a pointer, or if the byte_size doesn't match the default pointer size. Assuming there is no DW_ATTR_address_space defined for RISC-V yet, this means it should only be called for a size mismatch, and since we don't allow creating integer pointers in purecap, this means it can only be called for capability pointers for hybrid binaries. --- gdb/riscv-tdep.c | 75 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 75 insertions(+) diff --git a/gdb/riscv-tdep.c b/gdb/riscv-tdep.c index de59adc69a1..404cd72bb1c 100644 --- a/gdb/riscv-tdep.c +++ b/gdb/riscv-tdep.c @@ -3623,6 +3623,31 @@ riscv_features_from_bfd (const bfd *abfd) return features; } +/* Returns true if a bfd contains any references to CHERI via the + attributes section. This is true both for hybrid and purecap ELF + objects. */ + +static bool +riscv_bfd_has_cheri (bfd *abfd) +{ + if (abfd != nullptr && bfd_get_flavour (abfd) == bfd_target_elf_flavour) + { + const struct elf_backend_data *ebd = get_elf_backend_data (abfd); + if (ebd != nullptr) + { + const char *sec_name = ebd->obj_attrs_section; + if (bfd_get_section_by_name (abfd, sec_name) != nullptr) + { + obj_attribute *attr = elf_known_obj_attributes_proc (abfd); + + if (strstr(attr[Tag_RISCV_arch].s, "xcheri") != nullptr) + return true; + } + } + } + return false; +} + /* Find a suitable default target description. Use the contents of INFO, specifically the bfd object being executed, to guide the selection of a suitable default target description. */ @@ -3641,6 +3666,10 @@ riscv_find_default_target_description (const struct gdbarch_info info) if (features.xlen == 0) features.xlen = info.bfd_arch_info->bits_per_word == 32 ? 4 : 8; + /* Check for a CHERI hybrid binary. */ + if (features.clen == 0 && riscv_bfd_has_cheri (info.abfd)) + features.clen = features.xlen * 2; + /* Now build a target description based on the feature set. */ return riscv_lookup_target_description (features); } @@ -3688,6 +3717,46 @@ riscv_dwarf_reg_to_regnum (struct gdbarch *gdbarch, int reg) return -1; } +/* Implementation of `address_class_type_flags' gdbarch method. */ + +static type_instance_flags +riscv_address_class_type_flags (int byte_size, int dwarf2_addr_class) +{ + /* XXX: This should be conditional on byte_size == riscv_isa_clen (). */ + return TYPE_INSTANCE_FLAG_CAPABILITY; +} + +/* Implementation of `address_class_type_flags_to_name' gdbarch method. + + Convert a type_instance_flag_value to an address space qualifier. */ + +static const char* +riscv_address_class_type_flags_to_name (struct gdbarch *gdbarch, + type_instance_flags type_flags) +{ + /* No need to display the extra __capability modifier. GDB already takes + cares of this. */ + return NULL; +} + +/* Implementation of `address_class_name_to_type_flags' gdbarch method. + + Convert an address space qualifier to a type_instance_flag_value. */ + +static bool +riscv_address_class_name_to_type_flags (struct gdbarch *gdbarch, + const char* name, + type_instance_flags *type_flags_ptr) +{ + if (strcmp (name, "__capability") == 0) + { + *type_flags_ptr = TYPE_INSTANCE_FLAG_CAPABILITY; + return true; + } + else + return false; +} + static CORE_ADDR riscv_cheri_pointer_to_address (struct gdbarch *gdbarch, struct type *type, const gdb_byte *buf) @@ -4212,6 +4281,12 @@ riscv_gdbarch_init (struct gdbarch_info info, /* Settings for CHERI processors. */ if (riscv_has_cheri (gdbarch)) { + set_gdbarch_address_class_type_flags (gdbarch, + riscv_address_class_type_flags); + set_gdbarch_address_class_name_to_type_flags + (gdbarch, riscv_address_class_name_to_type_flags); + set_gdbarch_address_class_type_flags_to_name + (gdbarch, riscv_address_class_type_flags_to_name); 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); -- 2.47.2