Index: src/ld/emulparams/arm_epoc_pe.sh
===================================================================
--- src.orig/ld/emulparams/arm_epoc_pe.sh	2009-10-28 10:19:00.277475000 +0100
+++ src/ld/emulparams/arm_epoc_pe.sh	2009-10-28 10:19:32.485370800 +0100
@@ -4,7 +4,6 @@
 LITTLE_OUTPUT_FORMAT="epoc-pei-arm-little"
 BIG_OUTPUT_FORMAT="epoc-pei-arm-big"
 TEMPLATE_NAME=pe
-ENTRY="_mainCRTStartup"
 SUBSYSTEM=PE_DEF_SUBSYSTEM
 INITIAL_SYMBOL_CHAR=\"_\"
 TARGET_PAGE_SIZE=0x1000
Index: src/ld/emulparams/arm_wince_pe.sh
===================================================================
--- src.orig/ld/emulparams/arm_wince_pe.sh	2009-10-28 10:19:00.279475000 +0100
+++ src/ld/emulparams/arm_wince_pe.sh	2009-10-28 10:19:32.485370800 +0100
@@ -8,7 +8,6 @@
 RELOCATEABLE_OUTPUT_FORMAT="pe-arm-wince-little"
 
 TEMPLATE_NAME=pe
-ENTRY="WinMainCRTStartup"
 SUBSYSTEM=PE_DEF_SUBSYSTEM
 INITIAL_SYMBOL_CHAR=\"\"
 TARGET_PAGE_SIZE=0x1000
Index: src/ld/emulparams/i386pe.sh
===================================================================
--- src.orig/ld/emulparams/i386pe.sh	2009-10-28 10:19:00.281475000 +0100
+++ src/ld/emulparams/i386pe.sh	2009-10-28 10:19:32.485370800 +0100
@@ -3,7 +3,6 @@
 OUTPUT_FORMAT="pei-i386"
 RELOCATEABLE_OUTPUT_FORMAT="pe-i386"
 TEMPLATE_NAME=pe
-ENTRY="_mainCRTStartup"
 SUBSYSTEM=PE_DEF_SUBSYSTEM
 INITIAL_SYMBOL_CHAR=\"_\"
 TARGET_PAGE_SIZE=0x1000
Index: src/ld/emulparams/i386pe_posix.sh
===================================================================
--- src.orig/ld/emulparams/i386pe_posix.sh	2009-10-28 10:19:00.284475000 +0100
+++ src/ld/emulparams/i386pe_posix.sh	2009-10-28 10:19:32.485370800 +0100
@@ -3,7 +3,6 @@
 OUTPUT_FORMAT="pei-i386"
 RELOCATEABLE_OUTPUT_FORMAT="pe-i386"
 TEMPLATE_NAME=pe
-ENTRY="___PosixProcessStartup"
 SUBSYSTEM=7
 EXECUTABLE_NAME=a.out
 INITIAL_SYMBOL_CHAR=\"_\"
Index: src/ld/emulparams/mcorepe.sh
===================================================================
--- src.orig/ld/emulparams/mcorepe.sh	2009-10-28 10:19:00.285475000 +0100
+++ src/ld/emulparams/mcorepe.sh	2009-10-28 10:19:32.485370800 +0100
@@ -4,7 +4,6 @@
 LITTLE_OUTPUT_FORMAT="pei-mcore-little"
 BIG_OUTPUT_FORMAT="pei-mcore-big"
 TEMPLATE_NAME=pe
-ENTRY="_mainCRTStartup"
 SUBSYSTEM=PE_DEF_SUBSYSTEM
 INITIAL_SYMBOL_CHAR=\"_\"
 TARGET_PAGE_SIZE=0x1000
Index: src/ld/emulparams/mipspe.sh
===================================================================
--- src.orig/ld/emulparams/mipspe.sh	2009-10-28 10:19:00.286475000 +0100
+++ src/ld/emulparams/mipspe.sh	2009-10-28 10:19:32.485370800 +0100
@@ -6,5 +6,4 @@
 TEMPLATE_NAME=pe
 SUBSYSTEM=PE_DEF_SUBSYSTEM
 INITIAL_SYMBOL_CHAR=\"_\"
-ENTRY="_mainCRTStartup"
 TARGET_PAGE_SIZE=0x1000
Index: src/ld/emulparams/ppcpe.sh
===================================================================
--- src.orig/ld/emulparams/ppcpe.sh	2009-10-28 10:19:00.287475000 +0100
+++ src/ld/emulparams/ppcpe.sh	2009-10-28 10:19:32.485370800 +0100
@@ -2,7 +2,6 @@
 SCRIPT_NAME=ppcpe
 OUTPUT_FORMAT="pei-powerpcle"
 TEMPLATE_NAME=pe
-ENTRY="_mainCRTStartup"
 SUBSYSTEM=PE_DEF_SUBSYSTEM
 INITIAL_SYMBOL_CHAR=\"_\"
 TARGET_PAGE_SIZE=0x1000
Index: src/ld/emulparams/shpe.sh
===================================================================
--- src.orig/ld/emulparams/shpe.sh	2009-10-28 10:19:00.289475000 +0100
+++ src/ld/emulparams/shpe.sh	2009-10-28 10:19:32.485370800 +0100
@@ -4,7 +4,4 @@
 TEMPLATE_NAME=pe
 SUBSYSTEM=PE_DEF_SUBSYSTEM
 INITIAL_SYMBOL_CHAR=\"_\"
-ENTRY="_mainCRTStartup"
-SUBSYSTEM=PE_DEF_SUBSYSTEM
-INITIAL_SYMBOL_CHAR=\"_\"
 TARGET_PAGE_SIZE=0x1000
Index: src/ld/emultempl/pe.em
===================================================================
--- src.orig/ld/emultempl/pe.em	2009-10-28 10:19:00.291475000 +0100
+++ src/ld/emultempl/pe.em	2009-10-28 12:10:54.233246600 +0100
@@ -1,6 +1,5 @@
 # This shell script emits a C file. -*- C -*-
 # It does some substitutions.
-test -z "${ENTRY}" && ENTRY="_mainCRTStartup"
 if [ -z "$MACHINE" ]; then
   OUTPUT_ARCH=${ARCH}
 else
@@ -122,6 +121,8 @@
 
 static struct internal_extra_pe_aouthdr pe;
 static int dll;
+static int is_linked_dll = 0;
+static int pe_subsystem = ${SUBSYSTEM};
 static flagword real_flags = 0;
 static int support_old_code = 0;
 static char * thumb_entry_symbol = NULL;
@@ -162,16 +163,6 @@
 fragment <<EOF
   link_info.pei386_auto_import = ${default_auto_import};
   link_info.pei386_runtime_pseudo_reloc = 1; /* Use by default version 1.  */
-
-#if (PE_DEF_SUBSYSTEM == 9) || (PE_DEF_SUBSYSTEM == 2)
-#if defined TARGET_IS_mipspe || defined TARGET_IS_armpe || defined TARGET_IS_arm_wince_pe
-  lang_default_entry ("WinMainCRTStartup");
-#else
-  lang_default_entry ("_WinMainCRTStartup");
-#endif
-#else
-  lang_default_entry ("${ENTRY}");
-#endif
 #endif
 }
 
@@ -459,36 +450,95 @@
   abort ();
 }
 
+static void
+set_entry_point (void)
+{
+  const char *entry;
+  const char *initial_symbol_char;
+  int i;
+
+  static const struct
+    {
+      const int value;
+      const char *entry;
+    }
+  v[] =
+    {
+      { 1, "NtProcessStartup"  },
+      { 2, "WinMainCRTStartup" },
+      { 3, "mainCRTStartup"    },
+      { 7, "__PosixProcessStartup"},
+      { 9, "WinMainCRTStartup" },
+      {14, "mainCRTStartup"    },
+      { 0, NULL          }
+    };
+
+  /* Entry point name for arbitrary subsystem numbers.  */
+  static const char default_entry[] = "mainCRTStartup";
+
+  if (link_info.shared || is_linked_dll)
+    {
+#if defined (TARGET_IS_i386pe)
+      entry = "DllMainCRTStartup@12";
+#else
+      entry = "DllMainCRTStartup";
+#endif
+    }
+  else
+    {
+
+      for (i = 0; v[i].entry; i++)
+        if (v[i].value == pe_subsystem)
+          break;
+
+      /* If no match, use the default.  */
+      if (v[i].entry != NULL)
+        entry = v[i].entry;
+      else
+        entry = default_entry;
+    }
+
+  initial_symbol_char = ${INITIAL_SYMBOL_CHAR};
+  if (*initial_symbol_char != '\0')
+    {
+      char *alc_entry;
+
+      /* lang_default_entry expects its argument to be permanently
+	 allocated, so we don't free this string.  */
+      alc_entry = xmalloc (strlen (initial_symbol_char)
+			   + strlen (entry)
+			   + 1);
+      strcpy (alc_entry, initial_symbol_char);
+      strcat (alc_entry, entry);
+      entry = alc_entry;
+    }
+
+  lang_default_entry (entry);
+}
 
 static void
 set_pe_subsystem (void)
 {
   const char *sver;
-  const char *entry;
-  const char *initial_symbol_char;
   char *end;
   int len;
   int i;
-  int subsystem;
   unsigned long temp_subsystem;
   static const struct
     {
       const char *name;
       const int value;
-      const char *entry;
     }
   v[] =
     {
-      { "native",  1, "NtProcessStartup" },
-      { "windows", 2, "WinMainCRTStartup" },
-      { "console", 3, "mainCRTStartup" },
-      { "posix",   7, "__PosixProcessStartup"},
-      { "wince",   9, "WinMainCRTStartup" },
-      { "xbox",   14, "mainCRTStartup" },
-      { NULL, 0, NULL }
+      { "native",  1},
+      { "windows", 2},
+      { "console", 3},
+      { "posix",   7},
+      { "wince",   9},
+      { "xbox",   14},
+      { NULL, 0 }
     };
-  /* Entry point name for arbitrary subsystem numbers.  */
-  static const char default_entry[] = "mainCRTStartup";
 
   /* Check for the presence of a version number.  */
   sver = strchr (optarg, ':');
@@ -498,10 +548,10 @@
     {
       len = sver - optarg;
       set_pe_name ("__major_subsystem_version__",
-		   strtoul (sver + 1, &end, 0));
+		    strtoul (sver + 1, &end, 0));
       if (*end == '.')
 	set_pe_name ("__minor_subsystem_version__",
-		     strtoul (end + 1, &end, 0));
+		      strtoul (end + 1, &end, 0));
       if (*end != '\0')
 	einfo (_("%P: warning: bad version number in -subsystem option\n"));
     }
@@ -515,14 +565,8 @@
 	if (v[i].value == (int) temp_subsystem)
 	  break;
 
-      /* If no match, use the default.  */
-      if (v[i].name != NULL)
-	entry = v[i].entry;
-      else
-	entry = default_entry;
-
       /* Use this subsystem.  */
-      subsystem = (int) temp_subsystem;
+      pe_subsystem = (int) temp_subsystem;
     }
   else
     {
@@ -538,28 +582,10 @@
 	  return;
 	}
 
-      entry = v[i].entry;
-      subsystem = v[i].value;
+      pe_subsystem = v[i].value;
     }
 
-  set_pe_name ("__subsystem__", subsystem);
-
-  initial_symbol_char = ${INITIAL_SYMBOL_CHAR};
-  if (*initial_symbol_char != '\0')
-    {
-      char *alc_entry;
-
-      /* lang_default_entry expects its argument to be permanently
-	 allocated, so we don't free this string.  */
-      alc_entry = xmalloc (strlen (initial_symbol_char)
-			   + strlen (entry)
-			   + 1);
-      strcpy (alc_entry, initial_symbol_char);
-      strcat (alc_entry, entry);
-      entry = alc_entry;
-    }
-
-  lang_default_entry (entry);
+  set_pe_name ("__subsystem__", pe_subsystem);
 
   return;
 }
@@ -648,6 +674,7 @@
       set_pe_value ("__section_alignment__");
       break;
     case OPTION_DLL:
+      is_linked_dll = 1;
       set_pe_name ("__dll__", 1);
       break;
     case OPTION_IMAGE_BASE:
@@ -889,6 +916,8 @@
     einfo (_("%P: warning: --export-dynamic is not supported for PE "
       "targets, did you mean --export-all-symbols?\n"));
 
+  set_entry_point ();
+
   after_parse_default ();
 }
 
Index: src/ld/emultempl/pep.em
===================================================================
--- src.orig/ld/emultempl/pep.em	2009-10-28 10:19:00.293475000 +0100
+++ src/ld/emultempl/pep.em	2009-10-28 10:46:06.734904400 +0100
@@ -1,6 +1,5 @@
 # This shell script emits a C file. -*- C -*-
 # It does some substitutions.
-test -z "${ENTRY}" && ENTRY="_mainCRTStartup"
 if [ -z "$MACHINE" ]; then
   OUTPUT_ARCH=${ARCH}
 else
@@ -101,6 +100,8 @@
 
 static struct internal_extra_pe_aouthdr pep;
 static int dll;
+static int is_linked_dll = 0;
+static int pep_subsystem = ${SUBSYSTEM};
 static flagword real_flags = IMAGE_FILE_LARGE_ADDRESS_AWARE;
 static int support_old_code = 0;
 static lang_assignment_statement_type *image_base_statement = 0;
@@ -126,12 +127,6 @@
   config.has_shared = 1;
   link_info.pei386_auto_import = -1;
   link_info.pei386_runtime_pseudo_reloc = 2; /* Use by default version 2.  */
-
-#if (PE_DEF_SUBSYSTEM == 9) || (PE_DEF_SUBSYSTEM == 2)
-  lang_default_entry ("_WinMainCRTStartup");
-#else
-  lang_default_entry ("${ENTRY}");
-#endif
 #endif
 }
 
@@ -402,36 +397,90 @@
   abort ();
 }
 
+static void
+set_entry_point (void)
+{
+  const char *entry;
+  const char *initial_symbol_char;
+  int i;
+
+  static const struct
+    {
+      const int value;
+      const char *entry;
+    }
+  v[] =
+    {
+      { 1, "NtProcessStartup"  },
+      { 2, "WinMainCRTStartup" },
+      { 3, "mainCRTStartup"    },
+      { 7, "__PosixProcessStartup" },
+      { 9, "WinMainCRTStartup" },
+      {14, "mainCRTStartup"    },
+      { 0, NULL          }
+    };
+
+  /* Entry point name for arbitrary subsystem numbers.  */
+  static const char default_entry[] = "mainCRTStartup";
+
+  if (link_info.shared || is_linked_dll)
+    {
+      entry = "DllMainCRTStartup";
+    }
+  else
+    {
+      for (i = 0; v[i].entry; i++)
+        if (v[i].value == pep_subsystem)
+          break;
+
+      /* If no match, use the default.  */
+      if (v[i].entry != NULL)
+        entry = v[i].entry;
+      else
+        entry = default_entry;
+    }
+
+  initial_symbol_char = ${INITIAL_SYMBOL_CHAR};
+  if (*initial_symbol_char != '\0')
+    {
+      char *alc_entry;
+
+      /* lang_default_entry expects its argument to be permanently
+	 allocated, so we don't free this string.  */
+      alc_entry = xmalloc (strlen (initial_symbol_char)
+			   + strlen (entry)
+			   + 1);
+      strcpy (alc_entry, initial_symbol_char);
+      strcat (alc_entry, entry);
+      entry = alc_entry;
+    }
+
+  lang_default_entry (entry);
+}
 
 static void
 set_pep_subsystem (void)
 {
   const char *sver;
-  const char *entry;
-  const char *initial_symbol_char;
   char *end;
   int len;
   int i;
-  int subsystem;
   unsigned long temp_subsystem;
   static const struct
     {
       const char *name;
       const int value;
-      const char *entry;
     }
   v[] =
     {
-      { "native",  1, "NtProcessStartup" },
-      { "windows", 2, "WinMainCRTStartup" },
-      { "console", 3, "mainCRTStartup" },
-      { "posix",   7, "__PosixProcessStartup"},
-      { "wince",   9, "_WinMainCRTStartup" },
-      { "xbox",   14, "mainCRTStartup" },
-      { NULL, 0, NULL }
+      { "native",  1 },
+      { "windows", 2 },
+      { "console", 3 },
+      { "posix",   7 },
+      { "wince",   9 },
+      { "xbox",   14 },
+      { NULL, 0 }
     };
-  /* Entry point name for arbitrary subsystem numbers.  */
-  static const char default_entry[] = "mainCRTStartup";
 
   /* Check for the presence of a version number.  */
   sver = strchr (optarg, ':');
@@ -458,14 +507,8 @@
 	if (v[i].value == (int) temp_subsystem)
 	  break;
 
-      /* If no match, use the default.  */
-      if (v[i].name != NULL)
-	entry = v[i].entry;
-      else
-	entry = default_entry;
-
       /* Use this subsystem.  */
-      subsystem = (int) temp_subsystem;
+      pep_subsystem = (int) temp_subsystem;
     }
   else
     {
@@ -481,28 +524,10 @@
 	  return;
 	}
 
-      entry = v[i].entry;
-      subsystem = v[i].value;
-    }
-
-  set_pep_name ("__subsystem__", subsystem);
-
-  initial_symbol_char = ${INITIAL_SYMBOL_CHAR};
-  if (*initial_symbol_char != '\0')
-    {
-      char *alc_entry;
-
-      /* lang_default_entry expects its argument to be permanently
-	 allocated, so we don't free this string.  */
-      alc_entry = xmalloc (strlen (initial_symbol_char)
-			   + strlen (entry)
-			   + 1);
-      strcpy (alc_entry, initial_symbol_char);
-      strcat (alc_entry, entry);
-      entry = alc_entry;
+      pep_subsystem = v[i].value;
     }
 
-  lang_default_entry (entry);
+  set_pep_name ("__subsystem__", pep_subsystem);
 
   return;
 }
@@ -591,6 +616,7 @@
       set_pep_value ("__section_alignment__");
       break;
     case OPTION_DLL:
+      is_linked_dll = 1;
       set_pep_name ("__dll__", 1);
       break;
     case OPTION_IMAGE_BASE:
@@ -826,6 +852,8 @@
     einfo (_("%P: warning: --export-dynamic is not supported for PE+ "
       "targets, did you mean --export-all-symbols?\n"));
 
+  set_entry_point ();
+  
   after_parse_default ();
 }
 
Index: src/ld/emulparams/armpe.sh
===================================================================
--- src.orig/ld/emulparams/armpe.sh	2009-10-28 10:19:00.276475000 +0100
+++ src/ld/emulparams/armpe.sh	2009-10-28 10:19:32.500998600 +0100
@@ -8,7 +8,6 @@
 RELOCATEABLE_OUTPUT_FORMAT="pe-arm-little"
 
 TEMPLATE_NAME=pe
-ENTRY="_mainCRTStartup"
 SUBSYSTEM=PE_DEF_SUBSYSTEM
 INITIAL_SYMBOL_CHAR=\"_\"
 
Index: src/ld/emulparams/i386pep.sh
===================================================================
--- src.orig/ld/emulparams/i386pep.sh	2009-10-28 10:19:00.282475000 +0100
+++ src/ld/emulparams/i386pep.sh	2009-10-28 10:19:32.500998600 +0100
@@ -3,7 +3,6 @@
 OUTPUT_FORMAT="pei-x86-64"
 RELOCATEABLE_OUTPUT_FORMAT="pe-x86-64"
 TEMPLATE_NAME=pep
-ENTRY="_mainCRTStartup"
 SUBSYSTEM=PE_DEF_SUBSYSTEM
 INITIAL_SYMBOL_CHAR=\"_\"
 TARGET_PAGE_SIZE=0x1000
