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


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

Rewrite __start and __stop symbol handling


This arranges for __start and __stop symbols to be defined before
garbage collection, for all target formats.  That should allow the
COFF and PE --gc-sections to keep a singleton orphan input section,
a feature lost by 2017-06-13 commit cbd0eecf26.  The fancier ELF
treatment of keeping all input sections associated with a __start or
__stop symbol, from 2015-10-23 commit 1cce69b9dc, is retained.

.startof. and .sizeof. symbols are deliberately not defined before
garbage collection, so these won't affect garbage collection of
sections.

The patch also ensures __start, __stop, .startof. and .sizeof. symbols
are defined before target size_dynamic_sections is called, albeit
with a preliminary value, so that target code doesn't need to cope
with a symbol changing from undefined at size_dynamic_sections to
defined at relocate_section.

Also, a number of problems with the testcases have been fixed.

	PR ld/20022
	PR ld/21557
	PR ld/21562
	PR ld/21571
include/
	* bfdlink.h (struct bfd_link_hash_entry): Delete undef.section.
bfd/
	* targets.c (struct bfd_target): Add _bfd_define_start_stop.
	(BFD_JUMP_TABLE_LINK): Likewise.
	* elf-bfd.h (bfd_elf_define_start_stop): Declare.
	* elflink.c (_bfd_elf_gc_mark_rsec): Update comment.
	(bfd_elf_define_start_stop): New function.
	* linker.c (bfd_generic_define_start_stop): New function.
	* coff64-rs6000.c (rs6000_xcoff64_vec, rs6000_xcoff64_aix_vec): Init
	new field.
	* aout-adobe.c (aout_32_bfd_define_start_stop): Define.
	* aout-target.h (MY_bfd_define_start_stop): Define.
	* aout-tic30.c (MY_bfd_define_start_stop): Define.
	* binary.c (binary_bfd_define_start_stop): Define.
	* bout.c (b_out_bfd_define_start_stop): Define.
	* coff-alpha.c (_bfd_ecoff_bfd_define_start_stop): Define.
	* coff-mips.c (_bfd_ecoff_bfd_define_start_stop): Define.
	* coff-rs6000.c (_bfd_xcoff_bfd_define_start_stop): Define.
	* coffcode.h (coff_bfd_define_start_stop): Define.
	* elfxx-target.h (bfd_elfNN_bfd_define_start_stop): Define.
	* i386msdos.c (msdos_bfd_define_start_stop): Define.
	* i386os9k.c (os9k_bfd_define_start_stop): Define.
	* ieee.c (ieee_bfd_define_start_stop): Define.
	* ihex.c (ihex_bfd_define_start_stop): Define.
	* libbfd-in.h (_bfd_nolink_bfd_define_start_stop): Define.
	* mach-o-target.c (bfd_mach_o_bfd_define_start_stop): Define.
	* mmo.c (mmo_bfd_define_start_stop): Define.
	* nlm-target.h (nlm_bfd_define_start_stop): Define.
	* oasys.c (oasys_bfd_define_start_stop): Define.
	* pef.c (bfd_pef_bfd_define_start_stop): Define.
	* plugin.c (bfd_plugin_bfd_define_start_stop): Define.
	* ppcboot.c (ppcboot_bfd_define_start_stop): Define.
	* som.c (som_bfd_define_start_stop): Define.
	* srec.c (srec_bfd_define_start_stop): Define.
	* tekhex.c (tekhex_bfd_define_start_stop): Define.
	* versados.c (versados_bfd_define_start_stop): Define.
	* vms-alpha.c (vms_bfd_define_start_stop): Define.
	(alpha_vms_bfd_define_start_stop): Define.
	* xsym.c (bfd_sym_bfd_define_start_stop): Define.
	* bfd-in2.h: Regenerate.
	* libbfd.h: Regenerate.
ld/
	* emultempl/elf32.em (gld${EMULATION_NAME}_after_open): Don't set
	__start/__stop syms here.
	* ldlang.c (lang_set_startof): Delete.
	(start_stop_syms, start_stop_count, start_stop_alloc): New vars.
	(lang_define_start_stop, lang_init_start_stop, foreach_start_stop,
	undef_start_stop, lang_undef_start_stop, lang_init_startof_sizeof,
	set_start_stop, lang_finalize_start_stop): New functions.
	(lang_process): Call _start_stop functions.
	* testsuite/ld-elf/pr21562a.d: Use xfail rather than notarget.
	Correct typos and list of xfail targets.
	* testsuite/ld-elf/pr21562b.d: 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-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-elf/sizeofa.d: Likewise.  Adjust to pass for generic ELF.
	* testsuite/ld-elf/sizeofb.d: Likewise.
	* testsuite/ld-elf/startofa.d: Likewise.
	* testsuite/ld-elf/startofb.d: Likewise.

diff --git a/bfd/ChangeLog b/bfd/ChangeLog
index 879ced7..f50678d 100644
--- a/bfd/ChangeLog
+++ b/bfd/ChangeLog
@@ -1,3 +1,49 @@
+2017-06-16  Alan Modra  <amodra@gmail.com>
+
+	PR ld/20022
+	PR ld/21557
+	PR ld/21562
+	PR ld/21571
+	* targets.c (struct bfd_target): Add _bfd_define_start_stop.
+	(BFD_JUMP_TABLE_LINK): Likewise.
+	* elf-bfd.h (bfd_elf_define_start_stop): Declare.
+	* elflink.c (_bfd_elf_gc_mark_rsec): Update comment.
+	(bfd_elf_define_start_stop): New function.
+	* linker.c (bfd_generic_define_start_stop): New function.
+	* coff64-rs6000.c (rs6000_xcoff64_vec, rs6000_xcoff64_aix_vec): Init
+	new field.
+	* aout-adobe.c (aout_32_bfd_define_start_stop): Define.
+	* aout-target.h (MY_bfd_define_start_stop): Define.
+	* aout-tic30.c (MY_bfd_define_start_stop): Define.
+	* binary.c (binary_bfd_define_start_stop): Define.
+	* bout.c (b_out_bfd_define_start_stop): Define.
+	* coff-alpha.c (_bfd_ecoff_bfd_define_start_stop): Define.
+	* coff-mips.c (_bfd_ecoff_bfd_define_start_stop): Define.
+	* coff-rs6000.c (_bfd_xcoff_bfd_define_start_stop): Define.
+	* coffcode.h (coff_bfd_define_start_stop): Define.
+	* elfxx-target.h (bfd_elfNN_bfd_define_start_stop): Define.
+	* i386msdos.c (msdos_bfd_define_start_stop): Define.
+	* i386os9k.c (os9k_bfd_define_start_stop): Define.
+	* ieee.c (ieee_bfd_define_start_stop): Define.
+	* ihex.c (ihex_bfd_define_start_stop): Define.
+	* libbfd-in.h (_bfd_nolink_bfd_define_start_stop): Define.
+	* mach-o-target.c (bfd_mach_o_bfd_define_start_stop): Define.
+	* mmo.c (mmo_bfd_define_start_stop): Define.
+	* nlm-target.h (nlm_bfd_define_start_stop): Define.
+	* oasys.c (oasys_bfd_define_start_stop): Define.
+	* pef.c (bfd_pef_bfd_define_start_stop): Define.
+	* plugin.c (bfd_plugin_bfd_define_start_stop): Define.
+	* ppcboot.c (ppcboot_bfd_define_start_stop): Define.
+	* som.c (som_bfd_define_start_stop): Define.
+	* srec.c (srec_bfd_define_start_stop): Define.
+	* tekhex.c (tekhex_bfd_define_start_stop): Define.
+	* versados.c (versados_bfd_define_start_stop): Define.
+	* vms-alpha.c (vms_bfd_define_start_stop): Define.
+	(alpha_vms_bfd_define_start_stop): Define.
+	* xsym.c (bfd_sym_bfd_define_start_stop): Define.
+	* bfd-in2.h: Regenerate.
+	* libbfd.h: Regenerate.
+
 2017-06-15  Jiong Wang  <jiong.wang@arm.com>
 
 	PR ld/21532
diff --git a/bfd/aout-adobe.c b/bfd/aout-adobe.c
index a2c927d..487ed8c 100644
--- a/bfd/aout-adobe.c
+++ b/bfd/aout-adobe.c
@@ -466,6 +466,7 @@ aout_adobe_sizeof_headers (bfd *ignore_abfd ATTRIBUTE_UNUSED,
 #define aout_32_bfd_discard_group	            bfd_generic_discard_group
 #define aout_32_section_already_linked              _bfd_generic_section_already_linked
 #define aout_32_bfd_define_common_symbol            bfd_generic_define_common_symbol
+#define aout_32_bfd_define_start_stop               bfd_generic_define_start_stop
 #define aout_32_bfd_link_hash_table_create          _bfd_generic_link_hash_table_create
 #define aout_32_bfd_link_add_symbols	            _bfd_generic_link_add_symbols
 #define aout_32_bfd_link_just_syms	            _bfd_generic_link_just_syms
diff --git a/bfd/aout-target.h b/bfd/aout-target.h
index 2e98c4d..65bc44c 100644
--- a/bfd/aout-target.h
+++ b/bfd/aout-target.h
@@ -513,6 +513,9 @@ MY_bfd_final_link (bfd *abfd, struct bfd_link_info *info)
 #ifndef MY_bfd_define_common_symbol
 #define MY_bfd_define_common_symbol bfd_generic_define_common_symbol
 #endif
+#ifndef MY_bfd_define_start_stop
+#define MY_bfd_define_start_stop bfd_generic_define_start_stop
+#endif
 #ifndef MY_bfd_reloc_type_lookup
 #define MY_bfd_reloc_type_lookup NAME (aout, reloc_type_lookup)
 #endif
diff --git a/bfd/aout-tic30.c b/bfd/aout-tic30.c
index 5db3da7..068428c 100644
--- a/bfd/aout-tic30.c
+++ b/bfd/aout-tic30.c
@@ -968,6 +968,9 @@ tic30_aout_set_arch_mach (bfd *abfd,
 #ifndef MY_bfd_define_common_symbol
 #define MY_bfd_define_common_symbol bfd_generic_define_common_symbol
 #endif
+#ifndef MY_bfd_define_start_stop
+#define MY_bfd_define_start_stop bfd_generic_define_start_stop
+#endif
 #ifndef MY_bfd_reloc_type_lookup
 #define MY_bfd_reloc_type_lookup tic30_aout_reloc_type_lookup
 #endif
diff --git a/bfd/bfd-in2.h b/bfd/bfd-in2.h
index a23bb98..4348793 100644
--- a/bfd/bfd-in2.h
+++ b/bfd/bfd-in2.h
@@ -7593,7 +7593,8 @@ typedef struct bfd_target
   NAME##_bfd_is_group_section, \
   NAME##_bfd_discard_group, \
   NAME##_section_already_linked, \
-  NAME##_bfd_define_common_symbol
+  NAME##_bfd_define_common_symbol, \
+  NAME##_bfd_define_start_stop
 
   int         (*_bfd_sizeof_headers) (bfd *, struct bfd_link_info *);
   bfd_byte *  (*_bfd_get_relocated_section_contents)
@@ -7657,6 +7658,11 @@ typedef struct bfd_target
   bfd_boolean (*_bfd_define_common_symbol) (bfd *, struct bfd_link_info *,
                                             struct bfd_link_hash_entry *);
 
+  /* Define a __start, __stop, .startof. or .sizeof. symbol.  */
+  struct bfd_link_hash_entry *(*_bfd_define_start_stop) (struct bfd_link_info *,
+                                                         const char *,
+                                                         asection *);
+
   /* Routines to handle dynamic symbols and relocs.  */
 #define BFD_JUMP_TABLE_DYNAMIC(NAME) \
   NAME##_get_dynamic_symtab_upper_bound, \
@@ -7736,6 +7742,13 @@ bfd_boolean bfd_generic_define_common_symbol
 #define bfd_define_common_symbol(output_bfd, info, h) \
        BFD_SEND (output_bfd, _bfd_define_common_symbol, (output_bfd, info, h))
 
+struct bfd_link_hash_entry *bfd_generic_define_start_stop
+   (struct bfd_link_info *info,
+    const char *symbol, asection *sec);
+
+#define bfd_define_start_stop(output_bfd, info, symbol, sec) \
+       BFD_SEND (output_bfd, _bfd_define_start_stop, (info, symbol, sec))
+
 struct bfd_elf_version_tree * bfd_find_version_for_sym
    (struct bfd_elf_version_tree *verdefs,
     const char *sym_name, bfd_boolean *hide);
diff --git a/bfd/binary.c b/bfd/binary.c
index 0a811cf..1018d56 100644
--- a/bfd/binary.c
+++ b/bfd/binary.c
@@ -310,6 +310,7 @@ binary_sizeof_headers (bfd *abfd ATTRIBUTE_UNUSED,
 #define binary_bfd_discard_group                   bfd_generic_discard_group
 #define binary_section_already_linked             _bfd_generic_section_already_linked
 #define binary_bfd_define_common_symbol            bfd_generic_define_common_symbol
+#define binary_bfd_define_start_stop               bfd_generic_define_start_stop
 #define binary_bfd_link_hash_table_create         _bfd_generic_link_hash_table_create
 #define binary_bfd_link_just_syms                 _bfd_generic_link_just_syms
 #define binary_bfd_copy_link_hash_symbol_type     _bfd_generic_copy_link_hash_symbol_type
diff --git a/bfd/bout.c b/bfd/bout.c
index 0a6f8db..33692d6 100644
--- a/bfd/bout.c
+++ b/bfd/bout.c
@@ -1390,6 +1390,7 @@ b_out_bfd_get_relocated_section_contents (bfd *output_bfd,
 #define b_out_bfd_discard_group                bfd_generic_discard_group
 #define b_out_section_already_linked           _bfd_generic_section_already_linked
 #define b_out_bfd_define_common_symbol         bfd_generic_define_common_symbol
+#define b_out_bfd_define_start_stop            bfd_generic_define_start_stop
 #define aout_32_get_section_contents_in_window _bfd_generic_get_section_contents_in_window
 #define b_out_bfd_link_check_relocs            _bfd_generic_link_check_relocs
 #define b_out_set_reloc			       _bfd_generic_set_reloc
diff --git a/bfd/coff-alpha.c b/bfd/coff-alpha.c
index 8ecba2f..47e3740 100644
--- a/bfd/coff-alpha.c
+++ b/bfd/coff-alpha.c
@@ -2340,6 +2340,7 @@ static const struct ecoff_backend_data alpha_ecoff_backend_data =
 #define _bfd_ecoff_section_already_linked \
   _bfd_coff_section_already_linked
 #define _bfd_ecoff_bfd_define_common_symbol bfd_generic_define_common_symbol
+#define _bfd_ecoff_bfd_define_start_stop    bfd_generic_define_start_stop
 #define _bfd_ecoff_bfd_link_check_relocs    _bfd_generic_link_check_relocs
 
 /* Installing internal relocations in a section is also generic.  */
diff --git a/bfd/coff-mips.c b/bfd/coff-mips.c
index 45c65f8..c3ade62 100644
--- a/bfd/coff-mips.c
+++ b/bfd/coff-mips.c
@@ -1356,6 +1356,7 @@ static const struct ecoff_backend_data mips_ecoff_backend_data =
 #define _bfd_ecoff_section_already_linked \
   _bfd_coff_section_already_linked
 #define _bfd_ecoff_bfd_define_common_symbol bfd_generic_define_common_symbol
+#define _bfd_ecoff_bfd_define_start_stop bfd_generic_define_start_stop
 #define _bfd_ecoff_set_reloc _bfd_generic_set_reloc
 
 extern const bfd_target mips_ecoff_be_vec;
diff --git a/bfd/coff-rs6000.c b/bfd/coff-rs6000.c
index b49e393..fabf971 100644
--- a/bfd/coff-rs6000.c
+++ b/bfd/coff-rs6000.c
@@ -4013,6 +4013,7 @@ const struct xcoff_dwsect_name xcoff_dwsect_names[] = {
 #define _bfd_xcoff_bfd_discard_group bfd_generic_discard_group
 #define _bfd_xcoff_section_already_linked _bfd_generic_section_already_linked
 #define _bfd_xcoff_bfd_define_common_symbol _bfd_xcoff_define_common_symbol
+#define _bfd_xcoff_bfd_define_start_stop    bfd_generic_define_start_stop
 #define _bfd_xcoff_bfd_link_check_relocs    _bfd_generic_link_check_relocs
 
 /* For dynamic symbols and relocs entry points.  */
diff --git a/bfd/coff64-rs6000.c b/bfd/coff64-rs6000.c
index 56458e0..525b079 100644
--- a/bfd/coff64-rs6000.c
+++ b/bfd/coff64-rs6000.c
@@ -2746,6 +2746,7 @@ const bfd_target rs6000_xcoff64_vec =
     bfd_generic_discard_group,
     _bfd_generic_section_already_linked,
     _bfd_xcoff_define_common_symbol,
+    bfd_generic_define_start_stop,
 
     /* Dynamic */
     _bfd_xcoff_get_dynamic_symtab_upper_bound,
@@ -3006,6 +3007,7 @@ const bfd_target rs6000_xcoff64_aix_vec =
     bfd_generic_discard_group,
     _bfd_generic_section_already_linked,
     _bfd_xcoff_define_common_symbol,
+    bfd_generic_define_start_stop,
 
     /* Dynamic */
     _bfd_xcoff_get_dynamic_symtab_upper_bound,
diff --git a/bfd/coffcode.h b/bfd/coffcode.h
index f9d3978..3331f4c 100644
--- a/bfd/coffcode.h
+++ b/bfd/coffcode.h
@@ -6061,6 +6061,10 @@ static bfd_coff_backend_data bigobj_swap_table =
 #define coff_bfd_define_common_symbol	    bfd_generic_define_common_symbol
 #endif
 
+#ifndef coff_bfd_define_start_stop
+#define coff_bfd_define_start_stop	    bfd_generic_define_start_stop
+#endif
+
 #define CREATE_BIG_COFF_TARGET_VEC(VAR, NAME, EXTRA_O_FLAGS, EXTRA_S_FLAGS, UNDER, ALTERNATIVE, SWAP_TABLE)	\
 const bfd_target VAR =							\
 {									\
diff --git a/bfd/elf-bfd.h b/bfd/elf-bfd.h
index fe15b93..b889720 100644
--- a/bfd/elf-bfd.h
+++ b/bfd/elf-bfd.h
@@ -2273,6 +2273,9 @@ extern bfd_reloc_status_type bfd_elf_perform_complex_relocation
 extern bfd_boolean _bfd_elf_setup_sections
   (bfd *);
 
+extern struct bfd_link_hash_entry *bfd_elf_define_start_stop
+  (struct bfd_link_info *, const char *, asection *);
+
 extern void _bfd_elf_post_process_headers (bfd * , struct bfd_link_info *);
 
 extern const bfd_target *bfd_elf32_object_p
diff --git a/bfd/elflink.c b/bfd/elflink.c
index 9b0f544..1a83b88 100644
--- a/bfd/elflink.c
+++ b/bfd/elflink.c
@@ -12738,11 +12738,9 @@ _bfd_elf_gc_mark_rsec (struct bfd_link_info *info, asection *sec,
 
       if (start_stop != NULL)
 	{
-	  /* To work around a glibc bug, mark all XXX input sections
-	     when there is an as yet undefined reference to __start_XXX
-	     or __stop_XXX symbols.  The linker will later define such
-	     symbols for orphan input sections that have a name
-	     representable as a C identifier.  */
+	  /* To work around a glibc bug, mark XXX input sections
+	     when there is a reference to __start_XXX or __stop_XXX
+	     symbols.  */
 	  if (h->start_stop)
 	    {
 	      asection *s = h->u2.start_stop_section;
@@ -14193,3 +14191,25 @@ elf_append_rel (bfd *abfd, asection *s, Elf_Internal_Rela *rel)
   BFD_ASSERT (loc + bed->s->sizeof_rel <= s->contents + s->size);
   bed->s->swap_reloc_out (abfd, rel, loc);
 }
+
+/* Define __start, __stop, .startof. or .sizeof. symbol.  */
+
+struct bfd_link_hash_entry *
+bfd_elf_define_start_stop (struct bfd_link_info *info,
+			   const char *symbol, asection *sec)
+{
+  struct bfd_link_hash_entry *h;
+
+  h = bfd_generic_define_start_stop (info, symbol, sec);
+  if (h != NULL)
+    {
+      struct elf_link_hash_entry *eh = (struct elf_link_hash_entry *) h;
+      eh->start_stop = 1;
+      eh->u2.start_stop_section = sec;
+      _bfd_elf_link_hash_hide_symbol (info, eh, TRUE);
+      if (ELF_ST_VISIBILITY (eh->other) != STV_INTERNAL)
+	eh->other = ((eh->other & ~ELF_ST_VISIBILITY (-1))
+		     | STV_HIDDEN);
+    }
+  return h;
+}
diff --git a/bfd/elfxx-target.h b/bfd/elfxx-target.h
index 072efaa..551883f 100644
--- a/bfd/elfxx-target.h
+++ b/bfd/elfxx-target.h
@@ -269,6 +269,9 @@
 #ifndef bfd_elfNN_bfd_link_add_symbols
 #define bfd_elfNN_bfd_link_add_symbols	bfd_elf_link_add_symbols
 #endif
+#ifndef bfd_elfNN_bfd_define_start_stop
+#define bfd_elfNN_bfd_define_start_stop bfd_elf_define_start_stop
+#endif
 #ifndef bfd_elfNN_bfd_final_link
 #define bfd_elfNN_bfd_final_link	bfd_elf_final_link
 #endif
@@ -289,6 +292,9 @@
 #ifndef bfd_elfNN_bfd_link_add_symbols
 #define bfd_elfNN_bfd_link_add_symbols	_bfd_generic_link_add_symbols
 #endif
+#ifndef bfd_elfNN_bfd_define_start_stop
+#define bfd_elfNN_bfd_define_start_stop bfd_generic_define_start_stop
+#endif
 #ifndef bfd_elfNN_bfd_final_link
 #define bfd_elfNN_bfd_final_link	_bfd_generic_final_link
 #endif
diff --git a/bfd/i386msdos.c b/bfd/i386msdos.c
index 5062506..62d2696 100644
--- a/bfd/i386msdos.c
+++ b/bfd/i386msdos.c
@@ -149,6 +149,7 @@ msdos_set_section_contents (bfd *abfd,
 #define msdos_section_already_linked \
   _bfd_generic_section_already_linked
 #define msdos_bfd_define_common_symbol bfd_generic_define_common_symbol
+#define msdos_bfd_define_start_stop bfd_generic_define_start_stop
 #define msdos_bfd_link_hash_table_create _bfd_generic_link_hash_table_create
 #define msdos_bfd_link_add_symbols _bfd_generic_link_add_symbols
 #define msdos_bfd_link_just_syms _bfd_generic_link_just_syms
diff --git a/bfd/i386os9k.c b/bfd/i386os9k.c
index 7f79b23..78c58fd 100644
--- a/bfd/i386os9k.c
+++ b/bfd/i386os9k.c
@@ -178,6 +178,7 @@ os9k_sizeof_headers (bfd *abfd ATTRIBUTE_UNUSED,
 #define os9k_section_already_linked \
   _bfd_generic_section_already_linked
 #define os9k_bfd_define_common_symbol bfd_generic_define_common_symbol
+#define os9k_bfd_define_start_stop bfd_generic_define_start_stop
 #define os9k_bfd_link_hash_table_create _bfd_generic_link_hash_table_create
 #define os9k_bfd_link_add_symbols _bfd_generic_link_add_symbols
 #define os9k_bfd_link_just_syms _bfd_generic_link_just_syms
diff --git a/bfd/ieee.c b/bfd/ieee.c
index f7ea4bd..d5220b6 100644
--- a/bfd/ieee.c
+++ b/bfd/ieee.c
@@ -3872,6 +3872,7 @@ ieee_sizeof_headers (bfd *abfd ATTRIBUTE_UNUSED,
 #define ieee_section_already_linked \
   _bfd_generic_section_already_linked
 #define ieee_bfd_define_common_symbol bfd_generic_define_common_symbol
+#define ieee_bfd_define_start_stop bfd_generic_define_start_stop
 #define ieee_bfd_link_hash_table_create _bfd_generic_link_hash_table_create
 #define ieee_bfd_link_add_symbols _bfd_generic_link_add_symbols
 #define ieee_bfd_link_just_syms _bfd_generic_link_just_syms
diff --git a/bfd/ihex.c b/bfd/ihex.c
index 6dda98f..a0c704a 100644
--- a/bfd/ihex.c
+++ b/bfd/ihex.c
@@ -945,6 +945,7 @@ ihex_sizeof_headers (bfd *abfd ATTRIBUTE_UNUSED,
 #define ihex_bfd_discard_group                    bfd_generic_discard_group
 #define ihex_section_already_linked               _bfd_generic_section_already_linked
 #define ihex_bfd_define_common_symbol             bfd_generic_define_common_symbol
+#define ihex_bfd_define_start_stop                bfd_generic_define_start_stop
 #define ihex_bfd_link_hash_table_create           _bfd_generic_link_hash_table_create
 #define ihex_bfd_link_add_symbols                 _bfd_generic_link_add_symbols
 #define ihex_bfd_link_just_syms                   _bfd_generic_link_just_syms
diff --git a/bfd/libbfd-in.h b/bfd/libbfd-in.h
index 2d1bf27..7adee99 100644
--- a/bfd/libbfd-in.h
+++ b/bfd/libbfd-in.h
@@ -515,6 +515,9 @@ extern bfd_boolean _bfd_generic_set_section_contents
 #define _bfd_nolink_bfd_define_common_symbol \
   ((bfd_boolean (*) (bfd *, struct bfd_link_info *, \
 		     struct bfd_link_hash_entry *)) bfd_false)
+#define _bfd_nolink_bfd_define_start_stop \
+  ((struct bfd_link_hash_entry * (*) (struct bfd_link_info *, \
+				      const char *, asection *)) bfd_nullvoidptr)
 #define _bfd_nolink_bfd_link_check_relocs \
   _bfd_generic_link_check_relocs
 
diff --git a/bfd/libbfd.h b/bfd/libbfd.h
index 7e58598..09df3b2 100644
--- a/bfd/libbfd.h
+++ b/bfd/libbfd.h
@@ -520,6 +520,9 @@ extern bfd_boolean _bfd_generic_set_section_contents
 #define _bfd_nolink_bfd_define_common_symbol \
   ((bfd_boolean (*) (bfd *, struct bfd_link_info *, \
 		     struct bfd_link_hash_entry *)) bfd_false)
+#define _bfd_nolink_bfd_define_start_stop \
+  ((struct bfd_link_hash_entry * (*) (struct bfd_link_info *, \
+				      const char *, asection *)) bfd_nullvoidptr)
 #define _bfd_nolink_bfd_link_check_relocs \
   _bfd_generic_link_check_relocs
 
diff --git a/bfd/linker.c b/bfd/linker.c
index f94d2f8..72d5705 100644
--- a/bfd/linker.c
+++ b/bfd/linker.c
@@ -3097,6 +3097,43 @@ bfd_generic_define_common_symbol (bfd *output_bfd,
 
 /*
 FUNCTION
+	bfd_generic_define_start_stop
+
+SYNOPSIS
+	struct bfd_link_hash_entry *bfd_generic_define_start_stop
+	  (struct bfd_link_info *info,
+	   const char *symbol, asection *sec);
+
+DESCRIPTION
+	Define a __start, __stop, .startof. or .sizeof. symbol.
+	Return the symbol or NULL if no such undefined symbol exists.
+
+.#define bfd_define_start_stop(output_bfd, info, symbol, sec) \
+.       BFD_SEND (output_bfd, _bfd_define_start_stop, (info, symbol, sec))
+.
+*/
+
+struct bfd_link_hash_entry *
+bfd_generic_define_start_stop (struct bfd_link_info *info,
+			       const char *symbol, asection *sec)
+{
+  struct bfd_link_hash_entry *h;
+
+  h = bfd_link_hash_lookup (info->hash, symbol, 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.section = sec;
+      h->u.def.value = 0;
+      return h;
+    }
+  return NULL;
+}
+
+/*
+FUNCTION
 	bfd_find_version_for_sym
 
 SYNOPSIS
diff --git a/bfd/mach-o-target.c b/bfd/mach-o-target.c
index c25a743..9c01df8 100644
--- a/bfd/mach-o-target.c
+++ b/bfd/mach-o-target.c
@@ -55,6 +55,7 @@
 #define bfd_mach_o_bfd_discard_group                  bfd_generic_discard_group
 #define bfd_mach_o_section_already_linked             _bfd_generic_section_already_linked
 #define bfd_mach_o_bfd_define_common_symbol           bfd_generic_define_common_symbol
+#define bfd_mach_o_bfd_define_start_stop              bfd_generic_define_start_stop
 #define bfd_mach_o_bfd_copy_private_bfd_data          _bfd_generic_bfd_copy_private_bfd_data
 #define bfd_mach_o_core_file_matches_executable_p     generic_core_file_matches_executable_p
 #define bfd_mach_o_core_file_pid                      _bfd_nocore_core_file_pid
diff --git a/bfd/mmo.c b/bfd/mmo.c
index 6b2772b..99a591b 100644
--- a/bfd/mmo.c
+++ b/bfd/mmo.c
@@ -3320,6 +3320,7 @@ mmo_write_object_contents (bfd *abfd)
 #define mmo_section_already_linked \
   _bfd_generic_section_already_linked
 #define mmo_bfd_define_common_symbol bfd_generic_define_common_symbol
+#define mmo_bfd_define_start_stop bfd_generic_define_start_stop
 
 /* We want to copy time of creation, otherwise we'd use
    BFD_JUMP_TABLE_COPY (_bfd_generic).  */
diff --git a/bfd/nlm-target.h b/bfd/nlm-target.h
index 872ee32..4dadb33 100644
--- a/bfd/nlm-target.h
+++ b/bfd/nlm-target.h
@@ -53,6 +53,7 @@
 #define nlm_bfd_discard_group                   bfd_generic_discard_group
 #define nlm_section_already_linked              _bfd_generic_section_already_linked
 #define nlm_bfd_define_common_symbol            bfd_generic_define_common_symbol
+#define nlm_bfd_define_start_stop               bfd_generic_define_start_stop
 #define nlm_bfd_link_hash_table_create          _bfd_generic_link_hash_table_create
 #define nlm_bfd_link_add_symbols                _bfd_generic_link_add_symbols
 #define nlm_bfd_link_just_syms                  _bfd_generic_link_just_syms
diff --git a/bfd/oasys.c b/bfd/oasys.c
index defb25a..efe0d7c 100644
--- a/bfd/oasys.c
+++ b/bfd/oasys.c
@@ -1186,6 +1186,7 @@ oasys_sizeof_headers (bfd *abfd ATTRIBUTE_UNUSED,
 #define oasys_bfd_discard_group                    bfd_generic_discard_group
 #define oasys_section_already_linked               _bfd_generic_section_already_linked
 #define oasys_bfd_define_common_symbol             bfd_generic_define_common_symbol
+#define oasys_bfd_define_start_stop                bfd_generic_define_start_stop
 #define oasys_bfd_link_hash_table_create           _bfd_generic_link_hash_table_create
 #define oasys_bfd_link_add_symbols                 _bfd_generic_link_add_symbols
 #define oasys_bfd_link_just_syms                   _bfd_generic_link_just_syms
diff --git a/bfd/pef.c b/bfd/pef.c
index 5f64d44..7f03d17 100644
--- a/bfd/pef.c
+++ b/bfd/pef.c
@@ -59,6 +59,7 @@
 #define bfd_pef_bfd_discard_group                   bfd_generic_discard_group
 #define bfd_pef_section_already_linked	            _bfd_generic_section_already_linked
 #define bfd_pef_bfd_define_common_symbol            bfd_generic_define_common_symbol
+#define bfd_pef_bfd_define_start_stop               bfd_generic_define_start_stop
 #define bfd_pef_bfd_link_hash_table_create          _bfd_generic_link_hash_table_create
 #define bfd_pef_bfd_link_add_symbols                _bfd_generic_link_add_symbols
 #define bfd_pef_bfd_link_just_syms                  _bfd_generic_link_just_syms
diff --git a/bfd/plugin.c b/bfd/plugin.c
index 1c8c3fb..af50be1 100644
--- a/bfd/plugin.c
+++ b/bfd/plugin.c
@@ -105,6 +105,7 @@ dlerror (void)
 #define bfd_plugin_bfd_discard_group                  bfd_generic_discard_group
 #define bfd_plugin_section_already_linked             _bfd_generic_section_already_linked
 #define bfd_plugin_bfd_define_common_symbol           bfd_generic_define_common_symbol
+#define bfd_plugin_bfd_define_start_stop              bfd_generic_define_start_stop
 #define bfd_plugin_bfd_copy_link_hash_symbol_type     _bfd_generic_copy_link_hash_symbol_type
 #define bfd_plugin_bfd_link_check_relocs              _bfd_generic_link_check_relocs
 
diff --git a/bfd/ppcboot.c b/bfd/ppcboot.c
index e27e915..a0f9621 100644
--- a/bfd/ppcboot.c
+++ b/bfd/ppcboot.c
@@ -461,6 +461,7 @@ ppcboot_bfd_print_private_bfd_data (bfd *abfd, void * farg)
 #define ppcboot_section_already_linked \
   _bfd_generic_section_already_linked
 #define ppcboot_bfd_define_common_symbol bfd_generic_define_common_symbol
+#define ppcboot_bfd_define_start_stop bfd_generic_define_start_stop
 #define ppcboot_bfd_link_hash_table_create _bfd_generic_link_hash_table_create
 #define ppcboot_bfd_link_add_symbols _bfd_generic_link_add_symbols
 #define ppcboot_bfd_link_just_syms _bfd_generic_link_just_syms
diff --git a/bfd/som.c b/bfd/som.c
index 496040c..8575c89 100644
--- a/bfd/som.c
+++ b/bfd/som.c
@@ -6754,6 +6754,7 @@ som_bfd_link_split_section (bfd *abfd ATTRIBUTE_UNUSED, asection *sec)
 #define som_bfd_discard_group		        bfd_generic_discard_group
 #define som_section_already_linked              _bfd_generic_section_already_linked
 #define som_bfd_define_common_symbol            bfd_generic_define_common_symbol
+#define som_bfd_define_start_stop               bfd_generic_define_start_stop
 #define som_bfd_merge_private_bfd_data		_bfd_generic_bfd_merge_private_bfd_data
 #define som_bfd_copy_private_header_data	_bfd_generic_bfd_copy_private_header_data
 #define som_bfd_set_private_flags		_bfd_generic_bfd_set_private_flags
diff --git a/bfd/srec.c b/bfd/srec.c
index 6d9b9a4..d7b240d 100644
--- a/bfd/srec.c
+++ b/bfd/srec.c
@@ -1278,6 +1278,7 @@ srec_print_symbol (bfd *abfd,
 #define srec_bfd_discard_group                    bfd_generic_discard_group
 #define srec_section_already_linked               _bfd_generic_section_already_linked
 #define srec_bfd_define_common_symbol             bfd_generic_define_common_symbol
+#define srec_bfd_define_start_stop                bfd_generic_define_start_stop
 #define srec_bfd_link_hash_table_create           _bfd_generic_link_hash_table_create
 #define srec_bfd_link_add_symbols                 _bfd_generic_link_add_symbols
 #define srec_bfd_link_just_syms                   _bfd_generic_link_just_syms
diff --git a/bfd/targets.c b/bfd/targets.c
index 2f3ea13..05224c4 100644
--- a/bfd/targets.c
+++ b/bfd/targets.c
@@ -462,7 +462,8 @@ BFD_JUMP_TABLE macros.
 .  NAME##_bfd_is_group_section, \
 .  NAME##_bfd_discard_group, \
 .  NAME##_section_already_linked, \
-.  NAME##_bfd_define_common_symbol
+.  NAME##_bfd_define_common_symbol, \
+.  NAME##_bfd_define_start_stop
 .
 .  int         (*_bfd_sizeof_headers) (bfd *, struct bfd_link_info *);
 .  bfd_byte *  (*_bfd_get_relocated_section_contents)
@@ -526,6 +527,11 @@ BFD_JUMP_TABLE macros.
 .  bfd_boolean (*_bfd_define_common_symbol) (bfd *, struct bfd_link_info *,
 .					     struct bfd_link_hash_entry *);
 .
+.  {* Define a __start, __stop, .startof. or .sizeof. symbol.  *}
+.  struct bfd_link_hash_entry *(*_bfd_define_start_stop) (struct bfd_link_info *,
+.							  const char *,
+.							  asection *);
+.
 .  {* Routines to handle dynamic symbols and relocs.  *}
 .#define BFD_JUMP_TABLE_DYNAMIC(NAME) \
 .  NAME##_get_dynamic_symtab_upper_bound, \
diff --git a/bfd/tekhex.c b/bfd/tekhex.c
index bbc2ccd..214b54a 100644
--- a/bfd/tekhex.c
+++ b/bfd/tekhex.c
@@ -977,6 +977,7 @@ tekhex_print_symbol (bfd *abfd,
 #define tekhex_bfd_discard_group                    bfd_generic_discard_group
 #define tekhex_section_already_linked               _bfd_generic_section_already_linked
 #define tekhex_bfd_define_common_symbol             bfd_generic_define_common_symbol
+#define tekhex_bfd_define_start_stop                bfd_generic_define_start_stop
 #define tekhex_bfd_link_hash_table_create           _bfd_generic_link_hash_table_create
 #define tekhex_bfd_link_add_symbols                 _bfd_generic_link_add_symbols
 #define tekhex_bfd_link_just_syms                   _bfd_generic_link_just_syms
diff --git a/bfd/versados.c b/bfd/versados.c
index f0c5fdf..d9ede27 100644
--- a/bfd/versados.c
+++ b/bfd/versados.c
@@ -871,6 +871,7 @@ versados_canonicalize_reloc (bfd *abfd,
 #define versados_bfd_discard_group                    bfd_generic_discard_group
 #define versados_section_already_linked               _bfd_generic_section_already_linked
 #define versados_bfd_define_common_symbol             bfd_generic_define_common_symbol
+#define versados_bfd_define_start_stop                bfd_generic_define_start_stop
 #define versados_bfd_link_hash_table_create           _bfd_generic_link_hash_table_create
 #define versados_bfd_link_add_symbols                 _bfd_generic_link_add_symbols
 #define versados_bfd_link_just_syms                   _bfd_generic_link_just_syms
diff --git a/bfd/vms-alpha.c b/bfd/vms-alpha.c
index 38237cd..83b6638 100644
--- a/bfd/vms-alpha.c
+++ b/bfd/vms-alpha.c
@@ -9311,6 +9311,7 @@ bfd_vms_get_data (bfd *abfd)
 #define vms_bfd_discard_group             bfd_generic_discard_group
 #define vms_section_already_linked        _bfd_generic_section_already_linked
 #define vms_bfd_define_common_symbol      bfd_generic_define_common_symbol
+#define vms_bfd_define_start_stop      bfd_generic_define_start_stop
 #define vms_bfd_copy_private_header_data  _bfd_generic_bfd_copy_private_header_data
 
 #define vms_bfd_copy_private_bfd_data	  _bfd_generic_bfd_copy_private_bfd_data
@@ -9358,6 +9359,7 @@ bfd_vms_get_data (bfd *abfd)
   _bfd_generic_section_already_linked
 
 #define alpha_vms_bfd_define_common_symbol bfd_generic_define_common_symbol
+#define alpha_vms_bfd_define_start_stop bfd_generic_define_start_stop
 #define alpha_vms_bfd_link_just_syms _bfd_generic_link_just_syms
 #define alpha_vms_bfd_copy_link_hash_symbol_type \
   _bfd_generic_copy_link_hash_symbol_type
diff --git a/bfd/xsym.c b/bfd/xsym.c
index 6a4a750..3160c10 100644
--- a/bfd/xsym.c
+++ b/bfd/xsym.c
@@ -51,6 +51,7 @@
 #define bfd_sym_bfd_discard_group                   bfd_generic_discard_group
 #define bfd_sym_section_already_linked              _bfd_generic_section_already_linked
 #define bfd_sym_bfd_define_common_symbol            bfd_generic_define_common_symbol
+#define bfd_sym_bfd_define_start_stop               bfd_generic_define_start_stop
 #define bfd_sym_bfd_link_hash_table_create          _bfd_generic_link_hash_table_create
 #define bfd_sym_bfd_link_add_symbols                _bfd_generic_link_add_symbols
 #define bfd_sym_bfd_link_just_syms                  _bfd_generic_link_just_syms
diff --git a/include/ChangeLog b/include/ChangeLog
index 1c7766f..44905d7 100644
--- a/include/ChangeLog
+++ b/include/ChangeLog
@@ -1,3 +1,11 @@
+2017-06-16  Alan Modra  <amodra@gmail.com>
+
+	PR ld/20022
+	PR ld/21557
+	PR ld/21562
+	PR ld/21571
+	* bfdlink.h (struct bfd_link_hash_entry): Delete undef.section.
+
 2017-06-14  Yao Qi  <yao.qi@linaro.org>
 
 	* dis-asm.h (print_insn_aarch64): Move it to opcodes/disassemble.h.
diff --git a/include/bfdlink.h b/include/bfdlink.h
index 2e3f0b1..69232c4 100644
--- a/include/bfdlink.h
+++ b/include/bfdlink.h
@@ -144,9 +144,6 @@ struct bfd_link_hash_entry
 	  struct bfd_link_hash_entry *next;
 	  /* BFD symbol was found in.  */
 	  bfd *abfd;
-	  /* For __start_<name> and __stop_<name> symbols, the first
-	     input section matching the name.  */
-	  asection *section;
 	} undef;
       /* bfd_link_hash_defined, bfd_link_hash_defweak.  */
       struct
diff --git a/ld/ChangeLog b/ld/ChangeLog
index 7791c03..38d9f3f 100644
--- a/ld/ChangeLog
+++ b/ld/ChangeLog
@@ -1,3 +1,37 @@
+2017-06-16  Alan Modra  <amodra@gmail.com>
+
+	PR ld/20022
+	PR ld/21557
+	PR ld/21562
+	PR ld/21571
+	* emultempl/elf32.em (gld${EMULATION_NAME}_after_open): Don't set
+	__start/__stop syms here.
+	* ldlang.c (lang_set_startof): Delete.
+	(start_stop_syms, start_stop_count, start_stop_alloc): New vars.
+	(lang_define_start_stop, lang_init_start_stop, foreach_start_stop,
+	undef_start_stop, lang_undef_start_stop, lang_init_startof_sizeof,
+	set_start_stop, lang_finalize_start_stop): New functions.
+	(lang_process): Call _start_stop functions.
+	* testsuite/ld-elf/pr21562a.d: Use xfail rather than notarget.
+	Correct typos and list of xfail targets.
+	* testsuite/ld-elf/pr21562b.d: 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-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-elf/sizeofa.d: Likewise.  Adjust to pass for generic ELF.
+	* testsuite/ld-elf/sizeofb.d: Likewise.
+	* testsuite/ld-elf/startofa.d: Likewise.
+	* testsuite/ld-elf/startofb.d: Likewise.
+
 2017-06-15  H.J. Lu  <hongjiu.lu@intel.com>
 
 	* exsup.c (elf_shlib_list_options): Display "-z stack-size=SIZE"
diff --git a/ld/emultempl/elf32.em b/ld/emultempl/elf32.em
index 9468f7d..325d847 100644
--- a/ld/emultempl/elf32.em
+++ b/ld/emultempl/elf32.em
@@ -1218,7 +1218,6 @@ gld${EMULATION_NAME}_after_open (void)
   struct elf_link_hash_table *htab;
   asection *s;
   bfd *abfd;
-  char leading_char;
 
   after_open_default ();
 
@@ -1277,62 +1276,6 @@ 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 *elfbfd = NULL;
diff --git a/ld/ldlang.c b/ld/ldlang.c
index eb4ba9e..726bc8e 100644
--- a/ld/ldlang.c
+++ b/ld/ldlang.c
@@ -5878,98 +5878,174 @@ section_for_dot (void)
   return bfd_abs_section_ptr;
 }
 
-/* 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.  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.  */
+/* Array of __start/__stop/.startof./.sizeof/ symbols.  */
+
+static struct bfd_link_hash_entry **start_stop_syms;
+static size_t start_stop_count = 0;
+static size_t start_stop_alloc = 0;
+
+/* Give start/stop SYMBOL for SEC a preliminary definition, and add it
+   to start_stop_syms.  */
+
+static void
+lang_define_start_stop (const char *symbol, asection *sec)
+{
+  struct bfd_link_hash_entry *h;
+
+  h = bfd_define_start_stop (link_info.output_bfd, &link_info, symbol, sec);
+  if (h != NULL)
+    {
+      if (start_stop_count == start_stop_alloc)
+	{
+	  start_stop_alloc = 2 * start_stop_alloc + 10;
+	  start_stop_syms
+	    = xrealloc (start_stop_syms,
+			start_stop_alloc * sizeof (*start_stop_syms));
+	}
+      start_stop_syms[start_stop_count++] = h;
+    }
+}
+
+/* Check for input sections whose names match references to
+   __start_SECNAME or __stop_SECNAME symbols.  Give the symbols
+   preliminary definitions.  */
 
 static void
-lang_set_startof (void)
+lang_init_start_stop (void)
 {
+  bfd *abfd;
   asection *s;
-  char leading_char;
-  bfd_boolean is_elf;
-  bfd_boolean is_relocatable;
+  char leading_char = bfd_get_symbol_leading_char (link_info.output_bfd);
+
+  for (abfd = link_info.input_bfds; abfd != NULL; abfd = abfd->link.next)
+    for (s = abfd->sections; s != NULL; s = s->next)
+      {
+	const char *ps;
+	const char *secname = s->name;
+
+	for (ps = secname; *ps != '\0'; ps++)
+	  if (!ISALNUM ((unsigned char) *ps) && *ps != '_')
+	    break;
+	if (*ps == '\0')
+	  {
+	    char *symbol = (char *) xmalloc (10 + strlen (secname));
 
-  if (!config.build_constructors)
+	    symbol[0] = leading_char;
+	    sprintf (symbol + (leading_char != 0), "__start_%s", secname);
+	    lang_define_start_stop (symbol, s);
+
+	    symbol[1] = leading_char;
+	    memcpy (symbol + 1 + (leading_char != 0), "__stop", 6);
+	    lang_define_start_stop (symbol + 1, s);
+
+	    free (symbol);
+	  }
+      }
+}
+
+/* Iterate over start_stop_syms.  */
+
+static void
+foreach_start_stop (void (*func) (struct bfd_link_hash_entry *))
+{
+  size_t i;
+
+  for (i = 0; i < start_stop_count; ++i)
+    func (start_stop_syms[i]);
+}
+
+/* __start and __stop symbols are only supposed to be defined by the
+   linker for orphan sections, but we now extend that to sections that
+   map to an output section of the same name.  The symbols were
+   defined early for --gc-sections, before we mapped input to output
+   sections, so undo those that don't satisfy this rule.  */
+
+static void
+undef_start_stop (struct bfd_link_hash_entry *h)
+{
+  if (h->ldscript_def)
     return;
 
-  is_elf = (bfd_get_flavour (link_info.output_bfd)
-	    == bfd_target_elf_flavour);
-  is_relocatable = bfd_link_relocatable (&link_info);
+  if (h->u.def.section->output_section == NULL
+      || h->u.def.section->output_section->owner != link_info.output_bfd
+      || strcmp (h->u.def.section->name,
+		 h->u.def.section->output_section->name) != 0)
+    {
+      h->type = bfd_link_hash_undefined;
+      h->u.undef.abfd = NULL;
+    }
+}
+
+static void
+lang_undef_start_stop (void)
+{
+  foreach_start_stop (undef_start_stop);
+}
+
+/* Check for output sections whose names match references to
+   .startof.SECNAME or .sizeof.SECNAME symbols.  Give the symbols
+   preliminary definitions.  */
 
-  leading_char = bfd_get_symbol_leading_char (link_info.output_bfd);
+static void
+lang_init_startof_sizeof (void)
+{
+  asection *s;
 
   for (s = link_info.output_bfd->sections; s != NULL; s = s->next)
     {
-      const char *secname;
-      char *buf;
-      struct bfd_link_hash_entry *h;
+      const char *secname = s->name;
+      char *symbol = (char *) xmalloc (10 + strlen (secname));
 
-      secname = bfd_get_section_name (link_info.output_bfd, s);
-      buf = (char *) xmalloc (10 + strlen (secname));
+      sprintf (symbol, ".startof.%s", secname);
+      lang_define_start_stop (symbol, s);
 
-      if (!is_relocatable)
-	{
-	  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;
-	    }
+      memcpy (symbol + 1, ".size", 5);
+      lang_define_start_stop (symbol + 1, s);
+      free (symbol);
+    }
+}
 
-	  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;
-	    }
-	}
+/* Set .startof., .sizeof., __start and __stop symbols final values.  */
 
-      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))
+static void
+set_start_stop (struct bfd_link_hash_entry *h)
+{
+  if (h->ldscript_def
+      || h->type != bfd_link_hash_defined)
+    return;
+
+  if (h->root.string[0] == '.')
+    {
+      /* .startof. or .sizeof. symbol.
+	 .startof. already has final value.  */
+      if (h->root.string[2] == 'i')
 	{
-	  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;
+	  /* .sizeof.  */
+	  h->u.def.value = TO_ADDR (h->u.def.section->size);
+	  h->u.def.section = bfd_abs_section_ptr;
 	}
+    }
+  else
+    {
+      /* __start or __stop symbol.  */
+      int has_lead = bfd_get_symbol_leading_char (link_info.output_bfd) != 0;
 
-      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->u.def.section = h->u.def.section->output_section;
+      if (h->root.string[4 + has_lead] == 'o')
 	{
-	  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;
+	  /* __stop_ */
+	  h->u.def.value = TO_ADDR (h->u.def.section->size);
 	}
-      free (buf);
     }
 }
 
 static void
+lang_finalize_start_stop (void)
+{
+  foreach_start_stop (set_start_stop);
+}
+
+static void
 lang_end (void)
 {
   struct bfd_link_hash_entry *h;
@@ -7035,6 +7111,12 @@ lang_process (void)
      files.  */
   ldctor_build_sets ();
 
+  /* Give initial values for __start and __stop symbols, so that  ELF
+     gc_sections will keep sections referenced by these symbols.  Must
+     be done before lang_do_assignments below.  */
+  if (config.build_constructors)
+    lang_init_start_stop ();
+
   /* PR 13683: We must rerun the assignments prior to running garbage
      collection in order to make sure that all symbol aliases are resolved.  */
   lang_do_assignments (lang_mark_phase_enum);
@@ -7089,6 +7171,17 @@ lang_process (void)
   /* Copy forward lma regions for output sections in same lma region.  */
   lang_propagate_lma_regions ();
 
+  /* Defining __start/__stop symbols early for --gc-sections to work
+     around a glibc build problem can result in these symbols being
+     defined when they should not be.  Fix them now.  */
+  if (config.build_constructors)
+    lang_undef_start_stop ();
+
+  /* Define .startof./.sizeof. symbols with preliminary values before
+     dynamic symbols are created.  */
+  if (!bfd_link_relocatable (&link_info))
+    lang_init_startof_sizeof ();
+
   /* Do anything special before sizing sections.  This is where ELF
      and other back-ends size dynamic sections.  */
   ldemul_before_allocation ();
@@ -7108,8 +7201,8 @@ lang_process (void)
      everything is.  This is where relaxation is done.  */
   ldemul_after_allocation ();
 
-  /* Fix any .startof. or .sizeof. symbols.  */
-  lang_set_startof ();
+  /* Fix any __start, __stop, .startof. or .sizeof. symbols.  */
+  lang_finalize_start_stop ();
 
   /* Do all the assignments, now that we know the final resting places
      of all the symbols.  */
diff --git a/ld/testsuite/ld-elf/pr21562a.d b/ld/testsuite/ld-elf/pr21562a.d
index 3b0dc65..1f57569 100644
--- a/ld/testsuite/ld-elf/pr21562a.d
+++ b/ld/testsuite/ld-elf/pr21562a.d
@@ -1,12 +1,12 @@
 #ld: -shared -z defs --gc-sections
 #readelf: -s -S --wide
 #target: *-*-linux* *-*-gnu*
-#notarget: d30v-*-* dlx-*-* i960-*-* pj*-*-*
-#notarget: hppa64-*-* i370-*-* i860-*-* ia64-*-* mep-*-* mn10200-*-*
-#notarget: bfin-*-* cr16-*-* cr16c-*-* cris*-*-* crx-*-* epiphany-*-*
-#notarget: h8300-*-* ip2k-*-* m10200-*-* m10300-*-* m32c-*-* metag-*-*
-#notarget: metag-*-* rl78-*-* rx-*-* sh*-*-* v850*-*-*
-# Targets with a leading char will faill this test.
+#xfail: d30v-*-* dlx-*-* i960-*-* pj*-*-*
+#xfail: hppa64-*-* i370-*-* i860-*-* ia64-*-* mep-*-* mn10200-*-*
+#xfail: bfin-*-* cr16-*-* cr16c-*-* crx-*-* epiphany-*-*
+#xfail: h8300-*-* ip2k-*-* mn10200-*-* mn10300-*-* m32c-*-* metag-*-*
+#xfail: rl78-*-* rx-*-* v850*-*-*
+# Targets with a leading char will fail this test.
 # generic linker targets don't support --gc-sections, nor do a bunch of others
 
 #...
diff --git a/ld/testsuite/ld-elf/pr21562b.d b/ld/testsuite/ld-elf/pr21562b.d
index af82bb8..dd28b66 100644
--- a/ld/testsuite/ld-elf/pr21562b.d
+++ b/ld/testsuite/ld-elf/pr21562b.d
@@ -1,12 +1,12 @@
 #ld: -shared -z defs --gc-sections
 #readelf: -s -S --wide
 #target: *-*-linux* *-*-gnu*
-#notarget: d30v-*-* dlx-*-* i960-*-* pj*-*-*
-#notarget: hppa64-*-* i370-*-* i860-*-* ia64-*-* mep-*-* mn10200-*-*
-#notarget: bfin-*-* cr16-*-* cr16c-*-* cris*-*-* crx-*-* epiphany-*-*
-#notarget: h8300-*-* ip2k-*-* m10200-*-* m10300-*-* m32c-*-* metag-*-*
-#notarget: metag-*-* rl78-*-* rx-*-* sh*-*-* v850*-*-*
-# Targets with a leading char will faill this test.
+#xfail: d30v-*-* dlx-*-* i960-*-* pj*-*-*
+#xfail: hppa64-*-* i370-*-* i860-*-* ia64-*-* mep-*-* mn10200-*-*
+#xfail: bfin-*-* cr16-*-* cr16c-*-* crx-*-* epiphany-*-*
+#xfail: h8300-*-* ip2k-*-* mn10200-*-* mn10300-*-* m32c-*-* metag-*-*
+#xfail: rl78-*-* rx-*-* v850*-*-*
+# Targets with a leading char will fail this test.
 # generic linker targets don't support --gc-sections, nor do a bunch of others
 
 #...
diff --git a/ld/testsuite/ld-elf/pr21562c.d b/ld/testsuite/ld-elf/pr21562c.d
index 0fcc25a..69eb6aa 100644
--- a/ld/testsuite/ld-elf/pr21562c.d
+++ b/ld/testsuite/ld-elf/pr21562c.d
@@ -2,12 +2,12 @@
 #ld: -shared -z defs --gc-sections -T pr21562a.t
 #readelf: -s -S --wide
 #target: *-*-linux* *-*-gnu*
-#notarget: d30v-*-* dlx-*-* i960-*-* pj*-*-*
-#notarget: hppa64-*-* i370-*-* i860-*-* ia64-*-* mep-*-* mn10200-*-*
-#notarget: bfin-*-* cr16-*-* cr16c-*-* cris*-*-* crx-*-* epiphany-*-*
-#notarget: h8300-*-* ip2k-*-* m10200-*-* m10300-*-* m32c-*-* metag-*-*
-#notarget: metag-*-* rl78-*-* rx-*-* sh*-*-* v850*-*-*
-# Targets with a leading char will faill this test.
+#xfail: d30v-*-* dlx-*-* i960-*-* pj*-*-*
+#xfail: hppa64-*-* i370-*-* i860-*-* ia64-*-* mep-*-* mn10200-*-*
+#xfail: bfin-*-* cr16-*-* cr16c-*-* crx-*-* epiphany-*-*
+#xfail: h8300-*-* ip2k-*-* mn10200-*-* mn10300-*-* m32c-*-* metag-*-*
+#xfail: rl78-*-* rx-*-* v850*-*-*
+# Targets with a leading char will fail this test.
 # generic linker targets don't support --gc-sections, nor do a bunch of others
 
 #...
diff --git a/ld/testsuite/ld-elf/pr21562d.d b/ld/testsuite/ld-elf/pr21562d.d
index b966b80..7e13821 100644
--- a/ld/testsuite/ld-elf/pr21562d.d
+++ b/ld/testsuite/ld-elf/pr21562d.d
@@ -2,12 +2,12 @@
 #ld: -shared -z defs --gc-sections -T pr21562a.t
 #readelf: -s -S --wide
 #target: *-*-linux* *-*-gnu*
-#notarget: d30v-*-* dlx-*-* i960-*-* pj*-*-*
-#notarget: hppa64-*-* i370-*-* i860-*-* ia64-*-* mep-*-* mn10200-*-*
-#notarget: bfin-*-* cr16-*-* cr16c-*-* cris*-*-* crx-*-* epiphany-*-*
-#notarget: h8300-*-* ip2k-*-* m10200-*-* m10300-*-* m32c-*-* metag-*-*
-#notarget: metag-*-* rl78-*-* rx-*-* sh*-*-* v850*-*-*
-# Targets with a leading char will faill this test.
+#xfail: d30v-*-* dlx-*-* i960-*-* pj*-*-*
+#xfail: hppa64-*-* i370-*-* i860-*-* ia64-*-* mep-*-* mn10200-*-*
+#xfail: bfin-*-* cr16-*-* cr16c-*-* crx-*-* epiphany-*-*
+#xfail: h8300-*-* ip2k-*-* mn10200-*-* mn10300-*-* m32c-*-* metag-*-*
+#xfail: rl78-*-* rx-*-* v850*-*-*
+# Targets with a leading char will fail this test.
 # generic linker targets don't support --gc-sections, nor do a bunch of others
 
 #...
diff --git a/ld/testsuite/ld-elf/pr21562e.d b/ld/testsuite/ld-elf/pr21562e.d
index 6f73c7b..0172a06 100644
--- a/ld/testsuite/ld-elf/pr21562e.d
+++ b/ld/testsuite/ld-elf/pr21562e.d
@@ -2,10 +2,10 @@
 #ld: -shared -z defs
 #readelf: -s -S --wide
 #target: *-*-linux* *-*-gnu*
-#notarget: bfin-*-* cr16-*-* cr16c-*-* cris*-*-* crx-*-* epiphany-*-*
-#notarget: h8300-*-* ip2k-*-* m10200-*-* m10300-*-* m32c-*-* metag-*-*
-#notarget: metag-*-* rl78-*-* rx-*-* sh*-*-* v850*-*-*
-# Targets with a leading char will faill this test.
+#xfail: bfin-*-* cr16-*-* cr16c-*-* crx-*-* epiphany-*-*
+#xfail: h8300-*-* ip2k-*-* mn10200-*-* mn10300-*-* m32c-*-* metag-*-*
+#xfail: rl78-*-* rx-*-* v850*-*-*
+# Targets with a leading char will fail this test.
 
 #...
   \[[ 0-9]+\] scnfoo[ \t]+PROGBITS[ \t]+[0-9a-f]+ +[0-9a-f]+ +0*10[ \t]+.*
diff --git a/ld/testsuite/ld-elf/pr21562f.d b/ld/testsuite/ld-elf/pr21562f.d
index 244f917..a0f1a24 100644
--- a/ld/testsuite/ld-elf/pr21562f.d
+++ b/ld/testsuite/ld-elf/pr21562f.d
@@ -2,10 +2,10 @@
 #ld: -shared -z defs
 #readelf: -s -S --wide
 #target: *-*-linux* *-*-gnu*
-#notarget: bfin-*-* cr16-*-* cr16c-*-* cris*-*-* crx-*-* epiphany-*-*
-#notarget: h8300-*-* ip2k-*-* m10200-*-* m10300-*-* m32c-*-* metag-*-*
-#notarget: metag-*-* rl78-*-* rx-*-* sh*-*-* v850*-*-*
-# Targets with a leading char will faill this test.
+#xfail: bfin-*-* cr16-*-* cr16c-*-* crx-*-* epiphany-*-*
+#xfail: h8300-*-* ip2k-*-* mn10200-*-* mn10300-*-* m32c-*-* metag-*-*
+#xfail: rl78-*-* rx-*-* v850*-*-*
+# Targets with a leading char will fail this test.
 
 #...
   \[[ 0-9]+\] scnfoo[ \t]+PROGBITS[ \t]+[0-9a-f]+ +[0-9a-f]+ +0*10[ \t]+.*
diff --git a/ld/testsuite/ld-elf/pr21562g.d b/ld/testsuite/ld-elf/pr21562g.d
index 411e1e3..289ab75 100644
--- a/ld/testsuite/ld-elf/pr21562g.d
+++ b/ld/testsuite/ld-elf/pr21562g.d
@@ -2,10 +2,10 @@
 #ld: -shared -z defs -T pr21562a.t
 #readelf: -s -S --wide
 #target: *-*-linux* *-*-gnu*
-#notarget: bfin-*-* cr16-*-* cr16c-*-* cris*-*-* crx-*-* epiphany-*-*
-#notarget: h8300-*-* ip2k-*-* m10200-*-* m10300-*-* m32c-*-* metag-*-*
-#notarget: metag-*-* rl78-*-* rx-*-* sh*-*-* v850*-*-*
-# Targets with a leading char will faill this test.
+#xfail: bfin-*-* cr16-*-* cr16c-*-* crx-*-* epiphany-*-*
+#xfail: h8300-*-* ip2k-*-* mn10200-*-* mn10300-*-* m32c-*-* metag-*-*
+#xfail: rl78-*-* rx-*-* v850*-*-*
+# Targets with a leading char will fail this test.
 
 #...
   \[[ 0-9]+\] scnfoo[ \t]+PROGBITS[ \t]+[0-9a-f]+ +[0-9a-f]+ +0*10[ \t]+.*
diff --git a/ld/testsuite/ld-elf/pr21562h.d b/ld/testsuite/ld-elf/pr21562h.d
index dc4b72a..c94e636 100644
--- a/ld/testsuite/ld-elf/pr21562h.d
+++ b/ld/testsuite/ld-elf/pr21562h.d
@@ -2,10 +2,10 @@
 #ld: -shared -z defs -T pr21562a.t
 #readelf: -s -S --wide
 #target: *-*-linux* *-*-gnu*
-#notarget: bfin-*-* cr16-*-* cr16c-*-* cris*-*-* crx-*-* epiphany-*-*
-#notarget: h8300-*-* ip2k-*-* m10200-*-* m10300-*-* m32c-*-* metag-*-*
-#notarget: metag-*-* rl78-*-* rx-*-* sh*-*-* v850*-*-*
-# Targets with a leading char will faill this test.
+#xfail: bfin-*-* cr16-*-* cr16c-*-* crx-*-* epiphany-*-*
+#xfail: h8300-*-* ip2k-*-* mn10200-*-* mn10300-*-* m32c-*-* metag-*-*
+#xfail: rl78-*-* rx-*-* v850*-*-*
+# Targets with a leading char will fail this test.
 
 #...
   \[[ 0-9]+\] scnfoo[ \t]+PROGBITS[ \t]+[0-9a-f]+ +[0-9a-f]+ +0*10[ \t]+.*
diff --git a/ld/testsuite/ld-elf/pr21562i.d b/ld/testsuite/ld-elf/pr21562i.d
index 47b9cad..2670f60 100644
--- a/ld/testsuite/ld-elf/pr21562i.d
+++ b/ld/testsuite/ld-elf/pr21562i.d
@@ -2,12 +2,12 @@
 #ld: -shared -z defs --gc-sections -T pr21562b.t
 #readelf: -s -S --wide
 #target: *-*-linux* *-*-gnu*
-#notarget: d30v-*-* dlx-*-* i960-*-* pj*-*-*
-#notarget: hppa64-*-* i370-*-* i860-*-* ia64-*-* mep-*-* mn10200-*-*
-#notarget: bfin-*-* cr16-*-* cr16c-*-* cris*-*-* crx-*-* epiphany-*-*
-#notarget: h8300-*-* ip2k-*-* m10200-*-* m10300-*-* m32c-*-* metag-*-*
-#notarget: metag-*-* rl78-*-* rx-*-* sh*-*-* v850*-*-*
-# Targets with a leading char will faill this test.
+#xfail: d30v-*-* dlx-*-* i960-*-* pj*-*-*
+#xfail: hppa64-*-* i370-*-* i860-*-* ia64-*-* mep-*-* mn10200-*-*
+#xfail: bfin-*-* cr16-*-* cr16c-*-* crx-*-* epiphany-*-*
+#xfail: h8300-*-* ip2k-*-* mn10200-*-* mn10300-*-* m32c-*-* metag-*-*
+#xfail: rl78-*-* rx-*-* v850*-*-*
+# Targets with a leading char will fail this test.
 # generic linker targets don't support --gc-sections, nor do a bunch of others
 
 #...
diff --git a/ld/testsuite/ld-elf/pr21562j.d b/ld/testsuite/ld-elf/pr21562j.d
index eba2487..7c5508a 100644
--- a/ld/testsuite/ld-elf/pr21562j.d
+++ b/ld/testsuite/ld-elf/pr21562j.d
@@ -2,12 +2,12 @@
 #ld: -shared -z defs --gc-sections -T pr21562b.t
 #readelf: -s -S --wide
 #target: *-*-linux* *-*-gnu*
-#notarget: d30v-*-* dlx-*-* i960-*-* pj*-*-*
-#notarget: hppa64-*-* i370-*-* i860-*-* ia64-*-* mep-*-* mn10200-*-*
-#notarget: bfin-*-* cr16-*-* cr16c-*-* cris*-*-* crx-*-* epiphany-*-*
-#notarget: h8300-*-* ip2k-*-* m10200-*-* m10300-*-* m32c-*-* metag-*-*
-#notarget: metag-*-* rl78-*-* rx-*-* sh*-*-* v850*-*-*
-# Targets with a leading char will faill this test.
+#xfail: d30v-*-* dlx-*-* i960-*-* pj*-*-*
+#xfail: hppa64-*-* i370-*-* i860-*-* ia64-*-* mep-*-* mn10200-*-*
+#xfail: bfin-*-* cr16-*-* cr16c-*-* crx-*-* epiphany-*-*
+#xfail: h8300-*-* ip2k-*-* mn10200-*-* mn10300-*-* m32c-*-* metag-*-*
+#xfail: rl78-*-* rx-*-* v850*-*-*
+# Targets with a leading char will fail this test.
 # generic linker targets don't support --gc-sections, nor do a bunch of others
 
 #...
diff --git a/ld/testsuite/ld-elf/pr21562k.d b/ld/testsuite/ld-elf/pr21562k.d
index 594bc89..7f76d08 100644
--- a/ld/testsuite/ld-elf/pr21562k.d
+++ b/ld/testsuite/ld-elf/pr21562k.d
@@ -2,12 +2,12 @@
 #ld: -shared -z defs --gc-sections -T pr21562c.t
 #readelf: -s -S --wide
 #target: *-*-linux* *-*-gnu*
-#notarget: d30v-*-* dlx-*-* i960-*-* pj*-*-*
-#notarget: hppa64-*-* i370-*-* i860-*-* ia64-*-* mep-*-* mn10200-*-*
-#notarget: bfin-*-* cr16-*-* cr16c-*-* cris*-*-* crx-*-* epiphany-*-*
-#notarget: h8300-*-* ip2k-*-* m10200-*-* m10300-*-* m32c-*-* metag-*-*
-#notarget: metag-*-* rl78-*-* rx-*-* sh*-*-* v850*-*-*
-# Targets with a leading char will faill this test.
+#xfail: d30v-*-* dlx-*-* i960-*-* pj*-*-*
+#xfail: hppa64-*-* i370-*-* i860-*-* ia64-*-* mep-*-* mn10200-*-*
+#xfail: bfin-*-* cr16-*-* cr16c-*-* crx-*-* epiphany-*-*
+#xfail: h8300-*-* ip2k-*-* mn10200-*-* mn10300-*-* m32c-*-* metag-*-*
+#xfail: rl78-*-* rx-*-* v850*-*-*
+# Targets with a leading char will fail this test.
 # generic linker targets don't support --gc-sections, nor do a bunch of others
 
 #...
diff --git a/ld/testsuite/ld-elf/pr21562l.d b/ld/testsuite/ld-elf/pr21562l.d
index 1a9c2d6..1ad601c 100644
--- a/ld/testsuite/ld-elf/pr21562l.d
+++ b/ld/testsuite/ld-elf/pr21562l.d
@@ -2,12 +2,12 @@
 #ld: -shared -z defs --gc-sections -T pr21562c.t
 #readelf: -s -S --wide
 #target: *-*-linux* *-*-gnu*
-#notarget: d30v-*-* dlx-*-* i960-*-* pj*-*-*
-#notarget: hppa64-*-* i370-*-* i860-*-* ia64-*-* mep-*-* mn10200-*-*
-#notarget: bfin-*-* cr16-*-* cr16c-*-* cris*-*-* crx-*-* epiphany-*-*
-#notarget: h8300-*-* ip2k-*-* m10200-*-* m10300-*-* m32c-*-* metag-*-*
-#notarget: metag-*-* rl78-*-* rx-*-* sh*-*-* v850*-*-*
-# Targets with a leading char will faill this test.
+#xfail: d30v-*-* dlx-*-* i960-*-* pj*-*-*
+#xfail: hppa64-*-* i370-*-* i860-*-* ia64-*-* mep-*-* mn10200-*-*
+#xfail: bfin-*-* cr16-*-* cr16c-*-* crx-*-* epiphany-*-*
+#xfail: h8300-*-* ip2k-*-* mn10200-*-* mn10300-*-* m32c-*-* metag-*-*
+#xfail: rl78-*-* rx-*-* v850*-*-*
+# Targets with a leading char will fail this test.
 # generic linker targets don't support --gc-sections, nor do a bunch of others
 
 #...
diff --git a/ld/testsuite/ld-elf/pr21562m.d b/ld/testsuite/ld-elf/pr21562m.d
index b21698a..2fedacd 100644
--- a/ld/testsuite/ld-elf/pr21562m.d
+++ b/ld/testsuite/ld-elf/pr21562m.d
@@ -2,12 +2,12 @@
 #ld: -shared -z defs --gc-sections -T pr21562d.t
 #readelf: -s -S --wide
 #target: *-*-linux* *-*-gnu*
-#notarget: d30v-*-* dlx-*-* i960-*-* pj*-*-*
-#notarget: hppa64-*-* i370-*-* i860-*-* ia64-*-* mep-*-* mn10200-*-*
-#notarget: bfin-*-* cr16-*-* cr16c-*-* cris*-*-* crx-*-* epiphany-*-*
-#notarget: h8300-*-* ip2k-*-* m10200-*-* m10300-*-* m32c-*-* metag-*-*
-#notarget: metag-*-* rl78-*-* rx-*-* sh*-*-* v850*-*-*
-# Targets with a leading char will faill this test.
+#xfail: d30v-*-* dlx-*-* i960-*-* pj*-*-*
+#xfail: hppa64-*-* i370-*-* i860-*-* ia64-*-* mep-*-* mn10200-*-*
+#xfail: bfin-*-* cr16-*-* cr16c-*-* crx-*-* epiphany-*-*
+#xfail: h8300-*-* ip2k-*-* mn10200-*-* mn10300-*-* m32c-*-* metag-*-*
+#xfail: rl78-*-* rx-*-* v850*-*-*
+# Targets with a leading char will fail this test.
 # generic linker targets don't support --gc-sections, nor do a bunch of others
 
 #...
diff --git a/ld/testsuite/ld-elf/pr21562n.d b/ld/testsuite/ld-elf/pr21562n.d
index 561ec6b..f12b23d 100644
--- a/ld/testsuite/ld-elf/pr21562n.d
+++ b/ld/testsuite/ld-elf/pr21562n.d
@@ -2,12 +2,12 @@
 #ld: -shared -z defs --gc-sections -T pr21562d.t
 #readelf: -s -S --wide
 #target: *-*-linux* *-*-gnu*
-#notarget: d30v-*-* dlx-*-* i960-*-* pj*-*-*
-#notarget: hppa64-*-* i370-*-* i860-*-* ia64-*-* mep-*-* mn10200-*-*
-#notarget: bfin-*-* cr16-*-* cr16c-*-* cris*-*-* crx-*-* epiphany-*-*
-#notarget: h8300-*-* ip2k-*-* m10200-*-* m10300-*-* m32c-*-* metag-*-*
-#notarget: metag-*-* rl78-*-* rx-*-* sh*-*-* v850*-*-*
-# Targets with a leading char will faill this test.
+#xfail: d30v-*-* dlx-*-* i960-*-* pj*-*-*
+#xfail: hppa64-*-* i370-*-* i860-*-* ia64-*-* mep-*-* mn10200-*-*
+#xfail: bfin-*-* cr16-*-* cr16c-*-* crx-*-* epiphany-*-*
+#xfail: h8300-*-* ip2k-*-* mn10200-*-* mn10300-*-* m32c-*-* metag-*-*
+#xfail: rl78-*-* rx-*-* v850*-*-*
+# Targets with a leading char will fail this test.
 # generic linker targets don't support --gc-sections, nor do a bunch of others
 
 #...
diff --git a/ld/testsuite/ld-elf/sizeofa.d b/ld/testsuite/ld-elf/sizeofa.d
index d4432a0..340456d 100644
--- a/ld/testsuite/ld-elf/sizeofa.d
+++ b/ld/testsuite/ld-elf/sizeofa.d
@@ -1,16 +1,17 @@
 #source: sizeof.s
 #ld: -Ur
 #readelf: -sW
-#notarget: bfin-*-* cr16-*-* cr16c-*-* cris*-*-* crx-*-* epiphany-*-*
-#notarget: h8300-*-* ip2k-*-* m10200-*-* m10300-*-* m32c-*-* metag-*-*
-#notarget: metag-*-* rl78-*-* rx-*-* sh*-*-* v850*-*-*
-# Targets with a leading char will faill this test.
+#xfail: bfin-*-* cr16-*-* cr16c-*-* cris*-*-elf crx-*-* epiphany-*-*
+#xfail: h8300-*-* ip2k-*-* mn10200-*-* mn10300-*-* m32c-*-* metag-*-*
+#xfail: rl78-*-* rx-*-* sh*-*-elf* sh*-*-kaos* sh*-*-nto* sh-*-rtems*
+#xfail: sh*-*-symbianelf* sh*-*-vxworks v850*-*-*
+# Targets with a leading char will fail this test.
 
 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 +(LOC|GLOB)AL +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/sizeofb.d b/ld/testsuite/ld-elf/sizeofb.d
index cd3920b..e25d88f 100644
--- a/ld/testsuite/ld-elf/sizeofb.d
+++ b/ld/testsuite/ld-elf/sizeofb.d
@@ -2,10 +2,10 @@
 #ld: -shared
 #readelf: -sW
 #target: *-*-linux* *-*-gnu*
-#notarget: bfin-*-* cr16-*-* cr16c-*-* cris*-*-* crx-*-* epiphany-*-*
-#notarget: h8300-*-* ip2k-*-* m10200-*-* m10300-*-* m32c-*-* metag-*-*
-#notarget: metag-*-* rl78-*-* rx-*-* sh*-*-* v850*-*-*
-# Targets with a leading char will faill this test.
+#xfail: bfin-*-* cr16-*-* cr16c-*-* crx-*-* epiphany-*-*
+#xfail: h8300-*-* ip2k-*-* mn10200-*-* mn10300-*-* m32c-*-* metag-*-*
+#xfail: rl78-*-* rx-*-* v850*-*-*
+# Targets with a leading char will fail this test.
 
 Symbol table '\.dynsym' contains [0-9]+ entries:
  +Num: +Value +Size Type +Bind +Vis +Ndx Name
@@ -13,5 +13,5 @@ Symbol table '\.dynsym' contains [0-9]+ entries:
 #...
  +[0-9]+: +[a-f0-9]+ +0 +NOTYPE +LOCAL +DEFAULT +[0-9]+ +__stop_scnfoo
 #...
- +[0-9]+: 0+10 + +0 +NOTYPE +GLOBAL +DEFAULT +ABS +.sizeof.scnfoo
+ +[0-9]+: 0+10 + +0 +NOTYPE +LOCAL +DEFAULT +ABS +.sizeof.scnfoo
 #pass
diff --git a/ld/testsuite/ld-elf/startofa.d b/ld/testsuite/ld-elf/startofa.d
index cb261df..19ac29d 100644
--- a/ld/testsuite/ld-elf/startofa.d
+++ b/ld/testsuite/ld-elf/startofa.d
@@ -1,16 +1,17 @@
 #source: startof.s
 #ld: -Ur
 #readelf: -sW
-#notarget: bfin-*-* cr16-*-* cr16c-*-* cris*-*-* crx-*-* epiphany-*-*
-#notarget: h8300-*-* ip2k-*-* m10200-*-* m10300-*-* m32c-*-* metag-*-*
-#notarget: metag-*-* rl78-*-* rx-*-* sh*-*-* v850*-*-*
-# Targets with a leading char will faill this test.
+#xfail: bfin-*-* cr16-*-* cr16c-*-* cris*-*-elf crx-*-* epiphany-*-*
+#xfail: h8300-*-* ip2k-*-* mn10200-*-* mn10300-*-* m32c-*-* metag-*-*
+#xfail: rl78-*-* rx-*-* sh*-*-elf* sh*-*-kaos* sh*-*-nto* sh-*-rtems*
+#xfail: sh*-*-symbianelf* sh*-*-vxworks v850*-*-*
+# Targets with a leading char will fail this test.
 
 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 +(LOCAL +DEFAULT +[0-9]+ +__start_scnfoo|GLOBAL +DEFAULT +UND +.startof.scnfoo)
 #...
- +[0-9]+: +[a-f0-9]+ +0 +NOTYPE +GLOBAL +DEFAULT +[0-9]+ +__start_scnfoo
+ +[0-9]+: +[a-f0-9]+ +0 +NOTYPE +GLOBAL +DEFAULT +(UND +.startof.scnfoo|[0-9]+ +__start_scnfoo)
 #pass
diff --git a/ld/testsuite/ld-elf/startofb.d b/ld/testsuite/ld-elf/startofb.d
index 0d1da66..2cc1b86 100644
--- a/ld/testsuite/ld-elf/startofb.d
+++ b/ld/testsuite/ld-elf/startofb.d
@@ -2,16 +2,16 @@
 #ld: -shared
 #readelf: -sW
 #target: *-*-linux* *-*-gnu*
-#notarget: bfin-*-* cr16-*-* cr16c-*-* cris*-*-* crx-*-* epiphany-*-*
-#notarget: h8300-*-* ip2k-*-* m10200-*-* m10300-*-* m32c-*-* metag-*-*
-#notarget: metag-*-* rl78-*-* rx-*-* sh*-*-* v850*-*-*
-# Targets with a leading char will faill this test.
+#xfail: bfin-*-* cr16-*-* cr16c-*-* crx-*-* epiphany-*-*
+#xfail: h8300-*-* ip2k-*-* mn10200-*-* mn10300-*-* m32c-*-* metag-*-*
+#xfail: rl78-*-* rx-*-* v850*-*-*
+# Targets with a leading char will fail this test.
 
 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]+ +.startof.scnfoo
 #...
  +[0-9]+: +[a-f0-9]+ +0 +NOTYPE +LOCAL +DEFAULT +[0-9]+ +__start_scnfoo
 #pass

-- 
Alan Modra
Australia Development Lab, IBM


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