public inbox for binutils@sourceware.org
 help / color / mirror / Atom feed
* [PATCH] Always define referenced __start_SECNAME/__stop_SECNAME
@ 2017-06-10 22:46 H.J. Lu
  2017-06-12 23:32 ` Alan Modra
  0 siblings, 1 reply; 16+ messages in thread
From: H.J. Lu @ 2017-06-10 22:46 UTC (permalink / raw)
  To: binutils

Currently, linker will define __start_SECNAME and __stop_SECNAME symbols
only for orphaned sections.  However, during garbage collection, ELF
linker marks all sections with references to __start_SECNAME and
__stop_SECNAME symbols as used even when section SECNAME isn't an orphaned
section and linker won't define __start_SECNAME nor __stop_SECNAME.

This patch changes linker to always define referenced __start_SECNAME and
__stop_SECNAME if the input section name is the same output section name,
which is always true for orphaned sections, and SECNAME is a C identifier.
Also __start_SECNAME and __stop_SECNAME symbols are marked as hidden by
ELF linker.

bfd/

	PR ld/20022
	PR ld/21557
	PR ld/21562
	* elf-bfd.h (elf_link_hash_entry): Add start_stop.
	(_bfd_elf_is_start_stop): Removed.
	* elf32-i386.c (elf_i386_convert_load_reloc): Also check for
	__start_SECNAME/__stop_SECNAME symbols.
	* elf64-x86-64.c (elf_x86_64_convert_load_reloc): Likewise.
	* elflink.c (_bfd_elf_is_start_stop): Removed.
	(_bfd_elf_gc_mark_rsec): Check start_stop instead of calling
	_bfd_elf_is_start_stop.

ld/

	PR ld/20022
	PR ld/21557
	PR ld/21562
	* emultempl/elf32.em (gld${EMULATION_NAME}_after_open): Mark
	referenced __start_SECNAME/__stop_SECNAME symbols as hidden and
	set start_stop for garbage collection.
	* ld.texinfo: Update __start_SECNAME/__stop_SECNAME symbols.
	* ldlang.c (lang_insert_orphan): Move handling of __start_SECNAME
	and __stop_SECNAME symbols to ...
	(lang_set_startof): Here.
	* testsuite/ld-elf/pr21562.t: New test.
	* testsuite/ld-elf/pr21562a.d: Likewise.
	* testsuite/ld-elf/pr21562a.s: Likewise.
	* testsuite/ld-elf/pr21562b.d: Likewise.
	* testsuite/ld-elf/pr21562b.s: Likewise.
	* testsuite/ld-elf/pr21562c.d: Likewise.
	* testsuite/ld-elf/pr21562d.d: Likewise.
	* testsuite/ld-elf/pr21562e.d: Likewise.
	* testsuite/ld-elf/pr21562f.d: Likewise.
	* testsuite/ld-elf/pr21562g.d: Likewise.
	* testsuite/ld-elf/pr21562h.d: Likewise.
	* testsuite/ld-gc/pr20022.d: Likewise.
	* testsuite/ld-gc/pr20022a.s: Likewise.
	* testsuite/ld-gc/pr20022b.s: Likewise.
	* testsuite/ld-gc/gc.exp: Run PR ld/20022 tests.
	* testsuite/ld-gc/pr19161.d: Also accept local __start_SECNAME
	symbol.
	* testsuite/ld-gc/start.d: Likewise.
	* testsuite/ld-x86-64/lea1a.d: Updated.
	* testsuite/ld-x86-64/lea1b.d: Updated.
	* testsuite/ld-x86-64/lea1d.d: Updated.
	* testsuite/ld-x86-64/lea1e.d: Likewise.
---
 bfd/elf-bfd.h                  |  5 +--
 bfd/elf32-i386.c               |  4 +-
 bfd/elf64-x86-64.c             |  8 +++-
 bfd/elflink.c                  | 54 +-----------------------
 ld/emultempl/elf32.em          | 64 +++++++++++++++++++++++++++--
 ld/ld.texinfo                  | 16 ++++----
 ld/ldlang.c                    | 93 +++++++++++++++++++-----------------------
 ld/testsuite/ld-elf/pr21562.t  |  3 ++
 ld/testsuite/ld-elf/pr21562a.d |  9 ++++
 ld/testsuite/ld-elf/pr21562a.s |  8 ++++
 ld/testsuite/ld-elf/pr21562b.d |  9 ++++
 ld/testsuite/ld-elf/pr21562b.s |  8 ++++
 ld/testsuite/ld-elf/pr21562c.d | 10 +++++
 ld/testsuite/ld-elf/pr21562d.d | 10 +++++
 ld/testsuite/ld-elf/pr21562e.d | 10 +++++
 ld/testsuite/ld-elf/pr21562f.d | 10 +++++
 ld/testsuite/ld-elf/pr21562g.d | 10 +++++
 ld/testsuite/ld-elf/pr21562h.d | 10 +++++
 ld/testsuite/ld-gc/gc.exp      |  6 +++
 ld/testsuite/ld-gc/pr19161.d   |  2 +-
 ld/testsuite/ld-gc/pr20022.d   | 11 +++++
 ld/testsuite/ld-gc/pr20022a.s  |  8 ++++
 ld/testsuite/ld-gc/pr20022b.s  |  8 ++++
 ld/testsuite/ld-gc/start.d     |  2 +-
 ld/testsuite/ld-x86-64/lea1a.d |  2 +-
 ld/testsuite/ld-x86-64/lea1b.d |  2 +-
 ld/testsuite/ld-x86-64/lea1d.d |  2 +-
 ld/testsuite/ld-x86-64/lea1e.d |  2 +-
 28 files changed, 259 insertions(+), 127 deletions(-)
 create mode 100644 ld/testsuite/ld-elf/pr21562.t
 create mode 100644 ld/testsuite/ld-elf/pr21562a.d
 create mode 100644 ld/testsuite/ld-elf/pr21562a.s
 create mode 100644 ld/testsuite/ld-elf/pr21562b.d
 create mode 100644 ld/testsuite/ld-elf/pr21562b.s
 create mode 100644 ld/testsuite/ld-elf/pr21562c.d
 create mode 100644 ld/testsuite/ld-elf/pr21562d.d
 create mode 100644 ld/testsuite/ld-elf/pr21562e.d
 create mode 100644 ld/testsuite/ld-elf/pr21562f.d
 create mode 100644 ld/testsuite/ld-elf/pr21562g.d
 create mode 100644 ld/testsuite/ld-elf/pr21562h.d
 create mode 100644 ld/testsuite/ld-gc/pr20022.d
 create mode 100644 ld/testsuite/ld-gc/pr20022a.s
 create mode 100644 ld/testsuite/ld-gc/pr20022b.s

diff --git a/bfd/elf-bfd.h b/bfd/elf-bfd.h
index 820bc98..b523d70 100644
--- a/bfd/elf-bfd.h
+++ b/bfd/elf-bfd.h
@@ -213,6 +213,8 @@ struct elf_link_hash_entry
   /* Symbol is defined by a shared library with non-default visibility
      in a read/write section.  */
   unsigned int protected_def : 1;
+  /* Symbol is __start_XXX or __stop_XXX to mark section XXX.  */
+  unsigned int start_stop : 1;
 
   /* String table index in .dynstr if this is a dynamic symbol.  */
   unsigned long dynstr_index;
@@ -2445,9 +2447,6 @@ extern bfd_boolean bfd_elf_gc_common_finalize_got_offsets
 extern bfd_boolean bfd_elf_gc_common_final_link
   (bfd *, struct bfd_link_info *);
 
-extern asection *_bfd_elf_is_start_stop
-  (const struct bfd_link_info *, struct elf_link_hash_entry *);
-
 extern bfd_boolean bfd_elf_reloc_symbol_deleted_p
   (bfd_vma, void *);
 
diff --git a/bfd/elf32-i386.c b/bfd/elf32-i386.c
index e447e3d..9e10225 100644
--- a/bfd/elf32-i386.c
+++ b/bfd/elf32-i386.c
@@ -1787,8 +1787,10 @@ convert_branch:
 	return TRUE;
 
       /* def_regular is set by an assignment in a linker script in
-	 bfd_elf_record_link_assignment.  */
+	 bfd_elf_record_link_assignment.  forced_local is set on
+	 __start_XXX/__stop_XXX which mark section XXX.  */
       if ((h->def_regular
+	   || (h->forced_local && h->start_stop)
 	   || h->root.type == bfd_link_hash_defined
 	   || h->root.type == bfd_link_hash_defweak)
 	  && SYMBOL_REFERENCES_LOCAL (link_info, h))
diff --git a/bfd/elf64-x86-64.c b/bfd/elf64-x86-64.c
index c94d7ff..479538c 100644
--- a/bfd/elf64-x86-64.c
+++ b/bfd/elf64-x86-64.c
@@ -1921,6 +1921,7 @@ elf_x86_64_convert_load_reloc (bfd *abfd, asection *sec,
       /* Avoid optimizing GOTPCREL relocations againt _DYNAMIC since
 	 ld.so may use its link-time address.  */
       else if ((h->def_regular
+		|| (h->forced_local && h->start_stop)
 		|| h->root.type == bfd_link_hash_defined
 		|| h->root.type == bfd_link_hash_defweak)
 	       && h != htab->elf.hdynamic
@@ -1928,8 +1929,11 @@ elf_x86_64_convert_load_reloc (bfd *abfd, asection *sec,
 	{
 	  /* bfd_link_hash_new or bfd_link_hash_undefined is
 	     set by an assignment in a linker script in
-	     bfd_elf_record_link_assignment.   */
-	  if (h->def_regular
+	     bfd_elf_record_link_assignment.   forced_local
+	     is set on __start_XXX/__stop_XXX which mark
+	     section XXX.  */
+	  if ((h->def_regular
+	       || (h->forced_local && h->start_stop))
 	      && (h->root.type == bfd_link_hash_new
 		  || h->root.type == bfd_link_hash_undefined
 		  || ((h->root.type == bfd_link_hash_defined
diff --git a/bfd/elflink.c b/bfd/elflink.c
index 1b447bb..2dc138e 100644
--- a/bfd/elflink.c
+++ b/bfd/elflink.c
@@ -12683,55 +12683,6 @@ elf_gc_mark_debug_section (asection *sec ATTRIBUTE_UNUSED,
   return NULL;
 }
 
-/* For undefined __start_<name> and __stop_<name> symbols, return the
-   first input section matching <name>.  Return NULL otherwise.  */
-
-asection *
-_bfd_elf_is_start_stop (const struct bfd_link_info *info,
-			struct elf_link_hash_entry *h)
-{
-  asection *s;
-  const char *sec_name;
-
-  if (h->root.type != bfd_link_hash_undefined
-      && h->root.type != bfd_link_hash_undefweak)
-    return NULL;
-
-  s = h->root.u.undef.section;
-  if (s != NULL)
-    {
-      if (s == (asection *) 0 - 1)
-	return NULL;
-      return s;
-    }
-
-  sec_name = NULL;
-  if (strncmp (h->root.root.string, "__start_", 8) == 0)
-    sec_name = h->root.root.string + 8;
-  else if (strncmp (h->root.root.string, "__stop_", 7) == 0)
-    sec_name = h->root.root.string + 7;
-
-  if (sec_name != NULL && *sec_name != '\0')
-    {
-      bfd *i;
-
-      for (i = info->input_bfds; i != NULL; i = i->link.next)
-	{
-	  s = bfd_get_section_by_name (i, sec_name);
-	  if (s != NULL)
-	    {
-	      h->root.u.undef.section = s;
-	      break;
-	    }
-	}
-    }
-
-  if (s == NULL)
-    h->root.u.undef.section = (asection *) 0 - 1;
-
-  return s;
-}
-
 /* COOKIE->rel describes a relocation against section SEC, which is
    a section we've decided to keep.  Return the section that contains
    the relocation symbol, or NULL if no section contains it.  */
@@ -12777,10 +12728,9 @@ _bfd_elf_gc_mark_rsec (struct bfd_link_info *info, asection *sec,
 	     or __stop_XXX symbols.  The linker will later define such
 	     symbols for orphan input sections that have a name
 	     representable as a C identifier.  */
-	  asection *s = _bfd_elf_is_start_stop (info, h);
-
-	  if (s != NULL)
+	  if (h->start_stop)
 	    {
+	      asection *s = h->root.u.undef.section;
 	      *start_stop = !s->gc_mark;
 	      return s;
 	    }
diff --git a/ld/emultempl/elf32.em b/ld/emultempl/elf32.em
index 0260b7a..7a06afe 100644
--- a/ld/emultempl/elf32.em
+++ b/ld/emultempl/elf32.em
@@ -1216,6 +1216,9 @@ gld${EMULATION_NAME}_after_open (void)
 {
   struct bfd_link_needed_list *needed, *l;
   struct elf_link_hash_table *htab;
+  asection *s;
+  bfd *abfd;
+  char leading_char;
 
   after_open_default ();
 
@@ -1239,8 +1242,6 @@ gld${EMULATION_NAME}_after_open (void)
 
   if (emit_note_gnu_build_id != NULL)
     {
-      bfd *abfd;
-
       /* Find an ELF input.  */
       for (abfd = link_info.input_bfds;
 	   abfd != (bfd *) NULL; abfd = abfd->link.next)
@@ -1276,11 +1277,66 @@ gld${EMULATION_NAME}_after_open (void)
       return;
     }
 
+  leading_char = bfd_get_symbol_leading_char (link_info.output_bfd);
+
+  /* Check for input sections whose names match references to __start_XXX
+     or __stop_XXX symbols.  Mark the matched symbols as hidden and set
+     start_stop for garbage collection.  */
+  for (abfd = link_info.input_bfds; abfd; abfd = abfd->link.next)
+    for (s = abfd->sections; s; s = s->next)
+      {
+	const char *name = bfd_get_section_name (abfd, s);
+	const char *ps;
+
+	for (ps = name; *ps != '\0'; ps++)
+	  if (!ISALNUM ((unsigned char) *ps) && *ps != '_')
+	    break;
+	if (*ps == '\0')
+	  {
+	    struct elf_link_hash_entry *h;
+	    char *symbol = (char *) xmalloc (ps - name
+					     + sizeof "__start_" + 1);
+
+	    symbol[0] = leading_char;
+	    sprintf (symbol + (leading_char != 0), "__start_%s", name);
+	    h = elf_link_hash_lookup (elf_hash_table (&link_info),
+				      symbol, FALSE, FALSE, TRUE);
+	    if (h != NULL
+		&& (h->root.type == bfd_link_hash_undefined
+		    || h->root.type == bfd_link_hash_undefweak)
+		&& h->root.u.undef.section == NULL)
+	      {
+		h->start_stop = 1;
+		h->root.u.undef.section = s;
+		_bfd_elf_link_hash_hide_symbol (&link_info, h, TRUE);
+		if (ELF_ST_VISIBILITY (h->other) != STV_INTERNAL)
+		  h->other = ((h->other & ~ELF_ST_VISIBILITY (-1))
+			      | STV_HIDDEN);
+	      }
+
+	    symbol[0] = leading_char;
+	    sprintf (symbol + (leading_char != 0), "__stop_%s", name);
+	    h = elf_link_hash_lookup (elf_hash_table (&link_info),
+				      symbol, FALSE, FALSE, TRUE);
+	    if (h != NULL
+		&& (h->root.type == bfd_link_hash_undefined
+		    || h->root.type == bfd_link_hash_undefweak)
+		&& h->root.u.undef.section == NULL)
+	      {
+		h->start_stop = 1;
+		h->root.u.undef.section = s;
+		_bfd_elf_link_hash_hide_symbol (&link_info, h, TRUE);
+		if (ELF_ST_VISIBILITY (h->other) != STV_INTERNAL)
+		  h->other = ((h->other & ~ELF_ST_VISIBILITY (-1))
+			      | STV_HIDDEN);
+	      }
+	  }
+      }
+
   if (!link_info.traditional_format)
     {
-      bfd *abfd, *elfbfd = NULL;
+      bfd *elfbfd = NULL;
       bfd_boolean warn_eh_frame = FALSE;
-      asection *s;
       int seen_type = 0;
 
       for (abfd = link_info.input_bfds; abfd; abfd = abfd->link.next)
diff --git a/ld/ld.texinfo b/ld/ld.texinfo
index 790b52f..44ad84b 100644
--- a/ld/ld.texinfo
+++ b/ld/ld.texinfo
@@ -4657,6 +4657,14 @@ SECTIONS @{
 @end group
 @end smallexample
 
+If an output section's name is the same as the input section's name
+and is representable as a C identifier, then the linker will
+automatically @pxref{PROVIDE} two symbols: __start_SECNAME and
+__stop_SECNAME, where SECNAME is the name of the section.  These
+indicate the start address and end address of the output section
+respectively.  Note: most section names are not representable as
+C identifiers because they contain a @samp{.} character.
+
 @node Output Section Data
 @subsection Output Section Data
 @cindex data
@@ -5841,14 +5849,6 @@ The command line options @samp{--orphan-handling} and @samp{--unique}
 (@pxref{Options,,Command Line Options}) can be used to control which
 output sections an orphan is placed in.
 
-If an orphaned section's name is representable as a C identifier then
-the linker will automatically @pxref{PROVIDE} two symbols:
-__start_SECNAME and __stop_SECNAME, where SECNAME is the name of the
-section.  These indicate the start address and end address of the
-orphaned section respectively.  Note: most section names are not
-representable as C identifiers because they contain a @samp{.}
-character.
-
 @node Location Counter
 @subsection The Location Counter
 @kindex .
diff --git a/ld/ldlang.c b/ld/ldlang.c
index 252400b..69619cd 100644
--- a/ld/ldlang.c
+++ b/ld/ldlang.c
@@ -1829,8 +1829,6 @@ lang_insert_orphan (asection *s,
 		    lang_statement_list_type *add_child)
 {
   lang_statement_list_type add;
-  const char *ps;
-  lang_assignment_statement_type *start_assign;
   lang_output_section_statement_type *os;
   lang_output_section_statement_type **os_tail;
 
@@ -1852,29 +1850,6 @@ lang_insert_orphan (asection *s,
   os = lang_enter_output_section_statement (secname, address, normal_section,
 					    NULL, NULL, NULL, constraint, 0);
 
-  ps = NULL;
-  start_assign = NULL;
-  if (config.build_constructors && *os_tail == os)
-    {
-      /* If the name of the section is representable in C, then create
-	 symbols to mark the start and the end of the section.  */
-      for (ps = secname; *ps != '\0'; ps++)
-	if (!ISALNUM ((unsigned char) *ps) && *ps != '_')
-	  break;
-      if (*ps == '\0')
-	{
-	  char *symname;
-
-	  symname = (char *) xmalloc (ps - secname + sizeof "__start_" + 1);
-	  symname[0] = bfd_get_symbol_leading_char (link_info.output_bfd);
-	  sprintf (symname + (symname[0] != 0), "__start_%s", secname);
-	  start_assign
-	    = lang_add_assignment (exp_provide (symname,
-						exp_nameop (NAME, "."),
-						FALSE));
-	}
-    }
-
   if (add_child == NULL)
     add_child = &os->children;
   lang_add_section (add_child, s, NULL, os);
@@ -1894,27 +1869,6 @@ lang_insert_orphan (asection *s,
     lang_leave_output_section_statement (NULL, DEFAULT_MEMORY_REGION, NULL,
 					 NULL);
 
-  if (start_assign != NULL)
-    {
-      char *symname;
-      lang_assignment_statement_type *stop_assign;
-      bfd_vma dot;
-
-      symname = (char *) xmalloc (ps - secname + sizeof "__stop_" + 1);
-      symname[0] = bfd_get_symbol_leading_char (link_info.output_bfd);
-      sprintf (symname + (symname[0] != 0), "__stop_%s", secname);
-      stop_assign
-	= lang_add_assignment (exp_provide (symname,
-					    exp_nameop (NAME, "."),
-					    FALSE));
-      /* Evaluate the expression to define the symbol if referenced,
-	 before sizing dynamic sections.  */
-      dot = os->bfd_section->vma;
-      exp_fold_tree (start_assign->exp, os->bfd_section, &dot);
-      dot += TO_ADDR (s->size);
-      exp_fold_tree (stop_assign->exp, os->bfd_section, &dot);
-    }
-
   /* Restore the global list pointer.  */
   if (after != NULL)
     pop_stat_ptr ();
@@ -5924,21 +5878,29 @@ section_for_dot (void)
   return bfd_abs_section_ptr;
 }
 
-/* Fix any .startof. or .sizeof. symbols.  When the assemblers see the
-   operator .startof. (section_name), it produces an undefined symbol
-   .startof.section_name.  Similarly, when it sees
+/* Fix any .startof., .sizeof., __start or __stop symbols.  When the
+   assemblers see the operator .startof. (section_name), it produces
+   an undefined symbol .startof.section_name.  Similarly, when it sees
    .sizeof. (section_name), it produces an undefined symbol
-   .sizeof.section_name.  For all the output sections, we look for
-   such symbols, and set them to the correct value.  */
+   .sizeof.section_name.  Also for ELF linker, __start_XXX or __stop_XXX
+   symbols should be resolved to the start and end of section XXX.  For
+   all the output sections, we look for such symbols, and set them to
+   the correct value.  */
 
 static void
 lang_set_startof (void)
 {
   asection *s;
+  bfd_boolean is_elf;
+  char leading_char;
 
   if (bfd_link_relocatable (&link_info))
     return;
 
+  is_elf = (bfd_get_flavour (link_info.output_bfd)
+	    == bfd_target_elf_flavour);
+  leading_char = bfd_get_symbol_leading_char (link_info.output_bfd);
+
   for (s = link_info.output_bfd->sections; s != NULL; s = s->next)
     {
       const char *secname;
@@ -5966,6 +5928,35 @@ lang_set_startof (void)
 	  h->u.def.section = bfd_abs_section_ptr;
 	}
 
+      buf[0] = leading_char;
+      sprintf (buf + (buf[0] != 0), "__start_%s", secname);
+      h = bfd_link_hash_lookup (link_info.hash, buf, FALSE, FALSE,
+				TRUE);
+      if (h != NULL
+	  && (h->type == bfd_link_hash_undefined
+	      || h->type == bfd_link_hash_undefweak))
+	{
+	  h->type = bfd_link_hash_defined;
+	  h->u.def.value = 0;
+	  h->u.def.section = s;
+	  if (is_elf)
+	    ((struct elf_link_hash_entry *) h)->def_regular = 1;
+	}
+
+      buf[0] = leading_char;
+      sprintf (buf + (buf[0] != 0), "__stop_%s", secname);
+      h = bfd_link_hash_lookup (link_info.hash, buf, FALSE, FALSE,
+				TRUE);
+      if (h != NULL
+	  && (h->type == bfd_link_hash_undefined
+	      || h->type == bfd_link_hash_undefweak))
+	{
+	  h->type = bfd_link_hash_defined;
+	  h->u.def.value = TO_ADDR (s->size);
+	  h->u.def.section = s;
+	  if (is_elf)
+	    ((struct elf_link_hash_entry *) h)->def_regular = 1;
+	}
       free (buf);
     }
 }
diff --git a/ld/testsuite/ld-elf/pr21562.t b/ld/testsuite/ld-elf/pr21562.t
new file mode 100644
index 0000000..01478e6
--- /dev/null
+++ b/ld/testsuite/ld-elf/pr21562.t
@@ -0,0 +1,3 @@
+SECTIONS {
+        scnfoo : { *(scnfoo) }
+}
diff --git a/ld/testsuite/ld-elf/pr21562a.d b/ld/testsuite/ld-elf/pr21562a.d
new file mode 100644
index 0000000..009dcfc
--- /dev/null
+++ b/ld/testsuite/ld-elf/pr21562a.d
@@ -0,0 +1,9 @@
+#ld: -shared -z defs --gc-sections
+#readelf: -s -S --wide
+#target: *-*-linux* *-*-gnu*
+
+#...
+  \[[ 0-9]+\] scnfoo[ \t]+PROGBITS[ \t]+[0-9a-f]+ +[0-9a-f]+ +0*10[ \t]+.*
+#...
+ +[0-9]+: +[0-9a-f]+ +[0-9a-f]+ +NOTYPE +LOCAL +DEFAULT +[0-9]+ +__start_scnfoo
+#pass
diff --git a/ld/testsuite/ld-elf/pr21562a.s b/ld/testsuite/ld-elf/pr21562a.s
new file mode 100644
index 0000000..ec36da4
--- /dev/null
+++ b/ld/testsuite/ld-elf/pr21562a.s
@@ -0,0 +1,8 @@
+        .section        scnfoo,"aw",%progbits
+        .zero 0x10
+
+        .globl  bar
+        .data
+        .type   bar, %object
+bar:
+        .dc.a   __start_scnfoo
diff --git a/ld/testsuite/ld-elf/pr21562b.d b/ld/testsuite/ld-elf/pr21562b.d
new file mode 100644
index 0000000..a03dbad
--- /dev/null
+++ b/ld/testsuite/ld-elf/pr21562b.d
@@ -0,0 +1,9 @@
+#ld: -shared -z defs --gc-sections
+#readelf: -s -S --wide
+#target: *-*-linux* *-*-gnu*
+
+#...
+  \[[ 0-9]+\] scnfoo[ \t]+PROGBITS[ \t]+[0-9a-f]+ +[0-9a-f]+ +0*10[ \t]+.*
+#...
+ +[0-9]+: +[0-9a-f]+ +[0-9a-f]+ +NOTYPE +LOCAL +DEFAULT +[0-9]+ +__stop_scnfoo
+#pass
diff --git a/ld/testsuite/ld-elf/pr21562b.s b/ld/testsuite/ld-elf/pr21562b.s
new file mode 100644
index 0000000..1732ee2
--- /dev/null
+++ b/ld/testsuite/ld-elf/pr21562b.s
@@ -0,0 +1,8 @@
+        .section        scnfoo,"aw",%progbits
+        .zero 0x10
+
+        .globl  bar
+        .data
+        .type   bar, %object
+bar:
+        .dc.a   __stop_scnfoo
diff --git a/ld/testsuite/ld-elf/pr21562c.d b/ld/testsuite/ld-elf/pr21562c.d
new file mode 100644
index 0000000..1d63f0c
--- /dev/null
+++ b/ld/testsuite/ld-elf/pr21562c.d
@@ -0,0 +1,10 @@
+#source: pr21562a.s
+#ld: -shared -z defs --gc-sections -T pr21562.t
+#readelf: -s -S --wide
+#target: *-*-linux* *-*-gnu*
+
+#...
+  \[[ 0-9]+\] scnfoo[ \t]+PROGBITS[ \t]+[0-9a-f]+ +[0-9a-f]+ +0*10[ \t]+.*
+#...
+ +[0-9]+: +[0-9a-f]+ +[0-9a-f]+ +NOTYPE +LOCAL +DEFAULT +[0-9]+ +__start_scnfoo
+#pass
diff --git a/ld/testsuite/ld-elf/pr21562d.d b/ld/testsuite/ld-elf/pr21562d.d
new file mode 100644
index 0000000..d87725e
--- /dev/null
+++ b/ld/testsuite/ld-elf/pr21562d.d
@@ -0,0 +1,10 @@
+#source: pr21562b.s
+#ld: -shared -z defs --gc-sections -T pr21562.t
+#readelf: -s -S --wide
+#target: *-*-linux* *-*-gnu*
+
+#...
+  \[[ 0-9]+\] scnfoo[ \t]+PROGBITS[ \t]+[0-9a-f]+ +[0-9a-f]+ +0*10[ \t]+.*
+#...
+ +[0-9]+: +[0-9a-f]+ +[0-9a-f]+ +NOTYPE +LOCAL +DEFAULT +[0-9]+ +__stop_scnfoo
+#pass
diff --git a/ld/testsuite/ld-elf/pr21562e.d b/ld/testsuite/ld-elf/pr21562e.d
new file mode 100644
index 0000000..afaf7e5
--- /dev/null
+++ b/ld/testsuite/ld-elf/pr21562e.d
@@ -0,0 +1,10 @@
+#source: pr21562a.s
+#ld: -shared -z defs
+#readelf: -s -S --wide
+#target: *-*-linux* *-*-gnu*
+
+#...
+  \[[ 0-9]+\] scnfoo[ \t]+PROGBITS[ \t]+[0-9a-f]+ +[0-9a-f]+ +0*10[ \t]+.*
+#...
+ +[0-9]+: +[0-9a-f]+ +[0-9a-f]+ +NOTYPE +LOCAL +DEFAULT +[0-9]+ +__start_scnfoo
+#pass
diff --git a/ld/testsuite/ld-elf/pr21562f.d b/ld/testsuite/ld-elf/pr21562f.d
new file mode 100644
index 0000000..b9c324a
--- /dev/null
+++ b/ld/testsuite/ld-elf/pr21562f.d
@@ -0,0 +1,10 @@
+#source: pr21562b.s
+#ld: -shared -z defs
+#readelf: -s -S --wide
+#target: *-*-linux* *-*-gnu*
+
+#...
+  \[[ 0-9]+\] scnfoo[ \t]+PROGBITS[ \t]+[0-9a-f]+ +[0-9a-f]+ +0*10[ \t]+.*
+#...
+ +[0-9]+: +[0-9a-f]+ +[0-9a-f]+ +NOTYPE +LOCAL +DEFAULT +[0-9]+ +__stop_scnfoo
+#pass
diff --git a/ld/testsuite/ld-elf/pr21562g.d b/ld/testsuite/ld-elf/pr21562g.d
new file mode 100644
index 0000000..0760027
--- /dev/null
+++ b/ld/testsuite/ld-elf/pr21562g.d
@@ -0,0 +1,10 @@
+#source: pr21562a.s
+#ld: -shared -z defs -T pr21562.t
+#readelf: -s -S --wide
+#target: *-*-linux* *-*-gnu*
+
+#...
+  \[[ 0-9]+\] scnfoo[ \t]+PROGBITS[ \t]+[0-9a-f]+ +[0-9a-f]+ +0*10[ \t]+.*
+#...
+ +[0-9]+: +[0-9a-f]+ +[0-9a-f]+ +NOTYPE +LOCAL +DEFAULT +[0-9]+ +__start_scnfoo
+#pass
diff --git a/ld/testsuite/ld-elf/pr21562h.d b/ld/testsuite/ld-elf/pr21562h.d
new file mode 100644
index 0000000..e654140
--- /dev/null
+++ b/ld/testsuite/ld-elf/pr21562h.d
@@ -0,0 +1,10 @@
+#source: pr21562b.s
+#ld: -shared -z defs -T pr21562.t
+#readelf: -s -S --wide
+#target: *-*-linux* *-*-gnu*
+
+#...
+  \[[ 0-9]+\] scnfoo[ \t]+PROGBITS[ \t]+[0-9a-f]+ +[0-9a-f]+ +0*10[ \t]+.*
+#...
+ +[0-9]+: +[0-9a-f]+ +[0-9a-f]+ +NOTYPE +LOCAL +DEFAULT +[0-9]+ +__stop_scnfoo
+#pass
diff --git a/ld/testsuite/ld-gc/gc.exp b/ld/testsuite/ld-gc/gc.exp
index ba5c46b..364c73b 100644
--- a/ld/testsuite/ld-gc/gc.exp
+++ b/ld/testsuite/ld-gc/gc.exp
@@ -119,6 +119,12 @@ if { [is_elf_format] && [check_shared_lib_support] } then {
 	run_dump_test "personality"
     }
     run_dump_test "pr18223"
+    if {![ld_assemble_flags $as $gasopt $srcdir/$subdir/pr20022a.s tmpdir/pr20022a.o]
+	|| ![ld_link $ld tmpdir/pr20022.so "-shared --gc-sections tmpdir/pr20022a.o"] } then {
+	fail pr20022
+    } else {
+	run_dump_test "pr20022"
+    }
 }
 
 if { [is_remote host] || [which $CC] != 0 } {
diff --git a/ld/testsuite/ld-gc/pr19161.d b/ld/testsuite/ld-gc/pr19161.d
index c36e663..baee8da 100644
--- a/ld/testsuite/ld-gc/pr19161.d
+++ b/ld/testsuite/ld-gc/pr19161.d
@@ -6,5 +6,5 @@
 #xfail: mips64vr-*-* msp430-*-* powerpc*-*-eabivle rl78-*-* rx-*-* sh*-*-*
 
 #...
-0*[1-9a-f]+[0-9a-f]*[ 	](D)[ 	]_*__start_my_section
+0*[1-9a-f]+[0-9a-f]*[ 	](d|D)[ 	]_*__start_my_section
 #...
diff --git a/ld/testsuite/ld-gc/pr20022.d b/ld/testsuite/ld-gc/pr20022.d
new file mode 100644
index 0000000..b51ec19
--- /dev/null
+++ b/ld/testsuite/ld-gc/pr20022.d
@@ -0,0 +1,11 @@
+#source: pr20022b.s
+#ld: --gc-sections -e _start tmpdir/pr20022.so
+#readelf: -SsW
+#target: *-*-linux* *-*-gnu*
+#notarget: *-*-*aout *-*-*oldld frv-*-linux* metag-*-linux*
+
+#...
+  \[[ 0-9]+\] _foo[ \t]+PROGBITS[ \t]+[0-9a-f]+ +[0-9a-f]+ +[0-9a-f]+[ \t]+.*
+#...
+ +[0-9]+: +[0-9a-f]+ +[0-9a-f]+ +NOTYPE +LOCAL +DEFAULT +[0-9]+ +__start__foo
+#pass
diff --git a/ld/testsuite/ld-gc/pr20022a.s b/ld/testsuite/ld-gc/pr20022a.s
new file mode 100644
index 0000000..6bd346f
--- /dev/null
+++ b/ld/testsuite/ld-gc/pr20022a.s
@@ -0,0 +1,8 @@
+	.data
+	.globl bar
+	.type bar,%object
+bar:
+	.dc.a	__start__foo
+	.section _foo,"aw",%progbits
+foo:
+	.ascii "This is bar"
diff --git a/ld/testsuite/ld-gc/pr20022b.s b/ld/testsuite/ld-gc/pr20022b.s
new file mode 100644
index 0000000..2306c59
--- /dev/null
+++ b/ld/testsuite/ld-gc/pr20022b.s
@@ -0,0 +1,8 @@
+	.text
+	.globl _start
+_start:
+	.dc.a	__start__foo
+	.dc.a	bar
+	.section _foo,"aw",%progbits
+foo:
+	.ascii "This is foo"
diff --git a/ld/testsuite/ld-gc/start.d b/ld/testsuite/ld-gc/start.d
index 18e74c1..9113b48 100644
--- a/ld/testsuite/ld-gc/start.d
+++ b/ld/testsuite/ld-gc/start.d
@@ -5,5 +5,5 @@
 #notarget: *-*-*aout *-*-*oldld frv-*-linux* metag-*-linux*
 
 #...
-[0-9a-f]+ D +__start__foo
+[0-9a-f]+ d +__start__foo
 #...
diff --git a/ld/testsuite/ld-x86-64/lea1a.d b/ld/testsuite/ld-x86-64/lea1a.d
index 9b662cb..28ea4b9 100644
--- a/ld/testsuite/ld-x86-64/lea1a.d
+++ b/ld/testsuite/ld-x86-64/lea1a.d
@@ -15,5 +15,5 @@ Disassembly of section .text:
 [ 	]*[a-f0-9]+:	48 8d 05 ([0-9a-f]{2} ){4} *	lea    -0x[a-f0-9]+\(%rip\),%rax        # [a-f0-9]+ <foo>
 [ 	]*[a-f0-9]+:	4c 8d 1d ([0-9a-f]{2} ){4} *	lea    0x[a-f0-9]+\(%rip\),%r11        # [a-f0-9]+ <bar>
 [ 	]*[a-f0-9]+:	48 8d 05 ([0-9a-f]{2} ){4} *	lea    0x[a-f0-9]+\(%rip\),%rax        # [a-f0-9]+ <__start_my_section>
-[ 	]*[a-f0-9]+:	4c 8d 1d ([0-9a-f]{2} ){4} *	lea    0x[a-f0-9]+\(%rip\),%r11        # [a-f0-9]+ <__stop_my_section>
+[ 	]*[a-f0-9]+:	4c 8d 1d ([0-9a-f]{2} ){4} *	lea    0x[a-f0-9]+\(%rip\),%r11        # [a-f0-9]+ <.*>
 #pass
diff --git a/ld/testsuite/ld-x86-64/lea1b.d b/ld/testsuite/ld-x86-64/lea1b.d
index 9108149..c7873cd 100644
--- a/ld/testsuite/ld-x86-64/lea1b.d
+++ b/ld/testsuite/ld-x86-64/lea1b.d
@@ -15,5 +15,5 @@ Disassembly of section .text:
 [ 	]*[a-f0-9]+:	48 8d 05 ([0-9a-f]{2} ){4} *	lea    -0x[a-f0-9]+\(%rip\),%rax        # [a-f0-9]+ <foo>
 [ 	]*[a-f0-9]+:	4c 8d 1d ([0-9a-f]{2} ){4} *	lea    0x[a-f0-9]+\(%rip\),%r11        # [a-f0-9]+ <bar>
 [ 	]*[a-f0-9]+:	48 8d 05 ([0-9a-f]{2} ){4} *	lea    0x[a-f0-9]+\(%rip\),%rax        # [a-f0-9]+ <__start_my_section>
-[ 	]*[a-f0-9]+:	4c 8d 1d ([0-9a-f]{2} ){4} *	lea    0x[a-f0-9]+\(%rip\),%r11        # [a-f0-9]+ <__stop_my_section>
+[ 	]*[a-f0-9]+:	4c 8d 1d ([0-9a-f]{2} ){4} *	lea    0x[a-f0-9]+\(%rip\),%r11        # [a-f0-9]+ <.*>
 #pass
diff --git a/ld/testsuite/ld-x86-64/lea1d.d b/ld/testsuite/ld-x86-64/lea1d.d
index 4d708d2..70fc603 100644
--- a/ld/testsuite/ld-x86-64/lea1d.d
+++ b/ld/testsuite/ld-x86-64/lea1d.d
@@ -15,5 +15,5 @@ Disassembly of section .text:
 [ 	]*[a-f0-9]+:	48 8d 05 ([0-9a-f]{2} ){4} *	lea    -0x[a-f0-9]+\(%rip\),%rax        # [a-f0-9]+ <foo>
 [ 	]*[a-f0-9]+:	4c 8d 1d ([0-9a-f]{2} ){4} *	lea    0x[a-f0-9]+\(%rip\),%r11        # [a-f0-9]+ <bar>
 [ 	]*[a-f0-9]+:	48 8d 05 ([0-9a-f]{2} ){4} *	lea    0x[a-f0-9]+\(%rip\),%rax        # [a-f0-9]+ <__start_my_section>
-[ 	]*[a-f0-9]+:	4c 8d 1d ([0-9a-f]{2} ){4} *	lea    0x[a-f0-9]+\(%rip\),%r11        # [a-f0-9]+ <__stop_my_section>
+[ 	]*[a-f0-9]+:	4c 8d 1d ([0-9a-f]{2} ){4} *	lea    0x[a-f0-9]+\(%rip\),%r11        # [a-f0-9]+ <.*>
 #pass
diff --git a/ld/testsuite/ld-x86-64/lea1e.d b/ld/testsuite/ld-x86-64/lea1e.d
index da60137..123fcd2 100644
--- a/ld/testsuite/ld-x86-64/lea1e.d
+++ b/ld/testsuite/ld-x86-64/lea1e.d
@@ -15,5 +15,5 @@ Disassembly of section .text:
 [ 	]*[a-f0-9]+:	48 8d 05 ([0-9a-f]{2} ){4} *	lea    -0x[a-f0-9]+\(%rip\),%rax        # [a-f0-9]+ <foo>
 [ 	]*[a-f0-9]+:	4c 8d 1d ([0-9a-f]{2} ){4} *	lea    0x[a-f0-9]+\(%rip\),%r11        # [a-f0-9]+ <bar>
 [ 	]*[a-f0-9]+:	48 8d 05 ([0-9a-f]{2} ){4} *	lea    0x[a-f0-9]+\(%rip\),%rax        # [a-f0-9]+ <__start_my_section>
-[ 	]*[a-f0-9]+:	4c 8d 1d ([0-9a-f]{2} ){4} *	lea    0x[a-f0-9]+\(%rip\),%r11        # [a-f0-9]+ <__stop_my_section>
+[ 	]*[a-f0-9]+:	4c 8d 1d ([0-9a-f]{2} ){4} *	lea    0x[a-f0-9]+\(%rip\),%r11        # [a-f0-9]+ <.*>
 #pass
-- 
2.9.4

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

* Re: [PATCH] Always define referenced __start_SECNAME/__stop_SECNAME
  2017-06-10 22:46 [PATCH] Always define referenced __start_SECNAME/__stop_SECNAME H.J. Lu
@ 2017-06-12 23:32 ` Alan Modra
  2017-06-13  0:18   ` H.J. Lu
  0 siblings, 1 reply; 16+ messages in thread
From: Alan Modra @ 2017-06-12 23:32 UTC (permalink / raw)
  To: H.J. Lu; +Cc: binutils

On Sat, Jun 10, 2017 at 03:46:49PM -0700, H.J. Lu wrote:
> This patch changes linker to always define referenced __start_SECNAME and
> __stop_SECNAME if the input section name is the same output section name,
> which is always true for orphaned sections, and SECNAME is a C identifier.

I think this change is reasonable.

> Also __start_SECNAME and __stop_SECNAME symbols are marked as hidden by
> ELF linker.

Why is this necessary?  Also, you make another change in behaviour
that you don't mention:  __start and __stop symbols were previously
defined by ld -Ur, not just at final link.  You'll need to modify
lang_set_startof to keep this behaviour (and be careful to not change
.startof. and .sizeof. syms).

-- 
Alan Modra
Australia Development Lab, IBM

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

* Re: [PATCH] Always define referenced __start_SECNAME/__stop_SECNAME
  2017-06-12 23:32 ` Alan Modra
@ 2017-06-13  0:18   ` H.J. Lu
  2017-06-13  1:54     ` Alan Modra
  0 siblings, 1 reply; 16+ messages in thread
From: H.J. Lu @ 2017-06-13  0:18 UTC (permalink / raw)
  To: Alan Modra; +Cc: Binutils

On Mon, Jun 12, 2017 at 4:32 PM, Alan Modra <amodra@gmail.com> wrote:
> On Sat, Jun 10, 2017 at 03:46:49PM -0700, H.J. Lu wrote:
>> This patch changes linker to always define referenced __start_SECNAME and
>> __stop_SECNAME if the input section name is the same output section name,
>> which is always true for orphaned sections, and SECNAME is a C identifier.
>
> I think this change is reasonable.
>
>> Also __start_SECNAME and __stop_SECNAME symbols are marked as hidden by
>> ELF linker.
>
> Why is this necessary?  Also, you make another change in behaviour

It is to make sure that  __start_SECNAME and __stop_SECNAME
symbols     for section SECNAME in different modules are unique.

> that you don't mention:  __start and __stop symbols were previously
> defined by ld -Ur, not just at final link.  You'll need to modify

Is there a testcase for this behavior?

> lang_set_startof to keep this behaviour (and be careful to not change
> .startof. and .sizeof. syms).
>

I have an updated patch to address:

https://sourceware.org/bugzilla/show_bug.cgi?id=21571

-- 
H.J.

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

* Re: [PATCH] Always define referenced __start_SECNAME/__stop_SECNAME
  2017-06-13  0:18   ` H.J. Lu
@ 2017-06-13  1:54     ` Alan Modra
  2017-06-13  2:10       ` H.J. Lu
  0 siblings, 1 reply; 16+ messages in thread
From: Alan Modra @ 2017-06-13  1:54 UTC (permalink / raw)
  To: H.J. Lu; +Cc: Binutils

On Mon, Jun 12, 2017 at 05:18:58PM -0700, H.J. Lu wrote:
> On Mon, Jun 12, 2017 at 4:32 PM, Alan Modra <amodra@gmail.com> wrote:
> > On Sat, Jun 10, 2017 at 03:46:49PM -0700, H.J. Lu wrote:
> >> This patch changes linker to always define referenced __start_SECNAME and
> >> __stop_SECNAME if the input section name is the same output section name,
> >> which is always true for orphaned sections, and SECNAME is a C identifier.
> >
> > I think this change is reasonable.
> >
> >> Also __start_SECNAME and __stop_SECNAME symbols are marked as hidden by
> >> ELF linker.
> >
> > Why is this necessary?  Also, you make another change in behaviour
> 
> It is to make sure that  __start_SECNAME and __stop_SECNAME
> symbols     for section SECNAME in different modules are unique.

I understand, and it would have been good if these symbols were
defined that way in the beginning, but they weren't.  I'm concerned
that if you make this change as well we will find some code that
relies on the symbols being dynamic.

> 
> > that you don't mention:  __start and __stop symbols were previously
> > defined by ld -Ur, not just at final link.  You'll need to modify
> 
> Is there a testcase for this behavior?

Not that I'm aware of.  

> > lang_set_startof to keep this behaviour (and be careful to not change
> > .startof. and .sizeof. syms).
> >
> 
> I have an updated patch to address:
> 
> https://sourceware.org/bugzilla/show_bug.cgi?id=21571
> 
> -- 
> H.J.

-- 
Alan Modra
Australia Development Lab, IBM

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

* Re: [PATCH] Always define referenced __start_SECNAME/__stop_SECNAME
  2017-06-13  1:54     ` Alan Modra
@ 2017-06-13  2:10       ` H.J. Lu
  2017-06-13 12:26         ` Alan Modra
  0 siblings, 1 reply; 16+ messages in thread
From: H.J. Lu @ 2017-06-13  2:10 UTC (permalink / raw)
  To: Alan Modra; +Cc: Binutils

[-- Attachment #1: Type: text/plain, Size: 3041 bytes --]

On Mon, Jun 12, 2017 at 6:54 PM, Alan Modra <amodra@gmail.com> wrote:
> On Mon, Jun 12, 2017 at 05:18:58PM -0700, H.J. Lu wrote:
>> On Mon, Jun 12, 2017 at 4:32 PM, Alan Modra <amodra@gmail.com> wrote:
>> > On Sat, Jun 10, 2017 at 03:46:49PM -0700, H.J. Lu wrote:
>> >> This patch changes linker to always define referenced __start_SECNAME and
>> >> __stop_SECNAME if the input section name is the same output section name,
>> >> which is always true for orphaned sections, and SECNAME is a C identifier.
>> >
>> > I think this change is reasonable.
>> >
>> >> Also __start_SECNAME and __stop_SECNAME symbols are marked as hidden by
>> >> ELF linker.
>> >
>> > Why is this necessary?  Also, you make another change in behaviour
>>
>> It is to make sure that  __start_SECNAME and __stop_SECNAME
>> symbols     for section SECNAME in different modules are unique.
>
> I understand, and it would have been good if these symbols were
> defined that way in the beginning, but they weren't.  I'm concerned
> that if you make this change as well we will find some code that
> relies on the symbols being dynamic.

My change fixes a real bug:

https://sourceware.org/bugzilla/show_bug.cgi?id=20022

We can suggest workarounds if some codes depend on that.

>>
>> > that you don't mention:  __start and __stop symbols were previously
>> > defined by ld -Ur, not just at final link.  You'll need to modify
>>
>> Is there a testcase for this behavior?
>
> Not that I'm aware of.
>

From ld manual:

'-Ur'
     For anything other than C++ programs, this option is equivalent to
     '-r': it generates relocatable output--i.e., an output file that
     can in turn serve as input to 'ld'.  When linking C++ programs,
     '-Ur' _does_ resolve references to constructors, unlike '-r'.  It
     does not work to use '-Ur' on files that were themselves linked
     with '-Ur'; once the constructor table has been built, it cannot be
     added to.  Use '-Ur' only for the last partial link, and '-r' for
     the others.

It isn't intended for  __start_SECNAME and __stop_SECNAME.  Check
config.build_constructors for __start_SECNAME and __stop_SECNAME
was introduced by:

commit 71bfc0aef6964c54b8e29466e97fb246cdeb2049
Author: Alan Modra <amodra@gmail.com>
Date:   Thu Sep 7 07:08:58 2000 +0000

    Fix list handling for orphan section output statements.

diff --git a/ld/ChangeLog b/ld/ChangeLog
index e9ca684..0292f83 100644
--- a/ld/ChangeLog
+++ b/ld/ChangeLog
@@ -1,3 +1,10 @@
+2000-09-07  Alan Modra  <alan@linuxcare.com.au>
+
+  * emultempl/elf32.em (gld${EMULATION_NAME}_place_orphan): Fix
+  broken list handling.  Create __start_SECNAME and __stop_SECNAME
+  when no place-holder.  Add some comments.  Test both SEC_CODE and
+  SEC_READONLY for hold_text to prevent .rodata orphan poisoning.

Do you remember if it was done on purpose to generate
__start_SECNAME and __stop_SECNAME for -Ur? If yes,
we can add your use case as a testcase.

Here is the updated patch to address

https://sourceware.org/bugzilla/show_bug.cgi?id=21571


-- 
H.J.

[-- Attachment #2: 0001-Always-define-referenced-__start_SECNAME-__stop_SECN.patch --]
[-- Type: text/x-patch, Size: 41737 bytes --]

From 34d937f1220804c847718f68a680ad0f4ff0ec15 Mon Sep 17 00:00:00 2001
From: "H.J. Lu" <hjl.tools@gmail.com>
Date: Sat, 10 Jun 2017 07:30:17 -0700
Subject: [PATCH] Always define referenced __start_SECNAME/__stop_SECNAME

Currently, linker will define __start_SECNAME and __stop_SECNAME symbols
only for orphaned sections.

However, during garbage collection, ELF linker marks all sections with
references to __start_SECNAME and __stop_SECNAME symbols as used even
when section SECNAME isn't an orphaned section and linker won't define
__start_SECNAME nor __stop_SECNAME.  And ELF linker stores the first
input section whose name matches __start_SECNAME or __stop_SECNAME in
u.undef.section for garbage collection.  If these symbols are provided
in linker script, u.undef.section is set to the section where they will
defined by linker script, which leads to the incorrect output.

This patch changes linker to always define referenced __start_SECNAME and
__stop_SECNAME if the input section name is the same as the output section
name, which is always true for orphaned sections, and SECNAME is a C
identifier.  Also __start_SECNAME and __stop_SECNAME symbols are marked
as hidden by ELF linker so that __start_SECNAME and __stop_SECNAME symbols
for section SECNAME in different modules are unique.  For garbage
collection, ELF linker stores the first matched input section in the
unused vtable field.

bfd/

	PR ld/20022
	PR ld/21557
	PR ld/21562
	PR ld/21571
	* elf-bfd.h (elf_link_hash_entry): Add start_stop.  Change the
	vtable field to a union.
	(_bfd_elf_is_start_stop): Removed.
	* elf32-i386.c (elf_i386_convert_load_reloc): Also check for
	__start_SECNAME and __stop_SECNAME symbols.
	* elf64-x86-64.c (elf_x86_64_convert_load_reloc): Likewise.
	* elflink.c (_bfd_elf_is_start_stop): Removed.
	(_bfd_elf_gc_mark_rsec): Check start_stop instead of calling
	_bfd_elf_is_start_stop.
	(elf_gc_propagate_vtable_entries_used): Skip __start_SECNAME and
	__stop_SECNAME symbols.  Updated.
	(elf_gc_smash_unused_vtentry_relocs): Likewise.
	(bfd_elf_gc_record_vtinherit): Likewise.
	(bfd_elf_gc_record_vtentry): Likewise.

ld/

	PR ld/20022
	PR ld/21557
	PR ld/21562
	PR ld/21571
	* ld.texinfo: Update __start_SECNAME/__stop_SECNAME symbols.
	* ldlang.c (lang_insert_orphan): Move handling of __start_SECNAME
	and __stop_SECNAME symbols to ...
	(lang_set_startof): Here.
	* emultempl/elf32.em (gld${EMULATION_NAME}_after_open): Mark
	referenced __start_SECNAME and __stop_SECNAME symbols as hidden
	and set start_stop for garbage collection.
	* testsuite/ld-elf/pr21562a.d: New file.
	* testsuite/ld-elf/pr21562a.s: Likewise.
	* testsuite/ld-elf/pr21562a.t: Likewise.
	* testsuite/ld-elf/pr21562b.d: Likewise.
	* testsuite/ld-elf/pr21562b.s: Likewise.
	* testsuite/ld-elf/pr21562b.t: Likewise.
	* testsuite/ld-elf/pr21562c.d: Likewise.
	* testsuite/ld-elf/pr21562c.t: Likewise.
	* testsuite/ld-elf/pr21562d.d: Likewise.
	* testsuite/ld-elf/pr21562d.t: Likewise.
	* testsuite/ld-elf/pr21562e.d: Likewise.
	* testsuite/ld-elf/pr21562f.d: Likewise.
	* testsuite/ld-elf/pr21562g.d: Likewise.
	* testsuite/ld-elf/pr21562h.d: Likewise.
	* testsuite/ld-elf/pr21562i.d: Likewise.
	* testsuite/ld-elf/pr21562j.d: Likewise.
	* testsuite/ld-elf/pr21562k.d: Likewise.
	* testsuite/ld-elf/pr21562l.d: Likewise.
	* testsuite/ld-elf/pr21562m.d: Likewise.
	* testsuite/ld-elf/pr21562n.d: Likewise.
	* testsuite/ld-gc/pr20022.d: Likewise.
	* testsuite/ld-gc/pr20022a.s: Likewise.
	* testsuite/ld-gc/pr20022b.s: Likewise.
	* testsuite/ld-gc/gc.exp: Run PR ld/20022 tests.
	* testsuite/ld-gc/pr19161.d: Also accept local __start_SECNAME
	symbol.
	* testsuite/ld-gc/start.d: Likewise.
	* testsuite/ld-x86-64/lea1a.d: Updated.
	* testsuite/ld-x86-64/lea1b.d: Updated.
	* testsuite/ld-x86-64/lea1d.d: Updated.
	* testsuite/ld-x86-64/lea1e.d: Likewise.
---
 bfd/elf-bfd.h                  |  16 ++++--
 bfd/elf32-i386.c               |  12 +++--
 bfd/elf64-x86-64.c             |  28 +++++-----
 bfd/elflink.c                  | 118 +++++++++++++----------------------------
 ld/emultempl/elf32.em          |  64 ++++++++++++++++++++--
 ld/ld.texinfo                  |  16 +++---
 ld/ldlang.c                    |  93 +++++++++++++++-----------------
 ld/testsuite/ld-elf/pr21562a.d |   9 ++++
 ld/testsuite/ld-elf/pr21562a.s |   8 +++
 ld/testsuite/ld-elf/pr21562a.t |   3 ++
 ld/testsuite/ld-elf/pr21562b.d |   9 ++++
 ld/testsuite/ld-elf/pr21562b.s |   8 +++
 ld/testsuite/ld-elf/pr21562b.t |   5 ++
 ld/testsuite/ld-elf/pr21562c.d |  10 ++++
 ld/testsuite/ld-elf/pr21562c.t |   7 +++
 ld/testsuite/ld-elf/pr21562d.d |  10 ++++
 ld/testsuite/ld-elf/pr21562d.t |   5 ++
 ld/testsuite/ld-elf/pr21562e.d |  10 ++++
 ld/testsuite/ld-elf/pr21562f.d |  10 ++++
 ld/testsuite/ld-elf/pr21562g.d |  10 ++++
 ld/testsuite/ld-elf/pr21562h.d |  10 ++++
 ld/testsuite/ld-elf/pr21562i.d |  10 ++++
 ld/testsuite/ld-elf/pr21562j.d |  10 ++++
 ld/testsuite/ld-elf/pr21562k.d |  10 ++++
 ld/testsuite/ld-elf/pr21562l.d |  10 ++++
 ld/testsuite/ld-elf/pr21562m.d |  10 ++++
 ld/testsuite/ld-elf/pr21562n.d |  10 ++++
 ld/testsuite/ld-gc/gc.exp      |   6 +++
 ld/testsuite/ld-gc/pr19161.d   |   2 +-
 ld/testsuite/ld-gc/pr20022.d   |  11 ++++
 ld/testsuite/ld-gc/pr20022a.s  |   8 +++
 ld/testsuite/ld-gc/pr20022b.s  |   8 +++
 ld/testsuite/ld-gc/start.d     |   2 +-
 ld/testsuite/ld-x86-64/lea1a.d |   2 +-
 ld/testsuite/ld-x86-64/lea1b.d |   2 +-
 ld/testsuite/ld-x86-64/lea1d.d |   2 +-
 ld/testsuite/ld-x86-64/lea1e.d |   2 +-
 37 files changed, 394 insertions(+), 172 deletions(-)
 create mode 100644 ld/testsuite/ld-elf/pr21562a.d
 create mode 100644 ld/testsuite/ld-elf/pr21562a.s
 create mode 100644 ld/testsuite/ld-elf/pr21562a.t
 create mode 100644 ld/testsuite/ld-elf/pr21562b.d
 create mode 100644 ld/testsuite/ld-elf/pr21562b.s
 create mode 100644 ld/testsuite/ld-elf/pr21562b.t
 create mode 100644 ld/testsuite/ld-elf/pr21562c.d
 create mode 100644 ld/testsuite/ld-elf/pr21562c.t
 create mode 100644 ld/testsuite/ld-elf/pr21562d.d
 create mode 100644 ld/testsuite/ld-elf/pr21562d.t
 create mode 100644 ld/testsuite/ld-elf/pr21562e.d
 create mode 100644 ld/testsuite/ld-elf/pr21562f.d
 create mode 100644 ld/testsuite/ld-elf/pr21562g.d
 create mode 100644 ld/testsuite/ld-elf/pr21562h.d
 create mode 100644 ld/testsuite/ld-elf/pr21562i.d
 create mode 100644 ld/testsuite/ld-elf/pr21562j.d
 create mode 100644 ld/testsuite/ld-elf/pr21562k.d
 create mode 100644 ld/testsuite/ld-elf/pr21562l.d
 create mode 100644 ld/testsuite/ld-elf/pr21562m.d
 create mode 100644 ld/testsuite/ld-elf/pr21562n.d
 create mode 100644 ld/testsuite/ld-gc/pr20022.d
 create mode 100644 ld/testsuite/ld-gc/pr20022a.s
 create mode 100644 ld/testsuite/ld-gc/pr20022b.s

diff --git a/bfd/elf-bfd.h b/bfd/elf-bfd.h
index 567b63a..fe15b93 100644
--- a/bfd/elf-bfd.h
+++ b/bfd/elf-bfd.h
@@ -213,6 +213,9 @@ struct elf_link_hash_entry
   /* Symbol is defined by a shared library with non-default visibility
      in a read/write section.  */
   unsigned int protected_def : 1;
+  /* Symbol is __start_SECNAME or __stop_SECNAME to mark section
+     SECNAME.  */
+  unsigned int start_stop : 1;
 
   /* String table index in .dynstr if this is a dynamic symbol.  */
   unsigned long dynstr_index;
@@ -243,7 +246,15 @@ struct elf_link_hash_entry
     struct bfd_elf_version_tree *vertree;
   } verinfo;
 
-  struct elf_link_virtual_table_entry *vtable;
+  union
+  {
+    /* For __start_SECNAME and __stop_SECNAME symbols, record the first
+       input section whose section name is SECNAME.  */
+    asection *start_stop_section;
+
+    /* Vtable information. */
+    struct elf_link_virtual_table_entry *vtable;
+  } u2;
 };
 
 /* Will references to this symbol always reference the symbol
@@ -2445,9 +2456,6 @@ extern bfd_boolean bfd_elf_gc_common_finalize_got_offsets
 extern bfd_boolean bfd_elf_gc_common_final_link
   (bfd *, struct bfd_link_info *);
 
-extern asection *_bfd_elf_is_start_stop
-  (const struct bfd_link_info *, struct elf_link_hash_entry *);
-
 extern bfd_boolean bfd_elf_reloc_symbol_deleted_p
   (bfd_vma, void *);
 
diff --git a/bfd/elf32-i386.c b/bfd/elf32-i386.c
index f9142a9..6636551 100644
--- a/bfd/elf32-i386.c
+++ b/bfd/elf32-i386.c
@@ -1787,11 +1787,13 @@ convert_branch:
 	return TRUE;
 
       /* def_regular is set by an assignment in a linker script in
-	 bfd_elf_record_link_assignment.  */
-      if ((h->def_regular
-	   || h->root.type == bfd_link_hash_defined
-	   || h->root.type == bfd_link_hash_defweak)
-	  && SYMBOL_REFERENCES_LOCAL (link_info, h))
+	 bfd_elf_record_link_assignment.  start_stop is set on
+	 __start_SECNAME/__stop_SECNAME which mark section SECNAME.  */
+      if (h->start_stop
+	  || ((h->def_regular
+	       || h->root.type == bfd_link_hash_defined
+	       || h->root.type == bfd_link_hash_defweak)
+	      && SYMBOL_REFERENCES_LOCAL (link_info, h)))
 	{
 convert_load:
 	  if (opcode == 0x8b)
diff --git a/bfd/elf64-x86-64.c b/bfd/elf64-x86-64.c
index 5306019..ab6f068 100644
--- a/bfd/elf64-x86-64.c
+++ b/bfd/elf64-x86-64.c
@@ -1920,21 +1920,25 @@ elf_x86_64_convert_load_reloc (bfd *abfd, asection *sec,
 	}
       /* Avoid optimizing GOTPCREL relocations againt _DYNAMIC since
 	 ld.so may use its link-time address.  */
-      else if ((h->def_regular
-		|| h->root.type == bfd_link_hash_defined
-		|| h->root.type == bfd_link_hash_defweak)
-	       && h != htab->elf.hdynamic
-	       && SYMBOL_REFERENCES_LOCAL (link_info, h))
+      else if (h->start_stop
+	       || ((h->def_regular
+		    || h->root.type == bfd_link_hash_defined
+		    || h->root.type == bfd_link_hash_defweak)
+		   && h != htab->elf.hdynamic
+		   && SYMBOL_REFERENCES_LOCAL (link_info, h)))
 	{
 	  /* bfd_link_hash_new or bfd_link_hash_undefined is
 	     set by an assignment in a linker script in
-	     bfd_elf_record_link_assignment.   */
-	  if (h->def_regular
-	      && (h->root.type == bfd_link_hash_new
-		  || h->root.type == bfd_link_hash_undefined
-		  || ((h->root.type == bfd_link_hash_defined
-		       || h->root.type == bfd_link_hash_defweak)
-		      && h->root.u.def.section == bfd_und_section_ptr)))
+	     bfd_elf_record_link_assignment.  start_stop is set
+	     on __start_SECNAME/__stop_SECNAME which mark section
+	     SECNAME.  */
+	  if (h->start_stop
+	      || (h->def_regular
+		  && (h->root.type == bfd_link_hash_new
+		      || h->root.type == bfd_link_hash_undefined
+		      || ((h->root.type == bfd_link_hash_defined
+			   || h->root.type == bfd_link_hash_defweak)
+			  && h->root.u.def.section == bfd_und_section_ptr))))
 	    {
 	      /* Skip since R_X86_64_32/R_X86_64_32S may overflow.  */
 	      if (require_reloc_pc32)
diff --git a/bfd/elflink.c b/bfd/elflink.c
index 1b447bb..d745abf 100644
--- a/bfd/elflink.c
+++ b/bfd/elflink.c
@@ -12683,55 +12683,6 @@ elf_gc_mark_debug_section (asection *sec ATTRIBUTE_UNUSED,
   return NULL;
 }
 
-/* For undefined __start_<name> and __stop_<name> symbols, return the
-   first input section matching <name>.  Return NULL otherwise.  */
-
-asection *
-_bfd_elf_is_start_stop (const struct bfd_link_info *info,
-			struct elf_link_hash_entry *h)
-{
-  asection *s;
-  const char *sec_name;
-
-  if (h->root.type != bfd_link_hash_undefined
-      && h->root.type != bfd_link_hash_undefweak)
-    return NULL;
-
-  s = h->root.u.undef.section;
-  if (s != NULL)
-    {
-      if (s == (asection *) 0 - 1)
-	return NULL;
-      return s;
-    }
-
-  sec_name = NULL;
-  if (strncmp (h->root.root.string, "__start_", 8) == 0)
-    sec_name = h->root.root.string + 8;
-  else if (strncmp (h->root.root.string, "__stop_", 7) == 0)
-    sec_name = h->root.root.string + 7;
-
-  if (sec_name != NULL && *sec_name != '\0')
-    {
-      bfd *i;
-
-      for (i = info->input_bfds; i != NULL; i = i->link.next)
-	{
-	  s = bfd_get_section_by_name (i, sec_name);
-	  if (s != NULL)
-	    {
-	      h->root.u.undef.section = s;
-	      break;
-	    }
-	}
-    }
-
-  if (s == NULL)
-    h->root.u.undef.section = (asection *) 0 - 1;
-
-  return s;
-}
-
 /* COOKIE->rel describes a relocation against section SEC, which is
    a section we've decided to keep.  Return the section that contains
    the relocation symbol, or NULL if no section contains it.  */
@@ -12777,10 +12728,9 @@ _bfd_elf_gc_mark_rsec (struct bfd_link_info *info, asection *sec,
 	     or __stop_XXX symbols.  The linker will later define such
 	     symbols for orphan input sections that have a name
 	     representable as a C identifier.  */
-	  asection *s = _bfd_elf_is_start_stop (info, h);
-
-	  if (s != NULL)
+	  if (h->start_stop)
 	    {
+	      asection *s = h->u2.start_stop_section;
 	      *start_stop = !s->gc_mark;
 	      return s;
 	    }
@@ -13121,26 +13071,28 @@ static bfd_boolean
 elf_gc_propagate_vtable_entries_used (struct elf_link_hash_entry *h, void *okp)
 {
   /* Those that are not vtables.  */
-  if (h->vtable == NULL || h->vtable->parent == NULL)
+  if (h->start_stop
+      || h->u2.vtable == NULL
+      || h->u2.vtable->parent == NULL)
     return TRUE;
 
   /* Those vtables that do not have parents, we cannot merge.  */
-  if (h->vtable->parent == (struct elf_link_hash_entry *) -1)
+  if (h->u2.vtable->parent == (struct elf_link_hash_entry *) -1)
     return TRUE;
 
   /* If we've already been done, exit.  */
-  if (h->vtable->used && h->vtable->used[-1])
+  if (h->u2.vtable->used && h->u2.vtable->used[-1])
     return TRUE;
 
   /* Make sure the parent's table is up to date.  */
-  elf_gc_propagate_vtable_entries_used (h->vtable->parent, okp);
+  elf_gc_propagate_vtable_entries_used (h->u2.vtable->parent, okp);
 
-  if (h->vtable->used == NULL)
+  if (h->u2.vtable->used == NULL)
     {
       /* None of this table's entries were referenced.  Re-use the
 	 parent's table.  */
-      h->vtable->used = h->vtable->parent->vtable->used;
-      h->vtable->size = h->vtable->parent->vtable->size;
+      h->u2.vtable->used = h->u2.vtable->parent->u2.vtable->used;
+      h->u2.vtable->size = h->u2.vtable->parent->u2.vtable->size;
     }
   else
     {
@@ -13148,9 +13100,9 @@ elf_gc_propagate_vtable_entries_used (struct elf_link_hash_entry *h, void *okp)
       bfd_boolean *cu, *pu;
 
       /* Or the parent's entries into ours.  */
-      cu = h->vtable->used;
+      cu = h->u2.vtable->used;
       cu[-1] = TRUE;
-      pu = h->vtable->parent->vtable->used;
+      pu = h->u2.vtable->parent->u2.vtable->used;
       if (pu != NULL)
 	{
 	  const struct elf_backend_data *bed;
@@ -13158,7 +13110,7 @@ elf_gc_propagate_vtable_entries_used (struct elf_link_hash_entry *h, void *okp)
 
 	  bed = get_elf_backend_data (h->root.u.def.section->owner);
 	  log_file_align = bed->s->log_file_align;
-	  n = h->vtable->parent->vtable->size >> log_file_align;
+	  n = h->u2.vtable->parent->u2.vtable->size >> log_file_align;
 	  while (n--)
 	    {
 	      if (*pu)
@@ -13183,7 +13135,9 @@ elf_gc_smash_unused_vtentry_relocs (struct elf_link_hash_entry *h, void *okp)
 
   /* Take care of both those symbols that do not describe vtables as
      well as those that are not loaded.  */
-  if (h->vtable == NULL || h->vtable->parent == NULL)
+  if (h->start_stop
+      || h->u2.vtable == NULL
+      || h->u2.vtable->parent == NULL)
     return TRUE;
 
   BFD_ASSERT (h->root.type == bfd_link_hash_defined
@@ -13205,11 +13159,11 @@ elf_gc_smash_unused_vtentry_relocs (struct elf_link_hash_entry *h, void *okp)
     if (rel->r_offset >= hstart && rel->r_offset < hend)
       {
 	/* If the entry is in use, do nothing.  */
-	if (h->vtable->used
-	    && (rel->r_offset - hstart) < h->vtable->size)
+	if (h->u2.vtable->used
+	    && (rel->r_offset - hstart) < h->u2.vtable->size)
 	  {
 	    bfd_vma entry = (rel->r_offset - hstart) >> log_file_align;
-	    if (h->vtable->used[entry])
+	    if (h->u2.vtable->used[entry])
 	      continue;
 	  }
 	/* Otherwise, kill it.  */
@@ -13433,11 +13387,11 @@ bfd_elf_gc_record_vtinherit (bfd *abfd,
   return FALSE;
 
  win:
-  if (!child->vtable)
+  if (!child->u2.vtable)
     {
-      child->vtable = ((struct elf_link_virtual_table_entry *)
-		       bfd_zalloc (abfd, sizeof (*child->vtable)));
-      if (!child->vtable)
+      child->u2.vtable = ((struct elf_link_virtual_table_entry *)
+			  bfd_zalloc (abfd, sizeof (*child->u2.vtable)));
+      if (!child->u2.vtable)
 	return FALSE;
     }
   if (!h)
@@ -13447,10 +13401,10 @@ bfd_elf_gc_record_vtinherit (bfd *abfd,
 	 would be bad.  It isn't worth paging in the local symbols to be
 	 sure though; that case should simply be handled by the assembler.  */
 
-      child->vtable->parent = (struct elf_link_hash_entry *) -1;
+      child->u2.vtable->parent = (struct elf_link_hash_entry *) -1;
     }
   else
-    child->vtable->parent = h;
+    child->u2.vtable->parent = h;
 
   return TRUE;
 }
@@ -13466,18 +13420,18 @@ bfd_elf_gc_record_vtentry (bfd *abfd ATTRIBUTE_UNUSED,
   const struct elf_backend_data *bed = get_elf_backend_data (abfd);
   unsigned int log_file_align = bed->s->log_file_align;
 
-  if (!h->vtable)
+  if (!h->u2.vtable)
     {
-      h->vtable = ((struct elf_link_virtual_table_entry *)
-		   bfd_zalloc (abfd, sizeof (*h->vtable)));
-      if (!h->vtable)
+      h->u2.vtable = ((struct elf_link_virtual_table_entry *)
+		      bfd_zalloc (abfd, sizeof (*h->u2.vtable)));
+      if (!h->u2.vtable)
 	return FALSE;
     }
 
-  if (addend >= h->vtable->size)
+  if (addend >= h->u2.vtable->size)
     {
       size_t size, bytes, file_align;
-      bfd_boolean *ptr = h->vtable->used;
+      bfd_boolean *ptr = h->u2.vtable->used;
 
       /* While the symbol is undefined, we have to be prepared to handle
 	 a zero size.  */
@@ -13508,7 +13462,7 @@ bfd_elf_gc_record_vtentry (bfd *abfd ATTRIBUTE_UNUSED,
 	    {
 	      size_t oldbytes;
 
-	      oldbytes = (((h->vtable->size >> log_file_align) + 1)
+	      oldbytes = (((h->u2.vtable->size >> log_file_align) + 1)
 			  * sizeof (bfd_boolean));
 	      memset (((char *) ptr) + oldbytes, 0, bytes - oldbytes);
 	    }
@@ -13520,11 +13474,11 @@ bfd_elf_gc_record_vtentry (bfd *abfd ATTRIBUTE_UNUSED,
 	return FALSE;
 
       /* And arrange for that done flag to be at index -1.  */
-      h->vtable->used = ptr + 1;
-      h->vtable->size = size;
+      h->u2.vtable->used = ptr + 1;
+      h->u2.vtable->size = size;
     }
 
-  h->vtable->used[addend >> log_file_align] = TRUE;
+  h->u2.vtable->used[addend >> log_file_align] = TRUE;
 
   return TRUE;
 }
diff --git a/ld/emultempl/elf32.em b/ld/emultempl/elf32.em
index 0260b7a..9468f7d 100644
--- a/ld/emultempl/elf32.em
+++ b/ld/emultempl/elf32.em
@@ -1216,6 +1216,9 @@ gld${EMULATION_NAME}_after_open (void)
 {
   struct bfd_link_needed_list *needed, *l;
   struct elf_link_hash_table *htab;
+  asection *s;
+  bfd *abfd;
+  char leading_char;
 
   after_open_default ();
 
@@ -1239,8 +1242,6 @@ gld${EMULATION_NAME}_after_open (void)
 
   if (emit_note_gnu_build_id != NULL)
     {
-      bfd *abfd;
-
       /* Find an ELF input.  */
       for (abfd = link_info.input_bfds;
 	   abfd != (bfd *) NULL; abfd = abfd->link.next)
@@ -1276,11 +1277,66 @@ gld${EMULATION_NAME}_after_open (void)
       return;
     }
 
+  leading_char = bfd_get_symbol_leading_char (link_info.output_bfd);
+
+  /* Check for input sections whose names match references to
+     __start_SECNAME or __stop_SECNAME symbols.  Mark the matched
+     symbols as hidden and set start_stop for garbage collection.  */
+  for (abfd = link_info.input_bfds; abfd; abfd = abfd->link.next)
+    for (s = abfd->sections; s; s = s->next)
+      {
+	const char *name = bfd_get_section_name (abfd, s);
+	const char *ps;
+
+	for (ps = name; *ps != '\0'; ps++)
+	  if (!ISALNUM ((unsigned char) *ps) && *ps != '_')
+	    break;
+	if (*ps == '\0')
+	  {
+	    struct elf_link_hash_entry *h;
+	    char *symbol = (char *) xmalloc (ps - name
+					     + sizeof "__start_" + 1);
+
+	    symbol[0] = leading_char;
+	    sprintf (symbol + (leading_char != 0), "__start_%s", name);
+	    h = elf_link_hash_lookup (elf_hash_table (&link_info),
+				      symbol, FALSE, FALSE, TRUE);
+	    if (h != NULL
+		&& (h->root.type == bfd_link_hash_undefined
+		    || h->root.type == bfd_link_hash_undefweak)
+		&& h->u2.start_stop_section == NULL)
+	      {
+		h->start_stop = 1;
+		h->u2.start_stop_section = s;
+		_bfd_elf_link_hash_hide_symbol (&link_info, h, TRUE);
+		if (ELF_ST_VISIBILITY (h->other) != STV_INTERNAL)
+		  h->other = ((h->other & ~ELF_ST_VISIBILITY (-1))
+			      | STV_HIDDEN);
+	      }
+
+	    symbol[0] = leading_char;
+	    sprintf (symbol + (leading_char != 0), "__stop_%s", name);
+	    h = elf_link_hash_lookup (elf_hash_table (&link_info),
+				      symbol, FALSE, FALSE, TRUE);
+	    if (h != NULL
+		&& (h->root.type == bfd_link_hash_undefined
+		    || h->root.type == bfd_link_hash_undefweak)
+		&& h->u2.start_stop_section == NULL)
+	      {
+		h->start_stop = 1;
+		h->u2.start_stop_section = s;
+		_bfd_elf_link_hash_hide_symbol (&link_info, h, TRUE);
+		if (ELF_ST_VISIBILITY (h->other) != STV_INTERNAL)
+		  h->other = ((h->other & ~ELF_ST_VISIBILITY (-1))
+			      | STV_HIDDEN);
+	      }
+	  }
+      }
+
   if (!link_info.traditional_format)
     {
-      bfd *abfd, *elfbfd = NULL;
+      bfd *elfbfd = NULL;
       bfd_boolean warn_eh_frame = FALSE;
-      asection *s;
       int seen_type = 0;
 
       for (abfd = link_info.input_bfds; abfd; abfd = abfd->link.next)
diff --git a/ld/ld.texinfo b/ld/ld.texinfo
index 790b52f..44ad84b 100644
--- a/ld/ld.texinfo
+++ b/ld/ld.texinfo
@@ -4657,6 +4657,14 @@ SECTIONS @{
 @end group
 @end smallexample
 
+If an output section's name is the same as the input section's name
+and is representable as a C identifier, then the linker will
+automatically @pxref{PROVIDE} two symbols: __start_SECNAME and
+__stop_SECNAME, where SECNAME is the name of the section.  These
+indicate the start address and end address of the output section
+respectively.  Note: most section names are not representable as
+C identifiers because they contain a @samp{.} character.
+
 @node Output Section Data
 @subsection Output Section Data
 @cindex data
@@ -5841,14 +5849,6 @@ The command line options @samp{--orphan-handling} and @samp{--unique}
 (@pxref{Options,,Command Line Options}) can be used to control which
 output sections an orphan is placed in.
 
-If an orphaned section's name is representable as a C identifier then
-the linker will automatically @pxref{PROVIDE} two symbols:
-__start_SECNAME and __stop_SECNAME, where SECNAME is the name of the
-section.  These indicate the start address and end address of the
-orphaned section respectively.  Note: most section names are not
-representable as C identifiers because they contain a @samp{.}
-character.
-
 @node Location Counter
 @subsection The Location Counter
 @kindex .
diff --git a/ld/ldlang.c b/ld/ldlang.c
index 252400b..69619cd 100644
--- a/ld/ldlang.c
+++ b/ld/ldlang.c
@@ -1829,8 +1829,6 @@ lang_insert_orphan (asection *s,
 		    lang_statement_list_type *add_child)
 {
   lang_statement_list_type add;
-  const char *ps;
-  lang_assignment_statement_type *start_assign;
   lang_output_section_statement_type *os;
   lang_output_section_statement_type **os_tail;
 
@@ -1852,29 +1850,6 @@ lang_insert_orphan (asection *s,
   os = lang_enter_output_section_statement (secname, address, normal_section,
 					    NULL, NULL, NULL, constraint, 0);
 
-  ps = NULL;
-  start_assign = NULL;
-  if (config.build_constructors && *os_tail == os)
-    {
-      /* If the name of the section is representable in C, then create
-	 symbols to mark the start and the end of the section.  */
-      for (ps = secname; *ps != '\0'; ps++)
-	if (!ISALNUM ((unsigned char) *ps) && *ps != '_')
-	  break;
-      if (*ps == '\0')
-	{
-	  char *symname;
-
-	  symname = (char *) xmalloc (ps - secname + sizeof "__start_" + 1);
-	  symname[0] = bfd_get_symbol_leading_char (link_info.output_bfd);
-	  sprintf (symname + (symname[0] != 0), "__start_%s", secname);
-	  start_assign
-	    = lang_add_assignment (exp_provide (symname,
-						exp_nameop (NAME, "."),
-						FALSE));
-	}
-    }
-
   if (add_child == NULL)
     add_child = &os->children;
   lang_add_section (add_child, s, NULL, os);
@@ -1894,27 +1869,6 @@ lang_insert_orphan (asection *s,
     lang_leave_output_section_statement (NULL, DEFAULT_MEMORY_REGION, NULL,
 					 NULL);
 
-  if (start_assign != NULL)
-    {
-      char *symname;
-      lang_assignment_statement_type *stop_assign;
-      bfd_vma dot;
-
-      symname = (char *) xmalloc (ps - secname + sizeof "__stop_" + 1);
-      symname[0] = bfd_get_symbol_leading_char (link_info.output_bfd);
-      sprintf (symname + (symname[0] != 0), "__stop_%s", secname);
-      stop_assign
-	= lang_add_assignment (exp_provide (symname,
-					    exp_nameop (NAME, "."),
-					    FALSE));
-      /* Evaluate the expression to define the symbol if referenced,
-	 before sizing dynamic sections.  */
-      dot = os->bfd_section->vma;
-      exp_fold_tree (start_assign->exp, os->bfd_section, &dot);
-      dot += TO_ADDR (s->size);
-      exp_fold_tree (stop_assign->exp, os->bfd_section, &dot);
-    }
-
   /* Restore the global list pointer.  */
   if (after != NULL)
     pop_stat_ptr ();
@@ -5924,21 +5878,29 @@ section_for_dot (void)
   return bfd_abs_section_ptr;
 }
 
-/* Fix any .startof. or .sizeof. symbols.  When the assemblers see the
-   operator .startof. (section_name), it produces an undefined symbol
-   .startof.section_name.  Similarly, when it sees
+/* Fix any .startof., .sizeof., __start or __stop symbols.  When the
+   assemblers see the operator .startof. (section_name), it produces
+   an undefined symbol .startof.section_name.  Similarly, when it sees
    .sizeof. (section_name), it produces an undefined symbol
-   .sizeof.section_name.  For all the output sections, we look for
-   such symbols, and set them to the correct value.  */
+   .sizeof.section_name.  Also for ELF linker, __start_XXX or __stop_XXX
+   symbols should be resolved to the start and end of section XXX.  For
+   all the output sections, we look for such symbols, and set them to
+   the correct value.  */
 
 static void
 lang_set_startof (void)
 {
   asection *s;
+  bfd_boolean is_elf;
+  char leading_char;
 
   if (bfd_link_relocatable (&link_info))
     return;
 
+  is_elf = (bfd_get_flavour (link_info.output_bfd)
+	    == bfd_target_elf_flavour);
+  leading_char = bfd_get_symbol_leading_char (link_info.output_bfd);
+
   for (s = link_info.output_bfd->sections; s != NULL; s = s->next)
     {
       const char *secname;
@@ -5966,6 +5928,35 @@ lang_set_startof (void)
 	  h->u.def.section = bfd_abs_section_ptr;
 	}
 
+      buf[0] = leading_char;
+      sprintf (buf + (buf[0] != 0), "__start_%s", secname);
+      h = bfd_link_hash_lookup (link_info.hash, buf, FALSE, FALSE,
+				TRUE);
+      if (h != NULL
+	  && (h->type == bfd_link_hash_undefined
+	      || h->type == bfd_link_hash_undefweak))
+	{
+	  h->type = bfd_link_hash_defined;
+	  h->u.def.value = 0;
+	  h->u.def.section = s;
+	  if (is_elf)
+	    ((struct elf_link_hash_entry *) h)->def_regular = 1;
+	}
+
+      buf[0] = leading_char;
+      sprintf (buf + (buf[0] != 0), "__stop_%s", secname);
+      h = bfd_link_hash_lookup (link_info.hash, buf, FALSE, FALSE,
+				TRUE);
+      if (h != NULL
+	  && (h->type == bfd_link_hash_undefined
+	      || h->type == bfd_link_hash_undefweak))
+	{
+	  h->type = bfd_link_hash_defined;
+	  h->u.def.value = TO_ADDR (s->size);
+	  h->u.def.section = s;
+	  if (is_elf)
+	    ((struct elf_link_hash_entry *) h)->def_regular = 1;
+	}
       free (buf);
     }
 }
diff --git a/ld/testsuite/ld-elf/pr21562a.d b/ld/testsuite/ld-elf/pr21562a.d
new file mode 100644
index 0000000..009dcfc
--- /dev/null
+++ b/ld/testsuite/ld-elf/pr21562a.d
@@ -0,0 +1,9 @@
+#ld: -shared -z defs --gc-sections
+#readelf: -s -S --wide
+#target: *-*-linux* *-*-gnu*
+
+#...
+  \[[ 0-9]+\] scnfoo[ \t]+PROGBITS[ \t]+[0-9a-f]+ +[0-9a-f]+ +0*10[ \t]+.*
+#...
+ +[0-9]+: +[0-9a-f]+ +[0-9a-f]+ +NOTYPE +LOCAL +DEFAULT +[0-9]+ +__start_scnfoo
+#pass
diff --git a/ld/testsuite/ld-elf/pr21562a.s b/ld/testsuite/ld-elf/pr21562a.s
new file mode 100644
index 0000000..ec36da4
--- /dev/null
+++ b/ld/testsuite/ld-elf/pr21562a.s
@@ -0,0 +1,8 @@
+        .section        scnfoo,"aw",%progbits
+        .zero 0x10
+
+        .globl  bar
+        .data
+        .type   bar, %object
+bar:
+        .dc.a   __start_scnfoo
diff --git a/ld/testsuite/ld-elf/pr21562a.t b/ld/testsuite/ld-elf/pr21562a.t
new file mode 100644
index 0000000..5e05ab3
--- /dev/null
+++ b/ld/testsuite/ld-elf/pr21562a.t
@@ -0,0 +1,3 @@
+SECTIONS {
+	scnfoo : { *(scnfoo) }
+}
diff --git a/ld/testsuite/ld-elf/pr21562b.d b/ld/testsuite/ld-elf/pr21562b.d
new file mode 100644
index 0000000..a03dbad
--- /dev/null
+++ b/ld/testsuite/ld-elf/pr21562b.d
@@ -0,0 +1,9 @@
+#ld: -shared -z defs --gc-sections
+#readelf: -s -S --wide
+#target: *-*-linux* *-*-gnu*
+
+#...
+  \[[ 0-9]+\] scnfoo[ \t]+PROGBITS[ \t]+[0-9a-f]+ +[0-9a-f]+ +0*10[ \t]+.*
+#...
+ +[0-9]+: +[0-9a-f]+ +[0-9a-f]+ +NOTYPE +LOCAL +DEFAULT +[0-9]+ +__stop_scnfoo
+#pass
diff --git a/ld/testsuite/ld-elf/pr21562b.s b/ld/testsuite/ld-elf/pr21562b.s
new file mode 100644
index 0000000..1732ee2
--- /dev/null
+++ b/ld/testsuite/ld-elf/pr21562b.s
@@ -0,0 +1,8 @@
+        .section        scnfoo,"aw",%progbits
+        .zero 0x10
+
+        .globl  bar
+        .data
+        .type   bar, %object
+bar:
+        .dc.a   __stop_scnfoo
diff --git a/ld/testsuite/ld-elf/pr21562b.t b/ld/testsuite/ld-elf/pr21562b.t
new file mode 100644
index 0000000..b30b521
--- /dev/null
+++ b/ld/testsuite/ld-elf/pr21562b.t
@@ -0,0 +1,5 @@
+SECTIONS {
+	PROVIDE (__start_scnfoo = .);
+	scnfoo : { *(scnfoo) }
+	PROVIDE (__stop_scnfoo = .);
+}
diff --git a/ld/testsuite/ld-elf/pr21562c.d b/ld/testsuite/ld-elf/pr21562c.d
new file mode 100644
index 0000000..9de035f
--- /dev/null
+++ b/ld/testsuite/ld-elf/pr21562c.d
@@ -0,0 +1,10 @@
+#source: pr21562a.s
+#ld: -shared -z defs --gc-sections -T pr21562a.t
+#readelf: -s -S --wide
+#target: *-*-linux* *-*-gnu*
+
+#...
+  \[[ 0-9]+\] scnfoo[ \t]+PROGBITS[ \t]+[0-9a-f]+ +[0-9a-f]+ +0*10[ \t]+.*
+#...
+ +[0-9]+: +[0-9a-f]+ +[0-9a-f]+ +NOTYPE +LOCAL +DEFAULT +[0-9]+ +__start_scnfoo
+#pass
diff --git a/ld/testsuite/ld-elf/pr21562c.t b/ld/testsuite/ld-elf/pr21562c.t
new file mode 100644
index 0000000..f9cb901
--- /dev/null
+++ b/ld/testsuite/ld-elf/pr21562c.t
@@ -0,0 +1,7 @@
+SECTIONS {
+    .foo : {
+	PROVIDE (__start_scnfoo = .);
+	*(scnfoo)
+	PROVIDE (__stop_scnfoo = .);
+    }
+}
diff --git a/ld/testsuite/ld-elf/pr21562d.d b/ld/testsuite/ld-elf/pr21562d.d
new file mode 100644
index 0000000..e5344ef
--- /dev/null
+++ b/ld/testsuite/ld-elf/pr21562d.d
@@ -0,0 +1,10 @@
+#source: pr21562b.s
+#ld: -shared -z defs --gc-sections -T pr21562a.t
+#readelf: -s -S --wide
+#target: *-*-linux* *-*-gnu*
+
+#...
+  \[[ 0-9]+\] scnfoo[ \t]+PROGBITS[ \t]+[0-9a-f]+ +[0-9a-f]+ +0*10[ \t]+.*
+#...
+ +[0-9]+: +[0-9a-f]+ +[0-9a-f]+ +NOTYPE +LOCAL +DEFAULT +[0-9]+ +__stop_scnfoo
+#pass
diff --git a/ld/testsuite/ld-elf/pr21562d.t b/ld/testsuite/ld-elf/pr21562d.t
new file mode 100644
index 0000000..c0cea61
--- /dev/null
+++ b/ld/testsuite/ld-elf/pr21562d.t
@@ -0,0 +1,5 @@
+SECTIONS {
+	PROVIDE (__start_scnfoo = .);
+	.foo : { *(scnfoo) }
+	PROVIDE (__stop_scnfoo = .);
+}
diff --git a/ld/testsuite/ld-elf/pr21562e.d b/ld/testsuite/ld-elf/pr21562e.d
new file mode 100644
index 0000000..afaf7e5
--- /dev/null
+++ b/ld/testsuite/ld-elf/pr21562e.d
@@ -0,0 +1,10 @@
+#source: pr21562a.s
+#ld: -shared -z defs
+#readelf: -s -S --wide
+#target: *-*-linux* *-*-gnu*
+
+#...
+  \[[ 0-9]+\] scnfoo[ \t]+PROGBITS[ \t]+[0-9a-f]+ +[0-9a-f]+ +0*10[ \t]+.*
+#...
+ +[0-9]+: +[0-9a-f]+ +[0-9a-f]+ +NOTYPE +LOCAL +DEFAULT +[0-9]+ +__start_scnfoo
+#pass
diff --git a/ld/testsuite/ld-elf/pr21562f.d b/ld/testsuite/ld-elf/pr21562f.d
new file mode 100644
index 0000000..b9c324a
--- /dev/null
+++ b/ld/testsuite/ld-elf/pr21562f.d
@@ -0,0 +1,10 @@
+#source: pr21562b.s
+#ld: -shared -z defs
+#readelf: -s -S --wide
+#target: *-*-linux* *-*-gnu*
+
+#...
+  \[[ 0-9]+\] scnfoo[ \t]+PROGBITS[ \t]+[0-9a-f]+ +[0-9a-f]+ +0*10[ \t]+.*
+#...
+ +[0-9]+: +[0-9a-f]+ +[0-9a-f]+ +NOTYPE +LOCAL +DEFAULT +[0-9]+ +__stop_scnfoo
+#pass
diff --git a/ld/testsuite/ld-elf/pr21562g.d b/ld/testsuite/ld-elf/pr21562g.d
new file mode 100644
index 0000000..a813594
--- /dev/null
+++ b/ld/testsuite/ld-elf/pr21562g.d
@@ -0,0 +1,10 @@
+#source: pr21562a.s
+#ld: -shared -z defs -T pr21562a.t
+#readelf: -s -S --wide
+#target: *-*-linux* *-*-gnu*
+
+#...
+  \[[ 0-9]+\] scnfoo[ \t]+PROGBITS[ \t]+[0-9a-f]+ +[0-9a-f]+ +0*10[ \t]+.*
+#...
+ +[0-9]+: +[0-9a-f]+ +[0-9a-f]+ +NOTYPE +LOCAL +DEFAULT +[0-9]+ +__start_scnfoo
+#pass
diff --git a/ld/testsuite/ld-elf/pr21562h.d b/ld/testsuite/ld-elf/pr21562h.d
new file mode 100644
index 0000000..6adabd7
--- /dev/null
+++ b/ld/testsuite/ld-elf/pr21562h.d
@@ -0,0 +1,10 @@
+#source: pr21562b.s
+#ld: -shared -z defs -T pr21562a.t
+#readelf: -s -S --wide
+#target: *-*-linux* *-*-gnu*
+
+#...
+  \[[ 0-9]+\] scnfoo[ \t]+PROGBITS[ \t]+[0-9a-f]+ +[0-9a-f]+ +0*10[ \t]+.*
+#...
+ +[0-9]+: +[0-9a-f]+ +[0-9a-f]+ +NOTYPE +LOCAL +DEFAULT +[0-9]+ +__stop_scnfoo
+#pass
diff --git a/ld/testsuite/ld-elf/pr21562i.d b/ld/testsuite/ld-elf/pr21562i.d
new file mode 100644
index 0000000..49eb2ec
--- /dev/null
+++ b/ld/testsuite/ld-elf/pr21562i.d
@@ -0,0 +1,10 @@
+#source: pr21562a.s
+#ld: -shared -z defs --gc-sections -T pr21562b.t
+#readelf: -s -S --wide
+#target: *-*-linux* *-*-gnu*
+
+#...
+  \[[ 0-9]+\] scnfoo[ \t]+PROGBITS[ \t]+[0-9a-f]+ +[0-9a-f]+ +0*10[ \t]+.*
+#...
+ +[0-9]+: +[0-9a-f]+ +[0-9a-f]+ +NOTYPE +LOCAL +DEFAULT +[0-9]+ +__start_scnfoo
+#pass
diff --git a/ld/testsuite/ld-elf/pr21562j.d b/ld/testsuite/ld-elf/pr21562j.d
new file mode 100644
index 0000000..14bb035
--- /dev/null
+++ b/ld/testsuite/ld-elf/pr21562j.d
@@ -0,0 +1,10 @@
+#source: pr21562b.s
+#ld: -shared -z defs --gc-sections -T pr21562b.t
+#readelf: -s -S --wide
+#target: *-*-linux* *-*-gnu*
+
+#...
+  \[[ 0-9]+\] scnfoo[ \t]+PROGBITS[ \t]+[0-9a-f]+ +[0-9a-f]+ +0*10[ \t]+.*
+#...
+ +[0-9]+: +[0-9a-f]+ +[0-9a-f]+ +NOTYPE +LOCAL +DEFAULT +[0-9]+ +__stop_scnfoo
+#pass
diff --git a/ld/testsuite/ld-elf/pr21562k.d b/ld/testsuite/ld-elf/pr21562k.d
new file mode 100644
index 0000000..1bf1e93
--- /dev/null
+++ b/ld/testsuite/ld-elf/pr21562k.d
@@ -0,0 +1,10 @@
+#source: pr21562a.s
+#ld: -shared -z defs --gc-sections -T pr21562c.t
+#readelf: -s -S --wide
+#target: *-*-linux* *-*-gnu*
+
+#...
+  \[[ 0-9]+\] \.foo[ \t]+PROGBITS[ \t]+[0-9a-f]+ +[0-9a-f]+ +0*10[ \t]+.*
+#...
+ +[0-9]+: +[0-9a-f]+ +[0-9a-f]+ +NOTYPE +LOCAL +DEFAULT +[0-9]+ +__start_scnfoo
+#pass
diff --git a/ld/testsuite/ld-elf/pr21562l.d b/ld/testsuite/ld-elf/pr21562l.d
new file mode 100644
index 0000000..8297ec2
--- /dev/null
+++ b/ld/testsuite/ld-elf/pr21562l.d
@@ -0,0 +1,10 @@
+#source: pr21562b.s
+#ld: -shared -z defs --gc-sections -T pr21562c.t
+#readelf: -s -S --wide
+#target: *-*-linux* *-*-gnu*
+
+#...
+  \[[ 0-9]+\] \.foo[ \t]+PROGBITS[ \t]+[0-9a-f]+ +[0-9a-f]+ +0*10[ \t]+.*
+#...
+ +[0-9]+: +[0-9a-f]+ +[0-9a-f]+ +NOTYPE +LOCAL +DEFAULT +[0-9]+ +__stop_scnfoo
+#pass
diff --git a/ld/testsuite/ld-elf/pr21562m.d b/ld/testsuite/ld-elf/pr21562m.d
new file mode 100644
index 0000000..34f8df0
--- /dev/null
+++ b/ld/testsuite/ld-elf/pr21562m.d
@@ -0,0 +1,10 @@
+#source: pr21562a.s
+#ld: -shared -z defs --gc-sections -T pr21562d.t
+#readelf: -s -S --wide
+#target: *-*-linux* *-*-gnu*
+
+#...
+  \[[ 0-9]+\] \.foo[ \t]+PROGBITS[ \t]+[0-9a-f]+ +[0-9a-f]+ +0*10[ \t]+.*
+#...
+ +[0-9]+: +[0-9a-f]+ +[0-9a-f]+ +NOTYPE +LOCAL +DEFAULT +[0-9]+ +__start_scnfoo
+#pass
diff --git a/ld/testsuite/ld-elf/pr21562n.d b/ld/testsuite/ld-elf/pr21562n.d
new file mode 100644
index 0000000..e4b1919
--- /dev/null
+++ b/ld/testsuite/ld-elf/pr21562n.d
@@ -0,0 +1,10 @@
+#source: pr21562b.s
+#ld: -shared -z defs --gc-sections -T pr21562d.t
+#readelf: -s -S --wide
+#target: *-*-linux* *-*-gnu*
+
+#...
+  \[[ 0-9]+\] \.foo[ \t]+PROGBITS[ \t]+[0-9a-f]+ +[0-9a-f]+ +0*10[ \t]+.*
+#...
+ +[0-9]+: +[0-9a-f]+ +[0-9a-f]+ +NOTYPE +LOCAL +DEFAULT +[0-9]+ +__stop_scnfoo
+#pass
diff --git a/ld/testsuite/ld-gc/gc.exp b/ld/testsuite/ld-gc/gc.exp
index ba5c46b..364c73b 100644
--- a/ld/testsuite/ld-gc/gc.exp
+++ b/ld/testsuite/ld-gc/gc.exp
@@ -119,6 +119,12 @@ if { [is_elf_format] && [check_shared_lib_support] } then {
 	run_dump_test "personality"
     }
     run_dump_test "pr18223"
+    if {![ld_assemble_flags $as $gasopt $srcdir/$subdir/pr20022a.s tmpdir/pr20022a.o]
+	|| ![ld_link $ld tmpdir/pr20022.so "-shared --gc-sections tmpdir/pr20022a.o"] } then {
+	fail pr20022
+    } else {
+	run_dump_test "pr20022"
+    }
 }
 
 if { [is_remote host] || [which $CC] != 0 } {
diff --git a/ld/testsuite/ld-gc/pr19161.d b/ld/testsuite/ld-gc/pr19161.d
index c36e663..baee8da 100644
--- a/ld/testsuite/ld-gc/pr19161.d
+++ b/ld/testsuite/ld-gc/pr19161.d
@@ -6,5 +6,5 @@
 #xfail: mips64vr-*-* msp430-*-* powerpc*-*-eabivle rl78-*-* rx-*-* sh*-*-*
 
 #...
-0*[1-9a-f]+[0-9a-f]*[ 	](D)[ 	]_*__start_my_section
+0*[1-9a-f]+[0-9a-f]*[ 	](d|D)[ 	]_*__start_my_section
 #...
diff --git a/ld/testsuite/ld-gc/pr20022.d b/ld/testsuite/ld-gc/pr20022.d
new file mode 100644
index 0000000..b51ec19
--- /dev/null
+++ b/ld/testsuite/ld-gc/pr20022.d
@@ -0,0 +1,11 @@
+#source: pr20022b.s
+#ld: --gc-sections -e _start tmpdir/pr20022.so
+#readelf: -SsW
+#target: *-*-linux* *-*-gnu*
+#notarget: *-*-*aout *-*-*oldld frv-*-linux* metag-*-linux*
+
+#...
+  \[[ 0-9]+\] _foo[ \t]+PROGBITS[ \t]+[0-9a-f]+ +[0-9a-f]+ +[0-9a-f]+[ \t]+.*
+#...
+ +[0-9]+: +[0-9a-f]+ +[0-9a-f]+ +NOTYPE +LOCAL +DEFAULT +[0-9]+ +__start__foo
+#pass
diff --git a/ld/testsuite/ld-gc/pr20022a.s b/ld/testsuite/ld-gc/pr20022a.s
new file mode 100644
index 0000000..6bd346f
--- /dev/null
+++ b/ld/testsuite/ld-gc/pr20022a.s
@@ -0,0 +1,8 @@
+	.data
+	.globl bar
+	.type bar,%object
+bar:
+	.dc.a	__start__foo
+	.section _foo,"aw",%progbits
+foo:
+	.ascii "This is bar"
diff --git a/ld/testsuite/ld-gc/pr20022b.s b/ld/testsuite/ld-gc/pr20022b.s
new file mode 100644
index 0000000..2306c59
--- /dev/null
+++ b/ld/testsuite/ld-gc/pr20022b.s
@@ -0,0 +1,8 @@
+	.text
+	.globl _start
+_start:
+	.dc.a	__start__foo
+	.dc.a	bar
+	.section _foo,"aw",%progbits
+foo:
+	.ascii "This is foo"
diff --git a/ld/testsuite/ld-gc/start.d b/ld/testsuite/ld-gc/start.d
index 18e74c1..9113b48 100644
--- a/ld/testsuite/ld-gc/start.d
+++ b/ld/testsuite/ld-gc/start.d
@@ -5,5 +5,5 @@
 #notarget: *-*-*aout *-*-*oldld frv-*-linux* metag-*-linux*
 
 #...
-[0-9a-f]+ D +__start__foo
+[0-9a-f]+ d +__start__foo
 #...
diff --git a/ld/testsuite/ld-x86-64/lea1a.d b/ld/testsuite/ld-x86-64/lea1a.d
index 9b662cb..28ea4b9 100644
--- a/ld/testsuite/ld-x86-64/lea1a.d
+++ b/ld/testsuite/ld-x86-64/lea1a.d
@@ -15,5 +15,5 @@ Disassembly of section .text:
 [ 	]*[a-f0-9]+:	48 8d 05 ([0-9a-f]{2} ){4} *	lea    -0x[a-f0-9]+\(%rip\),%rax        # [a-f0-9]+ <foo>
 [ 	]*[a-f0-9]+:	4c 8d 1d ([0-9a-f]{2} ){4} *	lea    0x[a-f0-9]+\(%rip\),%r11        # [a-f0-9]+ <bar>
 [ 	]*[a-f0-9]+:	48 8d 05 ([0-9a-f]{2} ){4} *	lea    0x[a-f0-9]+\(%rip\),%rax        # [a-f0-9]+ <__start_my_section>
-[ 	]*[a-f0-9]+:	4c 8d 1d ([0-9a-f]{2} ){4} *	lea    0x[a-f0-9]+\(%rip\),%r11        # [a-f0-9]+ <__stop_my_section>
+[ 	]*[a-f0-9]+:	4c 8d 1d ([0-9a-f]{2} ){4} *	lea    0x[a-f0-9]+\(%rip\),%r11        # [a-f0-9]+ <.*>
 #pass
diff --git a/ld/testsuite/ld-x86-64/lea1b.d b/ld/testsuite/ld-x86-64/lea1b.d
index 9108149..c7873cd 100644
--- a/ld/testsuite/ld-x86-64/lea1b.d
+++ b/ld/testsuite/ld-x86-64/lea1b.d
@@ -15,5 +15,5 @@ Disassembly of section .text:
 [ 	]*[a-f0-9]+:	48 8d 05 ([0-9a-f]{2} ){4} *	lea    -0x[a-f0-9]+\(%rip\),%rax        # [a-f0-9]+ <foo>
 [ 	]*[a-f0-9]+:	4c 8d 1d ([0-9a-f]{2} ){4} *	lea    0x[a-f0-9]+\(%rip\),%r11        # [a-f0-9]+ <bar>
 [ 	]*[a-f0-9]+:	48 8d 05 ([0-9a-f]{2} ){4} *	lea    0x[a-f0-9]+\(%rip\),%rax        # [a-f0-9]+ <__start_my_section>
-[ 	]*[a-f0-9]+:	4c 8d 1d ([0-9a-f]{2} ){4} *	lea    0x[a-f0-9]+\(%rip\),%r11        # [a-f0-9]+ <__stop_my_section>
+[ 	]*[a-f0-9]+:	4c 8d 1d ([0-9a-f]{2} ){4} *	lea    0x[a-f0-9]+\(%rip\),%r11        # [a-f0-9]+ <.*>
 #pass
diff --git a/ld/testsuite/ld-x86-64/lea1d.d b/ld/testsuite/ld-x86-64/lea1d.d
index 4d708d2..70fc603 100644
--- a/ld/testsuite/ld-x86-64/lea1d.d
+++ b/ld/testsuite/ld-x86-64/lea1d.d
@@ -15,5 +15,5 @@ Disassembly of section .text:
 [ 	]*[a-f0-9]+:	48 8d 05 ([0-9a-f]{2} ){4} *	lea    -0x[a-f0-9]+\(%rip\),%rax        # [a-f0-9]+ <foo>
 [ 	]*[a-f0-9]+:	4c 8d 1d ([0-9a-f]{2} ){4} *	lea    0x[a-f0-9]+\(%rip\),%r11        # [a-f0-9]+ <bar>
 [ 	]*[a-f0-9]+:	48 8d 05 ([0-9a-f]{2} ){4} *	lea    0x[a-f0-9]+\(%rip\),%rax        # [a-f0-9]+ <__start_my_section>
-[ 	]*[a-f0-9]+:	4c 8d 1d ([0-9a-f]{2} ){4} *	lea    0x[a-f0-9]+\(%rip\),%r11        # [a-f0-9]+ <__stop_my_section>
+[ 	]*[a-f0-9]+:	4c 8d 1d ([0-9a-f]{2} ){4} *	lea    0x[a-f0-9]+\(%rip\),%r11        # [a-f0-9]+ <.*>
 #pass
diff --git a/ld/testsuite/ld-x86-64/lea1e.d b/ld/testsuite/ld-x86-64/lea1e.d
index da60137..123fcd2 100644
--- a/ld/testsuite/ld-x86-64/lea1e.d
+++ b/ld/testsuite/ld-x86-64/lea1e.d
@@ -15,5 +15,5 @@ Disassembly of section .text:
 [ 	]*[a-f0-9]+:	48 8d 05 ([0-9a-f]{2} ){4} *	lea    -0x[a-f0-9]+\(%rip\),%rax        # [a-f0-9]+ <foo>
 [ 	]*[a-f0-9]+:	4c 8d 1d ([0-9a-f]{2} ){4} *	lea    0x[a-f0-9]+\(%rip\),%r11        # [a-f0-9]+ <bar>
 [ 	]*[a-f0-9]+:	48 8d 05 ([0-9a-f]{2} ){4} *	lea    0x[a-f0-9]+\(%rip\),%rax        # [a-f0-9]+ <__start_my_section>
-[ 	]*[a-f0-9]+:	4c 8d 1d ([0-9a-f]{2} ){4} *	lea    0x[a-f0-9]+\(%rip\),%r11        # [a-f0-9]+ <__stop_my_section>
+[ 	]*[a-f0-9]+:	4c 8d 1d ([0-9a-f]{2} ){4} *	lea    0x[a-f0-9]+\(%rip\),%r11        # [a-f0-9]+ <.*>
 #pass
-- 
2.9.4


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

* Re: [PATCH] Always define referenced __start_SECNAME/__stop_SECNAME
  2017-06-13  2:10       ` H.J. Lu
@ 2017-06-13 12:26         ` Alan Modra
  2017-06-13 12:38           ` H.J. Lu
  0 siblings, 1 reply; 16+ messages in thread
From: Alan Modra @ 2017-06-13 12:26 UTC (permalink / raw)
  To: H.J. Lu; +Cc: Binutils

On Mon, Jun 12, 2017 at 07:10:47PM -0700, H.J. Lu wrote:
> On Mon, Jun 12, 2017 at 6:54 PM, Alan Modra <amodra@gmail.com> wrote:
> > On Mon, Jun 12, 2017 at 05:18:58PM -0700, H.J. Lu wrote:
> >> On Mon, Jun 12, 2017 at 4:32 PM, Alan Modra <amodra@gmail.com> wrote:
> >> > On Sat, Jun 10, 2017 at 03:46:49PM -0700, H.J. Lu wrote:
> >> >> This patch changes linker to always define referenced __start_SECNAME and
> >> >> __stop_SECNAME if the input section name is the same output section name,
> >> >> which is always true for orphaned sections, and SECNAME is a C identifier.
> >> >
> >> > I think this change is reasonable.
> >> >
> >> >> Also __start_SECNAME and __stop_SECNAME symbols are marked as hidden by
> >> >> ELF linker.
> >> >
> >> > Why is this necessary?  Also, you make another change in behaviour
> >>
> >> It is to make sure that  __start_SECNAME and __stop_SECNAME
> >> symbols     for section SECNAME in different modules are unique.
> >
> > I understand, and it would have been good if these symbols were
> > defined that way in the beginning, but they weren't.  I'm concerned
> > that if you make this change as well we will find some code that
> > relies on the symbols being dynamic.
> 
> My change fixes a real bug:
> 
> https://sourceware.org/bugzilla/show_bug.cgi?id=20022

Really, your change is a workaround not a fix.  You avoid exporting
__start or __stop symbols because doing so shows a problem with gc.  A
real fix for the PR would make ld do the right thing even in the
presense of exported dynamic symbols.

> We can suggest workarounds if some codes depend on that.
> 
> >>
> >> > that you don't mention:  __start and __stop symbols were previously
> >> > defined by ld -Ur, not just at final link.  You'll need to modify
> >>
> >> Is there a testcase for this behavior?
> >
> > Not that I'm aware of.
> >
> 
> >From ld manual:
> 
> '-Ur'
>      For anything other than C++ programs, this option is equivalent to
>      '-r': it generates relocatable output--i.e., an output file that
>      can in turn serve as input to 'ld'.  When linking C++ programs,
>      '-Ur' _does_ resolve references to constructors, unlike '-r'.  It
>      does not work to use '-Ur' on files that were themselves linked
>      with '-Ur'; once the constructor table has been built, it cannot be
>      added to.  Use '-Ur' only for the last partial link, and '-r' for
>      the others.
> 
> It isn't intended for  __start_SECNAME and __stop_SECNAME.  Check
> config.build_constructors for __start_SECNAME and __stop_SECNAME
> was introduced by:
> 
> commit 71bfc0aef6964c54b8e29466e97fb246cdeb2049
> Author: Alan Modra <amodra@gmail.com>
> Date:   Thu Sep 7 07:08:58 2000 +0000
> 
>     Fix list handling for orphan section output statements.

That's a long time ago.  Prior to that patch, ld defined __start and
__stop symbols for ld -r, which can lead to unexpected results for the
unwary.  I can't remember, but I suspect I changed ld to define the
symbols for -Ur so that people who wanted the previous ld -r behaviour
for __start and __stop could get that by using ld -Ur.

-- 
Alan Modra
Australia Development Lab, IBM

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

* Re: [PATCH] Always define referenced __start_SECNAME/__stop_SECNAME
  2017-06-13 12:26         ` Alan Modra
@ 2017-06-13 12:38           ` H.J. Lu
  2017-06-13 14:28             ` Alan Modra
  0 siblings, 1 reply; 16+ messages in thread
From: H.J. Lu @ 2017-06-13 12:38 UTC (permalink / raw)
  To: Alan Modra; +Cc: Binutils

On Tue, Jun 13, 2017 at 5:26 AM, Alan Modra <amodra@gmail.com> wrote:
> On Mon, Jun 12, 2017 at 07:10:47PM -0700, H.J. Lu wrote:
>> On Mon, Jun 12, 2017 at 6:54 PM, Alan Modra <amodra@gmail.com> wrote:
>> > On Mon, Jun 12, 2017 at 05:18:58PM -0700, H.J. Lu wrote:
>> >> On Mon, Jun 12, 2017 at 4:32 PM, Alan Modra <amodra@gmail.com> wrote:
>> >> > On Sat, Jun 10, 2017 at 03:46:49PM -0700, H.J. Lu wrote:
>> >> >> This patch changes linker to always define referenced __start_SECNAME and
>> >> >> __stop_SECNAME if the input section name is the same output section name,
>> >> >> which is always true for orphaned sections, and SECNAME is a C identifier.
>> >> >
>> >> > I think this change is reasonable.
>> >> >
>> >> >> Also __start_SECNAME and __stop_SECNAME symbols are marked as hidden by
>> >> >> ELF linker.
>> >> >
>> >> > Why is this necessary?  Also, you make another change in behaviour
>> >>
>> >> It is to make sure that  __start_SECNAME and __stop_SECNAME
>> >> symbols     for section SECNAME in different modules are unique.
>> >
>> > I understand, and it would have been good if these symbols were
>> > defined that way in the beginning, but they weren't.  I'm concerned
>> > that if you make this change as well we will find some code that
>> > relies on the symbols being dynamic.
>>
>> My change fixes a real bug:
>>
>> https://sourceware.org/bugzilla/show_bug.cgi?id=20022
>
> Really, your change is a workaround not a fix.  You avoid exporting
> __start or __stop symbols because doing so shows a problem with gc.  A
> real fix for the PR would make ld do the right thing even in the
> presense of exported dynamic symbols.

Exporting __start_SECNAME and __stop_SECNAME as dynamic
symbols may lead to unexpected behavior.  Reference to __start_SECNAME
and __stop_SECNAME to section SECNAME within a DSO will be
resolved to __start_SECNAME and __stop_SECNAME in another DSO
or executable.  In most cases, it isn't the intended behavior and there are
workaround if it is needed.

>> We can suggest workarounds if some codes depend on that.
>>
>> >>
>> >> > that you don't mention:  __start and __stop symbols were previously
>> >> > defined by ld -Ur, not just at final link.  You'll need to modify
>> >>
>> >> Is there a testcase for this behavior?
>> >
>> > Not that I'm aware of.
>> >
>>
>> >From ld manual:
>>
>> '-Ur'
>>      For anything other than C++ programs, this option is equivalent to
>>      '-r': it generates relocatable output--i.e., an output file that
>>      can in turn serve as input to 'ld'.  When linking C++ programs,
>>      '-Ur' _does_ resolve references to constructors, unlike '-r'.  It
>>      does not work to use '-Ur' on files that were themselves linked
>>      with '-Ur'; once the constructor table has been built, it cannot be
>>      added to.  Use '-Ur' only for the last partial link, and '-r' for
>>      the others.
>>
>> It isn't intended for  __start_SECNAME and __stop_SECNAME.  Check
>> config.build_constructors for __start_SECNAME and __stop_SECNAME
>> was introduced by:
>>
>> commit 71bfc0aef6964c54b8e29466e97fb246cdeb2049
>> Author: Alan Modra <amodra@gmail.com>
>> Date:   Thu Sep 7 07:08:58 2000 +0000
>>
>>     Fix list handling for orphan section output statements.
>
> That's a long time ago.  Prior to that patch, ld defined __start and
> __stop symbols for ld -r, which can lead to unexpected results for the
> unwary.  I can't remember, but I suspect I changed ld to define the
> symbols for -Ur so that people who wanted the previous ld -r behaviour
> for __start and __stop could get that by using ld -Ur.
>

If it is the case, it isn't intended usage for ld -Ur and people shouldn't
depend on it.


-- 
H.J.

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

* Re: [PATCH] Always define referenced __start_SECNAME/__stop_SECNAME
  2017-06-13 12:38           ` H.J. Lu
@ 2017-06-13 14:28             ` Alan Modra
  2017-06-13 15:22               ` H.J. Lu
  0 siblings, 1 reply; 16+ messages in thread
From: Alan Modra @ 2017-06-13 14:28 UTC (permalink / raw)
  To: H.J. Lu; +Cc: Binutils

On Tue, Jun 13, 2017 at 05:38:45AM -0700, H.J. Lu wrote:
> On Tue, Jun 13, 2017 at 5:26 AM, Alan Modra <amodra@gmail.com> wrote:
> > On Mon, Jun 12, 2017 at 07:10:47PM -0700, H.J. Lu wrote:
> >> On Mon, Jun 12, 2017 at 6:54 PM, Alan Modra <amodra@gmail.com> wrote:
> >> > On Mon, Jun 12, 2017 at 05:18:58PM -0700, H.J. Lu wrote:
> >> >> On Mon, Jun 12, 2017 at 4:32 PM, Alan Modra <amodra@gmail.com> wrote:
> >> >> > On Sat, Jun 10, 2017 at 03:46:49PM -0700, H.J. Lu wrote:
> >> >> >> This patch changes linker to always define referenced __start_SECNAME and
> >> >> >> __stop_SECNAME if the input section name is the same output section name,
> >> >> >> which is always true for orphaned sections, and SECNAME is a C identifier.
> >> >> >
> >> >> > I think this change is reasonable.
> >> >> >
> >> >> >> Also __start_SECNAME and __stop_SECNAME symbols are marked as hidden by
> >> >> >> ELF linker.
> >> >> >
> >> >> > Why is this necessary?  Also, you make another change in behaviour
> >> >>
> >> >> It is to make sure that  __start_SECNAME and __stop_SECNAME
> >> >> symbols     for section SECNAME in different modules are unique.
> >> >
> >> > I understand, and it would have been good if these symbols were
> >> > defined that way in the beginning, but they weren't.  I'm concerned
> >> > that if you make this change as well we will find some code that
> >> > relies on the symbols being dynamic.
> >>
> >> My change fixes a real bug:
> >>
> >> https://sourceware.org/bugzilla/show_bug.cgi?id=20022
> >
> > Really, your change is a workaround not a fix.  You avoid exporting
> > __start or __stop symbols because doing so shows a problem with gc.  A
> > real fix for the PR would make ld do the right thing even in the
> > presense of exported dynamic symbols.
> 
> Exporting __start_SECNAME and __stop_SECNAME as dynamic
> symbols may lead to unexpected behavior.  Reference to __start_SECNAME
> and __stop_SECNAME to section SECNAME within a DSO will be
> resolved to __start_SECNAME and __stop_SECNAME in another DSO
> or executable.  In most cases, it isn't the intended behavior and there are
> workaround if it is needed.

You're correct regarding shared libraries.  I was thinking more about
an executable when I said the patch was a workaround.  OK, so I
suppose we should leave that in, and wait to see if we get complaints.

> >> We can suggest workarounds if some codes depend on that.
> >>
> >> >>
> >> >> > that you don't mention:  __start and __stop symbols were previously
> >> >> > defined by ld -Ur, not just at final link.  You'll need to modify
> >> >>
> >> >> Is there a testcase for this behavior?
> >> >
> >> > Not that I'm aware of.
> >> >
> >>
> >> >From ld manual:
> >>
> >> '-Ur'
> >>      For anything other than C++ programs, this option is equivalent to
> >>      '-r': it generates relocatable output--i.e., an output file that
> >>      can in turn serve as input to 'ld'.  When linking C++ programs,
> >>      '-Ur' _does_ resolve references to constructors, unlike '-r'.  It
> >>      does not work to use '-Ur' on files that were themselves linked
> >>      with '-Ur'; once the constructor table has been built, it cannot be
> >>      added to.  Use '-Ur' only for the last partial link, and '-r' for
> >>      the others.
> >>
> >> It isn't intended for  __start_SECNAME and __stop_SECNAME.  Check
> >> config.build_constructors for __start_SECNAME and __stop_SECNAME
> >> was introduced by:
> >>
> >> commit 71bfc0aef6964c54b8e29466e97fb246cdeb2049
> >> Author: Alan Modra <amodra@gmail.com>
> >> Date:   Thu Sep 7 07:08:58 2000 +0000
> >>
> >>     Fix list handling for orphan section output statements.
> >
> > That's a long time ago.  Prior to that patch, ld defined __start and
> > __stop symbols for ld -r, which can lead to unexpected results for the
> > unwary.  I can't remember, but I suspect I changed ld to define the
> > symbols for -Ur so that people who wanted the previous ld -r behaviour
> > for __start and __stop could get that by using ld -Ur.
> >
> 
> If it is the case, it isn't intended usage for ld -Ur and people shouldn't
> depend on it.

Please leave that behaviour unchanged.

-- 
Alan Modra
Australia Development Lab, IBM

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

* Re: [PATCH] Always define referenced __start_SECNAME/__stop_SECNAME
  2017-06-13 14:28             ` Alan Modra
@ 2017-06-13 15:22               ` H.J. Lu
  2017-06-13 15:31                 ` H.J. Lu
  2017-06-13 19:07                 ` H.J. Lu
  0 siblings, 2 replies; 16+ messages in thread
From: H.J. Lu @ 2017-06-13 15:22 UTC (permalink / raw)
  To: Alan Modra; +Cc: Binutils

[-- Attachment #1: Type: text/plain, Size: 4392 bytes --]

On Tue, Jun 13, 2017 at 7:28 AM, Alan Modra <amodra@gmail.com> wrote:
> On Tue, Jun 13, 2017 at 05:38:45AM -0700, H.J. Lu wrote:
>> On Tue, Jun 13, 2017 at 5:26 AM, Alan Modra <amodra@gmail.com> wrote:
>> > On Mon, Jun 12, 2017 at 07:10:47PM -0700, H.J. Lu wrote:
>> >> On Mon, Jun 12, 2017 at 6:54 PM, Alan Modra <amodra@gmail.com> wrote:
>> >> > On Mon, Jun 12, 2017 at 05:18:58PM -0700, H.J. Lu wrote:
>> >> >> On Mon, Jun 12, 2017 at 4:32 PM, Alan Modra <amodra@gmail.com> wrote:
>> >> >> > On Sat, Jun 10, 2017 at 03:46:49PM -0700, H.J. Lu wrote:
>> >> >> >> This patch changes linker to always define referenced __start_SECNAME and
>> >> >> >> __stop_SECNAME if the input section name is the same output section name,
>> >> >> >> which is always true for orphaned sections, and SECNAME is a C identifier.
>> >> >> >
>> >> >> > I think this change is reasonable.
>> >> >> >
>> >> >> >> Also __start_SECNAME and __stop_SECNAME symbols are marked as hidden by
>> >> >> >> ELF linker.
>> >> >> >
>> >> >> > Why is this necessary?  Also, you make another change in behaviour
>> >> >>
>> >> >> It is to make sure that  __start_SECNAME and __stop_SECNAME
>> >> >> symbols     for section SECNAME in different modules are unique.
>> >> >
>> >> > I understand, and it would have been good if these symbols were
>> >> > defined that way in the beginning, but they weren't.  I'm concerned
>> >> > that if you make this change as well we will find some code that
>> >> > relies on the symbols being dynamic.
>> >>
>> >> My change fixes a real bug:
>> >>
>> >> https://sourceware.org/bugzilla/show_bug.cgi?id=20022
>> >
>> > Really, your change is a workaround not a fix.  You avoid exporting
>> > __start or __stop symbols because doing so shows a problem with gc.  A
>> > real fix for the PR would make ld do the right thing even in the
>> > presense of exported dynamic symbols.
>>
>> Exporting __start_SECNAME and __stop_SECNAME as dynamic
>> symbols may lead to unexpected behavior.  Reference to __start_SECNAME
>> and __stop_SECNAME to section SECNAME within a DSO will be
>> resolved to __start_SECNAME and __stop_SECNAME in another DSO
>> or executable.  In most cases, it isn't the intended behavior and there are
>> workaround if it is needed.
>
> You're correct regarding shared libraries.  I was thinking more about
> an executable when I said the patch was a workaround.  OK, so I
> suppose we should leave that in, and wait to see if we get complaints.
>
>> >> We can suggest workarounds if some codes depend on that.
>> >>
>> >> >>
>> >> >> > that you don't mention:  __start and __stop symbols were previously
>> >> >> > defined by ld -Ur, not just at final link.  You'll need to modify
>> >> >>
>> >> >> Is there a testcase for this behavior?
>> >> >
>> >> > Not that I'm aware of.
>> >> >
>> >>
>> >> >From ld manual:
>> >>
>> >> '-Ur'
>> >>      For anything other than C++ programs, this option is equivalent to
>> >>      '-r': it generates relocatable output--i.e., an output file that
>> >>      can in turn serve as input to 'ld'.  When linking C++ programs,
>> >>      '-Ur' _does_ resolve references to constructors, unlike '-r'.  It
>> >>      does not work to use '-Ur' on files that were themselves linked
>> >>      with '-Ur'; once the constructor table has been built, it cannot be
>> >>      added to.  Use '-Ur' only for the last partial link, and '-r' for
>> >>      the others.
>> >>
>> >> It isn't intended for  __start_SECNAME and __stop_SECNAME.  Check
>> >> config.build_constructors for __start_SECNAME and __stop_SECNAME
>> >> was introduced by:
>> >>
>> >> commit 71bfc0aef6964c54b8e29466e97fb246cdeb2049
>> >> Author: Alan Modra <amodra@gmail.com>
>> >> Date:   Thu Sep 7 07:08:58 2000 +0000
>> >>
>> >>     Fix list handling for orphan section output statements.
>> >
>> > That's a long time ago.  Prior to that patch, ld defined __start and
>> > __stop symbols for ld -r, which can lead to unexpected results for the
>> > unwary.  I can't remember, but I suspect I changed ld to define the
>> > symbols for -Ur so that people who wanted the previous ld -r behaviour
>> > for __start and __stop could get that by using ld -Ur.
>> >
>>
>> If it is the case, it isn't intended usage for ld -Ur and people shouldn't
>> depend on it.
>
> Please leave that behaviour unchanged.
>

I am checking this patch to verify it and I will update my patch.


-- 
H.J.

[-- Attachment #2: 0001-Add-tests-for-Ur.patch --]
[-- Type: text/x-patch, Size: 3430 bytes --]

From b04772be9a254f6bcf0dab491dd0272ae4b4f6ee Mon Sep 17 00:00:00 2001
From: "H.J. Lu" <hjl.tools@gmail.com>
Date: Tue, 13 Jun 2017 08:18:19 -0700
Subject: [PATCH] Add tests for -Ur

Test -Ur with __start_SECNAME, __stop_SECNAME, .startof.SECNAME and
.sizeof.SECNAME.  __start_SECNAME and __stop_SECNAME should be defined
to the start and the end of section SECNAME.  .startof.SECNAME and
.sizeof.SECNAME should be undefined.

	* testsuite/ld-elf/sizeof.d: New file.
	* testsuite/ld-elf/sizeof.s: Likewise.
	* testsuite/ld-elf/startof.d: Likewise.
	* testsuite/ld-elf/startof.s: Likewise.
---
 ld/ChangeLog                  |  7 +++++++
 ld/testsuite/ld-elf/sizeof.d  | 11 +++++++++++
 ld/testsuite/ld-elf/sizeof.s  | 11 +++++++++++
 ld/testsuite/ld-elf/startof.d | 11 +++++++++++
 ld/testsuite/ld-elf/startof.s | 11 +++++++++++
 5 files changed, 51 insertions(+)
 create mode 100644 ld/testsuite/ld-elf/sizeof.d
 create mode 100644 ld/testsuite/ld-elf/sizeof.s
 create mode 100644 ld/testsuite/ld-elf/startof.d
 create mode 100644 ld/testsuite/ld-elf/startof.s

diff --git a/ld/ChangeLog b/ld/ChangeLog
index 1c81211..309bb3a 100644
--- a/ld/ChangeLog
+++ b/ld/ChangeLog
@@ -1,3 +1,10 @@
+2017-06-13  H.J. Lu  <hongjiu.lu@intel.com>
+
+	* testsuite/ld-elf/sizeof.d: New file.
+	* testsuite/ld-elf/sizeof.s: Likewise.
+	* testsuite/ld-elf/startof.d: Likewise.
+	* testsuite/ld-elf/startof.s: Likewise.
+
 2017-06-13  Renlin Li  <renlin.li@arm.com>
 
 	* testsuite/ld-elf/shared.exp (build_tests): Add --no-dynamic-linker
diff --git a/ld/testsuite/ld-elf/sizeof.d b/ld/testsuite/ld-elf/sizeof.d
new file mode 100644
index 0000000..7cad75a
--- /dev/null
+++ b/ld/testsuite/ld-elf/sizeof.d
@@ -0,0 +1,11 @@
+#ld: -Ur
+#readelf: -sW
+
+Symbol table '\.symtab' contains [0-9]+ entries:
+ +Num: +Value +Size Type +Bind +Vis +Ndx Name
+ +0: 0+ +0 +NOTYPE +LOCAL +DEFAULT +UND +
+#...
+ +[0-9]+: +[a-f0-9]+ +0 +NOTYPE +GLOBAL +DEFAULT +[0-9]+ +__stop_scnfoo
+#...
+ +[0-9]+: +[a-f0-9]+ +0 +NOTYPE +GLOBAL +DEFAULT +UND +.sizeof.scnfoo
+#pass
diff --git a/ld/testsuite/ld-elf/sizeof.s b/ld/testsuite/ld-elf/sizeof.s
new file mode 100644
index 0000000..016ac60
--- /dev/null
+++ b/ld/testsuite/ld-elf/sizeof.s
@@ -0,0 +1,11 @@
+        .section        scnfoo,"aw",%progbits
+        .zero 0x10
+
+        .globl  bar
+        .data
+        .align 8
+        .type   bar, %object
+        .size   bar, 8
+bar:
+        .dc.a   __stop_scnfoo
+        .dc.a  .sizeof. (scnfoo)
diff --git a/ld/testsuite/ld-elf/startof.d b/ld/testsuite/ld-elf/startof.d
new file mode 100644
index 0000000..cf1f064
--- /dev/null
+++ b/ld/testsuite/ld-elf/startof.d
@@ -0,0 +1,11 @@
+#ld: -Ur
+#readelf: -sW
+
+Symbol table '\.symtab' contains [0-9]+ entries:
+ +Num: +Value +Size Type +Bind +Vis +Ndx Name
+ +0: 0+ +0 +NOTYPE +LOCAL +DEFAULT +UND +
+#...
+ +[0-9]+: +[a-f0-9]+ +0 +NOTYPE +GLOBAL +DEFAULT +UND +.startof.scnfoo
+#...
+ +[0-9]+: +[a-f0-9]+ +0 +NOTYPE +GLOBAL +DEFAULT +[0-9]+ +__start_scnfoo
+#pass
diff --git a/ld/testsuite/ld-elf/startof.s b/ld/testsuite/ld-elf/startof.s
new file mode 100644
index 0000000..982f347
--- /dev/null
+++ b/ld/testsuite/ld-elf/startof.s
@@ -0,0 +1,11 @@
+        .section        scnfoo,"aw",%progbits
+        .zero 0x10
+
+        .globl  bar
+        .data
+        .align 8
+        .type   bar, %object
+        .size   bar, 8
+bar:
+        .dc.a   __start_scnfoo
+        .dc.a  .startof. (scnfoo)
-- 
2.9.4


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

* Re: [PATCH] Always define referenced __start_SECNAME/__stop_SECNAME
  2017-06-13 15:22               ` H.J. Lu
@ 2017-06-13 15:31                 ` H.J. Lu
  2017-06-13 19:07                 ` H.J. Lu
  1 sibling, 0 replies; 16+ messages in thread
From: H.J. Lu @ 2017-06-13 15:31 UTC (permalink / raw)
  To: Alan Modra; +Cc: Binutils

[-- Attachment #1: Type: text/plain, Size: 4605 bytes --]

On Tue, Jun 13, 2017 at 8:22 AM, H.J. Lu <hjl.tools@gmail.com> wrote:
> On Tue, Jun 13, 2017 at 7:28 AM, Alan Modra <amodra@gmail.com> wrote:
>> On Tue, Jun 13, 2017 at 05:38:45AM -0700, H.J. Lu wrote:
>>> On Tue, Jun 13, 2017 at 5:26 AM, Alan Modra <amodra@gmail.com> wrote:
>>> > On Mon, Jun 12, 2017 at 07:10:47PM -0700, H.J. Lu wrote:
>>> >> On Mon, Jun 12, 2017 at 6:54 PM, Alan Modra <amodra@gmail.com> wrote:
>>> >> > On Mon, Jun 12, 2017 at 05:18:58PM -0700, H.J. Lu wrote:
>>> >> >> On Mon, Jun 12, 2017 at 4:32 PM, Alan Modra <amodra@gmail.com> wrote:
>>> >> >> > On Sat, Jun 10, 2017 at 03:46:49PM -0700, H.J. Lu wrote:
>>> >> >> >> This patch changes linker to always define referenced __start_SECNAME and
>>> >> >> >> __stop_SECNAME if the input section name is the same output section name,
>>> >> >> >> which is always true for orphaned sections, and SECNAME is a C identifier.
>>> >> >> >
>>> >> >> > I think this change is reasonable.
>>> >> >> >
>>> >> >> >> Also __start_SECNAME and __stop_SECNAME symbols are marked as hidden by
>>> >> >> >> ELF linker.
>>> >> >> >
>>> >> >> > Why is this necessary?  Also, you make another change in behaviour
>>> >> >>
>>> >> >> It is to make sure that  __start_SECNAME and __stop_SECNAME
>>> >> >> symbols     for section SECNAME in different modules are unique.
>>> >> >
>>> >> > I understand, and it would have been good if these symbols were
>>> >> > defined that way in the beginning, but they weren't.  I'm concerned
>>> >> > that if you make this change as well we will find some code that
>>> >> > relies on the symbols being dynamic.
>>> >>
>>> >> My change fixes a real bug:
>>> >>
>>> >> https://sourceware.org/bugzilla/show_bug.cgi?id=20022
>>> >
>>> > Really, your change is a workaround not a fix.  You avoid exporting
>>> > __start or __stop symbols because doing so shows a problem with gc.  A
>>> > real fix for the PR would make ld do the right thing even in the
>>> > presense of exported dynamic symbols.
>>>
>>> Exporting __start_SECNAME and __stop_SECNAME as dynamic
>>> symbols may lead to unexpected behavior.  Reference to __start_SECNAME
>>> and __stop_SECNAME to section SECNAME within a DSO will be
>>> resolved to __start_SECNAME and __stop_SECNAME in another DSO
>>> or executable.  In most cases, it isn't the intended behavior and there are
>>> workaround if it is needed.
>>
>> You're correct regarding shared libraries.  I was thinking more about
>> an executable when I said the patch was a workaround.  OK, so I
>> suppose we should leave that in, and wait to see if we get complaints.
>>
>>> >> We can suggest workarounds if some codes depend on that.
>>> >>
>>> >> >>
>>> >> >> > that you don't mention:  __start and __stop symbols were previously
>>> >> >> > defined by ld -Ur, not just at final link.  You'll need to modify
>>> >> >>
>>> >> >> Is there a testcase for this behavior?
>>> >> >
>>> >> > Not that I'm aware of.
>>> >> >
>>> >>
>>> >> >From ld manual:
>>> >>
>>> >> '-Ur'
>>> >>      For anything other than C++ programs, this option is equivalent to
>>> >>      '-r': it generates relocatable output--i.e., an output file that
>>> >>      can in turn serve as input to 'ld'.  When linking C++ programs,
>>> >>      '-Ur' _does_ resolve references to constructors, unlike '-r'.  It
>>> >>      does not work to use '-Ur' on files that were themselves linked
>>> >>      with '-Ur'; once the constructor table has been built, it cannot be
>>> >>      added to.  Use '-Ur' only for the last partial link, and '-r' for
>>> >>      the others.
>>> >>
>>> >> It isn't intended for  __start_SECNAME and __stop_SECNAME.  Check
>>> >> config.build_constructors for __start_SECNAME and __stop_SECNAME
>>> >> was introduced by:
>>> >>
>>> >> commit 71bfc0aef6964c54b8e29466e97fb246cdeb2049
>>> >> Author: Alan Modra <amodra@gmail.com>
>>> >> Date:   Thu Sep 7 07:08:58 2000 +0000
>>> >>
>>> >>     Fix list handling for orphan section output statements.
>>> >
>>> > That's a long time ago.  Prior to that patch, ld defined __start and
>>> > __stop symbols for ld -r, which can lead to unexpected results for the
>>> > unwary.  I can't remember, but I suspect I changed ld to define the
>>> > symbols for -Ur so that people who wanted the previous ld -r behaviour
>>> > for __start and __stop could get that by using ld -Ur.
>>> >
>>>
>>> If it is the case, it isn't intended usage for ld -Ur and people shouldn't
>>> depend on it.
>>
>> Please leave that behaviour unchanged.
>>
>
> I am checking this patch to verify it and I will update my patch.
>

This is the patch I am checking in.

Thanks.

-- 
H.J.

[-- Attachment #2: 0001-Always-define-referenced-__start_SECNAME-__stop_SECN.patch --]
[-- Type: text/x-patch, Size: 42969 bytes --]

From 32acdc7730c243867d4afbeeb187f5ab3653f012 Mon Sep 17 00:00:00 2001
From: "H.J. Lu" <hjl.tools@gmail.com>
Date: Sat, 10 Jun 2017 07:30:17 -0700
Subject: [PATCH] Always define referenced __start_SECNAME/__stop_SECNAME

Currently, linker will define __start_SECNAME and __stop_SECNAME symbols
only for orphaned sections.

However, during garbage collection, ELF linker marks all sections with
references to __start_SECNAME and __stop_SECNAME symbols as used even
when section SECNAME isn't an orphaned section and linker won't define
__start_SECNAME nor __stop_SECNAME.  And ELF linker stores the first
input section whose name matches __start_SECNAME or __stop_SECNAME in
u.undef.section for garbage collection.  If these symbols are provided
in linker script, u.undef.section is set to the section where they will
defined by linker script, which leads to the incorrect output.

This patch changes linker to always define referenced __start_SECNAME and
__stop_SECNAME if the input section name is the same as the output section
name, which is always true for orphaned sections, and SECNAME is a C
identifier.  Also __start_SECNAME and __stop_SECNAME symbols are marked
as hidden by ELF linker so that __start_SECNAME and __stop_SECNAME symbols
for section SECNAME in different modules are unique.  For garbage
collection, ELF linker stores the first matched input section in the
unused vtable field.

bfd/

	PR ld/20022
	PR ld/21557
	PR ld/21562
	PR ld/21571
	* elf-bfd.h (elf_link_hash_entry): Add start_stop.  Change the
	vtable field to a union.
	(_bfd_elf_is_start_stop): Removed.
	* elf32-i386.c (elf_i386_convert_load_reloc): Also check for
	__start_SECNAME and __stop_SECNAME symbols.
	* elf64-x86-64.c (elf_x86_64_convert_load_reloc): Likewise.
	* elflink.c (_bfd_elf_is_start_stop): Removed.
	(_bfd_elf_gc_mark_rsec): Check start_stop instead of calling
	_bfd_elf_is_start_stop.
	(elf_gc_propagate_vtable_entries_used): Skip __start_SECNAME and
	__stop_SECNAME symbols.  Updated.
	(elf_gc_smash_unused_vtentry_relocs): Likewise.
	(bfd_elf_gc_record_vtinherit): Likewise.
	(bfd_elf_gc_record_vtentry): Likewise.

ld/

	PR ld/20022
	PR ld/21557
	PR ld/21562
	PR ld/21571
	* ld.texinfo: Update __start_SECNAME/__stop_SECNAME symbols.
	* ldlang.c (lang_insert_orphan): Move handling of __start_SECNAME
	and __stop_SECNAME symbols to ...
	(lang_set_startof): Here.  Also define __start_SECNAME and
	__stop_SECNAME for -Ur.
	* emultempl/elf32.em (gld${EMULATION_NAME}_after_open): Mark
	referenced __start_SECNAME and __stop_SECNAME symbols as hidden
	and set start_stop for garbage collection.
	* testsuite/ld-elf/pr21562a.d: New file.
	* testsuite/ld-elf/pr21562a.s: Likewise.
	* testsuite/ld-elf/pr21562a.t: Likewise.
	* testsuite/ld-elf/pr21562b.d: Likewise.
	* testsuite/ld-elf/pr21562b.s: Likewise.
	* testsuite/ld-elf/pr21562b.t: Likewise.
	* testsuite/ld-elf/pr21562c.d: Likewise.
	* testsuite/ld-elf/pr21562c.t: Likewise.
	* testsuite/ld-elf/pr21562d.d: Likewise.
	* testsuite/ld-elf/pr21562d.t: Likewise.
	* testsuite/ld-elf/pr21562e.d: Likewise.
	* testsuite/ld-elf/pr21562f.d: Likewise.
	* testsuite/ld-elf/pr21562g.d: Likewise.
	* testsuite/ld-elf/pr21562h.d: Likewise.
	* testsuite/ld-elf/pr21562i.d: Likewise.
	* testsuite/ld-elf/pr21562j.d: Likewise.
	* testsuite/ld-elf/pr21562k.d: Likewise.
	* testsuite/ld-elf/pr21562l.d: Likewise.
	* testsuite/ld-elf/pr21562m.d: Likewise.
	* testsuite/ld-elf/pr21562n.d: Likewise.
	* testsuite/ld-gc/pr20022.d: Likewise.
	* testsuite/ld-gc/pr20022a.s: Likewise.
	* testsuite/ld-gc/pr20022b.s: Likewise.
	* testsuite/ld-gc/gc.exp: Run PR ld/20022 tests.
	* testsuite/ld-gc/pr19161.d: Also accept local __start_SECNAME
	symbol.
	* testsuite/ld-gc/start.d: Likewise.
	* testsuite/ld-x86-64/lea1a.d: Updated.
	* testsuite/ld-x86-64/lea1b.d: Updated.
	* testsuite/ld-x86-64/lea1d.d: Updated.
	* testsuite/ld-x86-64/lea1e.d: Likewise.
---
 bfd/elf-bfd.h                  |  16 ++++--
 bfd/elf32-i386.c               |  12 +++--
 bfd/elf64-x86-64.c             |  28 +++++-----
 bfd/elflink.c                  | 118 +++++++++++++----------------------------
 ld/emultempl/elf32.em          |  64 ++++++++++++++++++++--
 ld/ld.texinfo                  |  16 +++---
 ld/ldlang.c                    | 115 +++++++++++++++++++--------------------
 ld/testsuite/ld-elf/pr21562a.d |   9 ++++
 ld/testsuite/ld-elf/pr21562a.s |   8 +++
 ld/testsuite/ld-elf/pr21562a.t |   3 ++
 ld/testsuite/ld-elf/pr21562b.d |   9 ++++
 ld/testsuite/ld-elf/pr21562b.s |   8 +++
 ld/testsuite/ld-elf/pr21562b.t |   5 ++
 ld/testsuite/ld-elf/pr21562c.d |  10 ++++
 ld/testsuite/ld-elf/pr21562c.t |   7 +++
 ld/testsuite/ld-elf/pr21562d.d |  10 ++++
 ld/testsuite/ld-elf/pr21562d.t |   5 ++
 ld/testsuite/ld-elf/pr21562e.d |  10 ++++
 ld/testsuite/ld-elf/pr21562f.d |  10 ++++
 ld/testsuite/ld-elf/pr21562g.d |  10 ++++
 ld/testsuite/ld-elf/pr21562h.d |  10 ++++
 ld/testsuite/ld-elf/pr21562i.d |  10 ++++
 ld/testsuite/ld-elf/pr21562j.d |  10 ++++
 ld/testsuite/ld-elf/pr21562k.d |  10 ++++
 ld/testsuite/ld-elf/pr21562l.d |  10 ++++
 ld/testsuite/ld-elf/pr21562m.d |  10 ++++
 ld/testsuite/ld-elf/pr21562n.d |  10 ++++
 ld/testsuite/ld-gc/gc.exp      |   6 +++
 ld/testsuite/ld-gc/pr19161.d   |   2 +-
 ld/testsuite/ld-gc/pr20022.d   |  11 ++++
 ld/testsuite/ld-gc/pr20022a.s  |   8 +++
 ld/testsuite/ld-gc/pr20022b.s  |   8 +++
 ld/testsuite/ld-gc/start.d     |   2 +-
 ld/testsuite/ld-x86-64/lea1a.d |   2 +-
 ld/testsuite/ld-x86-64/lea1b.d |   2 +-
 ld/testsuite/ld-x86-64/lea1d.d |   2 +-
 ld/testsuite/ld-x86-64/lea1e.d |   2 +-
 37 files changed, 406 insertions(+), 182 deletions(-)
 create mode 100644 ld/testsuite/ld-elf/pr21562a.d
 create mode 100644 ld/testsuite/ld-elf/pr21562a.s
 create mode 100644 ld/testsuite/ld-elf/pr21562a.t
 create mode 100644 ld/testsuite/ld-elf/pr21562b.d
 create mode 100644 ld/testsuite/ld-elf/pr21562b.s
 create mode 100644 ld/testsuite/ld-elf/pr21562b.t
 create mode 100644 ld/testsuite/ld-elf/pr21562c.d
 create mode 100644 ld/testsuite/ld-elf/pr21562c.t
 create mode 100644 ld/testsuite/ld-elf/pr21562d.d
 create mode 100644 ld/testsuite/ld-elf/pr21562d.t
 create mode 100644 ld/testsuite/ld-elf/pr21562e.d
 create mode 100644 ld/testsuite/ld-elf/pr21562f.d
 create mode 100644 ld/testsuite/ld-elf/pr21562g.d
 create mode 100644 ld/testsuite/ld-elf/pr21562h.d
 create mode 100644 ld/testsuite/ld-elf/pr21562i.d
 create mode 100644 ld/testsuite/ld-elf/pr21562j.d
 create mode 100644 ld/testsuite/ld-elf/pr21562k.d
 create mode 100644 ld/testsuite/ld-elf/pr21562l.d
 create mode 100644 ld/testsuite/ld-elf/pr21562m.d
 create mode 100644 ld/testsuite/ld-elf/pr21562n.d
 create mode 100644 ld/testsuite/ld-gc/pr20022.d
 create mode 100644 ld/testsuite/ld-gc/pr20022a.s
 create mode 100644 ld/testsuite/ld-gc/pr20022b.s

diff --git a/bfd/elf-bfd.h b/bfd/elf-bfd.h
index 567b63a..fe15b93 100644
--- a/bfd/elf-bfd.h
+++ b/bfd/elf-bfd.h
@@ -213,6 +213,9 @@ struct elf_link_hash_entry
   /* Symbol is defined by a shared library with non-default visibility
      in a read/write section.  */
   unsigned int protected_def : 1;
+  /* Symbol is __start_SECNAME or __stop_SECNAME to mark section
+     SECNAME.  */
+  unsigned int start_stop : 1;
 
   /* String table index in .dynstr if this is a dynamic symbol.  */
   unsigned long dynstr_index;
@@ -243,7 +246,15 @@ struct elf_link_hash_entry
     struct bfd_elf_version_tree *vertree;
   } verinfo;
 
-  struct elf_link_virtual_table_entry *vtable;
+  union
+  {
+    /* For __start_SECNAME and __stop_SECNAME symbols, record the first
+       input section whose section name is SECNAME.  */
+    asection *start_stop_section;
+
+    /* Vtable information. */
+    struct elf_link_virtual_table_entry *vtable;
+  } u2;
 };
 
 /* Will references to this symbol always reference the symbol
@@ -2445,9 +2456,6 @@ extern bfd_boolean bfd_elf_gc_common_finalize_got_offsets
 extern bfd_boolean bfd_elf_gc_common_final_link
   (bfd *, struct bfd_link_info *);
 
-extern asection *_bfd_elf_is_start_stop
-  (const struct bfd_link_info *, struct elf_link_hash_entry *);
-
 extern bfd_boolean bfd_elf_reloc_symbol_deleted_p
   (bfd_vma, void *);
 
diff --git a/bfd/elf32-i386.c b/bfd/elf32-i386.c
index f9142a9..6636551 100644
--- a/bfd/elf32-i386.c
+++ b/bfd/elf32-i386.c
@@ -1787,11 +1787,13 @@ convert_branch:
 	return TRUE;
 
       /* def_regular is set by an assignment in a linker script in
-	 bfd_elf_record_link_assignment.  */
-      if ((h->def_regular
-	   || h->root.type == bfd_link_hash_defined
-	   || h->root.type == bfd_link_hash_defweak)
-	  && SYMBOL_REFERENCES_LOCAL (link_info, h))
+	 bfd_elf_record_link_assignment.  start_stop is set on
+	 __start_SECNAME/__stop_SECNAME which mark section SECNAME.  */
+      if (h->start_stop
+	  || ((h->def_regular
+	       || h->root.type == bfd_link_hash_defined
+	       || h->root.type == bfd_link_hash_defweak)
+	      && SYMBOL_REFERENCES_LOCAL (link_info, h)))
 	{
 convert_load:
 	  if (opcode == 0x8b)
diff --git a/bfd/elf64-x86-64.c b/bfd/elf64-x86-64.c
index 5306019..ab6f068 100644
--- a/bfd/elf64-x86-64.c
+++ b/bfd/elf64-x86-64.c
@@ -1920,21 +1920,25 @@ elf_x86_64_convert_load_reloc (bfd *abfd, asection *sec,
 	}
       /* Avoid optimizing GOTPCREL relocations againt _DYNAMIC since
 	 ld.so may use its link-time address.  */
-      else if ((h->def_regular
-		|| h->root.type == bfd_link_hash_defined
-		|| h->root.type == bfd_link_hash_defweak)
-	       && h != htab->elf.hdynamic
-	       && SYMBOL_REFERENCES_LOCAL (link_info, h))
+      else if (h->start_stop
+	       || ((h->def_regular
+		    || h->root.type == bfd_link_hash_defined
+		    || h->root.type == bfd_link_hash_defweak)
+		   && h != htab->elf.hdynamic
+		   && SYMBOL_REFERENCES_LOCAL (link_info, h)))
 	{
 	  /* bfd_link_hash_new or bfd_link_hash_undefined is
 	     set by an assignment in a linker script in
-	     bfd_elf_record_link_assignment.   */
-	  if (h->def_regular
-	      && (h->root.type == bfd_link_hash_new
-		  || h->root.type == bfd_link_hash_undefined
-		  || ((h->root.type == bfd_link_hash_defined
-		       || h->root.type == bfd_link_hash_defweak)
-		      && h->root.u.def.section == bfd_und_section_ptr)))
+	     bfd_elf_record_link_assignment.  start_stop is set
+	     on __start_SECNAME/__stop_SECNAME which mark section
+	     SECNAME.  */
+	  if (h->start_stop
+	      || (h->def_regular
+		  && (h->root.type == bfd_link_hash_new
+		      || h->root.type == bfd_link_hash_undefined
+		      || ((h->root.type == bfd_link_hash_defined
+			   || h->root.type == bfd_link_hash_defweak)
+			  && h->root.u.def.section == bfd_und_section_ptr))))
 	    {
 	      /* Skip since R_X86_64_32/R_X86_64_32S may overflow.  */
 	      if (require_reloc_pc32)
diff --git a/bfd/elflink.c b/bfd/elflink.c
index f0ca33f..9b0f544 100644
--- a/bfd/elflink.c
+++ b/bfd/elflink.c
@@ -12698,55 +12698,6 @@ elf_gc_mark_debug_section (asection *sec ATTRIBUTE_UNUSED,
   return NULL;
 }
 
-/* For undefined __start_<name> and __stop_<name> symbols, return the
-   first input section matching <name>.  Return NULL otherwise.  */
-
-asection *
-_bfd_elf_is_start_stop (const struct bfd_link_info *info,
-			struct elf_link_hash_entry *h)
-{
-  asection *s;
-  const char *sec_name;
-
-  if (h->root.type != bfd_link_hash_undefined
-      && h->root.type != bfd_link_hash_undefweak)
-    return NULL;
-
-  s = h->root.u.undef.section;
-  if (s != NULL)
-    {
-      if (s == (asection *) 0 - 1)
-	return NULL;
-      return s;
-    }
-
-  sec_name = NULL;
-  if (strncmp (h->root.root.string, "__start_", 8) == 0)
-    sec_name = h->root.root.string + 8;
-  else if (strncmp (h->root.root.string, "__stop_", 7) == 0)
-    sec_name = h->root.root.string + 7;
-
-  if (sec_name != NULL && *sec_name != '\0')
-    {
-      bfd *i;
-
-      for (i = info->input_bfds; i != NULL; i = i->link.next)
-	{
-	  s = bfd_get_section_by_name (i, sec_name);
-	  if (s != NULL)
-	    {
-	      h->root.u.undef.section = s;
-	      break;
-	    }
-	}
-    }
-
-  if (s == NULL)
-    h->root.u.undef.section = (asection *) 0 - 1;
-
-  return s;
-}
-
 /* COOKIE->rel describes a relocation against section SEC, which is
    a section we've decided to keep.  Return the section that contains
    the relocation symbol, or NULL if no section contains it.  */
@@ -12792,10 +12743,9 @@ _bfd_elf_gc_mark_rsec (struct bfd_link_info *info, asection *sec,
 	     or __stop_XXX symbols.  The linker will later define such
 	     symbols for orphan input sections that have a name
 	     representable as a C identifier.  */
-	  asection *s = _bfd_elf_is_start_stop (info, h);
-
-	  if (s != NULL)
+	  if (h->start_stop)
 	    {
+	      asection *s = h->u2.start_stop_section;
 	      *start_stop = !s->gc_mark;
 	      return s;
 	    }
@@ -13136,26 +13086,28 @@ static bfd_boolean
 elf_gc_propagate_vtable_entries_used (struct elf_link_hash_entry *h, void *okp)
 {
   /* Those that are not vtables.  */
-  if (h->vtable == NULL || h->vtable->parent == NULL)
+  if (h->start_stop
+      || h->u2.vtable == NULL
+      || h->u2.vtable->parent == NULL)
     return TRUE;
 
   /* Those vtables that do not have parents, we cannot merge.  */
-  if (h->vtable->parent == (struct elf_link_hash_entry *) -1)
+  if (h->u2.vtable->parent == (struct elf_link_hash_entry *) -1)
     return TRUE;
 
   /* If we've already been done, exit.  */
-  if (h->vtable->used && h->vtable->used[-1])
+  if (h->u2.vtable->used && h->u2.vtable->used[-1])
     return TRUE;
 
   /* Make sure the parent's table is up to date.  */
-  elf_gc_propagate_vtable_entries_used (h->vtable->parent, okp);
+  elf_gc_propagate_vtable_entries_used (h->u2.vtable->parent, okp);
 
-  if (h->vtable->used == NULL)
+  if (h->u2.vtable->used == NULL)
     {
       /* None of this table's entries were referenced.  Re-use the
 	 parent's table.  */
-      h->vtable->used = h->vtable->parent->vtable->used;
-      h->vtable->size = h->vtable->parent->vtable->size;
+      h->u2.vtable->used = h->u2.vtable->parent->u2.vtable->used;
+      h->u2.vtable->size = h->u2.vtable->parent->u2.vtable->size;
     }
   else
     {
@@ -13163,9 +13115,9 @@ elf_gc_propagate_vtable_entries_used (struct elf_link_hash_entry *h, void *okp)
       bfd_boolean *cu, *pu;
 
       /* Or the parent's entries into ours.  */
-      cu = h->vtable->used;
+      cu = h->u2.vtable->used;
       cu[-1] = TRUE;
-      pu = h->vtable->parent->vtable->used;
+      pu = h->u2.vtable->parent->u2.vtable->used;
       if (pu != NULL)
 	{
 	  const struct elf_backend_data *bed;
@@ -13173,7 +13125,7 @@ elf_gc_propagate_vtable_entries_used (struct elf_link_hash_entry *h, void *okp)
 
 	  bed = get_elf_backend_data (h->root.u.def.section->owner);
 	  log_file_align = bed->s->log_file_align;
-	  n = h->vtable->parent->vtable->size >> log_file_align;
+	  n = h->u2.vtable->parent->u2.vtable->size >> log_file_align;
 	  while (n--)
 	    {
 	      if (*pu)
@@ -13198,7 +13150,9 @@ elf_gc_smash_unused_vtentry_relocs (struct elf_link_hash_entry *h, void *okp)
 
   /* Take care of both those symbols that do not describe vtables as
      well as those that are not loaded.  */
-  if (h->vtable == NULL || h->vtable->parent == NULL)
+  if (h->start_stop
+      || h->u2.vtable == NULL
+      || h->u2.vtable->parent == NULL)
     return TRUE;
 
   BFD_ASSERT (h->root.type == bfd_link_hash_defined
@@ -13220,11 +13174,11 @@ elf_gc_smash_unused_vtentry_relocs (struct elf_link_hash_entry *h, void *okp)
     if (rel->r_offset >= hstart && rel->r_offset < hend)
       {
 	/* If the entry is in use, do nothing.  */
-	if (h->vtable->used
-	    && (rel->r_offset - hstart) < h->vtable->size)
+	if (h->u2.vtable->used
+	    && (rel->r_offset - hstart) < h->u2.vtable->size)
 	  {
 	    bfd_vma entry = (rel->r_offset - hstart) >> log_file_align;
-	    if (h->vtable->used[entry])
+	    if (h->u2.vtable->used[entry])
 	      continue;
 	  }
 	/* Otherwise, kill it.  */
@@ -13448,11 +13402,11 @@ bfd_elf_gc_record_vtinherit (bfd *abfd,
   return FALSE;
 
  win:
-  if (!child->vtable)
+  if (!child->u2.vtable)
     {
-      child->vtable = ((struct elf_link_virtual_table_entry *)
-		       bfd_zalloc (abfd, sizeof (*child->vtable)));
-      if (!child->vtable)
+      child->u2.vtable = ((struct elf_link_virtual_table_entry *)
+			  bfd_zalloc (abfd, sizeof (*child->u2.vtable)));
+      if (!child->u2.vtable)
 	return FALSE;
     }
   if (!h)
@@ -13462,10 +13416,10 @@ bfd_elf_gc_record_vtinherit (bfd *abfd,
 	 would be bad.  It isn't worth paging in the local symbols to be
 	 sure though; that case should simply be handled by the assembler.  */
 
-      child->vtable->parent = (struct elf_link_hash_entry *) -1;
+      child->u2.vtable->parent = (struct elf_link_hash_entry *) -1;
     }
   else
-    child->vtable->parent = h;
+    child->u2.vtable->parent = h;
 
   return TRUE;
 }
@@ -13481,18 +13435,18 @@ bfd_elf_gc_record_vtentry (bfd *abfd ATTRIBUTE_UNUSED,
   const struct elf_backend_data *bed = get_elf_backend_data (abfd);
   unsigned int log_file_align = bed->s->log_file_align;
 
-  if (!h->vtable)
+  if (!h->u2.vtable)
     {
-      h->vtable = ((struct elf_link_virtual_table_entry *)
-		   bfd_zalloc (abfd, sizeof (*h->vtable)));
-      if (!h->vtable)
+      h->u2.vtable = ((struct elf_link_virtual_table_entry *)
+		      bfd_zalloc (abfd, sizeof (*h->u2.vtable)));
+      if (!h->u2.vtable)
 	return FALSE;
     }
 
-  if (addend >= h->vtable->size)
+  if (addend >= h->u2.vtable->size)
     {
       size_t size, bytes, file_align;
-      bfd_boolean *ptr = h->vtable->used;
+      bfd_boolean *ptr = h->u2.vtable->used;
 
       /* While the symbol is undefined, we have to be prepared to handle
 	 a zero size.  */
@@ -13523,7 +13477,7 @@ bfd_elf_gc_record_vtentry (bfd *abfd ATTRIBUTE_UNUSED,
 	    {
 	      size_t oldbytes;
 
-	      oldbytes = (((h->vtable->size >> log_file_align) + 1)
+	      oldbytes = (((h->u2.vtable->size >> log_file_align) + 1)
 			  * sizeof (bfd_boolean));
 	      memset (((char *) ptr) + oldbytes, 0, bytes - oldbytes);
 	    }
@@ -13535,11 +13489,11 @@ bfd_elf_gc_record_vtentry (bfd *abfd ATTRIBUTE_UNUSED,
 	return FALSE;
 
       /* And arrange for that done flag to be at index -1.  */
-      h->vtable->used = ptr + 1;
-      h->vtable->size = size;
+      h->u2.vtable->used = ptr + 1;
+      h->u2.vtable->size = size;
     }
 
-  h->vtable->used[addend >> log_file_align] = TRUE;
+  h->u2.vtable->used[addend >> log_file_align] = TRUE;
 
   return TRUE;
 }
diff --git a/ld/emultempl/elf32.em b/ld/emultempl/elf32.em
index 0260b7a..9468f7d 100644
--- a/ld/emultempl/elf32.em
+++ b/ld/emultempl/elf32.em
@@ -1216,6 +1216,9 @@ gld${EMULATION_NAME}_after_open (void)
 {
   struct bfd_link_needed_list *needed, *l;
   struct elf_link_hash_table *htab;
+  asection *s;
+  bfd *abfd;
+  char leading_char;
 
   after_open_default ();
 
@@ -1239,8 +1242,6 @@ gld${EMULATION_NAME}_after_open (void)
 
   if (emit_note_gnu_build_id != NULL)
     {
-      bfd *abfd;
-
       /* Find an ELF input.  */
       for (abfd = link_info.input_bfds;
 	   abfd != (bfd *) NULL; abfd = abfd->link.next)
@@ -1276,11 +1277,66 @@ gld${EMULATION_NAME}_after_open (void)
       return;
     }
 
+  leading_char = bfd_get_symbol_leading_char (link_info.output_bfd);
+
+  /* Check for input sections whose names match references to
+     __start_SECNAME or __stop_SECNAME symbols.  Mark the matched
+     symbols as hidden and set start_stop for garbage collection.  */
+  for (abfd = link_info.input_bfds; abfd; abfd = abfd->link.next)
+    for (s = abfd->sections; s; s = s->next)
+      {
+	const char *name = bfd_get_section_name (abfd, s);
+	const char *ps;
+
+	for (ps = name; *ps != '\0'; ps++)
+	  if (!ISALNUM ((unsigned char) *ps) && *ps != '_')
+	    break;
+	if (*ps == '\0')
+	  {
+	    struct elf_link_hash_entry *h;
+	    char *symbol = (char *) xmalloc (ps - name
+					     + sizeof "__start_" + 1);
+
+	    symbol[0] = leading_char;
+	    sprintf (symbol + (leading_char != 0), "__start_%s", name);
+	    h = elf_link_hash_lookup (elf_hash_table (&link_info),
+				      symbol, FALSE, FALSE, TRUE);
+	    if (h != NULL
+		&& (h->root.type == bfd_link_hash_undefined
+		    || h->root.type == bfd_link_hash_undefweak)
+		&& h->u2.start_stop_section == NULL)
+	      {
+		h->start_stop = 1;
+		h->u2.start_stop_section = s;
+		_bfd_elf_link_hash_hide_symbol (&link_info, h, TRUE);
+		if (ELF_ST_VISIBILITY (h->other) != STV_INTERNAL)
+		  h->other = ((h->other & ~ELF_ST_VISIBILITY (-1))
+			      | STV_HIDDEN);
+	      }
+
+	    symbol[0] = leading_char;
+	    sprintf (symbol + (leading_char != 0), "__stop_%s", name);
+	    h = elf_link_hash_lookup (elf_hash_table (&link_info),
+				      symbol, FALSE, FALSE, TRUE);
+	    if (h != NULL
+		&& (h->root.type == bfd_link_hash_undefined
+		    || h->root.type == bfd_link_hash_undefweak)
+		&& h->u2.start_stop_section == NULL)
+	      {
+		h->start_stop = 1;
+		h->u2.start_stop_section = s;
+		_bfd_elf_link_hash_hide_symbol (&link_info, h, TRUE);
+		if (ELF_ST_VISIBILITY (h->other) != STV_INTERNAL)
+		  h->other = ((h->other & ~ELF_ST_VISIBILITY (-1))
+			      | STV_HIDDEN);
+	      }
+	  }
+      }
+
   if (!link_info.traditional_format)
     {
-      bfd *abfd, *elfbfd = NULL;
+      bfd *elfbfd = NULL;
       bfd_boolean warn_eh_frame = FALSE;
-      asection *s;
       int seen_type = 0;
 
       for (abfd = link_info.input_bfds; abfd; abfd = abfd->link.next)
diff --git a/ld/ld.texinfo b/ld/ld.texinfo
index 790b52f..44ad84b 100644
--- a/ld/ld.texinfo
+++ b/ld/ld.texinfo
@@ -4657,6 +4657,14 @@ SECTIONS @{
 @end group
 @end smallexample
 
+If an output section's name is the same as the input section's name
+and is representable as a C identifier, then the linker will
+automatically @pxref{PROVIDE} two symbols: __start_SECNAME and
+__stop_SECNAME, where SECNAME is the name of the section.  These
+indicate the start address and end address of the output section
+respectively.  Note: most section names are not representable as
+C identifiers because they contain a @samp{.} character.
+
 @node Output Section Data
 @subsection Output Section Data
 @cindex data
@@ -5841,14 +5849,6 @@ The command line options @samp{--orphan-handling} and @samp{--unique}
 (@pxref{Options,,Command Line Options}) can be used to control which
 output sections an orphan is placed in.
 
-If an orphaned section's name is representable as a C identifier then
-the linker will automatically @pxref{PROVIDE} two symbols:
-__start_SECNAME and __stop_SECNAME, where SECNAME is the name of the
-section.  These indicate the start address and end address of the
-orphaned section respectively.  Note: most section names are not
-representable as C identifiers because they contain a @samp{.}
-character.
-
 @node Location Counter
 @subsection The Location Counter
 @kindex .
diff --git a/ld/ldlang.c b/ld/ldlang.c
index 252400b..f8e4f52 100644
--- a/ld/ldlang.c
+++ b/ld/ldlang.c
@@ -1829,8 +1829,6 @@ lang_insert_orphan (asection *s,
 		    lang_statement_list_type *add_child)
 {
   lang_statement_list_type add;
-  const char *ps;
-  lang_assignment_statement_type *start_assign;
   lang_output_section_statement_type *os;
   lang_output_section_statement_type **os_tail;
 
@@ -1852,29 +1850,6 @@ lang_insert_orphan (asection *s,
   os = lang_enter_output_section_statement (secname, address, normal_section,
 					    NULL, NULL, NULL, constraint, 0);
 
-  ps = NULL;
-  start_assign = NULL;
-  if (config.build_constructors && *os_tail == os)
-    {
-      /* If the name of the section is representable in C, then create
-	 symbols to mark the start and the end of the section.  */
-      for (ps = secname; *ps != '\0'; ps++)
-	if (!ISALNUM ((unsigned char) *ps) && *ps != '_')
-	  break;
-      if (*ps == '\0')
-	{
-	  char *symname;
-
-	  symname = (char *) xmalloc (ps - secname + sizeof "__start_" + 1);
-	  symname[0] = bfd_get_symbol_leading_char (link_info.output_bfd);
-	  sprintf (symname + (symname[0] != 0), "__start_%s", secname);
-	  start_assign
-	    = lang_add_assignment (exp_provide (symname,
-						exp_nameop (NAME, "."),
-						FALSE));
-	}
-    }
-
   if (add_child == NULL)
     add_child = &os->children;
   lang_add_section (add_child, s, NULL, os);
@@ -1894,27 +1869,6 @@ lang_insert_orphan (asection *s,
     lang_leave_output_section_statement (NULL, DEFAULT_MEMORY_REGION, NULL,
 					 NULL);
 
-  if (start_assign != NULL)
-    {
-      char *symname;
-      lang_assignment_statement_type *stop_assign;
-      bfd_vma dot;
-
-      symname = (char *) xmalloc (ps - secname + sizeof "__stop_" + 1);
-      symname[0] = bfd_get_symbol_leading_char (link_info.output_bfd);
-      sprintf (symname + (symname[0] != 0), "__stop_%s", secname);
-      stop_assign
-	= lang_add_assignment (exp_provide (symname,
-					    exp_nameop (NAME, "."),
-					    FALSE));
-      /* Evaluate the expression to define the symbol if referenced,
-	 before sizing dynamic sections.  */
-      dot = os->bfd_section->vma;
-      exp_fold_tree (start_assign->exp, os->bfd_section, &dot);
-      dot += TO_ADDR (s->size);
-      exp_fold_tree (stop_assign->exp, os->bfd_section, &dot);
-    }
-
   /* Restore the global list pointer.  */
   if (after != NULL)
     pop_stat_ptr ();
@@ -5924,20 +5878,25 @@ section_for_dot (void)
   return bfd_abs_section_ptr;
 }
 
-/* Fix any .startof. or .sizeof. symbols.  When the assemblers see the
-   operator .startof. (section_name), it produces an undefined symbol
-   .startof.section_name.  Similarly, when it sees
+/* Fix any .startof., .sizeof., __start or __stop symbols.  When the
+   assemblers see the operator .startof. (section_name), it produces
+   an undefined symbol .startof.section_name.  Similarly, when it sees
    .sizeof. (section_name), it produces an undefined symbol
-   .sizeof.section_name.  For all the output sections, we look for
-   such symbols, and set them to the correct value.  */
+   .sizeof.section_name.  Also for ELF linker, __start_XXX or __stop_XXX
+   symbols should be resolved to the start and end of section XXX.  For
+   all the output sections, we look for such symbols, and set them to
+   the correct value.  */
 
 static void
 lang_set_startof (void)
 {
   asection *s;
+  char leading_char;
+  bfd_boolean is_elf = (bfd_get_flavour (link_info.output_bfd)
+			== bfd_target_elf_flavour);
+  bfd_boolean is_elocatable = bfd_link_relocatable (&link_info);
 
-  if (bfd_link_relocatable (&link_info))
-    return;
+  leading_char = bfd_get_symbol_leading_char (link_info.output_bfd);
 
   for (s = link_info.output_bfd->sections; s != NULL; s = s->next)
     {
@@ -5948,24 +5907,58 @@ lang_set_startof (void)
       secname = bfd_get_section_name (link_info.output_bfd, s);
       buf = (char *) xmalloc (10 + strlen (secname));
 
-      sprintf (buf, ".startof.%s", secname);
-      h = bfd_link_hash_lookup (link_info.hash, buf, FALSE, FALSE, TRUE);
-      if (h != NULL && h->type == bfd_link_hash_undefined)
+      if (!is_elocatable)
+	{
+	  sprintf (buf, ".startof.%s", secname);
+	  h = bfd_link_hash_lookup (link_info.hash, buf, FALSE, FALSE,
+				    TRUE);
+	  if (h != NULL && h->type == bfd_link_hash_undefined)
+	    {
+	      h->type = bfd_link_hash_defined;
+	      h->u.def.value = 0;
+	      h->u.def.section = s;
+	    }
+
+	  sprintf (buf, ".sizeof.%s", secname);
+	  h = bfd_link_hash_lookup (link_info.hash, buf, FALSE, FALSE,
+				    TRUE);
+	  if (h != NULL && h->type == bfd_link_hash_undefined)
+	    {
+	      h->type = bfd_link_hash_defined;
+	      h->u.def.value = TO_ADDR (s->size);
+	      h->u.def.section = bfd_abs_section_ptr;
+	    }
+	}
+
+      buf[0] = leading_char;
+      sprintf (buf + (buf[0] != 0), "__start_%s", secname);
+      h = bfd_link_hash_lookup (link_info.hash, buf, FALSE, FALSE,
+				TRUE);
+      if (h != NULL
+	  && (h->type == bfd_link_hash_undefined
+	      || h->type == bfd_link_hash_undefweak))
 	{
 	  h->type = bfd_link_hash_defined;
 	  h->u.def.value = 0;
 	  h->u.def.section = s;
+	  if (is_elf)
+	    ((struct elf_link_hash_entry *) h)->def_regular = 1;
 	}
 
-      sprintf (buf, ".sizeof.%s", secname);
-      h = bfd_link_hash_lookup (link_info.hash, buf, FALSE, FALSE, TRUE);
-      if (h != NULL && h->type == bfd_link_hash_undefined)
+      buf[0] = leading_char;
+      sprintf (buf + (buf[0] != 0), "__stop_%s", secname);
+      h = bfd_link_hash_lookup (link_info.hash, buf, FALSE, FALSE,
+				TRUE);
+      if (h != NULL
+	  && (h->type == bfd_link_hash_undefined
+	      || h->type == bfd_link_hash_undefweak))
 	{
 	  h->type = bfd_link_hash_defined;
 	  h->u.def.value = TO_ADDR (s->size);
-	  h->u.def.section = bfd_abs_section_ptr;
+	  h->u.def.section = s;
+	  if (is_elf)
+	    ((struct elf_link_hash_entry *) h)->def_regular = 1;
 	}
-
       free (buf);
     }
 }
diff --git a/ld/testsuite/ld-elf/pr21562a.d b/ld/testsuite/ld-elf/pr21562a.d
new file mode 100644
index 0000000..009dcfc
--- /dev/null
+++ b/ld/testsuite/ld-elf/pr21562a.d
@@ -0,0 +1,9 @@
+#ld: -shared -z defs --gc-sections
+#readelf: -s -S --wide
+#target: *-*-linux* *-*-gnu*
+
+#...
+  \[[ 0-9]+\] scnfoo[ \t]+PROGBITS[ \t]+[0-9a-f]+ +[0-9a-f]+ +0*10[ \t]+.*
+#...
+ +[0-9]+: +[0-9a-f]+ +[0-9a-f]+ +NOTYPE +LOCAL +DEFAULT +[0-9]+ +__start_scnfoo
+#pass
diff --git a/ld/testsuite/ld-elf/pr21562a.s b/ld/testsuite/ld-elf/pr21562a.s
new file mode 100644
index 0000000..ec36da4
--- /dev/null
+++ b/ld/testsuite/ld-elf/pr21562a.s
@@ -0,0 +1,8 @@
+        .section        scnfoo,"aw",%progbits
+        .zero 0x10
+
+        .globl  bar
+        .data
+        .type   bar, %object
+bar:
+        .dc.a   __start_scnfoo
diff --git a/ld/testsuite/ld-elf/pr21562a.t b/ld/testsuite/ld-elf/pr21562a.t
new file mode 100644
index 0000000..5e05ab3
--- /dev/null
+++ b/ld/testsuite/ld-elf/pr21562a.t
@@ -0,0 +1,3 @@
+SECTIONS {
+	scnfoo : { *(scnfoo) }
+}
diff --git a/ld/testsuite/ld-elf/pr21562b.d b/ld/testsuite/ld-elf/pr21562b.d
new file mode 100644
index 0000000..a03dbad
--- /dev/null
+++ b/ld/testsuite/ld-elf/pr21562b.d
@@ -0,0 +1,9 @@
+#ld: -shared -z defs --gc-sections
+#readelf: -s -S --wide
+#target: *-*-linux* *-*-gnu*
+
+#...
+  \[[ 0-9]+\] scnfoo[ \t]+PROGBITS[ \t]+[0-9a-f]+ +[0-9a-f]+ +0*10[ \t]+.*
+#...
+ +[0-9]+: +[0-9a-f]+ +[0-9a-f]+ +NOTYPE +LOCAL +DEFAULT +[0-9]+ +__stop_scnfoo
+#pass
diff --git a/ld/testsuite/ld-elf/pr21562b.s b/ld/testsuite/ld-elf/pr21562b.s
new file mode 100644
index 0000000..1732ee2
--- /dev/null
+++ b/ld/testsuite/ld-elf/pr21562b.s
@@ -0,0 +1,8 @@
+        .section        scnfoo,"aw",%progbits
+        .zero 0x10
+
+        .globl  bar
+        .data
+        .type   bar, %object
+bar:
+        .dc.a   __stop_scnfoo
diff --git a/ld/testsuite/ld-elf/pr21562b.t b/ld/testsuite/ld-elf/pr21562b.t
new file mode 100644
index 0000000..b30b521
--- /dev/null
+++ b/ld/testsuite/ld-elf/pr21562b.t
@@ -0,0 +1,5 @@
+SECTIONS {
+	PROVIDE (__start_scnfoo = .);
+	scnfoo : { *(scnfoo) }
+	PROVIDE (__stop_scnfoo = .);
+}
diff --git a/ld/testsuite/ld-elf/pr21562c.d b/ld/testsuite/ld-elf/pr21562c.d
new file mode 100644
index 0000000..9de035f
--- /dev/null
+++ b/ld/testsuite/ld-elf/pr21562c.d
@@ -0,0 +1,10 @@
+#source: pr21562a.s
+#ld: -shared -z defs --gc-sections -T pr21562a.t
+#readelf: -s -S --wide
+#target: *-*-linux* *-*-gnu*
+
+#...
+  \[[ 0-9]+\] scnfoo[ \t]+PROGBITS[ \t]+[0-9a-f]+ +[0-9a-f]+ +0*10[ \t]+.*
+#...
+ +[0-9]+: +[0-9a-f]+ +[0-9a-f]+ +NOTYPE +LOCAL +DEFAULT +[0-9]+ +__start_scnfoo
+#pass
diff --git a/ld/testsuite/ld-elf/pr21562c.t b/ld/testsuite/ld-elf/pr21562c.t
new file mode 100644
index 0000000..f9cb901
--- /dev/null
+++ b/ld/testsuite/ld-elf/pr21562c.t
@@ -0,0 +1,7 @@
+SECTIONS {
+    .foo : {
+	PROVIDE (__start_scnfoo = .);
+	*(scnfoo)
+	PROVIDE (__stop_scnfoo = .);
+    }
+}
diff --git a/ld/testsuite/ld-elf/pr21562d.d b/ld/testsuite/ld-elf/pr21562d.d
new file mode 100644
index 0000000..e5344ef
--- /dev/null
+++ b/ld/testsuite/ld-elf/pr21562d.d
@@ -0,0 +1,10 @@
+#source: pr21562b.s
+#ld: -shared -z defs --gc-sections -T pr21562a.t
+#readelf: -s -S --wide
+#target: *-*-linux* *-*-gnu*
+
+#...
+  \[[ 0-9]+\] scnfoo[ \t]+PROGBITS[ \t]+[0-9a-f]+ +[0-9a-f]+ +0*10[ \t]+.*
+#...
+ +[0-9]+: +[0-9a-f]+ +[0-9a-f]+ +NOTYPE +LOCAL +DEFAULT +[0-9]+ +__stop_scnfoo
+#pass
diff --git a/ld/testsuite/ld-elf/pr21562d.t b/ld/testsuite/ld-elf/pr21562d.t
new file mode 100644
index 0000000..c0cea61
--- /dev/null
+++ b/ld/testsuite/ld-elf/pr21562d.t
@@ -0,0 +1,5 @@
+SECTIONS {
+	PROVIDE (__start_scnfoo = .);
+	.foo : { *(scnfoo) }
+	PROVIDE (__stop_scnfoo = .);
+}
diff --git a/ld/testsuite/ld-elf/pr21562e.d b/ld/testsuite/ld-elf/pr21562e.d
new file mode 100644
index 0000000..afaf7e5
--- /dev/null
+++ b/ld/testsuite/ld-elf/pr21562e.d
@@ -0,0 +1,10 @@
+#source: pr21562a.s
+#ld: -shared -z defs
+#readelf: -s -S --wide
+#target: *-*-linux* *-*-gnu*
+
+#...
+  \[[ 0-9]+\] scnfoo[ \t]+PROGBITS[ \t]+[0-9a-f]+ +[0-9a-f]+ +0*10[ \t]+.*
+#...
+ +[0-9]+: +[0-9a-f]+ +[0-9a-f]+ +NOTYPE +LOCAL +DEFAULT +[0-9]+ +__start_scnfoo
+#pass
diff --git a/ld/testsuite/ld-elf/pr21562f.d b/ld/testsuite/ld-elf/pr21562f.d
new file mode 100644
index 0000000..b9c324a
--- /dev/null
+++ b/ld/testsuite/ld-elf/pr21562f.d
@@ -0,0 +1,10 @@
+#source: pr21562b.s
+#ld: -shared -z defs
+#readelf: -s -S --wide
+#target: *-*-linux* *-*-gnu*
+
+#...
+  \[[ 0-9]+\] scnfoo[ \t]+PROGBITS[ \t]+[0-9a-f]+ +[0-9a-f]+ +0*10[ \t]+.*
+#...
+ +[0-9]+: +[0-9a-f]+ +[0-9a-f]+ +NOTYPE +LOCAL +DEFAULT +[0-9]+ +__stop_scnfoo
+#pass
diff --git a/ld/testsuite/ld-elf/pr21562g.d b/ld/testsuite/ld-elf/pr21562g.d
new file mode 100644
index 0000000..a813594
--- /dev/null
+++ b/ld/testsuite/ld-elf/pr21562g.d
@@ -0,0 +1,10 @@
+#source: pr21562a.s
+#ld: -shared -z defs -T pr21562a.t
+#readelf: -s -S --wide
+#target: *-*-linux* *-*-gnu*
+
+#...
+  \[[ 0-9]+\] scnfoo[ \t]+PROGBITS[ \t]+[0-9a-f]+ +[0-9a-f]+ +0*10[ \t]+.*
+#...
+ +[0-9]+: +[0-9a-f]+ +[0-9a-f]+ +NOTYPE +LOCAL +DEFAULT +[0-9]+ +__start_scnfoo
+#pass
diff --git a/ld/testsuite/ld-elf/pr21562h.d b/ld/testsuite/ld-elf/pr21562h.d
new file mode 100644
index 0000000..6adabd7
--- /dev/null
+++ b/ld/testsuite/ld-elf/pr21562h.d
@@ -0,0 +1,10 @@
+#source: pr21562b.s
+#ld: -shared -z defs -T pr21562a.t
+#readelf: -s -S --wide
+#target: *-*-linux* *-*-gnu*
+
+#...
+  \[[ 0-9]+\] scnfoo[ \t]+PROGBITS[ \t]+[0-9a-f]+ +[0-9a-f]+ +0*10[ \t]+.*
+#...
+ +[0-9]+: +[0-9a-f]+ +[0-9a-f]+ +NOTYPE +LOCAL +DEFAULT +[0-9]+ +__stop_scnfoo
+#pass
diff --git a/ld/testsuite/ld-elf/pr21562i.d b/ld/testsuite/ld-elf/pr21562i.d
new file mode 100644
index 0000000..49eb2ec
--- /dev/null
+++ b/ld/testsuite/ld-elf/pr21562i.d
@@ -0,0 +1,10 @@
+#source: pr21562a.s
+#ld: -shared -z defs --gc-sections -T pr21562b.t
+#readelf: -s -S --wide
+#target: *-*-linux* *-*-gnu*
+
+#...
+  \[[ 0-9]+\] scnfoo[ \t]+PROGBITS[ \t]+[0-9a-f]+ +[0-9a-f]+ +0*10[ \t]+.*
+#...
+ +[0-9]+: +[0-9a-f]+ +[0-9a-f]+ +NOTYPE +LOCAL +DEFAULT +[0-9]+ +__start_scnfoo
+#pass
diff --git a/ld/testsuite/ld-elf/pr21562j.d b/ld/testsuite/ld-elf/pr21562j.d
new file mode 100644
index 0000000..14bb035
--- /dev/null
+++ b/ld/testsuite/ld-elf/pr21562j.d
@@ -0,0 +1,10 @@
+#source: pr21562b.s
+#ld: -shared -z defs --gc-sections -T pr21562b.t
+#readelf: -s -S --wide
+#target: *-*-linux* *-*-gnu*
+
+#...
+  \[[ 0-9]+\] scnfoo[ \t]+PROGBITS[ \t]+[0-9a-f]+ +[0-9a-f]+ +0*10[ \t]+.*
+#...
+ +[0-9]+: +[0-9a-f]+ +[0-9a-f]+ +NOTYPE +LOCAL +DEFAULT +[0-9]+ +__stop_scnfoo
+#pass
diff --git a/ld/testsuite/ld-elf/pr21562k.d b/ld/testsuite/ld-elf/pr21562k.d
new file mode 100644
index 0000000..1bf1e93
--- /dev/null
+++ b/ld/testsuite/ld-elf/pr21562k.d
@@ -0,0 +1,10 @@
+#source: pr21562a.s
+#ld: -shared -z defs --gc-sections -T pr21562c.t
+#readelf: -s -S --wide
+#target: *-*-linux* *-*-gnu*
+
+#...
+  \[[ 0-9]+\] \.foo[ \t]+PROGBITS[ \t]+[0-9a-f]+ +[0-9a-f]+ +0*10[ \t]+.*
+#...
+ +[0-9]+: +[0-9a-f]+ +[0-9a-f]+ +NOTYPE +LOCAL +DEFAULT +[0-9]+ +__start_scnfoo
+#pass
diff --git a/ld/testsuite/ld-elf/pr21562l.d b/ld/testsuite/ld-elf/pr21562l.d
new file mode 100644
index 0000000..8297ec2
--- /dev/null
+++ b/ld/testsuite/ld-elf/pr21562l.d
@@ -0,0 +1,10 @@
+#source: pr21562b.s
+#ld: -shared -z defs --gc-sections -T pr21562c.t
+#readelf: -s -S --wide
+#target: *-*-linux* *-*-gnu*
+
+#...
+  \[[ 0-9]+\] \.foo[ \t]+PROGBITS[ \t]+[0-9a-f]+ +[0-9a-f]+ +0*10[ \t]+.*
+#...
+ +[0-9]+: +[0-9a-f]+ +[0-9a-f]+ +NOTYPE +LOCAL +DEFAULT +[0-9]+ +__stop_scnfoo
+#pass
diff --git a/ld/testsuite/ld-elf/pr21562m.d b/ld/testsuite/ld-elf/pr21562m.d
new file mode 100644
index 0000000..34f8df0
--- /dev/null
+++ b/ld/testsuite/ld-elf/pr21562m.d
@@ -0,0 +1,10 @@
+#source: pr21562a.s
+#ld: -shared -z defs --gc-sections -T pr21562d.t
+#readelf: -s -S --wide
+#target: *-*-linux* *-*-gnu*
+
+#...
+  \[[ 0-9]+\] \.foo[ \t]+PROGBITS[ \t]+[0-9a-f]+ +[0-9a-f]+ +0*10[ \t]+.*
+#...
+ +[0-9]+: +[0-9a-f]+ +[0-9a-f]+ +NOTYPE +LOCAL +DEFAULT +[0-9]+ +__start_scnfoo
+#pass
diff --git a/ld/testsuite/ld-elf/pr21562n.d b/ld/testsuite/ld-elf/pr21562n.d
new file mode 100644
index 0000000..e4b1919
--- /dev/null
+++ b/ld/testsuite/ld-elf/pr21562n.d
@@ -0,0 +1,10 @@
+#source: pr21562b.s
+#ld: -shared -z defs --gc-sections -T pr21562d.t
+#readelf: -s -S --wide
+#target: *-*-linux* *-*-gnu*
+
+#...
+  \[[ 0-9]+\] \.foo[ \t]+PROGBITS[ \t]+[0-9a-f]+ +[0-9a-f]+ +0*10[ \t]+.*
+#...
+ +[0-9]+: +[0-9a-f]+ +[0-9a-f]+ +NOTYPE +LOCAL +DEFAULT +[0-9]+ +__stop_scnfoo
+#pass
diff --git a/ld/testsuite/ld-gc/gc.exp b/ld/testsuite/ld-gc/gc.exp
index ba5c46b..364c73b 100644
--- a/ld/testsuite/ld-gc/gc.exp
+++ b/ld/testsuite/ld-gc/gc.exp
@@ -119,6 +119,12 @@ if { [is_elf_format] && [check_shared_lib_support] } then {
 	run_dump_test "personality"
     }
     run_dump_test "pr18223"
+    if {![ld_assemble_flags $as $gasopt $srcdir/$subdir/pr20022a.s tmpdir/pr20022a.o]
+	|| ![ld_link $ld tmpdir/pr20022.so "-shared --gc-sections tmpdir/pr20022a.o"] } then {
+	fail pr20022
+    } else {
+	run_dump_test "pr20022"
+    }
 }
 
 if { [is_remote host] || [which $CC] != 0 } {
diff --git a/ld/testsuite/ld-gc/pr19161.d b/ld/testsuite/ld-gc/pr19161.d
index c36e663..baee8da 100644
--- a/ld/testsuite/ld-gc/pr19161.d
+++ b/ld/testsuite/ld-gc/pr19161.d
@@ -6,5 +6,5 @@
 #xfail: mips64vr-*-* msp430-*-* powerpc*-*-eabivle rl78-*-* rx-*-* sh*-*-*
 
 #...
-0*[1-9a-f]+[0-9a-f]*[ 	](D)[ 	]_*__start_my_section
+0*[1-9a-f]+[0-9a-f]*[ 	](d|D)[ 	]_*__start_my_section
 #...
diff --git a/ld/testsuite/ld-gc/pr20022.d b/ld/testsuite/ld-gc/pr20022.d
new file mode 100644
index 0000000..b51ec19
--- /dev/null
+++ b/ld/testsuite/ld-gc/pr20022.d
@@ -0,0 +1,11 @@
+#source: pr20022b.s
+#ld: --gc-sections -e _start tmpdir/pr20022.so
+#readelf: -SsW
+#target: *-*-linux* *-*-gnu*
+#notarget: *-*-*aout *-*-*oldld frv-*-linux* metag-*-linux*
+
+#...
+  \[[ 0-9]+\] _foo[ \t]+PROGBITS[ \t]+[0-9a-f]+ +[0-9a-f]+ +[0-9a-f]+[ \t]+.*
+#...
+ +[0-9]+: +[0-9a-f]+ +[0-9a-f]+ +NOTYPE +LOCAL +DEFAULT +[0-9]+ +__start__foo
+#pass
diff --git a/ld/testsuite/ld-gc/pr20022a.s b/ld/testsuite/ld-gc/pr20022a.s
new file mode 100644
index 0000000..6bd346f
--- /dev/null
+++ b/ld/testsuite/ld-gc/pr20022a.s
@@ -0,0 +1,8 @@
+	.data
+	.globl bar
+	.type bar,%object
+bar:
+	.dc.a	__start__foo
+	.section _foo,"aw",%progbits
+foo:
+	.ascii "This is bar"
diff --git a/ld/testsuite/ld-gc/pr20022b.s b/ld/testsuite/ld-gc/pr20022b.s
new file mode 100644
index 0000000..2306c59
--- /dev/null
+++ b/ld/testsuite/ld-gc/pr20022b.s
@@ -0,0 +1,8 @@
+	.text
+	.globl _start
+_start:
+	.dc.a	__start__foo
+	.dc.a	bar
+	.section _foo,"aw",%progbits
+foo:
+	.ascii "This is foo"
diff --git a/ld/testsuite/ld-gc/start.d b/ld/testsuite/ld-gc/start.d
index 18e74c1..9113b48 100644
--- a/ld/testsuite/ld-gc/start.d
+++ b/ld/testsuite/ld-gc/start.d
@@ -5,5 +5,5 @@
 #notarget: *-*-*aout *-*-*oldld frv-*-linux* metag-*-linux*
 
 #...
-[0-9a-f]+ D +__start__foo
+[0-9a-f]+ d +__start__foo
 #...
diff --git a/ld/testsuite/ld-x86-64/lea1a.d b/ld/testsuite/ld-x86-64/lea1a.d
index 9b662cb..28ea4b9 100644
--- a/ld/testsuite/ld-x86-64/lea1a.d
+++ b/ld/testsuite/ld-x86-64/lea1a.d
@@ -15,5 +15,5 @@ Disassembly of section .text:
 [ 	]*[a-f0-9]+:	48 8d 05 ([0-9a-f]{2} ){4} *	lea    -0x[a-f0-9]+\(%rip\),%rax        # [a-f0-9]+ <foo>
 [ 	]*[a-f0-9]+:	4c 8d 1d ([0-9a-f]{2} ){4} *	lea    0x[a-f0-9]+\(%rip\),%r11        # [a-f0-9]+ <bar>
 [ 	]*[a-f0-9]+:	48 8d 05 ([0-9a-f]{2} ){4} *	lea    0x[a-f0-9]+\(%rip\),%rax        # [a-f0-9]+ <__start_my_section>
-[ 	]*[a-f0-9]+:	4c 8d 1d ([0-9a-f]{2} ){4} *	lea    0x[a-f0-9]+\(%rip\),%r11        # [a-f0-9]+ <__stop_my_section>
+[ 	]*[a-f0-9]+:	4c 8d 1d ([0-9a-f]{2} ){4} *	lea    0x[a-f0-9]+\(%rip\),%r11        # [a-f0-9]+ <.*>
 #pass
diff --git a/ld/testsuite/ld-x86-64/lea1b.d b/ld/testsuite/ld-x86-64/lea1b.d
index 9108149..c7873cd 100644
--- a/ld/testsuite/ld-x86-64/lea1b.d
+++ b/ld/testsuite/ld-x86-64/lea1b.d
@@ -15,5 +15,5 @@ Disassembly of section .text:
 [ 	]*[a-f0-9]+:	48 8d 05 ([0-9a-f]{2} ){4} *	lea    -0x[a-f0-9]+\(%rip\),%rax        # [a-f0-9]+ <foo>
 [ 	]*[a-f0-9]+:	4c 8d 1d ([0-9a-f]{2} ){4} *	lea    0x[a-f0-9]+\(%rip\),%r11        # [a-f0-9]+ <bar>
 [ 	]*[a-f0-9]+:	48 8d 05 ([0-9a-f]{2} ){4} *	lea    0x[a-f0-9]+\(%rip\),%rax        # [a-f0-9]+ <__start_my_section>
-[ 	]*[a-f0-9]+:	4c 8d 1d ([0-9a-f]{2} ){4} *	lea    0x[a-f0-9]+\(%rip\),%r11        # [a-f0-9]+ <__stop_my_section>
+[ 	]*[a-f0-9]+:	4c 8d 1d ([0-9a-f]{2} ){4} *	lea    0x[a-f0-9]+\(%rip\),%r11        # [a-f0-9]+ <.*>
 #pass
diff --git a/ld/testsuite/ld-x86-64/lea1d.d b/ld/testsuite/ld-x86-64/lea1d.d
index 4d708d2..70fc603 100644
--- a/ld/testsuite/ld-x86-64/lea1d.d
+++ b/ld/testsuite/ld-x86-64/lea1d.d
@@ -15,5 +15,5 @@ Disassembly of section .text:
 [ 	]*[a-f0-9]+:	48 8d 05 ([0-9a-f]{2} ){4} *	lea    -0x[a-f0-9]+\(%rip\),%rax        # [a-f0-9]+ <foo>
 [ 	]*[a-f0-9]+:	4c 8d 1d ([0-9a-f]{2} ){4} *	lea    0x[a-f0-9]+\(%rip\),%r11        # [a-f0-9]+ <bar>
 [ 	]*[a-f0-9]+:	48 8d 05 ([0-9a-f]{2} ){4} *	lea    0x[a-f0-9]+\(%rip\),%rax        # [a-f0-9]+ <__start_my_section>
-[ 	]*[a-f0-9]+:	4c 8d 1d ([0-9a-f]{2} ){4} *	lea    0x[a-f0-9]+\(%rip\),%r11        # [a-f0-9]+ <__stop_my_section>
+[ 	]*[a-f0-9]+:	4c 8d 1d ([0-9a-f]{2} ){4} *	lea    0x[a-f0-9]+\(%rip\),%r11        # [a-f0-9]+ <.*>
 #pass
diff --git a/ld/testsuite/ld-x86-64/lea1e.d b/ld/testsuite/ld-x86-64/lea1e.d
index da60137..123fcd2 100644
--- a/ld/testsuite/ld-x86-64/lea1e.d
+++ b/ld/testsuite/ld-x86-64/lea1e.d
@@ -15,5 +15,5 @@ Disassembly of section .text:
 [ 	]*[a-f0-9]+:	48 8d 05 ([0-9a-f]{2} ){4} *	lea    -0x[a-f0-9]+\(%rip\),%rax        # [a-f0-9]+ <foo>
 [ 	]*[a-f0-9]+:	4c 8d 1d ([0-9a-f]{2} ){4} *	lea    0x[a-f0-9]+\(%rip\),%r11        # [a-f0-9]+ <bar>
 [ 	]*[a-f0-9]+:	48 8d 05 ([0-9a-f]{2} ){4} *	lea    0x[a-f0-9]+\(%rip\),%rax        # [a-f0-9]+ <__start_my_section>
-[ 	]*[a-f0-9]+:	4c 8d 1d ([0-9a-f]{2} ){4} *	lea    0x[a-f0-9]+\(%rip\),%r11        # [a-f0-9]+ <__stop_my_section>
+[ 	]*[a-f0-9]+:	4c 8d 1d ([0-9a-f]{2} ){4} *	lea    0x[a-f0-9]+\(%rip\),%r11        # [a-f0-9]+ <.*>
 #pass
-- 
2.9.4


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

* Re: [PATCH] Always define referenced __start_SECNAME/__stop_SECNAME
  2017-06-13 15:22               ` H.J. Lu
  2017-06-13 15:31                 ` H.J. Lu
@ 2017-06-13 19:07                 ` H.J. Lu
  2017-06-13 20:06                   ` H.J. Lu
  1 sibling, 1 reply; 16+ messages in thread
From: H.J. Lu @ 2017-06-13 19:07 UTC (permalink / raw)
  To: Alan Modra; +Cc: Binutils

[-- Attachment #1: Type: text/plain, Size: 4646 bytes --]

On Tue, Jun 13, 2017 at 8:22 AM, H.J. Lu <hjl.tools@gmail.com> wrote:
> On Tue, Jun 13, 2017 at 7:28 AM, Alan Modra <amodra@gmail.com> wrote:
>> On Tue, Jun 13, 2017 at 05:38:45AM -0700, H.J. Lu wrote:
>>> On Tue, Jun 13, 2017 at 5:26 AM, Alan Modra <amodra@gmail.com> wrote:
>>> > On Mon, Jun 12, 2017 at 07:10:47PM -0700, H.J. Lu wrote:
>>> >> On Mon, Jun 12, 2017 at 6:54 PM, Alan Modra <amodra@gmail.com> wrote:
>>> >> > On Mon, Jun 12, 2017 at 05:18:58PM -0700, H.J. Lu wrote:
>>> >> >> On Mon, Jun 12, 2017 at 4:32 PM, Alan Modra <amodra@gmail.com> wrote:
>>> >> >> > On Sat, Jun 10, 2017 at 03:46:49PM -0700, H.J. Lu wrote:
>>> >> >> >> This patch changes linker to always define referenced __start_SECNAME and
>>> >> >> >> __stop_SECNAME if the input section name is the same output section name,
>>> >> >> >> which is always true for orphaned sections, and SECNAME is a C identifier.
>>> >> >> >
>>> >> >> > I think this change is reasonable.
>>> >> >> >
>>> >> >> >> Also __start_SECNAME and __stop_SECNAME symbols are marked as hidden by
>>> >> >> >> ELF linker.
>>> >> >> >
>>> >> >> > Why is this necessary?  Also, you make another change in behaviour
>>> >> >>
>>> >> >> It is to make sure that  __start_SECNAME and __stop_SECNAME
>>> >> >> symbols     for section SECNAME in different modules are unique.
>>> >> >
>>> >> > I understand, and it would have been good if these symbols were
>>> >> > defined that way in the beginning, but they weren't.  I'm concerned
>>> >> > that if you make this change as well we will find some code that
>>> >> > relies on the symbols being dynamic.
>>> >>
>>> >> My change fixes a real bug:
>>> >>
>>> >> https://sourceware.org/bugzilla/show_bug.cgi?id=20022
>>> >
>>> > Really, your change is a workaround not a fix.  You avoid exporting
>>> > __start or __stop symbols because doing so shows a problem with gc.  A
>>> > real fix for the PR would make ld do the right thing even in the
>>> > presense of exported dynamic symbols.
>>>
>>> Exporting __start_SECNAME and __stop_SECNAME as dynamic
>>> symbols may lead to unexpected behavior.  Reference to __start_SECNAME
>>> and __stop_SECNAME to section SECNAME within a DSO will be
>>> resolved to __start_SECNAME and __stop_SECNAME in another DSO
>>> or executable.  In most cases, it isn't the intended behavior and there are
>>> workaround if it is needed.
>>
>> You're correct regarding shared libraries.  I was thinking more about
>> an executable when I said the patch was a workaround.  OK, so I
>> suppose we should leave that in, and wait to see if we get complaints.
>>
>>> >> We can suggest workarounds if some codes depend on that.
>>> >>
>>> >> >>
>>> >> >> > that you don't mention:  __start and __stop symbols were previously
>>> >> >> > defined by ld -Ur, not just at final link.  You'll need to modify
>>> >> >>
>>> >> >> Is there a testcase for this behavior?
>>> >> >
>>> >> > Not that I'm aware of.
>>> >> >
>>> >>
>>> >> >From ld manual:
>>> >>
>>> >> '-Ur'
>>> >>      For anything other than C++ programs, this option is equivalent to
>>> >>      '-r': it generates relocatable output--i.e., an output file that
>>> >>      can in turn serve as input to 'ld'.  When linking C++ programs,
>>> >>      '-Ur' _does_ resolve references to constructors, unlike '-r'.  It
>>> >>      does not work to use '-Ur' on files that were themselves linked
>>> >>      with '-Ur'; once the constructor table has been built, it cannot be
>>> >>      added to.  Use '-Ur' only for the last partial link, and '-r' for
>>> >>      the others.
>>> >>
>>> >> It isn't intended for  __start_SECNAME and __stop_SECNAME.  Check
>>> >> config.build_constructors for __start_SECNAME and __stop_SECNAME
>>> >> was introduced by:
>>> >>
>>> >> commit 71bfc0aef6964c54b8e29466e97fb246cdeb2049
>>> >> Author: Alan Modra <amodra@gmail.com>
>>> >> Date:   Thu Sep 7 07:08:58 2000 +0000
>>> >>
>>> >>     Fix list handling for orphan section output statements.
>>> >
>>> > That's a long time ago.  Prior to that patch, ld defined __start and
>>> > __stop symbols for ld -r, which can lead to unexpected results for the
>>> > unwary.  I can't remember, but I suspect I changed ld to define the
>>> > symbols for -Ur so that people who wanted the previous ld -r behaviour
>>> > for __start and __stop could get that by using ld -Ur.
>>> >
>>>
>>> If it is the case, it isn't intended usage for ld -Ur and people shouldn't
>>> depend on it.
>>
>> Please leave that behaviour unchanged.
>>
>
> I am checking this patch to verify it and I will update my patch.
>
>

I checked in this patch to add some tests for .startof.SECNAME
and sizeof.SECNAME.


-- 
H.J.

[-- Attachment #2: 0001-ld-Add-tests-for-.startof.SECNAME-.sizeof.SECNAME.patch --]
[-- Type: text/x-patch, Size: 3422 bytes --]

From da614360f520b84a9c87506eb0c880f7a056468b Mon Sep 17 00:00:00 2001
From: "H.J. Lu" <hjl.tools@gmail.com>
Date: Tue, 13 Jun 2017 12:03:40 -0700
Subject: [PATCH] ld: Add tests for .startof.SECNAME/.sizeof.SECNAME

	* testsuite/ld-elf/sizeof.d: Renamed to ...
	* testsuite/ld-elf/sizeofa.d: This.  Updated.
	* testsuite/ld-elf/startof.d: Renamed to ...
	* testsuite/ld-elf/startofa.d: This.  Updated.
	* testsuite/ld-elf/sizeofb.d: New file.
	* testsuite/ld-elf/startofb.d: Likewise.
---
 ld/ChangeLog                                  |  9 +++++++++
 ld/testsuite/ld-elf/{sizeof.d => sizeofa.d}   |  1 +
 ld/testsuite/ld-elf/sizeofb.d                 | 13 +++++++++++++
 ld/testsuite/ld-elf/{startof.d => startofa.d} |  1 +
 ld/testsuite/ld-elf/startofb.d                | 13 +++++++++++++
 5 files changed, 37 insertions(+)
 rename ld/testsuite/ld-elf/{sizeof.d => sizeofa.d} (94%)
 create mode 100644 ld/testsuite/ld-elf/sizeofb.d
 rename ld/testsuite/ld-elf/{startof.d => startofa.d} (94%)
 create mode 100644 ld/testsuite/ld-elf/startofb.d

diff --git a/ld/ChangeLog b/ld/ChangeLog
index dcfc602..59c99ae 100644
--- a/ld/ChangeLog
+++ b/ld/ChangeLog
@@ -1,5 +1,14 @@
 2017-06-13  H.J. Lu  <hongjiu.lu@intel.com>
 
+	* testsuite/ld-elf/sizeof.d: Renamed to ...
+	* testsuite/ld-elf/sizeofa.d: This.  Updated.
+	* testsuite/ld-elf/startof.d: Renamed to ...
+	* testsuite/ld-elf/startofa.d: This.  Updated.
+	* testsuite/ld-elf/sizeofb.d: New file.
+	* testsuite/ld-elf/startofb.d: Likewise.
+
+2017-06-13  H.J. Lu  <hongjiu.lu@intel.com>
+
 	PR ld/20022
 	PR ld/21557
 	PR ld/21562
diff --git a/ld/testsuite/ld-elf/sizeof.d b/ld/testsuite/ld-elf/sizeofa.d
similarity index 94%
rename from ld/testsuite/ld-elf/sizeof.d
rename to ld/testsuite/ld-elf/sizeofa.d
index 7cad75a..0aac607 100644
--- a/ld/testsuite/ld-elf/sizeof.d
+++ b/ld/testsuite/ld-elf/sizeofa.d
@@ -1,3 +1,4 @@
+#source: sizeof.s
 #ld: -Ur
 #readelf: -sW
 
diff --git a/ld/testsuite/ld-elf/sizeofb.d b/ld/testsuite/ld-elf/sizeofb.d
new file mode 100644
index 0000000..331c386
--- /dev/null
+++ b/ld/testsuite/ld-elf/sizeofb.d
@@ -0,0 +1,13 @@
+#source: sizeof.s
+#ld: -shared
+#readelf: -sW
+#target: *-*-linux* *-*-gnu*
+
+Symbol table '\.dynsym' contains [0-9]+ entries:
+ +Num: +Value +Size Type +Bind +Vis +Ndx Name
+ +0: 0+ +0 +NOTYPE +LOCAL +DEFAULT +UND +
+#...
+ +[0-9]+: +[a-f0-9]+ +0 +NOTYPE +LOCAL +DEFAULT +[0-9]+ +__stop_scnfoo
+#...
+ +[0-9]+: 0+10 + +0 +NOTYPE +GLOBAL +DEFAULT +ABS +.sizeof.scnfoo
+#pass
diff --git a/ld/testsuite/ld-elf/startof.d b/ld/testsuite/ld-elf/startofa.d
similarity index 94%
rename from ld/testsuite/ld-elf/startof.d
rename to ld/testsuite/ld-elf/startofa.d
index cf1f064..00ab27e 100644
--- a/ld/testsuite/ld-elf/startof.d
+++ b/ld/testsuite/ld-elf/startofa.d
@@ -1,3 +1,4 @@
+#source: startof.s
 #ld: -Ur
 #readelf: -sW
 
diff --git a/ld/testsuite/ld-elf/startofb.d b/ld/testsuite/ld-elf/startofb.d
new file mode 100644
index 0000000..e03bd23
--- /dev/null
+++ b/ld/testsuite/ld-elf/startofb.d
@@ -0,0 +1,13 @@
+#source: startof.s
+#ld: -shared
+#readelf: -sW
+#target: *-*-linux* *-*-gnu*
+
+Symbol table '\.dynsym' contains [0-9]+ entries:
+ +Num: +Value +Size Type +Bind +Vis +Ndx Name
+ +0: 0+ +0 +NOTYPE +LOCAL +DEFAULT +UND +
+#...
+ +[0-9]+: +[a-f0-9]+ +0 +NOTYPE +GLOBAL +DEFAULT +[0-9]+ +.startof.scnfoo
+#...
+ +[0-9]+: +[a-f0-9]+ +0 +NOTYPE +LOCAL +DEFAULT +[0-9]+ +__start_scnfoo
+#pass
-- 
2.9.4


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

* Re: [PATCH] Always define referenced __start_SECNAME/__stop_SECNAME
  2017-06-13 19:07                 ` H.J. Lu
@ 2017-06-13 20:06                   ` H.J. Lu
  2017-06-14  3:50                     ` Alan Modra
  0 siblings, 1 reply; 16+ messages in thread
From: H.J. Lu @ 2017-06-13 20:06 UTC (permalink / raw)
  To: Alan Modra; +Cc: Binutils

[-- Attachment #1: Type: text/plain, Size: 4875 bytes --]

On Tue, Jun 13, 2017 at 12:07 PM, H.J. Lu <hjl.tools@gmail.com> wrote:
> On Tue, Jun 13, 2017 at 8:22 AM, H.J. Lu <hjl.tools@gmail.com> wrote:
>> On Tue, Jun 13, 2017 at 7:28 AM, Alan Modra <amodra@gmail.com> wrote:
>>> On Tue, Jun 13, 2017 at 05:38:45AM -0700, H.J. Lu wrote:
>>>> On Tue, Jun 13, 2017 at 5:26 AM, Alan Modra <amodra@gmail.com> wrote:
>>>> > On Mon, Jun 12, 2017 at 07:10:47PM -0700, H.J. Lu wrote:
>>>> >> On Mon, Jun 12, 2017 at 6:54 PM, Alan Modra <amodra@gmail.com> wrote:
>>>> >> > On Mon, Jun 12, 2017 at 05:18:58PM -0700, H.J. Lu wrote:
>>>> >> >> On Mon, Jun 12, 2017 at 4:32 PM, Alan Modra <amodra@gmail.com> wrote:
>>>> >> >> > On Sat, Jun 10, 2017 at 03:46:49PM -0700, H.J. Lu wrote:
>>>> >> >> >> This patch changes linker to always define referenced __start_SECNAME and
>>>> >> >> >> __stop_SECNAME if the input section name is the same output section name,
>>>> >> >> >> which is always true for orphaned sections, and SECNAME is a C identifier.
>>>> >> >> >
>>>> >> >> > I think this change is reasonable.
>>>> >> >> >
>>>> >> >> >> Also __start_SECNAME and __stop_SECNAME symbols are marked as hidden by
>>>> >> >> >> ELF linker.
>>>> >> >> >
>>>> >> >> > Why is this necessary?  Also, you make another change in behaviour
>>>> >> >>
>>>> >> >> It is to make sure that  __start_SECNAME and __stop_SECNAME
>>>> >> >> symbols     for section SECNAME in different modules are unique.
>>>> >> >
>>>> >> > I understand, and it would have been good if these symbols were
>>>> >> > defined that way in the beginning, but they weren't.  I'm concerned
>>>> >> > that if you make this change as well we will find some code that
>>>> >> > relies on the symbols being dynamic.
>>>> >>
>>>> >> My change fixes a real bug:
>>>> >>
>>>> >> https://sourceware.org/bugzilla/show_bug.cgi?id=20022
>>>> >
>>>> > Really, your change is a workaround not a fix.  You avoid exporting
>>>> > __start or __stop symbols because doing so shows a problem with gc.  A
>>>> > real fix for the PR would make ld do the right thing even in the
>>>> > presense of exported dynamic symbols.
>>>>
>>>> Exporting __start_SECNAME and __stop_SECNAME as dynamic
>>>> symbols may lead to unexpected behavior.  Reference to __start_SECNAME
>>>> and __stop_SECNAME to section SECNAME within a DSO will be
>>>> resolved to __start_SECNAME and __stop_SECNAME in another DSO
>>>> or executable.  In most cases, it isn't the intended behavior and there are
>>>> workaround if it is needed.
>>>
>>> You're correct regarding shared libraries.  I was thinking more about
>>> an executable when I said the patch was a workaround.  OK, so I
>>> suppose we should leave that in, and wait to see if we get complaints.
>>>
>>>> >> We can suggest workarounds if some codes depend on that.
>>>> >>
>>>> >> >>
>>>> >> >> > that you don't mention:  __start and __stop symbols were previously
>>>> >> >> > defined by ld -Ur, not just at final link.  You'll need to modify
>>>> >> >>
>>>> >> >> Is there a testcase for this behavior?
>>>> >> >
>>>> >> > Not that I'm aware of.
>>>> >> >
>>>> >>
>>>> >> >From ld manual:
>>>> >>
>>>> >> '-Ur'
>>>> >>      For anything other than C++ programs, this option is equivalent to
>>>> >>      '-r': it generates relocatable output--i.e., an output file that
>>>> >>      can in turn serve as input to 'ld'.  When linking C++ programs,
>>>> >>      '-Ur' _does_ resolve references to constructors, unlike '-r'.  It
>>>> >>      does not work to use '-Ur' on files that were themselves linked
>>>> >>      with '-Ur'; once the constructor table has been built, it cannot be
>>>> >>      added to.  Use '-Ur' only for the last partial link, and '-r' for
>>>> >>      the others.
>>>> >>
>>>> >> It isn't intended for  __start_SECNAME and __stop_SECNAME.  Check
>>>> >> config.build_constructors for __start_SECNAME and __stop_SECNAME
>>>> >> was introduced by:
>>>> >>
>>>> >> commit 71bfc0aef6964c54b8e29466e97fb246cdeb2049
>>>> >> Author: Alan Modra <amodra@gmail.com>
>>>> >> Date:   Thu Sep 7 07:08:58 2000 +0000
>>>> >>
>>>> >>     Fix list handling for orphan section output statements.
>>>> >
>>>> > That's a long time ago.  Prior to that patch, ld defined __start and
>>>> > __stop symbols for ld -r, which can lead to unexpected results for the
>>>> > unwary.  I can't remember, but I suspect I changed ld to define the
>>>> > symbols for -Ur so that people who wanted the previous ld -r behaviour
>>>> > for __start and __stop could get that by using ld -Ur.
>>>> >
>>>>
>>>> If it is the case, it isn't intended usage for ld -Ur and people shouldn't
>>>> depend on it.
>>>
>>> Please leave that behaviour unchanged.
>>>
>>
>> I am checking this patch to verify it and I will update my patch.
>>
>>
>
> I checked in this patch to add some tests for .startof.SECNAME
> and sizeof.SECNAME.
>

Don't define __start_SECNAME/__stop_SECNAME for -r.


-- 
H.J.

[-- Attachment #2: 0001-ld-Don-t-define-__start_SECNAME-__stop_SECNAME-for-r.patch --]
[-- Type: text/x-patch, Size: 3421 bytes --]

From b27685f2016c510d03ac9a64f7b04ce8efcf95c4 Mon Sep 17 00:00:00 2001
From: "H.J. Lu" <hjl.tools@gmail.com>
Date: Tue, 13 Jun 2017 13:04:56 -0700
Subject: [PATCH] ld: Don't define __start_SECNAME/__stop_SECNAME for -r

__start_SECNAME and __stop_SECNAME shouldn't be defined for "ld -r".

	* ldlang.c (lang_set_startof): Skip if config.build_constructors
	is FALSE.
	* testsuite/ld-elf/sizeofc.d: New file.
	* testsuite/ld-elf/startofc.d: Likewise.
---
 ld/ChangeLog                   |  7 +++++++
 ld/ldlang.c                    | 14 ++++++++++----
 ld/testsuite/ld-elf/sizeofc.d  | 12 ++++++++++++
 ld/testsuite/ld-elf/startofc.d | 12 ++++++++++++
 4 files changed, 41 insertions(+), 4 deletions(-)
 create mode 100644 ld/testsuite/ld-elf/sizeofc.d
 create mode 100644 ld/testsuite/ld-elf/startofc.d

diff --git a/ld/ChangeLog b/ld/ChangeLog
index 59c99ae..7995de8 100644
--- a/ld/ChangeLog
+++ b/ld/ChangeLog
@@ -1,5 +1,12 @@
 2017-06-13  H.J. Lu  <hongjiu.lu@intel.com>
 
+	* ldlang.c (lang_set_startof): Skip if config.build_constructors
+	is FALSE.
+	* testsuite/ld-elf/sizeofc.d: New file.
+	* testsuite/ld-elf/startofc.d: Likewise.
+
+2017-06-13  H.J. Lu  <hongjiu.lu@intel.com>
+
 	* testsuite/ld-elf/sizeof.d: Renamed to ...
 	* testsuite/ld-elf/sizeofa.d: This.  Updated.
 	* testsuite/ld-elf/startof.d: Renamed to ...
diff --git a/ld/ldlang.c b/ld/ldlang.c
index f8e4f52..eb4ba9e 100644
--- a/ld/ldlang.c
+++ b/ld/ldlang.c
@@ -5892,9 +5892,15 @@ lang_set_startof (void)
 {
   asection *s;
   char leading_char;
-  bfd_boolean is_elf = (bfd_get_flavour (link_info.output_bfd)
-			== bfd_target_elf_flavour);
-  bfd_boolean is_elocatable = bfd_link_relocatable (&link_info);
+  bfd_boolean is_elf;
+  bfd_boolean is_relocatable;
+
+  if (!config.build_constructors)
+    return;
+
+  is_elf = (bfd_get_flavour (link_info.output_bfd)
+	    == bfd_target_elf_flavour);
+  is_relocatable = bfd_link_relocatable (&link_info);
 
   leading_char = bfd_get_symbol_leading_char (link_info.output_bfd);
 
@@ -5907,7 +5913,7 @@ lang_set_startof (void)
       secname = bfd_get_section_name (link_info.output_bfd, s);
       buf = (char *) xmalloc (10 + strlen (secname));
 
-      if (!is_elocatable)
+      if (!is_relocatable)
 	{
 	  sprintf (buf, ".startof.%s", secname);
 	  h = bfd_link_hash_lookup (link_info.hash, buf, FALSE, FALSE,
diff --git a/ld/testsuite/ld-elf/sizeofc.d b/ld/testsuite/ld-elf/sizeofc.d
new file mode 100644
index 0000000..1cff854
--- /dev/null
+++ b/ld/testsuite/ld-elf/sizeofc.d
@@ -0,0 +1,12 @@
+#source: sizeof.s
+#ld: -r
+#readelf: -sW
+
+Symbol table '\.symtab' contains [0-9]+ entries:
+ +Num: +Value +Size Type +Bind +Vis +Ndx Name
+ +0: 0+ +0 +NOTYPE +LOCAL +DEFAULT +UND +
+#...
+ +[0-9]+: +[a-f0-9]+ +0 +NOTYPE +GLOBAL +DEFAULT +UND +__stop_scnfoo
+#...
+ +[0-9]+: +[a-f0-9]+ +0 +NOTYPE +GLOBAL +DEFAULT +UND +.sizeof.scnfoo
+#pass
diff --git a/ld/testsuite/ld-elf/startofc.d b/ld/testsuite/ld-elf/startofc.d
new file mode 100644
index 0000000..4005625
--- /dev/null
+++ b/ld/testsuite/ld-elf/startofc.d
@@ -0,0 +1,12 @@
+#source: startof.s
+#ld: -r
+#readelf: -sW
+
+Symbol table '\.symtab' contains [0-9]+ entries:
+ +Num: +Value +Size Type +Bind +Vis +Ndx Name
+ +0: 0+ +0 +NOTYPE +LOCAL +DEFAULT +UND +
+#...
+ +[0-9]+: +[a-f0-9]+ +0 +NOTYPE +GLOBAL +DEFAULT +UND +.startof.scnfoo
+#...
+ +[0-9]+: +[a-f0-9]+ +0 +NOTYPE +GLOBAL +DEFAULT +UND +__start_scnfoo
+#pass
-- 
2.9.4


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

* Re: [PATCH] Always define referenced __start_SECNAME/__stop_SECNAME
  2017-06-13 20:06                   ` H.J. Lu
@ 2017-06-14  3:50                     ` Alan Modra
  2017-06-14 13:20                       ` H.J. Lu
  0 siblings, 1 reply; 16+ messages in thread
From: Alan Modra @ 2017-06-14  3:50 UTC (permalink / raw)
  To: H.J. Lu; +Cc: Binutils

I see these fails.  Please investigate and fix.  The powerpc-linux
fails are due to leaving the __start and __stop symbols undefined when
sizing dynamic sections, which is wrong.  That at least needs to be
fixed so that allocate_dynrelocs doesn't see an undefined hidden
visibility symbol.

bfin-elf  +FAIL: ld-elf/sizeofa
bfin-elf  +FAIL: ld-elf/startofa
cr16-elf  +FAIL: ld-elf/sizeofa
cr16-elf  +FAIL: ld-elf/sizeofc
cr16-elf  +FAIL: ld-elf/startofa
cr16-elf  +FAIL: ld-elf/startofc
cris-elf  +FAIL: ld-elf/sizeofa
cris-elf  +FAIL: ld-elf/startofa
crx-elf  +FAIL: ld-elf/sizeofa
crx-elf  +FAIL: ld-elf/sizeofc
crx-elf  +FAIL: ld-elf/startofa
crx-elf  +FAIL: ld-elf/startofc
epiphany-elf  +FAIL: ld-elf/sizeofa
epiphany-elf  +FAIL: ld-elf/startofa
h8300-elf  +FAIL: ld-elf/sizeofa
h8300-elf  +FAIL: ld-elf/startofa
hppa64-linux  +FAIL: ld-elf/pr21562a
hppa64-linux  +FAIL: ld-elf/pr21562b
hppa64-linux  +FAIL: ld-elf/pr21562c
hppa64-linux  +FAIL: ld-elf/pr21562d
hppa64-linux  +FAIL: ld-elf/pr21562i
hppa64-linux  +FAIL: ld-elf/pr21562j
hppa64-linux  +FAIL: ld-elf/pr21562k
hppa64-linux  +FAIL: ld-elf/pr21562l
hppa64-linux  +FAIL: ld-elf/pr21562m
hppa64-linux  +FAIL: ld-elf/pr21562n
ia64-linux  +FAIL: ld-elf/pr21562a
ia64-linux  +FAIL: ld-elf/pr21562b
ia64-linux  +FAIL: ld-elf/pr21562c
ia64-linux  +FAIL: ld-elf/pr21562d
ia64-linux  +FAIL: ld-elf/pr21562i
ia64-linux  +FAIL: ld-elf/pr21562j
ia64-linux  +FAIL: ld-elf/pr21562k
ia64-linux  +FAIL: ld-elf/pr21562l
ia64-linux  +FAIL: ld-elf/pr21562m
ia64-linux  +FAIL: ld-elf/pr21562n
ip2k-elf  +FAIL: ld-elf/sizeofa
ip2k-elf  +FAIL: ld-elf/startofa
m32c-elf  +FAIL: ld-elf/sizeofa
m32c-elf  +FAIL: ld-elf/startofa
metag-linux  +FAIL: ld-elf/pr21562a
metag-linux  +FAIL: ld-elf/pr21562b
metag-linux  +FAIL: ld-elf/pr21562c
metag-linux  +FAIL: ld-elf/pr21562d
metag-linux  +FAIL: ld-elf/pr21562e
metag-linux  +FAIL: ld-elf/pr21562f
metag-linux  +FAIL: ld-elf/pr21562g
metag-linux  +FAIL: ld-elf/pr21562h
metag-linux  +FAIL: ld-elf/pr21562i
metag-linux  +FAIL: ld-elf/pr21562j
metag-linux  +FAIL: ld-elf/pr21562k
metag-linux  +FAIL: ld-elf/pr21562l
metag-linux  +FAIL: ld-elf/pr21562m
metag-linux  +FAIL: ld-elf/pr21562n
metag-linux  +FAIL: ld-elf/sizeofa
metag-linux  +FAIL: ld-elf/sizeofb
metag-linux  +FAIL: ld-elf/startofa
metag-linux  +FAIL: ld-elf/startofb
mips64-linux  +FAIL: ld-gc/pr20022
mipsel-linux-gnu  +FAIL: ld-gc/pr20022
mipsisa32el-linux  +FAIL: ld-gc/pr20022
mips-linux  +FAIL: ld-gc/pr20022
mn10200-elf  +FAIL: ld-elf/sizeofa
mn10200-elf  +FAIL: ld-elf/startofa
mn10300-elf  +FAIL: ld-elf/sizeofa
mn10300-elf  +FAIL: ld-elf/startofa
nios2-linux  +FAIL: ld-gc/pr20022
powerpc-eabisim  +FAIL: pr20022
powerpc-eabivle  +FAIL: pr20022
powerpcle-elf  +FAIL: pr20022
powerpc-linux  +FAIL: ld-elf/pr21562a
powerpc-linux  +FAIL: ld-elf/pr21562b
powerpc-linux  +FAIL: ld-elf/pr21562c
powerpc-linux  +FAIL: ld-elf/pr21562d
powerpc-linux  +FAIL: ld-elf/pr21562e
powerpc-linux  +FAIL: ld-elf/pr21562f
powerpc-linux  +FAIL: ld-elf/pr21562g
powerpc-linux  +FAIL: ld-elf/pr21562h
powerpc-linux  +FAIL: pr20022
rl78-elf  +FAIL: ld-elf/sizeofa
rl78-elf  +FAIL: ld-elf/startofa
rx-elf  +FAIL: ld-elf/sizeofa
rx-elf  +FAIL: ld-elf/startofa
sh-rtems  +FAIL: ld-elf/sizeofa
sh-rtems  +FAIL: ld-elf/startofa
v850-elf  +FAIL: ld-elf/sizeofa
v850-elf  +FAIL: ld-elf/startofa

-- 
Alan Modra
Australia Development Lab, IBM

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

* Re: [PATCH] Always define referenced __start_SECNAME/__stop_SECNAME
  2017-06-14  3:50                     ` Alan Modra
@ 2017-06-14 13:20                       ` H.J. Lu
  2017-06-15  3:31                         ` Alan Modra
  0 siblings, 1 reply; 16+ messages in thread
From: H.J. Lu @ 2017-06-14 13:20 UTC (permalink / raw)
  To: Alan Modra; +Cc: Binutils

[-- Attachment #1: Type: text/plain, Size: 4008 bytes --]

On Tue, Jun 13, 2017 at 8:50 PM, Alan Modra <amodra@gmail.com> wrote:
> I see these fails.  Please investigate and fix.  The powerpc-linux

Most of tests are supported on targets without --gc-sections support or
with a leading underscore in symbol name.  I checked in a couple patches
to address them.

> fails are due to leaving the __start and __stop symbols undefined when
> sizing dynamic sections, which is wrong.  That at least needs to be

There is no need to discard relocs on undefined symbols with
non-default visibilty, which may be defined later like __start_SECNAME
and __stop_SECNAME, or are real errors.  I am enclosing a patch here.

> fixed so that allocate_dynrelocs doesn't see an undefined hidden
> visibility symbol.
>
> bfin-elf  +FAIL: ld-elf/sizeofa
> bfin-elf  +FAIL: ld-elf/startofa
> cr16-elf  +FAIL: ld-elf/sizeofa
> cr16-elf  +FAIL: ld-elf/sizeofc
> cr16-elf  +FAIL: ld-elf/startofa
> cr16-elf  +FAIL: ld-elf/startofc
> cris-elf  +FAIL: ld-elf/sizeofa
> cris-elf  +FAIL: ld-elf/startofa
> crx-elf  +FAIL: ld-elf/sizeofa
> crx-elf  +FAIL: ld-elf/sizeofc
> crx-elf  +FAIL: ld-elf/startofa
> crx-elf  +FAIL: ld-elf/startofc
> epiphany-elf  +FAIL: ld-elf/sizeofa
> epiphany-elf  +FAIL: ld-elf/startofa
> h8300-elf  +FAIL: ld-elf/sizeofa
> h8300-elf  +FAIL: ld-elf/startofa
> hppa64-linux  +FAIL: ld-elf/pr21562a
> hppa64-linux  +FAIL: ld-elf/pr21562b
> hppa64-linux  +FAIL: ld-elf/pr21562c
> hppa64-linux  +FAIL: ld-elf/pr21562d
> hppa64-linux  +FAIL: ld-elf/pr21562i
> hppa64-linux  +FAIL: ld-elf/pr21562j
> hppa64-linux  +FAIL: ld-elf/pr21562k
> hppa64-linux  +FAIL: ld-elf/pr21562l
> hppa64-linux  +FAIL: ld-elf/pr21562m
> hppa64-linux  +FAIL: ld-elf/pr21562n
> ia64-linux  +FAIL: ld-elf/pr21562a
> ia64-linux  +FAIL: ld-elf/pr21562b
> ia64-linux  +FAIL: ld-elf/pr21562c
> ia64-linux  +FAIL: ld-elf/pr21562d
> ia64-linux  +FAIL: ld-elf/pr21562i
> ia64-linux  +FAIL: ld-elf/pr21562j
> ia64-linux  +FAIL: ld-elf/pr21562k
> ia64-linux  +FAIL: ld-elf/pr21562l
> ia64-linux  +FAIL: ld-elf/pr21562m
> ia64-linux  +FAIL: ld-elf/pr21562n
> ip2k-elf  +FAIL: ld-elf/sizeofa
> ip2k-elf  +FAIL: ld-elf/startofa
> m32c-elf  +FAIL: ld-elf/sizeofa
> m32c-elf  +FAIL: ld-elf/startofa
> metag-linux  +FAIL: ld-elf/pr21562a
> metag-linux  +FAIL: ld-elf/pr21562b
> metag-linux  +FAIL: ld-elf/pr21562c
> metag-linux  +FAIL: ld-elf/pr21562d
> metag-linux  +FAIL: ld-elf/pr21562e
> metag-linux  +FAIL: ld-elf/pr21562f
> metag-linux  +FAIL: ld-elf/pr21562g
> metag-linux  +FAIL: ld-elf/pr21562h
> metag-linux  +FAIL: ld-elf/pr21562i
> metag-linux  +FAIL: ld-elf/pr21562j
> metag-linux  +FAIL: ld-elf/pr21562k
> metag-linux  +FAIL: ld-elf/pr21562l
> metag-linux  +FAIL: ld-elf/pr21562m
> metag-linux  +FAIL: ld-elf/pr21562n
> metag-linux  +FAIL: ld-elf/sizeofa
> metag-linux  +FAIL: ld-elf/sizeofb
> metag-linux  +FAIL: ld-elf/startofa
> metag-linux  +FAIL: ld-elf/startofb
> mips64-linux  +FAIL: ld-gc/pr20022
> mipsel-linux-gnu  +FAIL: ld-gc/pr20022
> mipsisa32el-linux  +FAIL: ld-gc/pr20022
> mips-linux  +FAIL: ld-gc/pr20022
> mn10200-elf  +FAIL: ld-elf/sizeofa
> mn10200-elf  +FAIL: ld-elf/startofa
> mn10300-elf  +FAIL: ld-elf/sizeofa
> mn10300-elf  +FAIL: ld-elf/startofa
> nios2-linux  +FAIL: ld-gc/pr20022
> powerpc-eabisim  +FAIL: pr20022
> powerpc-eabivle  +FAIL: pr20022
> powerpcle-elf  +FAIL: pr20022
> powerpc-linux  +FAIL: ld-elf/pr21562a
> powerpc-linux  +FAIL: ld-elf/pr21562b
> powerpc-linux  +FAIL: ld-elf/pr21562c
> powerpc-linux  +FAIL: ld-elf/pr21562d
> powerpc-linux  +FAIL: ld-elf/pr21562e
> powerpc-linux  +FAIL: ld-elf/pr21562f
> powerpc-linux  +FAIL: ld-elf/pr21562g
> powerpc-linux  +FAIL: ld-elf/pr21562h
> powerpc-linux  +FAIL: pr20022
> rl78-elf  +FAIL: ld-elf/sizeofa
> rl78-elf  +FAIL: ld-elf/startofa
> rx-elf  +FAIL: ld-elf/sizeofa
> rx-elf  +FAIL: ld-elf/startofa
> sh-rtems  +FAIL: ld-elf/sizeofa
> sh-rtems  +FAIL: ld-elf/startofa
> v850-elf  +FAIL: ld-elf/sizeofa
> v850-elf  +FAIL: ld-elf/startofa
>
> --
> Alan Modra
> Australia Development Lab, IBM



-- 
H.J.

[-- Attachment #2: 0001-ppc-Don-t-discard-relocs-on-undefined-symbols.patch --]
[-- Type: text/x-patch, Size: 1568 bytes --]

From 5ee4d80423a8b082022553c0bc0bbab857b5fe92 Mon Sep 17 00:00:00 2001
From: "H.J. Lu" <hjl.tools@gmail.com>
Date: Wed, 14 Jun 2017 03:55:51 -0700
Subject: [PATCH 1/3] ppc: Don't discard relocs on undefined symbols

Don't discard relocs on undefined symbols with non-default visibilty,
which may be defined later like __start_SECNAME and __stop_SECNAME,
or are real errors.

	PR ld/21562
	* elf32-ppc.c (allocate_dynrelocs): Don't discard relocs on
	undefined symbols with non-default visibilty.
---
 bfd/elf32-ppc.c | 9 ++++-----
 1 file changed, 4 insertions(+), 5 deletions(-)

diff --git a/bfd/elf32-ppc.c b/bfd/elf32-ppc.c
index a4814fc..cc0976f 100644
--- a/bfd/elf32-ppc.c
+++ b/bfd/elf32-ppc.c
@@ -6056,14 +6056,13 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf)
      changes.  */
   else if (bfd_link_pic (info))
     {
-      /* Discard relocs on undefined symbols that must be local.  */
-      if (h->root.type == bfd_link_hash_undefined
-	  && ELF_ST_VISIBILITY (h->other) != STV_DEFAULT)
-	eh->dyn_relocs = NULL;
+      /* Don't discard relocs on undefined symbols with non-default
+	 visibilty, which may be defined later like __start_SECNAME
+	 and __stop_SECNAME, or are real errors.  */
 
       /* Also discard relocs on undefined weak syms with non-default
 	 visibility, or when dynamic_undefined_weak says so.  */
-      else if (UNDEFWEAK_NO_DYNAMIC_RELOC (info, h))
+      if (UNDEFWEAK_NO_DYNAMIC_RELOC (info, h))
 	eh->dyn_relocs = NULL;
 
       /* Relocs that use pc_count are those that appear on a call insn,
-- 
2.9.4


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

* Re: [PATCH] Always define referenced __start_SECNAME/__stop_SECNAME
  2017-06-14 13:20                       ` H.J. Lu
@ 2017-06-15  3:31                         ` Alan Modra
  2017-06-15 11:21                           ` H.J. Lu
  0 siblings, 1 reply; 16+ messages in thread
From: Alan Modra @ 2017-06-15  3:31 UTC (permalink / raw)
  To: H.J. Lu; +Cc: Binutils

On Wed, Jun 14, 2017 at 06:20:47AM -0700, H.J. Lu wrote:
> On Tue, Jun 13, 2017 at 8:50 PM, Alan Modra <amodra@gmail.com> wrote:
> > I see these fails.  Please investigate and fix.  The powerpc-linux
> 
> Most of tests are supported on targets without --gc-sections support or
> with a leading underscore in symbol name.  I checked in a couple patches
> to address them.
> 
> > fails are due to leaving the __start and __stop symbols undefined when
> > sizing dynamic sections, which is wrong.  That at least needs to be
> 
> There is no need to discard relocs on undefined symbols with
> non-default visibilty, which may be defined later like __start_SECNAME
> and __stop_SECNAME, or are real errors.  I am enclosing a patch here.

No, it is quite reasonable to discard these relocations, and it is a
maintenance nightmare when symbols change state between
allocate_dynrelocs and relocate_section.  Granted, that already
happened for .startof. and .sizeof. symbols, but the existence of
those special symbols was an undocumented feature of gas and ld.
Making that happen for __start and __stop too just makes the problem
worse.

In future please state on the mailing list which targets you tested
against when posting global changes.  I assumed you had tested this
change against a representative set of targets, but it's clear you
didn't.

-- 
Alan Modra
Australia Development Lab, IBM

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

* Re: [PATCH] Always define referenced __start_SECNAME/__stop_SECNAME
  2017-06-15  3:31                         ` Alan Modra
@ 2017-06-15 11:21                           ` H.J. Lu
  0 siblings, 0 replies; 16+ messages in thread
From: H.J. Lu @ 2017-06-15 11:21 UTC (permalink / raw)
  To: Alan Modra; +Cc: Binutils

[-- Attachment #1: Type: text/plain, Size: 1892 bytes --]

On Wed, Jun 14, 2017 at 8:30 PM, Alan Modra <amodra@gmail.com> wrote:
> On Wed, Jun 14, 2017 at 06:20:47AM -0700, H.J. Lu wrote:
>> On Tue, Jun 13, 2017 at 8:50 PM, Alan Modra <amodra@gmail.com> wrote:
>> > I see these fails.  Please investigate and fix.  The powerpc-linux
>>
>> Most of tests are supported on targets without --gc-sections support or
>> with a leading underscore in symbol name.  I checked in a couple patches
>> to address them.
>>
>> > fails are due to leaving the __start and __stop symbols undefined when
>> > sizing dynamic sections, which is wrong.  That at least needs to be
>>
>> There is no need to discard relocs on undefined symbols with
>> non-default visibilty, which may be defined later like __start_SECNAME
>> and __stop_SECNAME, or are real errors.  I am enclosing a patch here.
>
> No, it is quite reasonable to discard these relocations, and it is a
> maintenance nightmare when symbols change state between
> allocate_dynrelocs and relocate_section.  Granted, that already
> happened for .startof. and .sizeof. symbols, but the existence of

It is normal for linker defined symbols to change state.  BFD just
has to deal with it.

> those special symbols was an undocumented feature of gas and ld.
> Making that happen for __start and __stop too just makes the problem
> worse.

The main difference is that __start_SECNAME and __stop_SECNAME
are marked as hidden.   Here is a patch to check it.

> In future please state on the mailing list which targets you tested
> against when posting global changes.  I assumed you had tested this
> change against a representative set of targets, but it's clear you
> didn't.
>

Sure.  I also have a request for you.   Please add a testcase when
you fix a global bug in the future, especially there is one in the bug
report.   It will prevent your bug fix from being accidentally bypassed later.

Thanks.

-- 
H.J.

[-- Attachment #2: 0001-ppc-Don-t-discard-relocs-on-__start_SECNAME-__stop_S.patch --]
[-- Type: text/x-patch, Size: 1209 bytes --]

From de2b347055d7d3f9764e7c19f3bf8913cb1b5bb9 Mon Sep 17 00:00:00 2001
From: "H.J. Lu" <hjl.tools@gmail.com>
Date: Thu, 15 Jun 2017 04:10:58 -0700
Subject: [PATCH] ppc: Don't discard relocs on __start_SECNAME/__stop_SECNAME

__start_SECNAME and __stop_SECNAME may be undefined and hidden.
They will be defined by linker later.

	PR ld/21562
	* elf32-ppc.c (allocate_dynrelocs): Don't discard relocs on
	__start_SECNAME and __stop_SECNAME.
---
 bfd/elf32-ppc.c | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/bfd/elf32-ppc.c b/bfd/elf32-ppc.c
index a4814fc..92cc18b 100644
--- a/bfd/elf32-ppc.c
+++ b/bfd/elf32-ppc.c
@@ -6056,8 +6056,11 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf)
      changes.  */
   else if (bfd_link_pic (info))
     {
-      /* Discard relocs on undefined symbols that must be local.  */
+      /* Discard relocs on undefined symbols that must be local.
+	 start_stop is set on __start_SECNAME/__stop_SECNAME which
+	 mark section SECNAME and will be defined by linker later.  */
       if (h->root.type == bfd_link_hash_undefined
+	  && !h->start_stop
 	  && ELF_ST_VISIBILITY (h->other) != STV_DEFAULT)
 	eh->dyn_relocs = NULL;
 
-- 
2.9.4


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

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

Thread overview: 16+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-06-10 22:46 [PATCH] Always define referenced __start_SECNAME/__stop_SECNAME H.J. Lu
2017-06-12 23:32 ` Alan Modra
2017-06-13  0:18   ` H.J. Lu
2017-06-13  1:54     ` Alan Modra
2017-06-13  2:10       ` H.J. Lu
2017-06-13 12:26         ` Alan Modra
2017-06-13 12:38           ` H.J. Lu
2017-06-13 14:28             ` Alan Modra
2017-06-13 15:22               ` H.J. Lu
2017-06-13 15:31                 ` H.J. Lu
2017-06-13 19:07                 ` H.J. Lu
2017-06-13 20:06                   ` H.J. Lu
2017-06-14  3:50                     ` Alan Modra
2017-06-14 13:20                       ` H.J. Lu
2017-06-15  3:31                         ` Alan Modra
2017-06-15 11:21                           ` H.J. Lu

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).