+2016-03-22  Nick Clifton  <nickc@redhat.com>
+
+       PR ld/19803
+       * ldlang.c (lang_add_gc_name): New function.  Adds the provided
+       symbol name to the list of gc symbols.
+       (lang_process): Call lang_add_gc_name with entry_symbol_default if
+       entry_symbol.name is NULL.  Use lang_add_gc_name to add the init
+       and fini function names.
+       * pe-dll.c (process_def_file_and_drectve): Add exported names to
+       the gc symbol list.
+       * testsuite/ld-pe/pr19803.s: Do not export _testval symbol.
+       * testsuite/ld-pe/pr19803.d: Tweak expected output.
+
 2016-03-22  Nick Clifton  <nickc@redhat.com>
 
        * configure: Regenerate.
 
 }
 #endif /* ENABLE_PLUGINS */
 
+/* Add NAME to the list of garbage collection entry points.  */
+
+void
+lang_add_gc_name (const char * name)
+{
+  struct bfd_sym_chain *sym;
+
+  if (name == NULL)
+    return;
+
+  sym = (struct bfd_sym_chain *) stat_alloc (sizeof (*sym));
+
+  sym->next = link_info.gc_sym_list;
+  sym->name = name;
+  link_info.gc_sym_list = sym;
+}
+
 void
 lang_process (void)
 {
     }
 #endif /* ENABLE_PLUGINS */
 
+  /* Make sure that nobody has tried to add a symbol to this list before now.  */
+  ASSERT (link_info.gc_sym_list == NULL);
+
   link_info.gc_sym_list = &entry_symbol;
 
   if (entry_symbol.name == NULL)
       /* entry_symbol is normally initialied by a ENTRY definition in the
         linker script or the -e command line option.  But if neither of
         these have been used, the target specific backend may still have
-        provided an entry symbol via a call to lang_default_entry()o.
+        provided an entry symbol via a call to lang_default_entry().
         Unfortunately this value will not be processed until lang_end()
         is called, long after this function has finished.  So detect this
         case here and add the target's entry symbol to the list of starting
         points for garbage collection resolution.  */
-      if (entry_symbol_default != NULL)
-       {
-         struct bfd_sym_chain *sym
-           = (struct bfd_sym_chain *) stat_alloc (sizeof (*sym));
-         sym->next = link_info.gc_sym_list;
-         sym->name = entry_symbol_default;
-         link_info.gc_sym_list = sym;
-       }
+      lang_add_gc_name (entry_symbol_default);
     }
 
- if (link_info.init_function != NULL)
-    {
-      struct bfd_sym_chain *sym
-       = (struct bfd_sym_chain *) stat_alloc (sizeof (*sym));
-      sym->next = link_info.gc_sym_list;
-      sym->name = link_info.init_function;
-      link_info.gc_sym_list = sym;
-    }
-  if (link_info.fini_function != NULL)
-    {
-      struct bfd_sym_chain *sym
-       = (struct bfd_sym_chain *) stat_alloc (sizeof (*sym));
-      sym->next = link_info.gc_sym_list;
-      sym->name = link_info.fini_function;
-      link_info.gc_sym_list = sym;
-    }
+  lang_add_gc_name (link_info.init_function);
+  lang_add_gc_name (link_info.fini_function);
 
   ldemul_after_open ();
   if (config.map_file != NULL)
 
 #ld: -shared --out-implib dx.dll.a --gc-sections
 #objdump: --syms
-#notarget: mcore-* arm-epoc-pe
+#notarget: mcore-*
 #
-# Check that the target specific entry symbol _DllMainCRTStartup is still
+# The MCORE-PE target does not support -shared.
+#
+# Check that the target specific entry symbol *Startup is still
 # a defined (sec > 0), public (scl == 2) symbol, even after garbage
 # collection.
-#
-# Check that the symbol _testval is undefined (sec == 0) and hidden
-# (scl == 106) in the output.  It should have been changed to this state when
-# garbage collection was performed.
 
-#...
-.*\(sec  0\)\(fl 0x00\)\(ty   0\)\(scl 106\) \(nx 0\) 0x0+000 _testval
 #...
 .*\(sec  1\)\(fl 0x00\)\(ty   0\)\(scl   2\) \(nx 0\) 0x0+000 .*Startup.*
 #pass