This is the mail archive of the binutils@sourceware.cygnus.com mailing list for the binutils project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

Patch submission: Generic PE object file detection


Hi Guys,

  Here is a patch for your approval.  It moves the duplicate copies of
  the code to detect PE format COFF objects from their respective
  target specific files into peicode.h.  With several more PE based
  ports waiting in the wings it seems like a good idea to move this
  code to a central location and avoid unnecessary duplication.

  As a side effect of this move I have also added code to the routine
  to detect Microsoft's new Image Library Format object files.  The
  code cannot parse them yet, but it can now issue a warning message
  if their presence is detected.

  Is this patch OK to apply ?

Cheers
	Nick


1999-12-17  Nick Clifton  <nickc@cygnus.com>

	* coff-i386.c (i3coff_object_p): Delete.
	(i386coff_vec): Replace reference to i3coff_object_p with a
	reference to coff_object_p.

	* coff-mcore.c (pe_object_p): Delete.

	* peicode.h (pe_bfd_object_p): New function: Detect the
	presence of a PE format COFF object file.  Also detect and
	warn about the presence of LINK6 format Image Library Format
	object files.


Index: coff-i386.c
===================================================================
RCS file: /cvs/binutils/binutils/bfd/coff-i386.c,v
retrieving revision 1.6
diff -p -r1.6 coff-i386.c
*** coff-i386.c	1999/09/18 00:44:44	1.6
--- coff-i386.c	1999/12/17 18:43:36
*************** coff_i386_is_local_label_name (abfd, nam
*** 535,603 ****
  
  #include "coffcode.h"
  
- static const bfd_target *
- i3coff_object_p (abfd)
-      bfd *abfd;
- {
- #ifdef COFF_IMAGE_WITH_PE
-   /* We need to hack badly 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 ext_offset[4];
-     file_ptr offset;
-     bfd_byte ext_signature[4];
-     unsigned long signature;
- 
-     if (bfd_seek (abfd, 0x3c, SEEK_SET) != 0
- 	|| bfd_read (ext_offset, 1, 4, abfd) != 4)
-       {
- 	if (bfd_get_error () != bfd_error_system_call)
- 	  bfd_set_error (bfd_error_wrong_format);
- 	return NULL;
-       }
-     offset = bfd_h_get_32 (abfd, ext_offset);
-     if (bfd_seek (abfd, offset, SEEK_SET) != 0
- 	|| bfd_read (ext_signature, 1, 4, abfd) != 4)
-       {
- 	if (bfd_get_error () != bfd_error_system_call)
- 	  bfd_set_error (bfd_error_wrong_format);
- 	return NULL;
-       }
-     signature = bfd_h_get_32 (abfd, ext_signature);
- 
-     if (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.  */
- 
-     if (bfd_seek (abfd,
- 		  (bfd_tell (abfd)
- 		   - bfd_coff_filhsz (abfd)
- 		   + 20),
- 		  SEEK_SET)
- 	!= 0)
-       {
- 	if (bfd_get_error () != bfd_error_system_call)
- 	  bfd_set_error (bfd_error_wrong_format);
- 	return NULL;
-       }
-   }
- #endif
- 
-   return coff_object_p (abfd);
- }
- 
  const bfd_target
  #ifdef TARGET_SYM
    TARGET_SYM =
--- 535,540 ----
*************** const bfd_target
*** 640,647 ****
       bfd_getl16, bfd_getl_signed_16, bfd_putl16, /* hdrs */
  
  /* Note that we allow an object file to be treated as a core file as well. */
!     {_bfd_dummy_target, i3coff_object_p, /* bfd_check_format */
!        bfd_generic_archive_p, i3coff_object_p},
      {bfd_false, coff_mkobject, _bfd_generic_mkarchive, /* bfd_set_format */
         bfd_false},
      {bfd_false, coff_write_object_contents, /* bfd_write_contents */
--- 577,584 ----
       bfd_getl16, bfd_getl_signed_16, bfd_putl16, /* hdrs */
  
  /* Note that we allow an object file to be treated as a core file as well. */
!     {_bfd_dummy_target, coff_object_p, /* bfd_check_format */
!        bfd_generic_archive_p, coff_object_p},
      {bfd_false, coff_mkobject, _bfd_generic_mkarchive, /* bfd_set_format */
         bfd_false},
      {bfd_false, coff_write_object_contents, /* bfd_write_contents */

Index: coff-mcore.c
===================================================================
RCS file: /cvs/binutils/binutils/bfd/coff-mcore.c,v
retrieving revision 1.10
diff -p -r1.10 coff-mcore.c
*** coff-mcore.c	1999/11/20 11:53:57	1.10
--- coff-mcore.c	1999/12/17 18:43:36
*************** coff_mcore_relocate_section (output_bfd,
*** 582,650 ****
  
  #include "coffcode.h"
  
- static const bfd_target *
- pe_object_p (abfd)
-      bfd * abfd;
- {
- #ifdef COFF_IMAGE_WITH_PE
-   /* We need to hack badly 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 ext_offset[4];
-     file_ptr offset;
-     bfd_byte ext_signature[4];
-     unsigned long signature;
- 
-     if (bfd_seek (abfd, 0x3c, SEEK_SET) != 0
- 	|| bfd_read (ext_offset, 1, 4, abfd) != 4)
-       {
- 	if (bfd_get_error () != bfd_error_system_call)
- 	  bfd_set_error (bfd_error_wrong_format);
- 	return NULL;
-       }
-     
-     offset = bfd_h_get_32 (abfd, ext_offset);
-     
-     if (bfd_seek (abfd, offset, SEEK_SET) != 0
- 	|| bfd_read (ext_signature, 1, 4, abfd) != 4)
-       {
- 	if (bfd_get_error () != bfd_error_system_call)
- 	  bfd_set_error (bfd_error_wrong_format);
- 	
- 	return NULL;
-       }
-     
-     signature = bfd_h_get_32 (abfd, ext_signature);
- 
-     if (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 mips COFF filehdr.  */
-     if (bfd_seek (abfd, (bfd_tell (abfd) - bfd_coff_filhsz (abfd) + 20),
- 		  SEEK_SET) != 0)
-       {
- 	if (bfd_get_error () != bfd_error_system_call)
- 	  bfd_set_error (bfd_error_wrong_format);
- 	
- 	return NULL;
-       }
-   }
- #endif
- 
-   return coff_object_p (abfd);
- }
- 
  /* Forward declaration to initialise alterbative_target field.  */
  extern const bfd_target TARGET_LITTLE_SYM;
  
--- 582,587 ----

Index: peicode.h
===================================================================
RCS file: /cvs/binutils/binutils/bfd/peicode.h,v
retrieving revision 1.14
diff -p -r1.14 peicode.h
*** peicode.h	1999/09/12 00:30:27	1.14
--- peicode.h	1999/12/17 18:43:36
*************** pe_bfd_copy_private_bfd_data (ibfd, obfd
*** 361,363 ****
--- 361,444 ----
    _bfd_pe_bfd_copy_private_section_data
  
  #define coff_get_symbol_info _bfd_pe_get_symbol_info
+ 
+ static const bfd_target *
+ pe_bfd_object_p (abfd)
+      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];
+   file_ptr offset;
+   unsigned long signature;
+ 
+   /* Detect if this a Microsoft Import Library Format element.  */
+   if (bfd_seek (abfd, 0x00, SEEK_SET) != 0
+       || bfd_read (buffer, 1, 4, abfd) != 4)
+     {
+       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 == 0xffff0000)
+     {
+       _bfd_error_handler (_("%s: Import Library Format archives are not currently supported"),
+ 			  bfd_get_filename (abfd));
+       bfd_set_error (bfd_error_wrong_format);
+ 	
+       return NULL;
+     }
+   
+   if (bfd_seek (abfd, 0x3c, SEEK_SET) != 0
+       || bfd_read (buffer, 1, 4, abfd) != 4)
+     {
+       if (bfd_get_error () != bfd_error_system_call)
+ 	bfd_set_error (bfd_error_wrong_format);
+       return NULL;
+     }
+ 
+   offset = bfd_h_get_32 (abfd, buffer);
+ 
+   if (bfd_seek (abfd, offset, SEEK_SET) != 0
+       || bfd_read (buffer, 1, 4, abfd) != 4)
+     {
+       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)
+     {
+       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.  */
+   if (bfd_seek (abfd,
+ 		(bfd_tell (abfd)
+ 		 - bfd_coff_filhsz (abfd)
+ 		 + 20),
+ 		SEEK_SET)
+       != 0)
+     {
+       if (bfd_get_error () != bfd_error_system_call)
+ 	bfd_set_error (bfd_error_wrong_format);
+       return NULL;
+     }
+ 
+   return coff_object_p (abfd);
+ }
+ 
+ #define coff_object_p pe_bfd_object_p

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]