*** empty log message ***
[deliverable/binutils-gdb.git] / ld / emultempl / pe.em
index 99829a20371b62eebd64c40db084ac73ba7cb542..6519eae6d30642cd91f1f9483649e2608fcb2b65 100644 (file)
@@ -1,10 +1,16 @@
 # This shell script emits a C file. -*- C -*-
 # It does some substitutions.
+if [ -z "$MACHINE" ]; then 
+  OUTPUT_ARCH=${ARCH}
+else
+  OUTPUT_ARCH=${ARCH}:${MACHINE}
+fi
 rm -f e${EMULATION_NAME}.c
 (echo;echo;echo;echo;echo)>e${EMULATION_NAME}.c # there, now line numbers match ;-)
 cat >>e${EMULATION_NAME}.c <<EOF
 /* This file is part of GLD, the Gnu Linker.
-   Copyright 1995, 96, 97, 98, 99, 2000 Free Software Foundation, Inc.
+   Copyright 1995, 1996, 1997, 1998, 1999, 2000, 2001
+   Free Software Foundation, Inc.
 
 This program is free software; you can redistribute it and/or modify
 it under the terms of the GNU General Public License as published by
@@ -51,6 +57,8 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
 #include "deffile.h"
 #include "pe-dll.h"
 
+#include <ctype.h>
+
 #define TARGET_IS_${EMULATION_NAME}
 
 /* Permit the emulation parameters to override the default section
@@ -127,10 +135,20 @@ extern const char *output_filename;
 static void
 gld_${EMULATION_NAME}_before_parse()
 {
+  const bfd_arch_info_type *arch = bfd_scan_arch ("${OUTPUT_ARCH}");
+  if (arch)
+    {
+      ldfile_output_architecture = arch->arch;
+      ldfile_output_machine = arch->mach;
+      ldfile_output_machine_name = arch->printable_name;
+    }
+  else
+    ldfile_output_architecture = bfd_arch_${ARCH};
   output_filename = "${EXECUTABLE_NAME:-a.exe}";
-  ldfile_output_architecture = bfd_arch_${ARCH};
 #ifdef DLL_SUPPORT
+  config.dynamic_link = true;
   config.has_shared = 1;
+/* link_info.pei386_auto_import = true; */
 
 #if (PE_DEF_SUBSYSTEM == 9) || (PE_DEF_SUBSYSTEM == 2)
 #if defined TARGET_IS_mipspe || defined TARGET_IS_armpe
@@ -173,10 +191,13 @@ gld_${EMULATION_NAME}_before_parse()
 #define OPTION_IMP_COMPAT              (OPTION_WARN_DUPLICATE_EXPORTS + 1)
 #define OPTION_ENABLE_AUTO_IMAGE_BASE  (OPTION_IMP_COMPAT + 1)
 #define OPTION_DISABLE_AUTO_IMAGE_BASE (OPTION_ENABLE_AUTO_IMAGE_BASE + 1)
-#define OPTION_DLL_SEARCH_PREFIX               (OPTION_DISABLE_AUTO_IMAGE_BASE + 1)
+#define OPTION_DLL_SEARCH_PREFIX       (OPTION_DISABLE_AUTO_IMAGE_BASE + 1)
+#define OPTION_NO_DEFAULT_EXCLUDES     (OPTION_DLL_SEARCH_PREFIX + 1)
+#define OPTION_DLL_ENABLE_AUTO_IMPORT  (OPTION_NO_DEFAULT_EXCLUDES + 1)
+#define OPTION_DLL_DISABLE_AUTO_IMPORT (OPTION_DLL_ENABLE_AUTO_IMPORT + 1)
+#define OPTION_ENABLE_EXTRA_PE_DEBUG   (OPTION_DLL_DISABLE_AUTO_IMPORT + 1)
 
-static struct option longopts[] =
-{
+static struct option longopts[] = {
   /* PE options */
   {"base-file", required_argument, NULL, OPTION_BASE_FILE},
   {"dll", no_argument, NULL, OPTION_DLL},
@@ -211,6 +232,10 @@ static struct option longopts[] =
   {"enable-auto-image-base", no_argument, NULL, OPTION_ENABLE_AUTO_IMAGE_BASE},
   {"disable-auto-image-base", no_argument, NULL, OPTION_DISABLE_AUTO_IMAGE_BASE},
   {"dll-search-prefix", required_argument, NULL, OPTION_DLL_SEARCH_PREFIX},
+  {"no-default-excludes", no_argument, NULL, OPTION_NO_DEFAULT_EXCLUDES},
+  {"enable-auto-import", no_argument, NULL, OPTION_DLL_ENABLE_AUTO_IMPORT},
+  {"disable-auto-import", no_argument, NULL, OPTION_DLL_DISABLE_AUTO_IMPORT},
+  {"enable-extra-pe-debug", no_argument, NULL, OPTION_ENABLE_EXTRA_PE_DEBUG},
 #endif
   {NULL, no_argument, NULL, 0}
 };
@@ -250,7 +275,7 @@ static definfo init[] =
 #endif
   D(MinorSubsystemVersion,"__minor_subsystem_version__", 0),
   D(Subsystem,"__subsystem__", ${SUBSYSTEM}),
-  D(SizeOfStackReserve,"__size_of_stack_reserve__", 0x2000000),
+  D(SizeOfStackReserve,"__size_of_stack_reserve__", 0x200000),
   D(SizeOfStackCommit,"__size_of_stack_commit__", 0x1000),
   D(SizeOfHeapReserve,"__size_of_heap_reserve__", 0x100000),
   D(SizeOfHeapCommit,"__size_of_heap_commit__", 0x1000),
@@ -296,6 +321,11 @@ gld_${EMULATION_NAME}_list_options (file)
   fprintf (file, _("  --dll-search-prefix=<string>       When linking dynamically to a dll witout an\n"));
   fprintf (file, _("                                       importlib, use <string><basename>.dll \n"));
   fprintf (file, _("                                       in preference to lib<basename>.dll \n"));
+  fprintf (file, _("  --enable-auto-import               Do sophistcated linking of _sym to \n"));
+  fprintf (file, _("                                       __imp_sym for DATA references\n"));
+  fprintf (file, _("  --disable-auto-import              Do not auto-import DATA items from DLLs\n"));
+  fprintf (file, _("  --enable-extra-pe-debug            Enable verbose debug output when building\n"));
+  fprintf (file, _("                                       or linking to DLLs (esp. auto-import)\n"));
 #endif
 }
 
@@ -563,6 +593,18 @@ gld_${EMULATION_NAME}_parse_args(argc, argv)
     case OPTION_DLL_SEARCH_PREFIX:
       pe_dll_search_prefix = xstrdup( optarg );
       break;
+    case OPTION_NO_DEFAULT_EXCLUDES:
+      pe_dll_do_default_excludes = 0;
+      break;
+    case OPTION_DLL_ENABLE_AUTO_IMPORT:
+      link_info.pei386_auto_import = true;
+      break;
+    case OPTION_DLL_DISABLE_AUTO_IMPORT:
+      link_info.pei386_auto_import = false;
+      break;
+    case OPTION_ENABLE_EXTRA_PE_DEBUG:
+      pe_dll_extra_pe_debug = 1;
+      break;
 #endif
     }
   return 1;
@@ -696,14 +738,15 @@ pe_undef_cdecl_match (h, string)
   struct bfd_link_hash_entry *h;
   PTR string;
 {
-  int sl = strlen (string);
+  int sl;
+  sl = strlen (string); /* silence compiler warning */
   if (h->type == bfd_link_hash_defined
       && strncmp (h->root.string, string, sl) == 0
       && h->root.string[sl] == '@')
-  {
-    pe_undef_found_sym = h;
-    return false;
-  }
+    {
+      pe_undef_found_sym = h;
+      return false;
+    }
   return true;
 }
 
@@ -713,6 +756,11 @@ pe_fixup_stdcalls ()
   static int gave_warning_message = 0;
   struct bfd_link_hash_entry *undef, *sym;
   char *at;
+  if (pe_dll_extra_pe_debug) 
+    {
+      printf ("%s\n", __FUNCTION__);
+    }
+  
   for (undef = link_info.hash->undefs; undef; undef=undef->next)
     if (undef->type == bfd_link_hash_undefined)
     {
@@ -771,16 +819,127 @@ pe_fixup_stdcalls ()
       }
     }
 }
+
+static int
+make_import_fixup (rel)
+  arelent *rel;
+{
+  struct symbol_cache_entry *sym = *rel->sym_ptr_ptr;
+/*
+  bfd *b; 
+*/
+
+  if (pe_dll_extra_pe_debug) 
+    {
+      printf ("arelent: %s@%#x: add=%li\n", sym->name, 
+              (int) rel->address, rel->addend);
+    }
+  pe_create_import_fixup (rel);
+  return 1;
+}
+
+char *pe_data_import_dll;
+
+static void
+pe_find_data_imports ()
+{
+  struct bfd_link_hash_entry *undef, *sym;
+  for (undef = link_info.hash->undefs; undef; undef=undef->next)
+    {
+      if (undef->type == bfd_link_hash_undefined)
+        {
+          /* C++ symbols are *long* */
+          char buf[4096];
+          if (pe_dll_extra_pe_debug) 
+            {
+              printf ("%s:%s\n", __FUNCTION__, undef->root.string);
+            }
+          sprintf (buf, "__imp_%s", undef->root.string);
+
+          sym = bfd_link_hash_lookup (link_info.hash, buf, 0, 0, 1);
+          if (sym && sym->type == bfd_link_hash_defined)
+            {
+              einfo (_("Warning: resolving %s by linking to %s (auto-import)\n"),
+                     undef->root.string, buf);
+              {  
+                bfd *b = sym->u.def.section->owner;
+                asymbol **symbols;
+                int nsyms, symsize, i;
+     
+                symsize = bfd_get_symtab_upper_bound (b);
+                symbols = (asymbol **) xmalloc (symsize);
+                nsyms = bfd_canonicalize_symtab (b, symbols);
+
+                for (i = 0; i < nsyms; i++)
+                  {
+                    if (memcmp(symbols[i]->name, "__head_", 
+                             sizeof ("__head_") - 1))
+                      continue;
+                    if (pe_dll_extra_pe_debug)
+                      {
+                        printf ("->%s\n", symbols[i]->name);
+                      }
+                    pe_data_import_dll = (char*) (symbols[i]->name + 
+                                                  sizeof ("__head_") - 1);
+                    break;
+                  }
+              }
+
+              pe_walk_relocs_of_symbol (&link_info, undef->root.string, 
+                                        make_import_fixup);
+
+              /* let's differentiate it somehow from defined */
+              undef->type = bfd_link_hash_defweak;
+              /* we replace original name with __imp_ prefixed, this
+                 1) may trash memory 2) leads to duplicate symbol generation.
+                 Still, IMHO it's better than having name poluted. */
+              undef->root.string = sym->root.string;
+              undef->u.def.value = sym->u.def.value;
+              undef->u.def.section = sym->u.def.section;
+            }
+        }
+    }
+}
 #endif /* DLL_SUPPORT */
 
+static boolean
+pr_sym (h, string)
+  struct bfd_hash_entry *h;
+  PTR string;
+{
+  if (pe_dll_extra_pe_debug) 
+    {
+      printf("+%s\n",h->string);
+    }
+  return true;
+}
+
+
 static void
 gld_${EMULATION_NAME}_after_open ()
 {
+
+  if (pe_dll_extra_pe_debug) 
+    {
+      bfd *a;
+      struct bfd_link_hash_entry *sym;
+      printf ("%s()\n", __FUNCTION__);
+
+      for (sym = link_info.hash->undefs; sym; sym=sym->next)
+        printf ("-%s\n", sym->root.string);
+      bfd_hash_traverse (&link_info.hash->table, pr_sym,NULL);
+
+      for (a = link_info.input_bfds; a; a = a->link_next)
+        {
+          printf("*%s\n",a->filename);
+        }
+    }
+  
   /* Pass the wacky PE command line options into the output bfd.
      FIXME: This should be done via a function, rather than by
      including an internal BFD header.  */
   
-  if (!coff_data (output_bfd)->pe)
+  if (coff_data (output_bfd) == NULL || coff_data (output_bfd)->pe == NULL)
     einfo (_("%F%P: PE operations on non PE file.\n"));
 
   pe_data (output_bfd)->pe_opthdr = pe;
@@ -790,6 +949,8 @@ gld_${EMULATION_NAME}_after_open ()
   if (pe_enable_stdcall_fixup) /* -1=warn or 1=disable */
     pe_fixup_stdcalls ();
 
+  pe_find_data_imports (output_bfd, &link_info);
+
   pe_process_import_defs(output_bfd, &link_info);
   if (link_info.shared)
     pe_dll_build_sections (output_bfd, &link_info);
@@ -839,7 +1000,8 @@ gld_${EMULATION_NAME}_after_open ()
          {
            int idata2 = 0, reloc_count=0, is_imp = 0;
            asection *sec;
-           /* See if this is an import library thunk */
+           
+           /* See if this is an import library thunk.  */
            for (sec = is->the_bfd->sections; sec; sec = sec->next)
              {
                if (strcmp (sec->name, ".idata\$2") == 0)
@@ -848,46 +1010,83 @@ gld_${EMULATION_NAME}_after_open ()
                  is_imp = 1;
                reloc_count += sec->reloc_count;
              }
+           
            if (is_imp && !idata2 && reloc_count)
              {
-               /* it is, look for the reference to head and see if it's
-                  from our own library */
+               /* It is, look for the reference to head and see if it's
+                  from our own library */
                for (sec = is->the_bfd->sections; sec; sec = sec->next)
                  {
                    int i;
-                   int symsize = bfd_get_symtab_upper_bound (is->the_bfd);
-                   asymbol **symbols = (asymbol **) xmalloc (symsize);
-                   int relsize = bfd_get_reloc_upper_bound (is->the_bfd, sec);
-                   arelent **relocs = (arelent **) xmalloc ((size_t) relsize);
-                   int nrelocs = bfd_canonicalize_reloc (is->the_bfd, sec,
+                   long symsize;
+                   long relsize;
+                   asymbol **symbols;
+                   arelent **relocs;
+                   int nrelocs;
+                   
+                   symsize = bfd_get_symtab_upper_bound (is->the_bfd);
+                   if (symsize < 1)
+                     break;
+                   relsize = bfd_get_reloc_upper_bound (is->the_bfd, sec);
+                   if (relsize < 1)
+                     break;
+                   
+                   symbols = (asymbol **) xmalloc (symsize);
+                   symsize = bfd_canonicalize_symtab (is->the_bfd, symbols);
+                   if (symsize < 0)
+                     {
+                       einfo ("%X%P: unable to process symbols: %E");
+                       return;
+                     }
+                   
+                   relocs = (arelent **) xmalloc ((size_t) relsize);
+                   nrelocs = bfd_canonicalize_reloc (is->the_bfd, sec,
                                                          relocs, symbols);
-                   for (i=0; i<nrelocs; i++)
+                   if (nrelocs < 0)
+                     {
+                       free (relocs);
+                       einfo ("%X%P: unable to process relocs: %E");
+                       return;
+                     }
+                   
+                   for (i = 0; i < nrelocs; i++)
                      {
                        struct symbol_cache_entry *s;
+                       struct bfd_link_hash_entry * blhe;
+                       bfd *other_bfd;
+                       char *n;
+                       
                        s = (relocs[i]->sym_ptr_ptr)[0];
-                       if (!s->flags & BSF_LOCAL)
-                         {
-                           /* thunk section with reloc to another bfd... */
-                           struct bfd_link_hash_entry *blhe;
-                           blhe = bfd_link_hash_lookup (link_info.hash,
-                                                        s->name,
-                                                        false, false, true);
-                           if (blhe && blhe->type == bfd_link_hash_defined)
-                             {
-                               bfd *other_bfd = blhe->u.def.section->owner;
-                               if (strcmp (is->the_bfd->my_archive->filename,
-                                           other_bfd->my_archive->filename))
-                                 {
-                                   /* Rename this implib to match the other */
-                                   char *n = (char *) xmalloc (strlen (other_bfd->my_archive->filename) + 1);
-                                   strcpy (n, other_bfd->my_archive->filename);
-                                   is->the_bfd->my_archive->filename = n;
-                                 }
-                             }
-                         }
+                       
+                       if (s->flags & BSF_LOCAL)
+                         continue;
+                       
+                       /* Thunk section with reloc to another bfd.  */
+                       blhe = bfd_link_hash_lookup (link_info.hash,
+                                                    s->name,
+                                                    false, false, true);
+                           
+                       if (blhe == NULL
+                           || blhe->type != bfd_link_hash_defined)
+                         continue;
+                       
+                       other_bfd = blhe->u.def.section->owner;
+                           
+                       if (strcmp (is->the_bfd->my_archive->filename,
+                                   other_bfd->my_archive->filename) == 0)
+                         continue;
+                       
+                       /* Rename this implib to match the other.  */
+                       n = (char *) xmalloc (strlen (other_bfd->my_archive->filename) + 1);
+                           
+                       strcpy (n, other_bfd->my_archive->filename);
+                           
+                       is->the_bfd->my_archive->filename = n;
                      }
 
                    free (relocs);
+                   /* Note - we do not free the symbols,
+                      they are now cached in the BFD.  */
                  }
              }
          }
@@ -1193,6 +1392,16 @@ gld_${EMULATION_NAME}_finish ()
   if (pe_out_def_filename)
     pe_dll_generate_def_file (pe_out_def_filename);
 #endif /* DLL_SUPPORT */
+
+  /* I don't know where .idata gets set as code, but it shouldn't be */
+  {
+    asection *asec = bfd_get_section_by_name (output_bfd, ".idata");
+    if (asec)
+      {
+        asec->flags &= ~SEC_CODE;
+        asec->flags |= SEC_DATA;
+      }
+  }
 }
 
 \f
@@ -1225,6 +1434,7 @@ gld_${EMULATION_NAME}_place_orphan (file, s)
   const char *secname;
   char *hold_section_name;
   char *dollar = NULL;
+  const char *ps = NULL;
   lang_output_section_statement_type *os;
   lang_statement_list_type add_child;
 
@@ -1248,7 +1458,7 @@ gld_${EMULATION_NAME}_place_orphan (file, s)
       && os->bfd_section != NULL
       && ((s->flags ^ os->bfd_section->flags) & (SEC_LOAD | SEC_ALLOC)) == 0)
     {
-      wild_doit (&add_child, s, os, file);
+      lang_add_section (&add_child, s, os, file);
     }
   else
     {
@@ -1316,6 +1526,26 @@ gld_${EMULATION_NAME}_place_orphan (file, s)
       stat_ptr = &add;
       lang_list_init (stat_ptr);
 
+      if (config.build_constructors)
+       {
+         /* 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 = outsecname; *ps != '\0'; ps++)
+           if (! isalnum ((unsigned char) *ps) && *ps != '_')
+             break;
+         if (*ps == '\0')
+           {
+             char *symname;
+             etree_type *e_align;
+             
+             symname = (char *) xmalloc (ps - outsecname + sizeof "___start_");
+             sprintf (symname, "___start_%s", outsecname);
+             e_align = exp_unop (ALIGN_K,
+                                 exp_intop ((bfd_vma) 1 << s->alignment_power));
+             lang_add_assignment (exp_assop ('=', symname, e_align));
+           }
+       }
+      
       if (link_info.relocateable || (s->flags & (SEC_LOAD | SEC_ALLOC)) == 0)
        address = exp_intop ((bfd_vma) 0);
       else
@@ -1332,12 +1562,27 @@ gld_${EMULATION_NAME}_place_orphan (file, s)
                                                (etree_type *) NULL,
                                                (etree_type *) NULL);
 
-      wild_doit (&add_child, s, os, file);
+      lang_add_section (&add_child, s, os, file);
 
       lang_leave_output_section_statement
        ((bfd_vma) 0, "*default*",
         (struct lang_output_section_phdr_list *) NULL, "*default*");
 
+      if (config.build_constructors && *ps == '\0')
+        {
+         char *symname;
+
+         /* lang_leave_ouput_section_statement resets stat_ptr.  Put
+            stat_ptr back where we want it.  */
+         if (place != NULL)
+           stat_ptr = &add;
+         
+         symname = (char *) xmalloc (ps - outsecname + sizeof "___stop_");
+         sprintf (symname, "___stop_%s", outsecname);
+         lang_add_assignment (exp_assop ('=', symname,
+                                         exp_nameop (NAME, ".")));
+       }
+
       stat_ptr = old;
 
       if (place != NULL)
This page took 0.028553 seconds and 4 git commands to generate.