* archive.c (_bfd_generic_read_ar_hdr_mag): Simplify end-of-name test.
[binutils-gdb.git] / bfd / coff-i386.c
index 47ab12282359af38235162131646df005c465e05..79b9f94f9afc0b93cbdb20a9d82dfc6f0da6b9a6 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"
 
@@ -31,6 +30,10 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
 #include "coff/pe.h"
 #endif
 
+#ifdef COFF_GO32_EXE
+#include "coff/go32exe.h"
+#endif
+
 #include "libcoff.h"
 
 static bfd_reloc_status_type coff_i386_reloc 
@@ -71,7 +74,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 +98,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 +147,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 +294,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 +398,117 @@ 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
 
+#ifdef TARGET_UNDERSCORE
+
+/* If i386 gcc uses underscores for symbol names, then it does not use
+   a leading dot for local labels, so if TARGET_UNDERSCORE is defined
+   we treat all symbols starting with L as local.  */
+
+static boolean coff_i386_is_local_label_name PARAMS ((bfd *, const char *));
+
+static boolean
+coff_i386_is_local_label_name (abfd, name)
+     bfd *abfd;
+     const char *name;
+{
+  if (name[0] == 'L')
+    return true;
+
+  return _bfd_coff_is_local_label_name (abfd, name);
+}
+
+#define coff_bfd_is_local_label_name coff_i386_is_local_label_name
+
+#endif /* TARGET_UNDERSCORE */
+
 #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 +524,22 @@ 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),
 
-  (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_RELOC), /* section flags */
+#ifndef COFF_WITH_PE
+  (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_RELOC /* section flags */
+   | SEC_CODE | SEC_DATA),
+#else
+  (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_RELOC /* section flags */
+   | SEC_CODE | SEC_DATA
+   | SEC_LINK_ONCE | SEC_LINK_DUPLICATES),
+#endif
+
 #ifdef TARGET_UNDERSCORE
   TARGET_UNDERSCORE,           /* leading underscore */
 #else