]> git.ipfire.org Git - thirdparty/binutils-gdb.git/commitdiff
elf: Add size_relative_relocs and finish_relative_relocs
authorH.J. Lu <hjl.tools@gmail.com>
Thu, 6 Jan 2022 17:24:41 +0000 (09:24 -0800)
committerH.J. Lu <hjl.tools@gmail.com>
Wed, 12 Jan 2022 14:04:51 +0000 (06:04 -0800)
On some targets, the DT_RELR section size can be computed only after all
symbols addresses can be determined.  Set the preliminary DT_RELR section
size before mapping sections to segments and set the final DT_RELR section
size after regular symbol processing is done.

* elf-bfd.h (elf_backend_data): Add size_relative_relocs and
finish_relative_relocs.
* elf.c (_bfd_elf_map_sections_to_segments): Call
size_relative_relocs if DT_RELR is enabled.
* elflink.c (bfd_elf_final_link): Call finish_relative_relocs
after regular symbol processing is finished if DT_RELR is enabled.
* elfxx-target.h (elf_backend_size_relative_relocs): New.
(elf_backend_finish_relative_relocs): Likewise.
(elfNN_bed): Add elf_backend_size_relative_relocs and
elf_backend_finish_relative_relocs.

bfd/elf-bfd.h
bfd/elf.c
bfd/elflink.c
bfd/elfxx-target.h

index 7808f87d1f4b887461514e28dc010a7703ced65d..4a85255a50088cbc9ee47edd74613ded169c8132 100644 (file)
@@ -1105,6 +1105,16 @@ struct elf_backend_data
     (bfd *abfd, struct bfd_link_info *info, asection *o,
      const Elf_Internal_Rela *relocs);
 
+  /* The SIZE_RELATIVE_RELOCS function is called to size relative
+     relocations when mappig sections to segments.  */
+  bool (*size_relative_relocs)
+    (struct bfd_link_info *info, bool *need_layout);
+
+  /* The FINISH_RELATIVE_RELOCS function is called to finish relative
+     relocations in bfd_elf_final_link.  */
+  bool (*finish_relative_relocs)
+    (struct bfd_link_info *info);
+
   /* The CHECK_DIRECTIVES function is called once per input file by
      the add_symbols phase of the ELF backend linker.  The function
      must inspect the bfd and create any additional symbols according
index 8b866b63e1858b2ebf1781efe7051579dbcfcf5d..14c2c7ba734d4d0e5ccec7a637597aae08a97777 100644 (file)
--- a/bfd/elf.c
+++ b/bfd/elf.c
@@ -4615,7 +4615,7 @@ elf_modify_segment_map (bfd *abfd,
 bool
 _bfd_elf_map_sections_to_segments (bfd *abfd,
                                   struct bfd_link_info *info,
-                                  bool *need_layout ATTRIBUTE_UNUSED)
+                                  bool *need_layout)
 {
   unsigned int count;
   struct elf_segment_map *m;
@@ -4626,7 +4626,17 @@ _bfd_elf_map_sections_to_segments (bfd *abfd,
   no_user_phdrs = elf_seg_map (abfd) == NULL;
 
   if (info != NULL)
-    info->user_phdrs = !no_user_phdrs;
+    {
+      info->user_phdrs = !no_user_phdrs;
+
+      /* Size the relative relocations if DT_RELR is enabled.  */
+      if (info->enable_dt_relr
+         && need_layout != NULL
+         && bed->size_relative_relocs
+         && !bed->size_relative_relocs (info, need_layout))
+       info->callbacks->einfo
+         (_("%F%P: failed to size relative relocations\n"));
+    }
 
   if (no_user_phdrs && bfd_count_sections (abfd) != 0)
     {
index 17407f26bc161863c62d4d54bf38e757acadbb95..1613bc748195cdf188fecd9139c0199fc34e701f 100644 (file)
@@ -12599,6 +12599,14 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info)
   if (!_bfd_elf_fixup_eh_frame_hdr (info))
     return false;
 
+  /* Finish relative relocations here after regular symbol processing
+     is finished if DT_RELR is enabled.  */
+  if (info->enable_dt_relr
+      && bed->finish_relative_relocs
+      && !bed->finish_relative_relocs (info))
+    info->callbacks->einfo
+      (_("%F%P: %pB: failed to finish relative relocations\n"), abfd);
+
   /* Since ELF permits relocations to be against local symbols, we
      must have the local symbols available when we do the relocations.
      Since we would rather only read the local symbols once, and we
index 360b056ff58f5ddfeb6c789e095d9740b88fa015..e31985ef77739aaae6575b83bdc9c60b943bffd1 100644 (file)
 #ifndef elf_backend_check_relocs
 #define elf_backend_check_relocs       0
 #endif
+#ifndef elf_backend_size_relative_relocs
+#define elf_backend_size_relative_relocs 0
+#endif
+#ifndef elf_backend_finish_relative_relocs
+#define elf_backend_finish_relative_relocs 0
+#endif
 #ifndef elf_backend_check_directives
 #define elf_backend_check_directives   0
 #endif
@@ -842,6 +848,8 @@ static const struct elf_backend_data elfNN_bed =
   elf_backend_omit_section_dynsym,
   elf_backend_relocs_compatible,
   elf_backend_check_relocs,
+  elf_backend_size_relative_relocs,
+  elf_backend_finish_relative_relocs,
   elf_backend_check_directives,
   elf_backend_notice_as_needed,
   elf_backend_adjust_dynamic_symbol,