/* BFD back-end for Intel 386 COFF files.
- Copyright 1990, 91, 92, 93, 94, 95, 96, 97, 98, 1999
+ Copyright 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
+ 2000, 2001
Free Software Foundation, Inc.
Written by Cygnus Support.
bfd_vma *));
static reloc_howto_type *coff_i386_reloc_type_lookup
PARAMS ((bfd *, bfd_reloc_code_real_type));
-static const bfd_target *i3coff_object_p PARAMS ((bfd *));
#define COFF_DEFAULT_SECTION_ALIGNMENT_POWER (2)
/* The page size is a guess based on ELF. */
{
symvalue diff;
+#ifndef COFF_WITH_PE
if (output_bfd == (bfd *) NULL)
return bfd_reloc_continue;
+#endif
if (bfd_is_com_section (symbol->section))
{
ignores the addend for a COFF target when producing
relocateable output. This seems to be always wrong for 386
COFF, so we handle the addend here instead. */
- diff = reloc_entry->addend;
+#ifdef COFF_WITH_PE
+ if (output_bfd == (bfd *) NULL)
+ {
+ reloc_howto_type *howto = reloc_entry->howto;
+
+ /* Although PC relative relocations are very similar between
+ PE and non-PE formats, but they are off by 1 << howto->size
+ bytes. For the external relocation, PE is very different
+ from others. See md_apply_fix3 () in gas/config/tc-i386.c.
+ When we link PE and non-PE object files together to
+ generate a non-PE executable, we have to compensate it
+ here. */
+ if (howto->pc_relative == true && howto->pcrel_offset == true)
+ diff = -(1 << howto->size);
+ else
+ diff = -reloc_entry->addend;
+ }
+ else
+#endif
+ diff = reloc_entry->addend;
}
#ifdef COFF_WITH_PE
/* FIXME: How should this case be handled? */
- if (reloc_entry->howto->type == R_IMAGEBASE)
+ if (reloc_entry->howto->type == R_IMAGEBASE
+ && output_bfd != NULL
+ && bfd_get_flavour(output_bfd) == bfd_target_coff_flavour)
diff -= pe_data (output_bfd)->pe_opthdr.ImageBase;
#endif
}
#ifdef COFF_WITH_PE
-
/* Return true if this relocation should appear in the output .reloc
section. */
static boolean in_reloc_p PARAMS ((bfd *, reloc_howto_type *));
static boolean in_reloc_p (abfd, howto)
- bfd *abfd ATTRIBUTE_UNUSED;
+ bfd * abfd ATTRIBUTE_UNUSED;
reloc_howto_type *howto;
{
return ! howto->pc_relative && howto->type != R_IMAGEBASE;
}
-
#endif /* COFF_WITH_PE */
#ifndef PCRELOFFSET
*addendp -= sym->n_value;
}
- if (rel->r_type == R_IMAGEBASE)
+ if (rel->r_type == R_IMAGEBASE
+ && (bfd_get_flavour(sec->output_section->owner)
+ == bfd_target_coff_flavour))
{
*addendp -= pe_data(sec->output_section->owner)->pe_opthdr.ImageBase;
}
#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 =
(SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_RELOC /* section flags */
#ifdef COFF_WITH_PE
- | SEC_LINK_ONCE | SEC_LINK_DUPLICATES
+ | SEC_LINK_ONCE | SEC_LINK_DUPLICATES | SEC_READONLY
#endif
| SEC_CODE | SEC_DATA),
bfd_getl32, bfd_getl_signed_32, bfd_putl32,
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},
+/* 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 */