GNU Binutils with patches for OS216
修订版 | 2c7d3af06cfababfde33c8946620c3fe05fded52 (tree) |
---|---|
时间 | 2020-06-16 21:58:32 |
作者 | Luis Machado <luis.machado@lina...> |
Commiter | Luis Machado |
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.
@@ -30,6 +30,7 @@ | ||
30 | 30 | #include "symtab.h" |
31 | 31 | #include "tramp-frame.h" |
32 | 32 | #include "trad-frame.h" |
33 | +#include "target.h" | |
33 | 34 | #include "target/target.h" |
34 | 35 | |
35 | 36 | #include "regcache.h" |
@@ -46,6 +47,11 @@ | ||
46 | 47 | |
47 | 48 | #include "arch/aarch64-linux.h" |
48 | 49 | |
50 | +#include "arch-utils.h" | |
51 | +#include "value.h" | |
52 | + | |
53 | +#include "arch/aarch64-linux.h" | |
54 | + | |
49 | 55 | /* Signal frame handling. |
50 | 56 | |
51 | 57 | +------------+ ^ |
@@ -1457,6 +1463,241 @@ aarch64_linux_gcc_target_options (struct gdbarch *gdbarch) | ||
1457 | 1463 | return {}; |
1458 | 1464 | } |
1459 | 1465 | |
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 | + | |
1460 | 1701 | static void |
1461 | 1702 | aarch64_linux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch) |
1462 | 1703 | { |
@@ -1514,6 +1755,31 @@ aarch64_linux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch) | ||
1514 | 1755 | data associated with the address. */ |
1515 | 1756 | set_gdbarch_significant_addr_bit (gdbarch, 56); |
1516 | 1757 | |
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 | + | |
1517 | 1783 | /* Initialize the aarch64_linux_record_tdep. */ |
1518 | 1784 | /* These values are the size of the type that will be used in a system |
1519 | 1785 | call. They are obtained from Linux Kernel source. */ |
@@ -78,6 +78,56 @@ legacy_register_sim_regno (struct gdbarch *gdbarch, int regnum) | ||
78 | 78 | return LEGACY_SIM_REGNO_IGNORE; |
79 | 79 | } |
80 | 80 | |
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 | + | |
81 | 131 | CORE_ADDR |
82 | 132 | generic_skip_trampoline_code (struct frame_info *frame, CORE_ADDR pc) |
83 | 133 | { |
@@ -134,6 +134,29 @@ extern const struct floatformat ** | ||
134 | 134 | default_floatformat_for_type (struct gdbarch *gdbarch, |
135 | 135 | const char *name, int len); |
136 | 136 | |
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 | + | |
137 | 160 | extern CORE_ADDR generic_skip_trampoline_code (struct frame_info *frame, |
138 | 161 | CORE_ADDR pc); |
139 | 162 |
@@ -32,6 +32,8 @@ | ||
32 | 32 | |
33 | 33 | /* We have one tag per 16 bytes of memory. */ |
34 | 34 | #define MTE_GRANULE_SIZE 16 |
35 | +#define MTE_LOGICAL_TAG_START_BIT 56 | |
36 | +#define MTE_LOGICAL_MAX_VALUE 0xf | |
35 | 37 | |
36 | 38 | /* Return the number of tag granules in the memory range |
37 | 39 | [ADDR, ADDR + LEN) given GRANULE_SIZE. */ |
@@ -251,6 +251,12 @@ struct gdbarch | ||
251 | 251 | gdbarch_convert_from_func_ptr_addr_ftype *convert_from_func_ptr_addr; |
252 | 252 | gdbarch_addr_bits_remove_ftype *addr_bits_remove; |
253 | 253 | 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; | |
254 | 260 | gdbarch_software_single_step_ftype *software_single_step; |
255 | 261 | gdbarch_single_step_through_delay_ftype *single_step_through_delay; |
256 | 262 | gdbarch_print_insn_ftype *print_insn; |
@@ -427,6 +433,11 @@ gdbarch_alloc (const struct gdbarch_info *info, | ||
427 | 433 | gdbarch->stabs_argument_has_addr = default_stabs_argument_has_addr; |
428 | 434 | gdbarch->convert_from_func_ptr_addr = convert_from_func_ptr_addr_identity; |
429 | 435 | 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; | |
430 | 441 | gdbarch->print_insn = default_print_insn; |
431 | 442 | gdbarch->skip_trampoline_code = generic_skip_trampoline_code; |
432 | 443 | gdbarch->skip_solib_resolver = generic_skip_solib_resolver; |
@@ -616,6 +627,12 @@ verify_gdbarch (struct gdbarch *gdbarch) | ||
616 | 627 | /* Skip verify of convert_from_func_ptr_addr, invalid_p == 0 */ |
617 | 628 | /* Skip verify of addr_bits_remove, invalid_p == 0 */ |
618 | 629 | /* 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 */ | |
619 | 636 | /* Skip verify of software_single_step, has predicate. */ |
620 | 637 | /* Skip verify of single_step_through_delay, has predicate. */ |
621 | 638 | /* Skip verify of print_insn, invalid_p == 0 */ |
@@ -1056,6 +1073,9 @@ gdbarch_dump (struct gdbarch *gdbarch, struct ui_file *file) | ||
1056 | 1073 | "gdbarch_dump: get_longjmp_target = <%s>\n", |
1057 | 1074 | host_address_to_string (gdbarch->get_longjmp_target)); |
1058 | 1075 | fprintf_unfiltered (file, |
1076 | + "gdbarch_dump: get_memtag = <%s>\n", | |
1077 | + host_address_to_string (gdbarch->get_memtag)); | |
1078 | + fprintf_unfiltered (file, | |
1059 | 1079 | "gdbarch_dump: get_pc_address_flags = <%s>\n", |
1060 | 1080 | host_address_to_string (gdbarch->get_pc_address_flags)); |
1061 | 1081 | fprintf_unfiltered (file, |
@@ -1191,6 +1211,15 @@ gdbarch_dump (struct gdbarch *gdbarch, struct ui_file *file) | ||
1191 | 1211 | "gdbarch_dump: memory_remove_breakpoint = <%s>\n", |
1192 | 1212 | host_address_to_string (gdbarch->memory_remove_breakpoint)); |
1193 | 1213 | 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, | |
1194 | 1223 | "gdbarch_dump: num_pseudo_regs = %s\n", |
1195 | 1224 | plongest (gdbarch->num_pseudo_regs)); |
1196 | 1225 | fprintf_unfiltered (file, |
@@ -1335,6 +1364,9 @@ gdbarch_dump (struct gdbarch *gdbarch, struct ui_file *file) | ||
1335 | 1364 | "gdbarch_dump: sdb_reg_to_regnum = <%s>\n", |
1336 | 1365 | host_address_to_string (gdbarch->sdb_reg_to_regnum)); |
1337 | 1366 | fprintf_unfiltered (file, |
1367 | + "gdbarch_dump: set_memtags = <%s>\n", | |
1368 | + host_address_to_string (gdbarch->set_memtags)); | |
1369 | + fprintf_unfiltered (file, | |
1338 | 1370 | "gdbarch_dump: short_bit = %s\n", |
1339 | 1371 | plongest (gdbarch->short_bit)); |
1340 | 1372 | fprintf_unfiltered (file, |
@@ -1449,6 +1481,9 @@ gdbarch_dump (struct gdbarch *gdbarch, struct ui_file *file) | ||
1449 | 1481 | "gdbarch_dump: syscalls_info = %s\n", |
1450 | 1482 | host_address_to_string (gdbarch->syscalls_info)); |
1451 | 1483 | fprintf_unfiltered (file, |
1484 | + "gdbarch_dump: tagged_address_p = <%s>\n", | |
1485 | + host_address_to_string (gdbarch->tagged_address_p)); | |
1486 | + fprintf_unfiltered (file, | |
1452 | 1487 | "gdbarch_dump: target_desc = %s\n", |
1453 | 1488 | host_address_to_string (gdbarch->target_desc)); |
1454 | 1489 | fprintf_unfiltered (file, |
@@ -3220,6 +3255,108 @@ set_gdbarch_significant_addr_bit (struct gdbarch *gdbarch, | ||
3220 | 3255 | gdbarch->significant_addr_bit = significant_addr_bit; |
3221 | 3256 | } |
3222 | 3257 | |
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 | + | |
3223 | 3360 | int |
3224 | 3361 | gdbarch_software_single_step_p (struct gdbarch *gdbarch) |
3225 | 3362 | { |
@@ -115,6 +115,18 @@ enum function_call_return_method | ||
115 | 115 | return_method_struct, |
116 | 116 | }; |
117 | 117 | |
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 | + | |
118 | 130 | |
119 | 131 | |
120 | 132 | /* The following are pre-initialized by GDBARCH. */ |
@@ -705,6 +717,47 @@ extern void set_gdbarch_addr_bits_remove (struct gdbarch *gdbarch, gdbarch_addr_ | ||
705 | 717 | extern int gdbarch_significant_addr_bit (struct gdbarch *gdbarch); |
706 | 718 | extern void set_gdbarch_significant_addr_bit (struct gdbarch *gdbarch, int significant_addr_bit); |
707 | 719 | |
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 | + | |
708 | 761 | /* FIXME/cagney/2001-01-18: This should be split in two. A target method that |
709 | 762 | indicates if the target needs software single step. An ISA method to |
710 | 763 | implement it. |
@@ -604,6 +604,30 @@ m;CORE_ADDR;addr_bits_remove;CORE_ADDR addr;addr;;core_addr_identity;;0 | ||
604 | 604 | # additional data associated with the address. |
605 | 605 | v;int;significant_addr_bit;;;;;;0 |
606 | 606 | |
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 | + | |
607 | 631 | # FIXME/cagney/2001-01-18: This should be split in two. A target method that |
608 | 632 | # indicates if the target needs software single step. An ISA method to |
609 | 633 | # implement it. |
@@ -1355,6 +1379,18 @@ enum function_call_return_method | ||
1355 | 1379 | return_method_struct, |
1356 | 1380 | }; |
1357 | 1381 | |
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 | + | |
1358 | 1394 | EOF |
1359 | 1395 | |
1360 | 1396 | # function typedef's |