From: Luis Machado <luis.machado@linaro.org>
To: gdb-patches@sourceware.org, simon.marchi@polymtl.ca
Cc: alan.hayward@arm.com, jhb@FreeBSD.org, david.spickett@linaro.org,
catalin.marinas@arm.com
Subject: [PATCH,v4][AArch64] MTE corefile support
Date: Mon, 31 May 2021 13:44:20 -0300 [thread overview]
Message-ID: <20210531164420.4081735-1-luis.machado@linaro.org> (raw)
In-Reply-To: <20210518202047.3492211-1-luis.machado@linaro.org>
Updates on v4:
- Calculate sizes based on individual struct field sizes.
Updates on v3:
- Addressed review comments.
- New files gdbsupport/memtag.h, gdb/memtag.h and gdb/memtag.c.
- Updated code documentation.
- Removed code duplication.
Updates on v2:
- Reworked core_target::fetch_memtags to handle cases where address + len runs
over the NT_MEMTAG note.
- Turned a few magic numbers into constants. There is an unfortunate duplication
of a constant (NT_MEMTAG_HEADER_SIZE). It is a generic constant, but there is
no file generic enough that gets included by both corelow and linux-tdep.
- More sanity checks to make sure the note format is correct.
- Documented aarch64_linux_decode_memtag_note a little more.
---
Teach GDB how to dump memory tags when using the gcore command and how
to read them back from a core file generated via gcore or the kernel.
Each tagged memory range (listed in /proc/<pid>/smaps) gets dumped to its
own NT_MEMTAG note. A section named ".memtag" is created for each of those
when reading the core file back.
Dumping memory tags
-
When using the gcore command to dump a core file, GDB will go through the maps
in /proc/<pid>/smaps looking for tagged ranges. Each of those entries gets
passed to an arch-specific gdbarch hook that generates a vector of blobs of
memory tag data that are blindly put into a NT_MEMTAG note.
The vector is used because we may have, in the future, multiple tag types for
a particular memory range.
Each of the NT_MEMTAG notes have a generic header and a arch-specific header,
like so:
struct tag_dump_header
{
uint16_t format; // Only NT_MEMTAG_TYPE_AARCH_MTE at present
uint64_t start_vma;
uint64_t end_vma;
};
struct tag_dump_mte
{
uint16_t granule_byte_size;
uint16_t tag_bit_size;
uint16_t __unused;
};
The only bits meant to be generic are the tag_dump_format, start_vma and
end_vma fields.
The format-specific data is supposed to be opaque and only useful for the
arch-specific code.
We can extend the format in the future to make room for other memory tag
layouts.
Reading memory tags
-
When reading a core file that contains NT_MEMTAG entries, GDB will use
a different approach to check for tagged memory range. Rather than looking
at /proc/<pid>/smaps, it will now look for ".memtag" sections with the right
memory range.
When reading tags, GDB will now use the core target's implementation of
fetch_memtags (store_memtags doesn't exist for core targets). Then the data
is fed into an arch-specific hook that will decode the memory tag format and
return a vector of tags.
I've added a test to exercise writing and reading of memory tags in core
files.
gdb/ChangeLog:
YYYY-MM-DD Luis Machado <luis.machado@linaro.org>
* Makefile.in (COMMON_SFILES): Add memtag.c.
* NEWS: Mention core file support for memory tagging.
* aarch64-linux-tdep.c: Include elf/common.h.
Include gdbsupport/memtag.h.
(MAX_TAGS_TO_TRANSFER): New constant.
(aarch64_linux_create_memtag_notes_from_range): New function.
(aarch64_linux_decode_memtag_note): Likewise.
(aarch64_linux_init_abi): Register new core file hooks.
(NT_MEMTAG_TOTAL_HEADER_SIZE): New constant.
* arch/aarch64-mte-linux.h (tag_dump_mte): New struct.
(AARCH64_MTE_TAG_BIT_SIZE): New constant.
* corelow.c: Include gdbsupport/memtag.h and memtag.h.
(core_target) <supports_memory_tagging, fetch_memtags>: New
method overrides.
* gdbarch.c: Regenerate.
* gdbarch.h: Likewise.
* gdbarch.sh (create_memtag_notes_from_range): New hook.
(decode_memtag_note): Likewise.
* linux-tdep.c: Include gdbsupport/memtag.h and memtag.h.
(linux_address_in_memtag_page): Renamed to...
(linux_process_address_in_memtag_page): ... this.
(linux_core_file_address_in_memtag_page): New function.
(linux_address_in_memtag_page): Likewise.
(linux_make_memtag_corefile_notes): Likewise.
(linux_make_corefile_notes): Handle memory tag notes.
* memtag.c: New file.
* memtag.h: New file.
gdb/doc/ChangeLog:
YYYY-MM-DD Luis Machado <luis.machado@linaro.org>
* gdb.texinfo (AArch64 Memory Tagging Extension): Mention support
for memory tagging in core files.
gdb/testsuite/ChangeLog:
YYYY-MM-DD Luis Machado <luis.machado@linaro.org>
* gdb.arch/aarch64-mte-gcore.c: New file.
* gdb.arch/aarch64-mte-gcore.exp: New file.
gdbsupport/ChangeLog:
YYYY-MM-DD Luis Machado <luis.machado@linaro.org>
* memtag.h: New file.
---
gdb/Makefile.in | 1 +
gdb/NEWS | 4 +
gdb/aarch64-linux-tdep.c | 221 +++++++++++++++++++
gdb/arch/aarch64-mte-linux.h | 17 ++
gdb/corelow.c | 63 ++++++
gdb/doc/gdb.texinfo | 4 +
gdb/gdbarch.c | 64 ++++++
gdb/gdbarch.h | 16 ++
gdb/gdbarch.sh | 6 +
gdb/linux-tdep.c | 97 +++++++-
gdb/memtag.c | 88 ++++++++
gdb/memtag.h | 46 ++++
gdb/testsuite/gdb.arch/aarch64-mte-gcore.c | 93 ++++++++
gdb/testsuite/gdb.arch/aarch64-mte-gcore.exp | 111 ++++++++++
gdbsupport/memtag.h | 39 ++++
15 files changed, 867 insertions(+), 3 deletions(-)
create mode 100644 gdb/memtag.c
create mode 100644 gdb/memtag.h
create mode 100644 gdb/testsuite/gdb.arch/aarch64-mte-gcore.c
create mode 100644 gdb/testsuite/gdb.arch/aarch64-mte-gcore.exp
create mode 100644 gdbsupport/memtag.h
diff --git a/gdb/Makefile.in b/gdb/Makefile.in
index bb6c5dfa784..89149c17808 100644
--- a/gdb/Makefile.in
+++ b/gdb/Makefile.in
@@ -1099,6 +1099,7 @@ COMMON_SFILES = \
memattr.c \
memory-map.c \
memrange.c \
+ memtag.c \
minidebug.c \
minsyms.c \
mipsread.c \
diff --git a/gdb/NEWS b/gdb/NEWS
index ab678acec8b..58b9f739d4f 100644
--- a/gdb/NEWS
+++ b/gdb/NEWS
@@ -3,6 +3,10 @@
*** Changes since GDB 10
+* GDB now supports dumping memory tag data for AArch64 MTE. It also supports
+ reading memory tag data for AArch64 MTE from core files generated by
+ the gcore command or the Linux kernel.
+
* GDB now supports general memory tagging functionality if the underlying
architecture supports the proper primitives and hooks. Currently this is
enabled only for AArch64 MTE.
diff --git a/gdb/aarch64-linux-tdep.c b/gdb/aarch64-linux-tdep.c
index e9761ed2189..b4a8d09d5e2 100644
--- a/gdb/aarch64-linux-tdep.c
+++ b/gdb/aarch64-linux-tdep.c
@@ -52,6 +52,9 @@
#include "value.h"
#include "gdbsupport/selftest.h"
+#include "gdbsupport/memtag.h"
+
+#include "elf/common.h"
/* Signal frame handling.
@@ -1779,6 +1782,213 @@ aarch64_linux_report_signal_info (struct gdbarch *gdbarch,
}
}
+/* Memory tag note header size. Includes both the generic and the
+ arch-specific parts. */
+#define NT_MEMTAG_TOTAL_HEADER_SIZE (NT_MEMTAG_GENERIC_HEADER_SIZE \
+ + NT_MEMTAG_MTE_HEADER_SIZE)
+
+/* Maximum number of tags to request. */
+#define MAX_TAGS_TO_TRANSFER 1024
+
+/* AArch64 Linux implementation of the aarch64_create_memtag_notes_from_range
+ gdbarch hook. Create core file notes for memory tags. */
+
+static std::vector<gdb::byte_vector>
+aarch64_linux_create_memtag_notes_from_range (struct gdbarch *gdbarch,
+ CORE_ADDR start_address,
+ CORE_ADDR end_address)
+{
+ /* We only handle MTE tags for now. */
+
+ /* Figure out how many tags we need to store in this memory range. */
+ size_t granules = aarch64_mte_get_tag_granules (start_address,
+ end_address - start_address,
+ AARCH64_MTE_GRANULE_SIZE);
+
+ /* Vector of memory tag notes. Add the MTE note (we only have MTE tags
+ at the moment). */
+ std::vector<gdb::byte_vector> notes (1);
+
+ /* If there are no tag granules to fetch, just return. */
+ if (granules == 0)
+ return notes;
+
+ /* Adjust the MTE note size to hold the header + tags. */
+ notes[0].resize (NT_MEMTAG_TOTAL_HEADER_SIZE + granules);
+
+ CORE_ADDR address = start_address;
+ /* Vector of tags. */
+ gdb::byte_vector tags;
+
+ while (granules > 0)
+ {
+ /* Transfer tags in chunks. */
+ gdb::byte_vector tags_read;
+ size_t xfer_len
+ = (granules >= MAX_TAGS_TO_TRANSFER)?
+ MAX_TAGS_TO_TRANSFER * AARCH64_MTE_GRANULE_SIZE :
+ granules * AARCH64_MTE_GRANULE_SIZE;
+
+ if (!target_fetch_memtags (address, xfer_len, tags_read,
+ static_cast<int> (memtag_type::allocation)))
+ {
+ warning (_("Failed to read MTE tags from memory range [%s,%s]."),
+ phex_nz (start_address, sizeof (start_address)),
+ phex_nz (end_address, sizeof (end_address)));
+ notes.resize (0);
+ return notes;
+ }
+
+ /* Transfer over the tags that have been read. */
+ tags.insert (tags.end (), tags_read.begin (), tags_read.end ());
+
+ /* Adjust the remaining granules and starting address. */
+ granules -= tags_read.size ();
+ address += tags_read.size () * AARCH64_MTE_GRANULE_SIZE;
+ }
+
+ /* Create the header. */
+ enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
+ gdb_byte *buf = notes[0].data ();
+
+ /* Generic header. */
+ /* Tag dump format */
+ store_unsigned_integer (buf, sizeof (tag_dump_header::format),
+ byte_order, NT_MEMTAG_TYPE_AARCH_MTE);
+ buf += sizeof (tag_dump_header::format);
+
+ /* Start address */
+ store_unsigned_integer (buf, sizeof (tag_dump_header::start_vma),
+ byte_order, start_address);
+ buf += sizeof (tag_dump_header::start_vma);
+
+ /* End address */
+ store_unsigned_integer (buf, sizeof (tag_dump_header::end_vma),
+ byte_order, end_address);
+ buf += sizeof (tag_dump_header::end_vma);
+
+ /* MTE-specific header. */
+ /* Granule byte size */
+ store_unsigned_integer (buf, sizeof (tag_dump_mte::granule_byte_size),
+ byte_order, AARCH64_MTE_GRANULE_SIZE);
+ buf += sizeof (tag_dump_mte::granule_byte_size);
+
+ /* Tag bit size */
+ store_unsigned_integer (buf, sizeof (tag_dump_mte::tag_bit_size),
+ byte_order, AARCH64_MTE_TAG_BIT_SIZE);
+ buf += sizeof (tag_dump_mte::tag_bit_size);
+
+ /* Unused value */
+ store_unsigned_integer (buf, sizeof (tag_dump_mte::__unused), byte_order, 0);
+
+ /* Store the tags. */
+ memcpy (notes[0].data () + NT_MEMTAG_TOTAL_HEADER_SIZE, tags.data (),
+ tags.size ());
+
+ return notes;
+}
+
+/* AArch64 Linux implementation of the decode_memtag_note gdbarch
+ hook. Decode a memory tag note and return the requested tags.
+
+ The note is guaranteed to cover the [ADDRESS, ADDRESS + length)
+ range. */
+
+static gdb::byte_vector
+aarch64_linux_decode_memtag_note (struct gdbarch *gdbarch,
+ gdb::array_view <const gdb_byte> note,
+ CORE_ADDR address, size_t length)
+{
+ gdb::byte_vector tags;
+
+ /* Sanity check. */
+ if (note.size () < NT_MEMTAG_TOTAL_HEADER_SIZE)
+ {
+ warning (_("Malformed core note - too short for MTE header.\n"
+ "Expected %s bytes but got %s bytes."),
+ pulongest (NT_MEMTAG_TOTAL_HEADER_SIZE),
+ pulongest (note.size ()));
+ return tags;
+ }
+
+ /* The amount of memory tag granules we need to fetch. */
+ size_t granules
+ = aarch64_mte_get_tag_granules (address, length, AARCH64_MTE_GRANULE_SIZE);
+
+ /* If there are no tag granules to decode, just return. */
+ if (granules == 0)
+ return tags;
+
+ /* Read the generic header. */
+ enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
+ const gdb_byte *buf = note.data ();
+
+ unsigned int format
+ = extract_unsigned_integer (buf, sizeof (tag_dump_header::format),
+ byte_order);
+ buf += sizeof (tag_dump_header::format);
+
+ CORE_ADDR start_vma
+ = extract_unsigned_integer (buf, sizeof (tag_dump_header::start_vma),
+ byte_order);
+ buf += sizeof (tag_dump_header::start_vma);
+
+ CORE_ADDR end_vma
+ = extract_unsigned_integer (buf, sizeof (tag_dump_header::end_vma),
+ byte_order);
+ buf += sizeof (tag_dump_header::end_vma);
+
+ /* Validate that ADDRESS + LENGTH doesn't fall outside of this note's
+ range of addresses. */
+ gdb_assert (address + length < end_vma);
+
+ /* Is the tag header format correct for this note? */
+ if (format != NT_MEMTAG_TYPE_AARCH_MTE)
+ {
+ warning (_("Unexpected memory tag note format.\n"
+ "Expected %lx but got %x."), NT_MEMTAG_MTE_HEADER_SIZE,
+ format);
+ return tags;
+ }
+
+ size_t expected_tag_bytes = (end_vma - start_vma)/AARCH64_MTE_GRANULE_SIZE;
+
+ /* Does the number of tag bytes in this note match the expected number
+ of tag bytes the note says it has? */
+ if (note.size () < (NT_MEMTAG_TOTAL_HEADER_SIZE + expected_tag_bytes))
+ {
+ warning (_("Unexpected tag data size.\n"
+ "Expected %s but got %s."), pulongest (expected_tag_bytes),
+ pulongest (note.size () - NT_MEMTAG_TOTAL_HEADER_SIZE));
+ return tags;
+ }
+
+ /* Calculate how many granules we need to skip to get to the granule of
+ ADDRESS. Align both the start address and the requested address
+ so it is easier to get the number of granules to skip. This way we
+ don't need to consider cases where ADDRESS falls in the middle of a
+ tag granule range. */
+ CORE_ADDR aligned_start_address
+ = align_down (start_vma, AARCH64_MTE_GRANULE_SIZE);
+ CORE_ADDR aligned_address = align_down (address, AARCH64_MTE_GRANULE_SIZE);
+
+ size_t skipped_granules
+ = aarch64_mte_get_tag_granules (aligned_start_address,
+ aligned_address - aligned_start_address,
+ AARCH64_MTE_GRANULE_SIZE);
+
+ /* Point to the block of data that contains the first granule we are
+ interested in. */
+ const gdb::array_view<const gdb_byte> tags_data
+ = note.slice (NT_MEMTAG_TOTAL_HEADER_SIZE + skipped_granules, granules);
+
+ /* Read the tag granules. */
+ for (size_t i = 0; i < granules; i++)
+ tags.push_back (tags_data[i]);
+
+ return tags;
+}
+
static void
aarch64_linux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
{
@@ -1862,6 +2072,17 @@ aarch64_linux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
set_gdbarch_report_signal_info (gdbarch,
aarch64_linux_report_signal_info);
+
+ /* Core file helpers. */
+
+ /* Core file helper to create memory tag notes for a particular range of
+ addresses. */
+ set_gdbarch_create_memtag_notes_from_range
+ (gdbarch, aarch64_linux_create_memtag_notes_from_range);
+
+ /* Core file helper to decode a memory tag note. */
+ set_gdbarch_decode_memtag_note (gdbarch,
+ aarch64_linux_decode_memtag_note);
}
/* Initialize the aarch64_linux_record_tdep. */
diff --git a/gdb/arch/aarch64-mte-linux.h b/gdb/arch/aarch64-mte-linux.h
index 2aa97eb861a..7da9de4aefb 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,20 @@ 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);
+/* NT_MEMTAG header for MTE tags. */
+struct tag_dump_mte
+{
+ /* Size of the tag granule in bytes. */
+ uint16_t granule_byte_size;
+ /* Size of the tag in bits. */
+ uint16_t tag_bit_size;
+ /* Reserved field for the future. */
+ uint16_t __unused;
+};
+
+/* Size of the MTE header for a NT_MEMTAG note. */
+#define NT_MEMTAG_MTE_HEADER_SIZE (sizeof (tag_dump_mte::granule_byte_size) \
+ + sizeof (tag_dump_mte::tag_bit_size) \
+ + sizeof (tag_dump_mte::__unused))
+
#endif /* ARCH_AARCH64_LINUX_H */
diff --git a/gdb/corelow.c b/gdb/corelow.c
index 452b4dd4f9a..24c5bf29a11 100644
--- a/gdb/corelow.c
+++ b/gdb/corelow.c
@@ -51,6 +51,8 @@
#include "gdbcmd.h"
#include "xml-tdesc.h"
#include "observable.h"
+#include "gdbsupport/memtag.h"
+#include "memtag.h"
#ifndef O_LARGEFILE
#define O_LARGEFILE 0
@@ -100,6 +102,13 @@ class core_target final : public process_stratum_target
bool info_proc (const char *, enum info_proc_what) override;
+ bool supports_memory_tagging () override;
+
+ /* Core file implementation of fetch_memtags. Fetch the memory tags from
+ core file notes. */
+ bool fetch_memtags (CORE_ADDR address, size_t len,
+ gdb::byte_vector &tags, int type) override;
+
/* A few helpers. */
/* Getter, see variable definition. */
@@ -1115,6 +1124,60 @@ core_target::info_proc (const char *args, enum info_proc_what request)
return true;
}
+/* Implementation of the "supports_memory_tagging" target_ops method. */
+
+bool
+core_target::supports_memory_tagging ()
+{
+ /* Look for memory tag notes. If they exist, that means this core file
+ supports memory tagging. */
+
+ return (bfd_get_section_by_name (core_bfd, ".memtag") != nullptr);
+}
+
+/* Implementation of the "fetch_memtags" target_ops method. */
+
+bool
+core_target::fetch_memtags (CORE_ADDR address, size_t len,
+ gdb::byte_vector &tags, int type)
+{
+ struct gdbarch *gdbarch = target_gdbarch ();
+
+ /* Make sure we have a way to decode the memory tag notes. */
+ if (!gdbarch_decode_memtag_note_p (gdbarch))
+ error (_("gdbarch_decode_memtag_note not implemented for this "
+ "architecture."));
+
+ memtag_note_info info;
+ info.memtag_section = nullptr;
+
+ while (get_next_core_memtag_section (core_bfd, info.memtag_section,
+ address, info))
+ {
+ size_t adjusted_length
+ = (address + len < info.end_address)? len : (info.end_address - address);
+
+ /* Decode the memory tag note and return the tags. */
+ gdb::byte_vector tags_read
+ = gdbarch_decode_memtag_note (gdbarch, info.note, address,
+ adjusted_length);
+
+ /* Transfer over the tags that have been read. */
+ tags.insert (tags.end (), tags_read.begin (), tags_read.end ());
+
+ /* ADDRESS + LEN may cross the boundaries of a particular NT_MEMTAG
+ note. Check if we need to fetch tags from a different section. */
+ if (address + len < info.end_address)
+ return true;
+
+ /* There are more tags to fetch. Update ADDRESS and LEN. */
+ len -= (info.end_address - address);
+ address = info.end_address;
+ }
+
+ return false;
+}
+
/* Get a pointer to the current core target. If not connected to a
core target, return NULL. */
diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo
index 90d827a50e7..1b001e6cacb 100644
--- a/gdb/doc/gdb.texinfo
+++ b/gdb/doc/gdb.texinfo
@@ -25257,6 +25257,10 @@ options that can be controlled at runtime and emulates the @code{prctl}
option @code{PR_SET_TAGGED_ADDR_CTRL}. For further information, see the
documentation in the Linux kernel.
+@value{GDBN} supports dumping memory tag data to core files through the
+@command{gcore} command and reading memory tag data from core files generated
+by the @command{gcore} command or the Linux kernel.
+
@node i386
@subsection x86 Architecture-specific Issues
diff --git a/gdb/gdbarch.c b/gdb/gdbarch.c
index 208cf4b5aaa..de384da2e9a 100644
--- a/gdb/gdbarch.c
+++ b/gdb/gdbarch.c
@@ -283,6 +283,8 @@ struct gdbarch
gdbarch_iterate_over_regset_sections_ftype *iterate_over_regset_sections;
gdbarch_make_corefile_notes_ftype *make_corefile_notes;
gdbarch_find_memory_regions_ftype *find_memory_regions;
+ gdbarch_create_memtag_notes_from_range_ftype *create_memtag_notes_from_range;
+ gdbarch_decode_memtag_note_ftype *decode_memtag_note;
gdbarch_core_xfer_shared_libraries_ftype *core_xfer_shared_libraries;
gdbarch_core_xfer_shared_libraries_aix_ftype *core_xfer_shared_libraries_aix;
gdbarch_core_pid_to_str_ftype *core_pid_to_str;
@@ -667,6 +669,8 @@ verify_gdbarch (struct gdbarch *gdbarch)
/* Skip verify of iterate_over_regset_sections, has predicate. */
/* Skip verify of make_corefile_notes, has predicate. */
/* Skip verify of find_memory_regions, has predicate. */
+ /* Skip verify of create_memtag_notes_from_range, has predicate. */
+ /* Skip verify of decode_memtag_note, has predicate. */
/* Skip verify of core_xfer_shared_libraries, has predicate. */
/* Skip verify of core_xfer_shared_libraries_aix, has predicate. */
/* Skip verify of core_pid_to_str, has predicate. */
@@ -925,6 +929,18 @@ gdbarch_dump (struct gdbarch *gdbarch, struct ui_file *file)
fprintf_unfiltered (file,
"gdbarch_dump: core_xfer_siginfo = <%s>\n",
host_address_to_string (gdbarch->core_xfer_siginfo));
+ fprintf_unfiltered (file,
+ "gdbarch_dump: gdbarch_create_memtag_notes_from_range_p() = %d\n",
+ gdbarch_create_memtag_notes_from_range_p (gdbarch));
+ fprintf_unfiltered (file,
+ "gdbarch_dump: create_memtag_notes_from_range = <%s>\n",
+ host_address_to_string (gdbarch->create_memtag_notes_from_range));
+ fprintf_unfiltered (file,
+ "gdbarch_dump: gdbarch_decode_memtag_note_p() = %d\n",
+ gdbarch_decode_memtag_note_p (gdbarch));
+ fprintf_unfiltered (file,
+ "gdbarch_dump: decode_memtag_note = <%s>\n",
+ host_address_to_string (gdbarch->decode_memtag_note));
fprintf_unfiltered (file,
"gdbarch_dump: decr_pc_after_break = %s\n",
core_addr_to_string_nz (gdbarch->decr_pc_after_break));
@@ -3898,6 +3914,54 @@ set_gdbarch_find_memory_regions (struct gdbarch *gdbarch,
gdbarch->find_memory_regions = find_memory_regions;
}
+bool
+gdbarch_create_memtag_notes_from_range_p (struct gdbarch *gdbarch)
+{
+ gdb_assert (gdbarch != NULL);
+ return gdbarch->create_memtag_notes_from_range != NULL;
+}
+
+std::vector<gdb::byte_vector>
+gdbarch_create_memtag_notes_from_range (struct gdbarch *gdbarch, CORE_ADDR start_address, CORE_ADDR end_address)
+{
+ gdb_assert (gdbarch != NULL);
+ gdb_assert (gdbarch->create_memtag_notes_from_range != NULL);
+ if (gdbarch_debug >= 2)
+ fprintf_unfiltered (gdb_stdlog, "gdbarch_create_memtag_notes_from_range called\n");
+ return gdbarch->create_memtag_notes_from_range (gdbarch, start_address, end_address);
+}
+
+void
+set_gdbarch_create_memtag_notes_from_range (struct gdbarch *gdbarch,
+ gdbarch_create_memtag_notes_from_range_ftype create_memtag_notes_from_range)
+{
+ gdbarch->create_memtag_notes_from_range = create_memtag_notes_from_range;
+}
+
+bool
+gdbarch_decode_memtag_note_p (struct gdbarch *gdbarch)
+{
+ gdb_assert (gdbarch != NULL);
+ return gdbarch->decode_memtag_note != NULL;
+}
+
+gdb::byte_vector
+gdbarch_decode_memtag_note (struct gdbarch *gdbarch, gdb::array_view<const gdb_byte> note, CORE_ADDR address, size_t length)
+{
+ gdb_assert (gdbarch != NULL);
+ gdb_assert (gdbarch->decode_memtag_note != NULL);
+ if (gdbarch_debug >= 2)
+ fprintf_unfiltered (gdb_stdlog, "gdbarch_decode_memtag_note called\n");
+ return gdbarch->decode_memtag_note (gdbarch, note, address, length);
+}
+
+void
+set_gdbarch_decode_memtag_note (struct gdbarch *gdbarch,
+ gdbarch_decode_memtag_note_ftype decode_memtag_note)
+{
+ gdbarch->decode_memtag_note = decode_memtag_note;
+}
+
bool
gdbarch_core_xfer_shared_libraries_p (struct gdbarch *gdbarch)
{
diff --git a/gdb/gdbarch.h b/gdb/gdbarch.h
index 7157e5596fd..80e244624de 100644
--- a/gdb/gdbarch.h
+++ b/gdb/gdbarch.h
@@ -980,6 +980,22 @@ typedef int (gdbarch_find_memory_regions_ftype) (struct gdbarch *gdbarch, find_m
extern int gdbarch_find_memory_regions (struct gdbarch *gdbarch, find_memory_region_ftype func, void *data);
extern void set_gdbarch_find_memory_regions (struct gdbarch *gdbarch, gdbarch_find_memory_regions_ftype *find_memory_regions);
+/* Create memory tag core file notes given a range of addresses. */
+
+extern bool gdbarch_create_memtag_notes_from_range_p (struct gdbarch *gdbarch);
+
+typedef std::vector<gdb::byte_vector> (gdbarch_create_memtag_notes_from_range_ftype) (struct gdbarch *gdbarch, CORE_ADDR start_address, CORE_ADDR end_address);
+extern std::vector<gdb::byte_vector> gdbarch_create_memtag_notes_from_range (struct gdbarch *gdbarch, CORE_ADDR start_address, CORE_ADDR end_address);
+extern void set_gdbarch_create_memtag_notes_from_range (struct gdbarch *gdbarch, gdbarch_create_memtag_notes_from_range_ftype *create_memtag_notes_from_range);
+
+/* Decode a memory tag note and return the tags that it contains. */
+
+extern bool gdbarch_decode_memtag_note_p (struct gdbarch *gdbarch);
+
+typedef gdb::byte_vector (gdbarch_decode_memtag_note_ftype) (struct gdbarch *gdbarch, gdb::array_view<const gdb_byte> note, CORE_ADDR address, size_t length);
+extern gdb::byte_vector gdbarch_decode_memtag_note (struct gdbarch *gdbarch, gdb::array_view<const gdb_byte> note, CORE_ADDR address, size_t length);
+extern void set_gdbarch_decode_memtag_note (struct gdbarch *gdbarch, gdbarch_decode_memtag_note_ftype *decode_memtag_note);
+
/* Read offset OFFSET of TARGET_OBJECT_LIBRARIES formatted shared libraries list from
core file into buffer READBUF with length LEN. Return the number of bytes read
(zero indicates failure).
diff --git a/gdb/gdbarch.sh b/gdb/gdbarch.sh
index 43e51341f97..7c5eed0780c 100755
--- a/gdb/gdbarch.sh
+++ b/gdb/gdbarch.sh
@@ -745,6 +745,12 @@ M;gdb::unique_xmalloc_ptr<char>;make_corefile_notes;bfd *obfd, int *note_size;ob
# Find core file memory regions
M;int;find_memory_regions;find_memory_region_ftype func, void *data;func, data
+# Create memory tag core file notes given a range of addresses.
+M;std::vector<gdb::byte_vector>;create_memtag_notes_from_range;CORE_ADDR start_address, CORE_ADDR end_address;start_address, end_address
+
+# Decode a memory tag note and return the tags that it contains.
+M;gdb::byte_vector;decode_memtag_note;gdb::array_view<const gdb_byte> note, CORE_ADDR address, size_t length;note, address, length
+
# Read offset OFFSET of TARGET_OBJECT_LIBRARIES formatted shared libraries list from
# core file into buffer READBUF with length LEN. Return the number of bytes read
# (zero indicates failure).
diff --git a/gdb/linux-tdep.c b/gdb/linux-tdep.c
index 927e69bf1e1..6192cc4421b 100644
--- a/gdb/linux-tdep.c
+++ b/gdb/linux-tdep.c
@@ -41,6 +41,8 @@
#include "gdbsupport/gdb_optional.h"
#include "gcore.h"
#include "gcore-elf.h"
+#include "gdbsupport/memtag.h"
+#include "memtag.h"
#include <ctype.h>
@@ -1438,10 +1440,11 @@ parse_smaps_data (const char *data,
return smaps;
}
-/* See linux-tdep.h. */
+/* Helper that checks if an address is in a memory tag page for a live
+ process. */
-bool
-linux_address_in_memtag_page (CORE_ADDR address)
+static bool
+linux_process_address_in_memtag_page (CORE_ADDR address)
{
if (current_inferior ()->fake_pid_p)
return false;
@@ -1473,6 +1476,91 @@ linux_address_in_memtag_page (CORE_ADDR address)
return false;
}
+/* Helper that checks if an address is in a memory tag page for a core file
+ process. */
+
+static bool
+linux_core_file_address_in_memtag_page (CORE_ADDR address)
+{
+ if (core_bfd == nullptr)
+ return false;
+
+ memtag_note_info info;
+ return get_next_core_memtag_section (core_bfd, nullptr, address, info);
+}
+
+/* See linux-tdep.h. */
+
+bool
+linux_address_in_memtag_page (CORE_ADDR address)
+{
+ if (!target_has_execution ())
+ return linux_core_file_address_in_memtag_page (address);
+
+ return linux_process_address_in_memtag_page (address);
+}
+
+/* For each memory map entry that has memory tagging enabled, create a new
+ core file note that contains all of its memory tags. Save the data to
+ NOTE_DATA and update NOTE_SIZE accordingly. */
+
+static void
+linux_make_memtag_corefile_notes (struct gdbarch *gdbarch, bfd *obfd,
+ gdb::unique_xmalloc_ptr<char> ¬e_data,
+ int *note_size)
+{
+ if (current_inferior ()->fake_pid_p)
+ return;
+
+ /* If the architecture doesn't have a hook to return memory tag notes,
+ there is nothing left to do. */
+ if (!gdbarch_create_memtag_notes_from_range_p (gdbarch))
+ return;
+
+ pid_t pid = current_inferior ()->pid;
+
+ std::string smaps_file = string_printf ("/proc/%d/smaps", pid);
+
+ gdb::unique_xmalloc_ptr<char> data
+ = target_fileio_read_stralloc (NULL, smaps_file.c_str ());
+
+ if (data == nullptr)
+ return;
+
+ /* Parse the contents of smaps into a vector. */
+ std::vector<struct smaps_data> smaps
+ = parse_smaps_data (data.get (), smaps_file);
+
+ for (const smaps_data &map : smaps)
+ {
+ /* Does this mapping have memory tagging enabled? If so, save the
+ memory tags to the core file note. */
+ if (map.vmflags.memory_tagging == 0)
+ continue;
+
+ /* Ask the architecture to create (one or more) NT_MEMTAG notes for
+ this particular memory range, including the header.
+
+ If the notes are too big, we may need to break up the transfer
+ into smaller chunks.
+
+ If the architecture returns an empty vector, that means there are
+ no memory tag notes to write. */
+ std::vector<gdb::byte_vector> memory_tag_notes
+ = gdbarch_create_memtag_notes_from_range (gdbarch,
+ map.start_address,
+ map.end_address);
+ /* Write notes to the core file. */
+ for (const gdb::byte_vector ¬e : memory_tag_notes)
+ {
+ note_data.reset (elfcore_write_note (obfd, note_data.release (),
+ note_size, "CORE",
+ NT_MEMTAG, note.data (),
+ note.size ()));
+ }
+ }
+}
+
/* List memory regions in the inferior for a corefile. */
static int
@@ -2051,6 +2139,9 @@ linux_make_corefile_notes (struct gdbarch *gdbarch, bfd *obfd, int *note_size)
return NULL;
}
+ /* Dump the memory tags, if any. */
+ linux_make_memtag_corefile_notes (gdbarch, obfd, note_data, note_size);
+
/* File mappings. */
linux_make_mappings_corefile_notes (gdbarch, obfd, note_data, note_size);
diff --git a/gdb/memtag.c b/gdb/memtag.c
new file mode 100644
index 00000000000..4d92ecde84a
--- /dev/null
+++ b/gdb/memtag.c
@@ -0,0 +1,88 @@
+/* GDB generic memory tagging functions.
+
+ Copyright (C) 2021 Free Software Foundation, Inc.
+
+ This file is part of GDB.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>. */
+
+#include "defs.h"
+#include "memtag.h"
+#include "gdbsupport/memtag.h"
+#include "bfd.h"
+
+/* Helper function to walk through NT_MEMTAG notes in a core file.
+
+ Return a pointer to a .memtag section containing ADDRESS or nullptr
+ of none are found.
+
+ If SECTION is provided, search from that section onwards. */
+
+bool
+get_next_core_memtag_section (bfd *abfd, asection *section,
+ CORE_ADDR address, memtag_note_info &info)
+{
+ /* If SECTION is nullptr, start a fresh lookup. */
+ if (section == nullptr)
+ section = bfd_get_section_by_name (abfd, ".memtag");
+
+ /* Go through all the memtag sections and figure out if ADDRESS
+ falls within one of the memory ranges that contain tags. */
+ while (section != nullptr)
+ {
+ size_t note_size = bfd_section_size (section);
+
+ /* If the note is smaller than the size of the header, this core note
+ is malformed. */
+ if (note_size < NT_MEMTAG_GENERIC_HEADER_SIZE)
+ {
+ warning (_("Malformed core note - too short for NT_MEMTAG generic "
+ "header.\n"
+ "Expected %s bytes but got %s bytes."),
+ pulongest (NT_MEMTAG_GENERIC_HEADER_SIZE),
+ pulongest (note_size));
+ return false;
+ }
+
+ gdb::byte_vector note (note_size);
+
+ /* Fetch the contents of this particular memtag note. */
+ if (!bfd_get_section_contents (abfd, section,
+ note.data (), 0, note_size))
+ {
+ warning (_("could not get core note contents."));
+ return false;
+ }
+
+ /* Read the generic header of the note. It contains the format,
+ start address and end address. */
+ uint64_t start_address
+ = bfd_get_64 (abfd, note.data () + sizeof (tag_dump_header::format));
+ uint64_t end_address
+ = bfd_get_64 (abfd, note.data () + sizeof (tag_dump_header::format)
+ + sizeof (tag_dump_header::start_vma));
+
+ /* Is the address within [start_address, end_address)? */
+ if (address >= start_address
+ && address < end_address)
+ {
+ info.start_address = start_address;
+ info.end_address = end_address;
+ info.note = note;
+ info.memtag_section = section;
+ return true;
+ }
+ }
+ return false;
+}
diff --git a/gdb/memtag.h b/gdb/memtag.h
new file mode 100644
index 00000000000..43c9efb39a3
--- /dev/null
+++ b/gdb/memtag.h
@@ -0,0 +1,46 @@
+/* GDB generic memory tagging definitions.
+ Copyright (C) 2021 Free Software Foundation, Inc.
+
+ This file is part of GDB.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>. */
+
+#ifndef MEMTAG_H
+#define MEMTAG_H
+
+#include "bfd.h"
+
+struct memtag_note_info
+{
+ CORE_ADDR start_address;
+ CORE_ADDR end_address;
+ gdb::byte_vector note;
+ asection *memtag_section;
+};
+
+/* Helper function to walk through NT_MEMTAG notes in a core file.
+
+ Return TRUE if there is a .memtag section containing ADDRESS. Return FALSE
+ otherwise.
+
+ If SECTION is provided, search from that section onwards. If SECTION is
+ nullptr, then start a new search.
+
+ If a .memtag section containing ADDRESS is found, fill INFO with data
+ about such section. Otherwise leave it unchanged. */
+
+bool get_next_core_memtag_section (bfd *abfd, asection *section,
+ CORE_ADDR address, memtag_note_info &info);
+
+#endif /* MEMTAG_H */
diff --git a/gdb/testsuite/gdb.arch/aarch64-mte-gcore.c b/gdb/testsuite/gdb.arch/aarch64-mte-gcore.c
new file mode 100644
index 00000000000..b20ebcff424
--- /dev/null
+++ b/gdb/testsuite/gdb.arch/aarch64-mte-gcore.c
@@ -0,0 +1,93 @@
+/* This test program is part of GDB, the GNU debugger.
+
+ Copyright 2021 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>. */
+
+/* Exercise AArch64's Memory Tagging Extension with tagged pointers. */
+
+/* This test was based on the documentation for the AArch64 Memory Tagging
+ Extension from the Linux Kernel, found in the sources in
+ Documentation/arm64/memory-tagging-extension.rst. */
+
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <sys/auxv.h>
+#include <sys/mman.h>
+#include <sys/prctl.h>
+
+/* From arch/arm64/include/uapi/asm/hwcap.h */
+#define HWCAP2_MTE (1 << 18)
+
+/* From arch/arm64/include/uapi/asm/mman.h */
+#define PROT_MTE 0x20
+
+/* From include/uapi/linux/prctl.h */
+#define PR_SET_TAGGED_ADDR_CTRL 55
+#define PR_GET_TAGGED_ADDR_CTRL 56
+#define PR_TAGGED_ADDR_ENABLE (1UL << 0)
+#define PR_MTE_TCF_SHIFT 1
+#define PR_MTE_TCF_SYNC (1UL << PR_MTE_TCF_SHIFT)
+#define PR_MTE_TAG_SHIFT 3
+
+void
+access_memory (unsigned char *tagged_ptr)
+{
+ tagged_ptr[0] = 'a';
+}
+
+int
+main (int argc, char **argv)
+{
+ unsigned char *tagged_ptr;
+ unsigned long page_sz = sysconf (_SC_PAGESIZE);
+ unsigned long hwcap2 = getauxval(AT_HWCAP2);
+
+ /* Bail out if MTE is not supported. */
+ if (!(hwcap2 & HWCAP2_MTE))
+ return 1;
+
+ /* Enable the tagged address ABI, synchronous MTE tag check faults and
+ allow all non-zero tags in the randomly generated set. */
+ if (prctl (PR_SET_TAGGED_ADDR_CTRL,
+ PR_TAGGED_ADDR_ENABLE | PR_MTE_TCF_SYNC
+ | (0xfffe << PR_MTE_TAG_SHIFT),
+ 0, 0, 0))
+ {
+ perror ("prctl () failed");
+ return 1;
+ }
+
+ /* Create a mapping that will have PROT_MTE set. */
+ tagged_ptr = mmap (0, page_sz, PROT_READ | PROT_WRITE,
+ MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
+ if (tagged_ptr == MAP_FAILED)
+ {
+ perror ("mmap () failed");
+ return 1;
+ }
+
+ /* Enable MTE on the above anonymous mmap. */
+ if (mprotect (tagged_ptr, page_sz, PROT_READ | PROT_WRITE | PROT_MTE))
+ {
+ perror ("mprotect () failed");
+ return 1;
+ }
+
+ access_memory (tagged_ptr);
+
+ return 0;
+}
diff --git a/gdb/testsuite/gdb.arch/aarch64-mte-gcore.exp b/gdb/testsuite/gdb.arch/aarch64-mte-gcore.exp
new file mode 100644
index 00000000000..d0bcd036972
--- /dev/null
+++ b/gdb/testsuite/gdb.arch/aarch64-mte-gcore.exp
@@ -0,0 +1,111 @@
+# Copyright (C) 2018-2021 Free Software Foundation, Inc.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+# This file is part of the gdb testsuite.
+
+# Test generating and reading a core file with MTE memory tags.
+
+if {![is_aarch64_target]} {
+ verbose "Skipping ${gdb_test_file_name}."
+ return
+}
+
+standard_testfile
+if { [prepare_for_testing "failed to prepare" ${testfile} ${srcfile}] } {
+ return -1
+}
+
+if ![runto_main] {
+ untested "could not run to main"
+ return -1
+}
+
+# Targets that don't support memory tagging should not execute the
+# runtime memory tagging tests.
+if {![supports_memtag]} {
+ unsupported "memory tagging unsupported"
+ return -1
+}
+
+gdb_breakpoint "access_memory"
+
+if [gdb_continue "access_memory"] {
+ return -1
+}
+
+# Set each tag granule to a different tag value, from 0x0 to 0xf.
+set atag_msg "Allocation tag\\(s\\) updated successfully\."
+for {set i 15} {$i >= 0} {incr i -1} {
+ set index [expr [expr 15 - $i] * 16]
+ set tag [format "%02x" $i]
+ gdb_test "memory-tag set-allocation-tag &tagged_ptr\[$index\] 1 $tag" \
+ $atag_msg \
+ "set memory tag of &tagged_ptr\[$index\] to $tag"
+}
+
+# Run until a crash and confirm GDB displays memory tag violation
+# information.
+gdb_test "continue" \
+ [multi_line \
+ "Program received signal SIGSEGV, Segmentation fault" \
+ "Memory tag violation while accessing address $hex" \
+ "Allocation tag $hex" \
+ "Logical tag $hex\." \
+ "$hex in access_memory \\(.*\\) at .*" \
+ ".*tagged_ptr\\\[0\\\] = 'a';"] \
+ "display tag violation information for live process"
+
+# Generate the core file.
+set core_filename [standard_output_file "$testfile.core"]
+set core_generated [gdb_gcore_cmd "$core_filename" "generate core file"]
+
+if { !$core_generated } {
+ return -1
+}
+
+clean_restart $binfile
+
+if { $program_loaded } {
+ return -1
+}
+
+# Load the core file and make sure we see the tag violation fault
+# information.
+gdb_test "core $core_filename" \
+ [multi_line \
+ "Core was generated by.*\." \
+ "Program terminated with signal SIGSEGV, Segmentation fault" \
+ "Memory tag violation while accessing address $hex" \
+ "Allocation tag 0xf" \
+ "Logical tag 0x0\." \
+ "#0.*$hex in access_memory \\(.*\\) at .*" \
+ ".*tagged_ptr\\\[0\\\] = 'a';"] \
+ "core file shows tag violation information"
+
+# Make sure we have the tag_ctl register.
+gdb_test "info register tag_ctl" \
+ "tag_ctl.*$hex.*${::decimal}" \
+ "tag_ctl is available"
+
+# Check if the tag granules have the expected values. If they do, that
+# means the core file saved the tags properly and GDB has read them
+# correctly.
+for {set i 15} {$i >= 0} {incr i -1} {
+ set index [expr [expr 15 - $i] * 16]
+ set tag [format "%x" $i]
+ gdb_test "memory-tag print-allocation-tag &tagged_ptr\[$index\]" \
+ "= 0x$tag" \
+ "memory tag of &tagged_ptr\[$index\] is correct"
+}
diff --git a/gdbsupport/memtag.h b/gdbsupport/memtag.h
new file mode 100644
index 00000000000..bb47eed220b
--- /dev/null
+++ b/gdbsupport/memtag.h
@@ -0,0 +1,39 @@
+/* Generic memory tagging definitions.
+ Copyright (C) 2021 Free Software Foundation, Inc.
+
+ This file is part of GDB.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>. */
+
+#ifndef GDBSUPPORT_MEMTAG_H
+#define GDBSUPPORT_MEMTAG_H
+
+/* Generic NT_MEMTAG header. */
+struct tag_dump_header
+{
+ /* Tag format. */
+ uint16_t format;
+ /* Start address of the tagged range. */
+ uint64_t start_vma;
+ /* End address of the tagged range. */
+ uint64_t end_vma;
+};
+
+/* Size of the generic header for the NT_MEMTAG note. This is OS-independent
+ and should be shared with OS-specific and arch-specific code. */
+#define NT_MEMTAG_GENERIC_HEADER_SIZE (sizeof (tag_dump_header::format) \
+ + sizeof (tag_dump_header::start_vma) \
+ + sizeof (tag_dump_header::end_vma))
+
+#endif /* GDBSUPPORT_MEMTAG_H */
--
2.25.1
next prev parent reply other threads:[~2021-05-31 16:44 UTC|newest]
Thread overview: 47+ messages / expand[flat|nested] mbox.gz Atom feed top
2021-05-18 20:20 [PATCH] [AArch64] " Luis Machado
2021-05-19 10:01 ` David Spickett
2021-05-19 11:11 ` Luis Machado
2021-05-19 12:13 ` Eli Zaretskii
2021-05-21 15:12 ` Alan Hayward
2021-05-21 15:30 ` Luis Machado
2021-05-21 17:20 ` John Baldwin
2021-05-24 13:41 ` Luis Machado
2021-05-24 8:07 ` Alan Hayward
2021-05-24 12:45 ` Luis Machado
2021-05-26 14:08 ` [PATCH,v2] " Luis Machado
2021-05-29 3:14 ` Simon Marchi
2021-05-31 14:12 ` Luis Machado
2021-05-31 14:49 ` Simon Marchi
2021-05-31 14:56 ` Luis Machado
2021-05-31 14:15 ` [PATCH,v3][AArch64] " Luis Machado
2021-05-31 16:44 ` Luis Machado [this message]
2021-06-01 17:45 ` [PATCH,v5][AArch64] " Luis Machado
2021-06-15 14:10 ` [Ping][PATCH,v5][AArch64] " Luis Machado
2021-06-24 14:00 ` [PATCH,v5][AArch64] " Alan Hayward
2021-06-24 14:37 ` Luis Machado
2021-06-24 15:18 ` Alan Hayward
2021-07-01 13:50 ` [PING][PATCH,v5][AArch64] " Luis Machado
2021-07-11 14:22 ` Joel Brobecker
2021-07-14 13:07 ` Catalin Marinas
2021-07-29 2:26 ` Simon Marchi
2021-07-29 16:03 ` John Baldwin
2021-07-29 18:10 ` Catalin Marinas
2021-07-29 18:20 ` Simon Marchi
2021-08-01 15:44 ` Joel Brobecker
2021-08-02 12:06 ` Luis Machado
2021-07-19 19:05 ` Luis Machado
2021-07-27 16:10 ` Luis Machado
2022-03-31 14:03 [AArch64] " Luis Machado
2022-05-03 21:56 ` [PATCH, v4] " Luis Machado
2022-05-12 10:36 ` Luis Machado
2022-05-18 12:46 ` Luis Machado
2022-05-18 13:58 ` John Baldwin
2022-05-23 9:50 ` Luis Machado
2022-05-23 9:49 ` Luis Machado
2022-06-06 9:28 ` Luis Machado
2022-06-06 9:42 ` Kuan-Ying Lee
2022-06-06 9:47 ` Luis Machado
2022-06-06 9:54 ` Kuan-Ying Lee
2022-06-06 10:49 ` Eli Zaretskii
2022-06-22 9:04 ` Luis Machado
2022-06-27 14:51 ` Pedro Alves
2022-07-11 10:13 ` Luis Machado
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=20210531164420.4081735-1-luis.machado@linaro.org \
--to=luis.machado@linaro.org \
--cc=alan.hayward@arm.com \
--cc=catalin.marinas@arm.com \
--cc=david.spickett@linaro.org \
--cc=gdb-patches@sourceware.org \
--cc=jhb@FreeBSD.org \
--cc=simon.marchi@polymtl.ca \
/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;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).