This is the mail archive of the
binutils@sourceware.org
mailing list for the binutils project.
Re: PATCH: Fix EFI support
- From: "H.J. Lu" <hongjiu dot lu at intel dot com>
- To: binutils at sources dot redhat dot com
- Cc: pjones at redhat dot com
- Date: Wed, 15 Apr 2009 14:14:28 -0700
- Subject: Re: PATCH: Fix EFI support
- References: <20090415210525.GA14029@lucon.org>
- Reply-to: "H.J. Lu" <hjl dot tools at gmail dot com>
On Wed, Apr 15, 2009 at 02:05:25PM -0700, H.J. Lu wrote:
> This patch:
>
> http://sourceware.org/ml/binutils/2008-02/msg00051.html
>
> breaks EFI. I got
>
> [hjl@gnu-6 HelloWorldUefiGcc4.4]$ file HelloWorld.dll
> HelloWorld.dll: PE32+ executable (EFI boot service driver)
> [hjl@gnu-6 HelloWorldUefiGcc4.4]$ objdump -p HelloWorld.dll
> objdump: HelloWorld.dll: File format not recognized
> [hjl@gnu-6 HelloWorldUefiGcc4.4]$
>
> The problem is we have 3 EFI targets for each arch. When we scan
> all targets on EFI input, we always reach
>
> if (efi)
> {
> bfd_set_error (bfd_error_wrong_format);
> return NULL;
> }
>
> This patch fixes by checking Subsystem. This patch also adds
> bfd_target_efi_p so that we only needs to check one "efi-" instead of
> 3 "efi-XXX-". OK for trunl?
>
Here is the updated patch to support ia64 EFI. OK for trunk?
Thanks.
H.J.
---
2009-04-15 H.J. Lu <hongjiu.lu@intel.com>
* libpei.h (bfd_target_efi_p): New.
(bfd_pe_executable_p): Use it.
* peicode.h (arch_type): Add arch_type_ia64.
(pe_arch): Support arch_type_ia64.
(pe_bfd_object_p): Properly check EFI and PE.
--- bfd/libpei.h.efi 2009-04-08 08:46:35.000000000 -0700
+++ bfd/libpei.h 2009-04-15 11:31:48.000000000 -0700
@@ -317,6 +317,10 @@
#define bfd_target_efi_app_arch(xvec) \
((xvec)->name + sizeof ("efi-app-") - 1)
+/* Returns true if the target is an EFI target. */
+#define bfd_target_efi_p(xvec) \
+ (CONST_STRNEQ ((xvec)->name, "efi-"))
+
/* Returns true if the target is an EFI Boot Service driver target. */
#define bfd_target_efi_bsdrv_p(xvec) \
(CONST_STRNEQ ((xvec)->name, "efi-bsdrv-"))
@@ -336,10 +340,8 @@
/* Macro: Returns true if the bfd is a PE executable as opposed to a
PE object file. */
#define bfd_pe_executable_p(abfd) \
- ( bfd_target_pei_p ((abfd)->xvec) \
- || bfd_target_efi_app_p ((abfd)->xvec) \
- || bfd_target_efi_bsdrv_p ((abfd)->xvec) \
- || bfd_target_efi_rtdrv_p ((abfd)->xvec))
+ (bfd_target_pei_p ((abfd)->xvec) \
+ || bfd_target_efi_p ((abfd)->xvec))
/* These functions are architecture dependent, and are in peicode.h:
coff_swap_reloc_in
--- bfd/peicode.h.efi 2008-02-14 09:26:02.000000000 -0800
+++ bfd/peicode.h 2009-04-15 14:12:29.000000000 -0700
@@ -1240,7 +1240,8 @@ enum arch_type
{
arch_type_unknown,
arch_type_i386,
- arch_type_x86_64
+ arch_type_x86_64,
+ arch_type_ia64
};
static enum arch_type
@@ -1252,6 +1253,9 @@ pe_arch (const char *arch)
if (strcmp (arch, "x86_64") == 0 || strcmp (arch, "x86-64") == 0)
return arch_type_x86_64;
+ if (strcmp (arch, "ia64") == 0)
+ return arch_type_ia64;
+
return arch_type_unknown;
}
@@ -1373,12 +1377,11 @@ pe_bfd_object_p (bfd * abfd)
if (pe_arch (bfd_target_efi_app_arch (*target_ptr)) != arch)
continue;
- if (efi)
+ if (efi
+ && i->Subsystem == IMAGE_SUBSYSTEM_EFI_APPLICATION)
{
- /* TARGET_PTR is an EFI backend. Don't match
- TARGET with a EFI file. */
- bfd_set_error (bfd_error_wrong_format);
- return NULL;
+ /* This is a match. */
+ break;
}
}
else if (bfd_target_efi_bsdrv_p (*target_ptr))
@@ -1387,12 +1390,11 @@ pe_bfd_object_p (bfd * abfd)
if (pe_arch (bfd_target_efi_bsdrv_arch (*target_ptr)) != arch)
continue;
- if (efi)
+ if (efi
+ && i->Subsystem == IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER)
{
- /* TARGET_PTR is an EFI backend. Don't match
- TARGET with a EFI file. */
- bfd_set_error (bfd_error_wrong_format);
- return NULL;
+ /* This is a match. */
+ break;
}
}
else if (bfd_target_efi_rtdrv_p (*target_ptr))
@@ -1401,14 +1403,11 @@ pe_bfd_object_p (bfd * abfd)
if (pe_arch (bfd_target_efi_rtdrv_arch (*target_ptr)) != arch)
continue;
- if (efi)
+ if (efi
+ && i->Subsystem == IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER)
{
-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;
+ /* This is a match. */
+ break;
}
}
else if (bfd_target_pei_p (*target_ptr))
@@ -1419,13 +1418,20 @@ no_match:
if (!efi)
{
- /* TARGET_PTR is a PE backend. Don't match
- TARGET with a PE file. */
- goto no_match;
+ /* This is a match. */
+ break;
}
}
}
+ if (*target_ptr != NULL)
+ {
+ /* TARGET_PTR is a match. Don't match TARGET with input. */
+ bfd_preserve_restore (abfd, &preserve);
+ bfd_set_error (bfd_error_wrong_format);
+ return NULL;
+ }
+
bfd_preserve_finish (abfd, &preserve);
}
else