[hjl@valinux.com: Re: A PE patch.]

Christopher Faylor cgf@redhat.com
Thu Jan 25 21:39:00 GMT 2001


On Wed, Jan 24, 2001 at 03:33:44PM -0500, DJ Delorie wrote:
>Could people please look at this patch and try it?  The original code
>assumed things it shouldn't, and thus you couldn't run, say, objdump
>on MS system DLLs.  I like the idea about making bfd dynamic, but I
>refuse to accept patches to this code without a "gut feeling" that it
>will work *and* lots of testing, so the more people test it the
>better.

Shouldn't the PEI*_header stuff come from some w32api file or other?

cgf

>------- Start of forwarded message -------
>Date: Wed, 24 Jan 2001 11:15:05 -0800
>From: "H . J . Lu" <hjl@valinux.com>
>To: DJ Delorie <dj@redhat.com>
>Subject: Re: A PE patch.
>Content-Disposition: inline
>User-Agent: Mutt/1.2.5i
>In-Reply-To: <200101241909.OAA06907@greed.delorie.com>; from dj@redhat.com on Wed, Jan 24, 2001 at 02:09:12PM -0500
>Content-Type: text/plain; charset=us-ascii
>
>Here is the updated version. There is a bug in my old patch.
>
>-- 
>H.J. Lu (hjl@valinux.com)
>---
>2001-01-23  H.J. Lu  <hjl@gnu.org>
>
>	* include/coff/pe.h (struct external_PEI_DOS_hdr): New.
>	(struct external_PEI_IMAGE_hdr): New.
>	
>	* bfd/peicode.h (coff_swap_filehdr_in): Remove the e_magic
>	checking.
>	(pe_bfd_object_p): Rewrite with external_PEI_DOS_hdr and
>	external_PEI_IMAGE_hdr.
>
>Index: include/coff/pe.h
>===================================================================
>RCS file: /work/cvs/gnu/binutils/include/coff/pe.h,v
>retrieving revision 1.1.1.7
>diff -u -p -r1.1.1.7 pe.h
>--- include/coff/pe.h	2000/09/05 17:49:11	1.1.1.7
>+++ include/coff/pe.h	2001/01/24 18:46:34
>@@ -125,6 +125,45 @@
> #undef  FILNMLEN
> #define FILNMLEN	18	/* # characters in a file name.  */
> 
>+struct external_PEI_DOS_hdr
>+{
>+  /* DOS header fields - always at offset zero in the EXE file.  */
>+  char e_magic[2];		/* Magic number, 0x5a4d.  */
>+  char e_cblp[2];		/* Bytes on last page of file, 0x90.  */
>+  char e_cp[2];			/* Pages in file, 0x3.  */
>+  char e_crlc[2];		/* Relocations, 0x0.  */
>+  char e_cparhdr[2];		/* Size of header in paragraphs, 0x4.  */
>+  char e_minalloc[2];		/* Minimum extra paragraphs needed, 0x0.  */
>+  char e_maxalloc[2];		/* Maximum extra paragraphs needed, 0xFFFF.  */
>+  char e_ss[2];			/* Initial (relative) SS value, 0x0.  */
>+  char e_sp[2];			/* Initial SP value, 0xb8.  */
>+  char e_csum[2];		/* Checksum, 0x0.  */
>+  char e_ip[2];			/* Initial IP value, 0x0.  */
>+  char e_cs[2];			/* Initial (relative) CS value, 0x0.  */
>+  char e_lfarlc[2];		/* File address of relocation table, 0x40.  */
>+  char e_ovno[2];		/* Overlay number, 0x0.  */
>+  char e_res[4][2];		/* Reserved words, all 0x0.  */
>+  char e_oemid[2];		/* OEM identifier (for e_oeminfo), 0x0.  */
>+  char e_oeminfo[2];		/* OEM information; e_oemid specific, 0x0.  */
>+  char e_res2[10][2];		/* Reserved words, all 0x0.  */
>+  char e_lfanew[4];		/* File address of new exe header, usually 0x80.  */
>+  char dos_message[16][4];	/* Other stuff, always follow DOS header.  */
>+};
>+
>+struct external_PEI_IMAGE_hdr
>+{
>+  char nt_signature[4];		/* required NT signature, 0x4550.  */
>+
>+  /* From standard header.  */
>+  char f_magic[2];		/* Magic number.		*/
>+  char f_nscns[2];		/* Number of sections.		*/
>+  char f_timdat[4];		/* Time & date stamp.		*/
>+  char f_symptr[4];		/* File pointer to symtab.	*/
>+  char f_nsyms[4];		/* Number of symtab entries.	*/
>+  char f_opthdr[2];		/* Sizeof(optional hdr).	*/
>+  char f_flags[2];		/* Flags.			*/
>+};
>+
> struct external_PEI_filehdr
> {
>   /* DOS header fields - always at offset zero in the EXE file.  */
>Index: bfd/peicode.h
>===================================================================
>RCS file: /work/cvs/gnu/binutils/bfd/peicode.h,v
>retrieving revision 1.9
>diff -u -p -r1.9 peicode.h
>--- bfd/peicode.h	2001/01/23 20:11:14	1.9
>+++ bfd/peicode.h	2001/01/24 18:36:09
>@@ -208,26 +208,6 @@ coff_swap_filehdr_in (abfd, src, dst)
>   filehdr_dst->f_flags = bfd_h_get_16(abfd, (bfd_byte *)filehdr_src-> f_flags);
>   filehdr_dst->f_symptr = bfd_h_get_32 (abfd, (bfd_byte *) filehdr_src->f_symptr);
> 
>-#ifdef COFF_IMAGE_WITH_PE
>-  /* There are really two magic numbers involved; the magic number
>-     that says this is a NT executable (PEI) and the magic number that
>-     determines the architecture.  The former is DOSMAGIC, stored in
>-     the e_magic field.  The latter is stored in the f_magic field.
>-     If the NT magic number isn't valid, the architecture magic number
>-     could be mimicked by some other field (specifically, the number
>-     of relocs in section 3).  Since this routine can only be called
>-     correctly for a PEI file, check the e_magic number here, and, if
>-     it doesn't match, clobber the f_magic number so that we don't get
>-     a false match.  */
>-#if 0
>-  /* We can't assume that the PE header is at offset 0x80.  When it
>-     isn't, the DOS header isn't read correctly, so we can't assume
>-     e_magic is set even for valid PE files.  */
>-  if (bfd_h_get_16 (abfd, (bfd_byte *) filehdr_src->e_magic) != DOSMAGIC)
>-    filehdr_dst->f_magic = -1;
>-#endif
>-#endif
>-
>   /* Other people's tools sometimes generate headers with an nsyms but
>      a zero symptr.  */
>   if (filehdr_dst->f_nsyms != 0 && filehdr_dst->f_symptr == 0)
>@@ -1255,16 +1235,10 @@ _("%s: Recognised but unhandled machine 
> static const bfd_target *
> pe_bfd_object_p (bfd * abfd)
> {
>-  /* We need to handle a PE image correctly.  In PE images created by
>-     the GNU linker, the offset to the COFF header is always the size.
>-     However, this is not the case in images generated by other PE
>-     linkers.  The PE format stores a four byte offset to the PE
>-     signature just before the COFF header at location 0x3c of the file.
>-     We pick up that offset, verify that the PE signature is there, and
>-     then set ourselves up to read in the COFF header.  */
>   bfd_byte buffer[4];
>+  struct external_PEI_DOS_hdr dos_hdr;
>+  struct external_PEI_IMAGE_hdr image_hdr;
>   file_ptr offset;
>-  unsigned long signature;
> 
>   /* Detect if this a Microsoft Import Library Format element.  */
>   if (bfd_seek (abfd, 0x00, SEEK_SET) != 0
>@@ -1275,44 +1249,56 @@ pe_bfd_object_p (bfd * abfd)
>       return NULL;
>     }
> 
>-  signature = bfd_h_get_32 (abfd, buffer);
>-
>-  if (signature == 0xffff0000)
>+  if (bfd_h_get_32 (abfd, buffer) == 0xffff0000)
>     return pe_ILF_object_p (abfd);
> 
>-  if (bfd_seek (abfd, 0x3c, SEEK_SET) != 0
>-      || bfd_read (buffer, 1, 4, abfd) != 4)
>+  if (bfd_seek (abfd, 0x00, SEEK_SET) != 0
>+      || bfd_read (&dos_hdr, 1, sizeof (dos_hdr), abfd)
>+	 != sizeof (dos_hdr))
>     {
>       if (bfd_get_error () != bfd_error_system_call)
> 	bfd_set_error (bfd_error_wrong_format);
>       return NULL;
>     }
> 
>-  offset = bfd_h_get_32 (abfd, buffer);
>+  /* There are really two magic numbers involved; the magic number
>+     that says this is a NT executable (PEI) and the magic number that
>+     determines the architecture.  The former is DOSMAGIC, stored in
>+     the e_magic field.  The latter is stored in the f_magic field.
>+     If the NT magic number isn't valid, the architecture magic number
>+     could be mimicked by some other field (specifically, the number
>+     of relocs in section 3).  Since this routine can only be called
>+     correctly for a PEI file, check the e_magic number here, and, if
>+     it doesn't match, clobber the f_magic number so that we don't get
>+     a false match.  */
>+  if (bfd_h_get_16 (abfd, (bfd_byte *) dos_hdr.e_magic) != DOSMAGIC)
>+    {
>+      bfd_set_error (bfd_error_wrong_format);
>+      return NULL;
>+    }
> 
>-  if (bfd_seek (abfd, offset, SEEK_SET) != 0
>-      || bfd_read (buffer, 1, 4, abfd) != 4)
>+  offset = bfd_h_get_32 (abfd, (bfd_byte *) dos_hdr.e_lfanew);
>+  if (bfd_seek (abfd, (file_ptr) offset, SEEK_SET) != 0
>+      || bfd_read (&image_hdr, 1, sizeof (image_hdr), abfd)
>+	 != sizeof (image_hdr))
>     {
>       if (bfd_get_error () != bfd_error_system_call)
> 	bfd_set_error (bfd_error_wrong_format);
>       return NULL;
>     }
>-
>-  signature = bfd_h_get_32 (abfd, buffer);
> 
>-  if (signature != 0x4550)
>+  if (bfd_h_get_32 (abfd, (bfd_byte *) image_hdr.nt_signature)
>+      != 0x4550)
>     {
>       bfd_set_error (bfd_error_wrong_format);
>       return NULL;
>     }
> 
>   /* Here is the hack.  coff_object_p wants to read filhsz bytes to
>-     pick up the COFF header.  We adjust so that that will work.  20
>-     is the size of the i386 COFF filehdr.  */
>+     pick up the COFF header for PE, see "struct external_PEI_filehdr"
>+     in include/coff/pe.h.  We adjust so that that will work. */
>   if (bfd_seek (abfd,
>-		(bfd_tell (abfd)
>-		 - bfd_coff_filhsz (abfd)
>-		 + 20),
>+		(file_ptr) (offset - sizeof (dos_hdr)),
> 		SEEK_SET)
>       != 0)
>     {
>------- End of forwarded message -------

-- 
cgf@cygnus.com                        Red Hat, Inc.
http://sources.redhat.com/            http://www.redhat.com/


More information about the Cygwin-developers mailing list