* coff-i386.c (i3coff_object_p): If COFF_IMAGE_WITH_PE, hack to
authorIan Lance Taylor <ian@airs.com>
Sun, 22 Jun 1997 23:41:55 +0000 (23:41 +0000)
committerIan Lance Taylor <ian@airs.com>
Sun, 22 Jun 1997 23:41:55 +0000 (23:41 +0000)
handle case where COFF filehdr does not immediately follow PE
header.
* coffgen.c (coff_object_p): Remove useless seek to current
location.

bfd/ChangeLog
bfd/coff-i386.c
bfd/coffgen.c

index af5ed81..61c95bd 100644 (file)
@@ -1,3 +1,11 @@
+Sun Jun 22 19:40:57 1997  Ian Lance Taylor  <ian@cygnus.com>
+
+       * coff-i386.c (i3coff_object_p): If COFF_IMAGE_WITH_PE, hack to
+       handle case where COFF filehdr does not immediately follow PE
+       header.
+       * coffgen.c (coff_object_p): Remove useless seek to current
+       location.
+
 Wed Jun 18 19:03:38 1997  Ian Lance Taylor  <ian@cygnus.com>
 
        * linker.c (link_action): Change COMMON_ROW/indr to from CREF to
index 47ab122..04de751 100644 (file)
@@ -1,5 +1,5 @@
 /* BFD back-end for Intel 386 COFF files.
-   Copyright 1990, 1991, 1992, 1993, 1994, 1995 Free Software Foundation, Inc.
+   Copyright 1990, 91, 92, 93, 94, 95, 96, 1997 Free Software Foundation, Inc.
    Written by Cygnus Support.
 
 This file is part of BFD, the Binary File Descriptor library.
@@ -21,7 +21,6 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
 #include "bfd.h"
 #include "sysdep.h"
 #include "libbfd.h"
-#include "obstack.h"
 
 #include "coff/i386.h"
 
@@ -71,7 +70,6 @@ coff_i386_reloc (abfd, reloc_entry, symbol, data, input_section, output_bfd,
   if (output_bfd == (bfd *) NULL)
     return bfd_reloc_continue;
 
-
   if (bfd_is_com_section (symbol->section))
     {
       /* We are relocating a common symbol.  The current value in the
@@ -96,13 +94,10 @@ coff_i386_reloc (abfd, reloc_entry, symbol, data, input_section, output_bfd,
       diff = reloc_entry->addend;
     }
 
-
 #ifdef COFF_WITH_PE
-  if (reloc_entry->howto->type == 7)
-    {
-/*      diff -= coff_data(output_bfd)->link_info->pe_info.image_base.value;*/
-      exit(1);
-    }
+  /* FIXME: How should this case be handled?  */
+  if (reloc_entry->howto->type == R_IMAGEBASE && diff != 0)
+    abort ();
 #endif
 
 #define DOIT(x) \
@@ -148,7 +143,17 @@ coff_i386_reloc (abfd, reloc_entry, symbol, data, input_section, output_bfd,
   return bfd_reloc_continue;
 }
 
+#ifdef COFF_WITH_PE
+/* Return true if this relocation should
+   appear in the output .reloc section. */
 
+static boolean in_reloc_p(abfd, howto)
+     bfd * abfd;
+     reloc_howto_type *howto;
+{
+  return ! howto->pc_relative && howto->type != R_IMAGEBASE;
+}     
+#endif
 
 #ifndef PCRELOFFSET
 #define PCRELOFFSET false
@@ -285,11 +290,6 @@ static reloc_howto_type howto_table[] =
 #define RTYPE2HOWTO(cache_ptr, dst) \
            (cache_ptr)->howto = howto_table + (dst)->r_type;
 
-/* On SCO Unix 3.2.2 the native assembler generates two .data
-   sections.  We handle that by renaming the second one to .data2.  It
-   does no harm to do this for any 386 COFF target.  */
-#define TWO_DATA_SECS
-
 /* For 386 COFF a STYP_NOLOAD | STYP_BSS section is part of a shared
    library.  On some other COFF targets STYP_BSS is normally
    STYP_NOLOAD.  */
@@ -394,15 +394,96 @@ coff_i386_rtype_to_howto (abfd, sec, rel, h, sym, addendp)
   return howto;
 }
 
+
+#define coff_bfd_reloc_type_lookup coff_i386_reloc_type_lookup
+
+
+static reloc_howto_type *
+coff_i386_reloc_type_lookup (abfd, code)
+     bfd *abfd;
+     bfd_reloc_code_real_type code;
+{
+  switch (code)
+    {
+    case BFD_RELOC_RVA:
+      return howto_table +R_IMAGEBASE;
+    case BFD_RELOC_32:
+      return howto_table + R_DIR32;
+    case BFD_RELOC_32_PCREL:
+      return howto_table + R_PCRLONG;
+    default:
+      BFD_FAIL ();
+      return 0;
+    }
+}
+
+
+
 #define coff_rtype_to_howto coff_i386_rtype_to_howto
 
 #include "coffcode.h"
 
 static const bfd_target *
-i3coff_object_p(a)
-     bfd *a;
+i3coff_object_p (abfd)
+     bfd *abfd;
 {
-  return coff_object_p(a);
+#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
@@ -418,14 +499,20 @@ const bfd_target
   "coff-i386",                 /* name */
 #endif
   bfd_target_coff_flavour,
-  false,                       /* data byte order is little */
-  false,                       /* header byte order is little */
+  BFD_ENDIAN_LITTLE,           /* data byte order is little */
+  BFD_ENDIAN_LITTLE,           /* header byte order is little */
 
   (HAS_RELOC | EXEC_P |                /* object flags */
    HAS_LINENO | HAS_DEBUG |
    HAS_SYMS | HAS_LOCALS | WP_TEXT | D_PAGED),
 
+#ifndef COFF_WITH_PE
   (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_RELOC), /* section flags */
+#else
+  (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_RELOC /* section flags */
+   | SEC_LINK_ONCE | SEC_LINK_DUPLICATES),
+#endif
+
 #ifdef TARGET_UNDERSCORE
   TARGET_UNDERSCORE,           /* leading underscore */
 #else
index 3d7e85a..74414a1 100644 (file)
@@ -290,11 +290,6 @@ coff_object_p (abfd)
       bfd_coff_swap_aouthdr_in (abfd, opthdr, (PTR) & internal_a);
     }
 
-  /* Seek past the opt hdr stuff */
-  if (bfd_seek (abfd, (file_ptr) (internal_f.f_opthdr + filhsz), SEEK_SET)
-      != 0)
-    return NULL;
-
   return coff_real_object_p (abfd, nscns, &internal_f,
                             (internal_f.f_opthdr != 0
                              ? &internal_a