]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blobdiff - ld/pe-dll.c
2.41 Release sources
[thirdparty/binutils-gdb.git] / ld / pe-dll.c
index 577b911da8a6ffb5b845fee6c4789da1da169c47..02e03d169489259818e2e45f034b1ee44890b4d4 100644 (file)
@@ -1,5 +1,5 @@
 /* Routines to help build PEI-format DLLs (Win32 etc)
-   Copyright (C) 1998-2019 Free Software Foundation, Inc.
+   Copyright (C) 1998-2023 Free Software Foundation, Inc.
    Written by DJ Delorie <dj@cygnus.com>
 
    This file is part of the GNU Binutils.
@@ -25,6 +25,7 @@
 #include "libiberty.h"
 #include "filenames.h"
 #include "safe-ctype.h"
+#include "ctf-api.h"
 
 #include <time.h>
 
@@ -41,7 +42,7 @@
 #include "../bfd/libcoff.h"
 #include "deffile.h"
 
-#ifdef pe_use_x86_64
+#ifdef pe_use_plus
 
 #define PE_IDATA4_SIZE 8
 #define PE_IDATA5_SIZE 8
@@ -159,6 +160,7 @@ 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;
+int pe_dll_enable_reloc_section = 1;
 
 /* Static variables and types.  */
 
@@ -166,9 +168,10 @@ static bfd_vma image_base;
 static bfd *filler_bfd;
 static struct bfd_section *edata_s, *reloc_s;
 static unsigned char *edata_d, *reloc_d;
-static size_t edata_sz, reloc_sz;
+static unsigned char *reloc_d = NULL;
+static size_t edata_sz, reloc_sz = 0;
 static int runtime_pseudo_relocs_created = 0;
-static bfd_boolean runtime_pseudp_reloc_v2_init = FALSE;
+static bool runtime_pseudp_reloc_v2_init = false;
 
 typedef struct
 {
@@ -184,7 +187,7 @@ typedef struct
   unsigned int imagebase_reloc;
   int pe_arch;
   int bfd_arch;
-  bfd_boolean underscored;
+  bool underscored;
   const autofilter_entry_type* autofilter_symbollist;
 }
 pe_details_type;
@@ -207,7 +210,7 @@ static const autofilter_entry_type autofilter_symbollist_i386[] =
   { STRING_COMMA_LEN ("_NULL_IMPORT_DESCRIPTOR") },
   /* Entry point symbols, and entry hooks.  */
   { STRING_COMMA_LEN ("cygwin_crt0") },
-#ifdef pe_use_x86_64
+#ifdef pe_use_plus
   { STRING_COMMA_LEN ("DllMain") },
   { STRING_COMMA_LEN ("DllEntryPoint") },
   { STRING_COMMA_LEN ("DllMainCRTStartup") },
@@ -244,13 +247,14 @@ static const autofilter_entry_type autofilter_symbollist_i386[] =
 #define PE_ARCH_mips    3
 #define PE_ARCH_arm     4
 #define PE_ARCH_arm_wince 5
+#define PE_ARCH_aarch64  6
 
 /* 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
+#ifdef pe_use_plus
     "pei-x86-64",
     "pe-x86-64",
     3 /* R_IMAGEBASE */,
@@ -261,21 +265,31 @@ static pe_details_type pe_detail_list[] =
 #endif
     PE_ARCH_i386,
     bfd_arch_i386,
-#ifdef pe_use_x86_64
-    FALSE,
+#ifdef pe_use_plus
+    false,
 #else
-    TRUE,
+    true,
 #endif
     autofilter_symbollist_i386
   },
-#ifdef pe_use_x86_64
+#ifdef pe_use_plus
   {
     "pei-x86-64",
     "pe-bigobj-x86-64",
     3 /* R_IMAGEBASE */,
     PE_ARCH_i386,
     bfd_arch_i386,
-    FALSE,
+    false,
+    autofilter_symbollist_i386
+  },
+#else
+  {
+    "pei-i386",
+    "pe-bigobj-i386",
+    7 /* R_IMAGEBASE */,
+    PE_ARCH_i386,
+    bfd_arch_i386,
+    true,
     autofilter_symbollist_i386
   },
 #endif
@@ -285,7 +299,7 @@ static pe_details_type pe_detail_list[] =
     16 /* R_SH_IMAGEBASE */,
     PE_ARCH_sh,
     bfd_arch_sh,
-    TRUE,
+    true,
     autofilter_symbollist_generic
   },
   {
@@ -294,7 +308,7 @@ static pe_details_type pe_detail_list[] =
     34 /* MIPS_R_RVA */,
     PE_ARCH_mips,
     bfd_arch_mips,
-    FALSE,
+    false,
     autofilter_symbollist_generic
   },
   {
@@ -303,7 +317,7 @@ static pe_details_type pe_detail_list[] =
     11 /* ARM_RVA32 */,
     PE_ARCH_arm,
     bfd_arch_arm,
-    TRUE,
+    true,
     autofilter_symbollist_generic
   },
   {
@@ -312,10 +326,19 @@ static pe_details_type pe_detail_list[] =
     2,  /* ARM_RVA32 on Windows CE, see bfd/coff-arm.c.  */
     PE_ARCH_arm_wince,
     bfd_arch_arm,
-    FALSE,
+    false,
+    autofilter_symbollist_generic
+  },
+  {
+    "pei-aarch64-little",
+    "pe-aarch64-little",
+    2,  /* ARM64_RVA32 */
+    PE_ARCH_aarch64,
+    bfd_arch_aarch64,
+    false,
     autofilter_symbollist_generic
   },
-  { NULL, NULL, 0, 0, 0, FALSE, NULL }
+  { NULL, NULL, 0, 0, 0, false, NULL }
 };
 
 static const pe_details_type *pe_details;
@@ -336,6 +359,7 @@ static const autofilter_entry_type autofilter_liblist[] =
   { STRING_COMMA_LEN ("libgcj") },
   { STRING_COMMA_LEN ("libmsvcrt") },
   { STRING_COMMA_LEN ("libmsvcrt-os") },
+  { STRING_COMMA_LEN ("libucrt") },
   { STRING_COMMA_LEN ("libucrtbase") },
   { NULL, 0 }
 };
@@ -427,7 +451,7 @@ pe_dll_id_target (const char *target)
          bfd_get_target_info (target, NULL, NULL, &u, NULL);
        if (u == -1)
          abort ();
-       pe_detail_list[i].underscored = (u != 0 ? TRUE : FALSE);
+       pe_detail_list[i].underscored = u != 0;
        pe_details = pe_detail_list + i;
        pe_leading_underscore = (u != 0 ? 1 : 0);
        return;
@@ -444,16 +468,25 @@ typedef struct
     bfd_vma vma;
     char type;
     short extra;
+    int idx;
   }
 reloc_data_type;
 
 static int
 reloc_sort (const void *va, const void *vb)
 {
-  bfd_vma a = ((const reloc_data_type *) va)->vma;
-  bfd_vma b = ((const reloc_data_type *) vb)->vma;
+  const reloc_data_type *a = (const reloc_data_type *) va;
+  const reloc_data_type *b = (const reloc_data_type *) vb;
 
-  return (a > b) ? 1 : ((a < b) ? -1 : 0);
+  if (a->vma > b->vma)
+    return 1;
+  if (a->vma < b->vma)
+    return -1;
+  if (a->idx > b->idx)
+    return 1;
+  if (a->idx < b->idx)
+    return -1;
+  return 0;
 }
 
 static int
@@ -483,7 +516,7 @@ static int export_table_size;
 static int count_exported;
 static int count_exported_byname;
 static int count_with_ordinals;
-static const char *dll_name;
+static const char *dll_filename;
 static int min_ordinal, max_ordinal;
 static int *exported_symbols;
 
@@ -521,10 +554,10 @@ pe_dll_add_excludes (const char *new_excludes, const exclude_type type)
   free (local_copy);
 }
 
-static bfd_boolean
+static bool
 is_import (const char* n)
 {
-  return (CONST_STRNEQ (n, "__imp_"));
+  return (startswith (n, "__imp_"));
 }
 
 /* abfd is a bfd containing n (or NULL)
@@ -539,13 +572,14 @@ auto_export (bfd *abfd, def_file *d, const char *n)
   const char * libname = NULL;
 
   if (abfd && abfd->my_archive)
-    libname = lbasename (abfd->my_archive->filename);
+    libname = lbasename (bfd_get_filename (abfd->my_archive));
 
   key.name = key.its_name = (char *) n;
 
   /* Return false if n is in the d->exports table.  */
-  if (bsearch (&key, d->exports, d->num_exports,
-              sizeof (pe_def_file->exports[0]), pe_export_sort))
+  if (d->num_exports != 0
+      && bsearch (&key, d->exports, d->num_exports,
+                 sizeof (pe_def_file->exports[0]), pe_export_sort))
     return 0;
 
   if (pe_dll_do_default_excludes)
@@ -573,7 +607,7 @@ auto_export (bfd *abfd, def_file *d, const char *n)
 
       /* Next, exclude symbols from certain startup objects.  */
 
-      if (abfd && (p = lbasename (abfd->filename)))
+      if (abfd && (p = lbasename (bfd_get_filename (abfd))))
        {
          afptr = autofilter_objlist;
          while (afptr->name)
@@ -634,7 +668,7 @@ auto_export (bfd *abfd, def_file *d, const char *n)
        }
       else if (ex->type == EXCLUDEFORIMPLIB)
        {
-         if (filename_cmp (abfd->filename, ex->string) == 0)
+         if (filename_cmp (bfd_get_filename (abfd), ex->string) == 0)
            return 0;
        }
       else if (strcmp (n, ex->string) == 0)
@@ -648,11 +682,12 @@ static void
 process_def_file_and_drectve (bfd *abfd ATTRIBUTE_UNUSED, struct bfd_link_info *info)
 {
   int i, j;
+  unsigned int ui;
   struct bfd_link_hash_entry *blhe;
   bfd *b;
   struct bfd_section *s;
   def_file_export *e = 0;
-  bfd_boolean resort_needed;
+  bool resort_needed;
 
   if (!pe_def_file)
     pe_def_file = def_file_empty ();
@@ -685,7 +720,7 @@ process_def_file_and_drectve (bfd *abfd ATTRIBUTE_UNUSED, struct bfd_link_info *
        {
          struct coff_link_hash_entry *sym_hash;
          sym_hash = coff_link_hash_lookup (coff_hash_table (info),
-                                           ac->symbol_name, FALSE, FALSE, FALSE);
+                                           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)
            {
@@ -695,6 +730,15 @@ process_def_file_and_drectve (bfd *abfd ATTRIBUTE_UNUSED, struct bfd_link_info *
        }
     }
 
+  if (pe_def_file->exclude_symbols)
+    {
+      for (ui = 0; ui < pe_def_file->num_exclude_symbols; ui++)
+       {
+         pe_dll_add_excludes (pe_def_file->exclude_symbols[ui].symbol_name,
+                              EXCLUDESYMS);
+       }
+    }
+
   /* If we are building an executable and there is nothing
      to export, we do not build an export table at all.  */
   if (bfd_link_executable (info) && pe_def_file->num_exports == 0
@@ -724,7 +768,7 @@ process_def_file_and_drectve (bfd *abfd ATTRIBUTE_UNUSED, struct bfd_link_info *
              /* We should export symbols which are either global or not
                 anything at all.  (.bss data is the latter)
                 We should not export undefined symbols.  */
-             bfd_boolean would_export
+             bool would_export
                = (symbols[j]->section != bfd_und_section_ptr
                   && ((symbols[j]->flags & BSF_GLOBAL)
                       || (symbols[j]->flags == 0)));
@@ -746,7 +790,7 @@ process_def_file_and_drectve (bfd *abfd ATTRIBUTE_UNUSED, struct bfd_link_info *
                    sprintf (name, "%s%s", "__imp_", sn);
 
                    blhe = bfd_link_hash_lookup (info->hash, name,
-                                                FALSE, FALSE, FALSE);
+                                                false, false, false);
                    free (name);
 
                    if (blhe && blhe->type == bfd_link_hash_defined)
@@ -758,7 +802,7 @@ process_def_file_and_drectve (bfd *abfd ATTRIBUTE_UNUSED, struct bfd_link_info *
 
                  if (auto_export (b, pe_def_file, sn))
                    {
-                     int is_dup = 0;
+                     bool is_dup = false;
                      def_file_export *p;
 
                      p = def_file_add_export (pe_def_file, sn, 0, -1,
@@ -779,7 +823,7 @@ process_def_file_and_drectve (bfd *abfd ATTRIBUTE_UNUSED, struct bfd_link_info *
   if (NE == 0)
     return;
 
-  resort_needed = FALSE;
+  resort_needed = false;
 
   /* Canonicalize the export list.  */
   if (pe_dll_kill_ats)
@@ -804,7 +848,7 @@ process_def_file_and_drectve (bfd *abfd ATTRIBUTE_UNUSED, struct bfd_link_info *
                einfo (_("%X%P: cannot export %s: invalid export name\n"),
                       pe_def_file->exports[i].name);
              pe_def_file->exports[i].name = tmp;
-             resort_needed = TRUE;
+             resort_needed = true;
            }
        }
     }
@@ -824,7 +868,7 @@ process_def_file_and_drectve (bfd *abfd ATTRIBUTE_UNUSED, struct bfd_link_info *
 
          if (strchr (pe_def_file->exports[i].name, '@'))
            {
-             int is_dup = 1;
+             bool is_dup = true;
              int lead_at = (*pe_def_file->exports[i].name == '@');
              char *tmp = xstrdup (pe_def_file->exports[i].name + lead_at);
 
@@ -870,12 +914,9 @@ process_def_file_and_drectve (bfd *abfd ATTRIBUTE_UNUSED, struct bfd_link_info *
          e[j - 1].flag_constant |= e[i].flag_constant;
          e[j - 1].flag_noname |= e[i].flag_noname;
          e[j - 1].flag_data |= e[i].flag_data;
-         if (e[i].name)
-           free (e[i].name);
-         if (e[i].internal_name)
-           free (e[i].internal_name);
-         if (e[i].its_name)
-           free (e[i].its_name);
+         free (e[i].name);
+         free (e[i].internal_name);
+         free (e[i].its_name);
        }
       else
        {
@@ -918,7 +959,7 @@ process_def_file_and_drectve (bfd *abfd ATTRIBUTE_UNUSED, struct bfd_link_info *
 
       blhe = bfd_link_hash_lookup (info->hash,
                                   name,
-                                  FALSE, FALSE, TRUE);
+                                  false, false, true);
 
       if (blhe
          && (blhe->type == bfd_link_hash_defined
@@ -993,9 +1034,10 @@ process_def_file_and_drectve (bfd *abfd ATTRIBUTE_UNUSED, struct bfd_link_info *
 /* Build the bfd that will contain .edata and .reloc sections.  */
 
 static void
-build_filler_bfd (int include_edata)
+build_filler_bfd (bool include_edata)
 {
   lang_input_statement_type *filler_file;
+
   filler_file = lang_add_input_file ("dll stuff",
                                     lang_input_file_is_fake_enum,
                                     NULL);
@@ -1014,33 +1056,31 @@ build_filler_bfd (int include_edata)
     {
       edata_s = bfd_make_section_old_way (filler_bfd, ".edata");
       if (edata_s == NULL
-         || !bfd_set_section_flags (filler_bfd, edata_s,
-                                    (SEC_HAS_CONTENTS
-                                     | SEC_ALLOC
-                                     | SEC_LOAD
-                                     | SEC_KEEP
-                                     | SEC_IN_MEMORY)))
+         || !bfd_set_section_flags (edata_s, (SEC_HAS_CONTENTS
+                                              | SEC_ALLOC
+                                              | SEC_LOAD
+                                              | SEC_KEEP
+                                              | SEC_IN_MEMORY)))
        {
          einfo (_("%X%P: can not create .edata section: %E\n"));
          return;
        }
-      bfd_set_section_size (filler_bfd, edata_s, edata_sz);
+      bfd_set_section_size (edata_s, edata_sz);
     }
 
   reloc_s = bfd_make_section_old_way (filler_bfd, ".reloc");
   if (reloc_s == NULL
-      || !bfd_set_section_flags (filler_bfd, reloc_s,
-                                (SEC_HAS_CONTENTS
-                                 | SEC_ALLOC
-                                 | SEC_LOAD
-                                 | SEC_KEEP
-                                 | SEC_IN_MEMORY)))
+      || !bfd_set_section_flags (reloc_s, (SEC_HAS_CONTENTS
+                                          | SEC_ALLOC
+                                          | SEC_LOAD
+                                          | SEC_KEEP
+                                          | SEC_IN_MEMORY)))
     {
       einfo (_("%X%P: can not create .reloc section: %E\n"));
       return;
     }
 
-  bfd_set_section_size (filler_bfd, reloc_s, 0);
+  bfd_set_section_size (reloc_s, 0);
 
   ldlang_add_file (filler_file);
 }
@@ -1048,25 +1088,13 @@ build_filler_bfd (int include_edata)
 /* Gather all the exported symbols and build the .edata section.  */
 
 static void
-generate_edata (bfd *abfd, struct bfd_link_info *info ATTRIBUTE_UNUSED)
+generate_edata (void)
 {
   int i, next_ordinal;
   int name_table_size = 0;
-  const char *dlnp;
 
   /* First, we need to know how many exported symbols there are,
      and what the range of ordinals is.  */
-  if (pe_def_file->name)
-    dll_name = pe_def_file->name;
-  else
-    {
-      dll_name = abfd->filename;
-
-      for (dlnp = dll_name; *dlnp; dlnp++)
-       if (*dlnp == '\\' || *dlnp == '/' || *dlnp == ':')
-         dll_name = dlnp + 1;
-    }
-
   if (count_with_ordinals && max_ordinal > count_exported)
     {
       if (min_ordinal > max_ordinal - count_exported + 1)
@@ -1141,7 +1169,7 @@ generate_edata (bfd *abfd, struct bfd_link_info *info ATTRIBUTE_UNUSED)
              + 4 * export_table_size           /* addresses */
              + 4 * count_exported_byname       /* name ptrs */
              + 2 * count_exported_byname       /* ordinals */
-             + name_table_size + strlen (dll_name) + 1);
+             + name_table_size + strlen (dll_filename) + 1);
 }
 
 /* Fill the exported symbol offsets. The preliminary work has already
@@ -1169,7 +1197,7 @@ fill_exported_offsets (bfd *abfd ATTRIBUTE_UNUSED, struct bfd_link_info *info)
 
       blhe = bfd_link_hash_lookup (info->hash,
                                   name,
-                                  FALSE, FALSE, TRUE);
+                                  false, false, true);
 
       if (blhe && blhe->type == bfd_link_hash_defined)
        exported_symbol_offsets[i] = blhe->u.def.value;
@@ -1202,8 +1230,10 @@ fill_edata (bfd *abfd, struct bfd_link_info *info ATTRIBUTE_UNUSED)
 
   memset (edata_d, 0, edata_sz);
 
-  if (pe_data (abfd)->insert_timestamp)
+  if (pe_data (abfd)->timestamp == -1)
     H_PUT_32 (abfd, time (0), edata_d + 4);
+  else
+    H_PUT_32 (abfd, pe_data (abfd)->timestamp, edata_d + 4);
 
   if (pe_def_file->version_major != -1)
     {
@@ -1212,7 +1242,7 @@ fill_edata (bfd *abfd, struct bfd_link_info *info ATTRIBUTE_UNUSED)
     }
 
   bfd_put_32 (abfd, ERVA (enamestr), edata_d + 12);
-  strcpy (enamestr, dll_name);
+  strcpy (enamestr, dll_filename);
   enamestr += strlen (enamestr) + 1;
   bfd_put_32 (abfd, min_ordinal, edata_d + 16);
   bfd_put_32 (abfd, export_table_size, edata_d + 20);
@@ -1303,7 +1333,7 @@ pe_walk_relocs (struct bfd_link_info *info,
        {
          arelent **relocs;
          int relsize, nrelocs, i;
-         int flags = bfd_get_section_flags (b, s);
+         int flags = bfd_section_flags (s);
 
          /* Skip discarded linkonce sections.  */
          if (flags & SEC_LINK_ONCE
@@ -1323,7 +1353,7 @@ pe_walk_relocs (struct bfd_link_info *info,
              /* Warning: the callback needs to be passed NAME directly.  */
              if (import_hash)
                {
-                 if (bfd_hash_lookup (import_hash, sym->name, FALSE, FALSE))
+                 if (bfd_hash_lookup (import_hash, sym->name, false, false))
                    {
                      strcpy (name, sym->name);
                      cb (relocs[i], s, name, symname);
@@ -1393,7 +1423,7 @@ pe_find_data_imports (const char *symhead,
        char *impname;
 
        if (pe_dll_extra_pe_debug)
-         printf ("%s:%s\n", __FUNCTION__, undef->root.string);
+         printf ("%s:%s\n", __func__, undef->root.string);
 
        strcpy (name, undef->root.string);
        impname = name - (sizeof "__imp_" - 1);
@@ -1404,7 +1434,7 @@ pe_find_data_imports (const char *symhead,
        if (sym && sym->type == bfd_link_hash_defined)
          {
            if (import_hash)
-             bfd_hash_lookup (import_hash, undef->root.string, TRUE, FALSE);
+             bfd_hash_lookup (import_hash, undef->root.string, true, false);
            else
              {
                bfd *b = sym->u.def.section->owner;
@@ -1452,7 +1482,7 @@ pe_find_data_imports (const char *symhead,
 
            if (link_info.pei386_auto_import == -1)
              {
-               static bfd_boolean warned = FALSE;
+               static bool warned = false;
 
                info_msg (_("Info: resolving %s by linking to %s "
                            "(auto-import)\n"), name, impname);
@@ -1465,7 +1495,7 @@ pe_find_data_imports (const char *symhead,
                             "command line; this should work unless it "
                             "involves constant data structures referencing "
                             "symbols from auto-imported DLLs\n"));
-                   warned = TRUE;
+                   warned = true;
                  }
              }
          }
@@ -1487,17 +1517,19 @@ pe_find_data_imports (const char *symhead,
 static void
 generate_reloc (bfd *abfd, struct bfd_link_info *info)
 {
-
   /* For .reloc stuff.  */
   reloc_data_type *reloc_data;
   int total_relocs = 0;
   int i;
   bfd_vma sec_page = (bfd_vma) -1;
-  bfd_vma page_ptr, page_count;
-  int bi;
+  bfd_vma page_ptr;
   bfd *b;
   struct bfd_section *s;
 
+  if (reloc_s == NULL || reloc_s->output_section == bfd_abs_section_ptr)
+    return;
+
+  /* Set an upper bound for the total number of relocations we will have to generate.  */
   total_relocs = 0;
   for (b = info->input_bfds; b; b = b->link.next)
     for (s = b->sections; s; s = s->next)
@@ -1506,42 +1538,49 @@ generate_reloc (bfd *abfd, struct bfd_link_info *info)
   reloc_data = xmalloc (total_relocs * sizeof (reloc_data_type));
 
   total_relocs = 0;
-  bi = 0;
-  for (bi = 0, b = info->input_bfds; b; bi++, b = b->link.next)
+  for (b = info->input_bfds; b; b = b->link.next)
     {
       arelent **relocs;
       int relsize, nrelocs;
+      asymbol **symbols;
+
+      if (!bfd_generic_link_read_symbols (b))
+       {
+         einfo (_("%F%P: %pB: could not read symbols: %E\n"), b);
+         return;
+       }
+
+      symbols = bfd_get_outsymbols (b);
 
       for (s = b->sections; s; s = s->next)
        {
-         bfd_vma sec_vma = s->output_section->vma + s->output_offset;
-         asymbol **symbols;
+         bfd_vma sec_vma;
 
-         /* If it's not loaded, we don't need to relocate it this way.  */
-         if (!(s->output_section->flags & SEC_LOAD))
-           continue;
+         /* If the section is not going to be output, then ignore it.  */
+         if (s->output_section == NULL)
+           {
+             /* FIXME: This should not happen.  Convert to the correct
+                form here, but really, this should be investigated.  */
+             s->output_section = bfd_abs_section_ptr;
+             continue;
+           }
 
          /* I don't know why there would be a reloc for these, but I've
             seen it happen - DJ  */
          if (s->output_section == bfd_abs_section_ptr)
            continue;
 
+         /* If it's not loaded, we don't need to relocate it this way.  */
+         if (!(s->output_section->flags & SEC_LOAD))
+           continue;
+
+         /* This happens when linking with --just-symbols=<file>
+            so do not generate an error.  */
          if (s->output_section->vma == 0)
-           {
-             /* Huh?  Shouldn't happen, but punt if it does.  */
-             einfo (_("%P: zero vma section reloc detected: `%s' #%d f=%d\n"),
-                    s->output_section->name, s->output_section->index,
-                    s->output_section->flags);
-             continue;
-           }
+           continue;
 
-         if (!bfd_generic_link_read_symbols (b))
-           {
-             einfo (_("%F%P: %pB: could not read symbols: %E\n"), b);
-             return;
-           }
+         sec_vma = s->output_section->vma + s->output_offset;
 
-         symbols = bfd_get_outsymbols (b);
          relsize = bfd_get_reloc_upper_bound (b, s);
          relocs = xmalloc (relsize);
          nrelocs = bfd_canonicalize_reloc (b, s, relocs, symbols);
@@ -1557,13 +1596,13 @@ generate_reloc (bfd *abfd, struct bfd_link_info *info)
                  && relocs[i]->howto->type != pe_details->imagebase_reloc)
                {
                  struct bfd_symbol *sym = *relocs[i]->sym_ptr_ptr;
+                 const struct bfd_link_hash_entry *blhe
+                   = bfd_wrapped_link_hash_lookup (abfd, info, sym->name,
+                                                   false, false, false);
 
                  /* Don't create relocs for undefined weak symbols.  */
                  if (sym->flags == BSF_WEAK)
                    {
-                     struct bfd_link_hash_entry *blhe
-                       = bfd_wrapped_link_hash_lookup (abfd, info, sym->name,
-                                               FALSE, FALSE, FALSE);
                      if (blhe && blhe->type == bfd_link_hash_undefweak)
                        {
                          /* Check aux sym and see if it is defined or not. */
@@ -1572,7 +1611,7 @@ generate_reloc (bfd *abfd, struct bfd_link_info *info)
                          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];
+                                               [h->aux->x_sym.x_tagndx.u32];
                          /* 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
@@ -1595,30 +1634,46 @@ generate_reloc (bfd *abfd, struct bfd_link_info *info)
                      if (!strcmp (s->name, ".eh_frame"))
                        continue;
                    }
+                 /* Nor for absolute symbols.  */
+                 else if (blhe && ldexp_is_final_sym_absolute (blhe)
+                          && (!blhe->linker_def
+                              || (strcmp (sym->name, "__image_base__")
+                                  && strcmp (sym->name, U ("__ImageBase")))))
+                   continue;
 
                  reloc_data[total_relocs].vma = sec_vma + relocs[i]->address;
+                 reloc_data[total_relocs].idx = total_relocs;
+
+                 /* Since we're only about to determine .reloc's size,
+                    subsequent output section VMA calculations will shift up
+                    sections at this or higher addresses.  Relocations for
+                    such sections would hence end up not being correct.  */
+                 if (reloc_data[total_relocs].vma
+                     >= reloc_s->output_section->vma)
+                   einfo (_("%P: base relocation for section `%s' above "
+                            ".reloc section\n"), s->output_section->name);
 
 #define BITS_AND_SHIFT(bits, shift) (bits * 1000 | shift)
 
                  switch BITS_AND_SHIFT (relocs[i]->howto->bitsize,
                                         relocs[i]->howto->rightshift)
                    {
-#ifdef pe_use_x86_64
+#ifdef pe_use_plus
                    case BITS_AND_SHIFT (64, 0):
-                     reloc_data[total_relocs].type = 10;
+                     reloc_data[total_relocs].type = IMAGE_REL_BASED_DIR64;
                      total_relocs++;
                      break;
 #endif
                    case BITS_AND_SHIFT (32, 0):
-                     reloc_data[total_relocs].type = 3;
+                     reloc_data[total_relocs].type = IMAGE_REL_BASED_HIGHLOW;
                      total_relocs++;
                      break;
                    case BITS_AND_SHIFT (16, 0):
-                     reloc_data[total_relocs].type = 2;
+                     reloc_data[total_relocs].type = IMAGE_REL_BASED_LOW;
                      total_relocs++;
                      break;
                    case BITS_AND_SHIFT (16, 16):
-                     reloc_data[total_relocs].type = 4;
+                     reloc_data[total_relocs].type = IMAGE_REL_BASED_HIGHADJ;
                      /* FIXME: we can't know the symbol's right value
                         yet, but we probably can safely assume that
                         CE will relocate us in 64k blocks, so leaving
@@ -1627,7 +1682,8 @@ generate_reloc (bfd *abfd, struct bfd_link_info *info)
                      total_relocs++;
                      break;
                    case BITS_AND_SHIFT (26, 2):
-                     reloc_data[total_relocs].type = 5;
+                     reloc_data[total_relocs].type =
+                        IMAGE_REL_BASED_ARM_MOV32;
                      total_relocs++;
                      break;
                    case BITS_AND_SHIFT (24, 2):
@@ -1650,12 +1706,17 @@ generate_reloc (bfd *abfd, struct bfd_link_info *info)
                    }
                }
            }
+
          free (relocs);
          /* Warning: the allocated symbols are remembered in BFD and
             reused later, so don't free them!  */
        }
     }
 
+  /* This can happen for example when LTO has eliminated all code.  */
+  if (total_relocs == 0)
+    return;
+  
   /* At this point, we have total_relocs relocation addresses in
      reloc_addresses, which are all suitable for the .reloc section.
      We must now create the new sections.  */
@@ -1674,16 +1735,15 @@ generate_reloc (bfd *abfd, struct bfd_link_info *info)
 
       reloc_sz += 2;
 
-      if (reloc_data[i].type == 4)
+      if (reloc_data[i].type == IMAGE_REL_BASED_HIGHADJ)
        reloc_sz += 2;
     }
 
   reloc_sz = (reloc_sz + 3) & ~3;      /* 4-byte align.  */
   reloc_d = xmalloc (reloc_sz);
-  sec_page = (bfd_vma) -1;
+
+  page_ptr = sec_page = (bfd_vma) -1;
   reloc_sz = 0;
-  page_ptr = (bfd_vma) -1;
-  page_count = 0;
 
   for (i = 0; i < total_relocs; i++)
     {
@@ -1702,20 +1762,17 @@ generate_reloc (bfd *abfd, struct bfd_link_info *info)
          page_ptr = reloc_sz;
          reloc_sz += 8;
          sec_page = this_page;
-         page_count = 0;
        }
 
       bfd_put_16 (abfd, (rva & 0xfff) + (reloc_data[i].type << 12),
                  reloc_d + reloc_sz);
       reloc_sz += 2;
 
-      if (reloc_data[i].type == 4)
+      if (reloc_data[i].type == IMAGE_REL_BASED_HIGHADJ)
        {
          bfd_put_16 (abfd, reloc_data[i].extra, reloc_d + reloc_sz);
          reloc_sz += 2;
        }
-
-      page_count++;
     }
 
   while (reloc_sz & 3)
@@ -1723,9 +1780,6 @@ generate_reloc (bfd *abfd, struct bfd_link_info *info)
 
   if (page_ptr != (bfd_vma) -1)
     bfd_put_32 (abfd, reloc_sz - page_ptr, reloc_d + page_ptr + 4);
-
-  while (reloc_sz < reloc_s->size)
-    reloc_d[reloc_sz++] = 0;
 }
 
 /* Given the exiting def_file structure, print out a .DEF file that
@@ -1787,10 +1841,8 @@ pe_dll_generate_def_file (const char *pe_out_def_filename)
          quoteput (pe_def_file->name, out, 1);
 
          if (pe_data (link_info.output_bfd)->pe_opthdr.ImageBase)
-           {
-             fprintf (out, " BASE=0x");
-             fprintf_vma (out, ((bfd_vma) pe_data (link_info.output_bfd)->pe_opthdr.ImageBase));
-           }
+           fprintf (out, " BASE=0x%" PRIx64,
+                    (uint64_t) pe_data (link_info.output_bfd)->pe_opthdr.ImageBase);
          fprintf (out, "\n");
        }
 
@@ -1935,7 +1987,6 @@ pe_dll_generate_def_file (const char *pe_out_def_filename)
 static asymbol **symtab;
 static int symptr;
 static int tmp_seq;
-static const char *dll_filename;
 static char *dll_symname;
 
 #define UNDSEC bfd_und_section_ptr
@@ -1947,8 +1998,8 @@ quick_section (bfd *abfd, const char *name, int flags, int align)
   asymbol *sym;
 
   sec = bfd_make_section_old_way (abfd, name);
-  bfd_set_section_flags (abfd, sec, flags | SEC_ALLOC | SEC_LOAD | SEC_KEEP);
-  bfd_set_section_alignment (abfd, sec, align);
+  bfd_set_section_flags (sec, flags | SEC_ALLOC | SEC_LOAD | SEC_KEEP);
+  bfd_set_section_alignment (sec, align);
   /* Remember to undo this before trying to link internally!  */
   sec->output_section = sec;
 
@@ -2047,11 +2098,16 @@ make_head (bfd *parent)
   char *oname;
   bfd *abfd;
 
-  oname = xmalloc (20);
-  sprintf (oname, "d%06d.o", tmp_seq);
+  if (asprintf (&oname, "%s_d%06d.o", dll_symname, tmp_seq) < 4)
+    /* In theory we should return NULL here at let our caller decide what to
+       do.  But currently the return value is not checked, just used, and
+       besides, this condition only happens when the system has run out of
+       memory.  So just give up.  */
+    exit (EXIT_FAILURE);
   tmp_seq++;
 
   abfd = bfd_create (oname, parent);
+  free (oname);
   bfd_find_target (pe_details->object_target, abfd);
   bfd_make_writable (abfd);
 
@@ -2072,7 +2128,7 @@ make_head (bfd *parent)
      pointer to the list points to the *end* of this section, which is
      the start of the list of sections from other objects.  */
 
-  bfd_set_section_size (abfd, id2, 20);
+  bfd_set_section_size (id2, 20);
   d2 = xmalloc (20);
   id2->contents = d2;
   memset (d2, 0, 20);
@@ -2084,16 +2140,16 @@ make_head (bfd *parent)
   save_relocs (id2);
 
   if (pe_use_nul_prefixed_import_tables)
-    bfd_set_section_size (abfd, id5, PE_IDATA5_SIZE);
+    bfd_set_section_size (id5, PE_IDATA5_SIZE);
   else
-    bfd_set_section_size (abfd, id5, 0);
+    bfd_set_section_size (id5, 0);
   d5 = xmalloc (PE_IDATA5_SIZE);
   id5->contents = d5;
   memset (d5, 0, PE_IDATA5_SIZE);
   if (pe_use_nul_prefixed_import_tables)
-    bfd_set_section_size (abfd, id4, PE_IDATA4_SIZE);
+    bfd_set_section_size (id4, PE_IDATA4_SIZE);
   else
-    bfd_set_section_size (abfd, id4, 0);
+    bfd_set_section_size (id4, 0);
   d4 = xmalloc (PE_IDATA4_SIZE);
   id4->contents = d4;
   memset (d4, 0, PE_IDATA4_SIZE);
@@ -2136,11 +2192,16 @@ make_tail (bfd *parent)
   char *oname;
   bfd *abfd;
 
-  oname = xmalloc (20);
-  sprintf (oname, "d%06d.o", tmp_seq);
+  if (asprintf (&oname, "%s_d%06d.o", dll_symname, tmp_seq) < 4)
+    /* In theory we should return NULL here at let our caller decide what to
+       do.  But currently the return value is not checked, just used, and
+       besides, this condition only happens when the system has run out of
+       memory.  So just give up.  */
+    exit (EXIT_FAILURE);
   tmp_seq++;
 
   abfd = bfd_create (oname, parent);
+  free (oname);
   bfd_find_target (pe_details->object_target, abfd);
   bfd_make_writable (abfd);
 
@@ -2154,12 +2215,12 @@ make_tail (bfd *parent)
   id7 = quick_section (abfd, ".idata$7", SEC_HAS_CONTENTS, 2);
   quick_symbol (abfd, U (""), dll_symname, "_iname", id7, BSF_GLOBAL, 0);
 
-  bfd_set_section_size (abfd, id4, PE_IDATA4_SIZE);
+  bfd_set_section_size (id4, PE_IDATA4_SIZE);
   d4 = xmalloc (PE_IDATA4_SIZE);
   id4->contents = d4;
   memset (d4, 0, PE_IDATA4_SIZE);
 
-  bfd_set_section_size (abfd, id5, PE_IDATA5_SIZE);
+  bfd_set_section_size (id5, PE_IDATA5_SIZE);
   d5 = xmalloc (PE_IDATA5_SIZE);
   id5->contents = d5;
   memset (d5, 0, PE_IDATA5_SIZE);
@@ -2167,7 +2228,7 @@ make_tail (bfd *parent)
   len = strlen (dll_filename) + 1;
   if (len & 1)
     len++;
-  bfd_set_section_size (abfd, id7, len);
+  bfd_set_section_size (id7, len);
   d7 = xmalloc (len);
   id7->contents = d7;
   strcpy ((char *) d7, dll_filename);
@@ -2212,6 +2273,14 @@ static const unsigned char jmp_ix86_bytes[] =
   0xff, 0x25, 0x00, 0x00, 0x00, 0x00, 0x90, 0x90
 };
 
+static const unsigned char jmp_aarch64_bytes[] =
+{
+  0x10, 0x00, 0x00, 0x90, /* adrp x16, 0        */
+  0x10, 0x02, 0x00, 0x91, /* add x16, x16, #0x0 */
+  0x10, 0x02, 0x40, 0xf9, /* ldr x16, [x16]     */
+  0x00, 0x02, 0x1f, 0xd6  /* br x16             */
+};
+
 /* _function:
        mov.l   ip+8,r0
        mov.l   @r0,r0
@@ -2245,7 +2314,7 @@ static const unsigned char jmp_arm_bytes[] =
 
 
 static bfd *
-make_one (def_file_export *exp, bfd *parent, bfd_boolean include_jmp_stub)
+make_one (def_file_export *exp, bfd *parent, bool include_jmp_stub)
 {
   asection *tx, *id7, *id5, *id4, *id6;
   unsigned char *td = NULL, *d7, *d5, *d4, *d6 = NULL;
@@ -2254,6 +2323,31 @@ make_one (def_file_export *exp, bfd *parent, bfd_boolean include_jmp_stub)
   bfd *abfd;
   const unsigned char *jmp_bytes = NULL;
   int jmp_byte_count = 0;
+  const char *internal_name = exp->internal_name;
+
+  if (!exp->flag_noname)
+    {
+      /* Check for a decorated symbol name */
+      struct decoration_hash_entry *entry;
+
+      entry = (struct decoration_hash_entry *)
+             bfd_hash_lookup (&(coff_hash_table (&link_info)->decoration_hash),
+                              internal_name, false, false);
+      if (entry)
+       {
+         if (entry->decorated_link)
+           {
+             internal_name = entry->decorated_link->root.string;
+
+             if (pe_details->underscored && internal_name[0] == '_')
+               internal_name++;
+           }
+         else
+           {
+             einfo (_("%P: error: NULL decorated name for %s\n"), internal_name);
+           }
+       }
+    }
 
   /* Include the jump stub section only if it is needed. A jump
      stub is needed if the symbol being imported <sym> is a function
@@ -2282,16 +2376,25 @@ make_one (def_file_export *exp, bfd *parent, bfd_boolean include_jmp_stub)
          jmp_bytes = jmp_arm_bytes;
          jmp_byte_count = sizeof (jmp_arm_bytes);
          break;
+       case PE_ARCH_aarch64:
+         jmp_bytes = jmp_aarch64_bytes;
+         jmp_byte_count = sizeof (jmp_aarch64_bytes);
+         break;
        default:
          abort ();
        }
     }
 
-  oname = xmalloc (20);
-  sprintf (oname, "d%06d.o", tmp_seq);
+  if (asprintf (&oname, "%s_d%06d.o", dll_symname, tmp_seq) < 4)
+    /* In theory we should return NULL here at let our caller decide what to
+       do.  But currently the return value is not checked, just used, and
+       besides, this condition only happens when the system has run out of
+       memory.  So just give up.  */
+    exit (EXIT_FAILURE);
   tmp_seq++;
 
   abfd = bfd_create (oname, parent);
+  free (oname);
   bfd_find_target (pe_details->object_target, abfd);
   bfd_make_writable (abfd);
 
@@ -2307,13 +2410,13 @@ make_one (def_file_export *exp, bfd *parent, bfd_boolean include_jmp_stub)
   id4 = quick_section (abfd, ".idata$4", SEC_HAS_CONTENTS, 2);
   id6 = quick_section (abfd, ".idata$6", SEC_HAS_CONTENTS, 2);
 
-  if  (*exp->internal_name == '@')
+  if  (*internal_name == '@')
     {
       quick_symbol (abfd, U ("_head_"), dll_symname, "", UNDSEC,
                    BSF_GLOBAL, 0);
       if (include_jmp_stub)
-       quick_symbol (abfd, "", exp->internal_name, "", tx, BSF_GLOBAL, 0);
-      quick_symbol (abfd, "__imp_", exp->internal_name, "", id5,
+       quick_symbol (abfd, "", internal_name, "", tx, BSF_GLOBAL, 0);
+      quick_symbol (abfd, "__imp_", internal_name, "", id5,
                    BSF_GLOBAL, 0);
       /* Fastcall applies only to functions,
         so no need for auto-import symbol.  */
@@ -2323,23 +2426,23 @@ make_one (def_file_export *exp, bfd *parent, bfd_boolean include_jmp_stub)
       quick_symbol (abfd, U ("_head_"), dll_symname, "", UNDSEC,
                    BSF_GLOBAL, 0);
       if (include_jmp_stub)
-       quick_symbol (abfd, U (""), exp->internal_name, "", tx,
+       quick_symbol (abfd, U (""), internal_name, "", tx,
                      BSF_GLOBAL, 0);
-      quick_symbol (abfd, "__imp_", U (""), exp->internal_name, id5,
+      quick_symbol (abfd, "__imp_", U (""), internal_name, id5,
                    BSF_GLOBAL, 0);
       /* Symbol to reference ord/name of imported
         data symbol, used to implement auto-import.  */
       if (exp->flag_data)
-       quick_symbol (abfd, "__nm_", U (""), exp->internal_name, id6,
+       quick_symbol (abfd, "__nm_", U (""), internal_name, id6,
                      BSF_GLOBAL,0);
     }
   if (pe_dll_compat_implib)
-    quick_symbol (abfd, "___imp_", exp->internal_name, "", id5,
+    quick_symbol (abfd, "___imp_", internal_name, "", id5,
                  BSF_GLOBAL, 0);
 
   if (include_jmp_stub)
     {
-      bfd_set_section_size (abfd, tx, jmp_byte_count);
+      bfd_set_section_size (tx, jmp_byte_count);
       td = xmalloc (jmp_byte_count);
       tx->contents = td;
       memcpy (td, jmp_bytes, jmp_byte_count);
@@ -2347,7 +2450,7 @@ make_one (def_file_export *exp, bfd *parent, bfd_boolean include_jmp_stub)
       switch (pe_details->pe_arch)
        {
        case PE_ARCH_i386:
-#ifdef pe_use_x86_64
+#ifdef pe_use_plus
          quick_reloc (abfd, 2, BFD_RELOC_32_PCREL, 2);
 #else
          /* Mark this object as SAFESEH compatible.  */
@@ -2368,22 +2471,26 @@ make_one (def_file_export *exp, bfd *parent, bfd_boolean include_jmp_stub)
        case PE_ARCH_arm_wince:
          quick_reloc (abfd, 8, BFD_RELOC_32, 2);
          break;
+       case PE_ARCH_aarch64:
+         quick_reloc (abfd, 0, BFD_RELOC_AARCH64_ADR_HI21_NC_PCREL, 2);
+         quick_reloc (abfd, 4, BFD_RELOC_AARCH64_ADD_LO12, 2);
+         break;
        default:
          abort ();
        }
       save_relocs (tx);
     }
   else
-    bfd_set_section_size (abfd, tx, 0);
+    bfd_set_section_size (tx, 0);
 
-  bfd_set_section_size (abfd, id7, 4);
+  bfd_set_section_size (id7, 4);
   d7 = xmalloc (4);
   id7->contents = d7;
   memset (d7, 0, 4);
   quick_reloc (abfd, 0, BFD_RELOC_RVA, 5);
   save_relocs (id7);
 
-  bfd_set_section_size (abfd, id5, PE_IDATA5_SIZE);
+  bfd_set_section_size (id5, PE_IDATA5_SIZE);
   d5 = xmalloc (PE_IDATA5_SIZE);
   id5->contents = d5;
   memset (d5, 0, PE_IDATA5_SIZE);
@@ -2400,7 +2507,7 @@ make_one (def_file_export *exp, bfd *parent, bfd_boolean include_jmp_stub)
       save_relocs (id5);
     }
 
-  bfd_set_section_size (abfd, id4, PE_IDATA4_SIZE);
+  bfd_set_section_size (id4, PE_IDATA4_SIZE);
   d4 = xmalloc (PE_IDATA4_SIZE);
   id4->contents = d4;
   memset (d4, 0, PE_IDATA4_SIZE);
@@ -2420,7 +2527,7 @@ make_one (def_file_export *exp, bfd *parent, bfd_boolean include_jmp_stub)
   if (exp->flag_noname)
     {
       len = 0;
-      bfd_set_section_size (abfd, id6, 0);
+      bfd_set_section_size (id6, 0);
     }
   else
     {
@@ -2433,7 +2540,7 @@ make_one (def_file_export *exp, bfd *parent, bfd_boolean include_jmp_stub)
        len = 2 + strlen (exp->name) + 1;
       if (len & 1)
        len++;
-      bfd_set_section_size (abfd, id6, len);
+      bfd_set_section_size (id6, len);
       d6 = xmalloc (len);
       id6->contents = d6;
       memset (d6, 0, len);
@@ -2473,11 +2580,16 @@ make_singleton_name_thunk (const char *import, bfd *parent)
   char *oname;
   bfd *abfd;
 
-  oname = xmalloc (20);
-  sprintf (oname, "nmth%06d.o", tmp_seq);
+  if (asprintf (&oname, "%s_nmth%06d.o", dll_symname, tmp_seq) < 4)
+    /* In theory we should return NULL here at let our caller decide what to
+       do.  But currently the return value is not checked, just used, and
+       besides, this condition only happens when the system has run out of
+       memory.  So just give up.  */
+    exit (EXIT_FAILURE);
   tmp_seq++;
 
   abfd = bfd_create (oname, parent);
+  free (oname);
   bfd_find_target (pe_details->object_target, abfd);
   bfd_make_writable (abfd);
 
@@ -2491,7 +2603,7 @@ make_singleton_name_thunk (const char *import, bfd *parent)
   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);
+  bfd_set_section_size (id4, PE_IDATA4_SIZE * 2);
   d4 = xmalloc (PE_IDATA4_SIZE * 2);
   id4->contents = d4;
   memset (d4, 0, PE_IDATA4_SIZE * 2);
@@ -2514,7 +2626,7 @@ make_import_fixup_mark (arelent *rel, char *name)
   struct bfd_symbol *sym = *rel->sym_ptr_ptr;
   bfd *abfd = bfd_asymbol_bfd (sym);
   struct bfd_link_hash_entry *bh;
-  char *fixup_name, buf[26];
+  char *fixup_name, buf[256];
   size_t prefix_len;
 
   /* "name" buffer has space before the symbol name for prefixes.  */
@@ -2526,7 +2638,7 @@ make_import_fixup_mark (arelent *rel, char *name)
   bh = NULL;
   bfd_coff_link_add_one_symbol (&link_info, abfd, fixup_name, BSF_GLOBAL,
                                current_sec, /* sym->section, */
-                               rel->address, NULL, TRUE, FALSE, &bh);
+                               rel->address, NULL, true, false, &bh);
 
   return bh->root.string;
 }
@@ -2549,11 +2661,16 @@ make_import_fixup_entry (const char *name,
   char *oname;
   bfd *abfd;
 
-  oname = xmalloc (20);
-  sprintf (oname, "fu%06d.o", tmp_seq);
+  if (asprintf (&oname, "%s_fu%06d.o", dll_symname, tmp_seq) < 4)
+    /* In theory we should return NULL here at let our caller decide what to
+       do.  But currently the return value is not checked, just used, and
+       besides, this condition only happens when the system has run out of
+       memory.  So just give up.  */
+    exit (EXIT_FAILURE);
   tmp_seq++;
 
   abfd = bfd_create (oname, parent);
+  free (oname);
   bfd_find_target (pe_details->object_target, abfd);
   bfd_make_writable (abfd);
 
@@ -2568,7 +2685,7 @@ make_import_fixup_entry (const char *name,
   quick_symbol (abfd, U (""), symname, "_iname", UNDSEC, BSF_GLOBAL, 0);
   quick_symbol (abfd, "", fixup_name, "", UNDSEC, BSF_GLOBAL, 0);
 
-  bfd_set_section_size (abfd, id2, 20);
+  bfd_set_section_size (id2, 20);
   d2 = xmalloc (20);
   id2->contents = d2;
   memset (d2, 0, 20);
@@ -2603,11 +2720,16 @@ make_runtime_pseudo_reloc (const char *name ATTRIBUTE_UNUSED,
   bfd *abfd;
   bfd_size_type size;
 
-  oname = xmalloc (20);
-  sprintf (oname, "rtr%06d.o", tmp_seq);
+  if (asprintf (&oname, "%s_rtr%06d.o", dll_symname, tmp_seq) < 4)
+    /* In theory we should return NULL here at let our caller decide what to
+       do.  But currently the return value is not checked, just used, and
+       besides, this condition only happens when the system has run out of
+       memory.  So just give up.  */
+    exit (EXIT_FAILURE);
   tmp_seq++;
 
   abfd = bfd_create (oname, parent);
+  free (oname);
   bfd_find_target (pe_details->object_target, abfd);
   bfd_make_writable (abfd);
 
@@ -2629,6 +2751,7 @@ make_runtime_pseudo_reloc (const char *name ATTRIBUTE_UNUSED,
 
   rt_rel
     = quick_section (abfd, ".rdata_runtime_pseudo_reloc", SEC_HAS_CONTENTS, 2);
+  bfd_coff_set_long_section_names (abfd, true);
 
   quick_symbol (abfd, "", fixup_name, "", UNDSEC, BSF_GLOBAL, 0);
 
@@ -2638,12 +2761,12 @@ make_runtime_pseudo_reloc (const char *name ATTRIBUTE_UNUSED,
       if (!runtime_pseudp_reloc_v2_init)
        {
          size += 12;
-         runtime_pseudp_reloc_v2_init = TRUE;
+         runtime_pseudp_reloc_v2_init = true;
        }
 
       quick_symbol (abfd, "__imp_", name, "", UNDSEC, BSF_GLOBAL, 0);
 
-      bfd_set_section_size (abfd, rt_rel, size);
+      bfd_set_section_size (rt_rel, size);
       rt_rel_d = xmalloc (size);
       rt_rel->contents = rt_rel_d;
       memset (rt_rel_d, 0, size);
@@ -2660,7 +2783,7 @@ make_runtime_pseudo_reloc (const char *name ATTRIBUTE_UNUSED,
     }
   else
     {
-      bfd_set_section_size (abfd, rt_rel, 8);
+      bfd_set_section_size (rt_rel, 8);
       rt_rel_d = xmalloc (8);
       rt_rel->contents = rt_rel_d;
       memset (rt_rel_d, 0, 8);
@@ -2690,11 +2813,16 @@ pe_create_runtime_relocator_reference (bfd *parent)
   char *oname;
   bfd *abfd;
 
-  oname = xmalloc (20);
-  sprintf (oname, "ertr%06d.o", tmp_seq);
+  if (asprintf (&oname, "%s_ertr%06d.o", dll_symname, tmp_seq) < 4)
+    /* In theory we should return NULL here at let our caller decide what to
+       do.  But currently the return value is not checked, just used, and
+       besides, this condition only happens when the system has run out of
+       memory.  So just give up.  */
+    exit (EXIT_FAILURE);
   tmp_seq++;
 
   abfd = bfd_create (oname, parent);
+  free (oname);
   bfd_find_target (pe_details->object_target, abfd);
   bfd_make_writable (abfd);
 
@@ -2708,7 +2836,7 @@ pe_create_runtime_relocator_reference (bfd *parent)
   quick_symbol (abfd, "", U ("_pei386_runtime_relocator"), "", UNDSEC,
                BSF_NO_FLAGS, 0);
 
-  bfd_set_section_size (abfd, extern_rt_rel, PE_IDATA5_SIZE);
+  bfd_set_section_size (extern_rt_rel, PE_IDATA5_SIZE);
   extern_rt_rel_d = xcalloc (1, PE_IDATA5_SIZE);
   extern_rt_rel->contents = extern_rt_rel_d;
 
@@ -2745,10 +2873,10 @@ pe_create_import_fixup (arelent *rel, asection *s, bfd_vma addend, char *name,
       if (!(name_thunk_sym && name_thunk_sym->type == bfd_link_hash_defined))
        {
          b = make_singleton_name_thunk (name, link_info.output_bfd);
-         add_bfd_to_link (b, b->filename, &link_info);
+         add_bfd_to_link (b, bfd_get_filename (b), &link_info);
 
          /* If we ever use autoimport, we have to cast text section writable.  */
-         config.text_read_only = FALSE;
+         config.text_read_only = false;
          link_info.output_bfd->flags &= ~WP_TEXT;
        }
 
@@ -2756,7 +2884,7 @@ pe_create_import_fixup (arelent *rel, asection *s, bfd_vma addend, char *name,
        {
          b = make_import_fixup_entry (name, fixup_name, symname,
                                       link_info.output_bfd);
-         add_bfd_to_link (b, b->filename, &link_info);
+         add_bfd_to_link (b, bfd_get_filename (b), &link_info);
        }
     }
 
@@ -2770,19 +2898,20 @@ pe_create_import_fixup (arelent *rel, asection *s, bfd_vma addend, char *name,
        printf ("creating runtime pseudo-reloc entry for %s (addend=%d)\n",
                fixup_name, (int) addend);
 
-      b = make_runtime_pseudo_reloc (name, fixup_name, addend, rel->howto->bitsize,
+      b = make_runtime_pseudo_reloc (name, fixup_name, addend,
+                                    rel->howto->bitsize,
                                     link_info.output_bfd);
-      add_bfd_to_link (b, b->filename, &link_info);
+      add_bfd_to_link (b, bfd_get_filename (b), &link_info);
 
       if (runtime_pseudo_relocs_created++ == 0)
        {
          b = pe_create_runtime_relocator_reference (link_info.output_bfd);
-         add_bfd_to_link (b, b->filename, &link_info);
+         add_bfd_to_link (b, bfd_get_filename (b), &link_info);
        }
     }
 
   else if (addend != 0)
-    einfo (_("%X%P: %C: variable '%pT' can't be auto-imported; please read the documentation for ld's --enable-auto-import for details\n"),
+    einfo (_("%X%P: %H: variable '%pT' can't be auto-imported; please read the documentation for ld's --enable-auto-import for details\n"),
           s->owner, s, rel->address, (*rel->sym_ptr_ptr)->name);
 }
 
@@ -2796,12 +2925,6 @@ pe_dll_generate_implib (def_file *def, const char *impfilename, struct bfd_link_
   bfd *ibfd;
   bfd *head = 0;
 
-  dll_filename = (def->name) ? def->name : dll_name;
-  dll_symname = xstrdup (dll_filename);
-  for (i = 0; dll_symname[i]; i++)
-    if (!ISALNUM (dll_symname[i]))
-      dll_symname[i] = '_';
-
   unlink_if_ordinary (impfilename);
 
   outarch = bfd_openw (impfilename, 0);
@@ -2833,7 +2956,7 @@ pe_dll_generate_implib (def_file *def, const char *impfilename, struct bfd_link_
        {
          if (ex->type != EXCLUDEFORIMPLIB)
            continue;
-         found = (filename_cmp (ex->string, ibfd->filename) == 0);
+         found = (filename_cmp (ex->string, bfd_get_filename (ibfd)) == 0);
        }
       /* If it matched, we must open a fresh BFD for it (the original
         input BFD is still needed for the DLL's final link) and add
@@ -2841,10 +2964,11 @@ pe_dll_generate_implib (def_file *def, const char *impfilename, struct bfd_link_
       if (found)
        {
          bfd *newbfd = bfd_openr (ibfd->my_archive
-               ? ibfd->my_archive->filename : ibfd->filename, NULL);
+                                  ? bfd_get_filename (ibfd->my_archive)
+                                  : bfd_get_filename (ibfd), NULL);
          if (!newbfd)
            {
-             einfo (_("%X%P: bfd_openr %s: %E\n"), ibfd->filename);
+             einfo (_("%X%P: bfd_openr %s: %E\n"), bfd_get_filename (ibfd));
              return;
            }
          if (ibfd->my_archive)
@@ -2857,19 +2981,22 @@ pe_dll_generate_implib (def_file *def, const char *impfilename, struct bfd_link_
              if (!bfd_check_format_matches (arbfd, bfd_archive, NULL))
                {
                  einfo (_("%X%P: %s(%s): can't find member in non-archive file"),
-                   ibfd->my_archive->filename, ibfd->filename);
+                        bfd_get_filename (ibfd->my_archive),
+                        bfd_get_filename (ibfd));
                  return;
                }
              newbfd = NULL;
              while ((newbfd = bfd_openr_next_archived_file (arbfd, newbfd)) != 0)
                {
-                 if (filename_cmp (newbfd->filename, ibfd->filename) == 0)
+                 if (filename_cmp (bfd_get_filename (newbfd),
+                                   bfd_get_filename (ibfd)) == 0)
                    break;
                }
              if (!newbfd)
                {
                  einfo (_("%X%P: %s(%s): can't find member in archive"),
-                   ibfd->my_archive->filename, ibfd->filename);
+                        bfd_get_filename (ibfd->my_archive),
+                        bfd_get_filename (ibfd));
                  return;
                }
            }
@@ -2896,7 +3023,7 @@ pe_dll_generate_implib (def_file *def, const char *impfilename, struct bfd_link_
        struct coff_link_hash_entry *h;
 
        h = coff_link_hash_lookup (coff_hash_table (info), internal,
-                                  FALSE, FALSE, FALSE);
+                                  false, false, false);
        if (h != NULL
            /* If the symbol is hidden and undefined then it
               has been swept up by garbage collection.  */
@@ -2913,7 +3040,7 @@ pe_dll_generate_implib (def_file *def, const char *impfilename, struct bfd_link_
            sprintf (name, "_%s", internal);
 
            h = coff_link_hash_lookup (coff_hash_table (info), name,
-                                      FALSE, FALSE, FALSE);
+                                      false, false, false);
            free (name);
 
            if (h != NULL
@@ -2925,8 +3052,7 @@ pe_dll_generate_implib (def_file *def, const char *impfilename, struct bfd_link_
          }
       }
 
-      n = make_one (def->exports + i, outarch,
-                   ! (def->exports + i)->flag_data);
+      n = make_one (def->exports + i, outarch, !(def->exports + i)->flag_data);
       n->archive_next = head;
       head = n;
       def->exports[i].internal_name = internal;
@@ -2994,7 +3120,7 @@ pe_find_cdecl_alias_match (struct bfd_link_info *linfo, char *name)
 
   if (kv)
     {
-      h = bfd_link_hash_lookup (linfo->hash, kv->oname, FALSE, FALSE, FALSE);
+      h = bfd_link_hash_lookup (linfo->hash, kv->oname, false, false, false);
       if (h->type == bfd_link_hash_undefined)
        goto return_h;
     }
@@ -3009,13 +3135,15 @@ pe_find_cdecl_alias_match (struct bfd_link_info *linfo, char *name)
          if (pe_details->underscored)
            lname[0] = '_';
          else
-           strcpy (lname, lname + 1);
+           /* Use memmove rather than strcpy as that
+              can handle overlapping buffers.  */
+           memmove (lname, lname + 1, strlen (lname));
          key.key = lname;
          kv = bsearch (&key, udef_table, undef_count,
                        sizeof (struct key_value), undef_sort_cmp);
          if (kv)
            {
-             h = bfd_link_hash_lookup (linfo->hash, kv->oname, FALSE, FALSE, FALSE);
+             h = bfd_link_hash_lookup (linfo->hash, kv->oname, false, false, false);
              if (h->type == bfd_link_hash_undefined)
                goto return_h;
            }
@@ -3027,7 +3155,7 @@ pe_find_cdecl_alias_match (struct bfd_link_info *linfo, char *name)
                    sizeof (struct key_value), undef_sort_cmp);
       if (kv)
        {
-         h = bfd_link_hash_lookup (linfo->hash, kv->oname, FALSE, FALSE, FALSE);
+         h = bfd_link_hash_lookup (linfo->hash, kv->oname, false, false, false);
          if (h->type == bfd_link_hash_undefined)
            goto return_h;
        }
@@ -3041,7 +3169,7 @@ pe_find_cdecl_alias_match (struct bfd_link_info *linfo, char *name)
 
   if (kv)
     {
-      h = bfd_link_hash_lookup (linfo->hash, kv->oname, FALSE, FALSE, FALSE);
+      h = bfd_link_hash_lookup (linfo->hash, kv->oname, false, false, false);
       if (h->type == bfd_link_hash_undefined)
        goto return_h;
     }
@@ -3060,7 +3188,7 @@ pe_find_cdecl_alias_match (struct bfd_link_info *linfo, char *name)
 
   if (kv)
     {
-      h = bfd_link_hash_lookup (linfo->hash, kv->oname, FALSE, FALSE, FALSE);
+      h = bfd_link_hash_lookup (linfo->hash, kv->oname, false, false, false);
       if (h->type == bfd_link_hash_undefined)
        goto return_h;
     }
@@ -3072,16 +3200,16 @@ pe_find_cdecl_alias_match (struct bfd_link_info *linfo, char *name)
   return h;
 }
 
-static bfd_boolean
+static bool
 pe_undef_count (struct bfd_link_hash_entry *h ATTRIBUTE_UNUSED,
                void *inf ATTRIBUTE_UNUSED)
 {
   if (h->type == bfd_link_hash_undefined)
     undef_count++;
-  return TRUE;
+  return true;
 }
 
-static bfd_boolean
+static bool
 pe_undef_fill (struct bfd_link_hash_entry *h, void *inf ATTRIBUTE_UNUSED)
 {
   if (h->type == bfd_link_hash_undefined)
@@ -3096,7 +3224,7 @@ pe_undef_fill (struct bfd_link_hash_entry *h, void *inf ATTRIBUTE_UNUSED)
       udef_table[undef_count].oname = h->root.string;
       undef_count++;
     }
-  return TRUE;
+  return true;
 }
 
 static void
@@ -3136,127 +3264,145 @@ add_bfd_to_link (bfd *abfd, const char *name, struct bfd_link_info *linfo)
 void
 pe_process_import_defs (bfd *output_bfd, struct bfd_link_info *linfo)
 {
-  int i, j;
-  def_file_module *module;
-  def_file_import *imp;
-
   pe_dll_id_target (bfd_get_target (output_bfd));
 
-  if (!pe_def_file)
-    return;
-
-  imp = pe_def_file->imports;
-
-  pe_create_undef_table ();
-
-  for (module = pe_def_file->modules; module; module = module->next)
+  if (pe_def_file)
     {
-      int do_this_dll = 0;
+      int i, j;
+      def_file_module *module;
+      def_file_import *imp;
 
-      for (i = 0; i < pe_def_file->num_imports && imp[i].module != module; i++)
-       ;
-      if (i >= pe_def_file->num_imports)
-       continue;
+      imp = pe_def_file->imports;
 
-      dll_filename = module->name;
-      dll_symname = xstrdup (module->name);
-      for (j = 0; dll_symname[j]; j++)
-       if (!ISALNUM (dll_symname[j]))
-         dll_symname[j] = '_';
+      pe_create_undef_table ();
 
-      for (; i < pe_def_file->num_imports && imp[i].module == module; i++)
+      for (module = pe_def_file->modules; module; module = module->next)
        {
-         def_file_export exp;
-         struct bfd_link_hash_entry *blhe;
-         int lead_at = (*imp[i].internal_name == '@');
-         /* See if we need this import.  */
-         size_t len = strlen (imp[i].internal_name);
-         char *name = xmalloc (len + 2 + 6);
-         bfd_boolean include_jmp_stub = FALSE;
-         bfd_boolean is_cdecl = FALSE;
-         bfd_boolean is_undef = FALSE;
-
-         if (!lead_at && strchr (imp[i].internal_name, '@') == NULL)
-             is_cdecl = TRUE;
-
-         if (lead_at)
-           sprintf (name, "%s", imp[i].internal_name);
-         else
-           sprintf (name, "%s%s",U (""), imp[i].internal_name);
+         int do_this_dll = 0;
+
+         for (i = 0; i < pe_def_file->num_imports; i++)
+           if (imp[i].module == module)
+             break;
+         if (i >= pe_def_file->num_imports)
+           continue;
 
-         blhe = bfd_link_hash_lookup (linfo->hash, name,
-                                      FALSE, FALSE, FALSE);
+         dll_filename = module->name;
+         dll_symname = xstrdup (module->name);
+         for (j = 0; dll_symname[j]; j++)
+           if (!ISALNUM (dll_symname[j]))
+             dll_symname[j] = '_';
 
-         /* Include the jump stub for <sym> only if the <sym>
-            is undefined.  */
-         if (!blhe || (blhe && blhe->type != bfd_link_hash_undefined))
+         for (; i < pe_def_file->num_imports && imp[i].module == module; i++)
            {
+             def_file_export exp;
+             struct bfd_link_hash_entry *blhe;
+             int lead_at = (*imp[i].internal_name == '@');
+             /* See if we need this import.  */
+             size_t len = strlen (imp[i].internal_name);
+             char *name = xmalloc (len + 2 + 6);
+             bool include_jmp_stub = false;
+             bool is_cdecl = false;
+             bool is_undef = false;
+
+             if (!lead_at && strchr (imp[i].internal_name, '@') == NULL)
+               is_cdecl = true;
+
              if (lead_at)
-               sprintf (name, "%s%s", "__imp_", imp[i].internal_name);
+               sprintf (name, "%s", imp[i].internal_name);
              else
-               sprintf (name, "%s%s%s", "__imp_", U (""),
-                        imp[i].internal_name);
+               sprintf (name, "%s%s",U (""), imp[i].internal_name);
 
              blhe = bfd_link_hash_lookup (linfo->hash, name,
-                                          FALSE, FALSE, FALSE);
-             if (blhe)
-               is_undef = (blhe->type == bfd_link_hash_undefined);
-           }
-         else
-           {
-             include_jmp_stub = TRUE;
-             is_undef = (blhe->type == bfd_link_hash_undefined);
-           }
+                                          false, false, false);
 
-         if (is_cdecl && (!blhe || (blhe && blhe->type != bfd_link_hash_undefined)))
-           {
-             sprintf (name, "%s%s",U (""), imp[i].internal_name);
-             blhe = pe_find_cdecl_alias_match (linfo, name);
-             include_jmp_stub = TRUE;
-             if (blhe)
-               is_undef = (blhe->type == bfd_link_hash_undefined);
-           }
+             /* Include the jump stub for <sym> only if the <sym>
+                is undefined.  */
+             if (!blhe || (blhe && blhe->type != bfd_link_hash_undefined))
+               {
+                 if (lead_at)
+                   sprintf (name, "%s%s", "__imp_", imp[i].internal_name);
+                 else
+                   sprintf (name, "%s%s%s", "__imp_", U (""),
+                            imp[i].internal_name);
+
+                 blhe = bfd_link_hash_lookup (linfo->hash, name,
+                                              false, false, false);
+                 if (blhe)
+                   is_undef = (blhe->type == bfd_link_hash_undefined);
+               }
+             else
+               {
+                 include_jmp_stub = true;
+                 is_undef = (blhe->type == bfd_link_hash_undefined);
+               }
+
+             if (is_cdecl
+                 && (!blhe || (blhe && blhe->type != bfd_link_hash_undefined)))
+               {
+                 sprintf (name, "%s%s",U (""), imp[i].internal_name);
+                 blhe = pe_find_cdecl_alias_match (linfo, name);
+                 include_jmp_stub = true;
+                 if (blhe)
+                   is_undef = (blhe->type == bfd_link_hash_undefined);
+               }
 
-         free (name);
+             free (name);
 
-         if (is_undef)
-           {
-             bfd *one;
-             /* We do.  */
-             if (!do_this_dll)
+             if (is_undef)
                {
-                 bfd *ar_head = make_head (output_bfd);
-                 add_bfd_to_link (ar_head, ar_head->filename, linfo);
-                 do_this_dll = 1;
+                 bfd *one;
+                 /* We do.  */
+                 if (!do_this_dll)
+                   {
+                     bfd *ar_head = make_head (output_bfd);
+                     add_bfd_to_link (ar_head, bfd_get_filename (ar_head),
+                                      linfo);
+                     do_this_dll = 1;
+                   }
+                 exp.internal_name = imp[i].internal_name;
+                 exp.name = imp[i].name;
+                 exp.its_name = imp[i].its_name;
+                 exp.ordinal = imp[i].ordinal;
+                 exp.hint = exp.ordinal >= 0 ? exp.ordinal : 0;
+                 exp.flag_private = 0;
+                 exp.flag_constant = 0;
+                 exp.flag_data = imp[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, bfd_get_filename (one), linfo);
                }
-             exp.internal_name = imp[i].internal_name;
-             exp.name = imp[i].name;
-             exp.its_name = imp[i].its_name;
-             exp.ordinal = imp[i].ordinal;
-             exp.hint = exp.ordinal >= 0 ? exp.ordinal : 0;
-             exp.flag_private = 0;
-             exp.flag_constant = 0;
-             exp.flag_data = imp[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, linfo);
            }
+         if (do_this_dll)
+           {
+             bfd *ar_tail = make_tail (output_bfd);
+             add_bfd_to_link (ar_tail, bfd_get_filename (ar_tail), linfo);
+           }
+
+         free (dll_symname);
        }
-      if (do_this_dll)
+
+      while (undef_count)
        {
-         bfd *ar_tail = make_tail (output_bfd);
-         add_bfd_to_link (ar_tail, ar_tail->filename, linfo);
+         --undef_count;
+         free (udef_table[undef_count].key);
        }
-
-      free (dll_symname);
+      free (udef_table);
     }
 
-  while (undef_count)
+  if (pe_def_file && pe_def_file->name)
+    dll_filename = pe_def_file->name;
+  else
     {
-      --undef_count;
-      free (udef_table[undef_count].key);
+      dll_filename = bfd_get_filename (output_bfd);
+      for (const char *p = dll_filename; *p; p++)
+       if (*p == '\\' || *p == '/' || *p == ':')
+         dll_filename = p + 1;
     }
-  free (udef_table);
+  dll_symname = xstrdup (dll_filename);
+  for (int i = 0; dll_symname[i]; i++)
+    if (!ISALNUM (dll_symname[i]))
+      dll_symname[i] = '_';
 }
 
 /* We were handed a *.DLL file.  Parse it and turn it into a set of
@@ -3280,7 +3426,7 @@ pe_get32 (bfd *abfd, int where)
 
   bfd_seek (abfd, (file_ptr) where, SEEK_SET);
   bfd_bread (b, (bfd_size_type) 4, abfd);
-  return b[0] + (b[1] << 8) + (b[2] << 16) + (b[3] << 24);
+  return b[0] + (b[1] << 8) + (b[2] << 16) + ((unsigned) b[3] << 24);
 }
 
 static unsigned int
@@ -3288,10 +3434,10 @@ pe_as32 (void *ptr)
 {
   unsigned char *b = ptr;
 
-  return b[0] + (b[1] << 8) + (b[2] << 16) + (b[3] << 24);
+  return b[0] + (b[1] << 8) + (b[2] << 16) + ((unsigned) b[3] << 24);
 }
 
-bfd_boolean
+bool
 pe_implied_import_dll (const char *filename)
 {
   bfd *dll;
@@ -3318,20 +3464,22 @@ pe_implied_import_dll (const char *filename)
   if (!dll)
     {
       einfo (_("%X%P: open %s: %E\n"), filename);
-      return FALSE;
+      return false;
     }
 
+  track_dependency_files (filename);
+
   /* PEI dlls seem to be bfd_objects.  */
   if (!bfd_check_format (dll, bfd_object))
     {
       einfo (_("%X%P: %s: this doesn't appear to be a DLL\n"), filename);
-      return FALSE;
+      return false;
     }
 
   /* 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
+#ifdef pe_use_plus
   num_entries = pe_get32 (dll, opthdr_ofs + 92 + 4 * 4); /*  & NumberOfRvaAndSizes.  */
 #else
   num_entries = pe_get32 (dll, opthdr_ofs + 92);
@@ -3339,9 +3487,9 @@ pe_implied_import_dll (const char *filename)
 
   /* No import or export directory entry.  */
   if (num_entries < 1)
-    return FALSE;
+    return false;
 
-#ifdef pe_use_x86_64
+#ifdef pe_use_plus
   export_rva  = pe_get32 (dll, opthdr_ofs + 96 + 4 * 4);
   export_size = pe_get32 (dll, opthdr_ofs + 100 + 4 * 4);
 #else
@@ -3351,7 +3499,7 @@ pe_implied_import_dll (const char *filename)
 
   /* No export table - nothing to export.  */
   if (export_size == 0)
-    return FALSE;
+    return false;
 
   nsections = pe_get16 (dll, pe_header_offset + 4 + 2);
   secptr = (pe_header_offset + 4 + 20 +
@@ -3400,7 +3548,7 @@ pe_implied_import_dll (const char *filename)
 
          if (pe_dll_extra_pe_debug)
            printf ("%s %s: 0x%08lx-0x%08lx (0x%08lx)\n",
-                   __FUNCTION__, sec_name, (unsigned long) vaddr,
+                   __func__, sec_name, (unsigned long) vaddr,
                    (unsigned long) (vaddr + vsize), (unsigned long) flags);
        }
       else if (strcmp(sec_name,".rdata") == 0)
@@ -3410,7 +3558,7 @@ pe_implied_import_dll (const char *filename)
 
          if (pe_dll_extra_pe_debug)
            printf ("%s %s: 0x%08lx-0x%08lx (0x%08lx)\n",
-                   __FUNCTION__, sec_name, (unsigned long) vaddr,
+                   __func__, sec_name, (unsigned long) vaddr,
                    (unsigned long) (vaddr + vsize), (unsigned long) flags);
        }
       else if (strcmp (sec_name,".bss") == 0)
@@ -3420,7 +3568,7 @@ pe_implied_import_dll (const char *filename)
 
          if (pe_dll_extra_pe_debug)
            printf ("%s %s: 0x%08lx-0x%08lx (0x%08lx)\n",
-                   __FUNCTION__, sec_name, (unsigned long) vaddr,
+                   __func__, sec_name, (unsigned long) vaddr,
                    (unsigned long) (vaddr + vsize), (unsigned long) flags);
        }
     }
@@ -3448,7 +3596,7 @@ pe_implied_import_dll (const char *filename)
     {
       if (pe_dll_extra_pe_debug)
        printf ("%s is already loaded\n", dllname);
-      return TRUE;
+      return true;
     }
 
   /* This is an optimized version of the insertion loop, which avoids lots of
@@ -3478,11 +3626,11 @@ pe_implied_import_dll (const char *filename)
 
          if (pe_dll_extra_pe_debug)
            printf ("%s dll-name: %s sym: %s addr: 0x%lx %s\n",
-                   __FUNCTION__, dllname, erva + name_rva,
+                   __func__, dllname, erva + name_rva,
                    (unsigned long) func_rva, is_data ? "(data)" : "");
        }
 
-      return TRUE;
+      return true;
     }
 
   /* Iterate through the list of symbols.  */
@@ -3497,9 +3645,9 @@ 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 (! startswith (erva + name_rva, "__nm_"))
        {
-         int is_dup = 0;
+         bool is_dup = false;
          /* is_data is true if the address is in the data, rdata or bss
             segment.  */
          is_data =
@@ -3515,12 +3663,12 @@ pe_implied_import_dll (const char *filename)
 
          if (pe_dll_extra_pe_debug)
            printf ("%s dll-name: %s sym: %s addr: 0x%lx %s\n",
-                   __FUNCTION__, dllname, erva + name_rva,
+                   __func__, dllname, erva + name_rva,
                    (unsigned long) func_rva, is_data ? "(data)" : "");
        }
     }
 
-  return TRUE;
+  return true;
 }
 
 void
@@ -3544,11 +3692,19 @@ pe_dll_build_sections (bfd *abfd, struct bfd_link_info *info)
   pe_output_file_set_long_section_names (abfd);
   process_def_file_and_drectve (abfd, info);
 
-  if (pe_def_file->num_exports == 0 && !bfd_link_pic (info))
-    return;
+  if (pe_def_file->num_exports == 0
+      && (!bfd_link_pic (info) || pe_dll_exclude_all_symbols))
+    {
+      if (pe_dll_enable_reloc_section)
+       {
+         build_filler_bfd (false /* edata not needed.  */);
+         pe_output_file_set_long_section_names (filler_bfd);
+       }
+      return;
+    }
 
-  generate_edata (abfd, info);
-  build_filler_bfd (1);
+  generate_edata ();
+  build_filler_bfd (true /* edata is needed.  */);
   pe_output_file_set_long_section_names (filler_bfd);
 }
 
@@ -3564,33 +3720,16 @@ pe_exe_build_sections (bfd *abfd, struct bfd_link_info *info ATTRIBUTE_UNUSED)
 void
 pe_dll_fill_sections (bfd *abfd, struct bfd_link_info *info)
 {
-  pe_dll_id_target (bfd_get_target (abfd));
-  pe_output_file_set_long_section_names (abfd);
-  image_base = pe_data (abfd)->pe_opthdr.ImageBase;
+  pe_exe_fill_sections (abfd, info);
 
-  generate_reloc (abfd, info);
-  if (reloc_sz > 0)
+  if (edata_s)
     {
-      bfd_set_section_size (filler_bfd, reloc_s, reloc_sz);
-
-      /* Resize the sections.  */
-      lang_reset_memory_regions ();
-      lang_size_sections (NULL, TRUE);
-
-      /* Redo special stuff.  */
-      ldemul_after_allocation ();
-
-      /* Do the assignments again.  */
-      lang_do_assignments (lang_final_phase_enum);
+      fill_edata (abfd, info);
+      edata_s->contents = edata_d;
     }
 
-  fill_edata (abfd, info);
-
   if (bfd_link_dll (info))
     pe_data (abfd)->dll = 1;
-
-  edata_s->contents = edata_d;
-  reloc_s->contents = reloc_d;
 }
 
 void
@@ -3601,24 +3740,32 @@ pe_exe_fill_sections (bfd *abfd, struct bfd_link_info *info)
   image_base = pe_data (abfd)->pe_opthdr.ImageBase;
 
   generate_reloc (abfd, info);
+
   if (reloc_sz > 0)
     {
-      bfd_set_section_size (filler_bfd, reloc_s, reloc_sz);
+      bfd_set_section_size (reloc_s, reloc_sz);
 
       /* Resize the sections.  */
       lang_reset_memory_regions ();
-      lang_size_sections (NULL, TRUE);
+      lang_size_sections (NULL, true);
 
       /* Redo special stuff.  */
       ldemul_after_allocation ();
 
       /* Do the assignments again.  */
       lang_do_assignments (lang_final_phase_enum);
+
+      reloc_s->contents = reloc_d;
+    }
+  else if (reloc_s)
+    {
+      /* Do not emit an empty reloc section.  */
+      bfd_set_section_flags (reloc_s, SEC_IN_MEMORY | SEC_EXCLUDE);
+      reloc_s->output_section = bfd_abs_section_ptr;
     }
-  reloc_s->contents = reloc_d;
 }
 
-bfd_boolean
+bool
 pe_bfd_is_dll (bfd *abfd)
 {
   return (bfd_get_format (abfd) == bfd_object