public inbox for binutils@sourceware.org
 help / color / mirror / Atom feed
* [PATCH v2] PR ld/20828: Move symbol version processing ahead of GC symbol sweep
@ 2017-02-21  1:47 Maciej W. Rozycki
  2017-02-21 22:52 ` Alan Modra
  0 siblings, 1 reply; 9+ messages in thread
From: Maciej W. Rozycki @ 2017-02-21  1:47 UTC (permalink / raw)
  To: Alan Modra, Nick Clifton, James Cowgill; +Cc: binutils

Complement commit b531344c34b0 ("PR ld/20828: Reorder the symbol sweep 
stage of section GC") and commit 81ff47b3a546 ("PR ld/20828: Fix linker 
script symbols wrongly forced local with section GC") and move symbol 
version processing ahead of the symbol sweep stage of section GC, all in 
`bfd_elf_size_dynamic_sections', so that version symbols created stay in 
the global scope and are not output as local symbols to the dynamic 
symbol table in the presence of corresponding symbol definitions pulled 
from a DSO involved in a link.

Consolidate the whole of symbol version processing into a single block 
from all parts scattered across the function and rearranging the local 
variables used as necessary, however leaving the setting of dynamic 
entries associated with the DT_VERDEF, DT_VERDEFNUM, DT_VERNEED and 
DT_VERNEEDNUM tags and the SEC_EXCLUDE flag for unused `.gnu.version' 
section in the original places.

With the rearrangement of code blocks `Elf_Internal_Verneed *t' would 
shadow the previous definition of `struct bfd_elf_version_tree *t', so 
rename the former variable to `vn'.

	bfd/
	PR ld/20828
	* elflink.c (bfd_elf_size_dynamic_sections): Move symbol version 
	processing ahead of the call to `elf_gc_sweep_symbol'.

	ld/
	PR ld/20828
	* testsuite/ld-elf/pr20828-d.sd: New test.
	* testsuite/ld-elf/pr20828-e.sd: New test.
	* testsuite/ld-elf/pr20828-v.od: New test.
	* testsuite/ld-elf/pr20828-v.ver: New test version script.
	* testsuite/ld-elf/pr20828-v.ld: New test linker script.
	* testsuite/ld-elf/pr20828.ld: Add `.gnu.version' and 
	`.gnu.version_d'.
	* testsuite/ld-elf/shared.exp: Run the new tests.
---
Changes from v1:

- `--export-dynamic' handling moved ahead of symbol version processing,

- SEC_EXCLUDE setting for unused `.gnu.version' section moved back to the
  original place at the end,

- `pr20828-v-1' and `pr20828-v-2' tests added, reduced from `vers4a'.

 No regressions across my usual 175 targets nor in native `x86_64-linux'
testing.  OK to apply to master?

  Maciej

Index: binutils/bfd/elflink.c
===================================================================
--- binutils.orig/bfd/elflink.c	2017-02-18 02:23:54.900056052 +0000
+++ binutils/bfd/elflink.c	2017-02-21 00:50:35.255924046 +0000
@@ -5925,7 +5925,6 @@ bfd_elf_size_dynamic_sections (bfd *outp
   size_t soname_indx;
   bfd *dynobj;
   const struct elf_backend_data *bed;
-  struct elf_info_failed asvinfo;
 
   *sinterpptr = NULL;
 
@@ -5934,173 +5933,17 @@ bfd_elf_size_dynamic_sections (bfd *outp
   if (!is_elf_hash_table (info->hash))
     return TRUE;
 
-  bed = get_elf_backend_data (output_bfd);
-
-  if (info->gc_sections && bed->can_gc_sections)
-    {
-      struct elf_gc_sweep_symbol_info sweep_info;
-      unsigned long section_sym_count;
-
-      /* Remove the symbols that were in the swept sections from the
-	 dynamic symbol table.  GCFIXME: Anyone know how to get them
-	 out of the static symbol table as well?  */
-      sweep_info.info = info;
-      sweep_info.hide_symbol = bed->elf_backend_hide_symbol;
-      elf_link_hash_traverse (elf_hash_table (info), elf_gc_sweep_symbol,
-			      &sweep_info);
-
-      _bfd_elf_link_renumber_dynsyms (output_bfd, info, &section_sym_count);
-    }
-
-  /* Any syms created from now on start with -1 in
-     got.refcount/offset and plt.refcount/offset.  */
-  elf_hash_table (info)->init_got_refcount
-    = elf_hash_table (info)->init_got_offset;
-  elf_hash_table (info)->init_plt_refcount
-    = elf_hash_table (info)->init_plt_offset;
-
-  if (bfd_link_relocatable (info)
-      && !_bfd_elf_size_group_sections (info))
-    return FALSE;
-
-  /* The backend may have to create some sections regardless of whether
-     we're dynamic or not.  */
-  if (bed->elf_backend_always_size_sections
-      && ! (*bed->elf_backend_always_size_sections) (output_bfd, info))
-    return FALSE;
-
-  /* Determine any GNU_STACK segment requirements, after the backend
-     has had a chance to set a default segment size.  */
-  if (info->execstack)
-    elf_stack_flags (output_bfd) = PF_R | PF_W | PF_X;
-  else if (info->noexecstack)
-    elf_stack_flags (output_bfd) = PF_R | PF_W;
-  else
-    {
-      bfd *inputobj;
-      asection *notesec = NULL;
-      int exec = 0;
-
-      for (inputobj = info->input_bfds;
-	   inputobj;
-	   inputobj = inputobj->link.next)
-	{
-	  asection *s;
-
-	  if (inputobj->flags
-	      & (DYNAMIC | EXEC_P | BFD_PLUGIN | BFD_LINKER_CREATED))
-	    continue;
-	  s = bfd_get_section_by_name (inputobj, ".note.GNU-stack");
-	  if (s)
-	    {
-	      if (s->flags & SEC_CODE)
-		exec = PF_X;
-	      notesec = s;
-	    }
-	  else if (bed->default_execstack)
-	    exec = PF_X;
-	}
-      if (notesec || info->stacksize > 0)
-	elf_stack_flags (output_bfd) = PF_R | PF_W | exec;
-      if (notesec && exec && bfd_link_relocatable (info)
-	  && notesec->output_section != bfd_abs_section_ptr)
-	notesec->output_section->flags |= SEC_CODE;
-    }
-
   dynobj = elf_hash_table (info)->dynobj;
 
   if (dynobj != NULL && elf_hash_table (info)->dynamic_sections_created)
     {
-      struct elf_info_failed eif;
-      struct elf_link_hash_entry *h;
-      asection *dynstr;
+      struct bfd_elf_version_tree *verdefs;
+      struct elf_info_failed asvinfo;
       struct bfd_elf_version_tree *t;
       struct bfd_elf_version_expr *d;
-      asection *s;
+      struct elf_info_failed eif;
       bfd_boolean all_defined;
-
-      *sinterpptr = bfd_get_linker_section (dynobj, ".interp");
-      BFD_ASSERT (*sinterpptr != NULL || !bfd_link_executable (info) || info->nointerp);
-
-      if (soname != NULL)
-	{
-	  soname_indx = _bfd_elf_strtab_add (elf_hash_table (info)->dynstr,
-					     soname, TRUE);
-	  if (soname_indx == (size_t) -1
-	      || !_bfd_elf_add_dynamic_entry (info, DT_SONAME, soname_indx))
-	    return FALSE;
-	}
-
-      if (info->symbolic)
-	{
-	  if (!_bfd_elf_add_dynamic_entry (info, DT_SYMBOLIC, 0))
-	    return FALSE;
-	  info->flags |= DF_SYMBOLIC;
-	}
-
-      if (rpath != NULL)
-	{
-	  size_t indx;
-	  bfd_vma tag;
-
-	  indx = _bfd_elf_strtab_add (elf_hash_table (info)->dynstr, rpath,
-				      TRUE);
-	  if (indx == (size_t) -1)
-	    return FALSE;
-
-	  tag = info->new_dtags ? DT_RUNPATH : DT_RPATH;
-	  if (!_bfd_elf_add_dynamic_entry (info, tag, indx))
-	    return FALSE;
-	}
-
-      if (filter_shlib != NULL)
-	{
-	  size_t indx;
-
-	  indx = _bfd_elf_strtab_add (elf_hash_table (info)->dynstr,
-				      filter_shlib, TRUE);
-	  if (indx == (size_t) -1
-	      || !_bfd_elf_add_dynamic_entry (info, DT_FILTER, indx))
-	    return FALSE;
-	}
-
-      if (auxiliary_filters != NULL)
-	{
-	  const char * const *p;
-
-	  for (p = auxiliary_filters; *p != NULL; p++)
-	    {
-	      size_t indx;
-
-	      indx = _bfd_elf_strtab_add (elf_hash_table (info)->dynstr,
-					  *p, TRUE);
-	      if (indx == (size_t) -1
-		  || !_bfd_elf_add_dynamic_entry (info, DT_AUXILIARY, indx))
-		return FALSE;
-	    }
-	}
-
-      if (audit != NULL)
-	{
-	  size_t indx;
-
-	  indx = _bfd_elf_strtab_add (elf_hash_table (info)->dynstr, audit,
-				      TRUE);
-	  if (indx == (size_t) -1
-	      || !_bfd_elf_add_dynamic_entry (info, DT_AUDIT, indx))
-	    return FALSE;
-	}
-
-      if (depaudit != NULL)
-	{
-	  size_t indx;
-
-	  indx = _bfd_elf_strtab_add (elf_hash_table (info)->dynstr, depaudit,
-				      TRUE);
-	  if (indx == (size_t) -1
-	      || !_bfd_elf_add_dynamic_entry (info, DT_DEPAUDIT, indx))
-	    return FALSE;
-	}
+      asection *s;
 
       eif.info = info;
       eif.failed = FALSE;
@@ -6200,129 +6043,6 @@ bfd_elf_size_dynamic_sections (bfd *outp
 	    }
 	}
 
-      /* Find all symbols which were defined in a dynamic object and make
-	 the backend pick a reasonable value for them.  */
-      elf_link_hash_traverse (elf_hash_table (info),
-			      _bfd_elf_adjust_dynamic_symbol,
-			      &eif);
-      if (eif.failed)
-	return FALSE;
-
-      /* Add some entries to the .dynamic section.  We fill in some of the
-	 values later, in bfd_elf_final_link, but we must add the entries
-	 now so that we know the final size of the .dynamic section.  */
-
-      /* If there are initialization and/or finalization functions to
-	 call then add the corresponding DT_INIT/DT_FINI entries.  */
-      h = (info->init_function
-	   ? elf_link_hash_lookup (elf_hash_table (info),
-				   info->init_function, FALSE,
-				   FALSE, FALSE)
-	   : NULL);
-      if (h != NULL
-	  && (h->ref_regular
-	      || h->def_regular))
-	{
-	  if (!_bfd_elf_add_dynamic_entry (info, DT_INIT, 0))
-	    return FALSE;
-	}
-      h = (info->fini_function
-	   ? elf_link_hash_lookup (elf_hash_table (info),
-				   info->fini_function, FALSE,
-				   FALSE, FALSE)
-	   : NULL);
-      if (h != NULL
-	  && (h->ref_regular
-	      || h->def_regular))
-	{
-	  if (!_bfd_elf_add_dynamic_entry (info, DT_FINI, 0))
-	    return FALSE;
-	}
-
-      s = bfd_get_section_by_name (output_bfd, ".preinit_array");
-      if (s != NULL && s->linker_has_input)
-	{
-	  /* DT_PREINIT_ARRAY is not allowed in shared library.  */
-	  if (! bfd_link_executable (info))
-	    {
-	      bfd *sub;
-	      asection *o;
-
-	      for (sub = info->input_bfds; sub != NULL;
-		   sub = sub->link.next)
-		if (bfd_get_flavour (sub) == bfd_target_elf_flavour)
-		  for (o = sub->sections; o != NULL; o = o->next)
-		    if (elf_section_data (o)->this_hdr.sh_type
-			== SHT_PREINIT_ARRAY)
-		      {
-			_bfd_error_handler
-			  (_("%B: .preinit_array section is not allowed in DSO"),
-			   sub);
-			break;
-		      }
-
-	      bfd_set_error (bfd_error_nonrepresentable_section);
-	      return FALSE;
-	    }
-
-	  if (!_bfd_elf_add_dynamic_entry (info, DT_PREINIT_ARRAY, 0)
-	      || !_bfd_elf_add_dynamic_entry (info, DT_PREINIT_ARRAYSZ, 0))
-	    return FALSE;
-	}
-      s = bfd_get_section_by_name (output_bfd, ".init_array");
-      if (s != NULL && s->linker_has_input)
-	{
-	  if (!_bfd_elf_add_dynamic_entry (info, DT_INIT_ARRAY, 0)
-	      || !_bfd_elf_add_dynamic_entry (info, DT_INIT_ARRAYSZ, 0))
-	    return FALSE;
-	}
-      s = bfd_get_section_by_name (output_bfd, ".fini_array");
-      if (s != NULL && s->linker_has_input)
-	{
-	  if (!_bfd_elf_add_dynamic_entry (info, DT_FINI_ARRAY, 0)
-	      || !_bfd_elf_add_dynamic_entry (info, DT_FINI_ARRAYSZ, 0))
-	    return FALSE;
-	}
-
-      dynstr = bfd_get_linker_section (dynobj, ".dynstr");
-      /* If .dynstr is excluded from the link, we don't want any of
-	 these tags.  Strictly, we should be checking each section
-	 individually;  This quick check covers for the case where
-	 someone does a /DISCARD/ : { *(*) }.  */
-      if (dynstr != NULL && dynstr->output_section != bfd_abs_section_ptr)
-	{
-	  bfd_size_type strsize;
-
-	  strsize = _bfd_elf_strtab_size (elf_hash_table (info)->dynstr);
-	  if ((info->emit_hash
-	       && !_bfd_elf_add_dynamic_entry (info, DT_HASH, 0))
-	      || (info->emit_gnu_hash
-		  && !_bfd_elf_add_dynamic_entry (info, DT_GNU_HASH, 0))
-	      || !_bfd_elf_add_dynamic_entry (info, DT_STRTAB, 0)
-	      || !_bfd_elf_add_dynamic_entry (info, DT_SYMTAB, 0)
-	      || !_bfd_elf_add_dynamic_entry (info, DT_STRSZ, strsize)
-	      || !_bfd_elf_add_dynamic_entry (info, DT_SYMENT,
-					      bed->s->sizeof_sym))
-	    return FALSE;
-	}
-    }
-
-  if (! _bfd_elf_maybe_strip_eh_frame_hdr (info))
-    return FALSE;
-
-  /* The backend must work out the sizes of all the other dynamic
-     sections.  */
-  if (dynobj != NULL
-      && bed->elf_backend_size_dynamic_sections != NULL
-      && ! (*bed->elf_backend_size_dynamic_sections) (output_bfd, info))
-    return FALSE;
-
-  if (dynobj != NULL && elf_hash_table (info)->dynamic_sections_created)
-    {
-      unsigned long section_sym_count;
-      struct bfd_elf_version_tree *verdefs;
-      asection *s;
-
       /* Set up the version definition section.  */
       s = bfd_get_linker_section (dynobj, ".gnu.version_d");
       BFD_ASSERT (s != NULL);
@@ -6341,7 +6061,6 @@ bfd_elf_size_dynamic_sections (bfd *outp
 	{
 	  unsigned int cdefs;
 	  bfd_size_type size;
-	  struct bfd_elf_version_tree *t;
 	  bfd_byte *p;
 	  Elf_Internal_Verdef def;
 	  Elf_Internal_Verdaux defaux;
@@ -6557,34 +6276,9 @@ bfd_elf_size_dynamic_sections (bfd *outp
 		}
 	    }
 
-	  if (!_bfd_elf_add_dynamic_entry (info, DT_VERDEF, 0)
-	      || !_bfd_elf_add_dynamic_entry (info, DT_VERDEFNUM, cdefs))
-	    return FALSE;
-
 	  elf_tdata (output_bfd)->cverdefs = cdefs;
 	}
 
-      if ((info->new_dtags && info->flags) || (info->flags & DF_STATIC_TLS))
-	{
-	  if (!_bfd_elf_add_dynamic_entry (info, DT_FLAGS, info->flags))
-	    return FALSE;
-	}
-      else if (info->flags & DF_BIND_NOW)
-	{
-	  if (!_bfd_elf_add_dynamic_entry (info, DT_BIND_NOW, 0))
-	    return FALSE;
-	}
-
-      if (info->flags_1)
-	{
-	  if (bfd_link_executable (info))
-	    info->flags_1 &= ~ (DF_1_INITFIRST
-				| DF_1_NODELETE
-				| DF_1_NOOPEN);
-	  if (!_bfd_elf_add_dynamic_entry (info, DT_FLAGS_1, info->flags_1))
-	    return FALSE;
-	}
-
       /* Work out the size of the version reference section.  */
 
       s = bfd_get_linker_section (dynobj, ".gnu.version_r");
@@ -6608,7 +6302,7 @@ bfd_elf_size_dynamic_sections (bfd *outp
 	  s->flags |= SEC_EXCLUDE;
 	else
 	  {
-	    Elf_Internal_Verneed *t;
+	    Elf_Internal_Verneed *vn;
 	    unsigned int size;
 	    unsigned int crefs;
 	    bfd_byte *p;
@@ -6616,15 +6310,15 @@ bfd_elf_size_dynamic_sections (bfd *outp
 	    /* Build the version dependency section.  */
 	    size = 0;
 	    crefs = 0;
-	    for (t = elf_tdata (output_bfd)->verref;
-		 t != NULL;
-		 t = t->vn_nextref)
+	    for (vn = elf_tdata (output_bfd)->verref;
+		 vn != NULL;
+		 vn = vn->vn_nextref)
 	      {
 		Elf_Internal_Vernaux *a;
 
 		size += sizeof (Elf_External_Verneed);
 		++crefs;
-		for (a = t->vn_auxptr; a != NULL; a = a->vna_nextptr)
+		for (a = vn->vn_auxptr; a != NULL; a = a->vna_nextptr)
 		  size += sizeof (Elf_External_Vernaux);
 	      }
 
@@ -6634,40 +6328,40 @@ bfd_elf_size_dynamic_sections (bfd *outp
 	      return FALSE;
 
 	    p = s->contents;
-	    for (t = elf_tdata (output_bfd)->verref;
-		 t != NULL;
-		 t = t->vn_nextref)
+	    for (vn = elf_tdata (output_bfd)->verref;
+		 vn != NULL;
+		 vn = vn->vn_nextref)
 	      {
 		unsigned int caux;
 		Elf_Internal_Vernaux *a;
 		size_t indx;
 
 		caux = 0;
-		for (a = t->vn_auxptr; a != NULL; a = a->vna_nextptr)
+		for (a = vn->vn_auxptr; a != NULL; a = a->vna_nextptr)
 		  ++caux;
 
-		t->vn_version = VER_NEED_CURRENT;
-		t->vn_cnt = caux;
+		vn->vn_version = VER_NEED_CURRENT;
+		vn->vn_cnt = caux;
 		indx = _bfd_elf_strtab_add (elf_hash_table (info)->dynstr,
-					    elf_dt_name (t->vn_bfd) != NULL
-					    ? elf_dt_name (t->vn_bfd)
-					    : lbasename (t->vn_bfd->filename),
+					    elf_dt_name (vn->vn_bfd) != NULL
+					    ? elf_dt_name (vn->vn_bfd)
+					    : lbasename (vn->vn_bfd->filename),
 					    FALSE);
 		if (indx == (size_t) -1)
 		  return FALSE;
-		t->vn_file = indx;
-		t->vn_aux = sizeof (Elf_External_Verneed);
-		if (t->vn_nextref == NULL)
-		  t->vn_next = 0;
+		vn->vn_file = indx;
+		vn->vn_aux = sizeof (Elf_External_Verneed);
+		if (vn->vn_nextref == NULL)
+		  vn->vn_next = 0;
 		else
-		  t->vn_next = (sizeof (Elf_External_Verneed)
+		  vn->vn_next = (sizeof (Elf_External_Verneed)
 				+ caux * sizeof (Elf_External_Vernaux));
 
-		_bfd_elf_swap_verneed_out (output_bfd, t,
+		_bfd_elf_swap_verneed_out (output_bfd, vn,
 					   (Elf_External_Verneed *) p);
 		p += sizeof (Elf_External_Verneed);
 
-		for (a = t->vn_auxptr; a != NULL; a = a->vna_nextptr)
+		for (a = vn->vn_auxptr; a != NULL; a = a->vna_nextptr)
 		  {
 		    a->vna_hash = bfd_elf_hash (a->vna_nodename);
 		    indx = _bfd_elf_strtab_add (elf_hash_table (info)->dynstr,
@@ -6686,19 +6380,344 @@ bfd_elf_size_dynamic_sections (bfd *outp
 		  }
 	      }
 
-	    if (!_bfd_elf_add_dynamic_entry (info, DT_VERNEED, 0)
-		|| !_bfd_elf_add_dynamic_entry (info, DT_VERNEEDNUM, crefs))
-	      return FALSE;
-
 	    elf_tdata (output_bfd)->cverrefs = crefs;
 	  }
       }
+    }
+
+  bed = get_elf_backend_data (output_bfd);
+
+  if (info->gc_sections && bed->can_gc_sections)
+    {
+      struct elf_gc_sweep_symbol_info sweep_info;
+      unsigned long section_sym_count;
+
+      /* Remove the symbols that were in the swept sections from the
+	 dynamic symbol table.  GCFIXME: Anyone know how to get them
+	 out of the static symbol table as well?  */
+      sweep_info.info = info;
+      sweep_info.hide_symbol = bed->elf_backend_hide_symbol;
+      elf_link_hash_traverse (elf_hash_table (info), elf_gc_sweep_symbol,
+			      &sweep_info);
+
+      _bfd_elf_link_renumber_dynsyms (output_bfd, info, &section_sym_count);
+    }
+
+  /* Any syms created from now on start with -1 in
+     got.refcount/offset and plt.refcount/offset.  */
+  elf_hash_table (info)->init_got_refcount
+    = elf_hash_table (info)->init_got_offset;
+  elf_hash_table (info)->init_plt_refcount
+    = elf_hash_table (info)->init_plt_offset;
+
+  if (bfd_link_relocatable (info)
+      && !_bfd_elf_size_group_sections (info))
+    return FALSE;
+
+  /* The backend may have to create some sections regardless of whether
+     we're dynamic or not.  */
+  if (bed->elf_backend_always_size_sections
+      && ! (*bed->elf_backend_always_size_sections) (output_bfd, info))
+    return FALSE;
+
+  /* Determine any GNU_STACK segment requirements, after the backend
+     has had a chance to set a default segment size.  */
+  if (info->execstack)
+    elf_stack_flags (output_bfd) = PF_R | PF_W | PF_X;
+  else if (info->noexecstack)
+    elf_stack_flags (output_bfd) = PF_R | PF_W;
+  else
+    {
+      bfd *inputobj;
+      asection *notesec = NULL;
+      int exec = 0;
+
+      for (inputobj = info->input_bfds;
+	   inputobj;
+	   inputobj = inputobj->link.next)
+	{
+	  asection *s;
+
+	  if (inputobj->flags
+	      & (DYNAMIC | EXEC_P | BFD_PLUGIN | BFD_LINKER_CREATED))
+	    continue;
+	  s = bfd_get_section_by_name (inputobj, ".note.GNU-stack");
+	  if (s)
+	    {
+	      if (s->flags & SEC_CODE)
+		exec = PF_X;
+	      notesec = s;
+	    }
+	  else if (bed->default_execstack)
+	    exec = PF_X;
+	}
+      if (notesec || info->stacksize > 0)
+	elf_stack_flags (output_bfd) = PF_R | PF_W | exec;
+      if (notesec && exec && bfd_link_relocatable (info)
+	  && notesec->output_section != bfd_abs_section_ptr)
+	notesec->output_section->flags |= SEC_CODE;
+    }
+
+  if (dynobj != NULL && elf_hash_table (info)->dynamic_sections_created)
+    {
+      struct elf_info_failed eif;
+      struct elf_link_hash_entry *h;
+      asection *dynstr;
+      asection *s;
+
+      *sinterpptr = bfd_get_linker_section (dynobj, ".interp");
+      BFD_ASSERT (*sinterpptr != NULL || !bfd_link_executable (info) || info->nointerp);
+
+      if (soname != NULL)
+	{
+	  soname_indx = _bfd_elf_strtab_add (elf_hash_table (info)->dynstr,
+					     soname, TRUE);
+	  if (soname_indx == (size_t) -1
+	      || !_bfd_elf_add_dynamic_entry (info, DT_SONAME, soname_indx))
+	    return FALSE;
+	}
+
+      if (info->symbolic)
+	{
+	  if (!_bfd_elf_add_dynamic_entry (info, DT_SYMBOLIC, 0))
+	    return FALSE;
+	  info->flags |= DF_SYMBOLIC;
+	}
+
+      if (rpath != NULL)
+	{
+	  size_t indx;
+	  bfd_vma tag;
+
+	  indx = _bfd_elf_strtab_add (elf_hash_table (info)->dynstr, rpath,
+				      TRUE);
+	  if (indx == (size_t) -1)
+	    return FALSE;
+
+	  tag = info->new_dtags ? DT_RUNPATH : DT_RPATH;
+	  if (!_bfd_elf_add_dynamic_entry (info, tag, indx))
+	    return FALSE;
+	}
+
+      if (filter_shlib != NULL)
+	{
+	  size_t indx;
+
+	  indx = _bfd_elf_strtab_add (elf_hash_table (info)->dynstr,
+				      filter_shlib, TRUE);
+	  if (indx == (size_t) -1
+	      || !_bfd_elf_add_dynamic_entry (info, DT_FILTER, indx))
+	    return FALSE;
+	}
+
+      if (auxiliary_filters != NULL)
+	{
+	  const char * const *p;
+
+	  for (p = auxiliary_filters; *p != NULL; p++)
+	    {
+	      size_t indx;
+
+	      indx = _bfd_elf_strtab_add (elf_hash_table (info)->dynstr,
+					  *p, TRUE);
+	      if (indx == (size_t) -1
+		  || !_bfd_elf_add_dynamic_entry (info, DT_AUXILIARY, indx))
+		return FALSE;
+	    }
+	}
+
+      if (audit != NULL)
+	{
+	  size_t indx;
+
+	  indx = _bfd_elf_strtab_add (elf_hash_table (info)->dynstr, audit,
+				      TRUE);
+	  if (indx == (size_t) -1
+	      || !_bfd_elf_add_dynamic_entry (info, DT_AUDIT, indx))
+	    return FALSE;
+	}
+
+      if (depaudit != NULL)
+	{
+	  size_t indx;
+
+	  indx = _bfd_elf_strtab_add (elf_hash_table (info)->dynstr, depaudit,
+				      TRUE);
+	  if (indx == (size_t) -1
+	      || !_bfd_elf_add_dynamic_entry (info, DT_DEPAUDIT, indx))
+	    return FALSE;
+	}
+
+      eif.info = info;
+      eif.failed = FALSE;
+
+      /* Find all symbols which were defined in a dynamic object and make
+	 the backend pick a reasonable value for them.  */
+      elf_link_hash_traverse (elf_hash_table (info),
+			      _bfd_elf_adjust_dynamic_symbol,
+			      &eif);
+      if (eif.failed)
+	return FALSE;
+
+      /* Add some entries to the .dynamic section.  We fill in some of the
+	 values later, in bfd_elf_final_link, but we must add the entries
+	 now so that we know the final size of the .dynamic section.  */
+
+      /* If there are initialization and/or finalization functions to
+	 call then add the corresponding DT_INIT/DT_FINI entries.  */
+      h = (info->init_function
+	   ? elf_link_hash_lookup (elf_hash_table (info),
+				   info->init_function, FALSE,
+				   FALSE, FALSE)
+	   : NULL);
+      if (h != NULL
+	  && (h->ref_regular
+	      || h->def_regular))
+	{
+	  if (!_bfd_elf_add_dynamic_entry (info, DT_INIT, 0))
+	    return FALSE;
+	}
+      h = (info->fini_function
+	   ? elf_link_hash_lookup (elf_hash_table (info),
+				   info->fini_function, FALSE,
+				   FALSE, FALSE)
+	   : NULL);
+      if (h != NULL
+	  && (h->ref_regular
+	      || h->def_regular))
+	{
+	  if (!_bfd_elf_add_dynamic_entry (info, DT_FINI, 0))
+	    return FALSE;
+	}
+
+      s = bfd_get_section_by_name (output_bfd, ".preinit_array");
+      if (s != NULL && s->linker_has_input)
+	{
+	  /* DT_PREINIT_ARRAY is not allowed in shared library.  */
+	  if (! bfd_link_executable (info))
+	    {
+	      bfd *sub;
+	      asection *o;
+
+	      for (sub = info->input_bfds; sub != NULL;
+		   sub = sub->link.next)
+		if (bfd_get_flavour (sub) == bfd_target_elf_flavour)
+		  for (o = sub->sections; o != NULL; o = o->next)
+		    if (elf_section_data (o)->this_hdr.sh_type
+			== SHT_PREINIT_ARRAY)
+		      {
+			_bfd_error_handler
+			  (_("%B: .preinit_array section is not allowed in DSO"),
+			   sub);
+			break;
+		      }
+
+	      bfd_set_error (bfd_error_nonrepresentable_section);
+	      return FALSE;
+	    }
+
+	  if (!_bfd_elf_add_dynamic_entry (info, DT_PREINIT_ARRAY, 0)
+	      || !_bfd_elf_add_dynamic_entry (info, DT_PREINIT_ARRAYSZ, 0))
+	    return FALSE;
+	}
+      s = bfd_get_section_by_name (output_bfd, ".init_array");
+      if (s != NULL && s->linker_has_input)
+	{
+	  if (!_bfd_elf_add_dynamic_entry (info, DT_INIT_ARRAY, 0)
+	      || !_bfd_elf_add_dynamic_entry (info, DT_INIT_ARRAYSZ, 0))
+	    return FALSE;
+	}
+      s = bfd_get_section_by_name (output_bfd, ".fini_array");
+      if (s != NULL && s->linker_has_input)
+	{
+	  if (!_bfd_elf_add_dynamic_entry (info, DT_FINI_ARRAY, 0)
+	      || !_bfd_elf_add_dynamic_entry (info, DT_FINI_ARRAYSZ, 0))
+	    return FALSE;
+	}
+
+      dynstr = bfd_get_linker_section (dynobj, ".dynstr");
+      /* If .dynstr is excluded from the link, we don't want any of
+	 these tags.  Strictly, we should be checking each section
+	 individually;  This quick check covers for the case where
+	 someone does a /DISCARD/ : { *(*) }.  */
+      if (dynstr != NULL && dynstr->output_section != bfd_abs_section_ptr)
+	{
+	  bfd_size_type strsize;
+
+	  strsize = _bfd_elf_strtab_size (elf_hash_table (info)->dynstr);
+	  if ((info->emit_hash
+	       && !_bfd_elf_add_dynamic_entry (info, DT_HASH, 0))
+	      || (info->emit_gnu_hash
+		  && !_bfd_elf_add_dynamic_entry (info, DT_GNU_HASH, 0))
+	      || !_bfd_elf_add_dynamic_entry (info, DT_STRTAB, 0)
+	      || !_bfd_elf_add_dynamic_entry (info, DT_SYMTAB, 0)
+	      || !_bfd_elf_add_dynamic_entry (info, DT_STRSZ, strsize)
+	      || !_bfd_elf_add_dynamic_entry (info, DT_SYMENT,
+					      bed->s->sizeof_sym))
+	    return FALSE;
+	}
+    }
+
+  if (! _bfd_elf_maybe_strip_eh_frame_hdr (info))
+    return FALSE;
+
+  /* The backend must work out the sizes of all the other dynamic
+     sections.  */
+  if (dynobj != NULL
+      && bed->elf_backend_size_dynamic_sections != NULL
+      && ! (*bed->elf_backend_size_dynamic_sections) (output_bfd, info))
+    return FALSE;
+
+  if (dynobj != NULL && elf_hash_table (info)->dynamic_sections_created)
+    {
+      unsigned long section_sym_count;
+
+      if (elf_tdata (output_bfd)->cverdefs)
+	{
+	  unsigned int crefs = elf_tdata (output_bfd)->cverdefs;
+
+	  if (!_bfd_elf_add_dynamic_entry (info, DT_VERDEF, 0)
+	      || !_bfd_elf_add_dynamic_entry (info, DT_VERDEFNUM, crefs))
+	    return FALSE;
+	}
+
+      if ((info->new_dtags && info->flags) || (info->flags & DF_STATIC_TLS))
+	{
+	  if (!_bfd_elf_add_dynamic_entry (info, DT_FLAGS, info->flags))
+	    return FALSE;
+	}
+      else if (info->flags & DF_BIND_NOW)
+	{
+	  if (!_bfd_elf_add_dynamic_entry (info, DT_BIND_NOW, 0))
+	    return FALSE;
+	}
+
+      if (info->flags_1)
+	{
+	  if (bfd_link_executable (info))
+	    info->flags_1 &= ~ (DF_1_INITFIRST
+				| DF_1_NODELETE
+				| DF_1_NOOPEN);
+	  if (!_bfd_elf_add_dynamic_entry (info, DT_FLAGS_1, info->flags_1))
+	    return FALSE;
+	}
+
+      if (elf_tdata (output_bfd)->cverrefs)
+	{
+	  unsigned int crefs = elf_tdata (output_bfd)->cverrefs;
+
+	  if (!_bfd_elf_add_dynamic_entry (info, DT_VERNEED, 0)
+	      || !_bfd_elf_add_dynamic_entry (info, DT_VERNEEDNUM, crefs))
+	    return FALSE;
+	}
 
       if ((elf_tdata (output_bfd)->cverrefs == 0
 	   && elf_tdata (output_bfd)->cverdefs == 0)
 	  || _bfd_elf_link_renumber_dynsyms (output_bfd, info,
 					     &section_sym_count) == 0)
 	{
+	  asection *s;
+
 	  s = bfd_get_linker_section (dynobj, ".gnu.version");
 	  s->flags |= SEC_EXCLUDE;
 	}
Index: binutils/ld/testsuite/ld-elf/pr20828-d.sd
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ binutils/ld/testsuite/ld-elf/pr20828-d.sd	2017-02-18 02:35:25.447465308 +0000
@@ -0,0 +1,9 @@
+# Make sure `vdata' is global rather than local in the dynamic symbol table,
+# e.g.:
+#    Num:    Value  Size Type    Bind   Vis      Ndx Name
+#      1: 00000000     0 OBJECT  GLOBAL DEFAULT  ABS vdata
+# vs:
+#      1: 00000000     0 OBJECT  LOCAL  DEFAULT  ABS vdata
+#...
+ *[0-9]+: +[0-9a-f]+ +0 +OBJECT +GLOBAL +DEFAULT +ABS +vdata
+#pass
Index: binutils/ld/testsuite/ld-elf/pr20828-e.sd
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ binutils/ld/testsuite/ld-elf/pr20828-e.sd	2017-02-18 02:35:25.449491030 +0000
@@ -0,0 +1,9 @@
+# Make sure `edata' is global rather than local in the dynamic symbol table,
+# e.g.:
+#    Num:    Value  Size Type    Bind   Vis      Ndx Name
+#      1: 00000000     0 NOTYPE  GLOBAL DEFAULT    1 edata@@vdata
+# vs:
+#      1: 00000000     0 NOTYPE  LOCAL  DEFAULT    1 edata@@vdata
+#...
+ *[0-9]+: +[0-9a-f]+ +0 +NOTYPE +GLOBAL +DEFAULT +[0-9]+ +edata@@vdata
+#pass
Index: binutils/ld/testsuite/ld-elf/pr20828-v.ld
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ binutils/ld/testsuite/ld-elf/pr20828-v.ld	2017-02-21 00:50:19.000000000 +0000
@@ -0,0 +1,18 @@
+SECTIONS
+{
+  .hash : { *(.hash) }
+  .dynsym : { *(.dynsym) }
+  .dynstr : { *(.dynstr) }
+  .gnu.version : { *(.gnu.version) }
+  .gnu.version_d : { *(.gnu.version_d) }
+  .text : { *(.text) }
+  .dynamic : { *(.dynamic) }
+  .data : { *(.data) }
+  .symtab : { *(.symtab) }
+  .strtab : { *(.strtab) }
+  .shstrtab : { *(.shstrtab) }
+  .plt : { *(.plt) }
+  .got.plt : { *(.got.plt) }
+  .got : { *(.got) }
+  /DISCARD/ : { *(*) }
+}
Index: binutils/ld/testsuite/ld-elf/pr20828-v.od
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ binutils/ld/testsuite/ld-elf/pr20828-v.od	2017-02-21 00:50:19.000000000 +0000
@@ -0,0 +1,5 @@
+#...
+Version definitions:
+1 0x01 0x0b2e1e3([12]) pr20828-v-\1
+2 0x00 0x0cc85d2f ver_foo
+#pass
Index: binutils/ld/testsuite/ld-elf/pr20828-v.s
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ binutils/ld/testsuite/ld-elf/pr20828-v.s	2017-02-21 00:50:19.000000000 +0000
@@ -0,0 +1,13 @@
+	.text
+	.globl	new_foo
+	.type	new_foo, %function
+new_foo:
+	.size	new_foo, . - new_foo
+	.symver	new_foo, foo@@ver_foo
+
+	.data
+	.globl	bar
+	.type	bar, %object
+bar:
+	.dc.a	foo
+	.size	bar, . - bar
Index: binutils/ld/testsuite/ld-elf/pr20828-v.ver
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ binutils/ld/testsuite/ld-elf/pr20828-v.ver	2017-02-18 02:35:25.451506910 +0000
@@ -0,0 +1 @@
+vdata { global: edata; local: *; };
Index: binutils/ld/testsuite/ld-elf/pr20828.ld
===================================================================
--- binutils.orig/ld/testsuite/ld-elf/pr20828.ld	2017-02-18 02:23:54.912341461 +0000
+++ binutils/ld/testsuite/ld-elf/pr20828.ld	2017-02-18 02:35:25.454550287 +0000
@@ -10,6 +10,8 @@ SECTIONS
   .hash : { *(.hash) }
   .dynsym : { *(.dynsym) }
   .dynstr : { *(.dynstr) }
+  .gnu.version : { *(.gnu.version) }
+  .gnu.version_d : { *(.gnu.version_d) }
   .shstrtab : { *(.shstrtab) }
   .symtab : { *(.symtab) }
   .strtab : { *(.strtab) }
Index: binutils/ld/testsuite/ld-elf/shared.exp
===================================================================
--- binutils.orig/ld/testsuite/ld-elf/shared.exp	2017-02-18 02:23:54.920577402 +0000
+++ binutils/ld/testsuite/ld-elf/shared.exp	2017-02-21 00:50:19.000000000 +0000
@@ -50,6 +50,8 @@ if [istarget "tic6x-*-*"] {
 # - the shared library symbols have been swept in section garbage collection.
 # Verify that the symbols are global rather than local and that a version
 # script adjusts them accordingly.
+# Also verify that a version definition supplied by an object rather than
+# a version script and forcibly exported is unaffected by section GC.
 if { [check_gc_sections_available] } {
     run_ld_link_tests [list \
 	[list \
@@ -77,7 +79,41 @@ if { [check_gc_sections_available] } {
 	    {pr20828.s} \
 	    {{readelf --dyn-syms pr20828-b.sd} \
 	     {readelf --dyn-syms pr20828-c.sd}} \
-	    "pr20828-2.so"]]
+	    "pr20828-2.so"] \
+	[list \
+	    "PR ld/20828 dynamic symbols with section GC\
+	     (versioned shared library)" \
+	    "$LFLAGS -shared --gc-sections -T pr20828.ld\
+	     --version-script=pr20828-v.ver" \
+	    "" "$AFLAGS_PIC" \
+	    {pr20828.s} \
+	    {{readelf --dyn-syms pr20828-c.sd} \
+	     {readelf --dyn-syms pr20828-d.sd} \
+	     {readelf --dyn-syms pr20828-e.sd}} \
+	    "libpr20828-v.so"] \
+	[list \
+	    "PR ld/20828 dynamic symbols with section GC (versioned)" \
+	    "$LFLAGS -shared --gc-sections -T pr20828.ld\
+	     --version-script=pr20828-v.ver" \
+	    "tmpdir/libpr20828-v.so" \
+	    "$AFLAGS_PIC" \
+	    {pr20828.s} \
+	    {{readelf --dyn-syms pr20828-c.sd} \
+	     {readelf --dyn-syms pr20828-d.sd} \
+	     {readelf --dyn-syms pr20828-e.sd}} \
+	    "pr20828-v.so"] \
+	[list \
+	    "PR ld/20828 forcibly exported symbol version without section GC" \
+	    "$LFLAGS -e foo -E -T pr20828-v.ld" "" "" \
+	    {pr20828-v.s} \
+	    {{objdump -p pr20828-v.od}} \
+	    "pr20828-v-1"] \
+	[list \
+	    "PR ld/20828 forcibly exported symbol version with section GC" \
+	    "$LFLAGS -e foo --gc-sections -E -T pr20828-v.ld" "" "" \
+	    {pr20828-v.s} \
+	    {{objdump -p pr20828-v.od}} \
+	    "pr20828-v-2"]]
 }
 
 # Check to see if the C compiler works

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH v2] PR ld/20828: Move symbol version processing ahead of GC symbol sweep
  2017-02-21  1:47 [PATCH v2] PR ld/20828: Move symbol version processing ahead of GC symbol sweep Maciej W. Rozycki
@ 2017-02-21 22:52 ` Alan Modra
  2017-02-22 18:23   ` Maciej W. Rozycki
  2017-02-24 13:41   ` Alan Modra
  0 siblings, 2 replies; 9+ messages in thread
From: Alan Modra @ 2017-02-21 22:52 UTC (permalink / raw)
  To: Maciej W. Rozycki; +Cc: Nick Clifton, James Cowgill, binutils

On Tue, Feb 21, 2017 at 01:46:42AM +0000, Maciej W. Rozycki wrote:
> 	bfd/
> 	PR ld/20828
> 	* elflink.c (bfd_elf_size_dynamic_sections): Move symbol version 
> 	processing ahead of the call to `elf_gc_sweep_symbol'.
> 
> 	ld/
> 	PR ld/20828
> 	* testsuite/ld-elf/pr20828-d.sd: New test.
> 	* testsuite/ld-elf/pr20828-e.sd: New test.
> 	* testsuite/ld-elf/pr20828-v.od: New test.
> 	* testsuite/ld-elf/pr20828-v.ver: New test version script.
> 	* testsuite/ld-elf/pr20828-v.ld: New test linker script.
> 	* testsuite/ld-elf/pr20828.ld: Add `.gnu.version' and 
> 	`.gnu.version_d'.
> 	* testsuite/ld-elf/shared.exp: Run the new tests.

OK to commit.  If we find corner cases where the rearranged code
regresses we'll handle that as we find them.

-- 
Alan Modra
Australia Development Lab, IBM

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH v2] PR ld/20828: Move symbol version processing ahead of GC symbol sweep
  2017-02-21 22:52 ` Alan Modra
@ 2017-02-22 18:23   ` Maciej W. Rozycki
  2017-02-24 13:41   ` Alan Modra
  1 sibling, 0 replies; 9+ messages in thread
From: Maciej W. Rozycki @ 2017-02-22 18:23 UTC (permalink / raw)
  To: Alan Modra; +Cc: Nick Clifton, James Cowgill, binutils

On Tue, 21 Feb 2017, Alan Modra wrote:

> OK to commit.  If we find corner cases where the rearranged code
> regresses we'll handle that as we find them.

 Applied then, thanks for your review.  I do hope we won't have to get 
back to it.

  Maciej

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH v2] PR ld/20828: Move symbol version processing ahead of GC symbol sweep
  2017-02-21 22:52 ` Alan Modra
  2017-02-22 18:23   ` Maciej W. Rozycki
@ 2017-02-24 13:41   ` Alan Modra
  2017-02-24 14:28     ` Maciej W. Rozycki
  1 sibling, 1 reply; 9+ messages in thread
From: Alan Modra @ 2017-02-24 13:41 UTC (permalink / raw)
  To: Maciej W. Rozycki; +Cc: binutils

On Wed, Feb 22, 2017 at 09:22:19AM +1030, Alan Modra wrote:
> On Tue, Feb 21, 2017 at 01:46:42AM +0000, Maciej W. Rozycki wrote:
> > 	bfd/
> > 	PR ld/20828
> > 	* elflink.c (bfd_elf_size_dynamic_sections): Move symbol version 
> > 	processing ahead of the call to `elf_gc_sweep_symbol'.
> > 
> > 	ld/
> > 	PR ld/20828
> > 	* testsuite/ld-elf/pr20828-d.sd: New test.
> > 	* testsuite/ld-elf/pr20828-e.sd: New test.
> > 	* testsuite/ld-elf/pr20828-v.od: New test.
> > 	* testsuite/ld-elf/pr20828-v.ver: New test version script.
> > 	* testsuite/ld-elf/pr20828-v.ld: New test linker script.
> > 	* testsuite/ld-elf/pr20828.ld: Add `.gnu.version' and 
> > 	`.gnu.version_d'.
> > 	* testsuite/ld-elf/shared.exp: Run the new tests.
> 
> OK to commit.  If we find corner cases where the rearranged code
> regresses we'll handle that as we find them.

These seem to be fallout from the above change.

arc-linux-uclibc  +FAIL: ld-elf/pr13195
arc-linux-uclibc  +FAIL: ld-elf/pr19698
arc-linux-uclibc  +FAIL: Symbol export class test (auxiliary shared object)
arc-linux-uclibc  +FAIL: Symbol export class test (final shared object)

-- 
Alan Modra
Australia Development Lab, IBM

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH v2] PR ld/20828: Move symbol version processing ahead of GC symbol sweep
  2017-02-24 13:41   ` Alan Modra
@ 2017-02-24 14:28     ` Maciej W. Rozycki
  2017-02-24 14:48       ` Alan Modra
  0 siblings, 1 reply; 9+ messages in thread
From: Maciej W. Rozycki @ 2017-02-24 14:28 UTC (permalink / raw)
  To: Alan Modra; +Cc: binutils

On Fri, 24 Feb 2017, Alan Modra wrote:

> > OK to commit.  If we find corner cases where the rearranged code
> > regresses we'll handle that as we find them.
> 
> These seem to be fallout from the above change.
> 
> arc-linux-uclibc  +FAIL: ld-elf/pr13195
> arc-linux-uclibc  +FAIL: ld-elf/pr19698
> arc-linux-uclibc  +FAIL: Symbol export class test (auxiliary shared object)
> arc-linux-uclibc  +FAIL: Symbol export class test (final shared object)

 I'll have a look.  Unfortunately I've only added `arc-linux' to my target 
list as I was verifying my most recent `readelf' fixes, so I didn't catch 
these as PR ld/20828 regressions. :(

  Maciej

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH v2] PR ld/20828: Move symbol version processing ahead of GC symbol sweep
  2017-02-24 14:28     ` Maciej W. Rozycki
@ 2017-02-24 14:48       ` Alan Modra
  2017-02-24 18:01         ` Maciej W. Rozycki
  0 siblings, 1 reply; 9+ messages in thread
From: Alan Modra @ 2017-02-24 14:48 UTC (permalink / raw)
  To: Maciej W. Rozycki; +Cc: binutils

On Fri, Feb 24, 2017 at 02:28:07PM +0000, Maciej W. Rozycki wrote:
> On Fri, 24 Feb 2017, Alan Modra wrote:
> 
> > > OK to commit.  If we find corner cases where the rearranged code
> > > regresses we'll handle that as we find them.
> > 
> > These seem to be fallout from the above change.
> > 
> > arc-linux-uclibc  +FAIL: ld-elf/pr13195
> > arc-linux-uclibc  +FAIL: ld-elf/pr19698
> > arc-linux-uclibc  +FAIL: Symbol export class test (auxiliary shared object)
> > arc-linux-uclibc  +FAIL: Symbol export class test (final shared object)
> 
>  I'll have a look.  Unfortunately I've only added `arc-linux' to my target 
> list as I was verifying my most recent `readelf' fixes, so I didn't catch 
> these as PR ld/20828 regressions. :(

The problem is elf_arc_size_dynamic_sections allocates section
contents for all dynamic sections.  That's naughty because
.gnu.version_d now already has version defs.  Those versions are
therefore lost so they do not drain from the strtab, resulting in
assertion failures.  The arc backend needs fixing.  I'll do it
tomorrow.

-- 
Alan Modra
Australia Development Lab, IBM

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH v2] PR ld/20828: Move symbol version processing ahead of GC symbol sweep
  2017-02-24 14:48       ` Alan Modra
@ 2017-02-24 18:01         ` Maciej W. Rozycki
  2017-02-25  8:41           ` ARC naughtiness causing assertion fail at elf-strtab.c:302 Alan Modra
  0 siblings, 1 reply; 9+ messages in thread
From: Maciej W. Rozycki @ 2017-02-24 18:01 UTC (permalink / raw)
  To: Alan Modra; +Cc: binutils

On Fri, 24 Feb 2017, Alan Modra wrote:

> >  I'll have a look.  Unfortunately I've only added `arc-linux' to my target 
> > list as I was verifying my most recent `readelf' fixes, so I didn't catch 
> > these as PR ld/20828 regressions. :(
> 
> The problem is elf_arc_size_dynamic_sections allocates section
> contents for all dynamic sections.  That's naughty because
> .gnu.version_d now already has version defs.  Those versions are
> therefore lost so they do not drain from the strtab, resulting in
> assertion failures.  The arc backend needs fixing.  I'll do it
> tomorrow.

 Great!  I'll move on to my outstanding MIPS stuff then.

  Maciej

^ permalink raw reply	[flat|nested] 9+ messages in thread

* ARC naughtiness causing assertion fail at elf-strtab.c:302
  2017-02-24 18:01         ` Maciej W. Rozycki
@ 2017-02-25  8:41           ` Alan Modra
  2017-03-06 11:41             ` Cupertino Miranda
  0 siblings, 1 reply; 9+ messages in thread
From: Alan Modra @ 2017-02-25  8:41 UTC (permalink / raw)
  To: binutils

This patch fixes a number of issues in the ARC backend.

- The ARC size_dynamic_sections was trashing dynamic section contents,
  in particular the .gnu.version_d contents.  Those versions
  definitions are therefore lost so they do not drain from the strtab,
  resulting in assertion failures.
- The code attempting to set DT_TEXTREL was completely bogus.
- The ARC finish_dynamic_sections would segfault on trying to set
  sh_entsize for .rela.plt if that section had been discarded.
- arc_create_dynamic_sections wouldn't have ever created dynamics
  sections, which was just as well since the places it was called were
  way too late to create dynamic sections.  Its usefulness then
  devolved down to finding just one dynamic section.  All the others
  packaged into a struct were unused.
- .interp wasn't set for PIEs.

	* elf32-arc.c (struct dynamic_sections): Delete.
	(enum dyn_section_types): Delete.
	(dyn_section_names): Delete.
	(arc_create_dynamic_sections): Delete.
	(elf_arc_finish_dynamic_sections): Don't call the above.  Don't
	segfault on discarded .rela.plt section.
	(elf_arc_size_dynamic_sections): Formatting.  Don't call
	arc_create_dynamic_sections.  Don't allocate memory for sections
	handled by the generic linker.  Correct code finding relocs in
	read-only sections.  Set SEC_EXCLUDE on zero size .got,
	.got.plt, and .dynbss sections.  Do set .interp for pies.

diff --git a/bfd/ChangeLog b/bfd/ChangeLog
index 7eda963..1118c19 100644
--- a/bfd/ChangeLog
+++ b/bfd/ChangeLog
@@ -1,3 +1,17 @@
+2017-02-25  Alan Modra  <amodra@gmail.com>
+
+	* elf32-arc.c (struct dynamic_sections): Delete.
+	(enum dyn_section_types): Delete.
+	(dyn_section_names): Delete.
+	(arc_create_dynamic_sections): Delete.
+	(elf_arc_finish_dynamic_sections): Don't call the above.  Don't
+	segfault on discarded .rela.plt section.
+	(elf_arc_size_dynamic_sections): Formatting.  Don't call
+	arc_create_dynamic_sections.  Don't allocate memory for sections
+	handled by the generic linker.  Correct code finding relocs in
+	read-only sections.  Set SEC_EXCLUDE on zero size .got,
+	.got.plt, and .dynbss sections.  Do set .interp for pies.
+
 2017-02-24  Andrew Waterman  <andrew@sifive.com>
 
 	* elfnn-riscv.c (GP_NAME): New macro.
diff --git a/bfd/elf32-arc.c b/bfd/elf32-arc.c
index cc326bb..f31aeff 100644
--- a/bfd/elf32-arc.c
+++ b/bfd/elf32-arc.c
@@ -64,39 +64,6 @@ name_for_global_symbol (struct elf_link_hash_entry *h)
     bfd_elf32_swap_reloca_out (BFD, &_rel, _loc);			\
   }
 
-struct dynamic_sections
-{
-  bfd_boolean	  initialized;
-  asection *      sgot;
-  asection *      srelgot;
-  asection *      sgotplt;
-  asection *      srelgotplt;
-  asection *      sdyn;
-  asection *      splt;
-  asection *      srelplt;
-};
-
-enum dyn_section_types
-{
-  got = 0,
-  relgot,
-  gotplt,
-  dyn,
-  plt,
-  relplt,
-  DYN_SECTION_TYPES_END
-};
-
-const char * dyn_section_names[DYN_SECTION_TYPES_END] =
-{
-  ".got",
-  ".rela.got",
-  ".got.plt",
-  ".dynamic",
-  ".plt",
-  ".rela.plt"
-};
-
 
 /* The default symbols representing the init and fini dyn values.
    TODO: Check what is the relation of those strings with arclinux.em
@@ -1562,58 +1529,6 @@ elf_arc_relocate_section (bfd *		          output_bfd,
     (elf_hash_table_id ((struct elf_link_hash_table *) ((p)->hash)) \
   == ARC_ELF_DATA ? ((struct elf_arc_link_hash_table *) ((p)->hash)) : NULL)
 
-static struct dynamic_sections
-arc_create_dynamic_sections (bfd * abfd, struct bfd_link_info *info)
-{
-  struct elf_link_hash_table *htab;
-  bfd	 *dynobj;
-  struct dynamic_sections ds =
-    {
-      .initialized = FALSE,
-      .sgot = NULL,
-      .srelgot = NULL,
-      .sgotplt = NULL,
-      .srelgotplt = NULL,
-      .sdyn = NULL,
-      .splt = NULL,
-      .srelplt = NULL
-    };
-
-  htab = elf_hash_table (info);
-  BFD_ASSERT (htab);
-
-  /* Create dynamic sections for relocatable executables so that we
-     can copy relocations.  */
-  if (! htab->dynamic_sections_created && bfd_link_pic (info))
-    {
-      if (! _bfd_elf_link_create_dynamic_sections (abfd, info))
-	BFD_ASSERT (0);
-    }
-
-  dynobj = (elf_hash_table (info))->dynobj;
-
-  if (dynobj)
-    {
-      ds.sgot = htab->sgot;
-      ds.srelgot = htab->srelgot;
-
-      ds.sgotplt = bfd_get_section_by_name (dynobj, ".got.plt");
-      ds.srelgotplt = ds.srelplt;
-
-      ds.splt = bfd_get_section_by_name (dynobj, ".plt");
-      ds.srelplt = bfd_get_section_by_name (dynobj, ".rela.plt");
-    }
-
-  if (htab->dynamic_sections_created)
-    {
-      ds.sdyn = bfd_get_section_by_name (dynobj, ".dynamic");
-    }
-
-  ds.initialized = TRUE;
-
-  return ds;
-}
-
 static bfd_boolean
 elf_arc_check_relocs (bfd *			 abfd,
 		      struct bfd_link_info *     info,
@@ -2168,17 +2083,17 @@ static bfd_boolean
 elf_arc_finish_dynamic_sections (bfd * output_bfd,
 				 struct bfd_link_info *info)
 {
-  struct dynamic_sections ds = arc_create_dynamic_sections (output_bfd, info);
   struct elf_link_hash_table *htab = elf_hash_table (info);
   bfd *dynobj = (elf_hash_table (info))->dynobj;
+  asection *sdyn = bfd_get_linker_section (dynobj, ".dynamic");
 
-  if (ds.sdyn)
+  if (sdyn)
     {
       Elf32_External_Dyn *dyncon, *dynconend;
 
-      dyncon = (Elf32_External_Dyn *) ds.sdyn->contents;
+      dyncon = (Elf32_External_Dyn *) sdyn->contents;
       dynconend
-	= (Elf32_External_Dyn *) (ds.sdyn->contents + ds.sdyn->size);
+	= (Elf32_External_Dyn *) (sdyn->contents + sdyn->size);
       for (; dyncon < dynconend; dyncon++)
 	{
 	  Elf_Internal_Dyn internal_dyn;
@@ -2260,8 +2175,9 @@ elf_arc_finish_dynamic_sections (bfd * output_bfd,
 	}
 
       /* TODO: Validate this.  */
-      elf_section_data (htab->srelplt->output_section)->this_hdr.sh_entsize
-	= 0xc;
+      if (htab->srelplt->output_section != bfd_abs_section_ptr)
+	elf_section_data (htab->srelplt->output_section)
+	  ->this_hdr.sh_entsize = 12;
     }
 
   /* Fill in the first three entries in the global offset table.  */
@@ -2276,12 +2192,12 @@ elf_arc_finish_dynamic_sections (bfd * output_bfd,
 	{
 	  asection *sec = h->root.u.def.section;
 
-	  if (ds.sdyn == NULL)
+	  if (sdyn == NULL)
 	    bfd_put_32 (output_bfd, (bfd_vma) 0,
 			sec->contents);
 	  else
 	    bfd_put_32 (output_bfd,
-			ds.sdyn->output_section->vma + ds.sdyn->output_offset,
+			sdyn->output_section->vma + sdyn->output_offset,
 			sec->contents);
 	  bfd_put_32 (output_bfd, (bfd_vma) 0, sec->contents + 4);
 	  bfd_put_32 (output_bfd, (bfd_vma) 0, sec->contents + 8);
@@ -2300,26 +2216,25 @@ elf_arc_finish_dynamic_sections (bfd * output_bfd,
 
 /* Set the sizes of the dynamic sections.  */
 static bfd_boolean
-elf_arc_size_dynamic_sections (bfd * output_bfd,
+elf_arc_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
 			       struct bfd_link_info *info)
 {
-  bfd *	   dynobj;
-  asection *      s;
-  bfd_boolean	  relocs_exist = FALSE;
-  bfd_boolean	  reltext_exist = FALSE;
-  struct dynamic_sections ds = arc_create_dynamic_sections (output_bfd, info);
+  bfd *dynobj;
+  asection *s;
+  bfd_boolean relocs_exist = FALSE;
+  bfd_boolean reltext_exist = FALSE;
   struct elf_link_hash_table *htab = elf_hash_table (info);
 
-  dynobj = (elf_hash_table (info))->dynobj;
+  dynobj = htab->dynobj;
   BFD_ASSERT (dynobj != NULL);
 
-  if ((elf_hash_table (info))->dynamic_sections_created)
+  if (htab->dynamic_sections_created)
     {
       struct elf_link_hash_entry *h;
 
       /* Set the contents of the .interp section to the
 	 interpreter.  */
-      if (!bfd_link_pic (info) && !info->nointerp)
+      if (bfd_link_executable (info) && !info->nointerp)
 	{
 	  s = bfd_get_section_by_name (dynobj, ".interp");
 	  BFD_ASSERT (s != NULL);
@@ -2347,54 +2262,70 @@ elf_arc_size_dynamic_sections (bfd * output_bfd,
 	htab->srelgot->size = 0;
     }
 
-  if (htab->splt != NULL && htab->splt->size == 0)
-    htab->splt->flags |= SEC_EXCLUDE;
   for (s = dynobj->sections; s != NULL; s = s->next)
     {
       if ((s->flags & SEC_LINKER_CREATED) == 0)
 	continue;
 
-      if (strncmp (s->name, ".rela", 5) == 0)
+      if (s == htab->splt
+	  || s == htab->sgot
+	  || s == htab->sgotplt
+	  || s == htab->sdynbss)
 	{
-	  if (s->size == 0)
-	    {
-	      s->flags |= SEC_EXCLUDE;
-	    }
-	  else
+	  /* Strip this section if we don't need it.  */
+	}
+      else if (strncmp (s->name, ".rela", 5) == 0)
+	{
+	  if (s->size != 0 && s != htab->srelplt)
 	    {
-	      if (strcmp (s->name, ".rela.plt") != 0)
+	      if (!reltext_exist)
 		{
-		  const char *outname =
-		    bfd_get_section_name (output_bfd,
-					  htab->srelplt->output_section);
-
-		  asection *target = bfd_get_section_by_name (output_bfd,
-							      outname + 4);
-
-		  relocs_exist = TRUE;
-		  if (target != NULL && target->size != 0
-		      && (target->flags & SEC_READONLY) != 0
-		      && (target->flags & SEC_ALLOC) != 0)
-		    reltext_exist = TRUE;
+		  const char *name = s->name + 5;
+		  bfd *ibfd;
+		  for (ibfd = info->input_bfds; ibfd; ibfd = ibfd->link.next)
+		    if (bfd_get_flavour (ibfd) == bfd_target_elf_flavour)
+		      {
+			asection *target = bfd_get_section_by_name (ibfd, name);
+			if (target != NULL
+			    && elf_section_data (target)->sreloc == s
+			    && ((target->output_section->flags
+				 & (SEC_READONLY | SEC_ALLOC))
+				== (SEC_READONLY | SEC_ALLOC)))
+			  {
+			    reltext_exist = TRUE;
+			    break;
+			  }
+		      }
 		}
+	      relocs_exist = TRUE;
 	    }
 
 	  /* We use the reloc_count field as a counter if we need to
 	     copy relocs into the output file.  */
 	  s->reloc_count = 0;
 	}
+      else
+	{
+	  /* It's not one of our sections, so don't allocate space.  */
+	  continue;
+	}
 
-      if (strcmp (s->name, ".dynamic") == 0)
-	continue;
+      if (s->size == 0)
+	{
+	  s->flags |= SEC_EXCLUDE;
+	  continue;
+	}
 
-      if (s->size != 0)
-	s->contents = (bfd_byte *) bfd_zalloc (dynobj, s->size);
+      if ((s->flags & SEC_HAS_CONTENTS) == 0)
+	continue;
 
-      if (s->contents == NULL && s->size != 0)
+      /* Allocate memory for the section contents.  */
+      s->contents = bfd_zalloc (dynobj, s->size);
+      if (s->contents == NULL)
 	return FALSE;
     }
 
-  if (ds.sdyn)
+  if (htab->dynamic_sections_created)
     {
       /* TODO: Check if this is needed.  */
       if (!bfd_link_pic (info))
@@ -2405,19 +2336,17 @@ elf_arc_size_dynamic_sections (bfd * output_bfd,
 	if (!_bfd_elf_add_dynamic_entry (info, DT_PLTGOT, 0)
 	    || !_bfd_elf_add_dynamic_entry (info, DT_PLTRELSZ, 0)
 	    || !_bfd_elf_add_dynamic_entry (info, DT_PLTREL, DT_RELA)
-	    || !_bfd_elf_add_dynamic_entry (info, DT_JMPREL, 0)
-	   )
+	    || !_bfd_elf_add_dynamic_entry (info, DT_JMPREL, 0))
 	  return FALSE;
 
-      if (relocs_exist == TRUE)
+      if (relocs_exist)
 	if (!_bfd_elf_add_dynamic_entry (info, DT_RELA, 0)
 	    || !_bfd_elf_add_dynamic_entry (info, DT_RELASZ, 0)
 	    || !_bfd_elf_add_dynamic_entry (info, DT_RELAENT,
-					    sizeof (Elf32_External_Rela))
-	   )
+					    sizeof (Elf32_External_Rela)))
 	  return FALSE;
 
-      if (reltext_exist == TRUE)
+      if (reltext_exist)
 	if (!_bfd_elf_add_dynamic_entry (info, DT_TEXTREL, 0))
 	  return FALSE;
     }

-- 
Alan Modra
Australia Development Lab, IBM

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: ARC naughtiness causing assertion fail at elf-strtab.c:302
  2017-02-25  8:41           ` ARC naughtiness causing assertion fail at elf-strtab.c:302 Alan Modra
@ 2017-03-06 11:41             ` Cupertino Miranda
  0 siblings, 0 replies; 9+ messages in thread
From: Cupertino Miranda @ 2017-03-06 11:41 UTC (permalink / raw)
  To: Alan Modra, binutils
  Cc: Cupertino.Miranda, Claudiu Zissulescu, Francois Bedard

Hi Alan,

Apologies for such late notice of your patch. It passed under our radar. ;-)
I was honestly in the process of doing a similar clean up, also removing 
the structure and create sections function.

Please allow me a few days to try the patch in our testing 
infrastructure before I can give you a concrete feedback.

Best regards,
Cupertino


On 02/25/2017 09:41 AM, Alan Modra wrote:
> This patch fixes a number of issues in the ARC backend.
>
> - The ARC size_dynamic_sections was trashing dynamic section contents,
>   in particular the .gnu.version_d contents.  Those versions
>   definitions are therefore lost so they do not drain from the strtab,
>   resulting in assertion failures.
> - The code attempting to set DT_TEXTREL was completely bogus.
> - The ARC finish_dynamic_sections would segfault on trying to set
>   sh_entsize for .rela.plt if that section had been discarded.
> - arc_create_dynamic_sections wouldn't have ever created dynamics
>   sections, which was just as well since the places it was called were
>   way too late to create dynamic sections.  Its usefulness then
>   devolved down to finding just one dynamic section.  All the others
>   packaged into a struct were unused.
> - .interp wasn't set for PIEs.
>
> 	* elf32-arc.c (struct dynamic_sections): Delete.
> 	(enum dyn_section_types): Delete.
> 	(dyn_section_names): Delete.
> 	(arc_create_dynamic_sections): Delete.
> 	(elf_arc_finish_dynamic_sections): Don't call the above.  Don't
> 	segfault on discarded .rela.plt section.
> 	(elf_arc_size_dynamic_sections): Formatting.  Don't call
> 	arc_create_dynamic_sections.  Don't allocate memory for sections
> 	handled by the generic linker.  Correct code finding relocs in
> 	read-only sections.  Set SEC_EXCLUDE on zero size .got,
> 	.got.plt, and .dynbss sections.  Do set .interp for pies.
>
> diff --git a/bfd/ChangeLog b/bfd/ChangeLog
> index 7eda963..1118c19 100644
> --- a/bfd/ChangeLog
> +++ b/bfd/ChangeLog
> @@ -1,3 +1,17 @@
> +2017-02-25  Alan Modra  <amodra@gmail.com>
> +
> +	* elf32-arc.c (struct dynamic_sections): Delete.
> +	(enum dyn_section_types): Delete.
> +	(dyn_section_names): Delete.
> +	(arc_create_dynamic_sections): Delete.
> +	(elf_arc_finish_dynamic_sections): Don't call the above.  Don't
> +	segfault on discarded .rela.plt section.
> +	(elf_arc_size_dynamic_sections): Formatting.  Don't call
> +	arc_create_dynamic_sections.  Don't allocate memory for sections
> +	handled by the generic linker.  Correct code finding relocs in
> +	read-only sections.  Set SEC_EXCLUDE on zero size .got,
> +	.got.plt, and .dynbss sections.  Do set .interp for pies.
> +
>  2017-02-24  Andrew Waterman  <andrew@sifive.com>
>
>  	* elfnn-riscv.c (GP_NAME): New macro.
> diff --git a/bfd/elf32-arc.c b/bfd/elf32-arc.c
> index cc326bb..f31aeff 100644
> --- a/bfd/elf32-arc.c
> +++ b/bfd/elf32-arc.c
> @@ -64,39 +64,6 @@ name_for_global_symbol (struct elf_link_hash_entry *h)
>      bfd_elf32_swap_reloca_out (BFD, &_rel, _loc);			\
>    }
>
> -struct dynamic_sections
> -{
> -  bfd_boolean	  initialized;
> -  asection *      sgot;
> -  asection *      srelgot;
> -  asection *      sgotplt;
> -  asection *      srelgotplt;
> -  asection *      sdyn;
> -  asection *      splt;
> -  asection *      srelplt;
> -};
> -
> -enum dyn_section_types
> -{
> -  got = 0,
> -  relgot,
> -  gotplt,
> -  dyn,
> -  plt,
> -  relplt,
> -  DYN_SECTION_TYPES_END
> -};
> -
> -const char * dyn_section_names[DYN_SECTION_TYPES_END] =
> -{
> -  ".got",
> -  ".rela.got",
> -  ".got.plt",
> -  ".dynamic",
> -  ".plt",
> -  ".rela.plt"
> -};
> -
>
>  /* The default symbols representing the init and fini dyn values.
>     TODO: Check what is the relation of those strings with arclinux.em
> @@ -1562,58 +1529,6 @@ elf_arc_relocate_section (bfd *		          output_bfd,
>      (elf_hash_table_id ((struct elf_link_hash_table *) ((p)->hash)) \
>    == ARC_ELF_DATA ? ((struct elf_arc_link_hash_table *) ((p)->hash)) : NULL)
>
> -static struct dynamic_sections
> -arc_create_dynamic_sections (bfd * abfd, struct bfd_link_info *info)
> -{
> -  struct elf_link_hash_table *htab;
> -  bfd	 *dynobj;
> -  struct dynamic_sections ds =
> -    {
> -      .initialized = FALSE,
> -      .sgot = NULL,
> -      .srelgot = NULL,
> -      .sgotplt = NULL,
> -      .srelgotplt = NULL,
> -      .sdyn = NULL,
> -      .splt = NULL,
> -      .srelplt = NULL
> -    };
> -
> -  htab = elf_hash_table (info);
> -  BFD_ASSERT (htab);
> -
> -  /* Create dynamic sections for relocatable executables so that we
> -     can copy relocations.  */
> -  if (! htab->dynamic_sections_created && bfd_link_pic (info))
> -    {
> -      if (! _bfd_elf_link_create_dynamic_sections (abfd, info))
> -	BFD_ASSERT (0);
> -    }
> -
> -  dynobj = (elf_hash_table (info))->dynobj;
> -
> -  if (dynobj)
> -    {
> -      ds.sgot = htab->sgot;
> -      ds.srelgot = htab->srelgot;
> -
> -      ds.sgotplt = bfd_get_section_by_name (dynobj, ".got.plt");
> -      ds.srelgotplt = ds.srelplt;
> -
> -      ds.splt = bfd_get_section_by_name (dynobj, ".plt");
> -      ds.srelplt = bfd_get_section_by_name (dynobj, ".rela.plt");
> -    }
> -
> -  if (htab->dynamic_sections_created)
> -    {
> -      ds.sdyn = bfd_get_section_by_name (dynobj, ".dynamic");
> -    }
> -
> -  ds.initialized = TRUE;
> -
> -  return ds;
> -}
> -
>  static bfd_boolean
>  elf_arc_check_relocs (bfd *			 abfd,
>  		      struct bfd_link_info *     info,
> @@ -2168,17 +2083,17 @@ static bfd_boolean
>  elf_arc_finish_dynamic_sections (bfd * output_bfd,
>  				 struct bfd_link_info *info)
>  {
> -  struct dynamic_sections ds = arc_create_dynamic_sections (output_bfd, info);
>    struct elf_link_hash_table *htab = elf_hash_table (info);
>    bfd *dynobj = (elf_hash_table (info))->dynobj;
> +  asection *sdyn = bfd_get_linker_section (dynobj, ".dynamic");
>
> -  if (ds.sdyn)
> +  if (sdyn)
>      {
>        Elf32_External_Dyn *dyncon, *dynconend;
>
> -      dyncon = (Elf32_External_Dyn *) ds.sdyn->contents;
> +      dyncon = (Elf32_External_Dyn *) sdyn->contents;
>        dynconend
> -	= (Elf32_External_Dyn *) (ds.sdyn->contents + ds.sdyn->size);
> +	= (Elf32_External_Dyn *) (sdyn->contents + sdyn->size);
>        for (; dyncon < dynconend; dyncon++)
>  	{
>  	  Elf_Internal_Dyn internal_dyn;
> @@ -2260,8 +2175,9 @@ elf_arc_finish_dynamic_sections (bfd * output_bfd,
>  	}
>
>        /* TODO: Validate this.  */
> -      elf_section_data (htab->srelplt->output_section)->this_hdr.sh_entsize
> -	= 0xc;
> +      if (htab->srelplt->output_section != bfd_abs_section_ptr)
> +	elf_section_data (htab->srelplt->output_section)
> +	  ->this_hdr.sh_entsize = 12;
>      }
>
>    /* Fill in the first three entries in the global offset table.  */
> @@ -2276,12 +2192,12 @@ elf_arc_finish_dynamic_sections (bfd * output_bfd,
>  	{
>  	  asection *sec = h->root.u.def.section;
>
> -	  if (ds.sdyn == NULL)
> +	  if (sdyn == NULL)
>  	    bfd_put_32 (output_bfd, (bfd_vma) 0,
>  			sec->contents);
>  	  else
>  	    bfd_put_32 (output_bfd,
> -			ds.sdyn->output_section->vma + ds.sdyn->output_offset,
> +			sdyn->output_section->vma + sdyn->output_offset,
>  			sec->contents);
>  	  bfd_put_32 (output_bfd, (bfd_vma) 0, sec->contents + 4);
>  	  bfd_put_32 (output_bfd, (bfd_vma) 0, sec->contents + 8);
> @@ -2300,26 +2216,25 @@ elf_arc_finish_dynamic_sections (bfd * output_bfd,
>
>  /* Set the sizes of the dynamic sections.  */
>  static bfd_boolean
> -elf_arc_size_dynamic_sections (bfd * output_bfd,
> +elf_arc_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
>  			       struct bfd_link_info *info)
>  {
> -  bfd *	   dynobj;
> -  asection *      s;
> -  bfd_boolean	  relocs_exist = FALSE;
> -  bfd_boolean	  reltext_exist = FALSE;
> -  struct dynamic_sections ds = arc_create_dynamic_sections (output_bfd, info);
> +  bfd *dynobj;
> +  asection *s;
> +  bfd_boolean relocs_exist = FALSE;
> +  bfd_boolean reltext_exist = FALSE;
>    struct elf_link_hash_table *htab = elf_hash_table (info);
>
> -  dynobj = (elf_hash_table (info))->dynobj;
> +  dynobj = htab->dynobj;
>    BFD_ASSERT (dynobj != NULL);
>
> -  if ((elf_hash_table (info))->dynamic_sections_created)
> +  if (htab->dynamic_sections_created)
>      {
>        struct elf_link_hash_entry *h;
>
>        /* Set the contents of the .interp section to the
>  	 interpreter.  */
> -      if (!bfd_link_pic (info) && !info->nointerp)
> +      if (bfd_link_executable (info) && !info->nointerp)
>  	{
>  	  s = bfd_get_section_by_name (dynobj, ".interp");
>  	  BFD_ASSERT (s != NULL);
> @@ -2347,54 +2262,70 @@ elf_arc_size_dynamic_sections (bfd * output_bfd,
>  	htab->srelgot->size = 0;
>      }
>
> -  if (htab->splt != NULL && htab->splt->size == 0)
> -    htab->splt->flags |= SEC_EXCLUDE;
>    for (s = dynobj->sections; s != NULL; s = s->next)
>      {
>        if ((s->flags & SEC_LINKER_CREATED) == 0)
>  	continue;
>
> -      if (strncmp (s->name, ".rela", 5) == 0)
> +      if (s == htab->splt
> +	  || s == htab->sgot
> +	  || s == htab->sgotplt
> +	  || s == htab->sdynbss)
>  	{
> -	  if (s->size == 0)
> -	    {
> -	      s->flags |= SEC_EXCLUDE;
> -	    }
> -	  else
> +	  /* Strip this section if we don't need it.  */
> +	}
> +      else if (strncmp (s->name, ".rela", 5) == 0)
> +	{
> +	  if (s->size != 0 && s != htab->srelplt)
>  	    {
> -	      if (strcmp (s->name, ".rela.plt") != 0)
> +	      if (!reltext_exist)
>  		{
> -		  const char *outname =
> -		    bfd_get_section_name (output_bfd,
> -					  htab->srelplt->output_section);
> -
> -		  asection *target = bfd_get_section_by_name (output_bfd,
> -							      outname + 4);
> -
> -		  relocs_exist = TRUE;
> -		  if (target != NULL && target->size != 0
> -		      && (target->flags & SEC_READONLY) != 0
> -		      && (target->flags & SEC_ALLOC) != 0)
> -		    reltext_exist = TRUE;
> +		  const char *name = s->name + 5;
> +		  bfd *ibfd;
> +		  for (ibfd = info->input_bfds; ibfd; ibfd = ibfd->link.next)
> +		    if (bfd_get_flavour (ibfd) == bfd_target_elf_flavour)
> +		      {
> +			asection *target = bfd_get_section_by_name (ibfd, name);
> +			if (target != NULL
> +			    && elf_section_data (target)->sreloc == s
> +			    && ((target->output_section->flags
> +				 & (SEC_READONLY | SEC_ALLOC))
> +				== (SEC_READONLY | SEC_ALLOC)))
> +			  {
> +			    reltext_exist = TRUE;
> +			    break;
> +			  }
> +		      }
>  		}
> +	      relocs_exist = TRUE;
>  	    }
>
>  	  /* We use the reloc_count field as a counter if we need to
>  	     copy relocs into the output file.  */
>  	  s->reloc_count = 0;
>  	}
> +      else
> +	{
> +	  /* It's not one of our sections, so don't allocate space.  */
> +	  continue;
> +	}
>
> -      if (strcmp (s->name, ".dynamic") == 0)
> -	continue;
> +      if (s->size == 0)
> +	{
> +	  s->flags |= SEC_EXCLUDE;
> +	  continue;
> +	}
>
> -      if (s->size != 0)
> -	s->contents = (bfd_byte *) bfd_zalloc (dynobj, s->size);
> +      if ((s->flags & SEC_HAS_CONTENTS) == 0)
> +	continue;
>
> -      if (s->contents == NULL && s->size != 0)
> +      /* Allocate memory for the section contents.  */
> +      s->contents = bfd_zalloc (dynobj, s->size);
> +      if (s->contents == NULL)
>  	return FALSE;
>      }
>
> -  if (ds.sdyn)
> +  if (htab->dynamic_sections_created)
>      {
>        /* TODO: Check if this is needed.  */
>        if (!bfd_link_pic (info))
> @@ -2405,19 +2336,17 @@ elf_arc_size_dynamic_sections (bfd * output_bfd,
>  	if (!_bfd_elf_add_dynamic_entry (info, DT_PLTGOT, 0)
>  	    || !_bfd_elf_add_dynamic_entry (info, DT_PLTRELSZ, 0)
>  	    || !_bfd_elf_add_dynamic_entry (info, DT_PLTREL, DT_RELA)
> -	    || !_bfd_elf_add_dynamic_entry (info, DT_JMPREL, 0)
> -	   )
> +	    || !_bfd_elf_add_dynamic_entry (info, DT_JMPREL, 0))
>  	  return FALSE;
>
> -      if (relocs_exist == TRUE)
> +      if (relocs_exist)
>  	if (!_bfd_elf_add_dynamic_entry (info, DT_RELA, 0)
>  	    || !_bfd_elf_add_dynamic_entry (info, DT_RELASZ, 0)
>  	    || !_bfd_elf_add_dynamic_entry (info, DT_RELAENT,
> -					    sizeof (Elf32_External_Rela))
> -	   )
> +					    sizeof (Elf32_External_Rela)))
>  	  return FALSE;
>
> -      if (reltext_exist == TRUE)
> +      if (reltext_exist)
>  	if (!_bfd_elf_add_dynamic_entry (info, DT_TEXTREL, 0))
>  	  return FALSE;
>      }
>

^ permalink raw reply	[flat|nested] 9+ messages in thread

end of thread, other threads:[~2017-03-06 11:41 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-02-21  1:47 [PATCH v2] PR ld/20828: Move symbol version processing ahead of GC symbol sweep Maciej W. Rozycki
2017-02-21 22:52 ` Alan Modra
2017-02-22 18:23   ` Maciej W. Rozycki
2017-02-24 13:41   ` Alan Modra
2017-02-24 14:28     ` Maciej W. Rozycki
2017-02-24 14:48       ` Alan Modra
2017-02-24 18:01         ` Maciej W. Rozycki
2017-02-25  8:41           ` ARC naughtiness causing assertion fail at elf-strtab.c:302 Alan Modra
2017-03-06 11:41             ` Cupertino Miranda

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).