[binutils-gdb] Move DT_RELR tag setting to elflink.c

Alan Modra amodra@sourceware.org
Thu Jan 13 03:43:21 GMT 2022


https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=9c3d7d9b7ed5f442fea1ddcb41fc1e0488f51588

commit 9c3d7d9b7ed5f442fea1ddcb41fc1e0488f51588
Author: Alan Modra <amodra@gmail.com>
Date:   Thu Jan 13 10:59:30 2022 +1030

    Move DT_RELR tag setting to elflink.c
    
    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.

Diff:
---
 bfd/elflink.c   | 53 ++++++++++++++++++++++++++++++++++++++++++++++++-----
 bfd/elfxx-x86.c | 25 -------------------------
 2 files changed, 48 insertions(+), 30 deletions(-)

diff --git a/bfd/elflink.c b/bfd/elflink.c
index 4529f83dbca..2677561478d 100644
--- a/bfd/elflink.c
+++ b/bfd/elflink.c
@@ -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;
 
diff --git a/bfd/elfxx-x86.c b/bfd/elfxx-x86.c
index 119929bb093..da8a488db36 100644
--- a/bfd/elfxx-x86.c
+++ b/bfd/elfxx-x86.c
@@ -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;


More information about the Binutils-cvs mailing list