Mailing-List: contact cygwin-developers-help AT sourceware DOT cygnus DOT com; run by ezmlm List-Subscribe: List-Archive: List-Post: List-Help: , Sender: cygwin-developers-owner AT sources DOT redhat DOT com Delivered-To: mailing list cygwin-developers AT sources DOT redhat DOT com Date: Wed, 24 Jan 2001 15:33:44 -0500 Message-Id: <200101242033.PAA16287@envy.delorie.com> X-Authentication-Warning: envy.delorie.com: dj set sender to dj AT envy DOT delorie DOT com using -f From: DJ Delorie To: cygwin-developers AT cygwin DOT com Subject: [hjl AT valinux DOT com: Re: A PE patch.] 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. ------- Start of forwarded message ------- Date: Wed, 24 Jan 2001 11:15:05 -0800 From: "H . J . Lu" To: DJ Delorie Subject: Re: A PE patch. Content-Disposition: inline User-Agent: Mutt/1.2.5i In-Reply-To: <200101241909 DOT OAA06907 AT greed DOT delorie DOT com>; from dj AT redhat DOT 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 AT valinux DOT com) --- 2001-01-23 H.J. Lu * 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 -------