gdb: Add qIsAddressTagged packet

This commit adds a new packet, qIsAddressTagged, allowing GDB remote
targets to use it to query the stub if a given address is tagged.

Currently, the memory tagging address check is done via a read query,
where the contents of /proc/<PID>/smaps is read and the flags are
inspected for memory tagging-related flags that indicate the address is
in a memory tagged region.

This is not ideal, for example, for QEMU stub and other cases, such as
on bare-metal, where there is no notion of an OS file like 'smaps.'
Hence, the introduction of qIsAddressTagged packet allows checking
if an address is tagged in an agnostic way.

The is_address_tagged target hook in remote.c attempts to use the
qIsAddressTagged packet first for checking if an address is tagged and
if the stub does not support such a packet (reply is empty) it falls
back to using the current mechanism that reads the contents of
/proc/<PID>/smaps via vFile requests.

Signed-off-by: Gustavo Romero <gustavo.romero@linaro.org>
Approved-By: Luis Machado <luis.machado@arm.com>
Tested-By: Luis Machado <luis.machado@arm.com>
This commit is contained in:
Gustavo Romero
2024-04-18 20:10:37 +00:00
committed by Luis Machado
parent 7202f41f5f
commit c040e0b107

View File

@@ -337,6 +337,9 @@ enum {
packets and the tag violation stop replies. */
PACKET_memory_tagging_feature,
/* Support for the qIsAddressTagged packet. */
PACKET_qIsAddressTagged,
PACKET_MAX
};
@@ -15535,6 +15538,50 @@ create_store_memtags_request (gdb::char_vector &packet, CORE_ADDR address,
strcpy (packet.data (), request.c_str ());
}
static void
create_is_address_tagged_request (gdbarch *gdbarch, gdb::char_vector &packet,
CORE_ADDR address)
{
int addr_size;
std::string request;
addr_size = gdbarch_addr_bit (gdbarch) / 8;
request = string_printf ("qIsAddressTagged:%s", phex_nz (address, addr_size));
if (packet.size () < request.length () + 1)
error (_("Contents too big for packet qIsAddressTagged."));
strcpy (packet.data (), request.c_str ());
}
static bool
check_is_address_tagged_reply (remote_target *remote, gdb::char_vector &packet,
bool &tagged)
{
gdb_assert (remote != nullptr);
/* Check reply and disable qIsAddressTagged usage if it's not supported. */
packet_result result = remote->m_features.packet_ok (packet,
PACKET_qIsAddressTagged);
/* Return false on error (Exx), empty reply (packet not supported), or reply
size doesn't match 2 hex digits. */
if ((result.status () != PACKET_OK) || (strlen (packet.data ()) != 2))
return false;
gdb_byte reply;
/* Convert only 2 hex digits, i.e. 1 byte in hex format. */
hex2bin (packet.data (), &reply, 1);
if (reply == 0x00 || reply == 0x01)
{
tagged = !!reply;
return true;
}
/* Invalid reply. */
return false;
}
/* Implement the "fetch_memtags" target_ops method. */
bool
@@ -15581,6 +15628,31 @@ remote_target::store_memtags (CORE_ADDR address, size_t len,
bool
remote_target::is_address_tagged (gdbarch *gdbarch, CORE_ADDR address)
{
/* Firstly, attempt to check the address using the qIsAddressTagged
packet. */
if (m_features.packet_support (PACKET_qIsAddressTagged) != PACKET_DISABLE)
{
remote_target *remote = get_current_remote_target ();
struct remote_state *rs = get_remote_state ();
bool is_addr_tagged;
create_is_address_tagged_request (gdbarch, rs->buf, address);
putpkt (rs->buf);
getpkt (&rs->buf);
/* If qIsAddressTagged is not supported PACKET_qIsAddressTagged will be
set to PACKET_DISABLE so no further attempt is made to check addresses
using this packet and the fallback mechanism below will be used
instead. Also, if the check fails due to an error (Exx reply) the
fallback is used too. Otherwise, the qIsAddressTagged query succeeded
and is_addr_tagged is valid. */
if (check_is_address_tagged_reply (remote, rs->buf, is_addr_tagged))
return is_addr_tagged;
}
/* Fallback to arch-specific method of checking whether an address is tagged
in case check via qIsAddressTagged fails. */
return gdbarch_tagged_address_p (gdbarch, address);
}
@@ -16070,6 +16142,9 @@ 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_qIsAddressTagged,
"qIsAddressTagged", "memory-tagging-address-check", 0);
/* Assert that we've registered "set remote foo-packet" commands
for all packet configs. */
{