Move DT_RELR tag setting to elflink.c
authorAlan Modra <amodra@gmail.com>
Thu, 13 Jan 2022 00:29:30 +0000 (10:59 +1030)
committerAlan Modra <amodra@gmail.com>
Thu, 13 Jan 2022 03:42:43 +0000 (14:12 +1030)
This makes the code setting DT_RELR tags generally available.  Many
targets will be able to use the defaults.  Those that can't should set
up sh_entsize for .relr.dyn output section before reaching the dynamic
tag code in bfd_elf_final_link.

* elflink.c (bfd_elf_final_link): Set up DT_RELR tags and sh_entsize.
* elfxx-x86.c (_bfd_x86_elf_finish_dynamic_sections): Don't do any
of that here.

bfd/elflink.c
bfd/elfxx-x86.c

index 4529f83dbcab55f728b46cd5a08314a6d8fb9777..2677561478dd1ff9bc9d6e495c06948f2d22f049 100644 (file)
@@ -12209,7 +12209,8 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info)
   const struct elf_backend_data *bed = get_elf_backend_data (abfd);
   struct elf_outext_info eoinfo;
   bool merged;
-  size_t relativecount = 0;
+  size_t relativecount;
+  size_t relr_entsize;
   asection *reldyn = 0;
   bfd_size_type amt;
   asection *attr_section = NULL;
@@ -13053,9 +13054,24 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info)
       o->reloc_count = 0;
     }
 
+  relativecount = 0;
   if (dynamic && info->combreloc && dynobj != NULL)
     relativecount = elf_link_sort_relocs (abfd, info, &reldyn);
 
+  relr_entsize = 0;
+  if (htab->srelrdyn != NULL
+      && htab->srelrdyn->output_section != NULL
+      && htab->srelrdyn->size != 0)
+    {
+      asection *s = htab->srelrdyn->output_section;
+      relr_entsize = elf_section_data (s)->this_hdr.sh_entsize;
+      if (relr_entsize == 0)
+       {
+         relr_entsize = bed->s->arch_size / 8;
+         elf_section_data (s)->this_hdr.sh_entsize = relr_entsize;
+       }
+    }
+
   /* If we are linking against a dynamic object, or generating a
      shared library, finish up the dynamic linking information.  */
   if (dynamic)
@@ -13083,17 +13099,44 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info)
            default:
              continue;
            case DT_NULL:
-             if (relativecount > 0 && dyncon + bed->s->sizeof_dyn < dynconend)
+             if (relativecount != 0)
                {
                  switch (elf_section_data (reldyn)->this_hdr.sh_type)
                    {
                    case SHT_REL: dyn.d_tag = DT_RELCOUNT; break;
                    case SHT_RELA: dyn.d_tag = DT_RELACOUNT; break;
-                   default: continue;
                    }
-                 dyn.d_un.d_val = relativecount;
+                 if (dyn.d_tag != DT_NULL
+                     && dynconend - dyncon >= bed->s->sizeof_dyn)
+                   {
+                     dyn.d_un.d_val = relativecount;
+                     relativecount = 0;
+                     break;
+                   }
                  relativecount = 0;
-                 break;
+               }
+             if (relr_entsize != 0)
+               {
+                 if (dynconend - dyncon >= 3 * bed->s->sizeof_dyn)
+                   {
+                     asection *s = htab->srelrdyn;
+                     dyn.d_tag = DT_RELR;
+                     dyn.d_un.d_ptr
+                       = s->output_section->vma + s->output_offset;
+                     bed->s->swap_dyn_out (dynobj, &dyn, dyncon);
+                     dyncon += bed->s->sizeof_dyn;
+
+                     dyn.d_tag = DT_RELRSZ;
+                     dyn.d_un.d_val = s->size;
+                     bed->s->swap_dyn_out (dynobj, &dyn, dyncon);
+                     dyncon += bed->s->sizeof_dyn;
+
+                     dyn.d_tag = DT_RELRENT;
+                     dyn.d_un.d_val = relr_entsize;
+                     relr_entsize = 0;
+                     break;
+                   }
+                 relr_entsize = 0;
                }
              continue;
 
index 119929bb093854596314648d8ab2393b66726907..da8a488db3688b0b1324ed5344e5d7eca7c8e309 100644 (file)
@@ -2388,7 +2388,6 @@ _bfd_x86_elf_finish_dynamic_sections (bfd *output_bfd,
   asection *sdyn;
   bfd_byte *dyncon, *dynconend;
   bfd_size_type sizeof_dyn;
-  bfd_size_type dt_relr_bitmap_count;
 
   bed = get_elf_backend_data (output_bfd);
   htab = elf_x86_hash_table (info, bed->target_id);
@@ -2447,8 +2446,6 @@ _bfd_x86_elf_finish_dynamic_sections (bfd *output_bfd,
   if (sdyn == NULL || htab->elf.sgot == NULL)
     abort ();
 
-  dt_relr_bitmap_count = htab->dt_relr_bitmap.count;
-
   sizeof_dyn = bed->s->sizeof_dyn;
   dyncon = sdyn->contents;
   dynconend = sdyn->contents + sdyn->size;
@@ -2467,28 +2464,6 @@ _bfd_x86_elf_finish_dynamic_sections (bfd *output_bfd,
            break;
          continue;
 
-       case DT_NULL:
-         if (dt_relr_bitmap_count != 0)
-           {
-             /* Convert 3 spare dynamic tags to DT_RELR, DT_RELRSZ and
-                DT_RELRENT for compact relative relocation.  */
-             s = htab->elf.srelrdyn;
-             dyn.d_tag = DT_RELR;
-             dyn.d_un.d_ptr = s->output_section->vma + s->output_offset;
-             (*bed->s->swap_dyn_out) (output_bfd, &dyn, dyncon);
-             dyncon += sizeof_dyn;
-             dyn.d_tag = DT_RELRSZ;
-             dyn.d_un.d_val = s->size;
-             (*bed->s->swap_dyn_out) (output_bfd, &dyn, dyncon);
-             dyncon += sizeof_dyn;
-             dyn.d_tag = DT_RELRENT;
-             dyn.d_un.d_val = ABI_64_P (output_bfd) ? 8 : 4;
-             elf_section_data (s->output_section)->this_hdr.sh_entsize
-               = dyn.d_un.d_val;
-             dt_relr_bitmap_count = 0;
-           }
-         break;
-
        case DT_PLTGOT:
          s = htab->elf.sgotplt;
          dyn.d_un.d_ptr = s->output_section->vma + s->output_offset;