• R/O
  • HTTP
  • SSH
  • HTTPS

Commit

Tags
Keine 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

Revision74e76b725d270a7d800ba472b780eaac0d9cfc78 (tree)
Zeit2020-06-26 01:23:38
AutorLuis Machado <luis.machado@lina...>
CommiterLuis Machado

Log Message

AArch64: Implement the memory tagging gdbarch hooks

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_linux_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 (make_ltag_bits, make_ltag)
(aarch64_linux_set_ltag, aarch64_linux_get_ltag): New functions.
* arch/aarch64-mte-linux.h (MTE_LOGICAL_TAG_START_BIT)
(MTE_LOGICAL_MAX_VALUE): Define.
(make_ltag_bits, make_ltag, aarch64_linux_set_ltag)
(aarch64_linux_get_ltag): New prototype.

Ändern Zusammenfassung

Diff

--- 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,9 @@
4647
4748 #include "arch/aarch64-mte-linux.h"
4849
50+#include "arch-utils.h"
51+#include "value.h"
52+
4953 /* Signal frame handling.
5054
5155 +------------+ ^
@@ -1458,6 +1462,186 @@ aarch64_linux_gcc_target_options (struct gdbarch *gdbarch)
14581462 return {};
14591463 }
14601464
1465+/* Helper to get the allocation tag from a 64-bit ADDRESS.
1466+
1467+ Return 0 for success and non-zero otherwise. */
1468+
1469+static int
1470+aarch64_linux_get_atag (CORE_ADDR address, CORE_ADDR *tag)
1471+{
1472+ gdb::byte_vector tags;
1473+
1474+ /* Attempt to fetch the allocation tag. */
1475+ if (target_fetch_memtags (address, 0, tags) != 0)
1476+ return 1;
1477+
1478+ /* Only one tag should've been returned. Make sure we got exactly that. */
1479+ gdb_assert (tags.size () == 1);
1480+
1481+ /* Although our tags are 4 bits in size, they are stored in a
1482+ byte. */
1483+ *tag = tags[0];
1484+
1485+ return 0;
1486+}
1487+
1488+/* Implement the tagged_address_p gdbarch method. */
1489+
1490+static bool
1491+aarch64_linux_tagged_address_p (struct gdbarch *gdbarch, struct value *address)
1492+{
1493+ gdb_assert (address != nullptr);
1494+
1495+ CORE_ADDR addr = value_as_address (address);
1496+
1497+ /* Remove the top byte for the memory range check. */
1498+ addr = address_significant (gdbarch, addr);
1499+
1500+ /* Check if the page that contains ADDRESS is mapped with PROT_MTE. */
1501+ if (!linux_address_in_memtag_page (addr))
1502+ return false;
1503+
1504+ /* We have a valid tag in the top byte of the 64-bit address. */
1505+ return true;
1506+}
1507+
1508+/* Implement the memtag_mismatch_p gdbarch method. */
1509+
1510+static bool
1511+aarch64_linux_memtag_mismatch_p (struct gdbarch *gdbarch,
1512+ struct value *address)
1513+{
1514+ gdb_assert (address != nullptr);
1515+
1516+ /* Make sure we are dealing with a tagged address to begin with. */
1517+ if (!aarch64_linux_tagged_address_p (gdbarch, address))
1518+ return false;
1519+
1520+ CORE_ADDR addr = value_as_address (address);
1521+
1522+ /* Fetch the allocation tag for ADDRESS. */
1523+ CORE_ADDR atag = 0;
1524+
1525+ if (aarch64_linux_get_atag (addr, &atag) != 0)
1526+ return false;
1527+
1528+ /* Fetch the logical tag for ADDRESS. */
1529+ gdb_byte ltag = aarch64_linux_get_ltag (addr);
1530+
1531+ /* Are the tags the same? */
1532+ if (ltag == atag)
1533+ return false;
1534+
1535+ return true;
1536+}
1537+
1538+/* Implement the set_memtags gdbarch method. */
1539+
1540+static int
1541+aarch64_linux_set_memtags (struct gdbarch *gdbarch, struct value *address,
1542+ size_t length, const gdb::byte_vector &tags,
1543+ enum memtag_type tag_type)
1544+{
1545+ gdb_assert (address != nullptr);
1546+
1547+ CORE_ADDR addr = value_as_address (address);
1548+
1549+ /* Set the logical tag or the allocation tag. */
1550+ if (tag_type == tag_logical)
1551+ {
1552+ /* When setting logical tags, we don't care about the length, since
1553+ we are only setting a single logical tag. */
1554+ addr = aarch64_linux_set_ltag (addr, tags[0]);
1555+
1556+ /* Update the value's content with the tag. */
1557+ enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
1558+ gdb_byte *srcbuf = value_contents_raw (address);
1559+ store_unsigned_integer (srcbuf, sizeof (addr), byte_order, addr);
1560+ }
1561+ else
1562+ {
1563+ /* Make sure we are dealing with a tagged address to begin with. */
1564+ if (!aarch64_linux_tagged_address_p (gdbarch, address))
1565+ return 1;
1566+
1567+ /* With G being the number of tag granules and N the number of tags
1568+ passed in, we can have the following cases:
1569+
1570+ 1 - G == N: Store all the N tags to memory.
1571+
1572+ 2 - G < N : Warn about having more tags than granules, but write G
1573+ tags.
1574+
1575+ 3 - G > N : This is a "fill tags" operation. We should use the tags
1576+ as a pattern to fill the granules repeatedly until we have
1577+ written G tags to memory.
1578+ */
1579+
1580+ size_t g = get_tag_granules (addr, length, MTE_GRANULE_SIZE);
1581+ size_t n = tags.size ();
1582+
1583+ if (g < n)
1584+ {
1585+ warning (_("Got more tags than memory granules. Tags will be "
1586+ "truncated."));
1587+ }
1588+ else if (g > n)
1589+ warning (_("Using tag pattern to fill memory range."));
1590+
1591+ if (target_store_memtags (addr, length, tags) != 0)
1592+ return 1;
1593+ }
1594+ return 0;
1595+}
1596+
1597+/* Implement the get_memtag gdbarch method. */
1598+
1599+static struct value *
1600+aarch64_linux_get_memtag (struct gdbarch *gdbarch, struct value *address,
1601+ enum memtag_type tag_type)
1602+{
1603+ gdb_assert (address != nullptr);
1604+
1605+ CORE_ADDR addr = value_as_address (address);
1606+ CORE_ADDR tag = 0;
1607+
1608+ /* Get the logical tag or the allocation tag. */
1609+ if (tag_type == tag_logical)
1610+ tag = aarch64_linux_get_ltag (addr);
1611+ else
1612+ {
1613+ /* Make sure we are dealing with a tagged address to begin with. */
1614+ if (!aarch64_linux_tagged_address_p (gdbarch, address))
1615+ return nullptr;
1616+
1617+ if (aarch64_linux_get_atag (addr, &tag) != 0)
1618+ return nullptr;
1619+ }
1620+
1621+ /* Convert the tag to a value. */
1622+ return value_from_ulongest (builtin_type (gdbarch)->builtin_unsigned_int,
1623+ tag);
1624+}
1625+
1626+/* Implement the memtag_to_string gdbarch method. */
1627+
1628+static std::string
1629+aarch64_linux_memtag_to_string (struct gdbarch *gdbarch,
1630+ struct value *address,
1631+ enum memtag_type tag_type)
1632+{
1633+ gdb_assert (address != nullptr);
1634+
1635+ struct value *v_tag = aarch64_linux_get_memtag (gdbarch, address, tag_type);
1636+
1637+ if (v_tag == nullptr && tag_allocation)
1638+ error (_("Error getting tag from target"));
1639+
1640+ CORE_ADDR tag = value_as_address (v_tag);
1641+
1642+ return string_printf ("0x%s", phex_nz (tag, sizeof (tag)));
1643+}
1644+
14611645 static void
14621646 aarch64_linux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
14631647 {
@@ -1515,6 +1699,31 @@ aarch64_linux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
15151699 data associated with the address. */
15161700 set_gdbarch_significant_addr_bit (gdbarch, 56);
15171701
1702+ /* MTE-specific settings and hooks. */
1703+ if (tdep->has_mte ())
1704+ {
1705+ /* Register a hook for checking if an address is tagged or not. */
1706+ set_gdbarch_tagged_address_p (gdbarch, aarch64_linux_tagged_address_p);
1707+
1708+ /* Register a hook for checking if there is a memory tag mismatch. */
1709+ set_gdbarch_memtag_mismatch_p (gdbarch,
1710+ aarch64_linux_memtag_mismatch_p);
1711+
1712+ /* Register a hook for setting the logical/allocation tags for
1713+ a range of addresses. */
1714+ set_gdbarch_set_memtags (gdbarch, aarch64_linux_set_memtags);
1715+
1716+ /* Register a hook for extracting the logical/allocation tag from an
1717+ address. */
1718+ set_gdbarch_get_memtag (gdbarch, aarch64_linux_get_memtag);
1719+
1720+ /* Set the allocation tag granule size to 16 bytes. */
1721+ set_gdbarch_memtag_granule_size (gdbarch, MTE_GRANULE_SIZE);
1722+
1723+ /* Register a hook for converting a memory tag to a string. */
1724+ set_gdbarch_memtag_to_string (gdbarch, aarch64_linux_memtag_to_string);
1725+ }
1726+
15181727 /* Initialize the aarch64_linux_record_tdep. */
15191728 /* These values are the size of the type that will be used in a system
15201729 call. They are obtained from Linux Kernel source. */
--- a/gdb/arch/aarch64-mte-linux.c
+++ b/gdb/arch/aarch64-mte-linux.c
@@ -32,3 +32,39 @@ get_tag_granules (CORE_ADDR addr, size_t len, unsigned int granule_size)
3232 /* We always have at least 1 granule. */
3333 return 1 + (e_addr - s_addr) / granule_size;
3434 }
35+
36+/* See arch/aarch64-mte-linux.h */
37+
38+CORE_ADDR
39+make_ltag_bits (CORE_ADDR value)
40+{
41+ return value & MTE_LOGICAL_MAX_VALUE;
42+}
43+
44+/* See arch/aarch64-mte-linux.h */
45+
46+CORE_ADDR
47+make_ltag (CORE_ADDR value)
48+{
49+ return make_ltag_bits (value) << MTE_LOGICAL_TAG_START_BIT;
50+}
51+
52+/* See arch/aarch64-mte-linux.h */
53+
54+CORE_ADDR
55+aarch64_linux_set_ltag (CORE_ADDR address, CORE_ADDR tag)
56+{
57+ /* Remove the existing tag. */
58+ address &= ~make_ltag (MTE_LOGICAL_MAX_VALUE);
59+
60+ /* Return the new tagged address. */
61+ return address | make_ltag (tag);
62+}
63+
64+/* See arch/aarch64-mte-linux.h */
65+
66+CORE_ADDR
67+aarch64_linux_get_ltag (CORE_ADDR address)
68+{
69+ return make_ltag_bits (address >> MTE_LOGICAL_TAG_START_BIT);
70+}
--- a/gdb/arch/aarch64-mte-linux.h
+++ b/gdb/arch/aarch64-mte-linux.h
@@ -32,10 +32,29 @@
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. */
3840 extern int get_tag_granules (CORE_ADDR addr, size_t len,
3941 unsigned int granule_size);
4042
43+/* Return the 4-bit tag made from VALUE. */
44+extern CORE_ADDR make_ltag_bits (CORE_ADDR value);
45+
46+/* Return the 4-bit tag that can be OR-ed to an address. */
47+extern CORE_ADDR make_ltag (CORE_ADDR value);
48+
49+/* Helper to set the logical TAG for a 64-bit ADDRESS.
50+
51+ It is always possible to set the logical tag. */
52+extern CORE_ADDR aarch64_linux_set_ltag (CORE_ADDR address,
53+ CORE_ADDR tag);
54+
55+/* Helper to get the logical tag from a 64-bit ADDRESS.
56+
57+ It is always possible to get the logical tag. */
58+extern CORE_ADDR aarch64_linux_get_ltag (CORE_ADDR address);
59+
4160 #endif /* ARCH_AARCH64_LINUX_H */