• R/O
  • HTTP
  • SSH
  • HTTPS

提交

标签
No Tags

Frequently used words (click to add to your profile)

javac++androidlinuxc#windowsobjective-ccocoa誰得qtpythonphprubygameguibathyscaphec計画中(planning stage)翻訳omegatframeworktwitterdomtestvb.netdirectxゲームエンジンbtronarduinopreviewer

GNU Binutils with patches for OS216


Commit MetaInfo

修订版2c7d3af06cfababfde33c8946620c3fe05fded52 (tree)
时间2020-06-16 21:58:32
作者Luis Machado <luis.machado@lina...>
CommiterLuis Machado

Log Message

Add gdbarch hooks to detect and return tagged addresses

This patch adds a couple gdbarch hooks:

gdbarch_tagged_address_p checks if a particular address is tagged or not.

gdbarch_address_tag returns the tag for a particular address, if tagged.

I've used struct value as opposed to straight CORE_ADDR so other architectures
can use the infrastructure without having to rely on fixed types.

gdb/ChangeLog:

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

* aarch64-linux-tdep.c: Include target.h, arch-utils.h, value.h and
arch/aarch64-linux.h.
(make_ltag_bits, make_ltag, aarch64_linux_set_ltag)
(aarch64_linux_get_ltag, aarch64_linux_get_atag)
(value_valid_for_memtag, 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-utils.c (default_memtag_to_string, +default_tagged_address_p)
(default_memtag_mismatch_p, default_set_memtags)
(default_get_memtag): New functions.
* arch-utils.h (default_memtag_to_string, default_tagged_address_p)
(default_memtag_mismatch_p, default_set_memtags)
(default_get_memtag): New prototypes.
* arch/aarch64-linux.h (MTE_LOGICAL_TAG_START_BIT): Define.
(MTE_LOGICAL_MAX_VALUE): Define.
* gdbarch.c: Regenerate.
* gdbarch.h: Regenerate.
* gdbarch.sh (memtag_to_string, tagged_address_p, memtag_mismatch_p)
(set_memtags, get_memtag, memtag_granule_size): New gdbarch hooks.
(enum memtag_type): New enum.

更改概述

差异

--- a/gdb/aarch64-linux-tdep.c
+++ b/gdb/aarch64-linux-tdep.c
@@ -30,6 +30,7 @@
3030 #include "symtab.h"
3131 #include "tramp-frame.h"
3232 #include "trad-frame.h"
33+#include "target.h"
3334 #include "target/target.h"
3435
3536 #include "regcache.h"
@@ -46,6 +47,11 @@
4647
4748 #include "arch/aarch64-linux.h"
4849
50+#include "arch-utils.h"
51+#include "value.h"
52+
53+#include "arch/aarch64-linux.h"
54+
4955 /* Signal frame handling.
5056
5157 +------------+ ^
@@ -1457,6 +1463,241 @@ aarch64_linux_gcc_target_options (struct gdbarch *gdbarch)
14571463 return {};
14581464 }
14591465
1466+/* Return the 4-bit tag made from VALUE. */
1467+
1468+static CORE_ADDR
1469+make_ltag_bits (CORE_ADDR value)
1470+{
1471+ return value & MTE_LOGICAL_MAX_VALUE;
1472+}
1473+
1474+/* Return the 4-bit tag that can be OR-ed to an address. */
1475+
1476+static CORE_ADDR
1477+make_ltag (CORE_ADDR value)
1478+{
1479+ return make_ltag_bits (value) << MTE_LOGICAL_TAG_START_BIT;
1480+}
1481+
1482+/* Helper to set the logical TAG for a 64-bit ADDRESS.
1483+
1484+ It is always possible to set the logical tag. */
1485+
1486+static CORE_ADDR
1487+aarch64_linux_set_ltag (CORE_ADDR address, CORE_ADDR tag)
1488+{
1489+ /* Remove the existing tag. */
1490+ address &= ~make_ltag (MTE_LOGICAL_MAX_VALUE);
1491+
1492+ /* Return the new tagged address. */
1493+ return address | make_ltag (tag);
1494+}
1495+
1496+/* Helper to get the logical tag from a 64-bit ADDRESS.
1497+
1498+ It is always possible to get the logical tag. */
1499+
1500+static CORE_ADDR
1501+aarch64_linux_get_ltag (CORE_ADDR address)
1502+{
1503+ return make_ltag_bits (address >> MTE_LOGICAL_TAG_START_BIT);
1504+}
1505+
1506+/* Helper to get the allocation tag from a 64-bit ADDRESS.
1507+
1508+ Return 0 for success and non-zero otherwise. */
1509+
1510+static int
1511+aarch64_linux_get_atag (CORE_ADDR address, CORE_ADDR *tag)
1512+{
1513+ gdb::byte_vector tags;
1514+
1515+ /* Attempt to fetch the allocation tag. */
1516+ if (target_fetch_memtags (address, 0, tags) != 0)
1517+ return 1;
1518+
1519+ /* Empty tag vector is an error. */
1520+ if (tags.empty ())
1521+ return 1;
1522+
1523+ /* Although our tags are 4 bits in size, they are stored in a
1524+ byte. */
1525+ *tag = tags[0];
1526+
1527+ return 0;
1528+}
1529+
1530+/* Helper to validate VALUE for a memtag operation. */
1531+
1532+static bool
1533+value_valid_for_memtag (struct value *value)
1534+{
1535+ if (value != nullptr && VALUE_LVAL (value) == not_lval
1536+ && value_contents_raw (value) != nullptr)
1537+ return true;
1538+
1539+ return false;
1540+}
1541+
1542+/* Implement the tagged_address_p gdbarch method. */
1543+
1544+static bool
1545+aarch64_linux_tagged_address_p (struct gdbarch *gdbarch, struct value *address)
1546+{
1547+ if (!value_valid_for_memtag (address))
1548+ return false;
1549+
1550+ CORE_ADDR addr = value_as_address (address);
1551+
1552+ /* Check if the page that contains ADDRESS is mapped with PROT_MTE. */
1553+ if (!linux_address_in_memtag_page (addr))
1554+ return false;
1555+
1556+ /* We have a valid tag in the top byte of the 64-bit address. */
1557+ return true;
1558+}
1559+
1560+/* Implement the memtag_mismatch_p gdbarch method. */
1561+
1562+static bool
1563+aarch64_linux_memtag_mismatch_p (struct gdbarch *gdbarch,
1564+ struct value *address)
1565+{
1566+ if (!value_valid_for_memtag (address))
1567+ return false;
1568+
1569+ /* Make sure we are dealing with a tagged address to begin with. */
1570+ if (!aarch64_linux_tagged_address_p (gdbarch, address))
1571+ return false;
1572+
1573+ CORE_ADDR addr = value_as_address (address);
1574+
1575+ /* Fetch the allocation tag for ADDRESS. */
1576+ CORE_ADDR atag = 0;
1577+
1578+ if (aarch64_linux_get_atag (addr, &atag) != 0)
1579+ return false;
1580+
1581+ /* Fetch the logical tag for ADDRESS. */
1582+ gdb_byte ltag = aarch64_linux_get_ltag (addr);
1583+
1584+ /* Are the tags the same? */
1585+ if (ltag == atag)
1586+ return false;
1587+
1588+ return true;
1589+}
1590+
1591+/* Implement the set_memtags gdbarch method. */
1592+
1593+static int
1594+aarch64_linux_set_memtags (struct gdbarch *gdbarch, struct value *address,
1595+ size_t length, const gdb::byte_vector &tags,
1596+ enum memtag_type tag_type)
1597+{
1598+ if (!value_valid_for_memtag (address))
1599+ return 1;
1600+
1601+ /* Make sure we are dealing with a tagged address to begin with. */
1602+ if (!aarch64_linux_tagged_address_p (gdbarch, address))
1603+ return 1;
1604+
1605+ CORE_ADDR addr = value_as_address (address);
1606+
1607+ /* Set the logical tag or the allocation tag. */
1608+ if (tag_type == tag_logical)
1609+ {
1610+ /* When setting logical tags, we don't care about the length, since
1611+ we are only setting a single logical tag. */
1612+ addr = aarch64_linux_set_ltag (addr, tags[0]);
1613+
1614+ /* Update the value's content with the tag. */
1615+ enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
1616+ gdb_byte *srcbuf = value_contents_raw (address);
1617+ store_unsigned_integer (srcbuf, sizeof (addr), byte_order, addr);
1618+ }
1619+ else
1620+ {
1621+ /* With G being the number of tag granules and N the number of tags
1622+ passed in, we can have the following cases:
1623+
1624+ 1 - G == N: Store all the N tags to memory.
1625+
1626+ 2 - G < N : Warn about having more tags than granules, but write G
1627+ tags.
1628+
1629+ 3 - G > N : This is a "fill tags" operation. We should use the tags
1630+ as a pattern to fill the granules repeatedly until we have
1631+ written G tags to memory.
1632+ */
1633+
1634+ size_t g = get_tag_granules (addr, length, MTE_GRANULE_SIZE);
1635+ size_t n = tags.size ();
1636+
1637+ if (g < n)
1638+ {
1639+ warning (_("Got more tags than memory granules. Tags will be "
1640+ "truncated."));
1641+ }
1642+ else if (g > n)
1643+ warning (_("Using tag pattern to fill memory range."));
1644+
1645+ if (target_store_memtags (addr, length, tags) != 0)
1646+ return 1;
1647+ }
1648+ return 0;
1649+}
1650+
1651+/* Implement the get_memtag gdbarch method. */
1652+
1653+static struct value *
1654+aarch64_linux_get_memtag (struct gdbarch *gdbarch, struct value *address,
1655+ enum memtag_type tag_type)
1656+{
1657+ if (!value_valid_for_memtag (address))
1658+ return nullptr;
1659+
1660+ /* Make sure we are dealing with a tagged address to begin with. */
1661+ if (!aarch64_linux_tagged_address_p (gdbarch, address))
1662+ return nullptr;
1663+
1664+ CORE_ADDR addr = value_as_address (address);
1665+ CORE_ADDR tag = 0;
1666+
1667+ /* Get the logical tag or the allocation tag. */
1668+ if (tag_type == tag_logical)
1669+ tag = aarch64_linux_get_ltag (addr);
1670+ else
1671+ {
1672+ if (aarch64_linux_get_atag (addr, &tag) != 0)
1673+ return nullptr;
1674+ }
1675+
1676+ /* Convert the tag to a value. */
1677+ return value_from_ulongest (builtin_type (gdbarch)->builtin_unsigned_int,
1678+ tag);
1679+}
1680+
1681+/* Implement the memtag_to_string gdbarch method. */
1682+
1683+static std::string
1684+aarch64_linux_memtag_to_string (struct gdbarch *gdbarch,
1685+ struct value *address,
1686+ enum memtag_type tag_type)
1687+{
1688+ if (!value_valid_for_memtag (address))
1689+ return "";
1690+
1691+ struct value *v_tag = aarch64_linux_get_memtag (gdbarch, address, tag_type);
1692+
1693+ if (v_tag == nullptr && tag_allocation)
1694+ error (_("Error getting tag from target"));
1695+
1696+ CORE_ADDR tag = value_as_address (v_tag);
1697+
1698+ return string_printf ("0x%s", phex_nz (tag, sizeof (tag)));
1699+}
1700+
14601701 static void
14611702 aarch64_linux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
14621703 {
@@ -1514,6 +1755,31 @@ aarch64_linux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
15141755 data associated with the address. */
15151756 set_gdbarch_significant_addr_bit (gdbarch, 56);
15161757
1758+ /* MTE-specific settings and hooks. */
1759+ if (tdep->has_mte ())
1760+ {
1761+ /* Register a hook for checking if an address is tagged or not. */
1762+ set_gdbarch_tagged_address_p (gdbarch, aarch64_linux_tagged_address_p);
1763+
1764+ /* Register a hook for checking if there is a memory tag mismatch. */
1765+ set_gdbarch_memtag_mismatch_p (gdbarch,
1766+ aarch64_linux_memtag_mismatch_p);
1767+
1768+ /* Register a hook for setting the logical/allocation tags for
1769+ a range of addresses. */
1770+ set_gdbarch_set_memtags (gdbarch, aarch64_linux_set_memtags);
1771+
1772+ /* Register a hook for extracting the logical/allocation tag from an
1773+ address. */
1774+ set_gdbarch_get_memtag (gdbarch, aarch64_linux_get_memtag);
1775+
1776+ /* Set the allocation tag granule size to 16 bytes. */
1777+ set_gdbarch_memtag_granule_size (gdbarch, MTE_GRANULE_SIZE);
1778+
1779+ /* Register a hook for converting a memory tag to a string. */
1780+ set_gdbarch_memtag_to_string (gdbarch, aarch64_linux_memtag_to_string);
1781+ }
1782+
15171783 /* Initialize the aarch64_linux_record_tdep. */
15181784 /* These values are the size of the type that will be used in a system
15191785 call. They are obtained from Linux Kernel source. */
--- a/gdb/arch-utils.c
+++ b/gdb/arch-utils.c
@@ -78,6 +78,56 @@ legacy_register_sim_regno (struct gdbarch *gdbarch, int regnum)
7878 return LEGACY_SIM_REGNO_IGNORE;
7979 }
8080
81+
82+/* See arch-utils.h */
83+
84+std::string
85+default_memtag_to_string (struct gdbarch *gdbarch, struct value *address,
86+ enum memtag_type tag_type)
87+{
88+ /* By default, assume the address is untagged. */
89+ return "";
90+}
91+
92+/* See arch-utils.h */
93+
94+bool
95+default_tagged_address_p (struct gdbarch *gdbarch, struct value *address)
96+{
97+ /* By default, assume the address is untagged. */
98+ return false;
99+}
100+
101+/* See arch-utils.h */
102+
103+bool
104+default_memtag_mismatch_p (struct gdbarch *gdbarch, struct value *address)
105+{
106+ /* By default, assume there is no mismatch. */
107+ return false;
108+}
109+
110+/* See arch-utils.h */
111+
112+int
113+default_set_memtags (struct gdbarch *gdbarch, struct value *address,
114+ size_t length, const gdb::byte_vector &tags,
115+ enum memtag_type tag_type)
116+{
117+ /* By default, return 0; */
118+ return 0;
119+}
120+
121+/* See arch-utils.h */
122+
123+struct value *
124+default_get_memtag (struct gdbarch *gdbarch, struct value *address,
125+ enum memtag_type tag_type)
126+{
127+ /* By default, return no tag. */
128+ return NULL;
129+}
130+
81131 CORE_ADDR
82132 generic_skip_trampoline_code (struct frame_info *frame, CORE_ADDR pc)
83133 {
--- a/gdb/arch-utils.h
+++ b/gdb/arch-utils.h
@@ -134,6 +134,29 @@ extern const struct floatformat **
134134 default_floatformat_for_type (struct gdbarch *gdbarch,
135135 const char *name, int len);
136136
137+/* Default implementation of gdbarch_tagged_address_p. */
138+extern std::string default_memtag_to_string (struct gdbarch *gdbarch,
139+ struct value *address,
140+ enum memtag_type tag_type);
141+
142+/* Default implementation of gdbarch_tagged_address_p. */
143+bool default_tagged_address_p (struct gdbarch *gdbarch, struct value *address);
144+
145+/* Default implementation of gdbarch_memtag_mismatch_p. */
146+extern bool default_memtag_mismatch_p (struct gdbarch *gdbarch,
147+ struct value *address);
148+
149+/* Default implementation of gdbarch_set_memtags. */
150+int default_set_memtags (struct gdbarch *gdbarch,
151+ struct value *address, size_t length,
152+ const gdb::byte_vector &tags,
153+ enum memtag_type tag_type);
154+
155+/* Default implementation of gdbarch_get_memtag. */
156+struct value *default_get_memtag (struct gdbarch *gdbarch,
157+ struct value *address,
158+ enum memtag_type tag_type);
159+
137160 extern CORE_ADDR generic_skip_trampoline_code (struct frame_info *frame,
138161 CORE_ADDR pc);
139162
--- a/gdb/arch/aarch64-linux.h
+++ b/gdb/arch/aarch64-linux.h
@@ -32,6 +32,8 @@
3232
3333 /* We have one tag per 16 bytes of memory. */
3434 #define MTE_GRANULE_SIZE 16
35+#define MTE_LOGICAL_TAG_START_BIT 56
36+#define MTE_LOGICAL_MAX_VALUE 0xf
3537
3638 /* Return the number of tag granules in the memory range
3739 [ADDR, ADDR + LEN) given GRANULE_SIZE. */
--- a/gdb/gdbarch.c
+++ b/gdb/gdbarch.c
@@ -251,6 +251,12 @@ struct gdbarch
251251 gdbarch_convert_from_func_ptr_addr_ftype *convert_from_func_ptr_addr;
252252 gdbarch_addr_bits_remove_ftype *addr_bits_remove;
253253 int significant_addr_bit;
254+ gdbarch_memtag_to_string_ftype *memtag_to_string;
255+ gdbarch_tagged_address_p_ftype *tagged_address_p;
256+ gdbarch_memtag_mismatch_p_ftype *memtag_mismatch_p;
257+ gdbarch_set_memtags_ftype *set_memtags;
258+ gdbarch_get_memtag_ftype *get_memtag;
259+ CORE_ADDR memtag_granule_size;
254260 gdbarch_software_single_step_ftype *software_single_step;
255261 gdbarch_single_step_through_delay_ftype *single_step_through_delay;
256262 gdbarch_print_insn_ftype *print_insn;
@@ -427,6 +433,11 @@ gdbarch_alloc (const struct gdbarch_info *info,
427433 gdbarch->stabs_argument_has_addr = default_stabs_argument_has_addr;
428434 gdbarch->convert_from_func_ptr_addr = convert_from_func_ptr_addr_identity;
429435 gdbarch->addr_bits_remove = core_addr_identity;
436+ gdbarch->memtag_to_string = default_memtag_to_string;
437+ gdbarch->tagged_address_p = default_tagged_address_p;
438+ gdbarch->memtag_mismatch_p = default_memtag_mismatch_p;
439+ gdbarch->set_memtags = default_set_memtags;
440+ gdbarch->get_memtag = default_get_memtag;
430441 gdbarch->print_insn = default_print_insn;
431442 gdbarch->skip_trampoline_code = generic_skip_trampoline_code;
432443 gdbarch->skip_solib_resolver = generic_skip_solib_resolver;
@@ -616,6 +627,12 @@ verify_gdbarch (struct gdbarch *gdbarch)
616627 /* Skip verify of convert_from_func_ptr_addr, invalid_p == 0 */
617628 /* Skip verify of addr_bits_remove, invalid_p == 0 */
618629 /* Skip verify of significant_addr_bit, invalid_p == 0 */
630+ /* Skip verify of memtag_to_string, invalid_p == 0 */
631+ /* Skip verify of tagged_address_p, invalid_p == 0 */
632+ /* Skip verify of memtag_mismatch_p, invalid_p == 0 */
633+ /* Skip verify of set_memtags, invalid_p == 0 */
634+ /* Skip verify of get_memtag, invalid_p == 0 */
635+ /* Skip verify of memtag_granule_size, invalid_p == 0 */
619636 /* Skip verify of software_single_step, has predicate. */
620637 /* Skip verify of single_step_through_delay, has predicate. */
621638 /* Skip verify of print_insn, invalid_p == 0 */
@@ -1056,6 +1073,9 @@ gdbarch_dump (struct gdbarch *gdbarch, struct ui_file *file)
10561073 "gdbarch_dump: get_longjmp_target = <%s>\n",
10571074 host_address_to_string (gdbarch->get_longjmp_target));
10581075 fprintf_unfiltered (file,
1076+ "gdbarch_dump: get_memtag = <%s>\n",
1077+ host_address_to_string (gdbarch->get_memtag));
1078+ fprintf_unfiltered (file,
10591079 "gdbarch_dump: get_pc_address_flags = <%s>\n",
10601080 host_address_to_string (gdbarch->get_pc_address_flags));
10611081 fprintf_unfiltered (file,
@@ -1191,6 +1211,15 @@ gdbarch_dump (struct gdbarch *gdbarch, struct ui_file *file)
11911211 "gdbarch_dump: memory_remove_breakpoint = <%s>\n",
11921212 host_address_to_string (gdbarch->memory_remove_breakpoint));
11931213 fprintf_unfiltered (file,
1214+ "gdbarch_dump: memtag_granule_size = %s\n",
1215+ core_addr_to_string_nz (gdbarch->memtag_granule_size));
1216+ fprintf_unfiltered (file,
1217+ "gdbarch_dump: memtag_mismatch_p = <%s>\n",
1218+ host_address_to_string (gdbarch->memtag_mismatch_p));
1219+ fprintf_unfiltered (file,
1220+ "gdbarch_dump: memtag_to_string = <%s>\n",
1221+ host_address_to_string (gdbarch->memtag_to_string));
1222+ fprintf_unfiltered (file,
11941223 "gdbarch_dump: num_pseudo_regs = %s\n",
11951224 plongest (gdbarch->num_pseudo_regs));
11961225 fprintf_unfiltered (file,
@@ -1335,6 +1364,9 @@ gdbarch_dump (struct gdbarch *gdbarch, struct ui_file *file)
13351364 "gdbarch_dump: sdb_reg_to_regnum = <%s>\n",
13361365 host_address_to_string (gdbarch->sdb_reg_to_regnum));
13371366 fprintf_unfiltered (file,
1367+ "gdbarch_dump: set_memtags = <%s>\n",
1368+ host_address_to_string (gdbarch->set_memtags));
1369+ fprintf_unfiltered (file,
13381370 "gdbarch_dump: short_bit = %s\n",
13391371 plongest (gdbarch->short_bit));
13401372 fprintf_unfiltered (file,
@@ -1449,6 +1481,9 @@ gdbarch_dump (struct gdbarch *gdbarch, struct ui_file *file)
14491481 "gdbarch_dump: syscalls_info = %s\n",
14501482 host_address_to_string (gdbarch->syscalls_info));
14511483 fprintf_unfiltered (file,
1484+ "gdbarch_dump: tagged_address_p = <%s>\n",
1485+ host_address_to_string (gdbarch->tagged_address_p));
1486+ fprintf_unfiltered (file,
14521487 "gdbarch_dump: target_desc = %s\n",
14531488 host_address_to_string (gdbarch->target_desc));
14541489 fprintf_unfiltered (file,
@@ -3220,6 +3255,108 @@ set_gdbarch_significant_addr_bit (struct gdbarch *gdbarch,
32203255 gdbarch->significant_addr_bit = significant_addr_bit;
32213256 }
32223257
3258+std::string
3259+gdbarch_memtag_to_string (struct gdbarch *gdbarch, struct value *address, enum memtag_type tag_type)
3260+{
3261+ gdb_assert (gdbarch != NULL);
3262+ gdb_assert (gdbarch->memtag_to_string != NULL);
3263+ if (gdbarch_debug >= 2)
3264+ fprintf_unfiltered (gdb_stdlog, "gdbarch_memtag_to_string called\n");
3265+ return gdbarch->memtag_to_string (gdbarch, address, tag_type);
3266+}
3267+
3268+void
3269+set_gdbarch_memtag_to_string (struct gdbarch *gdbarch,
3270+ gdbarch_memtag_to_string_ftype memtag_to_string)
3271+{
3272+ gdbarch->memtag_to_string = memtag_to_string;
3273+}
3274+
3275+bool
3276+gdbarch_tagged_address_p (struct gdbarch *gdbarch, struct value *address)
3277+{
3278+ gdb_assert (gdbarch != NULL);
3279+ gdb_assert (gdbarch->tagged_address_p != NULL);
3280+ if (gdbarch_debug >= 2)
3281+ fprintf_unfiltered (gdb_stdlog, "gdbarch_tagged_address_p called\n");
3282+ return gdbarch->tagged_address_p (gdbarch, address);
3283+}
3284+
3285+void
3286+set_gdbarch_tagged_address_p (struct gdbarch *gdbarch,
3287+ gdbarch_tagged_address_p_ftype tagged_address_p)
3288+{
3289+ gdbarch->tagged_address_p = tagged_address_p;
3290+}
3291+
3292+bool
3293+gdbarch_memtag_mismatch_p (struct gdbarch *gdbarch, struct value *address)
3294+{
3295+ gdb_assert (gdbarch != NULL);
3296+ gdb_assert (gdbarch->memtag_mismatch_p != NULL);
3297+ if (gdbarch_debug >= 2)
3298+ fprintf_unfiltered (gdb_stdlog, "gdbarch_memtag_mismatch_p called\n");
3299+ return gdbarch->memtag_mismatch_p (gdbarch, address);
3300+}
3301+
3302+void
3303+set_gdbarch_memtag_mismatch_p (struct gdbarch *gdbarch,
3304+ gdbarch_memtag_mismatch_p_ftype memtag_mismatch_p)
3305+{
3306+ gdbarch->memtag_mismatch_p = memtag_mismatch_p;
3307+}
3308+
3309+int
3310+gdbarch_set_memtags (struct gdbarch *gdbarch, struct value *address, size_t length, const gdb::byte_vector &tags, enum memtag_type tag_type)
3311+{
3312+ gdb_assert (gdbarch != NULL);
3313+ gdb_assert (gdbarch->set_memtags != NULL);
3314+ if (gdbarch_debug >= 2)
3315+ fprintf_unfiltered (gdb_stdlog, "gdbarch_set_memtags called\n");
3316+ return gdbarch->set_memtags (gdbarch, address, length, tags, tag_type);
3317+}
3318+
3319+void
3320+set_gdbarch_set_memtags (struct gdbarch *gdbarch,
3321+ gdbarch_set_memtags_ftype set_memtags)
3322+{
3323+ gdbarch->set_memtags = set_memtags;
3324+}
3325+
3326+struct value *
3327+gdbarch_get_memtag (struct gdbarch *gdbarch, struct value *address, enum memtag_type tag_type)
3328+{
3329+ gdb_assert (gdbarch != NULL);
3330+ gdb_assert (gdbarch->get_memtag != NULL);
3331+ if (gdbarch_debug >= 2)
3332+ fprintf_unfiltered (gdb_stdlog, "gdbarch_get_memtag called\n");
3333+ return gdbarch->get_memtag (gdbarch, address, tag_type);
3334+}
3335+
3336+void
3337+set_gdbarch_get_memtag (struct gdbarch *gdbarch,
3338+ gdbarch_get_memtag_ftype get_memtag)
3339+{
3340+ gdbarch->get_memtag = get_memtag;
3341+}
3342+
3343+CORE_ADDR
3344+gdbarch_memtag_granule_size (struct gdbarch *gdbarch)
3345+{
3346+ gdb_assert (gdbarch != NULL);
3347+ /* Skip verify of memtag_granule_size, invalid_p == 0 */
3348+ if (gdbarch_debug >= 2)
3349+ fprintf_unfiltered (gdb_stdlog, "gdbarch_memtag_granule_size called\n");
3350+ return gdbarch->memtag_granule_size;
3351+}
3352+
3353+void
3354+set_gdbarch_memtag_granule_size (struct gdbarch *gdbarch,
3355+ CORE_ADDR memtag_granule_size)
3356+{
3357+ gdbarch->memtag_granule_size = memtag_granule_size;
3358+}
3359+
32233360 int
32243361 gdbarch_software_single_step_p (struct gdbarch *gdbarch)
32253362 {
--- a/gdb/gdbarch.h
+++ b/gdb/gdbarch.h
@@ -115,6 +115,18 @@ enum function_call_return_method
115115 return_method_struct,
116116 };
117117
118+enum memtag_type
119+{
120+ /* Logical tag, the tag that is stored in unused bits of a pointer to a
121+ virtual address. */
122+ tag_logical = 0,
123+
124+ /* Allocation tag, the tag that is associated with every granule of memory in
125+ the physical address space. Allocation tags are used to validate memory
126+ accesses via pointers containing logical tags. */
127+ tag_allocation,
128+};
129+
118130
119131
120132 /* The following are pre-initialized by GDBARCH. */
@@ -705,6 +717,47 @@ extern void set_gdbarch_addr_bits_remove (struct gdbarch *gdbarch, gdbarch_addr_
705717 extern int gdbarch_significant_addr_bit (struct gdbarch *gdbarch);
706718 extern void set_gdbarch_significant_addr_bit (struct gdbarch *gdbarch, int significant_addr_bit);
707719
720+/* Return a string representation of the memory tag TYPE of ADDRESS.
721+ If no tag is associated with such an address, return the empty string. */
722+
723+typedef std::string (gdbarch_memtag_to_string_ftype) (struct gdbarch *gdbarch, struct value *address, enum memtag_type tag_type);
724+extern std::string gdbarch_memtag_to_string (struct gdbarch *gdbarch, struct value *address, enum memtag_type tag_type);
725+extern void set_gdbarch_memtag_to_string (struct gdbarch *gdbarch, gdbarch_memtag_to_string_ftype *memtag_to_string);
726+
727+/* Return true if ADDRESS contains a tag and false otherwise. */
728+
729+typedef bool (gdbarch_tagged_address_p_ftype) (struct gdbarch *gdbarch, struct value *address);
730+extern bool gdbarch_tagged_address_p (struct gdbarch *gdbarch, struct value *address);
731+extern void set_gdbarch_tagged_address_p (struct gdbarch *gdbarch, gdbarch_tagged_address_p_ftype *tagged_address_p);
732+
733+/* Return true if the tag from ADDRESS does not match the memory tag for that
734+ particular address. Return false otherwise. */
735+
736+typedef bool (gdbarch_memtag_mismatch_p_ftype) (struct gdbarch *gdbarch, struct value *address);
737+extern bool gdbarch_memtag_mismatch_p (struct gdbarch *gdbarch, struct value *address);
738+extern void set_gdbarch_memtag_mismatch_p (struct gdbarch *gdbarch, gdbarch_memtag_mismatch_p_ftype *memtag_mismatch_p);
739+
740+/* Set the tags for the address range [ADDRESS, ADDRESS + LENGTH) to TAGS
741+ Return 0 if successful and non-zero otherwise. */
742+
743+typedef int (gdbarch_set_memtags_ftype) (struct gdbarch *gdbarch, struct value *address, size_t length, const gdb::byte_vector &tags, enum memtag_type tag_type);
744+extern int gdbarch_set_memtags (struct gdbarch *gdbarch, struct value *address, size_t length, const gdb::byte_vector &tags, enum memtag_type tag_type);
745+extern void set_gdbarch_set_memtags (struct gdbarch *gdbarch, gdbarch_set_memtags_ftype *set_memtags);
746+
747+/* Return the tag portion of ADDRESS, assuming ADDRESS is tagged. */
748+
749+typedef struct value * (gdbarch_get_memtag_ftype) (struct gdbarch *gdbarch, struct value *address, enum memtag_type tag_type);
750+extern struct value * gdbarch_get_memtag (struct gdbarch *gdbarch, struct value *address, enum memtag_type tag_type);
751+extern void set_gdbarch_get_memtag (struct gdbarch *gdbarch, gdbarch_get_memtag_ftype *get_memtag);
752+
753+/* memtag_granule_size is the size of the allocation tag granule, for
754+ architectures that support memory tagging.
755+ This is 0 for architectures that do not support memory tagging.
756+ For a non-zero value, this represents the number of bytes of memory per tag. */
757+
758+extern CORE_ADDR gdbarch_memtag_granule_size (struct gdbarch *gdbarch);
759+extern void set_gdbarch_memtag_granule_size (struct gdbarch *gdbarch, CORE_ADDR memtag_granule_size);
760+
708761 /* FIXME/cagney/2001-01-18: This should be split in two. A target method that
709762 indicates if the target needs software single step. An ISA method to
710763 implement it.
--- a/gdb/gdbarch.sh
+++ b/gdb/gdbarch.sh
@@ -604,6 +604,30 @@ m;CORE_ADDR;addr_bits_remove;CORE_ADDR addr;addr;;core_addr_identity;;0
604604 # additional data associated with the address.
605605 v;int;significant_addr_bit;;;;;;0
606606
607+# Return a string representation of the memory tag TYPE of ADDRESS.
608+# If no tag is associated with such an address, return the empty string.
609++m;std::string;memtag_to_string;struct value *address, enum memtag_type tag_type;address, tag_type;;default_memtag_to_string;;0
610+
611+# Return true if ADDRESS contains a tag and false otherwise.
612++m;bool;tagged_address_p;struct value *address;address;;default_tagged_address_p;;0
613+
614+# Return true if the tag from ADDRESS does not match the memory tag for that
615+# particular address. Return false otherwise.
616++m;bool;memtag_mismatch_p;struct value *address;address;;default_memtag_mismatch_p;;0
617+
618+# Set the tags for the address range [ADDRESS, ADDRESS + LENGTH) to TAGS
619+# Return 0 if successful and non-zero otherwise.
620++m;int;set_memtags;struct value *address, size_t length, const gdb::byte_vector \&tags, enum memtag_type tag_type;address, length, tags, tag_type;;default_set_memtags;;0
621+
622+# Return the tag portion of ADDRESS, assuming ADDRESS is tagged.
623++m;struct value *;get_memtag;struct value *address, enum memtag_type tag_type;address, tag_type;;default_get_memtag;;0
624+
625+# memtag_granule_size is the size of the allocation tag granule, for
626+# architectures that support memory tagging.
627+# This is 0 for architectures that do not support memory tagging.
628+# For a non-zero value, this represents the number of bytes of memory per tag.
629+v;CORE_ADDR;memtag_granule_size;;;;;;0
630+
607631 # FIXME/cagney/2001-01-18: This should be split in two. A target method that
608632 # indicates if the target needs software single step. An ISA method to
609633 # implement it.
@@ -1355,6 +1379,18 @@ enum function_call_return_method
13551379 return_method_struct,
13561380 };
13571381
1382+enum memtag_type
1383+{
1384+ /* Logical tag, the tag that is stored in unused bits of a pointer to a
1385+ virtual address. */
1386+ tag_logical = 0,
1387+
1388+ /* Allocation tag, the tag that is associated with every granule of memory in
1389+ the physical address space. Allocation tags are used to validate memory
1390+ accesses via pointers containing logical tags. */
1391+ tag_allocation,
1392+};
1393+
13581394 EOF
13591395
13601396 # function typedef's