aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--bfd/ChangeLog8
-rw-r--r--bfd/coff-i386.c125
-rw-r--r--bfd/coffgen.c5
3 files changed, 114 insertions, 24 deletions
diff --git a/bfd/ChangeLog b/bfd/ChangeLog
index af5ed81..61c95bd 100644
--- a/bfd/ChangeLog
+++ b/bfd/ChangeLog
@@ -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
diff --git a/bfd/coff-i386.c b/bfd/coff-i386.c
index 47ab122..04de751 100644
--- a/bfd/coff-i386.c
+++ b/bfd/coff-i386.c
@@ -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
diff --git a/bfd/coffgen.c b/bfd/coffgen.c
index 3d7e85a..74414a1 100644
--- a/bfd/coffgen.c
+++ b/bfd/coffgen.c
@@ -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