Initialize count_ field, tweak parameters testing.
[deliverable/binutils-gdb.git] / bfd / peicode.h
index fc9e4d6b02bcf877c5efa3084f0a95d0b3b5f72f..9a512a7d6d0c3daeab15f7bcaa9e362826f6e5fc 100644 (file)
@@ -1,13 +1,13 @@
 /* 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.
+   2005, 2006, 2007 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
-   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,
@@ -17,7 +17,9 @@
 
    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
@@ -55,8 +57,7 @@
 
 #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
@@ -64,11 +65,10 @@ static bfd_boolean (*pe_saved_coff_bfd_print_private_bfd_data)
 #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
 
-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
@@ -76,21 +76,12 @@ static bfd_boolean (*pe_saved_coff_bfd_copy_private_bfd_data)
 #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_mkobject      pe_mkobject
 #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;
@@ -131,66 +122,53 @@ typedef struct
 }
 pe_ILF_vars;
 #endif /* COFF_IMAGE_WITH_PE */
-
-/**********************************************************************/
-
+\f
 #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_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_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
-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_16 (abfd, reloc_src->r_type, reloc_dst->r_type);
 
-#ifdef SWAP_OUT_RELOC_OFFSET
+#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 */
 
 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;
-  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
@@ -206,27 +184,29 @@ coff_swap_filehdr_in (abfd, src, dst)
 
 #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
-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;
 
-  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_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
@@ -243,7 +223,10 @@ coff_swap_scnhdr_in (abfd, ext, in)
   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;
+#endif
     }
 
 #ifndef COFF_NO_HACK_SCNHDR_SIZE
@@ -255,20 +238,16 @@ coff_swap_scnhdr_in (abfd, ext, in)
       && (((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.  */
-    }
+  /* 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
-pe_mkobject (abfd)
-     bfd * abfd;
+pe_mkobject (bfd * abfd)
 {
   pe_data_type *pe;
   bfd_size_type amt = sizeof (pe_data_type);
@@ -296,11 +275,11 @@ pe_mkobject (abfd)
 }
 
 /* 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;
@@ -337,7 +316,7 @@ pe_mkobject_hook (abfd, filehdr, 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
@@ -345,35 +324,30 @@ pe_mkobject_hook (abfd, filehdr, aouthdr)
     coff_data (abfd) ->flags = 0;
 #endif
 
-  return (PTR) pe;
+  return (void *) pe;
 }
 
 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;
 
-  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
-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()
@@ -428,20 +402,28 @@ pe_bfd_copy_private_bfd_data (ibfd, obfd)
 #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_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)
+
+/* 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)
+#endif
+
 #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))
@@ -465,12 +447,13 @@ pe_bfd_copy_private_bfd_data (ibfd, obfd)
     + MAX_TEXT_SECTION_SIZE
 
 /* Create an empty relocation against the given symbol.  */
+
 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;
@@ -493,6 +476,7 @@ pe_ILF_make_a_symbol_reloc (pe_ILF_vars *                 vars,
 }
 
 /* Create an empty relocation against the given section.  */
+
 static void
 pe_ILF_make_a_reloc (pe_ILF_vars *             vars,
                     bfd_vma                   address,
@@ -504,6 +488,7 @@ pe_ILF_make_a_reloc (pe_ILF_vars *             vars,
 }
 
 /* Move the queued relocs into the given section.  */
+
 static void
 pe_ILF_save_relocs (pe_ILF_vars * vars,
                    asection_ptr  sec)
@@ -528,6 +513,7 @@ pe_ILF_save_relocs (pe_ILF_vars * vars,
 }
 
 /* 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,
@@ -581,7 +567,7 @@ pe_ILF_make_a_symbol (pe_ILF_vars *  vars,
   /* 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._n_n._n_offset = (bfd_hostptr_t) sym;
 
   sym->symbol.the_bfd = vars->abfd;
   sym->symbol.name    = vars->string_ptr;
@@ -605,6 +591,7 @@ pe_ILF_make_a_symbol (pe_ILF_vars *  vars,
 }
 
 /* Create a section.  */
+
 static asection_ptr
 pe_ILF_make_a_section (pe_ILF_vars * vars,
                       const char *  name,
@@ -686,9 +673,20 @@ static jump_table jtab[] =
   },
 #endif
 
+#ifdef AMD64MAGIC
+  { AMD64MAGIC,
+    { 0xff, 0x25, 0x00, 0x00, 0x00, 0x00, 0x90, 0x90 },
+    8, 2
+  },
+#endif
+
 #ifdef  MC68MAGIC
-  { MC68MAGIC, { /* XXX fill me in */ }, 0, 0 },
+  { MC68MAGIC,
+    { /* XXX fill me in */ },
+    0, 0
+  },
 #endif
+
 #ifdef  MIPS_ARCH_MAGIC_WINCE
   { MIPS_ARCH_MAGIC_WINCE,
     { 0x00, 0x00, 0x08, 0x3c, 0x00, 0x00, 0x08, 0x8d,
@@ -728,6 +726,7 @@ static jump_table jtab[] =
 #endif
 
 /* Build a full BFD from the information supplied in a ILF object.  */
+
 static bfd_boolean
 pe_ILF_build_a_bfd (bfd *           abfd,
                    unsigned int    magic,
@@ -859,8 +858,15 @@ pe_ILF_build_a_bfd (bfd *           abfd,
        /* XXX - treat as IMPORT_NAME ??? */
        abort ();
 
+#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;
+#endif
     }
   else
     {
@@ -988,7 +994,7 @@ pe_ILF_build_a_bfd (bfd *           abfd,
       || ! bfd_coff_set_arch_mach_hook (abfd, & internal_f))
     return FALSE;
 
-  if (bfd_coff_mkobject_hook (abfd, (PTR) & internal_f, NULL) == NULL)
+  if (bfd_coff_mkobject_hook (abfd, (void *) & internal_f, NULL) == NULL)
     return FALSE;
 
   coff_data (abfd)->pe = 1;
@@ -1001,7 +1007,7 @@ pe_ILF_build_a_bfd (bfd *           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->where = 0;
   obj_sym_filepos (abfd) = 0;
@@ -1039,7 +1045,7 @@ pe_ILF_build_a_bfd (bfd *           abfd,
   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;
@@ -1055,6 +1061,7 @@ pe_ILF_build_a_bfd (bfd *           abfd,
 
 /* 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)
 {
@@ -1099,6 +1106,12 @@ pe_ILF_object_p (bfd * abfd)
 #endif
       break;
 
+    case IMAGE_FILE_MACHINE_AMD64:
+#ifdef AMD64MAGIC
+      magic = AMD64MAGIC;
+#endif
+      break;
+
     case IMAGE_FILE_MACHINE_M68K:
 #ifdef MC68AGIC
       magic = MC68MAGIC;
@@ -1223,6 +1236,25 @@ pe_ILF_object_p (bfd * abfd)
   return abfd->xvec;
 }
 
+enum arch_type
+{
+  arch_type_unknown,
+  arch_type_i386,
+  arch_type_x86_64
+};
+
+static enum arch_type
+pe_arch (const char *arch)
+{
+  if (strcmp (arch, "i386") == 0 || strcmp (arch, "ia32") == 0)
+    return arch_type_i386;
+
+  if (strcmp (arch, "x86_64") == 0 || strcmp (arch, "x86-64") == 0)
+    return arch_type_x86_64;
+
+  return arch_type_unknown;
+}
+
 static const bfd_target *
 pe_bfd_object_p (bfd * abfd)
 {
@@ -1230,6 +1262,7 @@ pe_bfd_object_p (bfd * abfd)
   struct external_PEI_DOS_hdr dos_hdr;
   struct external_PEI_IMAGE_hdr image_hdr;
   file_ptr offset;
+  const bfd_target *target;
 
   /* Detect if this a Microsoft Import Library Format element.  */
   if (bfd_seek (abfd, (file_ptr) 0, SEEK_SET) != 0
@@ -1294,7 +1327,64 @@ pe_bfd_object_p (bfd * abfd)
       return NULL;
     }
 
-  return coff_object_p (abfd);
+  target = coff_object_p (abfd);
+  if (target)
+    {
+      pe_data_type *pe = pe_data (abfd);
+      struct internal_extra_pe_aouthdr *i = &pe->pe_opthdr;
+      bfd_boolean efi = i->Subsystem == IMAGE_SUBSYSTEM_EFI_APPLICATION;
+      enum arch_type arch;
+      const bfd_target * const *target_ptr;
+
+      /* Get the machine.  */
+      if (bfd_target_efi_p (abfd->xvec))
+       arch = pe_arch (bfd_target_efi_arch (abfd->xvec));
+      else
+       arch = pe_arch (bfd_target_pei_arch (abfd->xvec));
+
+      /* Don't check PE vs. EFI if arch is unknown.  */
+      if (arch == arch_type_unknown)
+       return target;
+
+      for (target_ptr = bfd_target_vector; *target_ptr != NULL;
+          target_ptr++)
+       {
+         if (*target_ptr == target
+             || (*target_ptr)->flavour != bfd_target_coff_flavour)
+           continue;
+
+         if (bfd_target_efi_p (*target_ptr))
+           {
+             /* Skip incompatible arch.  */
+             if (pe_arch (bfd_target_efi_arch (*target_ptr)) != arch)
+               continue;
+
+             if (efi)
+               {
+                 /* TARGET_PTR is an EFI backend.  Don't match
+                    TARGET with a EFI file.  */
+                 bfd_set_error (bfd_error_wrong_format);
+                 return NULL;
+               }
+           }
+         else if (bfd_target_pei_p (*target_ptr))
+           {
+             /* Skip incompatible arch.  */
+             if (pe_arch (bfd_target_pei_arch (*target_ptr)) != arch)
+               continue;
+
+             if (!efi)
+               {
+                 /* TARGET_PTR is a PE backend.  Don't match
+                    TARGET with a PE file.  */
+                 bfd_set_error (bfd_error_wrong_format);
+                 return NULL;
+               }
+           }
+       }
+    }
+
+  return target;
 }
 
 #define coff_object_p pe_bfd_object_p
This page took 0.037909 seconds and 4 git commands to generate.