aboutsummaryrefslogtreecommitdiff
path: root/gdb/arch
diff options
context:
space:
mode:
Diffstat (limited to 'gdb/arch')
-rw-r--r--gdb/arch/aarch64-mte-linux.c56
-rw-r--r--gdb/arch/aarch64-mte-linux.h10
2 files changed, 66 insertions, 0 deletions
diff --git a/gdb/arch/aarch64-mte-linux.c b/gdb/arch/aarch64-mte-linux.c
index fc7a8cc..3af6f36 100644
--- a/gdb/arch/aarch64-mte-linux.c
+++ b/gdb/arch/aarch64-mte-linux.c
@@ -21,6 +21,62 @@
/* See arch/aarch64-mte-linux.h */
+void
+aarch64_mte_pack_tags (gdb::byte_vector &tags)
+{
+ /* Nothing to pack? */
+ if (tags.empty ())
+ return;
+
+ /* If the tags vector has an odd number of elements, add another
+ zeroed-out element to make it even. This facilitates packing. */
+ if ((tags.size () % 2) != 0)
+ tags.emplace_back (0);
+
+ for (int unpacked = 0, packed = 0; unpacked < tags.size ();
+ unpacked += 2, packed++)
+ tags[packed] = (tags[unpacked + 1] << 4) | tags[unpacked];
+
+ /* Now we have half the size. */
+ tags.resize (tags.size () / 2);
+}
+
+/* See arch/aarch64-mte-linux.h */
+
+void
+aarch64_mte_unpack_tags (gdb::byte_vector &tags, bool skip_first)
+{
+ /* Nothing to unpack? */
+ if (tags.empty ())
+ return;
+
+ /* An unpacked MTE tags vector will have twice the number of elements
+ compared to an unpacked one. */
+ gdb::byte_vector unpacked_tags (tags.size () * 2);
+
+ int unpacked = 0, packed = 0;
+
+ if (skip_first)
+ {
+ /* We are not interested in the first unpacked element, just discard
+ it. */
+ unpacked_tags[unpacked] = (tags[packed] >> 4) & 0xf;
+ unpacked++;
+ packed++;
+ }
+
+ for (; packed < tags.size (); unpacked += 2, packed++)
+ {
+ unpacked_tags[unpacked] = tags[packed] & 0xf;
+ unpacked_tags[unpacked + 1] = (tags[packed] >> 4) & 0xf;
+ }
+
+ /* Update the original tags vector. */
+ tags = std::move (unpacked_tags);
+}
+
+/* See arch/aarch64-mte-linux.h */
+
size_t
aarch64_mte_get_tag_granules (CORE_ADDR addr, size_t len, size_t granule_size)
{
diff --git a/gdb/arch/aarch64-mte-linux.h b/gdb/arch/aarch64-mte-linux.h
index fed91bb..0771ef7 100644
--- a/gdb/arch/aarch64-mte-linux.h
+++ b/gdb/arch/aarch64-mte-linux.h
@@ -32,6 +32,7 @@
/* We have one tag per 16 bytes of memory. */
#define AARCH64_MTE_GRANULE_SIZE 16
+#define AARCH64_MTE_TAG_BIT_SIZE 4
#define AARCH64_MTE_LOGICAL_TAG_START_BIT 56
#define AARCH64_MTE_LOGICAL_MAX_VALUE 0xf
@@ -71,4 +72,13 @@ extern CORE_ADDR aarch64_mte_set_ltag (CORE_ADDR address, CORE_ADDR tag);
It is always possible to get the logical tag. */
extern CORE_ADDR aarch64_mte_get_ltag (CORE_ADDR address);
+/* Given a TAGS vector containing 1 MTE tag per byte, pack the data as
+ 2 tags per byte and resize the vector. */
+extern void aarch64_mte_pack_tags (gdb::byte_vector &tags);
+
+/* Given a TAGS vector containing 2 MTE tags per byte, unpack the data as
+ 1 tag per byte and resize the vector. If SKIP_FIRST is TRUE, skip the
+ first unpacked element. Otherwise leave it in the unpacked vector. */
+extern void aarch64_mte_unpack_tags (gdb::byte_vector &tags, bool skip_first);
+
#endif /* ARCH_AARCH64_MTE_LINUX_H */