Mirror of the gdb-patches mailing list
 help / color / mirror / Atom feed
From: Luis Machado via Gdb-patches <gdb-patches@sourceware.org>
To: gdb-patches@sourceware.org
Subject: [PATCH v5 15/25] AArch64: Implement the memory tagging gdbarch hooks
Date: Wed, 27 Jan 2021 17:21:02 -0300	[thread overview]
Message-ID: <20210127202112.2485702-16-luis.machado@linaro.org> (raw)
In-Reply-To: <20210127202112.2485702-1-luis.machado@linaro.org>

Updates on v4:

- Update function names to be more scoped.
- Use of gdb::optional values.
- Fixed up gdbarch hooks.

Updates on v2:

- Update target methods to contain a tag type parameter.

--

This patch implements the memory tagging gdbarch hooks for AArch64, for
the MTE feature.

gdb/ChangeLog:

YYYY-MM-DD  Luis Machado  <luis.machado@linaro.org>

	* aarch64-linux-tdep.c: Include target.h, arch-utils.h, value.h.
	(aarch64_mte_get_atag, aarch64_linux_tagged_address_p)
	(aarch64_linux_memtag_mismatch_p, aarch64_linux_set_memtags)
	(aarch64_linux_get_memtag, aarch64_linux_memtag_to_string): New
	functions.
	(aarch64_linux_init_abi): Initialize MTE-related gdbarch hooks.
	* arch/aarch64-mte-linux.c (aarch64_mte_make_ltag_bits)
	(aarch64_mte_make_ltag, aarch64_linux_set_ltag)
	(aarch64_linux_get_ltag): New functions.
	* arch/aarch64-mte-linux.h (AARCH64_MTE_LOGICAL_TAG_START_BIT)
	(AARCH64_MTE_LOGICAL_MAX_VALUE): Define.
	(aarch64_mte_make_ltag_bits, aarch64_mte_make_ltag)
	(aarch64_mte_set_ltag, aarch64_mte_get_ltag): New prototypes.
---
 gdb/aarch64-linux-tdep.c     | 210 +++++++++++++++++++++++++++++++++++
 gdb/arch/aarch64-mte-linux.c |  41 ++++++-
 gdb/arch/aarch64-mte-linux.h |  19 ++++
 3 files changed, 269 insertions(+), 1 deletion(-)

diff --git a/gdb/aarch64-linux-tdep.c b/gdb/aarch64-linux-tdep.c
index f113d1ea30..2fe88cf016 100644
--- a/gdb/aarch64-linux-tdep.c
+++ b/gdb/aarch64-linux-tdep.c
@@ -30,6 +30,7 @@
 #include "symtab.h"
 #include "tramp-frame.h"
 #include "trad-frame.h"
+#include "target.h"
 #include "target/target.h"
 
 #include "regcache.h"
@@ -46,6 +47,9 @@
 
 #include "arch/aarch64-mte-linux.h"
 
+#include "arch-utils.h"
+#include "value.h"
+
 /* Signal frame handling.
 
       +------------+  ^
@@ -1513,6 +1517,187 @@ aarch64_linux_gcc_target_options (struct gdbarch *gdbarch)
   return {};
 }
 
+/* Helper to get the allocation tag from a 64-bit ADDRESS.
+
+   Return the allocation tag if successful and nullopt otherwise.  */
+
+static gdb::optional<CORE_ADDR>
+aarch64_mte_get_atag (CORE_ADDR address)
+{
+  gdb::byte_vector tags;
+
+  /* Attempt to fetch the allocation tag.  */
+  if (!target_fetch_memtags (address, 0, tags, tag_allocation))
+    return {};
+
+  /* Only one tag should've been returned.  Make sure we got exactly that.  */
+  gdb_assert (tags.size () == 1);
+
+  /* Although our tags are 4 bits in size, they are stored in a
+     byte.  */
+  return tags[0];
+}
+
+/* Implement the tagged_address_p gdbarch method.  */
+
+static bool
+aarch64_linux_tagged_address_p (struct gdbarch *gdbarch, struct value *address)
+{
+  gdb_assert (address != nullptr);
+
+  CORE_ADDR addr = value_as_address (address);
+
+  /* Remove the top byte for the memory range check.  */
+  addr = address_significant (gdbarch, addr);
+
+  /* Check if the page that contains ADDRESS is mapped with PROT_MTE.  */
+  if (!linux_address_in_memtag_page (addr))
+    return false;
+
+  /* We have a valid tag in the top byte of the 64-bit address.  */
+  return true;
+}
+
+/* Implement the memtag_matches_p gdbarch method.  */
+
+static bool
+aarch64_linux_memtag_matches_p (struct gdbarch *gdbarch,
+				struct value *address)
+{
+  gdb_assert (address != nullptr);
+
+  /* Make sure we are dealing with a tagged address to begin with.  */
+  if (!aarch64_linux_tagged_address_p (gdbarch, address))
+    return true;
+
+  CORE_ADDR addr = value_as_address (address);
+
+  /* Fetch the allocation tag for ADDRESS.  */
+  gdb::optional<CORE_ADDR> atag = aarch64_mte_get_atag (addr);
+
+  if (!atag.has_value ())
+    return true;
+
+  /* Fetch the logical tag for ADDRESS.  */
+  gdb_byte ltag = aarch64_mte_get_ltag (addr);
+
+  /* Are the tags the same?  */
+  return ltag == *atag;
+}
+
+/* Implement the set_memtags gdbarch method.  */
+
+static bool
+aarch64_linux_set_memtags (struct gdbarch *gdbarch, struct value *address,
+			   size_t length, const gdb::byte_vector &tags,
+			   enum memtag_type tag_type)
+{
+  if (tags.empty ())
+    return true;
+
+  gdb_assert (address != nullptr);
+
+  CORE_ADDR addr = value_as_address (address);
+
+  /* Set the logical tag or the allocation tag.  */
+  if (tag_type == tag_logical)
+    {
+      /* When setting logical tags, we don't care about the length, since
+	 we are only setting a single logical tag.  */
+      addr = aarch64_mte_set_ltag (addr, tags[0]);
+
+      /* Update the value's content with the tag.  */
+      enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
+      gdb_byte *srcbuf = value_contents_raw (address);
+      store_unsigned_integer (srcbuf, sizeof (addr), byte_order, addr);
+    }
+  else
+    {
+      /* Make sure we are dealing with a tagged address to begin with.  */
+      if (!aarch64_linux_tagged_address_p (gdbarch, address))
+	return false;
+
+      /* With G being the number of tag granules and N the number of tags
+	 passed in, we can have the following cases:
+
+	 1 - G == N: Store all the N tags to memory.
+
+	 2 - G < N : Warn about having more tags than granules, but write G
+		     tags.
+
+	 3 - G > N : This is a "fill tags" operation.  We should use the tags
+		     as a pattern to fill the granules repeatedly until we have
+		     written G tags to memory.
+      */
+
+      size_t g = aarch64_mte_get_tag_granules (addr, length,
+					       AARCH64_MTE_GRANULE_SIZE);
+      size_t n = tags.size ();
+
+      if (g < n)
+	warning (_("Got more tags than memory granules.  Tags will be "
+		   "truncated."));
+      else if (g > n)
+	warning (_("Using tag pattern to fill memory range."));
+
+      if (!target_store_memtags (addr, length, tags, tag_allocation))
+	return false;
+    }
+  return true;
+}
+
+/* Implement the get_memtag gdbarch method.  */
+
+static struct value *
+aarch64_linux_get_memtag (struct gdbarch *gdbarch, struct value *address,
+			  enum memtag_type tag_type)
+{
+  gdb_assert (address != nullptr);
+
+  CORE_ADDR addr = value_as_address (address);
+  CORE_ADDR tag = 0;
+
+  /* Get the logical tag or the allocation tag.  */
+  if (tag_type == tag_logical)
+    tag = aarch64_mte_get_ltag (addr);
+  else
+    {
+      /* Make sure we are dealing with a tagged address to begin with.  */
+      if (!aarch64_linux_tagged_address_p (gdbarch, address))
+	return nullptr;
+
+      gdb::optional<CORE_ADDR> atag = aarch64_mte_get_atag (addr);
+
+      if (!atag.has_value ())
+	return nullptr;
+
+      tag = *atag;
+    }
+
+  /* Convert the tag to a value.  */
+  return value_from_ulongest (builtin_type (gdbarch)->builtin_unsigned_int,
+			      tag);
+}
+
+/* Implement the memtag_to_string gdbarch method.  */
+
+static std::string
+aarch64_linux_memtag_to_string (struct gdbarch *gdbarch,
+				struct value *address,
+				enum memtag_type tag_type)
+{
+  gdb_assert (address != nullptr);
+
+  struct value *v_tag = aarch64_linux_get_memtag (gdbarch, address, tag_type);
+
+  if (v_tag == nullptr && tag_allocation)
+    error (_("Error getting tag from target"));
+
+  CORE_ADDR tag = value_as_address (v_tag);
+
+  return string_printf ("0x%s", phex_nz (tag, sizeof (tag)));
+}
+
 static void
 aarch64_linux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
 {
@@ -1570,6 +1755,31 @@ aarch64_linux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
      data associated with the address.  */
   set_gdbarch_significant_addr_bit (gdbarch, 56);
 
+  /* MTE-specific settings and hooks.  */
+  if (tdep->has_mte ())
+    {
+      /* Register a hook for checking if an address is tagged or not.  */
+      set_gdbarch_tagged_address_p (gdbarch, aarch64_linux_tagged_address_p);
+
+      /* Register a hook for checking if there is a memory tag match.  */
+      set_gdbarch_memtag_matches_p (gdbarch,
+				    aarch64_linux_memtag_matches_p);
+
+      /* Register a hook for setting the logical/allocation tags for
+	 a range of addresses.  */
+      set_gdbarch_set_memtags (gdbarch, aarch64_linux_set_memtags);
+
+      /* Register a hook for extracting the logical/allocation tag from an
+	 address.  */
+      set_gdbarch_get_memtag (gdbarch, aarch64_linux_get_memtag);
+
+      /* Set the allocation tag granule size to 16 bytes.  */
+      set_gdbarch_memtag_granule_size (gdbarch, AARCH64_MTE_GRANULE_SIZE);
+
+      /* Register a hook for converting a memory tag to a string.  */
+      set_gdbarch_memtag_to_string (gdbarch, aarch64_linux_memtag_to_string);
+    }
+
   /* Initialize the aarch64_linux_record_tdep.  */
   /* These values are the size of the type that will be used in a system
      call.  They are obtained from Linux Kernel source.  */
diff --git a/gdb/arch/aarch64-mte-linux.c b/gdb/arch/aarch64-mte-linux.c
index ede5f5f2b9..4461864a32 100644
--- a/gdb/arch/aarch64-mte-linux.c
+++ b/gdb/arch/aarch64-mte-linux.c
@@ -22,7 +22,8 @@
 /* See arch/aarch64-mte-linux.h */
 
 size_t
-aarch64_mte_get_tag_granules (CORE_ADDR addr, size_t len, size_t granule_size)
+aarch64_mte_get_tag_granules (CORE_ADDR addr, size_t len,
+				    size_t granule_size)
 {
   /* Start address */
   CORE_ADDR s_addr = align_down (addr, granule_size);
@@ -32,3 +33,41 @@ aarch64_mte_get_tag_granules (CORE_ADDR addr, size_t len, size_t granule_size)
   /* We always have at least 1 granule.  */
   return 1 + (e_addr - s_addr) / granule_size;
 }
+
+/* See arch/aarch64-mte-linux.h */
+
+CORE_ADDR
+aarch64_mte_make_ltag_bits (CORE_ADDR value)
+{
+  return value & AARCH64_MTE_LOGICAL_MAX_VALUE;
+}
+
+/* See arch/aarch64-mte-linux.h */
+
+CORE_ADDR
+aarch64_mte_make_ltag (CORE_ADDR value)
+{
+  return aarch64_mte_make_ltag_bits (value)
+	 << AARCH64_MTE_LOGICAL_TAG_START_BIT;
+}
+
+/* See arch/aarch64-mte-linux.h */
+
+CORE_ADDR
+aarch64_mte_set_ltag (CORE_ADDR address, CORE_ADDR tag)
+{
+  /* Remove the existing tag.  */
+  address &= ~aarch64_mte_make_ltag (AARCH64_MTE_LOGICAL_MAX_VALUE);
+
+  /* Return the new tagged address.  */
+  return address | aarch64_mte_make_ltag (tag);
+}
+
+/* See arch/aarch64-mte-linux.h */
+
+CORE_ADDR
+aarch64_mte_get_ltag (CORE_ADDR address)
+{
+  CORE_ADDR ltag_addr = address >> AARCH64_MTE_LOGICAL_TAG_START_BIT;
+  return aarch64_mte_make_ltag_bits (ltag_addr);
+}
diff --git a/gdb/arch/aarch64-mte-linux.h b/gdb/arch/aarch64-mte-linux.h
index 108031e08a..d44cae92a6 100644
--- a/gdb/arch/aarch64-mte-linux.h
+++ b/gdb/arch/aarch64-mte-linux.h
@@ -32,6 +32,8 @@
 
 /* We have one tag per 16 bytes of memory.  */
 #define AARCH64_MTE_GRANULE_SIZE 16
+#define AARCH64_MTE_LOGICAL_TAG_START_BIT 56
+#define AARCH64_MTE_LOGICAL_MAX_VALUE 0xf
 
 /* Memory tag types for AArch64.  */
 enum class aarch64_memtag_type
@@ -47,4 +49,21 @@ enum class aarch64_memtag_type
 extern size_t aarch64_mte_get_tag_granules (CORE_ADDR addr, size_t len,
 					    size_t granule_size);
 
+/* Return the 4-bit tag made from VALUE.  */
+extern CORE_ADDR aarch64_mte_make_ltag_bits (CORE_ADDR value);
+
+/* Return the 4-bit tag that can be OR-ed to an address.  */
+extern CORE_ADDR aarch64_mte_make_ltag (CORE_ADDR value);
+
+/* Helper to set the logical TAG for a 64-bit ADDRESS.
+
+   It is always possible to set the logical tag.  */
+extern CORE_ADDR aarch64_mte_set_ltag (CORE_ADDR address,
+					     CORE_ADDR tag);
+
+/* Helper to get the logical tag from a 64-bit ADDRESS.
+
+   It is always possible to get the logical tag.  */
+extern CORE_ADDR aarch64_mte_get_ltag (CORE_ADDR address);
+
 #endif /* ARCH_AARCH64_LINUX_H */
-- 
2.25.1


  parent reply	other threads:[~2021-01-27 20:21 UTC|newest]

Thread overview: 61+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-01-27 20:20 [PATCH v5 00/25] Memory Tagging Support + AArch64 Linux implementation Luis Machado via Gdb-patches
2021-01-27 20:20 ` [PATCH v5 01/25] New target methods for memory tagging support Luis Machado via Gdb-patches
2021-01-27 23:26   ` Lancelot SIX via Gdb-patches
2021-01-28 10:02     ` Luis Machado via Gdb-patches
2021-02-05  2:31   ` Simon Marchi via Gdb-patches
2021-01-27 20:20 ` [PATCH v5 02/25] New gdbarch memory tagging hooks Luis Machado via Gdb-patches
2021-02-05  2:38   ` Simon Marchi via Gdb-patches
2021-02-05  3:58   ` Simon Marchi via Gdb-patches
2021-01-27 20:20 ` [PATCH v5 03/25] Add GDB-side remote target support for memory tagging Luis Machado via Gdb-patches
2021-02-05  2:48   ` Simon Marchi via Gdb-patches
2021-01-27 20:20 ` [PATCH v5 04/25] Unit testing for GDB-side remote memory tagging handling Luis Machado via Gdb-patches
2021-02-05  2:50   ` Simon Marchi via Gdb-patches
2021-01-27 20:20 ` [PATCH v5 05/25] GDBserver remote packet support for memory tagging Luis Machado via Gdb-patches
2021-02-05  2:56   ` Simon Marchi via Gdb-patches
2021-02-05 12:38     ` Luis Machado via Gdb-patches
2021-01-27 20:20 ` [PATCH v5 06/25] Unit tests for gdbserver memory tagging remote packets Luis Machado via Gdb-patches
2021-01-27 20:20 ` [PATCH v5 07/25] Documentation for " Luis Machado via Gdb-patches
2021-01-28  3:30   ` Eli Zaretskii via Gdb-patches
2021-01-28  9:58     ` Luis Machado via Gdb-patches
2021-01-27 20:20 ` [PATCH v5 08/25] AArch64: Add MTE CPU feature check support Luis Machado via Gdb-patches
2021-02-05  3:05   ` Simon Marchi via Gdb-patches
2021-01-27 20:20 ` [PATCH v5 09/25] AArch64: Add target description/feature for MTE registers Luis Machado via Gdb-patches
2021-01-27 20:20 ` [PATCH v5 10/25] AArch64: Add MTE register set support for GDB and gdbserver Luis Machado via Gdb-patches
2021-01-27 20:20 ` [PATCH v5 11/25] AArch64: Add MTE ptrace requests Luis Machado via Gdb-patches
2021-02-05  3:13   ` Simon Marchi via Gdb-patches
2021-01-27 20:20 ` [PATCH v5 12/25] AArch64: Implement memory tagging target methods for AArch64 Luis Machado via Gdb-patches
2021-02-05  3:30   ` Simon Marchi via Gdb-patches
2021-01-27 20:21 ` [PATCH v5 13/25] Convert char array to std::string in linux_find_memory_regions_full Luis Machado via Gdb-patches
2021-02-05  3:32   ` Simon Marchi via Gdb-patches
2021-01-27 20:21 ` [PATCH v5 14/25] Refactor parsing of /proc/<pid>/smaps Luis Machado via Gdb-patches
2021-02-05  3:38   ` Simon Marchi via Gdb-patches
2021-01-27 20:21 ` Luis Machado via Gdb-patches [this message]
2021-02-05  4:09   ` [PATCH v5 15/25] AArch64: Implement the memory tagging gdbarch hooks Simon Marchi via Gdb-patches
2021-02-05 14:05     ` Luis Machado via Gdb-patches
2021-01-27 20:21 ` [PATCH v5 16/25] AArch64: Add unit testing for logical tag set/get operations Luis Machado via Gdb-patches
2021-01-27 20:21 ` [PATCH v5 17/25] AArch64: Report tag violation error information Luis Machado via Gdb-patches
2021-02-05  4:22   ` Simon Marchi via Gdb-patches
2021-02-05 14:59     ` Luis Machado via Gdb-patches
2021-02-05 16:13       ` Simon Marchi via Gdb-patches
2021-01-27 20:21 ` [PATCH v5 18/25] AArch64: Add gdbserver MTE support Luis Machado via Gdb-patches
2021-01-27 20:21 ` [PATCH v5 19/25] AArch64: Add MTE register set support for core files Luis Machado via Gdb-patches
2021-01-27 20:21 ` [PATCH v5 20/25] New memory-tag commands Luis Machado via Gdb-patches
2021-02-05  4:49   ` Simon Marchi via Gdb-patches
2021-02-05  4:52     ` Simon Marchi via Gdb-patches
2021-02-08 18:59     ` Luis Machado via Gdb-patches
2021-03-23 21:46       ` Simon Marchi via Gdb-patches
2021-01-27 20:21 ` [PATCH v5 21/25] Documentation for the new mtag commands Luis Machado via Gdb-patches
2021-01-28  3:31   ` Eli Zaretskii via Gdb-patches
2021-02-05  4:50   ` Simon Marchi via Gdb-patches
2021-01-27 20:21 ` [PATCH v5 22/25] Extend "x" and "print" commands to support memory tagging Luis Machado via Gdb-patches
2021-02-05  5:02   ` Simon Marchi via Gdb-patches
2021-01-27 20:21 ` [PATCH v5 23/25] Document new "x" and "print" memory tagging extensions Luis Machado via Gdb-patches
2021-01-28  3:31   ` Eli Zaretskii via Gdb-patches
2021-02-05  5:04   ` Simon Marchi via Gdb-patches
2021-02-08 20:44     ` Luis Machado via Gdb-patches
2021-01-27 20:21 ` [PATCH v5 24/25] Add NEWS entry Luis Machado via Gdb-patches
2021-01-28  3:32   ` Eli Zaretskii via Gdb-patches
2021-02-05  5:06   ` Simon Marchi via Gdb-patches
2021-02-08 20:44     ` Luis Machado via Gdb-patches
2021-01-27 20:21 ` [PATCH v5 25/25] Add memory tagging testcases Luis Machado via Gdb-patches
2021-02-04 14:18 ` [PING] [PATCH v5 00/25] Memory Tagging Support + AArch64 Linux implementation Luis Machado via Gdb-patches

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20210127202112.2485702-16-luis.machado@linaro.org \
    --to=gdb-patches@sourceware.org \
    --cc=luis.machado@linaro.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox