]> git.ipfire.org Git - thirdparty/binutils-gdb.git/commitdiff
[Morello] Pad section alignment to account for capability range format
authorSiddhesh Poyarekar <siddesh.poyarekar@arm.com>
Fri, 11 Sep 2020 03:48:11 +0000 (09:18 +0530)
committerLuis Machado <luis.machado@linaro.org>
Tue, 20 Oct 2020 18:04:26 +0000 (15:04 -0300)
The capability format has limitations on the alignment and length of
capability bounds and are subject to rounding.  Add alignment and
padding at the boundaries of such long (typically >16M) sections so
that any capabilities referencing these sections do not end up
overlapping into neighbouring sections.

There are two cases where this is in use.  The first and most
important due to the current implementation is the range for PCC,
which needs to span all executable sections and all PLT and GOT
sections.  The other case is for linker and ldscript defined symbols
that may be used in dynamic relocations.

bfd/ChangeLog:

2020-10-20  Siddhesh Poyarekar  <siddesh.poyarekar@arm.com>

* elfnn-aarch64.c (elf_aarch64_link_hash_table): New member.
(section_start_symbol, c64_valid_cap_range, exponent): Move
up.
(sec_change_queue): New structure.
(queue_section_padding, record_section_change,
elfNN_c64_resize_sections): New functions.
(bfd_elfNN_aarch64_init_maps): Add info argument.  Adjust
callers.
* elfxx-aarch64.h (bfd_elf64_aarch64_init_maps,
bfd_elf32_aarch64_init_maps): Add info argument.
(elf64_c64_resize_sections, elf32_c64_resize_sections): New
function declarations.

ld/ChangeLog:

2020-10-20  Siddhesh Poyarekar  <siddesh.poyarekar@arm.com>

* emultempl/aarch64elf.em (elf64_c64_pad_section): New
function.
(gld${EMULATION_NAME}_after_allocation): Resize C64 sections.
* ldlang.c (lang_add_newdot): New function.
* ldlang.h (lang_add_newdot): New function declaration.
* testsuite/ld-aarch64/aarch64-elf.exp: Add new test.
* testsuite/ld-aarch64/morello-sec-round.d: New file.
* testsuite/ld-aarch64/morello-sec-round.ld: New file.
* testsuite/ld-aarch64/morello-sec-round.s: New file.

bfd/ChangeLog
bfd/elfnn-aarch64.c
bfd/elfxx-aarch64.h
ld/ChangeLog
ld/emultempl/aarch64elf.em
ld/ldlang.c
ld/ldlang.h
ld/testsuite/ld-aarch64/aarch64-elf.exp
ld/testsuite/ld-aarch64/morello-sec-round.d [new file with mode: 0644]
ld/testsuite/ld-aarch64/morello-sec-round.ld [new file with mode: 0644]
ld/testsuite/ld-aarch64/morello-sec-round.s [new file with mode: 0644]

index e714ede5d336194445666d34dbf0a5fc8c262ace..66e167c404387d9643315b395e3791e44861d11e 100644 (file)
@@ -1,3 +1,18 @@
+2020-10-20  Siddhesh Poyarekar  <siddesh.poyarekar@arm.com>
+
+       * elfnn-aarch64.c (elf_aarch64_link_hash_table): New member.
+       (section_start_symbol, c64_valid_cap_range, exponent): Move
+       up.
+       (sec_change_queue): New structure.
+       (queue_section_padding, record_section_change,
+       elfNN_c64_resize_sections): New functions.
+       (bfd_elfNN_aarch64_init_maps): Add info argument.  Adjust
+       callers.
+       * elfxx-aarch64.h (bfd_elf64_aarch64_init_maps,
+       bfd_elf32_aarch64_init_maps): Add info argument.
+       (elf64_c64_resize_sections, elf32_c64_resize_sections): New
+       function declarations.
+
 2020-10-20  Siddhesh Poyarekar  <siddesh.poyarekar@arm.com>
 
        * elf-bfd.h (elf_backend_data): New callback
index f1a43e18e0e57a33dbc0638b34d149aed5b64e70..83158d61cd19f9f105d7a9ffb3fd791813d7627d 100644 (file)
@@ -3049,6 +3049,7 @@ struct elf_aarch64_link_hash_table
   /* Used for capability relocations.  */
   asection *srelcaps;
   int c64_rel;
+  bfd_boolean c64_output;
 };
 
 /* Create an entry in an AArch64 ELF linker hash table.  */
@@ -4694,6 +4695,306 @@ _bfd_aarch64_erratum_843419_scan (bfd *input_bfd, asection *section,
   return TRUE;
 }
 
+static bfd_boolean
+section_start_symbol (bfd *abfd ATTRIBUTE_UNUSED, asection *section,
+                     void *valp)
+{
+  return section->vma == *(bfd_vma *)valp;
+}
+
+/* Capability format functions.  */
+
+static unsigned
+exponent (uint64_t len)
+{
+#define CAP_MAX_EXPONENT 50
+  /* Size is a 65 bit value, so there's an implicit 0 MSB.  */
+  unsigned zeroes = __builtin_clzl (len) + 1;
+
+  /* All bits up to and including CAP_MW - 2 are zero.  */
+  if (CAP_MAX_EXPONENT < zeroes)
+    return (unsigned) -1;
+  else
+    return CAP_MAX_EXPONENT - zeroes;
+#undef CAP_MAX_EXPONENT
+}
+
+#define ONES(x)         ((1ULL << ((x) + 1)) - 1)
+#define ALIGN_UP(x, a)  (((x) + ONES (a)) & (~ONES (a)))
+
+static bfd_boolean
+c64_valid_cap_range (bfd_vma *basep, bfd_vma *limitp)
+{
+  bfd_vma base = *basep, size = *limitp - *basep;
+
+  unsigned e, old_e;
+
+  if ((e = exponent (size)) == (unsigned) -1)
+    return TRUE;
+
+  size = ALIGN_UP (size, e + 3);
+  old_e = e;
+  e = exponent (size);
+  if (old_e != e)
+    size = ALIGN_UP (size, e + 3);
+
+  base = ALIGN_UP (base, e + 3);
+
+  if (base == *basep && *limitp == base + size)
+    return TRUE;
+
+  *basep = base;
+  *limitp = base + size;
+  return FALSE;
+}
+
+struct sec_change_queue
+{
+  asection *sec;
+  struct sec_change_queue *next;
+};
+
+/* Queue up the change, sorted in order of the output section vma.  */
+
+static void
+queue_section_padding (struct sec_change_queue **queue, asection *sec)
+{
+  struct sec_change_queue *q = *queue, *last_q = NULL, *n;
+
+  while (q != NULL)
+    {
+      if (q->sec->vma > sec->vma)
+       break;
+      last_q = q;
+      q = q->next;
+    }
+
+  n = bfd_zmalloc (sizeof (struct sec_change_queue));
+
+  if (last_q == NULL)
+    *queue = n;
+  else
+    {
+      n->next = q;
+      last_q->next = n;
+    }
+
+  n->sec = sec;
+}
+
+/* Check if the bounds covering all sections between LOW_SEC and HIGH_SEC will
+   get rounded off in the Morello capability format and if it does, queue up a
+   change to fix up the section layout.  */
+static inline void
+record_section_change (asection *sec, struct sec_change_queue **queue)
+{
+  bfd_vma low = sec->vma;
+  bfd_vma high = sec->vma + sec->size;
+
+  if (!c64_valid_cap_range (&low, &high))
+    queue_section_padding (queue, sec);
+}
+
+/* Make sure that all capabilities that refer to sections have bounds that
+   won't overlap with neighbouring sections.  This is needed in two specific
+   cases.  The first case is that of PCC, which needs to span across all
+   executable sections as well as the GOT and PLT sections in the output
+   binary.  The second case is that of linker and ldscript defined symbols that
+   indicate start and/or end of sections.
+
+   In both cases, overlap of capability bounds are avoided by aligning the base
+   of the section and if necessary, adding a pad at the end of the section so
+   that the section following it starts only after the pad.  */
+
+void
+elfNN_c64_resize_sections (bfd *output_bfd, struct bfd_link_info *info,
+                          void (*c64_pad_section) (asection *, bfd_vma),
+                          void (*layout_sections_again) (void))
+{
+  asection *sec, *pcc_low_sec = NULL, *pcc_high_sec = NULL;
+  struct elf_aarch64_link_hash_table *htab = elf_aarch64_hash_table (info);
+  bfd_vma low = (bfd_vma) -1, high = 0;
+
+  htab->layout_sections_again = layout_sections_again;
+
+  if (!htab->c64_output)
+    return;
+
+  struct sec_change_queue *queue = NULL;
+
+  /* First, walk through all the relocations to find those referring to linker
+     defined and ldscript defined symbols since we set their range to their
+     output sections.  */
+  for (bfd *input_bfd = info->input_bfds;
+       htab->c64_rel && input_bfd != NULL; input_bfd = input_bfd->link.next)
+    {
+      Elf_Internal_Shdr *symtab_hdr;
+
+      symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr;
+      if (symtab_hdr->sh_info == 0)
+       continue;
+
+      for (sec = input_bfd->sections; sec != NULL; sec = sec->next)
+       {
+         Elf_Internal_Rela *irelaend, *irela;
+
+         /* If there aren't any relocs, then there's nothing more to do.  */
+         if ((sec->flags & SEC_RELOC) == 0 || sec->reloc_count == 0)
+           continue;
+
+         irela = _bfd_elf_link_read_relocs (input_bfd, sec, NULL, NULL,
+                                            info->keep_memory);
+         if (irela == NULL)
+           continue;
+
+         /* Now examine each relocation.  */
+         irelaend = irela + sec->reloc_count;
+         for (; irela < irelaend; irela++)
+           {
+             unsigned int r_indx;
+             struct elf_link_hash_entry *h;
+             int e_indx;
+             asection *os;
+
+             r_indx = ELFNN_R_SYM (irela->r_info);
+
+             /* Linker defined or linker script defined symbols are always in
+                the symbol hash.  */
+             if (r_indx < symtab_hdr->sh_info)
+               continue;
+
+             e_indx = r_indx - symtab_hdr->sh_info;
+             h = elf_sym_hashes (input_bfd)[e_indx];
+
+             /* XXX Does this ever happen?  */
+             if (h == NULL)
+               continue;
+
+             os = h->root.u.def.section->output_section;
+
+             if (h->root.linker_def)
+               record_section_change (os, &queue);
+             else if (h->root.ldscript_def)
+               {
+                 const char *name = h->root.root.string;
+                 size_t len = strlen (name);
+
+                 if (len > 8 && name[0] == '_' && name[1] == '_'
+                     && (!strncmp (name + 2, "start_", 6)
+                         || !strcmp (name + len - 6, "_start")))
+
+                   {
+                     bfd_vma value = os->vma + os->size;
+
+                     os = bfd_sections_find_if (info->output_bfd,
+                                                section_start_symbol, &value);
+
+                     if (os != NULL)
+                       record_section_change (os, &queue);
+                   }
+                 /* XXX We're overfitting here because the offset of H within
+                    the output section is not yet resolved and ldscript
+                    defined symbols do not have input section information.  */
+                 else
+                   record_section_change (os, &queue);
+               }
+           }
+       }
+    }
+
+  /* Next, walk through output sections to find the PCC span and add a padding
+     at the end to ensure that PCC bounds don't bleed into neighbouring
+     sections.  For now PCC needs to encompass all code sections, .got, .plt
+     and .got.plt.  */
+  for (sec = output_bfd->sections; sec != NULL; sec = sec->next)
+    {
+      /* XXX This is a good place to figure out if there are any readable or
+        writable sections in the PCC range that are not in the list of
+        sections we want the PCC to span and then warn the user of it.  */
+
+#define NOT_OP_SECTION(s) ((s) == NULL || (s)->output_section != sec)
+
+      if ((sec->flags & SEC_CODE) == 0
+         && NOT_OP_SECTION (htab->root.sgotplt)
+         && NOT_OP_SECTION (htab->root.igotplt)
+         && NOT_OP_SECTION (htab->root.sgot)
+         && NOT_OP_SECTION (htab->root.splt)
+         && NOT_OP_SECTION (htab->root.iplt))
+       continue;
+
+      if (sec->vma < low)
+       {
+         low = sec->vma;
+         pcc_low_sec = sec;
+       }
+      if (sec->vma + sec->size > high)
+       {
+         high = sec->vma + sec->size;
+         pcc_high_sec = sec;
+       }
+
+#undef NOT_OP_SECTION
+    }
+
+  /* Sequentially add alignment and padding as required.  We also need to
+     account for the PCC-related alignment and padding here since its
+     requirements could change based on the range of sections it encompasses
+     and whether they need to be padded or aligned.  */
+  while (queue)
+    {
+      unsigned align = 0;
+      bfd_vma padding = 0;
+
+      low = queue->sec->vma;
+      high = queue->sec->vma + queue->sec->size;
+
+      if (!c64_valid_cap_range (&low, &high))
+       {
+         align = __builtin_ctzl (low);
+
+         if (queue->sec->alignment_power < align)
+           queue->sec->alignment_power = align;
+
+         padding = high - queue->sec->vma - queue->sec->size;
+
+         if (queue->sec != pcc_high_sec)
+           {
+             c64_pad_section (queue->sec, padding);
+             padding = 0;
+           }
+       }
+
+      /* If we have crossed all sections within the PCC range, set up alignment
+         and padding for the PCC range.  */
+      if (pcc_high_sec != NULL && pcc_low_sec != NULL
+         && (queue->next == NULL
+             || queue->next->sec->vma > pcc_high_sec->vma))
+       {
+         /* Layout sections since it affects the final range of PCC.  */
+         (*htab->layout_sections_again) ();
+
+         bfd_vma pcc_low = pcc_low_sec->vma;
+         bfd_vma pcc_high = pcc_high_sec->vma + pcc_high_sec->size + padding;
+
+         if (!c64_valid_cap_range (&pcc_low, &pcc_high))
+           {
+             align = __builtin_ctzl (pcc_low);
+             if (pcc_low_sec->alignment_power < align)
+               pcc_low_sec->alignment_power = align;
+
+             padding = pcc_high - pcc_high_sec->vma - pcc_high_sec->size;
+             c64_pad_section (pcc_high_sec, padding);
+           }
+       }
+
+      (*htab->layout_sections_again) ();
+
+      struct sec_change_queue *queue_free = queue;
+
+      queue = queue->next;
+      free (queue_free);
+    }
+}
 
 /* Determine and set the size of the stub section for a final link.
 
@@ -5194,7 +5495,7 @@ elfNN_aarch64_section_map_add (bfd *abfd, asection *sec, char type,
 
 /* Initialise maps of insn/data for input BFDs.  */
 void
-bfd_elfNN_aarch64_init_maps (bfd *abfd)
+bfd_elfNN_aarch64_init_maps (bfd *abfd, struct bfd_link_info *info)
 {
   Elf_Internal_Sym *isymbuf;
   Elf_Internal_Shdr *hdr;
@@ -5222,6 +5523,8 @@ bfd_elfNN_aarch64_init_maps (bfd *abfd)
   if (isymbuf == NULL)
     return;
 
+  struct elf_aarch64_link_hash_table *htab = elf_aarch64_hash_table ((info));
+
   for (i = 0; i < localsyms; i++)
     {
       Elf_Internal_Sym *isym = &isymbuf[i];
@@ -5236,7 +5539,12 @@ bfd_elfNN_aarch64_init_maps (bfd *abfd)
 
          if (bfd_is_aarch64_special_symbol_name
              (name, BFD_AARCH64_SPECIAL_SYM_TYPE_MAP))
-           elfNN_aarch64_section_map_add (abfd, sec, name[1], isym->st_value);
+           {
+             elfNN_aarch64_section_map_add (abfd, sec, name[1],
+                                            isym->st_value);
+             if (!htab->c64_output && name[1] == 'c')
+               htab->c64_output = TRUE;
+           }
        }
     }
   elf_aarch64_tdata (abfd)->secmaps_initialised = TRUE;
@@ -5923,53 +6231,6 @@ aarch64_relocation_aginst_gp_p (bfd_reloc_code_real_type reloc)
          || reloc == BFD_RELOC_AARCH64_MOVW_GOTOFF_G1);
 }
 
-/* Capability format functions.  */
-
-static unsigned
-exponent (uint64_t len)
-{
-#define CAP_MAX_EXPONENT 50
-  /* Size is a 65 bit value, so there's an implicit 0 MSB.  */
-  unsigned zeroes = __builtin_clzl (len) + 1;
-
-  /* All bits up to and including CAP_MW - 2 are zero.  */
-  if (CAP_MAX_EXPONENT < zeroes)
-    return (unsigned) -1;
-  else
-    return CAP_MAX_EXPONENT - zeroes;
-#undef CAP_MAX_EXPONENT
-}
-
-#define ONES(x)         ((1ULL << ((x) + 1)) - 1)
-#define ALIGN_UP(x, a)  (((x) + ONES (a)) & (~ONES (a)))
-
-static bfd_boolean
-c64_valid_cap_range (bfd_vma *basep, bfd_vma *limitp)
-{
-  bfd_vma base = *basep, size = *limitp - *basep;
-
-  unsigned e, old_e;
-
-  if ((e = exponent (size)) == (unsigned) -1)
-    return TRUE;
-
-  size = ALIGN_UP (size, e + 3);
-  old_e = e;
-  e = exponent (size);
-  if (old_e != e)
-    size = ALIGN_UP (size, e + 3);
-
-  base = ALIGN_UP (base, e + 3);
-
-  if (base == *basep && *limitp == base + size)
-    return TRUE;
-
-  *basep = base;
-  *limitp = base + size;
-  return FALSE;
-}
-
-
 /* Build capability meta data, i.e. size and permissions for a capability.  */
 
 static bfd_vma
@@ -5993,13 +6254,6 @@ cap_meta (size_t size, const asection *sec)
   abort ();
 }
 
-static bfd_boolean
-section_start_symbol (bfd *abfd ATTRIBUTE_UNUSED, asection *section,
-                     void *valp)
-{
-  return section->vma == *(bfd_vma *)valp;
-}
-
 static bfd_reloc_status_type
 c64_fixup_frag (bfd *input_bfd, struct bfd_link_info *info,
                bfd_reloc_code_real_type bfd_r_type, Elf_Internal_Sym *sym,
@@ -8477,7 +8731,7 @@ elfNN_aarch64_check_relocs (bfd *abfd, struct bfd_link_info *info,
   symtab_hdr = &elf_symtab_hdr (abfd);
   sym_hashes = elf_sym_hashes (abfd);
 
-  bfd_elfNN_aarch64_init_maps (abfd);
+  bfd_elfNN_aarch64_init_maps (abfd, info);
 
   rel_end = relocs + sec->reloc_count;
   for (rel = relocs; rel < rel_end; rel++)
@@ -9904,7 +10158,7 @@ elfNN_aarch64_size_dynamic_sections (bfd *output_bfd,
       {
        if (!is_aarch64_elf (ibfd))
          continue;
-       bfd_elfNN_aarch64_init_maps (ibfd);
+       bfd_elfNN_aarch64_init_maps (ibfd, info);
       }
 
   /* We now have determined the sizes of the various dynamic sections.
index 0bb78aa896b1430f340b8d17447be43fcffa6362..c9fc01bc71736f4e9f1026a618805178b4bac1ab 100644 (file)
    see <http://www.gnu.org/licenses/>.  */
 
 extern void bfd_elf64_aarch64_init_maps
-  (bfd *);
+  (bfd *, struct bfd_link_info *);
 
 extern void bfd_elf32_aarch64_init_maps
-  (bfd *);
+  (bfd *, struct bfd_link_info *);
 
 /* Types of PLTs based on the level of security.  This would be a
    bit-mask to denote which of the combinations of security features
@@ -82,6 +82,11 @@ extern bfd_boolean elf64_aarch64_size_stubs
   (bfd *, bfd *, struct bfd_link_info *, bfd_signed_vma,
    struct bfd_section * (*) (const char *, struct bfd_section *),
    void (*) (void));
+
+extern void elf64_c64_resize_sections (bfd *, struct bfd_link_info *,
+                                      void (*) (asection *, bfd_vma),
+                                      void (*) (void));
+
 extern bfd_boolean elf64_aarch64_build_stubs
   (struct bfd_link_info *);
 /* AArch64 stub generation support for ELF32.  Called from the linker.  */
@@ -96,6 +101,10 @@ extern bfd_boolean elf32_aarch64_size_stubs
 extern bfd_boolean elf32_aarch64_build_stubs
   (struct bfd_link_info *);
 
+extern void elf32_c64_resize_sections (bfd *, struct bfd_link_info *,
+                                      void (*) (asection *, bfd_vma),
+                                      void (*) (void));
+
 /* Take the PAGE component of an address or offset.  */
 #define PG(x)       ((x) & ~ (bfd_vma) 0xfff)
 #define PG_OFFSET(x) ((x) &   (bfd_vma) 0xfff)
index 303810eac6d6f0c3fddae3cdc3cb1b409392c47a..268a370cf2670815869cb625c3fadf421273a8cf 100644 (file)
@@ -1,3 +1,15 @@
+2020-10-20  Siddhesh Poyarekar  <siddesh.poyarekar@arm.com>
+
+       * emultempl/aarch64elf.em (elf64_c64_pad_section): New
+       function.
+       (gld${EMULATION_NAME}_after_allocation): Resize C64 sections.
+       * ldlang.c (lang_add_newdot): New function.
+       * ldlang.h (lang_add_newdot): New function declaration.
+       * testsuite/ld-aarch64/aarch64-elf.exp: Add new test.
+       * testsuite/ld-aarch64/morello-sec-round.d: New file.
+       * testsuite/ld-aarch64/morello-sec-round.ld: New file.
+       * testsuite/ld-aarch64/morello-sec-round.s: New file.
+
 2020-10-20  Siddhesh Poyarekar  <siddesh.poyarekar@arm.com>
 
        * testsuite/ld-aarch64/aarch64-elf.exp: Add test.
index a036da970e7e9bace0c3a3286ab3a39b45bff1ec..95cee025e3dc7f0f573ed170db3a0f050b375e6f 100644 (file)
@@ -67,7 +67,7 @@ aarch64_elf_before_allocation (void)
       LANG_FOR_EACH_INPUT_STATEMENT (is)
       {
        /* Initialise mapping tables for code/data.  */
-       bfd_elf${ELFSIZE}_aarch64_init_maps (is->the_bfd);
+       bfd_elf${ELFSIZE}_aarch64_init_maps (is->the_bfd, &link_info);
       }
     }
 
@@ -205,6 +205,30 @@ elf${ELFSIZE}_aarch64_add_stub_section (const char *stub_sec_name,
   return NULL;
 }
 
+/* Insert a pad immediately after OUTPUT_SECTION.  */
+
+static void
+elf64_c64_pad_section (asection *osec, bfd_vma padding)
+{
+  if (padding > 0)
+    {
+      lang_statement_list_type list;
+      lang_output_section_statement_type *os = lang_output_section_get (osec);
+
+      lang_list_init (&list);
+      lang_add_newdot (&list, osec->vma + osec->size + padding);
+
+      if (list.head == NULL)
+        {
+          einfo (_("%X%P: can not make padding section: %E\n"));
+          return;
+        }
+
+      *(list.tail) = os->header.next;
+      os->header.next = list.head;
+    }
+}
+
 /* Another call-back for elf${ELFSIZE}_aarch64_size_stubs.  */
 
 static void
@@ -250,6 +274,10 @@ gld${EMULATION_NAME}_after_allocation (void)
   else if (ret > 0)
     need_laying_out = 1;
 
+  elf${ELFSIZE}_c64_resize_sections (link_info.output_bfd, & link_info,
+                                    & elf64_c64_pad_section,
+                                    & gldaarch64_layout_sections_again);
+
   /* If generating a relocatable output file, then we don't
      have to examine the relocs.  */
   if (stub_file != NULL && !bfd_link_relocatable (&link_info))
index 2073ac09ce4320ddccd657726cf209aa90b82af4..fb9340603c2aa2f0dbf038ea975b192d0e95349f 100644 (file)
@@ -8370,6 +8370,16 @@ lang_add_assignment (etree_type *exp)
   return new_stmt;
 }
 
+void
+lang_add_newdot (lang_statement_list_type *ptr, bfd_vma newdot)
+{
+  lang_assignment_statement_type *new_stmt;
+  etree_type *exp = exp_assign (".", exp_intop (newdot), FALSE);
+
+  new_stmt = new_stat (lang_assignment_statement, ptr);
+  new_stmt->exp = exp;
+}
+
 void
 lang_add_attribute (enum statement_enum attribute)
 {
index 196debfa37e8ed15f2b1b67d57df05d8c9cf21f2..6074e2cb0129f60d7efbd44c8d9a14050b44f7c2 100644 (file)
@@ -561,6 +561,8 @@ extern lang_assignment_statement_type *lang_add_assignment
   (union etree_union *);
 extern void lang_add_attribute
   (enum statement_enum);
+extern void lang_add_newdot
+  (lang_statement_list_type *, bfd_vma);
 extern void lang_startup
   (const char *);
 extern void lang_float
index c2296f690fef43d99e1eaa99f85c7fc11f521c19..3e56105882ca6050c11e0b1e2eb5a4bca08efa2f 100644 (file)
@@ -248,6 +248,7 @@ run_dump_test_lp64 "emit-relocs-morello-3-a64c"
 run_dump_test_lp64 "morello-capinit"
 run_dump_test_lp64 "morello-stubs"
 run_dump_test_lp64 "morello-stubs-static"
+run_dump_test_lp64 "morello-sec-round"
 
 run_dump_test "reloc-overflow-bad"
 
diff --git a/ld/testsuite/ld-aarch64/morello-sec-round.d b/ld/testsuite/ld-aarch64/morello-sec-round.d
new file mode 100644 (file)
index 0000000..00eceb0
--- /dev/null
@@ -0,0 +1,11 @@
+#as: -march=morello+c64
+#ld: -static -pie -T morello-sec-round.ld
+#objdump: -x
+#...
+Sections:
+Idx Name          Size      VMA               LMA               File off  Algn
+#...
+  1 .text_sec     00020004  ...........20000  [0-9a-f]+  [0-9a-f]+  2\*\*17
+                  CONTENTS, ALLOC, LOAD, READONLY, CODE
+  2 \..*       [0-9a-f]+  ...........40080  [0-9a-f]+  [0-9a-f]+  .*
+#pass
diff --git a/ld/testsuite/ld-aarch64/morello-sec-round.ld b/ld/testsuite/ld-aarch64/morello-sec-round.ld
new file mode 100644 (file)
index 0000000..876c968
--- /dev/null
@@ -0,0 +1,12 @@
+SECTIONS {
+   . = SIZEOF_HEADERS;
+   .dynamic : { *(.dynamic) }
+   .text_sec :
+       {
+               text_sym = .;
+               *(.text)
+       }
+   .plt : { *(.plt) }
+   .got : { *(.got) }
+   .interp : { *(.interp) }
+}
diff --git a/ld/testsuite/ld-aarch64/morello-sec-round.s b/ld/testsuite/ld-aarch64/morello-sec-round.s
new file mode 100644 (file)
index 0000000..c7033bb
--- /dev/null
@@ -0,0 +1,9 @@
+.text
+.globl _start
+_start:
+       adrp c0, :got:text_sym
+       bl _start
+       ret
+.align 17
+_foo:
+       ret