2004-12-14 Randolph Chung <tausq@debian.org>
[deliverable/binutils-gdb.git] / ld / pe-dll.c
index cc69474d203d272f855e235d49b28fa2d1b6f780..46b0a1381f594c6d984755ef254db4b4b168bc5e 100644 (file)
@@ -1,5 +1,6 @@
 /* Routines to help build PEI-format DLLs (Win32 etc)
-   Copyright 1998, 1999, 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
+   Copyright 1998, 1999, 2000, 2001, 2002, 2003, 2004
+   Free Software Foundation, Inc.
    Written by DJ Delorie <dj@cygnus.com>
 
    This file is part of GLD, the Gnu Linker.
@@ -137,7 +138,7 @@ int pe_dll_extra_pe_debug = 0;
 
 static bfd_vma image_base;
 static bfd *filler_bfd;
-static struct sec *edata_s, *reloc_s;
+static struct bfd_section *edata_s, *reloc_s;
 static unsigned char *edata_d, *reloc_d;
 static size_t edata_sz, reloc_sz;
 static int runtime_pseudo_relocs_created = 0;
@@ -339,7 +340,7 @@ pe_export_sort (const void *va, const void *vb)
    defined, since we can't export symbols we don't have.  */
 
 static bfd_vma *exported_symbol_offsets;
-static struct sec **exported_symbol_sections;
+static struct bfd_section **exported_symbol_sections;
 static int export_table_size;
 static int count_exported;
 static int count_exported_byname;
@@ -397,7 +398,7 @@ auto_export (bfd *abfd, def_file *d, const char *n)
     libname = lbasename (abfd->my_archive->filename);
 
   /* We should not re-export imported stuff.  */
-  if (strncmp (n, "_imp__", 6) == 0)
+  if (strncmp (n, "_imp_", 5) == 0)
     return 0;
 
   for (i = 0; i < d->num_exports; i++)
@@ -501,7 +502,7 @@ process_def_file (bfd *abfd ATTRIBUTE_UNUSED, struct bfd_link_info *info)
   int i, j;
   struct bfd_link_hash_entry *blhe;
   bfd *b;
-  struct sec *s;
+  struct bfd_section *s;
   def_file_export *e = 0;
 
   if (!pe_def_file)
@@ -514,7 +515,7 @@ process_def_file (bfd *abfd ATTRIBUTE_UNUSED, struct bfd_link_info *info)
       s = bfd_get_section_by_name (b, ".drectve");
       if (s)
        {
-         int size = bfd_get_section_size_before_reloc (s);
+         long size = s->size;
          char *buf = xmalloc (size);
 
          bfd_get_section_contents (b, s, buf, 0, size);
@@ -526,7 +527,7 @@ process_def_file (bfd *abfd ATTRIBUTE_UNUSED, struct bfd_link_info *info)
   /* If we are not building a DLL, when there are no exports
      we do not build an export table at all.  */
   if (!pe_dll_export_everything && pe_def_file->num_exports == 0
-      && !info->shared)
+      && info->executable)
     return;
 
   /* Now, maybe export everything else the default way.  */
@@ -626,9 +627,9 @@ process_def_file (bfd *abfd ATTRIBUTE_UNUSED, struct bfd_link_info *info)
   e = pe_def_file->exports;
 
   exported_symbol_offsets = xmalloc (NE * sizeof (bfd_vma));
-  exported_symbol_sections = xmalloc (NE * sizeof (struct sec *));
+  exported_symbol_sections = xmalloc (NE * sizeof (struct bfd_section *));
 
-  memset (exported_symbol_sections, 0, NE * sizeof (struct sec *));
+  memset (exported_symbol_sections, 0, NE * sizeof (struct bfd_section *));
   max_ordinal = 0;
   min_ordinal = 65536;
   count_exported = 0;
@@ -916,9 +917,9 @@ fill_edata (bfd *abfd, struct bfd_link_info *info ATTRIBUTE_UNUSED)
 {
   int s, hint;
   unsigned char *edirectory;
-  unsigned long *eaddresses;
-  unsigned long *enameptrs;
-  unsigned short *eordinals;
+  unsigned char *eaddresses;
+  unsigned char *enameptrs;
+  unsigned char *eordinals;
   unsigned char *enamestr;
   time_t now;
 
@@ -928,10 +929,10 @@ fill_edata (bfd *abfd, struct bfd_link_info *info ATTRIBUTE_UNUSED)
 
   /* Note use of array pointer math here.  */
   edirectory = edata_d;
-  eaddresses = (unsigned long *) (edata_d + 40);
-  enameptrs = eaddresses + export_table_size;
-  eordinals = (unsigned short *) (enameptrs + count_exported_byname);
-  enamestr = (char *) (eordinals + count_exported_byname);
+  eaddresses = edata_d + 40;
+  enameptrs = eaddresses + 4 * export_table_size;
+  eordinals = enameptrs + 4 * count_exported_byname;
+  enamestr = eordinals + 2 * count_exported_byname;
 
 #define ERVA(ptr) (((unsigned char *)(ptr) - edata_d) \
                   + edata_s->output_section->vma - image_base)
@@ -965,27 +966,27 @@ fill_edata (bfd *abfd, struct bfd_link_info *info ATTRIBUTE_UNUSED)
   hint = 0;
   for (s = 0; s < NE; s++)
     {
-      if (pe_def_file->exports[s].ordinal != -1)
+      struct bfd_section *ssec = exported_symbol_sections[s];
+      if (ssec && pe_def_file->exports[s].ordinal != -1)
        {
-         struct sec *ssec = exported_symbol_sections[s];
          unsigned long srva = (exported_symbol_offsets[s]
                                + ssec->output_section->vma
                                + ssec->output_offset);
          int ord = pe_def_file->exports[s].ordinal;
 
          bfd_put_32 (abfd, srva - image_base,
-                     (void *) (eaddresses + ord - min_ordinal));
+                     eaddresses + 4 * (ord - min_ordinal));
 
          if (!pe_def_file->exports[s].flag_noname)
            {
              char *ename = pe_def_file->exports[s].name;
 
-             bfd_put_32 (abfd, ERVA (enamestr), (void *) enameptrs);
-             enameptrs++;
+             bfd_put_32 (abfd, ERVA (enamestr), enameptrs);
+             enameptrs += 4;
              strcpy (enamestr, ename);
              enamestr += strlen (enamestr) + 1;
-             bfd_put_16 (abfd, ord - min_ordinal, (void *) eordinals);
-             eordinals++;
+             bfd_put_16 (abfd, ord - min_ordinal, eordinals);
+             eordinals += 2;
              pe_def_file->exports[s].hint = hint++;
            }
        }
@@ -993,7 +994,7 @@ fill_edata (bfd *abfd, struct bfd_link_info *info ATTRIBUTE_UNUSED)
 }
 
 
-static struct sec *current_sec;
+static struct bfd_section *current_sec;
 
 void
 pe_walk_relocs_of_symbol (struct bfd_link_info *info,
@@ -1031,7 +1032,7 @@ pe_walk_relocs_of_symbol (struct bfd_link_info *info,
 
          for (i = 0; i < nrelocs; i++)
            {
-             struct symbol_cache_entry *sym = *relocs[i]->sym_ptr_ptr;
+             struct bfd_symbol *sym = *relocs[i]->sym_ptr_ptr;
 
              if (!strcmp (name, sym->name))
                cb (relocs[i], s);
@@ -1060,7 +1061,7 @@ generate_reloc (bfd *abfd, struct bfd_link_info *info)
   unsigned long page_ptr, page_count;
   int bi;
   bfd *b;
-  struct sec *s;
+  struct bfd_section *s;
 
   total_relocs = 0;
   for (b = info->input_bfds; b; b = b->link_next)
@@ -1112,14 +1113,14 @@ generate_reloc (bfd *abfd, struct bfd_link_info *info)
            {
              if (pe_dll_extra_pe_debug)
                {
-                 struct symbol_cache_entry *sym = *relocs[i]->sym_ptr_ptr;
+                 struct bfd_symbol *sym = *relocs[i]->sym_ptr_ptr;
                  printf ("rel: %s\n", sym->name);
                }
              if (!relocs[i]->howto->pc_relative
                  && relocs[i]->howto->type != pe_details->imagebase_reloc)
                {
                  bfd_vma sym_vma;
-                 struct symbol_cache_entry *sym = *relocs[i]->sym_ptr_ptr;
+                 struct bfd_symbol *sym = *relocs[i]->sym_ptr_ptr;
 
                  sym_vma = (relocs[i]->addend
                             + sym->value
@@ -1155,7 +1156,12 @@ generate_reloc (bfd *abfd, struct bfd_link_info *info)
                      total_relocs++;
                      break;
                    case BITS_AND_SHIFT (24, 2):
-                     if (relocs[i]->howto->type == 5)
+                     /* FIXME: 0 is ARM_26D, it is defined in bfd/coff-arm.c
+                        Those ARM_xxx definitions should go in proper
+                        header someday.  */
+                     if (relocs[i]->howto->type == 0
+                         /* Older GNU linkers used 5 instead of 0 for this reloc.  */
+                         || relocs[i]->howto->type == 5)
                        /* This is an ARM_26D reloc, which is an ARM_26 reloc
                           that has already been fully processed during a
                           previous link stage, so ignore it here.  */
@@ -1246,7 +1252,7 @@ generate_reloc (bfd *abfd, struct bfd_link_info *info)
   if (page_ptr != (unsigned long) -1)
     bfd_put_32 (abfd, reloc_sz - page_ptr, reloc_d + page_ptr + 4);
 
-  while (reloc_sz < reloc_s->_raw_size)
+  while (reloc_sz < reloc_s->size)
     reloc_d[reloc_sz++] = 0;
 }
 
@@ -1956,7 +1962,7 @@ make_import_fixup_mark (arelent *rel)
   static char *fixup_name = NULL;
   static size_t buffer_len = 0;
 
-  struct symbol_cache_entry *sym = *rel->sym_ptr_ptr;
+  struct bfd_symbol *sym = *rel->sym_ptr_ptr;
 
   bfd *abfd = bfd_asymbol_bfd (sym);
   struct bfd_link_hash_entry *bh;
@@ -2154,7 +2160,7 @@ void
 pe_create_import_fixup (arelent *rel, asection *s, int addend)
 {
   char buf[300];
-  struct symbol_cache_entry *sym = *rel->sym_ptr_ptr;
+  struct bfd_symbol *sym = *rel->sym_ptr_ptr;
   struct bfd_link_hash_entry *name_thunk_sym;
   const char *name = sym->name;
   char *fixup_name = make_import_fixup_mark (rel);
@@ -2171,6 +2177,7 @@ pe_create_import_fixup (arelent *rel, asection *s, int addend)
 
       /* If we ever use autoimport, we have to cast text section writable.  */
       config.text_read_only = FALSE;
+      output_bfd->flags &= ~WP_TEXT;   
     }
 
   if (addend == 0 || link_info.pei386_runtime_pseudo_reloc)
@@ -2250,6 +2257,9 @@ pe_dll_generate_implib (def_file *def, const char *impfilename)
       char *internal = def->exports[i].internal_name;
       bfd *n;
 
+      /* Don't add PRIVATE entries to import lib.  */  
+      if (pe_def_file->exports[i].flag_private)
+       continue;
       def->exports[i].internal_name = def->exports[i].name;
       n = make_one (def->exports + i, outarch);
       n->next = head;
@@ -2441,9 +2451,11 @@ pe_implied_import_dll (const char *filename)
   /* Initialization with start > end guarantees that is_data
      will not be set by mistake, and avoids compiler warning.  */
   unsigned long data_start = 1;
-  unsigned long data_end   = 0;
-  unsigned long bss_start  = 1;
-  unsigned long bss_end    = 0;
+  unsigned long data_end = 0;
+  unsigned long rdata_start = 1;
+  unsigned long rdata_end = 0;
+  unsigned long bss_start = 1;
+  unsigned long bss_end = 0;
 
   /* No, I can't use bfd here.  kernel32.dll puts its export table in
      the middle of the .rdata section.  */
@@ -2516,6 +2528,15 @@ pe_implied_import_dll (const char *filename)
          data_start = vaddr;
          data_end = vaddr + vsize;
 
+         if (pe_dll_extra_pe_debug)
+           printf ("%s %s: 0x%08lx-0x%08lx (0x%08lx)\n",
+                   __FUNCTION__, sec_name, vaddr, vaddr + vsize, flags);
+       }
+      else if (strcmp(sec_name,".rdata") == 0)
+       {
+         rdata_start = vaddr;
+         rdata_end = vaddr + vsize;
+
          if (pe_dll_extra_pe_debug)
            printf ("%s %s: 0x%08lx-0x%08lx (0x%08lx)\n",
                    __FUNCTION__, sec_name, vaddr, vaddr + vsize, flags);
@@ -2573,9 +2594,11 @@ pe_implied_import_dll (const char *filename)
         exported in buggy auto-import releases.  */
       if (strncmp (erva + name_rva, "_nm_", 4) != 0)
        {
-         /* is_data is true if the address is in the data or bss segment.  */
+         /* is_data is true if the address is in the data, rdata or bss
+            segment.  */
          is_data =
            (func_rva >= data_start && func_rva < data_end)
+           || (func_rva >= rdata_start && func_rva < rdata_end)
            || (func_rva >= bss_start && func_rva < bss_end);
 
          imp = def_file_add_import (pe_def_file, erva + name_rva,
@@ -2642,7 +2665,7 @@ pe_dll_fill_sections (bfd *abfd, struct bfd_link_info *info)
 
   fill_edata (abfd, info);
 
-  if (info->shared)
+  if (info->shared && !info->pie)
     pe_data (abfd)->dll = 1;
 
   edata_s->contents = edata_d;
This page took 0.028589 seconds and 4 git commands to generate.