public inbox for binutils@sourceware.org
 help / color / mirror / Atom feed
* Support AArch64 MTE memory tag dumps in core files
@ 2022-03-31 14:04 Luis Machado
  2022-04-01  1:34 ` Alan Modra
                   ` (2 more replies)
  0 siblings, 3 replies; 14+ messages in thread
From: Luis Machado @ 2022-03-31 14:04 UTC (permalink / raw)
  To: binutils

The Linux kernel can dump memory tag segments to a core file, one segment
per mapped range. The format and documentation can be found in the Linux
kernel tree [1].

The following patch adjusts bfd and binutils see they can handle this new
segment type and display it accordingly. It also adds code required so GDB
can properly read/dump core file data containing memory tags.

Upon reading, each segment that contains memory tags gets mapped to a
.memtag section. These sections will be used by GDB to lookup the tag data.

There is another patch for GDB that enables both reading
and dumping of memory tag segments.

Given sections based on segments are numbered, I had to update the code to
not number the memory tag ones. This simplifies GDB's lookup of the memory
tag sections.

Tested on aarch64-linux Ubuntu 20.04.

[1] Documentation/arm64/memory-tagging-extension.rst (Core Dump Support)
---
 bfd/bfd-in2.h        | 19 +++++++---
 bfd/elf-bfd.h        |  2 ++
 bfd/elf.c            | 82 ++++++++++++++++++++++++++++++++++++++++++++
 bfd/section.c        | 24 +++++++++----
 binutils/readelf.c   |  1 +
 include/elf/common.h |  5 +++
 6 files changed, 123 insertions(+), 10 deletions(-)

diff --git a/bfd/bfd-in2.h b/bfd/bfd-in2.h
index c0b563aec02..0e5e7104555 100644
--- a/bfd/bfd-in2.h
+++ b/bfd/bfd-in2.h
@@ -1027,6 +1027,9 @@ typedef struct bfd_section
   /* Nonzero if this section uses RELA relocations, rather than REL.  */
   unsigned int use_rela_p:1;
 
+  /* Nonzero if this section contains memory tag data.  Default is 0.  */
+  unsigned int has_memory_tags : 1;
+
   /* Bits used by various backends.  The generic code doesn't touch
      these fields.  */
 
@@ -1070,6 +1073,11 @@ typedef struct bfd_section
   /* The compressed size of the section in octets.  */
   bfd_size_type compressed_size;
 
+  /* If HAS_MEMORY_TAGS is true, MEMORY_TAGS_RANGE_SIZE is the original memory
+     range size, in octets, of the memory that contained the tags stored in this
+     section.  SIZE is the size of the packed tags from that memory range.  */
+  bfd_size_type memory_tags_range_size;
+
   /* Relaxation table. */
   struct relax_table *relax;
 
@@ -1330,14 +1338,17 @@ discarded_section (const asection *sec)
   /* linker_mark, linker_has_input, gc_mark, decompress_status,     */ \
      0,           0,                1,       0,                        \
                                                                        \
-  /* segment_mark, sec_info_type, use_rela_p,                       */ \
-     0,            0,             0,                                   \
+  /* segment_mark, sec_info_type, use_rela_p, has_memory_tags,      */ \
+     0,            0,             0,          0,                       \
                                                                        \
   /* sec_flg0, sec_flg1, sec_flg2, sec_flg3, sec_flg4, sec_flg5,    */ \
      0,        0,        0,        0,        0,        0,              \
                                                                        \
-  /* vma, lma, size, rawsize, compressed_size, relax, relax_count,  */ \
-     0,   0,   0,    0,       0,               0,     0,               \
+  /* vma, lma, size, rawsize, compressed_size,                      */ \
+     0,   0,   0,    0,       0,                                       \
+                                                                       \
+  /* memory_tags_range_size, relax, relax_count,                    */ \
+     0,                      0,     0,                                 \
                                                                        \
   /* output_offset, output_section, alignment_power,                */ \
      0,             &SEC,           0,                                 \
diff --git a/bfd/elf-bfd.h b/bfd/elf-bfd.h
index 5c3985f6e57..dc4c4faea7e 100644
--- a/bfd/elf-bfd.h
+++ b/bfd/elf-bfd.h
@@ -2227,6 +2227,8 @@ extern bool bfd_elf_mkcorefile
   (bfd *);
 extern bool _bfd_elf_make_section_from_shdr
   (bfd *, Elf_Internal_Shdr *, const char *, int);
+extern bool _bfd_elf_make_memtag_section_from_phdr
+  (bfd *, Elf_Internal_Phdr *);
 extern bool _bfd_elf_make_section_from_phdr
   (bfd *, Elf_Internal_Phdr *, int, const char *);
 extern struct bfd_hash_entry *_bfd_elf_link_hash_newfunc
diff --git a/bfd/elf.c b/bfd/elf.c
index 82b53be99f9..422f0f50151 100644
--- a/bfd/elf.c
+++ b/bfd/elf.c
@@ -1629,10 +1629,30 @@ _bfd_elf_copy_private_bfd_data (bfd *ibfd, bfd *obfd)
   return true;
 }
 
+/* Given P_TYPE, return TRUE if it represents a memory tag type.  Otherwise
+   return false.  */
+
+static bool
+is_memory_tag_p_type (unsigned int p_type)
+{
+  switch (p_type)
+    {
+    case PT_ARM_MEMTAG_MTE:
+      return true;
+    default:
+      return false;
+    }
+}
+
 static const char *
 get_segment_type (unsigned int p_type)
 {
   const char *pt;
+
+  /* Handle memory tag p_type's first.  */
+  if (is_memory_tag_p_type (p_type))
+    return "MEMTAG";
+
   switch (p_type)
     {
     case PT_NULL: pt = "NULL"; break;
@@ -2896,6 +2916,47 @@ _bfd_elf_new_section_hook (bfd *abfd, asection *sec)
   return _bfd_generic_new_section_hook (abfd, sec);
 }
 
+/* Create a new bfd section for a memory tag ELF segment.
+
+   The name of the section is "memtag" and there can be multiple such
+   sections.  */
+
+bool
+_bfd_elf_make_memtag_section_from_phdr (bfd *abfd,
+					Elf_Internal_Phdr *hdr)
+{
+  asection *newsect;
+  unsigned int opb = bfd_octets_per_byte (abfd, NULL);
+
+  if (!is_memory_tag_p_type (hdr->p_type))
+    return false;
+
+  if (hdr->p_filesz > 0)
+    {
+      /* Sections created from memory tag p_type's are always named
+	 "memtag".  */
+      newsect = bfd_make_section_anyway (abfd, "memtag");
+
+      if (newsect == NULL)
+	return false;
+
+      /* p_vaddr holds the original start address of the tagged memory
+	 range.  */
+      newsect->vma = hdr->p_vaddr / opb;
+
+      /* p_filesz holds the storage size of the packed tags.  */
+      newsect->size = hdr->p_filesz;
+      newsect->filepos = hdr->p_offset;
+
+      /* Set the memory tags range size to the original length of the tagged
+	 memory range.  */
+      newsect->has_memory_tags = 1;
+      newsect->memory_tags_range_size = hdr->p_memsz;
+    }
+
+  return true;
+}
+
 /* Create a new bfd section from an ELF program header.
 
    Since program segments have no names, we generate a synthetic name
@@ -3018,6 +3079,10 @@ bfd_section_from_phdr (bfd *abfd, Elf_Internal_Phdr *hdr, int hdr_index)
 {
   const struct elf_backend_data *bed;
 
+  /* Handle memory tag p_type's first.  */
+  if (is_memory_tag_p_type (hdr->p_type))
+    return _bfd_elf_make_memtag_section_from_phdr (abfd, hdr);
+
   switch (hdr->p_type)
     {
     case PT_NULL:
@@ -5896,6 +5961,23 @@ assign_file_positions_for_load_sections (bfd *abfd,
 		p->p_filesz += adjust;
 	    }
 
+	  /* For memory tag sections, the content size is smaller than the
+	     size of the memory range.  Adjust the file size and memory
+	     size accordingly.  */
+	  if (is_memory_tag_p_type (p->p_type)
+	      && bfd_get_format (abfd) == bfd_core)
+	    {
+	      if (m->count > 0)
+		{
+		  /* The storage size of tags in the section is usually much
+		     smaller than the memory range size of the memory the tags
+		     cover, so we need to adjust the file size and memory size
+		     fields.  */
+		  asection *memtag_section = m->sections[0];
+		  p->p_memsz = memtag_section->memory_tags_range_size;
+		}
+	    }
+
 	  if (p->p_type == PT_NOTE && bfd_get_format (abfd) == bfd_core)
 	    {
 	      /* The section at i == 0 is the one that actually contains
diff --git a/bfd/section.c b/bfd/section.c
index 9a1071454f5..e8c7caf9dd4 100644
--- a/bfd/section.c
+++ b/bfd/section.c
@@ -412,6 +412,9 @@ CODE_FRAGMENT
 .  {* Nonzero if this section uses RELA relocations, rather than REL.  *}
 .  unsigned int use_rela_p:1;
 .
+.  {* Nonzero if this section contains memory tag data.  Default is 0.  *}
+.  unsigned int has_memory_tags : 1;
+.
 .  {* Bits used by various backends.  The generic code doesn't touch
 .     these fields.  *}
 .
@@ -455,6 +458,11 @@ CODE_FRAGMENT
 .  {* The compressed size of the section in octets.  *}
 .  bfd_size_type compressed_size;
 .
+.  {* If HAS_MEMORY_TAGS is true, MEMORY_TAGS_RANGE_SIZE is the original memory
+.     range size, in octets, of the memory that contained the tags stored in this
+.     section.  SIZE is the size of the packed tags from that memory range.  *}
+.  bfd_size_type memory_tags_range_size;
+.
 .  {* Relaxation table. *}
 .  struct relax_table *relax;
 .
@@ -715,14 +723,17 @@ CODE_FRAGMENT
 .  {* linker_mark, linker_has_input, gc_mark, decompress_status,     *}	\
 .     0,           0,                1,       0,			\
 .									\
-.  {* segment_mark, sec_info_type, use_rela_p,                       *}	\
-.     0,            0,             0,					\
+.  {* segment_mark, sec_info_type, use_rela_p, has_memory_tags,      *}	\
+.     0,            0,             0,	       0,			\
 .									\
 .  {* sec_flg0, sec_flg1, sec_flg2, sec_flg3, sec_flg4, sec_flg5,    *}	\
 .     0,        0,        0,        0,        0,        0,		\
 .									\
-.  {* vma, lma, size, rawsize, compressed_size, relax, relax_count,  *}	\
-.     0,   0,   0,    0,       0,               0,     0,		\
+.  {* vma, lma, size, rawsize, compressed_size,			     *} \
+.     0,   0,   0,    0,       0,					\
+.									\
+.  {* memory_tags_range_size, relax, relax_count,		     *} \
+.     0,		      0,     0,					\
 .									\
 .  {* output_offset, output_section, alignment_power,                *}	\
 .     0,             &SEC,           0,					\
@@ -1499,7 +1510,8 @@ bfd_set_section_contents (bfd *abfd,
 {
   bfd_size_type sz;
 
-  if (!(bfd_section_flags (section) & SEC_HAS_CONTENTS))
+  if (!section->has_memory_tags
+      && !(bfd_section_flags (section) & SEC_HAS_CONTENTS))
     {
       bfd_set_error (bfd_error_no_contents);
       return false;
@@ -1588,7 +1600,7 @@ bfd_get_section_contents (bfd *abfd,
     /* Don't bother.  */
     return true;
 
-  if ((section->flags & SEC_HAS_CONTENTS) == 0)
+  if (!section->has_memory_tags && (section->flags & SEC_HAS_CONTENTS) == 0)
     {
       memset (location, 0, (size_t) count);
       return true;
diff --git a/binutils/readelf.c b/binutils/readelf.c
index a2dbaa4722e..ae1399c0577 100644
--- a/binutils/readelf.c
+++ b/binutils/readelf.c
@@ -4499,6 +4499,7 @@ get_aarch64_segment_type (unsigned long type)
   switch (type)
     {
     case PT_AARCH64_ARCHEXT:  return "AARCH64_ARCHEXT";
+    case PT_ARM_MEMTAG_MTE:   return "ARM_MEMTAG_MTE";
     default:                  return NULL;
     }
 }
diff --git a/include/elf/common.h b/include/elf/common.h
index 70d63e3299c..5a682e3bde7 100644
--- a/include/elf/common.h
+++ b/include/elf/common.h
@@ -500,6 +500,11 @@
 #define PT_GNU_MBIND_LO (PT_LOOS + 0x474e555)
 #define PT_GNU_MBIND_HI (PT_GNU_MBIND_LO + PT_GNU_MBIND_NUM - 1)
 
+/* ARM memory tag segment types.  */
+
+/* MTE memory tag segment type.  */
+#define PT_ARM_MEMTAG_MTE     (PT_LOPROC + 0x1)
+
 /* Program segment permissions, in program header p_flags field.  */
 
 #define PF_X		(1 << 0)	/* Segment is executable */
-- 
2.25.1


^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: Support AArch64 MTE memory tag dumps in core files
  2022-03-31 14:04 Support AArch64 MTE memory tag dumps in core files Luis Machado
@ 2022-04-01  1:34 ` Alan Modra
  2022-04-01  8:21   ` Luis Machado
  2022-04-03 12:04   ` Move microblaze relax info to target specific data Alan Modra
  2022-04-21 15:18 ` [PATCH, v2] [AArch64] Support AArch64 MTE memory tag dumps in core files Luis Machado
  2022-05-03 11:33 ` [PATCH] " Luis Machado
  2 siblings, 2 replies; 14+ messages in thread
From: Alan Modra @ 2022-04-01  1:34 UTC (permalink / raw)
  To: Luis Machado; +Cc: binutils

On Thu, Mar 31, 2022 at 03:04:57PM +0100, Luis Machado via Binutils wrote:
> diff --git a/bfd/section.c b/bfd/section.c
> index 9a1071454f5..e8c7caf9dd4 100644
> --- a/bfd/section.c
> +++ b/bfd/section.c
> @@ -412,6 +412,9 @@ CODE_FRAGMENT
>  .  {* Nonzero if this section uses RELA relocations, rather than REL.  *}
>  .  unsigned int use_rela_p:1;
>  .
> +.  {* Nonzero if this section contains memory tag data.  Default is 0.  *}
> +.  unsigned int has_memory_tags : 1;
> +.
>  .  {* Bits used by various backends.  The generic code doesn't touch
>  .     these fields.  *}
>  .
> @@ -455,6 +458,11 @@ CODE_FRAGMENT
>  .  {* The compressed size of the section in octets.  *}
>  .  bfd_size_type compressed_size;
>  .
> +.  {* If HAS_MEMORY_TAGS is true, MEMORY_TAGS_RANGE_SIZE is the original memory
> +.     range size, in octets, of the memory that contained the tags stored in this
> +.     section.  SIZE is the size of the packed tags from that memory range.  *}
> +.  bfd_size_type memory_tags_range_size;
> +.
>  .  {* Relaxation table. *}
>  .  struct relax_table *relax;
>  .

Really, you shouldn't be adding fields used by just one target to
struct bfd_section.  The linker might be dealing with hundreds of
thousands of sections.  If every target added fields because it was
convenient to do it that way, we'd end up with quite a non-trivial
memory cost for all targets.  Instead, you should look at adding the
new field to _aarch64_elf_section_data.

Yes, I know target specific fields have sneaked past review in the
past, eg. relax and relax_count are microblaze only.  I might even get
around to fixing those one day.

-- 
Alan Modra
Australia Development Lab, IBM

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: Support AArch64 MTE memory tag dumps in core files
  2022-04-01  1:34 ` Alan Modra
@ 2022-04-01  8:21   ` Luis Machado
  2022-04-03 12:04   ` Move microblaze relax info to target specific data Alan Modra
  1 sibling, 0 replies; 14+ messages in thread
From: Luis Machado @ 2022-04-01  8:21 UTC (permalink / raw)
  To: Alan Modra; +Cc: binutils

Hi Alan,

On 4/1/22 02:34, Alan Modra wrote:
> On Thu, Mar 31, 2022 at 03:04:57PM +0100, Luis Machado via Binutils wrote:
>> diff --git a/bfd/section.c b/bfd/section.c
>> index 9a1071454f5..e8c7caf9dd4 100644
>> --- a/bfd/section.c
>> +++ b/bfd/section.c
>> @@ -412,6 +412,9 @@ CODE_FRAGMENT
>>   .  {* Nonzero if this section uses RELA relocations, rather than REL.  *}
>>   .  unsigned int use_rela_p:1;
>>   .
>> +.  {* Nonzero if this section contains memory tag data.  Default is 0.  *}
>> +.  unsigned int has_memory_tags : 1;
>> +.
>>   .  {* Bits used by various backends.  The generic code doesn't touch
>>   .     these fields.  *}
>>   .
>> @@ -455,6 +458,11 @@ CODE_FRAGMENT
>>   .  {* The compressed size of the section in octets.  *}
>>   .  bfd_size_type compressed_size;
>>   .
>> +.  {* If HAS_MEMORY_TAGS is true, MEMORY_TAGS_RANGE_SIZE is the original memory
>> +.     range size, in octets, of the memory that contained the tags stored in this
>> +.     section.  SIZE is the size of the packed tags from that memory range.  *}
>> +.  bfd_size_type memory_tags_range_size;
>> +.
>>   .  {* Relaxation table. *}
>>   .  struct relax_table *relax;
>>   .
> 
> Really, you shouldn't be adding fields used by just one target to
> struct bfd_section.  The linker might be dealing with hundreds of
> thousands of sections.  If every target added fields because it was
> convenient to do it that way, we'd end up with quite a non-trivial
> memory cost for all targets.  Instead, you should look at adding the
> new field to _aarch64_elf_section_data.

That's a valid point. I was considering potential future use of memory 
tags by other architectures. Right now AArch64 and SPARC use it, but I 
understand the memory restrictions. I'm still finding my way through 
this code.

Let me rework this and shift these fields to a more arch-specific 
location. Thanks for the feedback!

> 
> Yes, I know target specific fields have sneaked past review in the
> past, eg. relax and relax_count are microblaze only.  I might even get
> around to fixing those one day.
> 


^ permalink raw reply	[flat|nested] 14+ messages in thread

* Move microblaze relax info to target specific data
  2022-04-01  1:34 ` Alan Modra
  2022-04-01  8:21   ` Luis Machado
@ 2022-04-03 12:04   ` Alan Modra
  1 sibling, 0 replies; 14+ messages in thread
From: Alan Modra @ 2022-04-03 12:04 UTC (permalink / raw)
  To: binutils

On Fri, Apr 01, 2022 at 12:04:17PM +1030, Alan Modra wrote:
> Yes, I know target specific fields have sneaked past review in the
> past, eg. relax and relax_count are microblaze only.  I might even get
> around to fixing those one day.

	* section.c (struct bfd_section): Delete relax and relax_count.
	(BFD_FAKE_SECTION): Adjust to suit.
	(struct relax_table): Move to..
	* elf32-microblaze.c (struct relax_table): ..here.
	(struct _microblaze_elf_section_data): New.
	(microblaze_elf_section_data): Define.
	(microblaze_elf_new_section_hook): New function.
	(bfd_elf32_new_section_hook): Define.
	(calc_fixup): Return a size_t.  Adjust to suit new location of
	relax and relax_count.
	(microblaze_elf_relax_section): Adjust to suit new location of
	relax and relax_count.  Make some variables size_t.
	* bfd-in2.h: Regenerate.

diff --git a/bfd/bfd-in2.h b/bfd/bfd-in2.h
index bf3b6c66fd0..404dae2eba5 100644
--- a/bfd/bfd-in2.h
+++ b/bfd/bfd-in2.h
@@ -1070,13 +1070,6 @@ typedef struct bfd_section
   /* The compressed size of the section in octets.  */
   bfd_size_type compressed_size;
 
-  /* Relaxation table. */
-  struct relax_table *relax;
-
-  /* Count of used relaxation table entries. */
-  int relax_count;
-
-
   /* If this section is going to be output, then this value is the
      offset in *bytes* into the output section of the first byte in the
      input section (byte ==> smallest addressable unit on the
@@ -1177,17 +1170,6 @@ typedef struct bfd_section
 
 } asection;
 
-/* Relax table contains information about instructions which can
-   be removed by relaxation -- replacing a long address with a
-   short address.  */
-struct relax_table {
-  /* Address where bytes may be deleted. */
-  bfd_vma addr;
-
-  /* Number of bytes to be deleted.  */
-  int size;
-};
-
 static inline const char *
 bfd_section_name (const asection *sec)
 {
@@ -1336,8 +1318,8 @@ discarded_section (const asection *sec)
   /* sec_flg0, sec_flg1, sec_flg2, sec_flg3, sec_flg4, sec_flg5,    */ \
      0,        0,        0,        0,        0,        0,              \
                                                                        \
-  /* vma, lma, size, rawsize, compressed_size, relax, relax_count,  */ \
-     0,   0,   0,    0,       0,               0,     0,               \
+  /* vma, lma, size, rawsize, compressed_size, */                      \
+     0,   0,   0,    0,       0,                                       \
                                                                        \
   /* output_offset, output_section, alignment_power,                */ \
      0,             &SEC,           0,                                 \
diff --git a/bfd/elf32-microblaze.c b/bfd/elf32-microblaze.c
index d09b3f7095d..ebdba93d0e9 100644
--- a/bfd/elf32-microblaze.c
+++ b/bfd/elf32-microblaze.c
@@ -697,6 +697,47 @@ microblaze_elf_info_to_howto (bfd * abfd,
   return true;
 }
 
+/* Relax table contains information about instructions which can
+   be removed by relaxation -- replacing a long address with a
+   short address.  */
+struct relax_table
+{
+  /* Address where bytes may be deleted.  */
+  bfd_vma addr;
+
+  /* Number of bytes to be deleted.  */
+  size_t size;
+};
+
+struct _microblaze_elf_section_data
+{
+  struct bfd_elf_section_data elf;
+  /* Count of used relaxation table entries.  */
+  size_t relax_count;
+  /* Relaxation table.  */
+  struct relax_table *relax;
+};
+
+#define microblaze_elf_section_data(sec) \
+  ((struct _microblaze_elf_section_data *) elf_section_data (sec))
+
+static bool
+microblaze_elf_new_section_hook (bfd *abfd, asection *sec)
+{
+  if (!sec->used_by_bfd)
+    {
+      struct _microblaze_elf_section_data *sdata;
+      size_t amt = sizeof (*sdata);
+
+      sdata = bfd_zalloc (abfd, amt);
+      if (sdata == NULL)
+	return false;
+      sec->used_by_bfd = sdata;
+    }
+
+  return _bfd_elf_new_section_hook (abfd, sec);
+}
+
 /* Microblaze ELF local labels start with 'L.' or '$L', not '.L'.  */
 
 static bool
@@ -1647,23 +1688,24 @@ microblaze_elf_relocate_section (bfd *output_bfd,
 \f
 /* Calculate fixup value for reference.  */
 
-static int
+static size_t
 calc_fixup (bfd_vma start, bfd_vma size, asection *sec)
 {
   bfd_vma end = start + size;
-  int i, fixup = 0;
+  size_t i, fixup = 0;
+  struct _microblaze_elf_section_data *sdata;
 
-  if (sec == NULL || sec->relax == NULL)
+  if (sec == NULL || (sdata = microblaze_elf_section_data (sec)) == NULL)
     return 0;
 
   /* Look for addr in relax table, total fixup value.  */
-  for (i = 0; i < sec->relax_count; i++)
+  for (i = 0; i < sdata->relax_count; i++)
     {
-      if (end <= sec->relax[i].addr)
+      if (end <= sdata->relax[i].addr)
 	break;
-      if ((end != start) && (start > sec->relax[i].addr))
+      if (end != start && start > sdata->relax[i].addr)
 	continue;
-      fixup += sec->relax[i].size;
+      fixup += sdata->relax[i].size;
     }
   return fixup;
 }
@@ -1712,14 +1754,15 @@ microblaze_elf_relax_section (bfd *abfd,
   bfd_byte *free_contents = NULL;
   int rel_count;
   unsigned int shndx;
-  int i, sym_index;
+  size_t i, sym_index;
   asection *o;
   struct elf_link_hash_entry *sym_hash;
   Elf_Internal_Sym *isymbuf, *isymend;
   Elf_Internal_Sym *isym;
-  int symcount;
-  int offset;
+  size_t symcount;
+  size_t offset;
   bfd_vma src, dest;
+  struct _microblaze_elf_section_data *sdata;
 
   /* We only do this once per section.  We may be able to delete some code
      by running multiple passes, but it is not worth it.  */
@@ -1728,8 +1771,9 @@ microblaze_elf_relax_section (bfd *abfd,
   /* Only do this for a text section.  */
   if (bfd_link_relocatable (link_info)
       || (sec->flags & SEC_RELOC) == 0
-      || (sec->reloc_count == 0)
-      || (sec->flags & SEC_CODE) == 0)
+      || (sec->flags & SEC_CODE) == 0
+      || sec->reloc_count == 0
+      || (sdata = microblaze_elf_section_data (sec)) == NULL)
     return true;
 
   BFD_ASSERT ((sec->size > 0) || (sec->rawsize > 0));
@@ -1754,11 +1798,11 @@ microblaze_elf_relax_section (bfd *abfd,
   if (! link_info->keep_memory)
     free_relocs = internal_relocs;
 
-  sec->relax = (struct relax_table *) bfd_malloc ((sec->reloc_count + 1)
-						  * sizeof (struct relax_table));
-  if (sec->relax == NULL)
+  sdata->relax_count = 0;
+  sdata->relax = (struct relax_table *) bfd_malloc ((sec->reloc_count + 1)
+						    * sizeof (*sdata->relax));
+  if (sdata->relax == NULL)
     goto error_return;
-  sec->relax_count = 0;
 
   irelend = internal_relocs + sec->reloc_count;
   rel_count = 0;
@@ -1848,9 +1892,9 @@ microblaze_elf_relax_section (bfd *abfd,
 	  || (symval & 0xffff8000) == 0xffff8000)
 	{
 	  /* We can delete this instruction.  */
-	  sec->relax[sec->relax_count].addr = irel->r_offset;
-	  sec->relax[sec->relax_count].size = INST_WORD_SIZE;
-	  sec->relax_count++;
+	  sdata->relax[sdata->relax_count].addr = irel->r_offset;
+	  sdata->relax[sdata->relax_count].size = INST_WORD_SIZE;
+	  sdata->relax_count++;
 
 	  /* Rewrite relocation type.  */
 	  switch ((enum elf_microblaze_reloc_type) ELF32_R_TYPE (irel->r_info))
@@ -1875,11 +1919,11 @@ microblaze_elf_relax_section (bfd *abfd,
     } /* Loop through all relocations.  */
 
   /* Loop through the relocs again, and see if anything needs to change.  */
-  if (sec->relax_count > 0)
+  if (sdata->relax_count > 0)
     {
       shndx = _bfd_elf_section_from_bfd_section (abfd, sec);
       rel_count = 0;
-      sec->relax[sec->relax_count].addr = sec->size;
+      sdata->relax[sdata->relax_count].addr = sec->size;
 
       for (irel = internal_relocs; irel < irelend; irel++, rel_count++)
 	{
@@ -1913,7 +1957,7 @@ microblaze_elf_relax_section (bfd *abfd,
 	      {
 		/* This was a PC-relative instruction that was
 		   completely resolved.  */
-		int sfix, efix;
+		size_t sfix, efix;
 		bfd_vma target_address;
 		target_address = irel->r_addend + irel->r_offset;
 		sfix = calc_fixup (irel->r_offset, 0, sec);
@@ -1928,7 +1972,7 @@ microblaze_elf_relax_section (bfd *abfd,
 	      {
 		/* This was a PC-relative 64-bit instruction that was
 		   completely resolved.  */
-		int sfix, efix;
+		size_t sfix, efix;
 		bfd_vma target_address;
 		target_address = irel->r_addend + irel->r_offset + INST_WORD_SIZE;
 		sfix = calc_fixup (irel->r_offset + INST_WORD_SIZE, 0, sec);
@@ -2195,15 +2239,16 @@ microblaze_elf_relax_section (bfd *abfd,
 	}
 
       /* Physically move the code and change the cooked size.  */
-      dest = sec->relax[0].addr;
-      for (i = 0; i < sec->relax_count; i++)
+      dest = sdata->relax[0].addr;
+      for (i = 0; i < sdata->relax_count; i++)
 	{
-	  int len;
-	  src = sec->relax[i].addr + sec->relax[i].size;
-	  len = sec->relax[i+1].addr - sec->relax[i].addr - sec->relax[i].size;
+	  size_t len;
+	  src = sdata->relax[i].addr + sdata->relax[i].size;
+	  len = (sdata->relax[i+1].addr - sdata->relax[i].addr
+		 - sdata->relax[i].size);
 
 	  memmove (contents + dest, contents + src, len);
-	  sec->size -= sec->relax[i].size;
+	  sec->size -= sdata->relax[i].size;
 	  dest += len;
 	}
 
@@ -2229,11 +2274,11 @@ microblaze_elf_relax_section (bfd *abfd,
       free_contents = NULL;
     }
 
-  if (sec->relax_count == 0)
+  if (sdata->relax_count == 0)
     {
       *again = false;
-      free (sec->relax);
-      sec->relax = NULL;
+      free (sdata->relax);
+      sdata->relax = NULL;
     }
   else
     *again = true;
@@ -2242,9 +2287,9 @@ microblaze_elf_relax_section (bfd *abfd,
  error_return:
   free (free_relocs);
   free (free_contents);
-  free (sec->relax);
-  sec->relax = NULL;
-  sec->relax_count = 0;
+  free (sdata->relax);
+  sdata->relax = NULL;
+  sdata->relax_count = 0;
   return false;
 }
 
@@ -3409,6 +3454,7 @@ microblaze_elf_add_symbol_hook (bfd *abfd,
 
 #define bfd_elf32_bfd_reloc_type_lookup		microblaze_elf_reloc_type_lookup
 #define bfd_elf32_bfd_is_local_label_name	microblaze_elf_is_local_label_name
+#define bfd_elf32_new_section_hook		microblaze_elf_new_section_hook
 #define elf_backend_relocate_section		microblaze_elf_relocate_section
 #define bfd_elf32_bfd_relax_section		microblaze_elf_relax_section
 #define bfd_elf32_bfd_merge_private_bfd_data	_bfd_generic_verify_endian_match
diff --git a/bfd/section.c b/bfd/section.c
index 9a1071454f5..d7922e0741a 100644
--- a/bfd/section.c
+++ b/bfd/section.c
@@ -455,13 +455,6 @@ CODE_FRAGMENT
 .  {* The compressed size of the section in octets.  *}
 .  bfd_size_type compressed_size;
 .
-.  {* Relaxation table. *}
-.  struct relax_table *relax;
-.
-.  {* Count of used relaxation table entries. *}
-.  int relax_count;
-.
-.
 .  {* If this section is going to be output, then this value is the
 .     offset in *bytes* into the output section of the first byte in the
 .     input section (byte ==> smallest addressable unit on the
@@ -562,17 +555,6 @@ CODE_FRAGMENT
 .
 .} asection;
 .
-.{* Relax table contains information about instructions which can
-.   be removed by relaxation -- replacing a long address with a
-.   short address.  *}
-.struct relax_table {
-.  {* Address where bytes may be deleted. *}
-.  bfd_vma addr;
-.
-.  {* Number of bytes to be deleted.  *}
-.  int size;
-.};
-.
 .static inline const char *
 .bfd_section_name (const asection *sec)
 .{
@@ -721,8 +703,8 @@ CODE_FRAGMENT
 .  {* sec_flg0, sec_flg1, sec_flg2, sec_flg3, sec_flg4, sec_flg5,    *}	\
 .     0,        0,        0,        0,        0,        0,		\
 .									\
-.  {* vma, lma, size, rawsize, compressed_size, relax, relax_count,  *}	\
-.     0,   0,   0,    0,       0,               0,     0,		\
+.  {* vma, lma, size, rawsize, compressed_size, *}			\
+.     0,   0,   0,    0,       0,					\
 .									\
 .  {* output_offset, output_section, alignment_power,                *}	\
 .     0,             &SEC,           0,					\

-- 
Alan Modra
Australia Development Lab, IBM

^ permalink raw reply	[flat|nested] 14+ messages in thread

* [PATCH, v2] [AArch64] Support AArch64 MTE memory tag dumps in core files
  2022-03-31 14:04 Support AArch64 MTE memory tag dumps in core files Luis Machado
  2022-04-01  1:34 ` Alan Modra
@ 2022-04-21 15:18 ` Luis Machado
  2022-04-23  0:15   ` Alan Modra
  2022-05-03 11:33 ` [PATCH] " Luis Machado
  2 siblings, 1 reply; 14+ messages in thread
From: Luis Machado @ 2022-04-21 15:18 UTC (permalink / raw)
  To: binutils

v2:

- Drop arch-specific fields from the generic section data structure.
- Use the rawsize field of the section structure to store the original
  memory range of the memory-tagged area.
- Implement the bfd_elf_modify_headers for aarch64, to adjust the values
  for the memory tag segment according to the Linux Kernel's format.

--

The Linux kernel can dump memory tag segments to a core file, one segment
per mapped range. The format and documentation can be found in the Linux
kernel tree [1].

The following patch adjusts bfd and binutils so they can handle this new
segment type and display it accordingly. It also adds code required so GDB
can properly read/dump core file data containing memory tags.

Upon reading, each segment that contains memory tags gets mapped to a
section named "memtag". These sections will be used by GDB to lookup the tag
data. There can be multiple such sections with the same name, and they are not
numbered to simplify GDB's handling and lookup.

There is another patch for GDB that enables both reading and dumping of
memory tag segments.

Tested on aarch64-linux Ubuntu 20.04.

[1] Documentation/arm64/memory-tagging-extension.rst (Core Dump Support)
---
 bfd/elfnn-aarch64.c  | 88 ++++++++++++++++++++++++++++++++++++++++++++
 binutils/readelf.c   |  1 +
 include/elf/common.h |  5 +++
 3 files changed, 94 insertions(+)

diff --git a/bfd/elfnn-aarch64.c b/bfd/elfnn-aarch64.c
index 4926bab9cf2..a79a6849a3a 100644
--- a/bfd/elfnn-aarch64.c
+++ b/bfd/elfnn-aarch64.c
@@ -8158,6 +8158,88 @@ elfNN_aarch64_section_from_shdr (bfd *abfd,
   return true;
 }
 
+/* Process any AArch64-specific program segment types.  */
+
+static bool
+elfNN_aarch64_section_from_phdr (bfd *abfd ATTRIBUTE_UNUSED,
+				 Elf_Internal_Phdr *hdr,
+				 int hdr_index ATTRIBUTE_UNUSED,
+				 const char *name ATTRIBUTE_UNUSED)
+{
+  /* Right now we only handle the PT_ARM_MEMTAG_MTE segment type.  */
+  if (hdr == NULL || hdr->p_type != PT_ARM_MEMTAG_MTE)
+    return false;
+
+  if (hdr->p_filesz > 0)
+    {
+      /* Sections created from memory tag p_type's are always named
+	 "memtag".  This makes it easier for tools (for example, GDB)
+	 to find them.  */
+      asection *newsect = bfd_make_section_anyway (abfd, "memtag");
+
+      if (newsect == NULL)
+	return false;
+
+      unsigned int opb = bfd_octets_per_byte (abfd, NULL);
+
+      /* p_vaddr holds the original start address of the tagged memory
+	 range.  */
+      newsect->vma = hdr->p_vaddr / opb;
+
+      /* p_filesz holds the storage size of the packed tags.  */
+      newsect->size = hdr->p_filesz;
+      newsect->filepos = hdr->p_offset;
+
+      /* p_memsz holds the size of the memory range that contains tags.  The
+	 section's rawsize field is reused for this purpose.  */
+      newsect->rawsize = hdr->p_memsz;
+
+      /* Make sure the section's flags has SEC_HAS_CONTENTS set, otherwise
+	 BFD will return all zeroes when attempting to get contents from this
+	 section.  */
+      newsect->flags |= SEC_HAS_CONTENTS;
+    }
+
+  return true;
+}
+
+/* Implements the bfd_elf_modify_headers hook for aarch64.  */
+
+static bool
+elfNN_aarch64_modify_headers (bfd *abfd,
+			      struct bfd_link_info *info)
+{
+  struct elf_segment_map *m;
+  unsigned int segment_count = 0;
+  Elf_Internal_Phdr *p;
+
+  for (m = elf_seg_map (abfd); m != NULL; m = m->next, segment_count++)
+    {
+      /* We are only interested in the memory tag segment that will be dumped
+	 to a core file.  If we have no memory tags or this isn't a core file we
+	 are dealing with, just skip this segment.  */
+      if (m->p_type != PT_ARM_MEMTAG_MTE || bfd_get_format (abfd) != bfd_core)
+	continue;
+
+      /* For memory tag segments in core files, the size of the file contents
+	 is smaller than the size of the memory range.  Adjust the memory size
+	 accordingly.  The real memory size is held in the section's rawsize
+	 field.  */
+      if (m->count > 0)
+	{
+	  p = elf_tdata (abfd)->phdr;
+	  p += m->idx;
+	  p->p_memsz = m->sections[0]->rawsize;
+	  p->p_flags = 0;
+	  p->p_paddr = 0;
+	  p->p_align = 0;
+	}
+    }
+
+  /* Give the generic code a chance to handle the headers.  */
+  return _bfd_elf_modify_headers (abfd, info);
+}
+
 /* A structure used to record a list of sections, independently
    of the next and prev fields in the asection structure.  */
 typedef struct section_list
@@ -10059,6 +10141,12 @@ const struct elf_size_info elfNN_aarch64_size_info =
 #define elf_backend_section_from_shdr		\
   elfNN_aarch64_section_from_shdr
 
+#define elf_backend_section_from_phdr		\
+  elfNN_aarch64_section_from_phdr
+
+#define elf_backend_modify_headers		\
+  elfNN_aarch64_modify_headers
+
 #define elf_backend_size_dynamic_sections	\
   elfNN_aarch64_size_dynamic_sections
 
diff --git a/binutils/readelf.c b/binutils/readelf.c
index d45e0920788..bf574509cb0 100644
--- a/binutils/readelf.c
+++ b/binutils/readelf.c
@@ -4499,6 +4499,7 @@ get_aarch64_segment_type (unsigned long type)
   switch (type)
     {
     case PT_AARCH64_ARCHEXT:  return "AARCH64_ARCHEXT";
+    case PT_ARM_MEMTAG_MTE:   return "ARM_MEMTAG_MTE";
     default:                  return NULL;
     }
 }
diff --git a/include/elf/common.h b/include/elf/common.h
index e4bc53e35b4..4eeaf3d4949 100644
--- a/include/elf/common.h
+++ b/include/elf/common.h
@@ -500,6 +500,11 @@
 #define PT_GNU_MBIND_LO (PT_LOOS + 0x474e555)
 #define PT_GNU_MBIND_HI (PT_GNU_MBIND_LO + PT_GNU_MBIND_NUM - 1)
 
+/* ARM memory tag segment types.  */
+
+/* MTE memory tag segment type.  */
+#define PT_ARM_MEMTAG_MTE     (PT_LOPROC + 0x1)
+
 /* Program segment permissions, in program header p_flags field.  */
 
 #define PF_X		(1 << 0)	/* Segment is executable */
-- 
2.25.1


^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH, v2] [AArch64] Support AArch64 MTE memory tag dumps in core files
  2022-04-21 15:18 ` [PATCH, v2] [AArch64] Support AArch64 MTE memory tag dumps in core files Luis Machado
@ 2022-04-23  0:15   ` Alan Modra
  2022-04-23 21:50     ` Fangrui Song
  2022-05-03 11:23     ` Luis Machado
  0 siblings, 2 replies; 14+ messages in thread
From: Alan Modra @ 2022-04-23  0:15 UTC (permalink / raw)
  To: Luis Machado; +Cc: binutils

On Thu, Apr 21, 2022 at 04:18:41PM +0100, Luis Machado wrote:
> v2:
> 
> - Drop arch-specific fields from the generic section data structure.
> - Use the rawsize field of the section structure to store the original
>   memory range of the memory-tagged area.
> - Implement the bfd_elf_modify_headers for aarch64, to adjust the values
>   for the memory tag segment according to the Linux Kernel's format.

This looks OK to me, except for defining PT_ARM_MEMTAG_MTE in
elf/common.h.  That belongs in elf/aarch64.h.  BTW, why isn't the
header called PT_AARCH64_MEMTAG_MTE?  Using PT_ARM_ looks odd,
considering that we already have PT_ARM_EXIDX at LOPROC+1.

-- 
Alan Modra
Australia Development Lab, IBM

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH, v2] [AArch64] Support AArch64 MTE memory tag dumps in core files
  2022-04-23  0:15   ` Alan Modra
@ 2022-04-23 21:50     ` Fangrui Song
  2022-05-03 11:23     ` Luis Machado
  1 sibling, 0 replies; 14+ messages in thread
From: Fangrui Song @ 2022-04-23 21:50 UTC (permalink / raw)
  To: Alan Modra; +Cc: Luis Machado, binutils

On 2022-04-23, Alan Modra via Binutils wrote:
>On Thu, Apr 21, 2022 at 04:18:41PM +0100, Luis Machado wrote:
>> v2:
>>
>> - Drop arch-specific fields from the generic section data structure.
>> - Use the rawsize field of the section structure to store the original
>>   memory range of the memory-tagged area.
>> - Implement the bfd_elf_modify_headers for aarch64, to adjust the values
>>   for the memory tag segment according to the Linux Kernel's format.
>
>This looks OK to me, except for defining PT_ARM_MEMTAG_MTE in
>elf/common.h.  That belongs in elf/aarch64.h.  BTW, why isn't the
>header called PT_AARCH64_MEMTAG_MTE?  Using PT_ARM_ looks odd,
>considering that we already have PT_ARM_EXIDX at LOPROC+1.

Agree PT_LOPROC+1 is strange.

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH, v2] [AArch64] Support AArch64 MTE memory tag dumps in core files
  2022-04-23  0:15   ` Alan Modra
  2022-04-23 21:50     ` Fangrui Song
@ 2022-05-03 11:23     ` Luis Machado
  1 sibling, 0 replies; 14+ messages in thread
From: Luis Machado @ 2022-05-03 11:23 UTC (permalink / raw)
  To: Alan Modra; +Cc: binutils

Hi Alan,

On 4/23/22 01:15, Alan Modra wrote:
> On Thu, Apr 21, 2022 at 04:18:41PM +0100, Luis Machado wrote:
>> v2:
>>
>> - Drop arch-specific fields from the generic section data structure.
>> - Use the rawsize field of the section structure to store the original
>>    memory range of the memory-tagged area.
>> - Implement the bfd_elf_modify_headers for aarch64, to adjust the values
>>    for the memory tag segment according to the Linux Kernel's format.
> 
> This looks OK to me, except for defining PT_ARM_MEMTAG_MTE in
> elf/common.h.  That belongs in elf/aarch64.h.  BTW, why isn't the
> header called PT_AARCH64_MEMTAG_MTE?  Using PT_ARM_ looks odd,
> considering that we already have PT_ARM_EXIDX at LOPROC+1.
> 

Your comment made me go back and chase the reason behind this naming. 
Turns out we should really be naming it PT_AARCH64_MEMTAG_MTE. While at 
it we should also update the constant value given there is a another 
AArch64 segment type using PT_LOPROC + 1, one that is not yet known to 
binutils-gdb.

I'll send a v3.


Thanks,
Luis

^ permalink raw reply	[flat|nested] 14+ messages in thread

* [PATCH] [AArch64] Support AArch64 MTE memory tag dumps in core files
  2022-03-31 14:04 Support AArch64 MTE memory tag dumps in core files Luis Machado
  2022-04-01  1:34 ` Alan Modra
  2022-04-21 15:18 ` [PATCH, v2] [AArch64] Support AArch64 MTE memory tag dumps in core files Luis Machado
@ 2022-05-03 11:33 ` Luis Machado
  2022-05-11 15:13   ` Luis Machado
  2 siblings, 1 reply; 14+ messages in thread
From: Luis Machado @ 2022-05-03 11:33 UTC (permalink / raw)
  To: binutils

v3:

- Update the segment name from PT_ARM_MEMTAG_MTE to PT_AARCH64_MEMTAG_MTE
  and change its value to PT_LOPROC + 0x2, as PT_LOPROC + 0x1 was taken.

v2:

- Drop arch-specific fields from the generic section data structure.
- Use the rawsize field of the section structure to store the original
  memory range of the memory-tagged area.
- Implement the bfd_elf_modify_headers for aarch64, to adjust the values
  for the memory tag segment according to the Linux Kernel's format.

--

The Linux kernel can dump memory tag segments to a core file, one segment
per mapped range. The format and documentation can be found in the Linux
kernel tree [1].

The following patch adjusts bfd and binutils so they can handle this new
segment type and display it accordingly. It also adds code required so GDB
can properly read/dump core file data containing memory tags.

Upon reading, each segment that contains memory tags gets mapped to a
section named "memtag". These sections will be used by GDB to lookup the tag
data. There can be multiple such sections with the same name, and they are not
numbered to simplify GDB's handling and lookup.

There is another patch for GDB that enables both reading
and dumping of memory tag segments.

Tested on aarch64-linux Ubuntu 20.04.

[1] Documentation/arm64/memory-tagging-extension.rst (Core Dump Support)
---
 bfd/elfnn-aarch64.c   | 89 +++++++++++++++++++++++++++++++++++++++++++
 binutils/readelf.c    |  1 +
 include/elf/aarch64.h |  3 ++
 3 files changed, 93 insertions(+)

diff --git a/bfd/elfnn-aarch64.c b/bfd/elfnn-aarch64.c
index 4926bab9cf2..3eee97b7ada 100644
--- a/bfd/elfnn-aarch64.c
+++ b/bfd/elfnn-aarch64.c
@@ -8158,6 +8158,89 @@ elfNN_aarch64_section_from_shdr (bfd *abfd,
   return true;
 }
 
+/* Process any AArch64-specific program segment types.  */
+
+static bool
+elfNN_aarch64_section_from_phdr (bfd *abfd ATTRIBUTE_UNUSED,
+				 Elf_Internal_Phdr *hdr,
+				 int hdr_index ATTRIBUTE_UNUSED,
+				 const char *name ATTRIBUTE_UNUSED)
+{
+  /* Right now we only handle the PT_AARCH64_MEMTAG_MTE segment type.  */
+  if (hdr == NULL || hdr->p_type != PT_AARCH64_MEMTAG_MTE)
+    return false;
+
+  if (hdr->p_filesz > 0)
+    {
+      /* Sections created from memory tag p_type's are always named
+	 "memtag".  This makes it easier for tools (for example, GDB)
+	 to find them.  */
+      asection *newsect = bfd_make_section_anyway (abfd, "memtag");
+
+      if (newsect == NULL)
+	return false;
+
+      unsigned int opb = bfd_octets_per_byte (abfd, NULL);
+
+      /* p_vaddr holds the original start address of the tagged memory
+	 range.  */
+      newsect->vma = hdr->p_vaddr / opb;
+
+      /* p_filesz holds the storage size of the packed tags.  */
+      newsect->size = hdr->p_filesz;
+      newsect->filepos = hdr->p_offset;
+
+      /* p_memsz holds the size of the memory range that contains tags.  The
+	 section's rawsize field is reused for this purpose.  */
+      newsect->rawsize = hdr->p_memsz;
+
+      /* Make sure the section's flags has SEC_HAS_CONTENTS set, otherwise
+	 BFD will return all zeroes when attempting to get contents from this
+	 section.  */
+      newsect->flags |= SEC_HAS_CONTENTS;
+    }
+
+  return true;
+}
+
+/* Implements the bfd_elf_modify_headers hook for aarch64.  */
+
+static bool
+elfNN_aarch64_modify_headers (bfd *abfd,
+			      struct bfd_link_info *info)
+{
+  struct elf_segment_map *m;
+  unsigned int segment_count = 0;
+  Elf_Internal_Phdr *p;
+
+  for (m = elf_seg_map (abfd); m != NULL; m = m->next, segment_count++)
+    {
+      /* We are only interested in the memory tag segment that will be dumped
+	 to a core file.  If we have no memory tags or this isn't a core file we
+	 are dealing with, just skip this segment.  */
+      if (m->p_type != PT_AARCH64_MEMTAG_MTE
+	  || bfd_get_format (abfd) != bfd_core)
+	continue;
+
+      /* For memory tag segments in core files, the size of the file contents
+	 is smaller than the size of the memory range.  Adjust the memory size
+	 accordingly.  The real memory size is held in the section's rawsize
+	 field.  */
+      if (m->count > 0)
+	{
+	  p = elf_tdata (abfd)->phdr;
+	  p += m->idx;
+	  p->p_memsz = m->sections[0]->rawsize;
+	  p->p_flags = 0;
+	  p->p_paddr = 0;
+	  p->p_align = 0;
+	}
+    }
+
+  /* Give the generic code a chance to handle the headers.  */
+  return _bfd_elf_modify_headers (abfd, info);
+}
+
 /* A structure used to record a list of sections, independently
    of the next and prev fields in the asection structure.  */
 typedef struct section_list
@@ -10059,6 +10142,12 @@ const struct elf_size_info elfNN_aarch64_size_info =
 #define elf_backend_section_from_shdr		\
   elfNN_aarch64_section_from_shdr
 
+#define elf_backend_section_from_phdr		\
+  elfNN_aarch64_section_from_phdr
+
+#define elf_backend_modify_headers		\
+  elfNN_aarch64_modify_headers
+
 #define elf_backend_size_dynamic_sections	\
   elfNN_aarch64_size_dynamic_sections
 
diff --git a/binutils/readelf.c b/binutils/readelf.c
index d45e0920788..ea20479daef 100644
--- a/binutils/readelf.c
+++ b/binutils/readelf.c
@@ -4499,6 +4499,7 @@ get_aarch64_segment_type (unsigned long type)
   switch (type)
     {
     case PT_AARCH64_ARCHEXT:  return "AARCH64_ARCHEXT";
+    case PT_AARCH64_MEMTAG_MTE:	return "AARCH64_MEMTAG_MTE";
     default:                  return NULL;
     }
 }
diff --git a/include/elf/aarch64.h b/include/elf/aarch64.h
index 703a62baeca..e368ff2dffe 100644
--- a/include/elf/aarch64.h
+++ b/include/elf/aarch64.h
@@ -27,6 +27,9 @@
 /* Processor specific program header types.  */
 #define PT_AARCH64_ARCHEXT	(PT_LOPROC + 0)
 
+/* MTE memory tag segment type.  */
+#define PT_AARCH64_MEMTAG_MTE     (PT_LOPROC + 0x2)
+
 /* Additional section types.  */
 #define SHT_AARCH64_ATTRIBUTES	0x70000003  /* Section holds attributes.  */
 
-- 
2.25.1


^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH] [AArch64] Support AArch64 MTE memory tag dumps in core files
  2022-05-03 11:33 ` [PATCH] " Luis Machado
@ 2022-05-11 15:13   ` Luis Machado
  2022-05-12  0:18     ` Alan Modra
  0 siblings, 1 reply; 14+ messages in thread
From: Luis Machado @ 2022-05-11 15:13 UTC (permalink / raw)
  To: binutils, Alan Modra

Alan,

Does this updated version look OK to you?

On 5/3/22 12:33, Luis Machado via Binutils wrote:
> v3:
> 
> - Update the segment name from PT_ARM_MEMTAG_MTE to PT_AARCH64_MEMTAG_MTE
>    and change its value to PT_LOPROC + 0x2, as PT_LOPROC + 0x1 was taken.
> 
> v2:
> 
> - Drop arch-specific fields from the generic section data structure.
> - Use the rawsize field of the section structure to store the original
>    memory range of the memory-tagged area.
> - Implement the bfd_elf_modify_headers for aarch64, to adjust the values
>    for the memory tag segment according to the Linux Kernel's format.
> 
> --
> 
> The Linux kernel can dump memory tag segments to a core file, one segment
> per mapped range. The format and documentation can be found in the Linux
> kernel tree [1].
> 
> The following patch adjusts bfd and binutils so they can handle this new
> segment type and display it accordingly. It also adds code required so GDB
> can properly read/dump core file data containing memory tags.
> 
> Upon reading, each segment that contains memory tags gets mapped to a
> section named "memtag". These sections will be used by GDB to lookup the tag
> data. There can be multiple such sections with the same name, and they are not
> numbered to simplify GDB's handling and lookup.
> 
> There is another patch for GDB that enables both reading
> and dumping of memory tag segments.
> 
> Tested on aarch64-linux Ubuntu 20.04.
> 
> [1] Documentation/arm64/memory-tagging-extension.rst (Core Dump Support)
> ---
>   bfd/elfnn-aarch64.c   | 89 +++++++++++++++++++++++++++++++++++++++++++
>   binutils/readelf.c    |  1 +
>   include/elf/aarch64.h |  3 ++
>   3 files changed, 93 insertions(+)
> 
> diff --git a/bfd/elfnn-aarch64.c b/bfd/elfnn-aarch64.c
> index 4926bab9cf2..3eee97b7ada 100644
> --- a/bfd/elfnn-aarch64.c
> +++ b/bfd/elfnn-aarch64.c
> @@ -8158,6 +8158,89 @@ elfNN_aarch64_section_from_shdr (bfd *abfd,
>     return true;
>   }
>   
> +/* Process any AArch64-specific program segment types.  */
> +
> +static bool
> +elfNN_aarch64_section_from_phdr (bfd *abfd ATTRIBUTE_UNUSED,
> +				 Elf_Internal_Phdr *hdr,
> +				 int hdr_index ATTRIBUTE_UNUSED,
> +				 const char *name ATTRIBUTE_UNUSED)
> +{
> +  /* Right now we only handle the PT_AARCH64_MEMTAG_MTE segment type.  */
> +  if (hdr == NULL || hdr->p_type != PT_AARCH64_MEMTAG_MTE)
> +    return false;
> +
> +  if (hdr->p_filesz > 0)
> +    {
> +      /* Sections created from memory tag p_type's are always named
> +	 "memtag".  This makes it easier for tools (for example, GDB)
> +	 to find them.  */
> +      asection *newsect = bfd_make_section_anyway (abfd, "memtag");
> +
> +      if (newsect == NULL)
> +	return false;
> +
> +      unsigned int opb = bfd_octets_per_byte (abfd, NULL);
> +
> +      /* p_vaddr holds the original start address of the tagged memory
> +	 range.  */
> +      newsect->vma = hdr->p_vaddr / opb;
> +
> +      /* p_filesz holds the storage size of the packed tags.  */
> +      newsect->size = hdr->p_filesz;
> +      newsect->filepos = hdr->p_offset;
> +
> +      /* p_memsz holds the size of the memory range that contains tags.  The
> +	 section's rawsize field is reused for this purpose.  */
> +      newsect->rawsize = hdr->p_memsz;
> +
> +      /* Make sure the section's flags has SEC_HAS_CONTENTS set, otherwise
> +	 BFD will return all zeroes when attempting to get contents from this
> +	 section.  */
> +      newsect->flags |= SEC_HAS_CONTENTS;
> +    }
> +
> +  return true;
> +}
> +
> +/* Implements the bfd_elf_modify_headers hook for aarch64.  */
> +
> +static bool
> +elfNN_aarch64_modify_headers (bfd *abfd,
> +			      struct bfd_link_info *info)
> +{
> +  struct elf_segment_map *m;
> +  unsigned int segment_count = 0;
> +  Elf_Internal_Phdr *p;
> +
> +  for (m = elf_seg_map (abfd); m != NULL; m = m->next, segment_count++)
> +    {
> +      /* We are only interested in the memory tag segment that will be dumped
> +	 to a core file.  If we have no memory tags or this isn't a core file we
> +	 are dealing with, just skip this segment.  */
> +      if (m->p_type != PT_AARCH64_MEMTAG_MTE
> +	  || bfd_get_format (abfd) != bfd_core)
> +	continue;
> +
> +      /* For memory tag segments in core files, the size of the file contents
> +	 is smaller than the size of the memory range.  Adjust the memory size
> +	 accordingly.  The real memory size is held in the section's rawsize
> +	 field.  */
> +      if (m->count > 0)
> +	{
> +	  p = elf_tdata (abfd)->phdr;
> +	  p += m->idx;
> +	  p->p_memsz = m->sections[0]->rawsize;
> +	  p->p_flags = 0;
> +	  p->p_paddr = 0;
> +	  p->p_align = 0;
> +	}
> +    }
> +
> +  /* Give the generic code a chance to handle the headers.  */
> +  return _bfd_elf_modify_headers (abfd, info);
> +}
> +
>   /* A structure used to record a list of sections, independently
>      of the next and prev fields in the asection structure.  */
>   typedef struct section_list
> @@ -10059,6 +10142,12 @@ const struct elf_size_info elfNN_aarch64_size_info =
>   #define elf_backend_section_from_shdr		\
>     elfNN_aarch64_section_from_shdr
>   
> +#define elf_backend_section_from_phdr		\
> +  elfNN_aarch64_section_from_phdr
> +
> +#define elf_backend_modify_headers		\
> +  elfNN_aarch64_modify_headers
> +
>   #define elf_backend_size_dynamic_sections	\
>     elfNN_aarch64_size_dynamic_sections
>   
> diff --git a/binutils/readelf.c b/binutils/readelf.c
> index d45e0920788..ea20479daef 100644
> --- a/binutils/readelf.c
> +++ b/binutils/readelf.c
> @@ -4499,6 +4499,7 @@ get_aarch64_segment_type (unsigned long type)
>     switch (type)
>       {
>       case PT_AARCH64_ARCHEXT:  return "AARCH64_ARCHEXT";
> +    case PT_AARCH64_MEMTAG_MTE:	return "AARCH64_MEMTAG_MTE";
>       default:                  return NULL;
>       }
>   }
> diff --git a/include/elf/aarch64.h b/include/elf/aarch64.h
> index 703a62baeca..e368ff2dffe 100644
> --- a/include/elf/aarch64.h
> +++ b/include/elf/aarch64.h
> @@ -27,6 +27,9 @@
>   /* Processor specific program header types.  */
>   #define PT_AARCH64_ARCHEXT	(PT_LOPROC + 0)
>   
> +/* MTE memory tag segment type.  */
> +#define PT_AARCH64_MEMTAG_MTE     (PT_LOPROC + 0x2)
> +
>   /* Additional section types.  */
>   #define SHT_AARCH64_ATTRIBUTES	0x70000003  /* Section holds attributes.  */
>   


^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH] [AArch64] Support AArch64 MTE memory tag dumps in core files
  2022-05-11 15:13   ` Luis Machado
@ 2022-05-12  0:18     ` Alan Modra
  2022-06-02  3:26       ` Fangrui Song
       [not found]       ` <DS7PR12MB57657DCC1DA5A6A4ABD7F813CBDE9@DS7PR12MB5765.namprd12.prod.outlook.com>
  0 siblings, 2 replies; 14+ messages in thread
From: Alan Modra @ 2022-05-12  0:18 UTC (permalink / raw)
  To: Luis Machado; +Cc: binutils

On Wed, May 11, 2022 at 04:13:13PM +0100, Luis Machado wrote:
> Alan,
> 
> Does this updated version look OK to you?

Yes.

-- 
Alan Modra
Australia Development Lab, IBM

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH] [AArch64] Support AArch64 MTE memory tag dumps in core files
  2022-05-12  0:18     ` Alan Modra
@ 2022-06-02  3:26       ` Fangrui Song
       [not found]       ` <DS7PR12MB57657DCC1DA5A6A4ABD7F813CBDE9@DS7PR12MB5765.namprd12.prod.outlook.com>
  1 sibling, 0 replies; 14+ messages in thread
From: Fangrui Song @ 2022-06-02  3:26 UTC (permalink / raw)
  To: Alan Modra; +Cc: Luis Machado, binutils

On Wed, May 11, 2022 at 5:18 PM Alan Modra via Binutils
<binutils@sourceware.org> wrote:
>
> On Wed, May 11, 2022 at 04:13:13PM +0100, Luis Machado wrote:
> > Alan,
> >
> > Does this updated version look OK to you?
>
> Yes.

Is this ready to be submitted?

Note: due to %-14.14s, readelf -l truncates the name and displays the
first 14 characters: "AARCH64_MEMTAG".
This is an existing issue that affects several long program header types.

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH] [AArch64] Support AArch64 MTE memory tag dumps in core files
       [not found]       ` <DS7PR12MB57657DCC1DA5A6A4ABD7F813CBDE9@DS7PR12MB5765.namprd12.prod.outlook.com>
@ 2022-06-06  7:05         ` Luis Machado
  2022-07-19 14:27           ` Luis Machado
  0 siblings, 1 reply; 14+ messages in thread
From: Luis Machado @ 2022-06-06  7:05 UTC (permalink / raw)
  To: Fangrui Song, Alan Modra; +Cc: binutils

On 6/2/22 04:26, Fangrui Song wrote:
> On Wed, May 11, 2022 at 5:18 PM Alan Modra via Binutils
> <binutils@sourceware.org> wrote:
>>
>> On Wed, May 11, 2022 at 04:13:13PM +0100, Luis Machado wrote:
>>> Alan,
>>>
>>> Does this updated version look OK to you?
>>
>> Yes.
> 
> Is this ready to be submitted?

It is, but I want to push this alongside the GDB changes, which have not been approved yet.

> 
> Note: due to %-14.14s, readelf -l truncates the name and displays the
> first 14 characters: "AARCH64_MEMTAG".
> This is an existing issue that affects several long program header types.

That's odd. Thanks for the heads-up.

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH] [AArch64] Support AArch64 MTE memory tag dumps in core files
  2022-06-06  7:05         ` Luis Machado
@ 2022-07-19 14:27           ` Luis Machado
  0 siblings, 0 replies; 14+ messages in thread
From: Luis Machado @ 2022-07-19 14:27 UTC (permalink / raw)
  To: Fangrui Song, Alan Modra; +Cc: binutils

On 6/6/22 08:05, Luis Machado via Binutils wrote:
> On 6/2/22 04:26, Fangrui Song wrote:
>> On Wed, May 11, 2022 at 5:18 PM Alan Modra via Binutils
>> <binutils@sourceware.org> wrote:
>>>
>>> On Wed, May 11, 2022 at 04:13:13PM +0100, Luis Machado wrote:
>>>> Alan,
>>>>
>>>> Does this updated version look OK to you?
>>>
>>> Yes.
>>
>> Is this ready to be submitted?
> 
> It is, but I want to push this alongside the GDB changes, which have not been approved yet.
> 
>>
>> Note: due to %-14.14s, readelf -l truncates the name and displays the
>> first 14 characters: "AARCH64_MEMTAG".
>> This is an existing issue that affects several long program header types.
> 
> That's odd. Thanks for the heads-up.

Got the OK from the GDB maintainers. I've pushed now this, alongside the GDB
changes.

^ permalink raw reply	[flat|nested] 14+ messages in thread

end of thread, other threads:[~2022-07-19 14:27 UTC | newest]

Thread overview: 14+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-03-31 14:04 Support AArch64 MTE memory tag dumps in core files Luis Machado
2022-04-01  1:34 ` Alan Modra
2022-04-01  8:21   ` Luis Machado
2022-04-03 12:04   ` Move microblaze relax info to target specific data Alan Modra
2022-04-21 15:18 ` [PATCH, v2] [AArch64] Support AArch64 MTE memory tag dumps in core files Luis Machado
2022-04-23  0:15   ` Alan Modra
2022-04-23 21:50     ` Fangrui Song
2022-05-03 11:23     ` Luis Machado
2022-05-03 11:33 ` [PATCH] " Luis Machado
2022-05-11 15:13   ` Luis Machado
2022-05-12  0:18     ` Alan Modra
2022-06-02  3:26       ` Fangrui Song
     [not found]       ` <DS7PR12MB57657DCC1DA5A6A4ABD7F813CBDE9@DS7PR12MB5765.namprd12.prod.outlook.com>
2022-06-06  7:05         ` Luis Machado
2022-07-19 14:27           ` Luis Machado

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).