* ld-elf/orphan-region.d: Use ld -N.
[binutils-gdb.git] / ld / pe-dll.c
index b5470c5c75b373fc4d92ee3f5f7fd4208d42493e..8b9d5b4b097ba246374a0fc4b99ba3697787b652 100644 (file)
@@ -1,6 +1,6 @@
 /* Routines to help build PEI-format DLLs (Win32 etc)
    Copyright 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007,
-   2008, 2009 Free Software Foundation, Inc.
+   2008, 2009, 2010 Free Software Foundation, Inc.
    Written by DJ Delorie <dj@cygnus.com>
 
    This file is part of the GNU Binutils.
@@ -149,6 +149,7 @@ static void add_bfd_to_link (bfd *, const char *, struct bfd_link_info *);
 
 def_file * pe_def_file = 0;
 int pe_dll_export_everything = 0;
+int pe_dll_exclude_all_symbols = 0;
 int pe_dll_do_default_excludes = 1;
 int pe_dll_kill_ats = 0;
 int pe_dll_stdcall_aliases = 0;
@@ -157,6 +158,7 @@ int pe_dll_compat_implib = 0;
 int pe_dll_extra_pe_debug = 0;
 int pe_use_nul_prefixed_import_tables = 0;
 int pe_use_coff_long_section_names = -1;
+int pe_leading_underscore = -1;
 
 /* Static variables and types.  */
 
@@ -243,7 +245,9 @@ static const autofilter_entry_type autofilter_symbollist_i386[] =
 #define PE_ARCH_arm_epoc 5
 #define PE_ARCH_arm_wince 6
 
-static const pe_details_type pe_detail_list[] =
+/* Don't make it constant as underscore mode gets possibly overriden
+   by target or -(no-)leading-underscore option.  */
+static pe_details_type pe_detail_list[] =
 {
   {
 #ifdef pe_use_x86_64
@@ -381,7 +385,7 @@ static const autofilter_entry_type autofilter_symbolprefixlist[] =
   { STRING_COMMA_LEN ("__rtti_") },
   { STRING_COMMA_LEN ("__builtin_") },
   /* Don't re-export auto-imported symbols.  */
-  { STRING_COMMA_LEN ("_nm_") },
+  { STRING_COMMA_LEN ("__nm_") },
   /* Don't export symbols specifying internal DLL layout.  */
   { STRING_COMMA_LEN ("_head_") },
   { STRING_COMMA_LEN ("_IMPORT_DESCRIPTOR_") },
@@ -409,6 +413,11 @@ pe_dll_id_target (const char *target)
     if (strcmp (pe_detail_list[i].target_name, target) == 0
        || strcmp (pe_detail_list[i].object_target, target) == 0)
       {
+       int u = pe_leading_underscore; /* Underscoring mode. -1 for use default.  */
+       if (u == -1)
+         bfd_get_target_info (target, NULL, NULL, &u, NULL);
+       if (u != -1)
+         pe_detail_list[i].underscored = (u != 0 ? TRUE : FALSE);
        pe_details = pe_detail_list + i;
        return;
       }
@@ -441,8 +450,14 @@ pe_export_sort (const void *va, const void *vb)
 {
   const def_file_export *a = va;
   const def_file_export *b = vb;
-
-  return strcmp (a->name, b->name);
+  char *an = a->name;
+  char *bn = b->name;
+  if (a->its_name)
+    an = a->its_name;
+  if (b->its_name)
+    bn = b->its_name;
+
+  return strcmp (an, bn);
 }
 
 /* Read and process the .DEF file.  */
@@ -615,7 +630,7 @@ auto_export (bfd *abfd, def_file *d, const char *n)
 }
 
 static void
-process_def_file (bfd *abfd ATTRIBUTE_UNUSED, struct bfd_link_info *info)
+process_def_file_and_drectve (bfd *abfd ATTRIBUTE_UNUSED, struct bfd_link_info *info)
 {
   int i, j;
   struct bfd_link_hash_entry *blhe;
@@ -642,14 +657,37 @@ 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->executable)
+  /* Process aligned common symbol information from the
+     .drectve sections now; common symbol allocation is
+     done before final link, so it will be too late to
+     process them in process_embedded_commands() called
+     from _bfd_coff_link_input_bfd().  */
+  if (pe_def_file->aligncomms)
+    {
+      def_file_aligncomm *ac = pe_def_file->aligncomms;
+      while (ac)
+       {
+         struct coff_link_hash_entry *sym_hash;
+         sym_hash = coff_link_hash_lookup (coff_hash_table (info),
+               ac->symbol_name, FALSE, FALSE, FALSE);
+         if (sym_hash && sym_hash->root.type == bfd_link_hash_common
+           && sym_hash->root.u.c.p->alignment_power < (unsigned) ac->alignment)
+           {
+             sym_hash->root.u.c.p->alignment_power = (unsigned) ac->alignment;
+           }
+         ac = ac->next;
+       }
+    }
+
+  /* If we are building an executable and there is nothing
+     to export, we do not build an export table at all.  */
+  if (info->executable && pe_def_file->num_exports == 0
+      && (!pe_dll_export_everything || pe_dll_exclude_all_symbols))
     return;
 
   /* Now, maybe export everything else the default way.  */
-  if (pe_dll_export_everything || pe_def_file->num_exports == 0)
+  if ((pe_dll_export_everything || pe_def_file->num_exports == 0)
+      && !pe_dll_exclude_all_symbols)
     {
       for (b = info->input_bfds; b; b = b->link_next)
        {
@@ -708,7 +746,7 @@ process_def_file (bfd *abfd ATTRIBUTE_UNUSED, struct bfd_link_info *info)
                  if (auto_export (b, pe_def_file, sn))
                    {
                      def_file_export *p;
-                     p=def_file_add_export (pe_def_file, sn, 0, -1);
+                     p=def_file_add_export (pe_def_file, sn, 0, -1, NULL);
                      /* Fill data flag properly, from dlltool.c.  */
                      p->flag_data = !(symbols[j]->flags & BSF_FUNCTION);
                    }
@@ -720,6 +758,10 @@ process_def_file (bfd *abfd ATTRIBUTE_UNUSED, struct bfd_link_info *info)
 #undef NE
 #define NE pe_def_file->num_exports
 
+  /* Don't create an empty export table.  */
+  if (NE == 0)
+    return;
+
   /* Canonicalize the export list.  */
   if (pe_dll_kill_ats)
     {
@@ -760,7 +802,7 @@ process_def_file (bfd *abfd ATTRIBUTE_UNUSED, struct bfd_link_info *info)
              if (auto_export (NULL, pe_def_file, tmp))
                def_file_add_export (pe_def_file, tmp,
                                     pe_def_file->exports[i].internal_name,
-                                    -1);
+                                    -1, NULL);
              else
                free (tmp);
            }
@@ -1021,7 +1063,10 @@ generate_edata (bfd *abfd, struct bfd_link_info *info ATTRIBUTE_UNUSED)
                }
              exported_symbols[ei] = i;
            }
-         name_table_size += strlen (pe_def_file->exports[i].name) + 1;
+         if (pe_def_file->exports[i].its_name)
+           name_table_size += strlen (pe_def_file->exports[i].its_name) + 1;
+         else
+           name_table_size += strlen (pe_def_file->exports[i].name) + 1;
        }
 
       /* Reserve space for the forward name. */
@@ -1053,7 +1098,7 @@ generate_edata (bfd *abfd, struct bfd_link_info *info ATTRIBUTE_UNUSED)
 }
 
 /* Fill the exported symbol offsets. The preliminary work has already
-   been done in process_def_file().  */
+   been done in process_def_file_and_drectve().  */
 
 static void
 fill_exported_offsets (bfd *abfd ATTRIBUTE_UNUSED, struct bfd_link_info *info)
@@ -1167,6 +1212,8 @@ fill_edata (bfd *abfd, struct bfd_link_info *info ATTRIBUTE_UNUSED)
          if (!pe_def_file->exports[s].flag_noname)
            {
              char *ename = pe_def_file->exports[s].name;
+             if (pe_def_file->exports[s].its_name)
+               ename = pe_def_file->exports[s].its_name;
 
              bfd_put_32 (abfd, ERVA (enamestr), enameptrs);
              enameptrs += 4;
@@ -1267,7 +1314,7 @@ generate_reloc (bfd *abfd, struct bfd_link_info *info)
   for (bi = 0, b = info->input_bfds; b; bi++, b = b->link_next)
     {
       arelent **relocs;
-      int relsize, nrelocs, i;
+      int relsize, nrelocs;
 
       for (s = b->sections; s; s = s->next)
        {
@@ -1322,10 +1369,29 @@ generate_reloc (bfd *abfd, struct bfd_link_info *info)
                  if (sym->flags == BSF_WEAK)
                    {
                      struct bfd_link_hash_entry *blhe
-                       = bfd_link_hash_lookup (info->hash, sym->name,
+                       = bfd_wrapped_link_hash_lookup (abfd, info, sym->name,
                                                FALSE, FALSE, FALSE);
-                     if (!blhe || blhe->type != bfd_link_hash_defined)
-                       continue;                     
+                     if (blhe && blhe->type == bfd_link_hash_undefweak)
+                       {
+                         /* Check aux sym and see if it is defined or not. */
+                         struct coff_link_hash_entry *h, *h2;
+                         h = (struct coff_link_hash_entry *)blhe;
+                         if (h->symbol_class != C_NT_WEAK || h->numaux != 1)
+                           continue;
+                         h2 = h->auxbfd->tdata.coff_obj_data->sym_hashes
+                                               [h->aux->x_sym.x_tagndx.l];
+                         /* We don't want a base reloc if the aux sym is not
+                            found, undefined, or if it is the constant ABS
+                            zero default value.  (We broaden that slightly by
+                            not testing the value, just the section; there's
+                            no reason we'd want a reference to any absolute
+                            address to get relocated during rebasing).  */
+                         if (!h2 || h2->root.type == bfd_link_hash_undefined
+                               || h2->root.u.def.section == &bfd_abs_section)
+                           continue;
+                       }
+                     else if (!blhe || blhe->type != bfd_link_hash_defined)
+                       continue;
                    }
 
                  sym_vma = (relocs[i]->addend
@@ -1649,6 +1715,12 @@ pe_dll_generate_def_file (const char *pe_out_def_filename)
              else
                fprintf (out, "%d", im->ordinal);
 
+             if (im->its_name)
+               {
+                 fprintf (out, " == ");
+                 quoteput (im->its_name, out, 0);
+               }
+
              fprintf (out, "\n");
            }
        }
@@ -2032,8 +2104,9 @@ make_one (def_file_export *exp, bfd *parent, bfd_boolean include_jmp_stub)
   bfd_set_arch_mach (abfd, pe_details->bfd_arch, 0);
 
   symptr = 0;
-  symtab = xmalloc (11 * sizeof (asymbol *));
-  tx  = quick_section (abfd, ".text",    SEC_CODE|SEC_HAS_CONTENTS, 2);
+  symtab = xmalloc (12 * sizeof (asymbol *));
+
+  tx  = quick_section (abfd, ".text", SEC_CODE | SEC_HAS_CONTENTS | SEC_READONLY, 2);
   id7 = quick_section (abfd, ".idata$7", SEC_HAS_CONTENTS, 2);
   id5 = quick_section (abfd, ".idata$5", SEC_HAS_CONTENTS, 2);
   id4 = quick_section (abfd, ".idata$4", SEC_HAS_CONTENTS, 2);
@@ -2062,11 +2135,11 @@ make_one (def_file_export *exp, bfd *parent, bfd_boolean include_jmp_stub)
       /* Symbol to reference ord/name of imported
         data symbol, used to implement auto-import.  */
       if (exp->flag_data)
-       quick_symbol (abfd, U ("_nm_"), U (""), exp->internal_name, id6,
+       quick_symbol (abfd, "__nm_", U (""), exp->internal_name, id6,
                      BSF_GLOBAL,0);
     }
   if (pe_dll_compat_implib)
-    quick_symbol (abfd, U ("__imp_"), exp->internal_name, "", id5,
+    quick_symbol (abfd, "___imp_", exp->internal_name, "", id5,
                  BSF_GLOBAL, 0);
 
   if (include_jmp_stub)
@@ -2082,6 +2155,9 @@ make_one (def_file_export *exp, bfd *parent, bfd_boolean include_jmp_stub)
 #ifdef pe_use_x86_64
          quick_reloc (abfd, 2, BFD_RELOC_32_PCREL, 2);
 #else
+         /* Mark this object as SAFESEH compatible.  */
+         quick_symbol (abfd, "", "@feat.00", "", bfd_abs_section_ptr,
+                       BSF_LOCAL, 1);
           quick_reloc (abfd, 2, BFD_RELOC_32, 2);
 #endif
          break;
@@ -2155,7 +2231,10 @@ make_one (def_file_export *exp, bfd *parent, bfd_boolean include_jmp_stub)
   else
     {
       /* { short, asciz }  */
-      len = 2 + strlen (exp->name) + 1;
+      if (exp->its_name)
+       len = 2 + strlen (exp->its_name) + 1;
+      else
+       len = 2 + strlen (exp->name) + 1;
       if (len & 1)
        len++;
       bfd_set_section_size (abfd, id6, len);
@@ -2164,7 +2243,10 @@ make_one (def_file_export *exp, bfd *parent, bfd_boolean include_jmp_stub)
       memset (d6, 0, len);
       d6[0] = exp->hint & 0xff;
       d6[1] = exp->hint >> 8;
-      strcpy ((char *) d6 + 2, exp->name);
+      if (exp->its_name)
+       strcpy ((char*) d6 + 2, exp->its_name);
+      else
+       strcpy ((char *) d6 + 2, exp->name);
     }
 
   bfd_set_symtab (abfd, symtab, symptr);
@@ -2204,7 +2286,7 @@ make_singleton_name_imp (const char *import, bfd *parent)
   symptr = 0;
   symtab = xmalloc (3 * sizeof (asymbol *));
   id5 = quick_section (abfd, ".idata$5", SEC_HAS_CONTENTS, 2);
-  quick_symbol (abfd, U ("_imp_"), import, "", id5, BSF_GLOBAL, 0);
+  quick_symbol (abfd, "__imp_", import, "", id5, BSF_GLOBAL, 0);
 
   /* We need space for the real thunk and for the null terminator.  */
   bfd_set_section_size (abfd, id5, PE_IDATA5_SIZE * 2);
@@ -2245,8 +2327,8 @@ make_singleton_name_thunk (const char *import, bfd *parent)
   symptr = 0;
   symtab = xmalloc (3 * sizeof (asymbol *));
   id4 = quick_section (abfd, ".idata$4", SEC_HAS_CONTENTS, 2);
-  quick_symbol (abfd, U ("_nm_thnk_"), import, "", id4, BSF_GLOBAL, 0);
-  quick_symbol (abfd, U ("_nm_"), import, "", UNDSEC, BSF_GLOBAL, 0);
+  quick_symbol (abfd, "__nm_thnk_", import, "", id4, BSF_GLOBAL, 0);
+  quick_symbol (abfd, "__nm_", import, "", UNDSEC, BSF_GLOBAL, 0);
 
   /* We need space for the real thunk and for the null terminator.  */
   bfd_set_section_size (abfd, id4, PE_IDATA4_SIZE * 2);
@@ -2315,7 +2397,7 @@ make_import_fixup_mark (arelent *rel)
 static bfd *
 make_import_fixup_entry (const char *name,
                         const char *fixup_name,
-                        const char *dll_symname,
+                        const char *symname,
                         bfd *parent)
 {
   asection *id2;
@@ -2338,12 +2420,12 @@ make_import_fixup_entry (const char *name,
   symtab = xmalloc (6 * sizeof (asymbol *));
   id2 = quick_section (abfd, ".idata$2", SEC_HAS_CONTENTS, 2);
 
-  quick_symbol (abfd, U ("_nm_thnk_"), name, "", UNDSEC, BSF_GLOBAL, 0);
-  quick_symbol (abfd, U (""), dll_symname, "_iname", UNDSEC, BSF_GLOBAL, 0);
+  quick_symbol (abfd, "__nm_thnk_", name, "", UNDSEC, BSF_GLOBAL, 0);
+  quick_symbol (abfd, U (""), symname, "_iname", UNDSEC, BSF_GLOBAL, 0);
   /* For relocator v2 we have to use the .idata$5 element and not 
      fixup_name.  */
   if (link_info.pei386_runtime_pseudo_reloc == 2)
-    quick_symbol (abfd, U ("_imp_"), name, "", UNDSEC, BSF_GLOBAL, 0);
+    quick_symbol (abfd, "__imp_", name, "", UNDSEC, BSF_GLOBAL, 0);
   else
     quick_symbol (abfd, "", fixup_name, "", UNDSEC, BSF_GLOBAL, 0);
 
@@ -2413,7 +2495,7 @@ make_runtime_pseudo_reloc (const char *name ATTRIBUTE_UNUSED,
                  size += 12;
                  runtime_pseudp_reloc_v2_init = 1;
            }
-      quick_symbol (abfd, U ("_imp_"), name, "", UNDSEC, BSF_GLOBAL, 0);
+      quick_symbol (abfd, "__imp_", name, "", UNDSEC, BSF_GLOBAL, 0);
 
       bfd_set_section_size (abfd, rt_rel, size);
       rt_rel_d = xmalloc (size);
@@ -2506,10 +2588,10 @@ pe_create_import_fixup (arelent *rel, asection *s, bfd_vma addend)
   bfd *b;
   int need_import_table = 1;
 
-  sprintf (buf, U ("_imp_%s"), name);
+  sprintf (buf, "__imp_%s", name);
   name_imp_sym = bfd_link_hash_lookup (link_info.hash, buf, 0, 0, 1);
 
-  sprintf (buf, U ("_nm_thnk_%s"), name);
+  sprintf (buf, "__nm_thnk_%s", name);
 
   name_thunk_sym = bfd_link_hash_lookup (link_info.hash, buf, 0, 0, 1);
 
@@ -2523,7 +2605,7 @@ pe_create_import_fixup (arelent *rel, asection *s, bfd_vma addend)
   if (need_import_table == 1
       && (!name_thunk_sym || name_thunk_sym->type != bfd_link_hash_defined))
     {
-      bfd *b = make_singleton_name_thunk (name, link_info.output_bfd);
+      b = make_singleton_name_thunk (name, link_info.output_bfd);
       add_bfd_to_link (b, b->filename, &link_info);
 
       /* If we ever use autoimport, we have to cast text section writable.
@@ -2544,9 +2626,9 @@ pe_create_import_fixup (arelent *rel, asection *s, bfd_vma addend)
       && need_import_table == 1)
     {
       extern char * pe_data_import_dll;
-      char * dll_symname = pe_data_import_dll ? pe_data_import_dll : "unknown";
+      char * symname = pe_data_import_dll ? pe_data_import_dll : "unknown";
 
-      b = make_import_fixup_entry (name, fixup_name, dll_symname,
+      b = make_import_fixup_entry (name, fixup_name, symname,
                                   link_info.output_bfd);
       add_bfd_to_link (b, b->filename, &link_info);
     }
@@ -2710,8 +2792,40 @@ pe_dll_generate_implib (def_file *def, const char *impfilename, struct bfd_link_
     }
 }
 
+static struct bfd_link_hash_entry *found_sym;
+
+static bfd_boolean
+pe_undef_alias_cdecl_match (struct bfd_link_hash_entry *h, void *inf)
+{
+  int sl;
+  char *string = inf;
+  const char *hs = h->root.string;
+
+  sl = strlen (string);
+  if (h->type == bfd_link_hash_undefined
+      && ((*hs == '@' && (!pe_details->underscored || *string == '_')
+          && strncmp (hs + 1, string + (pe_details->underscored != 0),
+                      sl - (pe_details->underscored != 0)) == 0)
+         || strncmp (hs, string, sl) == 0)
+      && h->root.string[sl] == '@')
+    {
+      found_sym = h;
+      return FALSE;
+    }
+  return TRUE;
+}
+
+static struct bfd_link_hash_entry *
+pe_find_cdecl_alias_match (char *name)
+{
+  found_sym = 0;
+  bfd_link_hash_traverse (link_info.hash, pe_undef_alias_cdecl_match,
+                         (char *) name);
+  return found_sym;
+}
+
 static void
-add_bfd_to_link (bfd *abfd, const char *name, struct bfd_link_info *link_info)
+add_bfd_to_link (bfd *abfd, const char *name, struct bfd_link_info *linfo)
 {
   lang_input_statement_type *fake_file;
 
@@ -2721,12 +2835,12 @@ add_bfd_to_link (bfd *abfd, const char *name, struct bfd_link_info *link_info)
   fake_file->the_bfd = abfd;
   ldlang_add_file (fake_file);
 
-  if (!bfd_link_add_symbols (abfd, link_info))
+  if (!bfd_link_add_symbols (abfd, linfo))
     einfo ("%Xaddsym %s: %E\n", name);
 }
 
 void
-pe_process_import_defs (bfd *output_bfd, struct bfd_link_info *link_info)
+pe_process_import_defs (bfd *output_bfd, struct bfd_link_info *linfo)
 {
   def_file_module *module;
 
@@ -2757,6 +2871,9 @@ pe_process_import_defs (bfd *output_bfd, struct bfd_link_info *link_info)
            size_t len = strlen (pe_def_file->imports[i].internal_name);
            char *name = xmalloc (len + 2 + 6);
            bfd_boolean include_jmp_stub = FALSE;
+           bfd_boolean is_cdecl = FALSE;
+           if (!lead_at && strchr (pe_def_file->imports[i].internal_name, '@') == NULL)
+               is_cdecl = TRUE;
 
            if (lead_at)
              sprintf (name, "%s",
@@ -2765,7 +2882,7 @@ pe_process_import_defs (bfd *output_bfd, struct bfd_link_info *link_info)
              sprintf (name, "%s%s",U (""),
                       pe_def_file->imports[i].internal_name);
 
-           blhe = bfd_link_hash_lookup (link_info->hash, name,
+           blhe = bfd_link_hash_lookup (linfo->hash, name,
                                         FALSE, FALSE, FALSE);
 
            /* Include the jump stub for <sym> only if the <sym>
@@ -2779,12 +2896,20 @@ pe_process_import_defs (bfd *output_bfd, struct bfd_link_info *link_info)
                  sprintf (name, "%s%s%s", "__imp_", U (""),
                           pe_def_file->imports[i].internal_name);
 
-               blhe = bfd_link_hash_lookup (link_info->hash, name,
+               blhe = bfd_link_hash_lookup (linfo->hash, name,
                                             FALSE, FALSE, FALSE);
              }
            else
              include_jmp_stub = TRUE;
 
+           if (is_cdecl && !blhe)
+             {
+               sprintf (name, "%s%s",U (""),
+                        pe_def_file->imports[i].internal_name);
+               blhe = pe_find_cdecl_alias_match (name);
+               include_jmp_stub = TRUE;
+             }
+
            free (name);
 
            if (blhe && blhe->type == bfd_link_hash_undefined)
@@ -2794,11 +2919,12 @@ pe_process_import_defs (bfd *output_bfd, struct bfd_link_info *link_info)
                if (!do_this_dll)
                  {
                    bfd *ar_head = make_head (output_bfd);
-                   add_bfd_to_link (ar_head, ar_head->filename, link_info);
+                   add_bfd_to_link (ar_head, ar_head->filename, linfo);
                    do_this_dll = 1;
                  }
                exp.internal_name = pe_def_file->imports[i].internal_name;
                exp.name = pe_def_file->imports[i].name;
+               exp.its_name = pe_def_file->imports[i].its_name;
                exp.ordinal = pe_def_file->imports[i].ordinal;
                exp.hint = exp.ordinal >= 0 ? exp.ordinal : 0;
                exp.flag_private = 0;
@@ -2806,13 +2932,13 @@ pe_process_import_defs (bfd *output_bfd, struct bfd_link_info *link_info)
                exp.flag_data = pe_def_file->imports[i].data;
                exp.flag_noname = exp.name ? 0 : 1;
                one = make_one (&exp, output_bfd, (! exp.flag_data) && include_jmp_stub);
-               add_bfd_to_link (one, one->filename, link_info);
+               add_bfd_to_link (one, one->filename, linfo);
              }
          }
       if (do_this_dll)
        {
          bfd *ar_tail = make_tail (output_bfd);
-         add_bfd_to_link (ar_tail, ar_tail->filename, link_info);
+         add_bfd_to_link (ar_tail, ar_tail->filename, linfo);
        }
 
       free (dll_symname);
@@ -2861,7 +2987,7 @@ pe_implied_import_dll (const char *filename)
   unsigned char *expdata;
   char *erva;
   bfd_vma name_rvas, ordinals, nexp, ordbase;
-  const char *dll_name;
+  const char *dllname;
   /* Initialization with start > end guarantees that is_data
      will not be set by mistake, and avoids compiler warning.  */
   bfd_vma data_start = 1;
@@ -2887,7 +3013,7 @@ pe_implied_import_dll (const char *filename)
       return FALSE;
     }
 
-  /* Get pe_header, optional header and numbers of export entries.  */
+  /* Get pe_header, optional header and numbers of directory entries.  */
   pe_header_offset = pe_get32 (dll, 0x3c);
   opthdr_ofs = pe_header_offset + 4 + 20;
 #ifdef pe_use_x86_64
@@ -2896,7 +3022,8 @@ pe_implied_import_dll (const char *filename)
   num_entries = pe_get32 (dll, opthdr_ofs + 92);
 #endif
 
-  if (num_entries < 1) /* No exports.  */
+  /* No import or export directory entry.  */
+  if (num_entries < 1)
     return FALSE;
 
 #ifdef pe_use_x86_64
@@ -2907,6 +3034,10 @@ pe_implied_import_dll (const char *filename)
   export_size = pe_get32 (dll, opthdr_ofs + 100);
 #endif
 
+  /* No export table - nothing to export.  */
+  if (export_size == 0)
+    return FALSE;
+
   nsections = pe_get16 (dll, pe_header_offset + 4 + 2);
   secptr = (pe_header_offset + 4 + 20 +
            pe_get16 (dll, pe_header_offset + 4 + 16));
@@ -2995,15 +3126,15 @@ pe_implied_import_dll (const char *filename)
 
   /* Use internal dll name instead of filename
      to enable symbolic dll linking.  */
-  dll_name = erva + pe_as32 (expdata + 12);
+  dllname = erva + pe_as32 (expdata + 12);
 
   /* Check to see if the dll has already been added to
      the definition list and if so return without error.
      This avoids multiple symbol definitions.  */
-  if (def_get_module (pe_def_file, dll_name))
+  if (def_get_module (pe_def_file, dllname))
     {
       if (pe_dll_extra_pe_debug)
-       printf ("%s is already loaded\n", dll_name);
+       printf ("%s is already loaded\n", dllname);
       return TRUE;
     }
 
@@ -3019,7 +3150,7 @@ pe_implied_import_dll (const char *filename)
 
       /* Skip unwanted symbols, which are
         exported in buggy auto-import releases.  */
-      if (! CONST_STRNEQ (erva + name_rva, "_nm_"))
+      if (! CONST_STRNEQ (erva + name_rva, "__nm_"))
        {
          /* is_data is true if the address is in the data, rdata or bss
             segment.  */
@@ -3029,13 +3160,13 @@ pe_implied_import_dll (const char *filename)
            || (func_rva >= bss_start && func_rva < bss_end);
 
          imp = def_file_add_import (pe_def_file, erva + name_rva,
-                                    dll_name, i, 0);
+                                    dllname, i, 0, NULL);
          /* Mark symbol type.  */
          imp->data = is_data;
 
          if (pe_dll_extra_pe_debug)
            printf ("%s dll-name: %s sym: %s addr: 0x%lx %s\n",
-                   __FUNCTION__, dll_name, erva + name_rva,
+                   __FUNCTION__, dllname, erva + name_rva,
                    (unsigned long) func_rva, is_data ? "(data)" : "");
        }
     }
@@ -3062,7 +3193,7 @@ pe_dll_build_sections (bfd *abfd, struct bfd_link_info *info)
 {
   pe_dll_id_target (bfd_get_target (abfd));
   pe_output_file_set_long_section_names (abfd);
-  process_def_file (abfd, info);
+  process_def_file_and_drectve (abfd, info);
 
   if (pe_def_file->num_exports == 0 && !info->shared)
     return;