RFC: Store ELF section index for input file

H. J. Lu hjl@lucon.org
Thu Mar 17 22:03:00 GMT 2005


When there are many sections in input file,
_bfd_elf_make_section_from_shdr can be very slow. Can we store ELF
section index in bfd section for input file? With this patch, the link
time of my testcase went from

966.01s user 0.81s system 99% cpu 16:06.87 total

to

49.03s user 0.76s system 99% cpu 49.816 total


H.J.
--- bfd/elf-bfd.h.fast	2005-03-03 13:35:31.000000000 -0800
+++ bfd/elf-bfd.h	2005-03-17 11:14:18.656521092 -0800
@@ -629,7 +629,7 @@ struct elf_backend_data
   /* A function to handle unusual section types when creating BFD
      sections from ELF sections.  */
   bfd_boolean (*elf_backend_section_from_shdr)
-    (bfd *, Elf_Internal_Shdr *, const char *);
+    (bfd *, Elf_Internal_Shdr *, const char *, int);
 
   /* A function to convert machine dependent section header flags to
      BFD internal section header flags.  */
@@ -1060,7 +1060,8 @@ struct bfd_elf_section_data
   unsigned int rel_count2;
 
   /* The ELF section number of this section.  Only used for an output
-     file.  */
+     file.  Also used for an input file as the index into the ELF
+     section array, elf_elfsections.  */
   int this_idx;
 
   /* The ELF section number of the reloc section indicated by
@@ -1416,7 +1417,7 @@ extern bfd_boolean bfd_elf_mkcorefile
 extern Elf_Internal_Shdr *bfd_elf_find_section
   (bfd *, char *);
 extern bfd_boolean _bfd_elf_make_section_from_shdr
-  (bfd *, Elf_Internal_Shdr *, const char *);
+  (bfd *, Elf_Internal_Shdr *, const char *, int);
 extern bfd_boolean _bfd_elf_make_section_from_phdr
   (bfd *, Elf_Internal_Phdr *, int, const char *);
 extern struct bfd_hash_entry *_bfd_elf_link_hash_newfunc
--- bfd/elf.c.fast	2005-03-16 15:14:41.000000000 -0800
+++ bfd/elf.c	2005-03-17 11:19:25.464861663 -0800
@@ -673,7 +673,8 @@ bfd_elf_is_group_section (bfd *abfd ATTR
 bfd_boolean
 _bfd_elf_make_section_from_shdr (bfd *abfd,
 				 Elf_Internal_Shdr *hdr,
-				 const char *name)
+				 const char *name,
+				 int shindex)
 {
   asection *newsect;
   flagword flags;
@@ -692,6 +693,7 @@ _bfd_elf_make_section_from_shdr (bfd *ab
 
   hdr->bfd_section = newsect;
   elf_section_data (newsect)->this_hdr = *hdr;
+  elf_section_data (newsect)->this_idx = shindex;
 
   /* Always use the real type/flags.  */
   elf_section_type (newsect) = hdr->sh_type;
@@ -1730,10 +1732,10 @@ bfd_section_from_shdr (bfd *abfd, unsign
     case SHT_FINI_ARRAY:	/* .fini_array section.  */
     case SHT_PREINIT_ARRAY:	/* .preinit_array section.  */
     case SHT_GNU_LIBLIST:	/* .gnu.liblist section.  */
-      return _bfd_elf_make_section_from_shdr (abfd, hdr, name);
+      return _bfd_elf_make_section_from_shdr (abfd, hdr, name, shindex);
 
     case SHT_DYNAMIC:	/* Dynamic linking information.  */
-      if (! _bfd_elf_make_section_from_shdr (abfd, hdr, name))
+      if (! _bfd_elf_make_section_from_shdr (abfd, hdr, name, shindex))
 	return FALSE;
       if (elf_elfsections (abfd)[hdr->sh_link]->sh_type != SHT_STRTAB)
 	{
@@ -1784,7 +1786,8 @@ bfd_section_from_shdr (bfd *abfd, unsign
          linker.  */
       if ((hdr->sh_flags & SHF_ALLOC) != 0
 	  && (abfd->flags & DYNAMIC) != 0
-	  && ! _bfd_elf_make_section_from_shdr (abfd, hdr, name))
+	  && ! _bfd_elf_make_section_from_shdr (abfd, hdr, name,
+						shindex))
 	return FALSE;
 
       /* Go looking for SHT_SYMTAB_SHNDX too, since if there is one we
@@ -1828,7 +1831,7 @@ bfd_section_from_shdr (bfd *abfd, unsign
 
       /* Besides being a symbol table, we also treat this as a regular
 	 section, so that objcopy can handle it.  */
-      return _bfd_elf_make_section_from_shdr (abfd, hdr, name);
+      return _bfd_elf_make_section_from_shdr (abfd, hdr, name, shindex);
 
     case SHT_SYMTAB_SHNDX:	/* Symbol section indices when >64k sections */
       if (elf_symtab_shndx (abfd) == shindex)
@@ -1864,7 +1867,8 @@ bfd_section_from_shdr (bfd *abfd, unsign
 	  elf_elfsections (abfd)[shindex] = hdr;
 	  /* We also treat this as a regular section, so that objcopy
 	     can handle it.  */
-	  return _bfd_elf_make_section_from_shdr (abfd, hdr, name);
+	  return _bfd_elf_make_section_from_shdr (abfd, hdr, name,
+						  shindex);
 	}
 
       /* If the string table isn't one of the above, then treat it as a
@@ -1889,7 +1893,7 @@ bfd_section_from_shdr (bfd *abfd, unsign
 		}
 	    }
 	}
-      return _bfd_elf_make_section_from_shdr (abfd, hdr, name);
+      return _bfd_elf_make_section_from_shdr (abfd, hdr, name, shindex);
 
     case SHT_REL:
     case SHT_RELA:
@@ -1906,7 +1910,8 @@ bfd_section_from_shdr (bfd *abfd, unsign
 	    ((*_bfd_error_handler)
 	     (_("%B: invalid link %lu for reloc section %s (index %u)"),
 	      abfd, hdr->sh_link, name, shindex));
-	    return _bfd_elf_make_section_from_shdr (abfd, hdr, name);
+	    return _bfd_elf_make_section_from_shdr (abfd, hdr, name,
+						    shindex);
 	  }
 
 	/* For some incomprehensible reason Oracle distributes
@@ -1953,7 +1958,8 @@ bfd_section_from_shdr (bfd *abfd, unsign
 	   can't use it as a reloc section if it points to the null
 	   section.  */
 	if (hdr->sh_link != elf_onesymtab (abfd) || hdr->sh_info == SHN_UNDEF)
-	  return _bfd_elf_make_section_from_shdr (abfd, hdr, name);
+	  return _bfd_elf_make_section_from_shdr (abfd, hdr, name,
+						  shindex);
 
 	if (! bfd_section_from_shdr (abfd, hdr->sh_info))
 	  return FALSE;
@@ -1990,19 +1996,19 @@ bfd_section_from_shdr (bfd *abfd, unsign
     case SHT_GNU_verdef:
       elf_dynverdef (abfd) = shindex;
       elf_tdata (abfd)->dynverdef_hdr = *hdr;
-      return _bfd_elf_make_section_from_shdr (abfd, hdr, name);
+      return _bfd_elf_make_section_from_shdr (abfd, hdr, name, shindex);
       break;
 
     case SHT_GNU_versym:
       elf_dynversym (abfd) = shindex;
       elf_tdata (abfd)->dynversym_hdr = *hdr;
-      return _bfd_elf_make_section_from_shdr (abfd, hdr, name);
+      return _bfd_elf_make_section_from_shdr (abfd, hdr, name, shindex);
       break;
 
     case SHT_GNU_verneed:
       elf_dynverref (abfd) = shindex;
       elf_tdata (abfd)->dynverref_hdr = *hdr;
-      return _bfd_elf_make_section_from_shdr (abfd, hdr, name);
+      return _bfd_elf_make_section_from_shdr (abfd, hdr, name, shindex);
       break;
 
     case SHT_SHLIB:
@@ -2015,7 +2021,7 @@ bfd_section_from_shdr (bfd *abfd, unsign
       name = group_signature (abfd, hdr);
       if (name == NULL)
 	return FALSE;
-      if (!_bfd_elf_make_section_from_shdr (abfd, hdr, name))
+      if (!_bfd_elf_make_section_from_shdr (abfd, hdr, name, shindex))
 	return FALSE;
       if (hdr->contents != NULL)
 	{
@@ -2041,7 +2047,8 @@ bfd_section_from_shdr (bfd *abfd, unsign
 
     default:
       /* Check for any processor-specific section types.  */
-      return bed->elf_backend_section_from_shdr (abfd, hdr, name);
+      return bed->elf_backend_section_from_shdr (abfd, hdr, name,
+						 shindex);
     }
 
   return TRUE;
--- bfd/elfxx-ia64.c.fast	2005-03-16 15:14:41.000000000 -0800
+++ bfd/elfxx-ia64.c	2005-03-17 11:23:28.057503044 -0800
@@ -193,8 +193,6 @@ static void elfNN_ia64_relax_ldxmov
   PARAMS((bfd_byte *contents, bfd_vma off));
 static bfd_boolean is_unwind_section_name
   PARAMS ((bfd *abfd, const char *));
-static bfd_boolean elfNN_ia64_section_from_shdr
-  PARAMS ((bfd *, Elf_Internal_Shdr *, const char *));
 static bfd_boolean elfNN_ia64_section_flags
   PARAMS ((flagword *, const Elf_Internal_Shdr *));
 static bfd_boolean elfNN_ia64_fake_sections
@@ -1271,13 +1269,14 @@ is_unwind_section_name (abfd, name)
 }
 
 /* Handle an IA-64 specific section when reading an object file.  This
-   is called when elfcode.h finds a section with an unknown type.  */
+   is called when bfd_section_from_shdr finds a section with an unknown
+   type.  */
 
 static bfd_boolean
-elfNN_ia64_section_from_shdr (abfd, hdr, name)
-     bfd *abfd;
-     Elf_Internal_Shdr *hdr;
-     const char *name;
+elfNN_ia64_section_from_shdr (bfd *abfd,
+			      Elf_Internal_Shdr *hdr,
+			      const char *name,
+			      int shindex)
 {
   asection *newsect;
 
@@ -1301,7 +1300,7 @@ elfNN_ia64_section_from_shdr (abfd, hdr,
       return FALSE;
     }
 
-  if (! _bfd_elf_make_section_from_shdr (abfd, hdr, name))
+  if (! _bfd_elf_make_section_from_shdr (abfd, hdr, name, shindex))
     return FALSE;
   newsect = hdr->bfd_section;
 



More information about the Binutils mailing list