+ 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
+ || 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_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++)
+ {
+ if (*target_ptr == target
+ || (*target_ptr)->flavour != bfd_target_coff_flavour)
+ continue;
+
+ 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_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;
+ }
+ }
+ 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))
+ {
+ /* 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. */
+ goto no_match;
+ }
+ }
+ }
+
+ bfd_preserve_finish (abfd, &preserve);
+ }
+ else
+ bfd_preserve_restore (abfd, &preserve);
+
+ return target;