Add unlink support to moxie simulator
[deliverable/binutils-gdb.git] / bfd / peicode.h
index 1282bb9b1c86d71e36d644ff01b6534fc6ccb58e..e9d205a01a10437a95fc15c85094ddc5985e26c4 100644 (file)
@@ -1,13 +1,12 @@
 /* Support for the generic parts of PE/PEI, for BFD.
 /* Support for the generic parts of PE/PEI, for BFD.
-   Copyright 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
-   2005 Free Software Foundation, Inc.
+   Copyright (C) 1995-2019 Free Software Foundation, Inc.
    Written by Cygnus Solutions.
 
    This file is part of BFD, the Binary File Descriptor library.
 
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    Written by Cygnus Solutions.
 
    This file is part of BFD, the Binary File Descriptor library.
 
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 2 of the License, or
+   the Free Software Foundation; either version 3 of the License, or
    (at your option) any later version.
 
    This program is distributed in the hope that it will be useful,
    (at your option) any later version.
 
    This program is distributed in the hope that it will be useful,
 
    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
 
    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
-   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
+   Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
+   MA 02110-1301, USA.  */
+
 
 /* Most of this hacked by  Steve Chamberlain,
                        sac@cygnus.com
 
    PE/PEI rearrangement (and code added): Donn Terry
 
 /* Most of this hacked by  Steve Chamberlain,
                        sac@cygnus.com
 
    PE/PEI rearrangement (and code added): Donn Terry
-                                       Softway Systems, Inc.  */
+                                      Softway Systems, Inc.  */
 
 /* Hey look, some documentation [and in a place you expect to find it]!
 
 
 /* Hey look, some documentation [and in a place you expect to find it]!
 
@@ -55,8 +56,7 @@
 
 #include "libpei.h"
 
 
 #include "libpei.h"
 
-static bfd_boolean (*pe_saved_coff_bfd_print_private_bfd_data)
-    PARAMS ((bfd *, PTR)) =
+static bfd_boolean (*pe_saved_coff_bfd_print_private_bfd_data) (bfd *, void *) =
 #ifndef coff_bfd_print_private_bfd_data
      NULL;
 #else
 #ifndef coff_bfd_print_private_bfd_data
      NULL;
 #else
@@ -64,11 +64,10 @@ static bfd_boolean (*pe_saved_coff_bfd_print_private_bfd_data)
 #undef coff_bfd_print_private_bfd_data
 #endif
 
 #undef coff_bfd_print_private_bfd_data
 #endif
 
-static bfd_boolean pe_print_private_bfd_data PARAMS ((bfd *, PTR));
+static bfd_boolean                     pe_print_private_bfd_data (bfd *, void *);
 #define coff_bfd_print_private_bfd_data pe_print_private_bfd_data
 
 #define coff_bfd_print_private_bfd_data pe_print_private_bfd_data
 
-static bfd_boolean (*pe_saved_coff_bfd_copy_private_bfd_data)
-    PARAMS ((bfd *, bfd *)) =
+static bfd_boolean (*pe_saved_coff_bfd_copy_private_bfd_data) (bfd *, bfd *) =
 #ifndef coff_bfd_copy_private_bfd_data
      NULL;
 #else
 #ifndef coff_bfd_copy_private_bfd_data
      NULL;
 #else
@@ -76,21 +75,12 @@ static bfd_boolean (*pe_saved_coff_bfd_copy_private_bfd_data)
 #undef coff_bfd_copy_private_bfd_data
 #endif
 
 #undef coff_bfd_copy_private_bfd_data
 #endif
 
-static bfd_boolean pe_bfd_copy_private_bfd_data PARAMS ((bfd *, bfd *));
+static bfd_boolean                    pe_bfd_copy_private_bfd_data (bfd *, bfd *);
 #define coff_bfd_copy_private_bfd_data pe_bfd_copy_private_bfd_data
 
 #define coff_bfd_copy_private_bfd_data pe_bfd_copy_private_bfd_data
 
-#define coff_mkobject      pe_mkobject
+#define coff_mkobject     pe_mkobject
 #define coff_mkobject_hook pe_mkobject_hook
 
 #define coff_mkobject_hook pe_mkobject_hook
 
-#ifndef NO_COFF_RELOCS
-static void coff_swap_reloc_in PARAMS ((bfd *, PTR, PTR));
-static unsigned int coff_swap_reloc_out PARAMS ((bfd *, PTR, PTR));
-#endif
-static void coff_swap_filehdr_in PARAMS ((bfd *, PTR, PTR));
-static void coff_swap_scnhdr_in PARAMS ((bfd *, PTR, PTR));
-static bfd_boolean pe_mkobject PARAMS ((bfd *));
-static PTR pe_mkobject_hook PARAMS ((bfd *, PTR, PTR));
-
 #ifdef COFF_IMAGE_WITH_PE
 /* This structure contains static variables used by the ILF code.  */
 typedef asection * asection_ptr;
 #ifdef COFF_IMAGE_WITH_PE
 /* This structure contains static variables used by the ILF code.  */
 typedef asection * asection_ptr;
@@ -100,17 +90,17 @@ typedef struct
   bfd *                        abfd;
   bfd_byte *           data;
   struct bfd_in_memory * bim;
   bfd *                        abfd;
   bfd_byte *           data;
   struct bfd_in_memory * bim;
-  unsigned short        magic;
+  unsigned short       magic;
 
   arelent *            reltab;
 
   arelent *            reltab;
-  unsigned int                 relcount;
+  unsigned int         relcount;
 
 
-  coff_symbol_type *   sym_cache;
-  coff_symbol_type *   sym_ptr;
-  unsigned int         sym_index;
+  coff_symbol_type *   sym_cache;
+  coff_symbol_type *   sym_ptr;
+  unsigned int         sym_index;
 
 
-  unsigned int *       sym_table;
-  unsigned int *       table_ptr;
+  unsigned int *       sym_table;
+  unsigned int *       table_ptr;
 
   combined_entry_type * native_syms;
   combined_entry_type * native_ptr;
 
   combined_entry_type * native_syms;
   combined_entry_type * native_ptr;
@@ -120,77 +110,72 @@ typedef struct
 
   unsigned int         sec_index;
 
 
   unsigned int         sec_index;
 
-  char *                string_table;
-  char *                string_ptr;
+  char *               string_table;
+  char *               string_ptr;
   char *               end_string_ptr;
 
   char *               end_string_ptr;
 
-  SYMENT *              esym_table;
-  SYMENT *              esym_ptr;
+  SYMENT *             esym_table;
+  SYMENT *             esym_ptr;
 
   struct internal_reloc * int_reltab;
 }
 pe_ILF_vars;
 #endif /* COFF_IMAGE_WITH_PE */
 
 
   struct internal_reloc * int_reltab;
 }
 pe_ILF_vars;
 #endif /* COFF_IMAGE_WITH_PE */
 
-/**********************************************************************/
-
+const bfd_target *coff_real_object_p
+  (bfd *, unsigned, struct internal_filehdr *, struct internal_aouthdr *);
+\f
 #ifndef NO_COFF_RELOCS
 static void
 #ifndef NO_COFF_RELOCS
 static void
-coff_swap_reloc_in (abfd, src, dst)
-     bfd *abfd;
-     PTR src;
-     PTR dst;
+coff_swap_reloc_in (bfd * abfd, void * src, void * dst)
 {
   RELOC *reloc_src = (RELOC *) src;
   struct internal_reloc *reloc_dst = (struct internal_reloc *) dst;
 
 {
   RELOC *reloc_src = (RELOC *) src;
   struct internal_reloc *reloc_dst = (struct internal_reloc *) dst;
 
-  reloc_dst->r_vaddr = H_GET_32 (abfd, reloc_src->r_vaddr);
+  reloc_dst->r_vaddr  = H_GET_32 (abfd, reloc_src->r_vaddr);
   reloc_dst->r_symndx = H_GET_S32 (abfd, reloc_src->r_symndx);
   reloc_dst->r_symndx = H_GET_S32 (abfd, reloc_src->r_symndx);
-
-  reloc_dst->r_type = H_GET_16 (abfd, reloc_src->r_type);
-
+  reloc_dst->r_type   = H_GET_16 (abfd, reloc_src->r_type);
 #ifdef SWAP_IN_RELOC_OFFSET
   reloc_dst->r_offset = SWAP_IN_RELOC_OFFSET (abfd, reloc_src->r_offset);
 #endif
 }
 
 static unsigned int
 #ifdef SWAP_IN_RELOC_OFFSET
   reloc_dst->r_offset = SWAP_IN_RELOC_OFFSET (abfd, reloc_src->r_offset);
 #endif
 }
 
 static unsigned int
-coff_swap_reloc_out (abfd, src, dst)
-     bfd       *abfd;
-     PTR       src;
-     PTR       dst;
+coff_swap_reloc_out (bfd * abfd, void * src, void * dst)
 {
 {
-  struct internal_reloc *reloc_src = (struct internal_reloc *)src;
-  struct external_reloc *reloc_dst = (struct external_reloc *)dst;
+  struct internal_reloc *reloc_src = (struct internal_reloc *) src;
+  struct external_reloc *reloc_dst = (struct external_reloc *) dst;
+
   H_PUT_32 (abfd, reloc_src->r_vaddr, reloc_dst->r_vaddr);
   H_PUT_32 (abfd, reloc_src->r_symndx, reloc_dst->r_symndx);
   H_PUT_32 (abfd, reloc_src->r_vaddr, reloc_dst->r_vaddr);
   H_PUT_32 (abfd, reloc_src->r_symndx, reloc_dst->r_symndx);
-
   H_PUT_16 (abfd, reloc_src->r_type, reloc_dst->r_type);
 
 #ifdef SWAP_OUT_RELOC_OFFSET
   SWAP_OUT_RELOC_OFFSET (abfd, reloc_src->r_offset, reloc_dst->r_offset);
 #endif
 #ifdef SWAP_OUT_RELOC_EXTRA
   H_PUT_16 (abfd, reloc_src->r_type, reloc_dst->r_type);
 
 #ifdef SWAP_OUT_RELOC_OFFSET
   SWAP_OUT_RELOC_OFFSET (abfd, reloc_src->r_offset, reloc_dst->r_offset);
 #endif
 #ifdef SWAP_OUT_RELOC_EXTRA
-  SWAP_OUT_RELOC_EXTRA(abfd, reloc_src, reloc_dst);
+  SWAP_OUT_RELOC_EXTRA (abfd, reloc_src, reloc_dst);
 #endif
   return RELSZ;
 }
 #endif /* not NO_COFF_RELOCS */
 
 #endif
   return RELSZ;
 }
 #endif /* not NO_COFF_RELOCS */
 
+#ifdef COFF_IMAGE_WITH_PE
+#undef FILHDR
+#define FILHDR struct external_PEI_IMAGE_hdr
+#endif
+
 static void
 static void
-coff_swap_filehdr_in (abfd, src, dst)
-     bfd            *abfd;
-     PTR            src;
-     PTR            dst;
+coff_swap_filehdr_in (bfd * abfd, void * src, void * dst)
 {
   FILHDR *filehdr_src = (FILHDR *) src;
   struct internal_filehdr *filehdr_dst = (struct internal_filehdr *) dst;
 {
   FILHDR *filehdr_src = (FILHDR *) src;
   struct internal_filehdr *filehdr_dst = (struct internal_filehdr *) dst;
-  filehdr_dst->f_magic = H_GET_16 (abfd, filehdr_src->f_magic);
-  filehdr_dst->f_nscns = H_GET_16 (abfd, filehdr_src-> f_nscns);
-  filehdr_dst->f_timdat = H_GET_32 (abfd, filehdr_src-> f_timdat);
 
 
-  filehdr_dst->f_nsyms = H_GET_32 (abfd, filehdr_src-> f_nsyms);
-  filehdr_dst->f_flags = H_GET_16 (abfd, filehdr_src-> f_flags);
+  filehdr_dst->f_magic  = H_GET_16 (abfd, filehdr_src->f_magic);
+  filehdr_dst->f_nscns  = H_GET_16 (abfd, filehdr_src->f_nscns);
+  filehdr_dst->f_timdat = H_GET_32 (abfd, filehdr_src->f_timdat);
+  filehdr_dst->f_nsyms  = H_GET_32 (abfd, filehdr_src->f_nsyms);
+  filehdr_dst->f_flags  = H_GET_16 (abfd, filehdr_src->f_flags);
   filehdr_dst->f_symptr = H_GET_32 (abfd, filehdr_src->f_symptr);
 
   /* Other people's tools sometimes generate headers with an nsyms but
   filehdr_dst->f_symptr = H_GET_32 (abfd, filehdr_src->f_symptr);
 
   /* Other people's tools sometimes generate headers with an nsyms but
@@ -206,27 +191,29 @@ coff_swap_filehdr_in (abfd, src, dst)
 
 #ifdef COFF_IMAGE_WITH_PE
 # define coff_swap_filehdr_out _bfd_XXi_only_swap_filehdr_out
 
 #ifdef COFF_IMAGE_WITH_PE
 # define coff_swap_filehdr_out _bfd_XXi_only_swap_filehdr_out
+#elif defined COFF_WITH_pex64
+# define coff_swap_filehdr_out _bfd_pex64_only_swap_filehdr_out
+#elif defined COFF_WITH_pep
+# define coff_swap_filehdr_out _bfd_pep_only_swap_filehdr_out
 #else
 # define coff_swap_filehdr_out _bfd_pe_only_swap_filehdr_out
 #endif
 
 static void
 #else
 # define coff_swap_filehdr_out _bfd_pe_only_swap_filehdr_out
 #endif
 
 static void
-coff_swap_scnhdr_in (abfd, ext, in)
-     bfd            *abfd;
-     PTR            ext;
-     PTR            in;
+coff_swap_scnhdr_in (bfd * abfd, void * ext, void * in)
 {
   SCNHDR *scnhdr_ext = (SCNHDR *) ext;
   struct internal_scnhdr *scnhdr_int = (struct internal_scnhdr *) in;
 
 {
   SCNHDR *scnhdr_ext = (SCNHDR *) ext;
   struct internal_scnhdr *scnhdr_int = (struct internal_scnhdr *) in;
 
-  memcpy(scnhdr_int->s_name, scnhdr_ext->s_name, sizeof (scnhdr_int->s_name));
-  scnhdr_int->s_vaddr = GET_SCNHDR_VADDR (abfd, scnhdr_ext->s_vaddr);
-  scnhdr_int->s_paddr = GET_SCNHDR_PADDR (abfd, scnhdr_ext->s_paddr);
-  scnhdr_int->s_size = GET_SCNHDR_SIZE (abfd, scnhdr_ext->s_size);
-  scnhdr_int->s_scnptr = GET_SCNHDR_SCNPTR (abfd, scnhdr_ext->s_scnptr);
-  scnhdr_int->s_relptr = GET_SCNHDR_RELPTR (abfd, scnhdr_ext->s_relptr);
+  memcpy (scnhdr_int->s_name, scnhdr_ext->s_name, sizeof (scnhdr_int->s_name));
+
+  scnhdr_int->s_vaddr   = GET_SCNHDR_VADDR (abfd, scnhdr_ext->s_vaddr);
+  scnhdr_int->s_paddr   = GET_SCNHDR_PADDR (abfd, scnhdr_ext->s_paddr);
+  scnhdr_int->s_size    = GET_SCNHDR_SIZE (abfd, scnhdr_ext->s_size);
+  scnhdr_int->s_scnptr  = GET_SCNHDR_SCNPTR (abfd, scnhdr_ext->s_scnptr);
+  scnhdr_int->s_relptr  = GET_SCNHDR_RELPTR (abfd, scnhdr_ext->s_relptr);
   scnhdr_int->s_lnnoptr = GET_SCNHDR_LNNOPTR (abfd, scnhdr_ext->s_lnnoptr);
   scnhdr_int->s_lnnoptr = GET_SCNHDR_LNNOPTR (abfd, scnhdr_ext->s_lnnoptr);
-  scnhdr_int->s_flags = H_GET_32 (abfd, scnhdr_ext->s_flags);
+  scnhdr_int->s_flags   = H_GET_32 (abfd, scnhdr_ext->s_flags);
 
   /* MS handles overflow of line numbers by carrying into the reloc
      field (it appears).  Since it's supposed to be zero for PE
 
   /* MS handles overflow of line numbers by carrying into the reloc
      field (it appears).  Since it's supposed to be zero for PE
@@ -243,7 +230,10 @@ coff_swap_scnhdr_in (abfd, ext, in)
   if (scnhdr_int->s_vaddr != 0)
     {
       scnhdr_int->s_vaddr += pe_data (abfd)->pe_opthdr.ImageBase;
   if (scnhdr_int->s_vaddr != 0)
     {
       scnhdr_int->s_vaddr += pe_data (abfd)->pe_opthdr.ImageBase;
+      /* Do not cut upper 32-bits for 64-bit vma.  */
+#ifndef COFF_WITH_pex64
       scnhdr_int->s_vaddr &= 0xffffffff;
       scnhdr_int->s_vaddr &= 0xffffffff;
+#endif
     }
 
 #ifndef COFF_NO_HACK_SCNHDR_SIZE
     }
 
 #ifndef COFF_NO_HACK_SCNHDR_SIZE
@@ -253,22 +243,18 @@ coff_swap_scnhdr_in (abfd, ext, in)
      use the virtual size (stored in s_paddr) instead.  */
   if (scnhdr_int->s_paddr > 0
       && (((scnhdr_int->s_flags & IMAGE_SCN_CNT_UNINITIALIZED_DATA) != 0
      use the virtual size (stored in s_paddr) instead.  */
   if (scnhdr_int->s_paddr > 0
       && (((scnhdr_int->s_flags & IMAGE_SCN_CNT_UNINITIALIZED_DATA) != 0
-          && (! bfd_pe_executable_p (abfd) || scnhdr_int->s_size == 0))
-          || (bfd_pe_executable_p (abfd) && scnhdr_int->s_size > scnhdr_int->s_paddr)))
-    {
-      scnhdr_int->s_size = scnhdr_int->s_paddr;
-
-      /* This code used to set scnhdr_int->s_paddr to 0.  However,
-         coff_set_alignment_hook stores s_paddr in virt_size, which
-         only works if it correctly holds the virtual size of the
-         section.  */
-    }
+          && (! bfd_pei_p (abfd) || scnhdr_int->s_size == 0))
+         || (bfd_pei_p (abfd) && (scnhdr_int->s_size > scnhdr_int->s_paddr))))
+  /* This code used to set scnhdr_int->s_paddr to 0.  However,
+     coff_set_alignment_hook stores s_paddr in virt_size, which
+     only works if it correctly holds the virtual size of the
+     section.  */
+    scnhdr_int->s_size = scnhdr_int->s_paddr;
 #endif
 }
 
 static bfd_boolean
 #endif
 }
 
 static bfd_boolean
-pe_mkobject (abfd)
-     bfd * abfd;
+pe_mkobject (bfd * abfd)
 {
   pe_data_type *pe;
   bfd_size_type amt = sizeof (pe_data_type);
 {
   pe_data_type *pe;
   bfd_size_type amt = sizeof (pe_data_type);
@@ -285,22 +271,34 @@ pe_mkobject (abfd)
   /* in_reloc_p is architecture dependent.  */
   pe->in_reloc_p = in_reloc_p;
 
   /* in_reloc_p is architecture dependent.  */
   pe->in_reloc_p = in_reloc_p;
 
-#ifdef PEI_FORCE_MINIMUM_ALIGNMENT
-  pe->force_minimum_alignment = 1;
-#endif
-#ifdef PEI_TARGET_SUBSYSTEM
-  pe->target_subsystem = PEI_TARGET_SUBSYSTEM;
-#endif
-
+  /* Default DOS message string.  */
+  pe->dos_message[0]  = 0x0eba1f0e;
+  pe->dos_message[1]  = 0xcd09b400;
+  pe->dos_message[2]  = 0x4c01b821;
+  pe->dos_message[3]  = 0x685421cd;
+  pe->dos_message[4]  = 0x70207369;
+  pe->dos_message[5]  = 0x72676f72;
+  pe->dos_message[6]  = 0x63206d61;
+  pe->dos_message[7]  = 0x6f6e6e61;
+  pe->dos_message[8]  = 0x65622074;
+  pe->dos_message[9]  = 0x6e757220;
+  pe->dos_message[10] = 0x206e6920;
+  pe->dos_message[11] = 0x20534f44;
+  pe->dos_message[12] = 0x65646f6d;
+  pe->dos_message[13] = 0x0a0d0d2e;
+  pe->dos_message[14] = 0x24;
+  pe->dos_message[15] = 0x0;
+
+  memset (& pe->pe_opthdr, 0, sizeof pe->pe_opthdr);
   return TRUE;
 }
 
 /* Create the COFF backend specific information.  */
   return TRUE;
 }
 
 /* Create the COFF backend specific information.  */
-static PTR
-pe_mkobject_hook (abfd, filehdr, aouthdr)
-     bfd * abfd;
-     PTR filehdr;
-     PTR aouthdr ATTRIBUTE_UNUSED;
+
+static void *
+pe_mkobject_hook (bfd * abfd,
+                 void * filehdr,
+                 void * aouthdr ATTRIBUTE_UNUSED)
 {
   struct internal_filehdr *internal_f = (struct internal_filehdr *) filehdr;
   pe_data_type *pe;
 {
   struct internal_filehdr *internal_f = (struct internal_filehdr *) filehdr;
   pe_data_type *pe;
@@ -337,7 +335,7 @@ pe_mkobject_hook (abfd, filehdr, aouthdr)
 
 #ifdef COFF_IMAGE_WITH_PE
   if (aouthdr)
 
 #ifdef COFF_IMAGE_WITH_PE
   if (aouthdr)
-    pe->pe_opthdr = ((struct internal_aouthdr *)aouthdr)->pe;
+    pe->pe_opthdr = ((struct internal_aouthdr *) aouthdr)->pe;
 #endif
 
 #ifdef ARM
 #endif
 
 #ifdef ARM
@@ -345,35 +343,33 @@ pe_mkobject_hook (abfd, filehdr, aouthdr)
     coff_data (abfd) ->flags = 0;
 #endif
 
     coff_data (abfd) ->flags = 0;
 #endif
 
-  return (PTR) pe;
+  memcpy (pe->dos_message, internal_f->pe.dos_message,
+         sizeof (pe->dos_message));
+
+  return (void *) pe;
 }
 
 static bfd_boolean
 }
 
 static bfd_boolean
-pe_print_private_bfd_data (abfd, vfile)
-     bfd *abfd;
-     PTR vfile;
+pe_print_private_bfd_data (bfd *abfd, void * vfile)
 {
   FILE *file = (FILE *) vfile;
 
   if (!_bfd_XX_print_private_bfd_data_common (abfd, vfile))
     return FALSE;
 
 {
   FILE *file = (FILE *) vfile;
 
   if (!_bfd_XX_print_private_bfd_data_common (abfd, vfile))
     return FALSE;
 
-  if (pe_saved_coff_bfd_print_private_bfd_data != NULL)
-    {
-      fputc ('\n', file);
+  if (pe_saved_coff_bfd_print_private_bfd_data == NULL)
+    return TRUE;
 
 
-      return pe_saved_coff_bfd_print_private_bfd_data (abfd, vfile);
-    }
+  fputc ('\n', file);
 
 
-  return TRUE;
+  return pe_saved_coff_bfd_print_private_bfd_data (abfd, vfile);
 }
 
 /* Copy any private info we understand from the input bfd
    to the output bfd.  */
 
 static bfd_boolean
 }
 
 /* Copy any private info we understand from the input bfd
    to the output bfd.  */
 
 static bfd_boolean
-pe_bfd_copy_private_bfd_data (ibfd, obfd)
-     bfd *ibfd, *obfd;
+pe_bfd_copy_private_bfd_data (bfd *ibfd, bfd *obfd)
 {
   /* PR binutils/716: Copy the large address aware flag.
      XXX: Should we be copying other flags or other fields in the pe_data()
 {
   /* PR binutils/716: Copy the large address aware flag.
      XXX: Should we be copying other flags or other fields in the pe_data()
@@ -382,7 +378,7 @@ pe_bfd_copy_private_bfd_data (ibfd, obfd)
       && pe_data (ibfd) != NULL
       && pe_data (ibfd)->real_flags & IMAGE_FILE_LARGE_ADDRESS_AWARE)
     pe_data (obfd)->real_flags |= IMAGE_FILE_LARGE_ADDRESS_AWARE;
       && pe_data (ibfd) != NULL
       && pe_data (ibfd)->real_flags & IMAGE_FILE_LARGE_ADDRESS_AWARE)
     pe_data (obfd)->real_flags |= IMAGE_FILE_LARGE_ADDRESS_AWARE;
-      
+
   if (!_bfd_XX_bfd_copy_private_bfd_data_common (ibfd, obfd))
     return FALSE;
 
   if (!_bfd_XX_bfd_copy_private_bfd_data_common (ibfd, obfd))
     return FALSE;
 
@@ -425,29 +421,36 @@ pe_bfd_copy_private_bfd_data (ibfd, obfd)
       the table in order to for the string lookup code in coffgen/coffcode to
       work.  */
 #define NUM_ILF_RELOCS         8
       the table in order to for the string lookup code in coffgen/coffcode to
       work.  */
 #define NUM_ILF_RELOCS         8
-#define NUM_ILF_SECTIONS        6
-#define NUM_ILF_SYMS           (2 + NUM_ILF_SECTIONS)
+#define NUM_ILF_SECTIONS       6
+#define NUM_ILF_SYMS           (2 + NUM_ILF_SECTIONS)
 
 
-#define SIZEOF_ILF_SYMS                (NUM_ILF_SYMS * sizeof (* vars.sym_cache))
-#define SIZEOF_ILF_SYM_TABLE   (NUM_ILF_SYMS * sizeof (* vars.sym_table))
-#define SIZEOF_ILF_NATIVE_SYMS (NUM_ILF_SYMS * sizeof (* vars.native_syms))
+#define SIZEOF_ILF_SYMS                 (NUM_ILF_SYMS * sizeof (* vars.sym_cache))
+#define SIZEOF_ILF_SYM_TABLE    (NUM_ILF_SYMS * sizeof (* vars.sym_table))
+#define SIZEOF_ILF_NATIVE_SYMS  (NUM_ILF_SYMS * sizeof (* vars.native_syms))
 #define SIZEOF_ILF_SYM_PTR_TABLE (NUM_ILF_SYMS * sizeof (* vars.sym_ptr_table))
 #define SIZEOF_ILF_SYM_PTR_TABLE (NUM_ILF_SYMS * sizeof (* vars.sym_ptr_table))
-#define SIZEOF_ILF_EXT_SYMS    (NUM_ILF_SYMS * sizeof (* vars.esym_table))
-#define SIZEOF_ILF_RELOCS      (NUM_ILF_RELOCS * sizeof (* vars.reltab))
-#define SIZEOF_ILF_INT_RELOCS  (NUM_ILF_RELOCS * sizeof (* vars.int_reltab))
-#define SIZEOF_ILF_STRINGS     (strlen (symbol_name) * 2 + 8 \
+#define SIZEOF_ILF_EXT_SYMS     (NUM_ILF_SYMS * sizeof (* vars.esym_table))
+#define SIZEOF_ILF_RELOCS       (NUM_ILF_RELOCS * sizeof (* vars.reltab))
+#define SIZEOF_ILF_INT_RELOCS   (NUM_ILF_RELOCS * sizeof (* vars.int_reltab))
+#define SIZEOF_ILF_STRINGS      (strlen (symbol_name) * 2 + 8 \
                                        + 21 + strlen (source_dll) \
                                        + NUM_ILF_SECTIONS * 9 \
                                        + STRING_SIZE_SIZE)
 #define SIZEOF_IDATA2          (5 * 4)
                                        + 21 + strlen (source_dll) \
                                        + NUM_ILF_SECTIONS * 9 \
                                        + STRING_SIZE_SIZE)
 #define SIZEOF_IDATA2          (5 * 4)
+
+/* For PEx64 idata4 & 5 have thumb size of 8 bytes.  */
+#ifdef COFF_WITH_pex64
+#define SIZEOF_IDATA4          (2 * 4)
+#define SIZEOF_IDATA5          (2 * 4)
+#else
 #define SIZEOF_IDATA4          (1 * 4)
 #define SIZEOF_IDATA5          (1 * 4)
 #define SIZEOF_IDATA4          (1 * 4)
 #define SIZEOF_IDATA5          (1 * 4)
+#endif
+
 #define SIZEOF_IDATA6          (2 + strlen (symbol_name) + 1 + 1)
 #define SIZEOF_IDATA7          (strlen (source_dll) + 1 + 1)
 #define SIZEOF_IDATA6          (2 + strlen (symbol_name) + 1 + 1)
 #define SIZEOF_IDATA7          (strlen (source_dll) + 1 + 1)
-#define SIZEOF_ILF_SECTIONS     (NUM_ILF_SECTIONS * sizeof (struct coff_section_tdata))
+#define SIZEOF_ILF_SECTIONS    (NUM_ILF_SECTIONS * sizeof (struct coff_section_tdata))
 
 #define ILF_DATA_SIZE                          \
 
 #define ILF_DATA_SIZE                          \
-      sizeof (* vars.bim)                      \
     + SIZEOF_ILF_SYMS                          \
     + SIZEOF_ILF_SYM_TABLE                     \
     + SIZEOF_ILF_NATIVE_SYMS                   \
     + SIZEOF_ILF_SYMS                          \
     + SIZEOF_ILF_SYM_TABLE                     \
     + SIZEOF_ILF_NATIVE_SYMS                   \
@@ -465,12 +468,13 @@ pe_bfd_copy_private_bfd_data (ibfd, obfd)
     + MAX_TEXT_SECTION_SIZE
 
 /* Create an empty relocation against the given symbol.  */
     + MAX_TEXT_SECTION_SIZE
 
 /* Create an empty relocation against the given symbol.  */
+
 static void
 static void
-pe_ILF_make_a_symbol_reloc (pe_ILF_vars *                 vars,
-                           bfd_vma                       address,
-                           bfd_reloc_code_real_type      reloc,
-                           struct bfd_symbol **  sym,
-                           unsigned int                  sym_index)
+pe_ILF_make_a_symbol_reloc (pe_ILF_vars *              vars,
+                           bfd_vma                     address,
+                           bfd_reloc_code_real_type    reloc,
+                           struct bfd_symbol **        sym,
+                           unsigned int                sym_index)
 {
   arelent * entry;
   struct internal_reloc * internal;
 {
   arelent * entry;
   struct internal_reloc * internal;
@@ -493,17 +497,19 @@ pe_ILF_make_a_symbol_reloc (pe_ILF_vars *                 vars,
 }
 
 /* Create an empty relocation against the given section.  */
 }
 
 /* Create an empty relocation against the given section.  */
+
 static void
 static void
-pe_ILF_make_a_reloc (pe_ILF_vars *             vars,
-                    bfd_vma                   address,
+pe_ILF_make_a_reloc (pe_ILF_vars *            vars,
+                    bfd_vma                   address,
                     bfd_reloc_code_real_type  reloc,
                     bfd_reloc_code_real_type  reloc,
-                    asection_ptr              sec)
+                    asection_ptr              sec)
 {
   pe_ILF_make_a_symbol_reloc (vars, address, reloc, sec->symbol_ptr_ptr,
                              coff_section_data (vars->abfd, sec)->i);
 }
 
 /* Move the queued relocs into the given section.  */
 {
   pe_ILF_make_a_symbol_reloc (vars, address, reloc, sec->symbol_ptr_ptr,
                              coff_section_data (vars->abfd, sec)->i);
 }
 
 /* Move the queued relocs into the given section.  */
+
 static void
 pe_ILF_save_relocs (pe_ILF_vars * vars,
                    asection_ptr  sec)
 static void
 pe_ILF_save_relocs (pe_ILF_vars * vars,
                    asection_ptr  sec)
@@ -528,6 +534,7 @@ pe_ILF_save_relocs (pe_ILF_vars * vars,
 }
 
 /* Create a global symbol and add it to the relevant tables.  */
 }
 
 /* Create a global symbol and add it to the relevant tables.  */
+
 static void
 pe_ILF_make_a_symbol (pe_ILF_vars *  vars,
                      const char *   prefix,
 static void
 pe_ILF_make_a_symbol (pe_ILF_vars *  vars,
                      const char *   prefix,
@@ -567,7 +574,7 @@ pe_ILF_make_a_symbol (pe_ILF_vars *  vars,
   sprintf (vars->string_ptr, "%s%s", prefix, symbol_name);
 
   if (section == NULL)
   sprintf (vars->string_ptr, "%s%s", prefix, symbol_name);
 
   if (section == NULL)
-    section = (asection_ptr) & bfd_und_section;
+    section = bfd_und_section_ptr;
 
   /* Initialise the external symbol.  */
   H_PUT_32 (vars->abfd, vars->string_ptr - vars->string_table,
 
   /* Initialise the external symbol.  */
   H_PUT_32 (vars->abfd, vars->string_ptr - vars->string_table,
@@ -579,15 +586,16 @@ pe_ILF_make_a_symbol (pe_ILF_vars *  vars,
      zero initialised.  They are just kept here as reminders.  */
 
   /* Initialise the internal symbol structure.  */
      zero initialised.  They are just kept here as reminders.  */
 
   /* Initialise the internal symbol structure.  */
-  ent->u.syment.n_sclass          = sclass;
-  ent->u.syment.n_scnum           = section->target_index;
-  ent->u.syment._n._n_n._n_offset = (long) sym;
+  ent->u.syment.n_sclass         = sclass;
+  ent->u.syment.n_scnum                  = section->target_index;
+  ent->u.syment._n._n_n._n_offset = (bfd_hostptr_t) sym;
+  ent->is_sym = TRUE;
 
   sym->symbol.the_bfd = vars->abfd;
   sym->symbol.name    = vars->string_ptr;
   sym->symbol.flags   = BSF_EXPORT | BSF_GLOBAL | extra_flags;
   sym->symbol.section = section;
 
   sym->symbol.the_bfd = vars->abfd;
   sym->symbol.name    = vars->string_ptr;
   sym->symbol.flags   = BSF_EXPORT | BSF_GLOBAL | extra_flags;
   sym->symbol.section = section;
-  sym->native         = ent;
+  sym->native        = ent;
 
   * vars->table_ptr = vars->sym_index;
   * vars->sym_ptr_ptr = sym;
 
   * vars->table_ptr = vars->sym_index;
   * vars->sym_ptr_ptr = sym;
@@ -605,6 +613,7 @@ pe_ILF_make_a_symbol (pe_ILF_vars *  vars,
 }
 
 /* Create a section.  */
 }
 
 /* Create a section.  */
+
 static asection_ptr
 pe_ILF_make_a_section (pe_ILF_vars * vars,
                       const char *  name,
 static asection_ptr
 pe_ILF_make_a_section (pe_ILF_vars * vars,
                       const char *  name,
@@ -620,16 +629,16 @@ pe_ILF_make_a_section (pe_ILF_vars * vars,
 
   flags = SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_KEEP | SEC_IN_MEMORY;
 
 
   flags = SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_KEEP | SEC_IN_MEMORY;
 
-  bfd_set_section_flags (vars->abfd, sec, flags | extra_flags);
+  bfd_set_section_flags (sec, flags | extra_flags);
 
 
-  bfd_set_section_alignment (vars->abfd, sec, 2);
+  bfd_set_section_alignment (sec, 2);
 
   /* Check that we will not run out of space.  */
   BFD_ASSERT (vars->data + size < vars->bim->buffer + vars->bim->size);
 
   /* Set the section size and contents.  The actual
      contents are filled in by our parent.  */
 
   /* Check that we will not run out of space.  */
   BFD_ASSERT (vars->data + size < vars->bim->buffer + vars->bim->size);
 
   /* Set the section size and contents.  The actual
      contents are filled in by our parent.  */
-  bfd_set_section_size (vars->abfd, sec, (bfd_size_type) size);
+  bfd_set_section_size (sec, (bfd_size_type) size);
   sec->contents = vars->data;
   sec->target_index = vars->sec_index ++;
 
   sec->contents = vars->data;
   sec->target_index = vars->sec_index ++;
 
@@ -643,6 +652,20 @@ pe_ILF_make_a_section (pe_ILF_vars * vars,
   if (size & 1)
     vars->data --;
 
   if (size & 1)
     vars->data --;
 
+# if (GCC_VERSION >= 3000)
+  /* PR 18758: See note in pe_ILF_buid_a_bfd.  We must make sure that we
+     preserve host alignment requirements.  We test 'size' rather than
+     vars.data as we cannot perform binary arithmetic on pointers.  We assume
+     that vars.data was sufficiently aligned upon entry to this function.
+     The BFD_ASSERTs in this functions will warn us if we run out of room,
+     but we should already have enough padding built in to ILF_DATA_SIZE.  */
+  {
+    unsigned int alignment = __alignof__ (struct coff_section_tdata);
+
+    if (size & (alignment - 1))
+      vars->data += alignment - (size & (alignment - 1));
+  }
+#endif
   /* Create a coff_section_tdata structure for our use.  */
   sec->used_by_bfd = (struct coff_section_tdata *) vars->data;
   vars->data += sizeof (struct coff_section_tdata);
   /* Create a coff_section_tdata structure for our use.  */
   sec->used_by_bfd = (struct coff_section_tdata *) vars->data;
   vars->data += sizeof (struct coff_section_tdata);
@@ -686,9 +709,20 @@ static jump_table jtab[] =
   },
 #endif
 
   },
 #endif
 
+#ifdef AMD64MAGIC
+  { AMD64MAGIC,
+    { 0xff, 0x25, 0x00, 0x00, 0x00, 0x00, 0x90, 0x90 },
+    8, 2
+  },
+#endif
+
 #ifdef  MC68MAGIC
 #ifdef  MC68MAGIC
-  { MC68MAGIC, { /* XXX fill me in */ }, 0, 0 },
+  { MC68MAGIC,
+    { /* XXX fill me in */ },
+    0, 0
+  },
 #endif
 #endif
+
 #ifdef  MIPS_ARCH_MAGIC_WINCE
   { MIPS_ARCH_MAGIC_WINCE,
     { 0x00, 0x00, 0x08, 0x3c, 0x00, 0x00, 0x08, 0x8d,
 #ifdef  MIPS_ARCH_MAGIC_WINCE
   { MIPS_ARCH_MAGIC_WINCE,
     { 0x00, 0x00, 0x08, 0x3c, 0x00, 0x00, 0x08, 0x8d,
@@ -728,22 +762,23 @@ static jump_table jtab[] =
 #endif
 
 /* Build a full BFD from the information supplied in a ILF object.  */
 #endif
 
 /* Build a full BFD from the information supplied in a ILF object.  */
+
 static bfd_boolean
 static bfd_boolean
-pe_ILF_build_a_bfd (bfd *           abfd,
+pe_ILF_build_a_bfd (bfd *          abfd,
                    unsigned int    magic,
                    unsigned int    magic,
-                   char *          symbol_name,
-                   char *          source_dll,
+                   char *          symbol_name,
+                   char *          source_dll,
                    unsigned int    ordinal,
                    unsigned int    types)
 {
                    unsigned int    ordinal,
                    unsigned int    types)
 {
-  bfd_byte *               ptr;
-  pe_ILF_vars              vars;
+  bfd_byte *              ptr;
+  pe_ILF_vars             vars;
   struct internal_filehdr  internal_f;
   struct internal_filehdr  internal_f;
-  unsigned int             import_type;
-  unsigned int             import_name_type;
-  asection_ptr             id4, id5, id6 = NULL, text = NULL;
-  coff_symbol_type **      imp_sym;
-  unsigned int             imp_index;
+  unsigned int            import_type;
+  unsigned int            import_name_type;
+  asection_ptr            id4, id5, id6 = NULL, text = NULL;
+  coff_symbol_type **     imp_sym;
+  unsigned int            imp_index;
 
   /* Decode and verify the types field of the ILF structure.  */
   import_type = types & 0x3;
 
   /* Decode and verify the types field of the ILF structure.  */
   import_type = types & 0x3;
@@ -757,12 +792,14 @@ pe_ILF_build_a_bfd (bfd *           abfd,
 
     case IMPORT_CONST:
       /* XXX code yet to be written.  */
 
     case IMPORT_CONST:
       /* XXX code yet to be written.  */
-      _bfd_error_handler (_("%B: Unhandled import type; %x"),
+      /* xgettext:c-format */
+      _bfd_error_handler (_("%pB: unhandled import type; %x"),
                          abfd, import_type);
       return FALSE;
 
     default:
                          abfd, import_type);
       return FALSE;
 
     default:
-      _bfd_error_handler (_("%B: Unrecognised import type; %x"),
+      /* xgettext:c-format */
+      _bfd_error_handler (_("%pB: unrecognized import type; %x"),
                          abfd, import_type);
       return FALSE;
     }
                          abfd, import_type);
       return FALSE;
     }
@@ -776,7 +813,8 @@ pe_ILF_build_a_bfd (bfd *           abfd,
       break;
 
     default:
       break;
 
     default:
-      _bfd_error_handler (_("%B: Unrecognised import name type; %x"),
+      /* xgettext:c-format */
+      _bfd_error_handler (_("%pB: unrecognized import name type; %x"),
                          abfd, import_name_type);
       return FALSE;
     }
                          abfd, import_name_type);
       return FALSE;
     }
@@ -788,15 +826,16 @@ pe_ILF_build_a_bfd (bfd *           abfd,
 
      We are going to construct the contents of the BFD in memory,
      so allocate all the space that we will need right now.  */
 
      We are going to construct the contents of the BFD in memory,
      so allocate all the space that we will need right now.  */
-  ptr = bfd_zalloc (abfd, (bfd_size_type) ILF_DATA_SIZE);
-  if (ptr == NULL)
+  vars.bim
+    = (struct bfd_in_memory *) bfd_malloc ((bfd_size_type) sizeof (*vars.bim));
+  if (vars.bim == NULL)
     return FALSE;
 
     return FALSE;
 
-  /* Create a bfd_in_memory structure.  */
-  vars.bim = (struct bfd_in_memory *) ptr;
+  ptr = (bfd_byte *) bfd_zmalloc ((bfd_size_type) ILF_DATA_SIZE);
   vars.bim->buffer = ptr;
   vars.bim->size   = ILF_DATA_SIZE;
   vars.bim->buffer = ptr;
   vars.bim->size   = ILF_DATA_SIZE;
-  ptr += sizeof (* vars.bim);
+  if (ptr == NULL)
+    goto error_return;
 
   /* Initialise the pointers to regions of the memory and the
      other contents of the pe_ILF_vars structure as well.  */
 
   /* Initialise the pointers to regions of the memory and the
      other contents of the pe_ILF_vars structure as well.  */
@@ -835,6 +874,24 @@ pe_ILF_build_a_bfd (bfd *           abfd,
 
   /* The remaining space in bim->buffer is used
      by the pe_ILF_make_a_section() function.  */
 
   /* The remaining space in bim->buffer is used
      by the pe_ILF_make_a_section() function.  */
+# if (GCC_VERSION >= 3000)
+  /* PR 18758: Make sure that the data area is sufficiently aligned for
+     pointers on the host.  __alignof__ is a gcc extension, hence the test
+     above.  For other compilers we will have to assume that the alignment is
+     unimportant, or else extra code can be added here and in
+     pe_ILF_make_a_section.
+
+     Note - we cannot test 'ptr' directly as it is illegal to perform binary
+     arithmetic on pointers, but we know that the strings section is the only
+     one that might end on an unaligned boundary.  */
+  {
+    unsigned int alignment = __alignof__ (char *);
+
+    if (SIZEOF_ILF_STRINGS & (alignment - 1))
+      ptr += alignment - (SIZEOF_ILF_STRINGS & (alignment - 1));
+  }
+#endif
+
   vars.data = ptr;
   vars.abfd = abfd;
   vars.sec_index = 0;
   vars.data = ptr;
   vars.abfd = abfd;
   vars.sec_index = 0;
@@ -850,78 +907,71 @@ pe_ILF_build_a_bfd (bfd *           abfd,
   id4 = pe_ILF_make_a_section (& vars, ".idata$4", SIZEOF_IDATA4, 0);
   id5 = pe_ILF_make_a_section (& vars, ".idata$5", SIZEOF_IDATA5, 0);
   if (id4 == NULL || id5 == NULL)
   id4 = pe_ILF_make_a_section (& vars, ".idata$4", SIZEOF_IDATA4, 0);
   id5 = pe_ILF_make_a_section (& vars, ".idata$5", SIZEOF_IDATA5, 0);
   if (id4 == NULL || id5 == NULL)
-    return FALSE;
+    goto error_return;
 
   /* Fill in the contents of these sections.  */
   if (import_name_type == IMPORT_ORDINAL)
     {
       if (ordinal == 0)
 
   /* Fill in the contents of these sections.  */
   if (import_name_type == IMPORT_ORDINAL)
     {
       if (ordinal == 0)
-       /* XXX - treat as IMPORT_NAME ??? */
-       abort ();
-
+       /* See PR 20907 for a reproducer.  */
+       goto error_return;
+
+#ifdef COFF_WITH_pex64
+      ((unsigned int *) id4->contents)[0] = ordinal;
+      ((unsigned int *) id4->contents)[1] = 0x80000000;
+      ((unsigned int *) id5->contents)[0] = ordinal;
+      ((unsigned int *) id5->contents)[1] = 0x80000000;
+#else
       * (unsigned int *) id4->contents = ordinal | 0x80000000;
       * (unsigned int *) id5->contents = ordinal | 0x80000000;
       * (unsigned int *) id4->contents = ordinal | 0x80000000;
       * (unsigned int *) id5->contents = ordinal | 0x80000000;
+#endif
     }
   else
     {
       char * symbol;
     }
   else
     {
       char * symbol;
+      unsigned int len;
 
       /* Create .idata$6 - the Hint Name Table.  */
       id6 = pe_ILF_make_a_section (& vars, ".idata$6", SIZEOF_IDATA6, 0);
       if (id6 == NULL)
 
       /* Create .idata$6 - the Hint Name Table.  */
       id6 = pe_ILF_make_a_section (& vars, ".idata$6", SIZEOF_IDATA6, 0);
       if (id6 == NULL)
-       return FALSE;
+       goto error_return;
 
       /* If necessary, trim the import symbol name.  */
       symbol = symbol_name;
 
 
       /* If necessary, trim the import symbol name.  */
       symbol = symbol_name;
 
+      /* As used by MS compiler, '_', '@', and '?' are alternative
+        forms of USER_LABEL_PREFIX, with '?' for c++ mangled names,
+        '@' used for fastcall (in C),  '_' everywhere else.  Only one
+        of these is used for a symbol.  We strip this leading char for
+        IMPORT_NAME_NOPREFIX and IMPORT_NAME_UNDECORATE as per the
+        PE COFF 6.0 spec (section 8.3, Import Name Type).  */
+
       if (import_name_type != IMPORT_NAME)
        {
       if (import_name_type != IMPORT_NAME)
        {
-         bfd_boolean skipped_leading_underscore = FALSE;
-         bfd_boolean skipped_leading_at = FALSE;
-         bfd_boolean skipped_leading_question_mark = FALSE;
-         bfd_boolean check_again;
-         
-         /* Skip any prefix in symbol_name.  */
-         -- symbol;
-         do
-           {
-             check_again = FALSE;
-             ++ symbol;
+         char c = symbol[0];
 
 
-             switch (*symbol)
-               {
-               case '@':
-                 if (! skipped_leading_at)
-                   check_again = skipped_leading_at = TRUE;
-                 break;
-               case '?':
-                 if (! skipped_leading_question_mark)
-                   check_again = skipped_leading_question_mark = TRUE;
-                 break;
-               case '_':
-                 if (! skipped_leading_underscore)
-                   check_again = skipped_leading_underscore = TRUE;
-                 break;
-               default:
-                 break;
-               }
-           }
-         while (check_again);
+         /* Check that we don't remove for targets with empty
+            USER_LABEL_PREFIX the leading underscore.  */
+         if ((c == '_' && abfd->xvec->symbol_leading_char != 0)
+             || c == '@' || c == '?')
+           symbol++;
        }
        }
-      
+
+      len = strlen (symbol);
       if (import_name_type == IMPORT_NAME_UNDECORATE)
        {
       if (import_name_type == IMPORT_NAME_UNDECORATE)
        {
-         /* Truncate at the first '@'  */
-         while (* symbol != 0 && * symbol != '@')
-           symbol ++;
+         /* Truncate at the first '@'.  */
+         char *at = strchr (symbol, '@');
 
 
-         * symbol = 0;
+         if (at != NULL)
+           len = at - symbol;
        }
 
       id6->contents[0] = ordinal & 0xff;
       id6->contents[1] = ordinal >> 8;
 
        }
 
       id6->contents[0] = ordinal & 0xff;
       id6->contents[1] = ordinal >> 8;
 
-      strcpy ((char *) id6->contents + 2, symbol);
+      memcpy ((char *) id6->contents + 2, symbol, len);
+      id6->contents[len + 2] = '\0';
     }
 
   if (import_name_type != IMPORT_ORDINAL)
     }
 
   if (import_name_type != IMPORT_ORDINAL)
@@ -933,13 +983,19 @@ pe_ILF_build_a_bfd (bfd *           abfd,
       pe_ILF_save_relocs (&vars, id5);
     }
 
       pe_ILF_save_relocs (&vars, id5);
     }
 
+  /* Create an import symbol.  */
+  pe_ILF_make_a_symbol (& vars, "__imp_", symbol_name, id5, 0);
+  imp_sym   = vars.sym_ptr_ptr - 1;
+  imp_index = vars.sym_index - 1;
+
   /* Create extra sections depending upon the type of import we are dealing with.  */
   switch (import_type)
     {
       int i;
 
     case IMPORT_CODE:
   /* Create extra sections depending upon the type of import we are dealing with.  */
   switch (import_type)
     {
       int i;
 
     case IMPORT_CODE:
-      /* Create a .text section.
+      /* CODE functions are special, in that they get a trampoline that
+        jumps to the main import symbol.  Create a .text section to hold it.
         First we need to look up its contents in the jump table.  */
       for (i = NUM_ENTRIES (jtab); i--;)
        {
         First we need to look up its contents in the jump table.  */
       for (i = NUM_ENTRIES (jtab); i--;)
        {
@@ -955,16 +1011,11 @@ pe_ILF_build_a_bfd (bfd *           abfd,
       /* Create the .text section.  */
       text = pe_ILF_make_a_section (& vars, ".text", jtab[i].size, SEC_CODE);
       if (text == NULL)
       /* Create the .text section.  */
       text = pe_ILF_make_a_section (& vars, ".text", jtab[i].size, SEC_CODE);
       if (text == NULL)
-       return FALSE;
+       goto error_return;
 
       /* Copy in the jump code.  */
       memcpy (text->contents, jtab[i].data, jtab[i].size);
 
 
       /* Copy in the jump code.  */
       memcpy (text->contents, jtab[i].data, jtab[i].size);
 
-      /* Create an import symbol.  */
-      pe_ILF_make_a_symbol (& vars, "__imp_", symbol_name, id5, 0);
-      imp_sym   = vars.sym_ptr_ptr - 1;
-      imp_index = vars.sym_index - 1;
-
       /* Create a reloc for the data in the text section.  */
 #ifdef MIPS_ARCH_MAGIC_WINCE
       if (magic == MIPS_ARCH_MAGIC_WINCE)
       /* Create a reloc for the data in the text section.  */
 #ifdef MIPS_ARCH_MAGIC_WINCE
       if (magic == MIPS_ARCH_MAGIC_WINCE)
@@ -978,6 +1029,15 @@ pe_ILF_build_a_bfd (bfd *           abfd,
                                      imp_index);
        }
       else
                                      imp_index);
        }
       else
+#endif
+#ifdef AMD64MAGIC
+      if (magic == AMD64MAGIC)
+       {
+         pe_ILF_make_a_symbol_reloc (&vars, (bfd_vma) jtab[i].offset,
+                                     BFD_RELOC_32_PCREL, (asymbol **) imp_sym,
+                                     imp_index);
+       }
+      else
 #endif
        pe_ILF_make_a_symbol_reloc (&vars, (bfd_vma) jtab[i].offset,
                                    BFD_RELOC_32, (asymbol **) imp_sym,
 #endif
        pe_ILF_make_a_symbol_reloc (&vars, (bfd_vma) jtab[i].offset,
                                    BFD_RELOC_32, (asymbol **) imp_sym,
@@ -1004,10 +1064,10 @@ pe_ILF_build_a_bfd (bfd *           abfd,
 
   if (   ! bfd_set_start_address (abfd, (bfd_vma) 0)
       || ! bfd_coff_set_arch_mach_hook (abfd, & internal_f))
 
   if (   ! bfd_set_start_address (abfd, (bfd_vma) 0)
       || ! bfd_coff_set_arch_mach_hook (abfd, & internal_f))
-    return FALSE;
+    goto error_return;
 
 
-  if (bfd_coff_mkobject_hook (abfd, (PTR) & internal_f, NULL) == NULL)
-    return FALSE;
+  if (bfd_coff_mkobject_hook (abfd, (void *) & internal_f, NULL) == NULL)
+    goto error_return;
 
   coff_data (abfd)->pe = 1;
 #ifdef THUMBPEMAGIC
 
   coff_data (abfd)->pe = 1;
 #ifdef THUMBPEMAGIC
@@ -1019,9 +1079,11 @@ pe_ILF_build_a_bfd (bfd *           abfd,
   /* Switch from file contents to memory contents.  */
   bfd_cache_close (abfd);
 
   /* Switch from file contents to memory contents.  */
   bfd_cache_close (abfd);
 
-  abfd->iostream = (PTR) vars.bim;
+  abfd->iostream = (void *) vars.bim;
   abfd->flags |= BFD_IN_MEMORY /* | HAS_LOCALS */;
   abfd->flags |= BFD_IN_MEMORY /* | HAS_LOCALS */;
+  abfd->iovec = &_bfd_memory_iovec;
   abfd->where = 0;
   abfd->where = 0;
+  abfd->origin = 0;
   obj_sym_filepos (abfd) = 0;
 
   /* Now create a symbol describing the imported value.  */
   obj_sym_filepos (abfd) = 0;
 
   /* Now create a symbol describing the imported value.  */
@@ -1031,14 +1093,6 @@ pe_ILF_build_a_bfd (bfd *           abfd,
       pe_ILF_make_a_symbol (& vars, "", symbol_name, text,
                            BSF_NOT_AT_END | BSF_FUNCTION);
 
       pe_ILF_make_a_symbol (& vars, "", symbol_name, text,
                            BSF_NOT_AT_END | BSF_FUNCTION);
 
-      /* Create an import symbol for the DLL, without the
-       .dll suffix.  */
-      ptr = (bfd_byte *) strrchr (source_dll, '.');
-      if (ptr)
-       * ptr = 0;
-      pe_ILF_make_a_symbol (& vars, "__IMPORT_DESCRIPTOR_", source_dll, NULL, 0);
-      if (ptr)
-       * ptr = '.';
       break;
 
     case IMPORT_DATA:
       break;
 
     case IMPORT_DATA:
@@ -1050,14 +1104,22 @@ pe_ILF_build_a_bfd (bfd *           abfd,
       abort ();
     }
 
       abort ();
     }
 
+  /* Create an import symbol for the DLL, without the .dll suffix.  */
+  ptr = (bfd_byte *) strrchr (source_dll, '.');
+  if (ptr)
+    * ptr = 0;
+  pe_ILF_make_a_symbol (& vars, "__IMPORT_DESCRIPTOR_", source_dll, NULL, 0);
+  if (ptr)
+    * ptr = '.';
+
   /* Point the bfd at the symbol table.  */
   obj_symbols (abfd) = vars.sym_cache;
   /* Point the bfd at the symbol table.  */
   obj_symbols (abfd) = vars.sym_cache;
-  bfd_get_symcount (abfd) = vars.sym_index;
+  abfd->symcount = vars.sym_index;
 
   obj_raw_syments (abfd) = vars.native_syms;
   obj_raw_syment_count (abfd) = vars.sym_index;
 
 
   obj_raw_syments (abfd) = vars.native_syms;
   obj_raw_syment_count (abfd) = vars.sym_index;
 
-  obj_coff_external_syms (abfd) = (PTR) vars.esym_table;
+  obj_coff_external_syms (abfd) = (void *) vars.esym_table;
   obj_coff_keep_syms (abfd) = TRUE;
 
   obj_convert (abfd) = vars.sym_table;
   obj_coff_keep_syms (abfd) = TRUE;
 
   obj_convert (abfd) = vars.sym_table;
@@ -1069,34 +1131,37 @@ pe_ILF_build_a_bfd (bfd *           abfd,
   abfd->flags |= HAS_SYMS;
 
   return TRUE;
   abfd->flags |= HAS_SYMS;
 
   return TRUE;
+
+ error_return:
+  if (vars.bim->buffer != NULL)
+    free (vars.bim->buffer);
+  free (vars.bim);
+  return FALSE;
 }
 
 /* We have detected a Image Library Format archive element.
    Decode the element and return the appropriate target.  */
 }
 
 /* We have detected a Image Library Format archive element.
    Decode the element and return the appropriate target.  */
+
 static const bfd_target *
 pe_ILF_object_p (bfd * abfd)
 {
 static const bfd_target *
 pe_ILF_object_p (bfd * abfd)
 {
-  bfd_byte        buffer[16];
-  bfd_byte *      ptr;
-  char *          symbol_name;
-  char *          source_dll;
-  unsigned int    machine;
-  bfd_size_type   size;
-  unsigned int    ordinal;
-  unsigned int    types;
-  unsigned int    magic;
-
-  /* Upon entry the first four buyes of the ILF header have
+  bfd_byte       buffer[14];
+  bfd_byte *     ptr;
+  char *         symbol_name;
+  char *         source_dll;
+  unsigned int   machine;
+  bfd_size_type          size;
+  unsigned int   ordinal;
+  unsigned int   types;
+  unsigned int   magic;
+
+  /* Upon entry the first six bytes of the ILF header have
       already been read.  Now read the rest of the header.  */
       already been read.  Now read the rest of the header.  */
-  if (bfd_bread (buffer, (bfd_size_type) 16, abfd) != 16)
+  if (bfd_bread (buffer, (bfd_size_type) 14, abfd) != 14)
     return NULL;
 
   ptr = buffer;
 
     return NULL;
 
   ptr = buffer;
 
-  /*  We do not bother to check the version number.
-      version = H_GET_16 (abfd, ptr);  */
-  ptr += 2;
-
   machine = H_GET_16 (abfd, ptr);
   ptr += 2;
 
   machine = H_GET_16 (abfd, ptr);
   ptr += 2;
 
@@ -1117,9 +1182,9 @@ pe_ILF_object_p (bfd * abfd)
 #endif
       break;
 
 #endif
       break;
 
-    case IMAGE_FILE_MACHINE_M68K:
-#ifdef MC68AGIC
-      magic = MC68MAGIC;
+    case IMAGE_FILE_MACHINE_AMD64:
+#ifdef AMD64MAGIC
+      magic = AMD64MAGIC;
 #endif
       break;
 
 #endif
       break;
 
@@ -1163,7 +1228,8 @@ pe_ILF_object_p (bfd * abfd)
       /* We no longer support PowerPC.  */
     default:
       _bfd_error_handler
       /* We no longer support PowerPC.  */
     default:
       _bfd_error_handler
-       (_("%B: Unrecognised machine type (0x%x)"
+       /* xgettext:c-format */
+       (_("%pB: unrecognised machine type (0x%x)"
           " in Import Library Format archive"),
         abfd, machine);
       bfd_set_error (bfd_error_malformed_archive);
           " in Import Library Format archive"),
         abfd, machine);
       bfd_set_error (bfd_error_malformed_archive);
@@ -1175,7 +1241,8 @@ pe_ILF_object_p (bfd * abfd)
   if (magic == 0)
     {
       _bfd_error_handler
   if (magic == 0)
     {
       _bfd_error_handler
-       (_("%B: Recognised but unhandled machine type (0x%x)"
+       /* xgettext:c-format */
+       (_("%pB: recognised but unhandled machine type (0x%x)"
           " in Import Library Format archive"),
         abfd, machine);
       bfd_set_error (bfd_error_wrong_format);
           " in Import Library Format archive"),
         abfd, machine);
       bfd_set_error (bfd_error_wrong_format);
@@ -1193,7 +1260,7 @@ pe_ILF_object_p (bfd * abfd)
   if (size == 0)
     {
       _bfd_error_handler
   if (size == 0)
     {
       _bfd_error_handler
-       (_("%B: size field is zero in Import Library Format header"), abfd);
+       (_("%pB: size field is zero in Import Library Format header"), abfd);
       bfd_set_error (bfd_error_malformed_archive);
 
       return NULL;
       bfd_set_error (bfd_error_malformed_archive);
 
       return NULL;
@@ -1206,7 +1273,7 @@ pe_ILF_object_p (bfd * abfd)
   /* ptr += 2; */
 
   /* Now read in the two strings that follow.  */
   /* ptr += 2; */
 
   /* Now read in the two strings that follow.  */
-  ptr = bfd_alloc (abfd, size);
+  ptr = (bfd_byte *) bfd_alloc (abfd, size);
   if (ptr == NULL)
     return NULL;
 
   if (ptr == NULL)
     return NULL;
 
@@ -1217,14 +1284,15 @@ pe_ILF_object_p (bfd * abfd)
     }
 
   symbol_name = (char *) ptr;
     }
 
   symbol_name = (char *) ptr;
-  source_dll  = symbol_name + strlen (symbol_name) + 1;
+  /* See PR 20905 for an example of where the strnlen is necessary.  */
+  source_dll  = symbol_name + strnlen (symbol_name, size - 1) + 1;
 
   /* Verify that the strings are null terminated.  */
   if (ptr[size - 1] != 0
       || (bfd_size_type) ((bfd_byte *) source_dll - ptr) >= size)
     {
       _bfd_error_handler
 
   /* Verify that the strings are null terminated.  */
   if (ptr[size - 1] != 0
       || (bfd_size_type) ((bfd_byte *) source_dll - ptr) >= size)
     {
       _bfd_error_handler
-       (_("%B: string not null terminated in ILF object file."), abfd);
+       (_("%pB: string not null terminated in ILF object file"), abfd);
       bfd_set_error (bfd_error_malformed_archive);
       bfd_release (abfd, ptr);
       return NULL;
       bfd_set_error (bfd_error_malformed_archive);
       bfd_release (abfd, ptr);
       return NULL;
@@ -1241,24 +1309,120 @@ pe_ILF_object_p (bfd * abfd)
   return abfd->xvec;
 }
 
   return abfd->xvec;
 }
 
+static void
+pe_bfd_read_buildid (bfd *abfd)
+{
+  pe_data_type *pe = pe_data (abfd);
+  struct internal_extra_pe_aouthdr *extra = &pe->pe_opthdr;
+  asection *section;
+  bfd_byte *data = 0;
+  bfd_size_type dataoff;
+  unsigned int i;
+  bfd_vma addr = extra->DataDirectory[PE_DEBUG_DATA].VirtualAddress;
+  bfd_size_type size = extra->DataDirectory[PE_DEBUG_DATA].Size;
+
+  if (size == 0)
+    return;
+
+  addr += extra->ImageBase;
+
+  /* Search for the section containing the DebugDirectory.  */
+  for (section = abfd->sections; section != NULL; section = section->next)
+    {
+      if ((addr >= section->vma) && (addr < (section->vma + section->size)))
+       break;
+    }
+
+  if (section == NULL)
+    return;
+
+  if (!(section->flags & SEC_HAS_CONTENTS))
+    return;
+
+  dataoff = addr - section->vma;
+
+  /* PR 20605 and 22373: Make sure that the data is really there.
+     Note - since we are dealing with unsigned quantities we have
+     to be careful to check for potential overflows.  */
+  if (dataoff >= section->size
+      || size > section->size - dataoff)
+    {
+      _bfd_error_handler
+       (_("%pB: error: debug data ends beyond end of debug directory"),
+        abfd);
+      return;
+    }
+
+  /* Read the whole section. */
+  if (!bfd_malloc_and_get_section (abfd, section, &data))
+    {
+      if (data != NULL)
+       free (data);
+      return;
+    }
+
+  /* Search for a CodeView entry in the DebugDirectory */
+  for (i = 0; i < size / sizeof (struct external_IMAGE_DEBUG_DIRECTORY); i++)
+    {
+      struct external_IMAGE_DEBUG_DIRECTORY *ext
+       = &((struct external_IMAGE_DEBUG_DIRECTORY *)(data + dataoff))[i];
+      struct internal_IMAGE_DEBUG_DIRECTORY idd;
+
+      _bfd_XXi_swap_debugdir_in (abfd, ext, &idd);
+
+      if (idd.Type == PE_IMAGE_DEBUG_TYPE_CODEVIEW)
+       {
+         char buffer[256 + 1];
+         CODEVIEW_INFO *cvinfo = (CODEVIEW_INFO *) buffer;
+
+         /*
+           The debug entry doesn't have to have to be in a section, in which
+           case AddressOfRawData is 0, so always use PointerToRawData.
+         */
+         if (_bfd_XXi_slurp_codeview_record (abfd,
+                                             (file_ptr) idd.PointerToRawData,
+                                             idd.SizeOfData, cvinfo))
+           {
+             struct bfd_build_id* build_id = bfd_alloc (abfd,
+                        sizeof (struct bfd_build_id) + cvinfo->SignatureLength);
+             if (build_id)
+               {
+                 build_id->size = cvinfo->SignatureLength;
+                 memcpy(build_id->data,  cvinfo->Signature,
+                        cvinfo->SignatureLength);
+                 abfd->build_id = build_id;
+               }
+           }
+         break;
+       }
+    }
+}
+
 static const bfd_target *
 pe_bfd_object_p (bfd * abfd)
 {
 static const bfd_target *
 pe_bfd_object_p (bfd * abfd)
 {
-  bfd_byte buffer[4];
-  struct external_PEI_DOS_hdr dos_hdr;
+  bfd_byte buffer[6];
+  struct external_DOS_hdr dos_hdr;
   struct external_PEI_IMAGE_hdr image_hdr;
   struct external_PEI_IMAGE_hdr image_hdr;
+  struct internal_filehdr internal_f;
+  struct internal_aouthdr internal_a;
+  file_ptr opt_hdr_size;
   file_ptr offset;
   file_ptr offset;
+  const bfd_target *result;
 
   /* Detect if this a Microsoft Import Library Format element.  */
 
   /* Detect if this a Microsoft Import Library Format element.  */
+  /* First read the beginning of the header.  */
   if (bfd_seek (abfd, (file_ptr) 0, SEEK_SET) != 0
   if (bfd_seek (abfd, (file_ptr) 0, SEEK_SET) != 0
-      || bfd_bread (buffer, (bfd_size_type) 4, abfd) != 4)
+      || bfd_bread (buffer, (bfd_size_type) 6, abfd) != 6)
     {
       if (bfd_get_error () != bfd_error_system_call)
        bfd_set_error (bfd_error_wrong_format);
       return NULL;
     }
 
     {
       if (bfd_get_error () != bfd_error_system_call)
        bfd_set_error (bfd_error_wrong_format);
       return NULL;
     }
 
-  if (H_GET_32 (abfd, buffer) == 0xffff0000)
+  /* Then check the magic and the version (only 0 is supported).  */
+  if (H_GET_32 (abfd, buffer) == 0xffff0000
+      && H_GET_16 (abfd, buffer + 4) == 0)
     return pe_ILF_object_p (abfd);
 
   if (bfd_seek (abfd, (file_ptr) 0, SEEK_SET) != 0
     return pe_ILF_object_p (abfd);
 
   if (bfd_seek (abfd, (file_ptr) 0, SEEK_SET) != 0
@@ -1272,7 +1436,7 @@ pe_bfd_object_p (bfd * abfd)
 
   /* There are really two magic numbers involved; the magic number
      that says this is a NT executable (PEI) and the magic number that
 
   /* There are really two magic numbers involved; the magic number
      that says this is a NT executable (PEI) and the magic number that
-     determines the architecture.  The former is DOSMAGIC, stored in
+     determines the architecture.  The former is IMAGE_DOS_SIGNATURE, stored in
      the e_magic field.  The latter is stored in the f_magic field.
      If the NT magic number isn't valid, the architecture magic number
      could be mimicked by some other field (specifically, the number
      the e_magic field.  The latter is stored in the f_magic field.
      If the NT magic number isn't valid, the architecture magic number
      could be mimicked by some other field (specifically, the number
@@ -1280,7 +1444,7 @@ pe_bfd_object_p (bfd * abfd)
      correctly for a PEI file, check the e_magic number here, and, if
      it doesn't match, clobber the f_magic number so that we don't get
      a false match.  */
      correctly for a PEI file, check the e_magic number here, and, if
      it doesn't match, clobber the f_magic number so that we don't get
      a false match.  */
-  if (H_GET_16 (abfd, dos_hdr.e_magic) != DOSMAGIC)
+  if (H_GET_16 (abfd, dos_hdr.e_magic) != IMAGE_DOS_SIGNATURE)
     {
       bfd_set_error (bfd_error_wrong_format);
       return NULL;
     {
       bfd_set_error (bfd_error_wrong_format);
       return NULL;
@@ -1302,17 +1466,59 @@ pe_bfd_object_p (bfd * abfd)
       return NULL;
     }
 
       return NULL;
     }
 
-  /* Here is the hack.  coff_object_p wants to read filhsz bytes to
-     pick up the COFF header for PE, see "struct external_PEI_filehdr"
-     in include/coff/pe.h.  We adjust so that that will work. */
-  if (bfd_seek (abfd, (file_ptr) (offset - sizeof (dos_hdr)), SEEK_SET) != 0)
+  /* Swap file header, so that we get the location for calling
+     real_object_p.  */
+  bfd_coff_swap_filehdr_in (abfd, &image_hdr, &internal_f);
+
+  if (! bfd_coff_bad_format_hook (abfd, &internal_f)
+      || internal_f.f_opthdr > bfd_coff_aoutsz (abfd))
     {
     {
-      if (bfd_get_error () != bfd_error_system_call)
-       bfd_set_error (bfd_error_wrong_format);
+      bfd_set_error (bfd_error_wrong_format);
       return NULL;
     }
 
       return NULL;
     }
 
-  return coff_object_p (abfd);
+  memcpy (internal_f.pe.dos_message, dos_hdr.dos_message,
+         sizeof (internal_f.pe.dos_message));
+
+  /* Read the optional header, which has variable size.  */
+  opt_hdr_size = internal_f.f_opthdr;
+
+  if (opt_hdr_size != 0)
+    {
+      bfd_size_type amt = opt_hdr_size;
+      void * opthdr;
+
+      /* PR 17521 file: 230-131433-0.004.  */
+      if (amt < sizeof (PEAOUTHDR))
+       amt = sizeof (PEAOUTHDR);
+
+      opthdr = bfd_zalloc (abfd, amt);
+      if (opthdr == NULL)
+       return NULL;
+      if (bfd_bread (opthdr, opt_hdr_size, abfd)
+         != (bfd_size_type) opt_hdr_size)
+       return NULL;
+
+      bfd_set_error (bfd_error_no_error);
+      bfd_coff_swap_aouthdr_in (abfd, opthdr, & internal_a);
+      if (bfd_get_error () != bfd_error_no_error)
+       return NULL;
+    }
+
+
+  result = coff_real_object_p (abfd, internal_f.f_nscns, &internal_f,
+                              (opt_hdr_size != 0
+                               ? &internal_a
+                               : (struct internal_aouthdr *) NULL));
+
+
+  if (result)
+    {
+      /* Now the whole header has been processed, see if there is a build-id */
+      pe_bfd_read_buildid(abfd);
+    }
+
+  return result;
 }
 
 #define coff_object_p pe_bfd_object_p
 }
 
 #define coff_object_p pe_bfd_object_p
This page took 0.040917 seconds and 4 git commands to generate.