@@ -110,6 +110,8 @@ class aarch64_linux_nat_target final
/* Write allocation tags to memory via PTRACE. */
bool store_memtags (CORE_ADDR address, size_t len,
const gdb::byte_vector &tags, int type) override;
+ /* Check if an address is tagged. */
+ bool check_memtag_addr (CORE_ADDR address) override;
};
static aarch64_linux_nat_target the_aarch64_linux_nat_target;
@@ -1071,6 +1073,12 @@ aarch64_linux_nat_target::store_memtags (CORE_ADDR address, size_t len,
return false;
}
+bool
+aarch64_linux_nat_target::check_memtag_addr (CORE_ADDR address)
+{
+ return gdbarch_tagged_address_p (current_inferior ()->arch (), address);
+}
+
void _initialize_aarch64_linux_nat ();
void
_initialize_aarch64_linux_nat ()
@@ -2451,17 +2451,15 @@ aarch64_mte_get_atag (CORE_ADDR address)
/* Implement the tagged_address_p gdbarch method. */
static bool
-aarch64_linux_tagged_address_p (struct gdbarch *gdbarch, struct value *address)
+aarch64_linux_tagged_address_p (struct gdbarch *gdbarch, CORE_ADDR address)
{
- gdb_assert (address != nullptr);
-
- CORE_ADDR addr = value_as_address (address);
+ gdb_assert (address);
/* Remove the top byte for the memory range check. */
- addr = gdbarch_remove_non_address_bits (gdbarch, addr);
+ address = gdbarch_remove_non_address_bits (gdbarch, address);
/* Check if the page that contains ADDRESS is mapped with PROT_MTE. */
- if (!linux_address_in_memtag_page (addr))
+ if (!linux_address_in_memtag_page (address))
return false;
/* We have a valid tag in the top byte of the 64-bit address. */
@@ -102,7 +102,7 @@ default_memtag_to_string (struct gdbarch *gdbarch, struct value *tag)
/* See arch-utils.h */
bool
-default_tagged_address_p (struct gdbarch *gdbarch, struct value *address)
+default_tagged_address_p (struct gdbarch *gdbarch, CORE_ADDR address)
{
/* By default, assume the address is untagged. */
return false;
@@ -141,7 +141,7 @@ extern std::string default_memtag_to_string (struct gdbarch *gdbarch,
struct value *tag);
/* Default implementation of gdbarch_tagged_address_p. */
-bool default_tagged_address_p (struct gdbarch *gdbarch, struct value *address);
+bool default_tagged_address_p (struct gdbarch *gdbarch, CORE_ADDR address);
/* Default implementation of gdbarch_memtag_matches_p. */
extern bool default_memtag_matches_p (struct gdbarch *gdbarch,
@@ -109,6 +109,8 @@ class core_target final : public process_stratum_target
bool fetch_memtags (CORE_ADDR address, size_t len,
gdb::byte_vector &tags, int type) override;
+ bool check_memtag_addr (CORE_ADDR address) override;
+
x86_xsave_layout fetch_x86_xsave_layout () override;
/* A few helpers. */
@@ -1410,6 +1412,12 @@ core_target::fetch_memtags (CORE_ADDR address, size_t len,
return false;
}
+bool
+core_target::check_memtag_addr (CORE_ADDR address)
+{
+ return gdbarch_tagged_address_p (current_inferior ()->arch (), address);
+}
+
/* Implementation of the "fetch_x86_xsave_layout" target_ops method. */
x86_xsave_layout
@@ -707,8 +707,8 @@ extern void set_gdbarch_memtag_to_string (struct gdbarch *gdbarch, gdbarch_memta
/* 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);
+typedef bool (gdbarch_tagged_address_p_ftype) (struct gdbarch *gdbarch, CORE_ADDR address);
+extern bool gdbarch_tagged_address_p (struct gdbarch *gdbarch, CORE_ADDR address);
extern void set_gdbarch_tagged_address_p (struct gdbarch *gdbarch, gdbarch_tagged_address_p_ftype *tagged_address_p);
/* Return true if the tag from ADDRESS matches the memory tag for that
@@ -3232,7 +3232,7 @@ set_gdbarch_memtag_to_string (struct gdbarch *gdbarch,
}
bool
-gdbarch_tagged_address_p (struct gdbarch *gdbarch, struct value *address)
+gdbarch_tagged_address_p (struct gdbarch *gdbarch, CORE_ADDR address)
{
gdb_assert (gdbarch != NULL);
gdb_assert (gdbarch->tagged_address_p != NULL);
@@ -1267,7 +1267,7 @@ must be either a pointer or a reference type.
""",
type="bool",
name="tagged_address_p",
- params=[("struct value *", "address")],
+ params=[("CORE_ADDR", "address")],
predefault="default_tagged_address_p",
invalid=False,
)
@@ -1132,7 +1132,7 @@ do_examine (struct format_data fmt, struct gdbarch *gdbarch, CORE_ADDR addr)
= value_from_ulongest (builtin_type (gdbarch)->builtin_data_ptr,
tag_laddr);
- if (gdbarch_tagged_address_p (current_inferior ()->arch (), v_addr))
+ if (target_check_memtag_addr (value_as_address(v_addr)))
{
/* Fetch the allocation tag. */
struct value *tag
@@ -1289,7 +1289,7 @@ should_validate_memtags (struct value *value)
return false;
/* We do. Check whether it includes any tags. */
- return gdbarch_tagged_address_p (current_inferior ()->arch (), value);
+ return target_check_memtag_addr (value_as_address(value));
}
/* Helper for parsing arguments for print_command_1. */
@@ -2946,9 +2946,10 @@ memory_tag_print_tag_command (const char *args, enum memtag_type tag_type)
flag, it is no use trying to access/manipulate its allocation tag.
It is OK to manipulate the logical tag though. */
+ CORE_ADDR addr = value_as_address(val);
if (tag_type == memtag_type::allocation
- && !gdbarch_tagged_address_p (arch, val))
- show_addr_not_tagged (value_as_address (val));
+ && !target_check_memtag_addr(addr))
+ show_addr_not_tagged (addr);
value *tag_value = gdbarch_get_memtag (arch, val, tag_type);
std::string tag = gdbarch_memtag_to_string (arch, tag_value);
@@ -3104,8 +3105,9 @@ parse_set_allocation_tag_input (const char *args, struct value **val,
/* If the address is not in a region memory mapped with a memory tagging
flag, it is no use trying to access/manipulate its allocation tag. */
- if (!gdbarch_tagged_address_p (current_inferior ()->arch (), *val))
- show_addr_not_tagged (value_as_address (*val));
+ CORE_ADDR addr = value_as_address (*val);
+ if (!target_check_memtag_addr (addr))
+ show_addr_not_tagged (addr);
}
/* Implement the "memory-tag set-allocation-tag" command.
@@ -3129,8 +3131,9 @@ memory_tag_set_allocation_tag_command (const char *args, int from_tty)
/* If the address is not in a region memory mapped with a memory tagging
flag, it is no use trying to manipulate its allocation tag. */
- if (!gdbarch_tagged_address_p (current_inferior ()->arch (), val)) {
- show_addr_not_tagged (value_as_address(val));
+ CORE_ADDR addr = value_as_address (val);
+ if (!target_check_memtag_addr (addr)) {
+ show_addr_not_tagged (addr);
}
if (!gdbarch_set_memtags (current_inferior ()->arch (), val, length, tags,
@@ -3158,12 +3161,12 @@ memory_tag_check_command (const char *args, int from_tty)
struct value *val = process_print_command_args (args, &print_opts, true);
gdbarch *arch = current_inferior ()->arch ();
+ CORE_ADDR addr = value_as_address (val);
+
/* If the address is not in a region memory mapped with a memory tagging
flag, it is no use trying to access/manipulate its allocation tag. */
- if (!gdbarch_tagged_address_p (arch, val))
- show_addr_not_tagged (value_as_address (val));
-
- CORE_ADDR addr = value_as_address (val);
+ if (!target_check_memtag_addr (addr))
+ show_addr_not_tagged (addr);
/* Check if the tag is valid. */
if (!gdbarch_memtag_matches_p (arch, val))
@@ -337,6 +337,9 @@ enum {
packets and the tag violation stop replies. */
PACKET_memory_tagging_feature,
+ /* Support checking if an address is tagged via qMemTagAddrCheck packet. */
+ PACKET_memory_tagging_check_addr_feature,
+
PACKET_MAX
};
@@ -758,6 +761,10 @@ struct remote_features
bool remote_memory_tagging_p () const
{ return packet_support (PACKET_memory_tagging_feature) == PACKET_ENABLE; }
+ bool remote_memory_tagging_check_addr_p () const
+ { return packet_support (PACKET_memory_tagging_check_addr_feature) ==
+ PACKET_ENABLE; }
+
/* Reset all packets back to "unknown support". Called when opening a
new connection to a remote target. */
void reset_all_packet_configs_support ();
@@ -1084,6 +1091,8 @@ class remote_target : public process_stratum_target
bool store_memtags (CORE_ADDR address, size_t len,
const gdb::byte_vector &tags, int type) override;
+ bool check_memtag_addr (CORE_ADDR address) override;
+
public: /* Remote specific methods. */
void remote_download_command_source (int num, ULONGEST addr,
@@ -5762,6 +5771,8 @@ static const struct protocol_feature remote_protocol_features[] = {
{ "no-resumed", PACKET_DISABLE, remote_supported_packet, PACKET_no_resumed },
{ "memory-tagging", PACKET_DISABLE, remote_supported_packet,
PACKET_memory_tagging_feature },
+ { "memory-tagging-check-addr", PACKET_DISABLE, remote_supported_packet,
+ PACKET_memory_tagging_check_addr_feature },
};
static char *remote_support_xml;
@@ -5873,6 +5884,10 @@ remote_target::remote_query_supported ()
!= AUTO_BOOLEAN_FALSE)
remote_query_supported_append (&q, "memory-tagging+");
+ if (m_features.packet_set_cmd_state (PACKET_memory_tagging_check_addr_feature)
+ != AUTO_BOOLEAN_FALSE)
+ remote_query_supported_append (&q, "memory-tagging-check-addr+");
+
/* Keep this one last to work around a gdbserver <= 7.10 bug in
the qSupported:xmlRegisters=i386 handling. */
if (remote_support_xml != NULL
@@ -15532,6 +15547,19 @@ create_store_memtags_request (gdb::char_vector &packet, CORE_ADDR address,
strcpy (packet.data (), request.c_str ());
}
+static void
+create_check_memtag_addr_request (gdb::char_vector &packet, CORE_ADDR address)
+{
+ int addr_size = gdbarch_addr_bit (current_inferior ()->arch()) / 8;
+
+ std::string request = string_printf ("qMemTagAddrCheck:%s", phex_nz (address, addr_size));
+
+ if (packet.size () < request.length ())
+ error (_("Contents too big for packet qMemTagAddrCheck."));
+
+ strcpy (packet.data (), request.c_str ());
+}
+
/* Implement the "fetch_memtags" target_ops method. */
bool
@@ -15573,6 +15601,36 @@ remote_target::store_memtags (CORE_ADDR address, size_t len,
return packet_check_result (rs->buf).status () == PACKET_OK;
}
+bool
+remote_target::check_memtag_addr (CORE_ADDR address)
+{
+ struct remote_state *rs = get_remote_state ();
+
+ if (!m_features.remote_memory_tagging_check_addr_p ())
+ /* Fallback to reading /proc/<PID>/smaps for checking if an address is
+ tagged or not. */
+ return gdbarch_tagged_address_p (current_inferior ()->arch (), address);
+
+ create_check_memtag_addr_request (rs->buf, address);
+
+ putpkt (rs->buf);
+ getpkt (&rs->buf);
+
+ /* Check if reply is OK. */
+ if ((packet_check_result (rs->buf.data ()) != PACKET_OK) || rs->buf.empty())
+ return false;
+
+ gdb_byte tagged_addr;
+ /* Convert only 2 hex digits, i.e. 1 byte in hex format. */
+ hex2bin(rs->buf.data(), &tagged_addr , 1);
+ if (tagged_addr)
+ /* 01 means address is tagged. */
+ return true;
+ else
+ /* 00 means address is not tagged. */
+ return false;
+}
+
/* Return true if remote target T is non-stop. */
bool
@@ -16056,6 +16114,10 @@ Show the maximum size of the address (in bits) in a memory packet."), NULL,
add_packet_config_cmd (PACKET_memory_tagging_feature,
"memory-tagging-feature", "memory-tagging-feature", 0);
+ add_packet_config_cmd (PACKET_memory_tagging_check_addr_feature,
+ "memory-tagging-check-addr-feature",
+ "memory-tagging-check-addr-feature", 0);
+
/* Assert that we've registered "set remote foo-packet" commands
for all packet configs. */
{
@@ -197,6 +197,7 @@ struct dummy_target : public target_ops
bool supports_memory_tagging () override;
bool fetch_memtags (CORE_ADDR arg0, size_t arg1, gdb::byte_vector &arg2, int arg3) override;
bool store_memtags (CORE_ADDR arg0, size_t arg1, const gdb::byte_vector &arg2, int arg3) override;
+ bool check_memtag_addr (CORE_ADDR arg0) override;
x86_xsave_layout fetch_x86_xsave_layout () override;
};
@@ -373,6 +374,7 @@ struct debug_target : public target_ops
bool supports_memory_tagging () override;
bool fetch_memtags (CORE_ADDR arg0, size_t arg1, gdb::byte_vector &arg2, int arg3) override;
bool store_memtags (CORE_ADDR arg0, size_t arg1, const gdb::byte_vector &arg2, int arg3) override;
+ bool check_memtag_addr (CORE_ADDR arg0) override;
x86_xsave_layout fetch_x86_xsave_layout () override;
};
@@ -4562,6 +4564,32 @@ debug_target::store_memtags (CORE_ADDR arg0, size_t arg1, const gdb::byte_vector
return result;
}
+bool
+target_ops::check_memtag_addr (CORE_ADDR arg0)
+{
+ return this->beneath ()->check_memtag_addr (arg0);
+}
+
+bool
+dummy_target::check_memtag_addr (CORE_ADDR arg0)
+{
+ tcomplain ();
+}
+
+bool
+debug_target::check_memtag_addr (CORE_ADDR arg0)
+{
+ gdb_printf (gdb_stdlog, "-> %s->check_memtag_addr (...)\n", this->beneath ()->shortname ());
+ bool result
+ = this->beneath ()->check_memtag_addr (arg0);
+ gdb_printf (gdb_stdlog, "<- %s->check_memtag_addr (", this->beneath ()->shortname ());
+ target_debug_print_CORE_ADDR (arg0);
+ gdb_puts (") = ", gdb_stdlog);
+ target_debug_print_bool (result);
+ gdb_puts ("\n", gdb_stdlog);
+ return result;
+}
+
x86_xsave_layout
target_ops::fetch_x86_xsave_layout ()
{
@@ -796,6 +796,12 @@ target_store_memtags (CORE_ADDR address, size_t len,
return current_inferior ()->top_target ()->store_memtags (address, len, tags, type);
}
+bool
+target_check_memtag_addr (CORE_ADDR address)
+{
+ return current_inferior ()->top_target ()->check_memtag_addr (address);
+}
+
x86_xsave_layout
target_fetch_x86_xsave_layout ()
{
@@ -1334,6 +1334,10 @@ struct target_ops
const gdb::byte_vector &tags, int type)
TARGET_DEFAULT_NORETURN (tcomplain ());
+ /* Returns true if ADDRESS is tagged, otherwise returns false. */
+ virtual bool check_memtag_addr (CORE_ADDR address)
+ TARGET_DEFAULT_NORETURN (tcomplain ());
+
/* Return the x86 XSAVE extended state area layout. */
virtual x86_xsave_layout fetch_x86_xsave_layout ()
TARGET_DEFAULT_RETURN (x86_xsave_layout ());
@@ -2317,6 +2321,8 @@ extern bool target_fetch_memtags (CORE_ADDR address, size_t len,
extern bool target_store_memtags (CORE_ADDR address, size_t len,
const gdb::byte_vector &tags, int type);
+extern bool target_check_memtag_addr (CORE_ADDR address);
+
extern x86_xsave_layout target_fetch_x86_xsave_layout ();
/* Command logging facility. */