/* 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, 2008 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,
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
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)))
+ || (bfd_pe_executable_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
/* 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;
struct external_PEI_IMAGE_hdr image_hdr;
file_ptr offset;
const bfd_target *target;
+ struct bfd_preserve preserve;
/* Detect if this a Microsoft Import Library Format element. */
if (bfd_seek (abfd, (file_ptr) 0, SEEK_SET) != 0
return NULL;
}
+ preserve.marker = NULL;
+ if (! bfd_preserve_save (abfd, &preserve))
+ return NULL;
+
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;
+ bfd_boolean efi = i->Subsystem == IMAGE_SUBSYSTEM_EFI_APPLICATION
+ || i->Subsystem == IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER
+ || i->Subsystem == IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER;
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));
+ if (bfd_target_efi_app_p (abfd->xvec))
+ arch = pe_arch (bfd_target_efi_app_arch (abfd->xvec));
+ else if (bfd_target_efi_bsdrv_p (abfd->xvec))
+ arch = pe_arch (bfd_target_efi_bsdrv_arch (abfd->xvec));
+ else if (bfd_target_efi_rtdrv_p (abfd->xvec))
+ arch = pe_arch (bfd_target_efi_rtdrv_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)
+ {
+ bfd_preserve_finish (abfd, &preserve);
+ return target;
+ }
+
for (target_ptr = bfd_target_vector; *target_ptr != NULL;
target_ptr++)
{
|| (*target_ptr)->flavour != bfd_target_coff_flavour)
continue;
- if (bfd_target_efi_p (*target_ptr))
+ if (bfd_target_efi_app_p (*target_ptr))
+ {
+ /* Skip incompatible arch. */
+ if (pe_arch (bfd_target_efi_app_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_efi_bsdrv_p (*target_ptr))
{
/* Skip incompatible arch. */
- if (pe_arch (bfd_target_efi_arch (*target_ptr)) != arch)
+ if (pe_arch (bfd_target_efi_bsdrv_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;
- }
+ 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_efi_rtdrv_p (*target_ptr))
+ {
+ /* Skip incompatible arch. */
+ if (pe_arch (bfd_target_efi_rtdrv_arch (*target_ptr)) != arch)
+ continue;
+
+ if (efi)
+ {
+no_match:
+ /* TARGET_PTR is an EFI backend. Don't match
+ TARGET with a EFI file. */
+ bfd_preserve_restore (abfd, &preserve);
+ bfd_set_error (bfd_error_wrong_format);
+ return NULL;
+ }
}
else if (bfd_target_pei_p (*target_ptr))
{
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;
- }
+ if (!efi)
+ {
+ /* TARGET_PTR is a PE backend. Don't match
+ TARGET with a PE file. */
+ goto no_match;
+ }
}
}
+
+ bfd_preserve_finish (abfd, &preserve);
}
+ else
+ bfd_preserve_restore (abfd, &preserve);
return target;
}