This is the mail archive of the binutils@sourceware.org mailing list for the binutils project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

PR 15891 infrastructure


Hi,

I invested some time in order to get a fix for bug 15891.
I tried to implement the --as-needed functionality with two passes in (in the function elf_link_add_object_symbols() in bfd/elflink.c). The first pass just performs some processing in order to figure out whether the object is needed or nor. A roll back is performed in any way after that.
The second pass performs the real processing if needed.

I have attached the (WIP-) patch below. It is *not* finished yet because ld reports some other error messages on --as needed, just as the following (Iceweasel/Firefox 17 testsuite which does a lot of linkages): /usr/bin/ld: /usr/lib/debug/usr/lib/ia64-linux-gnu/crt1.o(.debug_info): relocation 1 has invalid symbol index 13 /usr/bin/ld: /usr/lib/debug/usr/lib/ia64-linux-gnu/crt1.o(.debug_info): relocation 2 has invalid symbol index 2 /usr/bin/ld: /usr/lib/debug/usr/lib/ia64-linux-gnu/crt1.o(.debug_info): relocation 3 has invalid symbol index 2 /usr/bin/ld: /usr/lib/debug/usr/lib/ia64-linux-gnu/crt1.o(.debug_info): relocation 4 has invalid symbol index 12 /usr/bin/ld: /usr/lib/debug/usr/lib/ia64-linux-gnu/crt1.o(.debug_info): relocation 5 has invalid symbol index 14 /usr/bin/ld: /usr/lib/debug/usr/lib/ia64-linux-gnu/crt1.o(.debug_info): relocation 6 has invalid symbol index 14 /usr/bin/ld: /usr/lib/debug/usr/lib/ia64-linux-gnu/crt1.o(.debug_info): relocation 7 has invalid symbol index 14 /usr/bin/ld: /usr/lib/debug/usr/lib/ia64-linux-gnu/crt1.o(.debug_info): relocation 8 has invalid symbol index 2 /usr/bin/ld: /usr/lib/debug/usr/lib/ia64-linux-gnu/crt1.o(.debug_info): relocation 9 has invalid symbol index 2 /usr/bin/ld: /usr/lib/debug/usr/lib/ia64-linux-gnu/crt1.o(.debug_info): relocation 10 has invalid symbol index 13 /usr/bin/ld: /usr/lib/debug/usr/lib/ia64-linux-gnu/crt1.o(.debug_info): relocation 11 has invalid symbol index 14 /usr/bin/ld: /usr/lib/debug/usr/lib/ia64-linux-gnu/crt1.o(.debug_info): relocation 12 has invalid symbol index 14 /usr/bin/ld: /usr/lib/debug/usr/lib/ia64-linux-gnu/crt1.o(.debug_info): relocation 13 has invalid symbol index 14 /usr/bin/ld: /usr/lib/debug/usr/lib/ia64-linux-gnu/crt1.o(.debug_info): relocation 14 has invalid symbol index 14 /usr/bin/ld: /usr/lib/debug/usr/lib/ia64-linux-gnu/crt1.o(.debug_info): relocation 15 has invalid symbol index 14 /usr/bin/ld: /usr/lib/debug/usr/lib/ia64-linux-gnu/crt1.o(.debug_info): relocation 16 has invalid symbol index 14 /usr/bin/ld: /usr/lib/debug/usr/lib/ia64-linux-gnu/crt1.o(.debug_info): relocation 17 has invalid symbol index 14 /usr/bin/ld: /usr/lib/debug/usr/lib/ia64-linux-gnu/crt1.o(.debug_info): relocation 18 has invalid symbol index 14 /usr/bin/ld: /usr/lib/debug/usr/lib/ia64-linux-gnu/crt1.o(.debug_info): relocation 19 has invalid symbol index 14 /usr/bin/ld: /usr/lib/debug/usr/lib/ia64-linux-gnu/crt1.o(.debug_info): relocation 20 has invalid symbol index 22 /usr/bin/ld: /usr/lib/debug/usr/lib/ia64-linux-gnu/crt1.o(.debug_line): relocation 0 has invalid symbol index 2 /usr/lib/gcc/ia64-linux-gnu/4.6/../../../ia64-linux-gnu/crt1.o: In function `_start':
(.text+0x72): undefined reference to `__libc_start_main'
../bignum-dtoa.o: In function `EstimatePower':
/scratch/iceweasel-17/iceweasel-17.0.8esr/mfbt/double-conversion/bignum-dtoa.cc:410: undefined reference to `ceil' ../bignum-dtoa.o: In function `double_conversion::BignumDtoa(double, double_conversion::BignumDtoaMode, int, double_conversion::Vector<char>, int*, int*)': /scratch/iceweasel-17/iceweasel-17.0.8esr/mfbt/double-conversion/bignum-dtoa.cc:166: undefined reference to `abort'
../bignum.o: In function `HexCharValue':
/scratch/iceweasel-17/iceweasel-17.0.8esr/mfbt/double-conversion/bignum.cc:126: undefined reference to `abort'
../bignum.o: In function `double_conversion::Bignum::EnsureCapacity(int)':
/scratch/iceweasel-17/iceweasel-17.0.8esr/mfbt/double-conversion/bignum.h:116: undefined reference to `abort' /scratch/iceweasel-17/iceweasel-17.0.8esr/mfbt/double-conversion/bignum.h:116: undefined reference to `abort'
../bignum.o: In function `double_conversion::Bignum::Square()':
/scratch/iceweasel-17/iceweasel-17.0.8esr/mfbt/double-conversion/bignum.cc:358: undefined reference to `abort' ../bignum.o:/scratch/iceweasel-17/iceweasel-17.0.8esr/mfbt/double-conversion/bignum.h:116: more undefined references to `abort' follow ../cached-powers.o: In function `double_conversion::PowersOfTenCache::GetCachedPowerForBinaryExponentRange(int, int, double_conversion::DiyFp*, int*)': /scratch/iceweasel-17/iceweasel-17.0.8esr/mfbt/double-conversion/cached-powers.cc:148: undefined reference to `ceil' ../double-conversion.o: In function `double_conversion::DoubleToStringConverter::EcmaScriptConverter()': /scratch/iceweasel-17/iceweasel-17.0.8esr/mfbt/double-conversion/double-conversion.cc:49: undefined reference to `__cxa_guard_acquire' /scratch/iceweasel-17/iceweasel-17.0.8esr/mfbt/double-conversion/double-conversion.cc:49: undefined reference to `__cxa_guard_release'
../double-conversion.o: In function `StrLength':
/scratch/iceweasel-17/iceweasel-17.0.8esr/mfbt/double-conversion/utils.h:132: undefined reference to `strlen'
../double-conversion.o: In function `StrLength':
/usr/include/ia64-linux-gnu/bits/string3.h:57: undefined reference to `memmove'
../double-conversion.o: In function `StrLength':
/scratch/iceweasel-17/iceweasel-17.0.8esr/mfbt/double-conversion/utils.h:132: undefined reference to `strlen'
../double-conversion.o: In function `StrLength':
/usr/include/ia64-linux-gnu/bits/string3.h:57: undefined reference to `memmove' ../double-conversion.o: In function `double_conversion::DoubleToStringConverter::CreateExponentialRepresentation(char const*, int, int, double_conversion::StringBuilder*) const': /usr/include/ia64-linux-gnu/bits/string3.h:57: undefined reference to `memmove'
/usr/include/ia64-linux-gnu/bits/string3.h:57: undefined reference to `memcpy'
../double-conversion.o: In function `double_conversion::DoubleToStringConverter::CreateDecimalRepresentation(char const*, int, int, int, double_conversion::StringBuilder*) const': /usr/include/ia64-linux-gnu/bits/string3.h:57: undefined reference to `memmove' ../double-conversion.o: In function `double_conversion::StringBuilder::AddSubstring(char const*, int)': /usr/include/ia64-linux-gnu/bits/string3.h:57: undefined reference to `memmove' ../double-conversion.o: In function `double_conversion::DoubleToStringConverter::CreateDecimalRepresentation(char const*, int, int, int, double_conversion::StringBuilder*) const': /usr/include/ia64-linux-gnu/bits/string3.h:57: undefined reference to `memmove' ../double-conversion.o: In function `double_conversion::StringBuilder::AddPadding(char, int)': /usr/include/ia64-linux-gnu/bits/string3.h:57: undefined reference to `memmove'
../double-conversion.o: In function `DtoaToBignumDtoaMode':
/scratch/iceweasel-17/iceweasel-17.0.8esr/mfbt/double-conversion/double-conversion.cc:350: undefined reference to `abort' ../fast-dtoa.o: In function `double_conversion::FastDtoa(double, double_conversion::FastDtoaMode, int, double_conversion::Vector<char>, int*, int*)': /scratch/iceweasel-17/iceweasel-17.0.8esr/mfbt/double-conversion/fast-dtoa.cc:655: undefined reference to `abort'
../strtod.o: In function `AdjustmentPowerOfTen':
/scratch/iceweasel-17/iceweasel-17.0.8esr/mfbt/double-conversion/strtod.cc:265: undefined reference to `abort' ../SHA1.o: In function `mozilla::SHA1Sum::update(unsigned char const*, unsigned int)':
/usr/include/ia64-linux-gnu/bits/string3.h:51: undefined reference to `memcpy'
/usr/include/ia64-linux-gnu/bits/string3.h:51: undefined reference to `memcpy'
../SHA1.o: In function `mozilla::SHA1Sum::finish(unsigned char*)':
/usr/include/ia64-linux-gnu/bits/string3.h:51: undefined reference to `memcpy'


I don't have a clue what it is at the moment.
The 'dynamic' argument is FALSE in the elf_slurp_reloc_table_from_section () (in bfd/elfcode.h) when it outputs the 'relocation 1 has invalid symbol index 13' error message. bfd_get_symcount (abfd) is 0. abfd->symcount is 0 and has been set by the file read operation (wasn't modified after that).
Do you have an idea?
Or any other comment?



Furthermore, I have the suspicion that objalloc_free_block() is completely wrong. - It compares pointers whether they are less or greater of different chunks. Different chunks were created by different malloc calls. Comparing them doesn't make any sense. - The newest chunks comes at first in the singly linked list which starts with o->chunks. Oldest chinks at last. It seems it wasn't taken into account. I removed the code of objalloc_free_block() tentatively while working on the fix.

Some indents have been intentionally left wrong in order to avoid obfuscation on the first review.
The patch is for binutils 2.23.

Regards
Stephan



diff -u8 -rp binutils-2.23.52.20130727-orig/bfd/bfd-in2.h binutils-2.23.52.20130727-new/bfd/bfd-in2.h --- binutils-2.23.52.20130727-orig/bfd/bfd-in2.h 2013-08-12 12:57:56.993250786 +0200 +++ binutils-2.23.52.20130727-new/bfd/bfd-in2.h 2013-08-29 09:37:48.028176582 +0200
@@ -632,17 +632,18 @@ struct bfd_link_needed_list
   const char *name;
 };

 enum dynamic_lib_link_class {
   DYN_NORMAL = 0,
   DYN_AS_NEEDED = 1,
   DYN_DT_NEEDED = 2,
   DYN_NO_ADD_NEEDED = 4,
-  DYN_NO_NEEDED = 8
+  DYN_NO_NEEDED = 8,
+  DYN_CHECK_IN_PROGRESS = 16
 };

 enum notice_asneeded_action {
   notice_as_needed,
   notice_not_needed,
   notice_needed
 };

diff -u8 -rp binutils-2.23.52.20130727-orig/bfd/bfd-in.h binutils-2.23.52.20130727-new/bfd/bfd-in.h --- binutils-2.23.52.20130727-orig/bfd/bfd-in.h 2013-08-12 12:57:57.477250929 +0200 +++ binutils-2.23.52.20130727-new/bfd/bfd-in.h 2013-08-29 09:37:30.140171275 +0200
@@ -625,17 +625,18 @@ struct bfd_link_needed_list
   const char *name;
 };

 enum dynamic_lib_link_class {
   DYN_NORMAL = 0,
   DYN_AS_NEEDED = 1,
   DYN_DT_NEEDED = 2,
   DYN_NO_ADD_NEEDED = 4,
-  DYN_NO_NEEDED = 8
+  DYN_NO_NEEDED = 8,
+  DYN_CHECK_IN_PROGRESS = 16
 };

 enum notice_asneeded_action {
   notice_as_needed,
   notice_not_needed,
   notice_needed
 };

diff -u8 -rp binutils-2.23.52.20130727-orig/bfd/elflink.c binutils-2.23.52.20130727-new/bfd/elflink.c --- binutils-2.23.52.20130727-orig/bfd/elflink.c 2013-08-12 12:57:54.877250158 +0200 +++ binutils-2.23.52.20130727-new/bfd/elflink.c 2013-08-29 09:37:14.788166719 +0200
@@ -393,19 +393,20 @@ _bfd_elf_create_dynamic_sections (bfd *a
 /* Record a new dynamic symbol.  We record the dynamic symbols as we
    read the input files, since we need to have a list of all of them
    before we can determine the final sizes of the output sections.
    Note that we may actually call this function even though we are not
    going to output any dynamic symbols; in some cases we know that a
    symbol should be in the dynamic symbol table, but only if there is
    one.  */

-bfd_boolean
-bfd_elf_link_record_dynamic_symbol (struct bfd_link_info *info,
-				    struct elf_link_hash_entry *h)
+static bfd_boolean
+bfd_elf_link_rec_dyn_symbol_check (struct bfd_link_info *info,
+				   struct elf_link_hash_entry *h,
+				   bfd_boolean check_in_progress)
 {
   if (h->dynindx == -1)
     {
       struct elf_strtab_hash *dynstr;
       char *p;
       const char *name;
       bfd_size_type indx;

@@ -424,16 +425,24 @@ bfd_elf_link_record_dynamic_symbol (stru
 	      if (!elf_hash_table (info)->is_relocatable_executable)
 		return TRUE;
 	    }

 	default:
 	  break;
 	}

+      if (check_in_progress)
+	{
+	  /* Dummy values */
+	  h->dynindx = 0;
+	  h->dynstr_index = 0;
+	}
+      else
+	{
       h->dynindx = elf_hash_table (info)->dynsymcount;
       ++elf_hash_table (info)->dynsymcount;

       dynstr = elf_hash_table (info)->dynstr;
       if (dynstr == NULL)
 	{
 	  /* Create a strtab to hold the dynamic symbol names.  */
 	  elf_hash_table (info)->dynstr = dynstr = _bfd_elf_strtab_init ();
@@ -456,20 +465,28 @@ bfd_elf_link_record_dynamic_symbol (stru
       indx = _bfd_elf_strtab_add (dynstr, name, p != NULL);

       if (p != NULL)
 	*p = ELF_VER_CHR;

       if (indx == (bfd_size_type) -1)
 	return FALSE;
       h->dynstr_index = indx;
+	}
     }

   return TRUE;
 }
+
+bfd_boolean
+bfd_elf_link_record_dynamic_symbol (struct bfd_link_info *info,
+				    struct elf_link_hash_entry *h)
+{
+  return bfd_elf_link_rec_dyn_symbol_check (info, h, FALSE);
+}
 
 /* Mark a symbol dynamic.  */

 static void
 bfd_elf_link_mark_dynamic_symbol (struct bfd_link_info *info,
 				  struct elf_link_hash_entry *h,
 				  Elf_Internal_Sym *sym)
 {
@@ -498,16 +515,18 @@ bfd_elf_record_link_assignment (bfd *out
 				const char *name,
 				bfd_boolean provide,
 				bfd_boolean hidden)
 {
   struct elf_link_hash_entry *h, *hv;
   struct elf_link_hash_table *htab;
   const struct elf_backend_data *bed;

+  BFD_ASSERT ((elf_dyn_lib_class (output_bfd) & DYN_CHECK_IN_PROGRESS) == 0);
+
   if (!is_elf_hash_table (info->hash))
     return TRUE;

   htab = elf_hash_table (info);
   h = elf_link_hash_lookup (htab, name, !provide, TRUE, FALSE);
   if (h == NULL)
     return provide;

@@ -1174,17 +1193,18 @@ _bfd_elf_merge_symbol (bfd *abfd,
       /* Make sure this symbol is dynamic.  */
       h->ref_dynamic = 1;
       hi->ref_dynamic = 1;
       /* A protected symbol has external availability. Make sure it is
 	 recorded as dynamic.

 	 FIXME: Should we check type and size for protected symbol?  */
       if (ELF_ST_VISIBILITY (h->other) == STV_PROTECTED)
-	return bfd_elf_link_record_dynamic_symbol (info, h);
+	return bfd_elf_link_rec_dyn_symbol_check (info, h,
+		((elf_dyn_lib_class (abfd) & DYN_CHECK_IN_PROGRESS) != 0));
       else
 	return TRUE;
     }
   else if (!newdyn
 	   && ELF_ST_VISIBILITY (sym->st_other) != STV_DEFAULT
 	   && h->def_dynamic)
     {
       /* If the new symbol with non-default visibility comes from a
@@ -1195,23 +1215,26 @@ _bfd_elf_merge_symbol (bfd *abfd,
 	  /* Handle the case where the old dynamic definition is
 	     default versioned.  We need to copy the symbol info from
 	     the symbol with default version to the normal one if it
 	     was referenced before.  */
 	  if (h->ref_regular)
 	    {
 	      hi->root.type = h->root.type;
 	      h->root.type = bfd_link_hash_indirect;
+
+	    if ((elf_dyn_lib_class (abfd) & DYN_CHECK_IN_PROGRESS) == 0)
 	      (*bed->elf_backend_copy_indirect_symbol) (info, hi, h);

 	      h->root.u.i.link = (struct bfd_link_hash_entry *) hi;
 	      if (ELF_ST_VISIBILITY (sym->st_other) != STV_PROTECTED)
 		{
 		  /* If the new symbol is hidden or internal, completely undo
 		     any dynamic link state.  */
+		if ((elf_dyn_lib_class (abfd) & DYN_CHECK_IN_PROGRESS) == 0)
 		  (*bed->elf_backend_hide_symbol) (info, h, TRUE);
 		  h->forced_local = 0;
 		  h->ref_dynamic = 0;
 		}
 	      else
 		h->ref_dynamic = 1;

 	      h->def_dynamic = 0;
@@ -1242,16 +1265,17 @@ _bfd_elf_merge_symbol (bfd *abfd,
 	  h->root.type = bfd_link_hash_new;
 	  h->root.u.undef.abfd = NULL;
 	}

       if (ELF_ST_VISIBILITY (sym->st_other) != STV_PROTECTED)
 	{
 	  /* If the new symbol is hidden or internal, completely undo
 	     any dynamic link state.  */
+	if ((elf_dyn_lib_class (abfd) & DYN_CHECK_IN_PROGRESS) == 0)
 	  (*bed->elf_backend_hide_symbol) (info, h, TRUE);
 	  h->forced_local = 0;
 	  h->ref_dynamic = 0;
 	}
       else
 	h->ref_dynamic = 1;
       h->def_dynamic = 0;
       /* FIXME: Should we check type and size for protected symbol?  */
@@ -1342,16 +1366,17 @@ _bfd_elf_merge_symbol (bfd *abfd,
     olddyncommon = TRUE;
   else
     olddyncommon = FALSE;

   /* We now know everything about the old and new symbols.  We ask the
      backend to check if we can merge them.  */
   if (bed->merge_symbol != NULL)
     {
+    if ((elf_dyn_lib_class (abfd) & DYN_CHECK_IN_PROGRESS) == 0)
       if (!bed->merge_symbol (h, sym, psec, newdef, olddef, oldbfd, oldsec))
 	return FALSE;
       sec = *psec;
     }

   /* If both the old and the new symbols look like common symbols in a
      dynamic object, set the size of the symbol to the larger of the
      two.  */
@@ -1443,16 +1468,17 @@ _bfd_elf_merge_symbol (bfd *abfd,
 	 but visibility says it should not be visible, turn it into a
 	 local symbol.  */
       elf_merge_st_other (abfd, h, sym, newdef, newdyn);
       if (h->dynindx != -1)
 	switch (ELF_ST_VISIBILITY (h->other))
 	  {
 	  case STV_INTERNAL:
 	  case STV_HIDDEN:
+	  if ((elf_dyn_lib_class (abfd) & DYN_CHECK_IN_PROGRESS) == 0)
 	    (*bed->elf_backend_hide_symbol) (info, h, TRUE);
 	    break;
 	  }
     }

   /* If the old symbol is from a dynamic object, and the new symbol is
      a definition which is not from a dynamic object, then the new
      symbol overrides the old symbol.  Symbols from regular files
@@ -1555,16 +1581,17 @@ _bfd_elf_merge_symbol (bfd *abfd,
     {
       /* Handle the case where we had a versioned symbol in a dynamic
 	 library and now find a definition in a normal object.  In this
 	 case, we make the versioned symbol point to the normal one.  */
       flip->root.type = h->root.type;
       flip->root.u.undef.abfd = h->root.u.undef.abfd;
       h->root.type = bfd_link_hash_indirect;
       h->root.u.i.link = (struct bfd_link_hash_entry *) flip;
+    if ((elf_dyn_lib_class (abfd) & DYN_CHECK_IN_PROGRESS) == 0)
       (*bed->elf_backend_copy_indirect_symbol) (info, flip, h);
       if (h->def_dynamic)
 	{
 	  h->def_dynamic = 0;
 	  flip->ref_dynamic = 1;
 	}
     }

@@ -1672,17 +1699,18 @@ _bfd_elf_add_default_symbol (bfd *abfd,
       h->root.u.i.link = (struct bfd_link_hash_entry *) hi;
       if (h->def_dynamic)
 	{
 	  h->def_dynamic = 0;
 	  hi->ref_dynamic = 1;
 	  if (hi->ref_regular
 	      || hi->def_regular)
 	    {
-	      if (! bfd_elf_link_record_dynamic_symbol (info, hi))
+	      if (! bfd_elf_link_rec_dyn_symbol_check (info, hi,
+		      ((elf_dyn_lib_class (abfd) & DYN_CHECK_IN_PROGRESS) != 0)))
 		return FALSE;
 	    }
 	}

       /* Now set HI to H, so that the following code will set the
 	 other fields correctly.  */
       hi = h;
     }
@@ -1695,16 +1723,17 @@ _bfd_elf_add_default_symbol (bfd *abfd,
      point to an indirect symbol.  We will have reported an error to
      the user in that case.  */

   if (hi->root.type == bfd_link_hash_indirect)
     {
       struct elf_link_hash_entry *ht;

       ht = (struct elf_link_hash_entry *) hi->root.u.i.link;
+    if ((elf_dyn_lib_class (abfd) & DYN_CHECK_IN_PROGRESS) == 0)
       (*bed->elf_backend_copy_indirect_symbol) (info, ht, hi);

       /* See if the new flags lead us to realize that the symbol must
 	 be dynamic.  */
       if (! *dynsym)
 	{
 	  if (! dynamic)
 	    {
@@ -1765,16 +1794,17 @@ nondefault:
       hi = (struct elf_link_hash_entry *) bh;

       /* If there is a duplicate definition somewhere, then HI may not
 	 point to an indirect symbol.  We will have reported an error
 	 to the user in that case.  */

       if (hi->root.type == bfd_link_hash_indirect)
 	{
+	if ((elf_dyn_lib_class (abfd) & DYN_CHECK_IN_PROGRESS) == 0)
 	  (*bed->elf_backend_copy_indirect_symbol) (info, h, hi);

 	  /* See if the new flags lead us to realize that the symbol
 	     must be dynamic.  */
 	  if (! *dynsym)
 	    {
 	      if (! dynamic)
 		{
@@ -3316,16 +3346,17 @@ elf_link_add_object_symbols (bfd *abfd,
 {
   Elf_Internal_Ehdr *ehdr;
   Elf_Internal_Shdr *hdr;
   bfd_size_type symcount;
   bfd_size_type extsymcount;
   bfd_size_type extsymoff;
   struct elf_link_hash_entry **sym_hash;
   bfd_boolean dynamic;
+  bfd_boolean dyn_is_needed;
   Elf_External_Versym *extversym = NULL;
   Elf_External_Versym *ever;
   struct elf_link_hash_entry *weaks;
   struct elf_link_hash_entry **nondeflt_vers = NULL;
   bfd_size_type nondeflt_vers_cnt = 0;
   Elf_Internal_Sym *isymbuf = NULL;
   Elf_Internal_Sym *isym;
   Elf_Internal_Sym *isymend;
@@ -3336,18 +3367,16 @@ elf_link_add_object_symbols (bfd *abfd,
   void *alloc_mark = NULL;
   struct bfd_hash_entry **old_table = NULL;
   unsigned int old_size = 0;
   unsigned int old_count = 0;
   void *old_tab = NULL;
   void *old_ent;
   struct bfd_link_hash_entry *old_undefs = NULL;
   struct bfd_link_hash_entry *old_undefs_tail = NULL;
-  long old_dynsymcount = 0;
-  bfd_size_type old_dynstr_size = 0;
   size_t tabsize = 0;
   asection *s;

   htab = elf_hash_table (info);
   bed = get_elf_backend_data (abfd);

   if ((abfd->flags & DYNAMIC) == 0)
     dynamic = FALSE;
@@ -3726,20 +3755,28 @@ error_free_dyn:
 	    goto error_free_sym;
 	  amt = versymhdr->sh_size;
 	  if (bfd_seek (abfd, versymhdr->sh_offset, SEEK_SET) != 0
 	      || bfd_bread (extversym, amt, abfd) != amt)
 	    goto error_free_vers;
 	}
     }

+  if ((elf_dyn_lib_class (abfd) & DYN_AS_NEEDED) != 0)
+    elf_dyn_lib_class (abfd) = (enum dynamic_lib_link_class)
+                  (elf_dyn_lib_class (abfd) | DYN_CHECK_IN_PROGRESS);
+
+  do
+    {
+      dyn_is_needed = FALSE;
+
   /* If we are loading an as-needed shared lib, save the symbol table
      state before we start adding symbols.  If the lib turns out
      to be unneeded, restore the state.  */
-  if ((elf_dyn_lib_class (abfd) & DYN_AS_NEEDED) != 0)
+  if ((elf_dyn_lib_class (abfd) & DYN_CHECK_IN_PROGRESS) != 0)
     {
       unsigned int i;
       size_t entsize;

       for (entsize = 0, i = 0; i < htab->root.table.size; i++)
 	{
 	  struct bfd_hash_entry *p;
 	  struct elf_link_hash_entry *h;
@@ -3774,18 +3811,16 @@ error_free_dyn:
 	 symbol table, and dynamic symbol count.  */
       old_ent = (char *) old_tab + tabsize;
       memcpy (old_tab, htab->root.table.table, tabsize);
       old_undefs = htab->root.undefs;
       old_undefs_tail = htab->root.undefs_tail;
       old_table = htab->root.table.table;
       old_size = htab->root.table.size;
       old_count = htab->root.table.count;
-      old_dynsymcount = htab->dynsymcount;
-      old_dynstr_size = _bfd_elf_strtab_size (htab->dynstr);

       for (i = 0; i < htab->root.table.size; i++)
 	{
 	  struct bfd_hash_entry *p;
 	  struct elf_link_hash_entry *h;

 	  for (p = htab->root.table.table[i]; p != NULL; p = p->next)
 	    {
@@ -4374,23 +4409,25 @@ error_free_dyn:
 			goto error_free_vers;
 		    }
 		  nondeflt_vers[nondeflt_vers_cnt++] = h;
 		}
 	    }

 	  if (dynsym && h->dynindx == -1)
 	    {
-	      if (! bfd_elf_link_record_dynamic_symbol (info, h))
+	      if (! bfd_elf_link_rec_dyn_symbol_check (info, h,
+		      ((elf_dyn_lib_class (abfd) & DYN_CHECK_IN_PROGRESS) != 0)))
 		goto error_free_vers;
 	      if (h->u.weakdef != NULL
 		  && ! new_weakdef
 		  && h->u.weakdef->dynindx == -1)
 		{
-		  if (!bfd_elf_link_record_dynamic_symbol (info, h->u.weakdef))
+		  if (!bfd_elf_link_rec_dyn_symbol_check (info, h->u.weakdef,
+			  ((elf_dyn_lib_class (abfd) & DYN_CHECK_IN_PROGRESS) != 0)))
 		    goto error_free_vers;
 		}
 	    }
 	  else if (dynsym && h->dynindx != -1)
 	    /* If the symbol already has a dynamic index, but
 	       visibility says it should not be visible, turn it into
 	       a local symbol.  */
 	    switch (ELF_ST_VISIBILITY (h->other))
@@ -4426,73 +4463,70 @@ error_free_dyn:
 		{
 		  (*_bfd_error_handler)
 		    (_("%B: undefined reference to symbol '%s'"),
 		     old_bfd, name);
 		  bfd_set_error (bfd_error_missing_dso);
 		  goto error_free_vers;
 		}

+	      if ((elf_dyn_lib_class (abfd) & DYN_CHECK_IN_PROGRESS) != 0)
+		{
+		  dyn_is_needed = TRUE;
+		  goto out_is_needed;
+		}
+
 	      elf_dyn_lib_class (abfd) = (enum dynamic_lib_link_class)
                   (elf_dyn_lib_class (abfd) & ~DYN_AS_NEEDED);

 	      add_needed = TRUE;
 	      ret = elf_add_dt_needed_tag (abfd, info, soname, add_needed);
 	      if (ret < 0)
 		goto error_free_vers;

 	      BFD_ASSERT (ret == 0);
 	    }
 	}
     }

-  if (extversym != NULL)
-    {
-      free (extversym);
-      extversym = NULL;
-    }
-
-  if (isymbuf != NULL)
-    {
-      free (isymbuf);
-      isymbuf = NULL;
-    }
+out_is_needed:

-  if ((elf_dyn_lib_class (abfd) & DYN_AS_NEEDED) != 0)
+  if (old_tab != NULL)
     {
       unsigned int i;

+      BFD_ASSERT ((elf_dyn_lib_class (abfd) & DYN_CHECK_IN_PROGRESS) != 0);
+
+      elf_dyn_lib_class (abfd) = (enum dynamic_lib_link_class)
+          (elf_dyn_lib_class (abfd) & ~DYN_CHECK_IN_PROGRESS);
+
       /* Restore the symbol table.  */
       if (bed->as_needed_cleanup)
 	(*bed->as_needed_cleanup) (abfd, info);
       old_ent = (char *) old_tab + tabsize;
       memset (elf_sym_hashes (abfd), 0,
 	      extsymcount * sizeof (struct elf_link_hash_entry *));
       htab->root.table.table = old_table;
       htab->root.table.size = old_size;
       htab->root.table.count = old_count;
       memcpy (htab->root.table.table, old_tab, tabsize);
       htab->root.undefs = old_undefs;
       htab->root.undefs_tail = old_undefs_tail;
-      _bfd_elf_strtab_restore_size (htab->dynstr, old_dynstr_size);
       for (i = 0; i < htab->root.table.size; i++)
 	{
 	  struct bfd_hash_entry *p;
 	  struct elf_link_hash_entry *h;
 	  bfd_size_type size;
 	  unsigned int alignment_power;

 	  for (p = htab->root.table.table[i]; p != NULL; p = p->next)
 	    {
 	      h = (struct elf_link_hash_entry *) p;
 	      if (h->root.type == bfd_link_hash_warning)
 		h = (struct elf_link_hash_entry *) h->root.u.i.link;
-	      if (h->dynindx >= old_dynsymcount
-		  && h->dynstr_index < old_dynstr_size)
-		_bfd_elf_strtab_delref (htab->dynstr, h->dynstr_index);

 	      /* Preserve the maximum alignment and size for common
 		 symbols even if this dynamic lib isn't on DT_NEEDED
 		 since it can still be loaded at run time by another
 		 dynamic lib.  */
 	      if (h->root.type == bfd_link_hash_common)
 		{
 		  size = h->root.u.c.size;
@@ -4503,51 +4537,69 @@ error_free_dyn:
 		  size = 0;
 		  alignment_power = 0;
 		}
 	      memcpy (p, old_ent, htab->root.table.entsize);
 	      old_ent = (char *) old_ent + htab->root.table.entsize;
 	      h = (struct elf_link_hash_entry *) p;
 	      if (h->root.type == bfd_link_hash_warning)
 		{
+		  struct bfd_hash_entry t;
+		  /* preserve 'next' of the restored hash entry */
+		  t = h->root.u.i.link->root;
 		  memcpy (h->root.u.i.link, old_ent, htab->root.table.entsize);
+		  h->root.u.i.link->root = t;
 		  old_ent = (char *) old_ent + htab->root.table.entsize;
 		  h = (struct elf_link_hash_entry *) h->root.u.i.link;
 		}
 	      if (h->root.type == bfd_link_hash_common)
 		{
 		  if (size > h->root.u.c.size)
 		    h->root.u.c.size = size;
 		  if (alignment_power > h->root.u.c.p->alignment_power)
 		    h->root.u.c.p->alignment_power = alignment_power;
 		}
 	    }
 	}

+      free (old_tab);
+      old_tab = NULL;
+      objalloc_free_block ((struct objalloc *) htab->root.table.memory,
+			   alloc_mark);
+
+      if (!dyn_is_needed)
+        {
       /* Make a special call to the linker "notice" function to
 	 tell it that symbols added for crefs may need to be removed.  */
       if (!(*info->callbacks->notice) (info, NULL, abfd, NULL,
 				       notice_not_needed, 0, NULL))
 	goto error_free_vers;

-      free (old_tab);
-      objalloc_free_block ((struct objalloc *) htab->root.table.memory,
-			   alloc_mark);
       if (nondeflt_vers != NULL)
 	free (nondeflt_vers);
       return TRUE;
-    }
+        }

-  if (old_tab != NULL)
-    {
       if (!(*info->callbacks->notice) (info, NULL, abfd, NULL,
 				       notice_needed, 0, NULL))
 	goto error_free_vers;
-      free (old_tab);
-      old_tab = NULL;
+    }
+    }
+  while (dyn_is_needed);
+
+  if (extversym != NULL)
+    {
+      free (extversym);
+      extversym = NULL;
+    }
+
+  if (isymbuf != NULL)
+    {
+      free (isymbuf);
+      isymbuf = NULL;
     }

   /* Now that all the symbols from this input file are created, handle
.symver foo, foo@BAR such that any relocs against foo become foo@BAR. */
   if (nondeflt_vers != NULL)
     {
       bfd_size_type cnt, symidx;

diff -u8 -rp binutils-2.23.52.20130727-orig/libiberty/objalloc.c binutils-2.23.52.20130727-new/libiberty/objalloc.c --- binutils-2.23.52.20130727-orig/libiberty/objalloc.c 2013-08-12 12:57:50.841248959 +0200 +++ binutils-2.23.52.20130727-new/libiberty/objalloc.c 2013-08-29 09:38:14.148184333 +0200
@@ -192,107 +192,9 @@ objalloc_free (struct objalloc *o)
 }

 /* Free a block from an objalloc structure.  This also frees all more
    recently allocated blocks.  */

 void
 objalloc_free_block (struct objalloc *o, PTR block)
 {
-  struct objalloc_chunk *p, *small;
-  char *b = (char *) block;
-
-  /* First set P to the chunk which contains the block we are freeing,
-     and set Q to the last small object chunk we see before P.  */
-  small = NULL;
-  for (p = (struct objalloc_chunk *) o->chunks; p != NULL; p = p->next)
-    {
-      if (p->current_ptr == NULL)
-	{
-	  if (b > (char *) p && b < (char *) p + CHUNK_SIZE)
-	    break;
-	  small = p;
-	}
-      else
-	{
-	  if (b == (char *) p + CHUNK_HEADER_SIZE)
-	    break;
-	}
-    }
-
-  /* If we can't find the chunk, the caller has made a mistake.  */
-  if (p == NULL)
-    abort ();
-
-  if (p->current_ptr == NULL)
-    {
-      struct objalloc_chunk *q;
-      struct objalloc_chunk *first;
-
-      /* The block is in a chunk containing small objects.  We can
-	 free every chunk through SMALL, because they have certainly
-	 been allocated more recently.  After SMALL, we will not see
-	 any chunks containing small objects; we can free any big
-	 chunk if the current_ptr is greater than or equal to B.  We
-	 can then reset the new current_ptr to B.  */
-
-      first = NULL;
-      q = (struct objalloc_chunk *) o->chunks;
-      while (q != p)
-	{
-	  struct objalloc_chunk *next;
-
-	  next = q->next;
-	  if (small != NULL)
-	    {
-	      if (small == q)
-		small = NULL;
-	      free (q);
-	    }
-	  else if (q->current_ptr > b)
-	    free (q);
-	  else if (first == NULL)
-	    first = q;
-
-	  q = next;
-	}
-
-      if (first == NULL)
-	first = p;
-      o->chunks = (PTR) first;
-
-      /* Now start allocating from this small block again.  */
-      o->current_ptr = b;
-      o->current_space = ((char *) p + CHUNK_SIZE) - b;
-    }
-  else
-    {
-      struct objalloc_chunk *q;
-      char *current_ptr;
-
-      /* This block is in a large chunk by itself.  We can free
-         everything on the list up to and including this block.  We
-         then start allocating from the next chunk containing small
-         objects, setting current_ptr from the value stored with the
-         large chunk we are freeing.  */
-
-      current_ptr = p->current_ptr;
-      p = p->next;
-
-      q = (struct objalloc_chunk *) o->chunks;
-      while (q != p)
-	{
-	  struct objalloc_chunk *next;
-
-	  next = q->next;
-	  free (q);
-	  q = next;
-	}
-
-      o->chunks = (PTR) p;
-
-      while (p->current_ptr != NULL)
-	p = p->next;
-
-      o->current_ptr = current_ptr;
-      o->current_space = ((char *) p + CHUNK_SIZE) - current_ptr;
-    }
 }





Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]