Mirror of the gdb-patches mailing list
 help / color / mirror / Atom feed
From: Luis Machado via Gdb-patches <gdb-patches@sourceware.org>
To: Alan Hayward <Alan.Hayward@arm.com>
Cc: "david.spickett@linaro.org" <david.spickett@linaro.org>,
	nd <nd@arm.com>,
	"gdb-patches\\@sourceware.org" <gdb-patches@sourceware.org>,
	Catalin Marinas <Catalin.Marinas@arm.com>
Subject: Re: [PATCH] [AArch64] MTE corefile support
Date: Mon, 24 May 2021 09:45:06 -0300	[thread overview]
Message-ID: <eb48406a-5ba7-8932-a485-fa0380b0ab9e@linaro.org> (raw)
In-Reply-To: <C27AB606-F685-41F3-B320-357901C65ACA@arm.com>

On 5/24/21 5:07 AM, Alan Hayward wrote:
> 
> 
>> On 21 May 2021, at 16:30, Luis Machado <luis.machado@linaro.org 
>> <mailto:luis.machado@linaro.org>> wrote:
>>
>> Hi Alan,
>>
>> On 5/21/21 12:12 PM, Alan Hayward wrote:
>>>> On 18 May 2021, at 21:20, Luis Machado <luis.machado@linaro.org 
>>>> <mailto:luis.machado@linaro.org>> wrote:
>>>>
>>>> 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.
>>>>
>>> This is a wider question than this patch - but is there someplace 
>>> this format will
>>> be documented? Ideally either Linux or GDB needs something written 
>>> down in
>>> text format.
>>> A few nits below too, but mostly looks fine.
>>
>> Yes. I'm still thinking whether this should go into the Linux Kernel's 
>> documentation or somewhere in the GDB manual.
>>
>> Given GDB reads core files generated by the Linux Kernel and also 
>> creates cores files itself, I'm thinking it may be best to put it in 
>> the GDB manual.
>>
>> I want to wait for possible feedbacks about the format before we 
>> document how it will look like in the manual.
>>
>>>> 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 
>>>> <mailto:luis.machado@linaro.org>>
>>>>
>>>> * aarch64-linux-tdep.c: Include elf/common.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.
>>>> * arch/aarch64-mte-linux.h (AARCH64_MTE_TAG_BIT_SIZE): New constant.
>>>> (struct tag_dump_header): New struct.
>>>> (struct tag_dump_mte): New struct.
>>>> (MEMTAG_NOTE_HEADER_SIZE): New constant.
>>>> * corelow.c (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 (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.
>>>> * NEWS: Mention core file support for memory tagging.
>>>>
>>>> gdb/doc/ChangeLog:
>>>>
>>>> YYYY-MM-DD  Luis Machado  <luis.machado@linaro.org 
>>>> <mailto: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 
>>>> <mailto:luis.machado@linaro.org>>
>>>>
>>>> * gdb.arch/aarch64-mte-gcore.c: New file.
>>>> * gdb.arch/aarch64-mte-gcore.exp: New file.
>>>> ---
>>>> gdb/NEWS                                     |   4 +
>>>> gdb/aarch64-linux-tdep.c                     | 179 +++++++++++++++++++
>>>> gdb/arch/aarch64-mte-linux.h                 |  29 +++
>>>> gdb/corelow.c                                |  88 +++++++++
>>>> gdb/doc/gdb.texinfo                          |   4 +
>>>> gdb/gdbarch.c                                |  64 +++++++
>>>> gdb/gdbarch.h                                |  16 ++
>>>> gdb/gdbarch.sh                               |   6 +
>>>> gdb/linux-tdep.c                             | 141 ++++++++++++++-
>>>> gdb/testsuite/gdb.arch/aarch64-mte-gcore.c   |  93 ++++++++++
>>>> gdb/testsuite/gdb.arch/aarch64-mte-gcore.exp | 115 ++++++++++++
>>>> 11 files changed, 736 insertions(+), 3 deletions(-)
>>>> create mode 100644 gdb/testsuite/gdb.arch/aarch64-mte-gcore.c
>>>> create mode 100644 gdb/testsuite/gdb.arch/aarch64-mte-gcore.exp
>>>>
>>>> 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..663d0e1a215 100644
>>>> --- a/gdb/aarch64-linux-tdep.c
>>>> +++ b/gdb/aarch64-linux-tdep.c
>>>> @@ -53,6 +53,8 @@
>>>>
>>>> #include "gdbsupport/selftest.h"
>>>>
>>>> +#include "elf/common.h"
>>>> +
>>>> /* Signal frame handling.
>>>>
>>>>       +------------+  ^
>>>> @@ -1779,6 +1781,172 @@ aarch64_linux_report_signal_info (struct 
>>>> gdbarch *gdbarch,
>>>>     }
>>>> }
>>>>
>>>> +/* 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.  */
>>>> +  int 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 (MEMTAG_NOTE_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 (uint16_t), byte_order,
>>>> + NT_MEMTAG_TYPE_AARCH_MTE);
>>>> +  buf += sizeof (uint16_t);
>>>> +
>>>> +  /* Start address */
>>>> +  store_unsigned_integer (buf, sizeof (uint64_t), byte_order, 
>>>> start_address);
>>>> +  buf += sizeof (uint64_t);
>>>> +
>>>> +  /* End address */
>>>> +  store_unsigned_integer (buf, sizeof (uint64_t), byte_order, 
>>>> end_address);
>>>> +  buf += sizeof (uint64_t);
>>>> +
>>>> +  /* MTE-specific header.  */
>>>> +  /* Granule byte size */
>>>> +  store_unsigned_integer (buf, sizeof (uint16_t), byte_order,
>>>> + AARCH64_MTE_GRANULE_SIZE);
>>>> +  buf += sizeof (uint16_t);
>>>> +
>>>> +  /* Tag bit size */
>>>> +  store_unsigned_integer (buf, sizeof (uint16_t), byte_order,
>>>> + AARCH64_MTE_TAG_BIT_SIZE);
>>>> +  buf += sizeof (uint16_t);
>>>> +
>>>> +  /* Unused value */
>>>> +  store_unsigned_integer (buf, sizeof (uint16_t), byte_order, 0);
>>>> +
>>>> +  /* Store the tags.  */
>>>> +  memcpy (notes[0].data () + MEMTAG_NOTE_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 request tags.  */
>>>> +
>>>> +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;
>>>> +
>>>> +  /* Read the generic header.  */
>>>> +  enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
>>>> +  struct tag_dump_header header;
>>>> +  const gdb_byte *buf = note.data ();
>>>> +
>>>> +  header.format
>>>> +    = extract_unsigned_integer (buf, sizeof (uint16_t), byte_order);
>>>> +  buf += sizeof (uint16_t);
>>>> +
>>>> +  header.start_vma
>>>> +    = extract_unsigned_integer (buf, sizeof (uint64_t), byte_order);
>>>> +  buf += sizeof (uint64_t);
>>>> +
>>>> +  header.end_vma
>>>> +    = extract_unsigned_integer (buf, sizeof (uint64_t), byte_order);
>>>> +  buf += sizeof (uint64_t);
>>>> +
>>>> +  /* Sanity check  */
>>>> +  if (header.format != NT_MEMTAG_TYPE_AARCH_MTE)
>>>> +    {
>>>> +      warning (_("Unexpected memory tag note format (%x).\n"), 
>>>> header.format);
>>>> +      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 (header.start_vma, AARCH64_MTE_GRANULE_SIZE);
>>>> +  CORE_ADDR aligned_address = align_down (address, 
>>>> AARCH64_MTE_GRANULE_SIZE);
>>>> +
>>>> +  int skipped_granules
>>>> +    = aarch64_mte_get_tag_granules (aligned_start_address,
>>>> +   aligned_address - aligned_start_address,
>>>> +   AARCH64_MTE_GRANULE_SIZE);
>>>> +
>>>> +  /* The amount of memory tag granules we need to fetch.  */
>>>> +  int 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;
>>>> +
>>>> +  /* Point to the block of data that contains the first granule we are
>>>> +     interested in.  */
>>>> +  const gdb_byte *tags_data = note.data () + sizeof (header) + 
>>>> skipped_granules;
>>>> +
>>>> +  /* Read the tag granules.  */
>>>> +  for (unsigned int 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 +2030,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..a4a26628847 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,32 @@ 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);
>>>>
>>>> +/* Headers for the NT_MEMTAG notes.  */
>>>> +
>>>> +/* 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;
>>>> +};
>>>> +
>>>> +/* MTE-specific NT_MEMTAG header.  */
>>>> +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;
>>>> +};
>>>> +
>>>> +/* Memory tag note header size.  Includes both the generic and the
>>>> +   arch-specific parts.  */
>>>> +#define MEMTAG_NOTE_HEADER_SIZE (2 + 8 + 8 + 2 + 2 + 2)
>>> This should compile down to a constant value: ?
>>> #define MEMTAG_NOTE_HEADER_SIZE 
>>> (sizeof(tag_dump_header)+sizeof(tag_dump_mte))
>>
>> Right. But there may be padding between the members of the struct, and 
>> we don't want to rely on what the compiler is doing. We could force 
>> this to be "packed" maybe?
> 
> Should the data inside the core file be packed?
> Packed saves the space, but padded ensures the file is aligned and maybe 
> easier to copy. >

Packing it makes the layout predictable. With padding, we may have 
differing layouts between a 32-bit target and a 64-bit target. I wanted 
to avoid that sort of thing. At least on the generic header that is used 
by GDB's core target.

>>
>>>> +
>>>> #endif /* ARCH_AARCH64_LINUX_H */
>>>> diff --git a/gdb/corelow.c b/gdb/corelow.c
>>>> index 452b4dd4f9a..33d16b7220a 100644
>>>> --- a/gdb/corelow.c
>>>> +++ b/gdb/corelow.c
>>>> @@ -100,6 +100,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 +1122,87 @@ 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.  */
>>>> +  if (bfd_get_section_by_name (core_bfd, ".memtag") == nullptr)
>>>> +    return false;
>>>> +
>>>> +  return true;
>>>> +}
>>>> +
>>>> +/* 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))
>>>> +    warning (_("gdbarch_decode_memtag_note not implemented for this "
>>>> +      "architecture."));
>>>> +
>>>> +  asection *section
>>>> +    = bfd_get_section_by_name (core_bfd, ".memtag");
>>>> +
>>>> +  /* Remove the top byte for the memory range check.  */
>>>> +  address = address_significant (gdbarch, address);
>>>> +
>>>> +  /* 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 < 2 * sizeof (uint64_t) + sizeof (uint16_t))
>>> I’m not sure why 64+16 ?
>>
>> Actually 2 * 8 + 2. Two 64-bit entries and a 16-bit entry in the 
>> generic header.
>>
>> Does that make sense?
> 
> I completely missed the 2.
> Does this need a #define TAG_NOTE_SIZE then? (And use it in the
> MEMTAG_NOTE_HEADER_SIZE)
> 

It does. I'll add it. Thanks!

>>
>>>> +{
>>>> + warning (_("malformed core note - too short for header"));
>>>> + return false;
>>>> +}
>>>> +
>>>> +      gdb::byte_vector note (note_size);
>>>> +
>>>> +      /* Fetch the contents of this particular memtag note.  */
>>>> +      if (!bfd_get_section_contents (core_bfd, section,
>>>> +    note.data (), 0, note_size))
>>>> +{
>>>> + warning (_("could not get core note contents."));
>>>> + return false;
>>>> +}
>>>> +
>>>> +      /* Read the generic header of the note.  Thos contains the 
>>>> format,
>>>> +start address and end address.  */
>>>> +      uint64_t start_address
>>>> += bfd_get_64 (core_bfd, note.data () + sizeof (uint16_t));
>>>> +      uint64_t end_address
>>>> += bfd_get_64 (core_bfd, note.data () + sizeof (uint16_t)
>>>> ++ sizeof (uint64_t));
>>>> +
>>>> +      /* Is the address within [start_address, end_address)?  */
>>>> +      if (address >= start_address
>>>> + && address < end_address)
>>>> +{
>>>> + /* Decode the memory tag note and return the tags.  */
>>>> + tags = gdbarch_decode_memtag_note (gdbarch, note, address, len);
>>>> + return true;
>>>> +}
>>>> +
>>>> +      /* The requested address lies outside this particular memtag 
>>>> note.  Keep
>>>> +looking and get the next section.  */
>>>> +      section = bfd_get_next_section_by_name (core_bfd, section);
>>>> +    }
>>>> +
>>>> +  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 56f37eb2288..738cb3b56eb 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..f4ff57dec87 100644
>>>> --- a/gdb/linux-tdep.c
>>>> +++ b/gdb/linux-tdep.c
>>>> @@ -1438,10 +1438,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 +1474,137 @@ 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;
>>>> +
>>>> +  asection *section
>>>> +    = bfd_get_section_by_name (core_bfd, ".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 < 2 * sizeof (uint64_t) + sizeof (uint16_t))
>>>> +{
>>>> + warning (_("malformed core note - too short for header"));
>>>> + return false;
>>>> +}
>>>> +
>>>> +      gdb::byte_vector note (note_size);
>>>> +
>>>> +      /* Fetch the contents of this particular memtag note.  */
>>>> +      if (!bfd_get_section_contents (core_bfd, section,
>>>> +    note.data (), 0, note_size))
>>>> +{
>>>> + warning (_("could not get core note contents."));
>>>> + return false;
>>>> +}
>>>> +
>>>> +      /* Read the generic header of the note.  Those contain the 
>>>> format,
>>>> +start address and end address.  */
>>>> +      uint64_t start_address
>>>> += bfd_get_64 (core_bfd, note.data () + sizeof (uint16_t));
>>>> +      uint64_t end_address
>>>> += bfd_get_64 (core_bfd, note.data () + sizeof (uint16_t)
>>>> ++ sizeof (uint64_t));
>>>> +
>>>> +      /* Is the address within [start_address, end_address)?  */
>>>> +      if (address >= start_address
>>>> + && address < end_address)
>>>> +return true;
>>>> +
>>>> +      /* The requested address lies outside this particular memtag 
>>>> note.  Keep
>>>> +looking and get the next section.  */
>>>> +      section = bfd_get_next_section_by_name (core_bfd, section);
>>>> +    }
>>>> +
>>>> +  return false;
>>>> +}
>>>> +
>>>> +/* 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> &note_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;
>>>> +
>>>> +  std::vector<struct smaps_data> smaps;
>>>> +
>>>> +  /* Parse the contents of smaps into a vector.  */
>>>> +  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;
>>>> +      memory_tag_notes
>>>> += gdbarch_create_memtag_notes_from_range (gdbarch,
>>>> + map.start_address,
>>>> + map.end_address);
>>>> +      /* Write notes to the core file.  */
>>>> +      for (gdb::byte_vector note : 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 +2183,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/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/ <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_SHIFT1
>>>> +#define PR_MTE_TCF_SYNC(1UL << PR_MTE_TCF_SHIFT)
>>>> +#define PR_MTE_TAG_SHIFT3
>>>> +
>>>> +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..bb529a8b369
>>>> --- /dev/null
>>>> +++ b/gdb/testsuite/gdb.arch/aarch64-mte-gcore.exp
>>>> @@ -0,0 +1,115 @@
>>>> +# Copyright (C) 2018-2021 Free Software Foundation, Inc.
>>> 2018?
>>
>> I really copied the template from an existing file. The rule, AFAIR, 
>> is to keep the copyright years from the original file.
> 
> Ok
> 
>>
>>>> +#
>>>> +# 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/ <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
>>>> +
>>>> +# Load the program file.
>>>> +set program_filename [standard_output_file $testfile]
>>>> +set program_loaded [gdb_file_cmd $program_filename]
>>>> +
>>>> +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"
>>>> +}
>>>> --
>>>> 2.25.1
> 

  reply	other threads:[~2021-05-24 12:45 UTC|newest]

Thread overview: 33+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-05-18 20:20 Luis Machado via Gdb-patches
2021-05-19 10:01 ` David Spickett via Gdb-patches
2021-05-19 11:11   ` Luis Machado via Gdb-patches
2021-05-19 12:13 ` Eli Zaretskii via Gdb-patches
2021-05-21 15:12 ` Alan Hayward via Gdb-patches
2021-05-21 15:30   ` Luis Machado via Gdb-patches
2021-05-21 17:20     ` John Baldwin
2021-05-24 13:41       ` Luis Machado via Gdb-patches
2021-05-24  8:07     ` Alan Hayward via Gdb-patches
2021-05-24 12:45       ` Luis Machado via Gdb-patches [this message]
2021-05-26 14:08 ` [PATCH,v2] " Luis Machado via Gdb-patches
2021-05-29  3:14   ` Simon Marchi via Gdb-patches
2021-05-31 14:12     ` Luis Machado via Gdb-patches
2021-05-31 14:49       ` Simon Marchi via Gdb-patches
2021-05-31 14:56         ` Luis Machado via Gdb-patches
2021-05-31 14:15   ` [PATCH,v3][AArch64] " Luis Machado via Gdb-patches
2021-05-31 16:44 ` [PATCH,v4][AArch64] " Luis Machado via Gdb-patches
2021-06-01 17:45 ` [PATCH,v5][AArch64] " Luis Machado via Gdb-patches
2021-06-15 14:10   ` [Ping][PATCH,v5][AArch64] " Luis Machado via Gdb-patches
2021-06-24 14:00   ` [PATCH,v5][AArch64] " Alan Hayward via Gdb-patches
2021-06-24 14:37     ` Luis Machado via Gdb-patches
2021-06-24 15:18       ` Alan Hayward via Gdb-patches
2021-07-01 13:50   ` [PING][PATCH,v5][AArch64] " Luis Machado via Gdb-patches
2021-07-11 14:22     ` Joel Brobecker
2021-07-14 13:07       ` Catalin Marinas via Gdb-patches
2021-07-29  2:26         ` Simon Marchi via Gdb-patches
2021-07-29 16:03           ` John Baldwin
2021-07-29 18:10           ` Catalin Marinas via Gdb-patches
2021-07-29 18:20             ` Simon Marchi via Gdb-patches
2021-08-01 15:44               ` Joel Brobecker
2021-08-02 12:06                 ` Luis Machado via Gdb-patches
2021-07-19 19:05   ` Luis Machado via Gdb-patches
2021-07-27 16:10   ` Luis Machado via Gdb-patches

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=eb48406a-5ba7-8932-a485-fa0380b0ab9e@linaro.org \
    --to=gdb-patches@sourceware.org \
    --cc=Alan.Hayward@arm.com \
    --cc=Catalin.Marinas@arm.com \
    --cc=david.spickett@linaro.org \
    --cc=luis.machado@linaro.org \
    --cc=nd@arm.com \
    /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