Initialize count_ field, tweak parameters testing.
[deliverable/binutils-gdb.git] / bfd / peicode.h
index 22f1bbd4293ae87be130924cc82874bd1e1fffa8..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, 2006 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., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.  */
+   Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
+   MA 02110-1301, USA.  */
+
 
 /* Most of this hacked by  Steve Chamberlain,
                        sac@cygnus.com
@@ -565,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;
@@ -1234,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)
 {
@@ -1241,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
@@ -1305,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.025637 seconds and 4 git commands to generate.