diff --git a/gdb/gdbarch.h b/gdb/gdbarch.h index ece765b826f..7db3e36d76a 100644 --- a/gdb/gdbarch.h +++ b/gdb/gdbarch.h @@ -730,7 +730,8 @@ typedef std::string (gdbarch_memtag_to_string_ftype) (struct gdbarch *gdbarch, s extern std::string gdbarch_memtag_to_string (struct gdbarch *gdbarch, struct value *tag); extern void set_gdbarch_memtag_to_string (struct gdbarch *gdbarch, gdbarch_memtag_to_string_ftype *memtag_to_string); -/* Return true if ADDRESS contains a tag and false otherwise. */ +/* Return true if ADDRESS contains a tag and false otherwise. ADDRESS + must be either a pointer or a reference type. */ typedef bool (gdbarch_tagged_address_p_ftype) (struct gdbarch *gdbarch, struct value *address); extern bool gdbarch_tagged_address_p (struct gdbarch *gdbarch, struct value *address); diff --git a/gdb/gdbarch.sh b/gdb/gdbarch.sh index d9332c2103e..9bc9de91c30 100755 --- a/gdb/gdbarch.sh +++ b/gdb/gdbarch.sh @@ -608,7 +608,8 @@ v;int;significant_addr_bit;;;;;;0 # Return a string representation of the memory tag TAG. m;std::string;memtag_to_string;struct value *tag;tag;;default_memtag_to_string;;0 -# Return true if ADDRESS contains a tag and false otherwise. +# Return true if ADDRESS contains a tag and false otherwise. ADDRESS +# must be either a pointer or a reference type. m;bool;tagged_address_p;struct value *address;address;;default_tagged_address_p;;0 # Return true if the tag from ADDRESS matches the memory tag for that diff --git a/gdb/printcmd.c b/gdb/printcmd.c index 3cd42f817f5..416b87c69c6 100644 --- a/gdb/printcmd.c +++ b/gdb/printcmd.c @@ -1266,19 +1266,26 @@ print_value (value *val, const value_print_options &opts) static bool should_validate_memtags (struct value *value) { - if (target_supports_memory_tagging () - && gdbarch_tagged_address_p (target_gdbarch (), value)) - { - gdb_assert (value != nullptr && value_type (value) != nullptr); + gdb_assert (value != nullptr && value_type (value) != nullptr); - enum type_code code = value_type (value)->code (); + if (!target_supports_memory_tagging ()) + return false; - return (code == TYPE_CODE_PTR - || code == TYPE_CODE_REF - || code == TYPE_CODE_METHODPTR - || code == TYPE_CODE_MEMBERPTR); - } - return false; + enum type_code code = value_type (value)->code (); + + /* Skip non-address values. */ + if (code != TYPE_CODE_PTR + && !TYPE_IS_REFERENCE (value_type (value))) + return false; + + /* OK, we have an address value. Check we have a complete value we + can extract. */ + if (value_optimized_out (value) + || !value_entirely_available (value)) + return false; + + /* We do. Check whether it includes any tags. */ + return gdbarch_tagged_address_p (target_gdbarch (), value); } /* Helper for parsing arguments for print_command_1. */ @@ -1321,26 +1328,42 @@ print_command_1 (const char *args, int voidprint) value_type (val)->code () != TYPE_CODE_VOID)) { /* If memory tagging validation is on, check if the tag is valid. */ - if (print_opts.memory_tag_violations && should_validate_memtags (val) - && !gdbarch_memtag_matches_p (target_gdbarch (), val)) + if (print_opts.memory_tag_violations) { - /* Fetch the logical tag. */ - struct value *tag - = gdbarch_get_memtag (target_gdbarch (), val, - memtag_type::logical); - std::string ltag - = gdbarch_memtag_to_string (target_gdbarch (), tag); + try + { + if (should_validate_memtags (val) + && !gdbarch_memtag_matches_p (target_gdbarch (), val)) + { + /* Fetch the logical tag. */ + struct value *tag + = gdbarch_get_memtag (target_gdbarch (), val, + memtag_type::logical); + std::string ltag + = gdbarch_memtag_to_string (target_gdbarch (), tag); - /* Fetch the allocation tag. */ - tag = gdbarch_get_memtag (target_gdbarch (), val, - memtag_type::allocation); - std::string atag - = gdbarch_memtag_to_string (target_gdbarch (), tag); + /* Fetch the allocation tag. */ + tag = gdbarch_get_memtag (target_gdbarch (), val, + memtag_type::allocation); + std::string atag + = gdbarch_memtag_to_string (target_gdbarch (), tag); - printf_filtered (_("Logical tag (%s) does not match the " - "allocation tag (%s).\n"), - ltag.c_str (), atag.c_str ()); + printf_filtered (_("Logical tag (%s) does not match the " + "allocation tag (%s).\n"), + ltag.c_str (), atag.c_str ()); + } + } + catch (gdb_exception_error &ex) + { + if (ex.error == TARGET_CLOSE_ERROR) + throw; + + fprintf_filtered (gdb_stderr, + _("Could not validate memory tag: %s\n"), + ex.message->c_str ()); + } } + print_value (val, print_opts); } }