/* BFD back-end for ARM COFF files.
Copyright 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
- 2000, 2001, 2002
+ 2000, 2001, 2002, 2003, 2004
Free Software Foundation, Inc.
Written by Cygnus Support.
-This file is part of BFD, the Binary File Descriptor library.
+ This file is part of BFD, the Binary File Descriptor library.
-This program is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2 of the License, or
-(at your option) any later version.
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
-You should have received a copy of the GNU General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
#include "bfd.h"
#include "sysdep.h"
#undef ARM_THUMB12
#undef ARM_26D
+#define ARM_26D 0
#define ARM_32 1
#define ARM_RVA32 2
#define ARM_26 3
#define ARM_THUMB12 4
-#define ARM_26D 5
#define ARM_SECTION 14
#define ARM_SECREL 15
#endif
static reloc_howto_type aoutarm_std_reloc_howto[] =
{
#ifdef ARM_WINCE
- EMPTY_HOWTO (-1),
+ HOWTO (ARM_26D,
+ 2,
+ 2,
+ 24,
+ TRUE,
+ 0,
+ complain_overflow_dont,
+ aoutarm_fix_pcrel_26_done,
+ "ARM_26D",
+ FALSE,
+ 0x00ffffff,
+ 0x0,
+ PCRELOFFSET),
HOWTO (ARM_32,
0,
2,
complain_overflow_bitfield,
coff_arm_reloc,
"ARM_32",
- TRUE,
+ FALSE,
0xffffffff,
0xffffffff,
PCRELOFFSET),
complain_overflow_bitfield,
coff_arm_reloc,
"ARM_RVA32",
- TRUE,
+ FALSE,
0xffffffff,
0xffffffff,
PCRELOFFSET),
0x000007ff,
0x000007ff,
PCRELOFFSET),
- HOWTO (ARM_26D,
- 2,
- 2,
- 24,
- FALSE,
- 0,
- complain_overflow_dont,
- aoutarm_fix_pcrel_26_done,
- "ARM_26D",
- TRUE,
- 0x00ffffff,
- 0x0,
- FALSE),
+ EMPTY_HOWTO (-1),
EMPTY_HOWTO (-1),
EMPTY_HOWTO (-1),
EMPTY_HOWTO (-1),
0,
complain_overflow_bitfield,
coff_arm_reloc,
- "ARM_16",
- TRUE,
+ "ARM_SECTION",
+ FALSE,
0x0000ffff,
0x0000ffff,
PCRELOFFSET),
0,
complain_overflow_bitfield,
coff_arm_reloc,
- "ARM_32",
- TRUE,
+ "ARM_SECREL",
+ FALSE,
0xffffffff,
0xffffffff,
PCRELOFFSET),
/* The original coff_link_hash_table structure. MUST be first field. */
struct coff_link_hash_table root;
- /* The size in bytes of the section containg the Thumb-to-ARM glue. */
+ /* The size in bytes of the section containing the Thumb-to-ARM glue. */
bfd_size_type thumb_glue_size;
- /* The size in bytes of the section containg the ARM-to-Thumb glue. */
+ /* The size in bytes of the section containing the ARM-to-Thumb glue. */
bfd_size_type arm_glue_size;
- /* An arbitary input BFD chosen to hold the glue sections. */
+ /* An arbitrary input BFD chosen to hold the glue sections. */
bfd * bfd_of_glue_owner;
/* Support interworking with old, non-interworking aware ARM code. */
instruction.
It takes two thumb instructions to encode the target address. Each has
- 11 bits to invest. The upper 11 bits are stored in one (identifed by
+ 11 bits to invest. The upper 11 bits are stored in one (identified by
H-0.. see below), the lower 11 bits are stored in the other (identified
by H-1).
if (myh == NULL)
/* xgettext:c-format */
- _bfd_error_handler (_("%s: unable to find THUMB glue '%s' for `%s'"),
- bfd_archive_filename (input_bfd), tmp_name, name);
+ _bfd_error_handler (_("%B: unable to find THUMB glue '%s' for `%s'"),
+ input_bfd, tmp_name, name);
free (tmp_name);
if (myh == NULL)
/* xgettext:c-format */
- _bfd_error_handler (_("%s: unable to find ARM glue '%s' for `%s'"),
- bfd_archive_filename (input_bfd), tmp_name, name);
+ _bfd_error_handler (_("%B: unable to find ARM glue '%s' for `%s'"),
+ input_bfd, tmp_name, name);
free (tmp_name);
{
struct internal_reloc * rel;
struct internal_reloc * relend;
+ bfd_vma high_address = bfd_get_section_limit (input_bfd, input_section);
rel = relocs;
relend = rel + input_section->reloc_count;
return FALSE;
/* The relocation_section function will skip pcrel_offset relocs
- when doing a relocateable link. However, we want to convert
- ARM26 to ARM26D relocs if possible. We return a fake howto in
+ when doing a relocatable link. However, we want to convert
+ ARM_26 to ARM_26D relocs if possible. We return a fake howto in
this case without pcrel_offset set, and adjust the addend to
- compensate. */
+ compensate. 'partial_inplace' is also set, since we want 'done'
+ relocations to be reflected in section's data. */
if (rel->r_type == ARM_26
&& h != NULL
- && info->relocateable
+ && info->relocatable
&& (h->root.type == bfd_link_hash_defined
|| h->root.type == bfd_link_hash_defweak)
&& (h->root.u.def.section->output_section
complain_overflow_signed,
aoutarm_fix_pcrel_26 ,
"ARM_26",
- FALSE,
+ TRUE,
0x00ffffff,
0x00ffffff,
FALSE);
addend -= rel->r_vaddr - input_section->vma;
+#ifdef ARM_WINCE
+ /* FIXME: I don't know why, but the hack is necessary for correct
+ generation of bl's instruction offset. */
+ addend -= 8;
+#endif
howto = &fake_arm26_reloc;
}
the next opcode's pc, so is off by one. */
#if 0 /* This appears to have been true for WINCE 2.0, but it is not
true for WINCE 3.0. */
- if (howto->pc_relative && !info->relocateable)
+ if (howto->pc_relative && !info->relocatable)
addend -= 8;
#endif
#endif
- /* If we are doing a relocateable link, then we can just ignore
+ /* If we are doing a relocatable link, then we can just ignore
a PC relative reloc that is pcrel_offset. It will already
- have the correct value. If this is not a relocateable link,
+ have the correct value. If this is not a relocatable link,
then we should ignore the symbol value. */
if (howto->pc_relative && howto->pcrel_offset)
{
- if (info->relocateable)
+ if (info->relocatable)
continue;
/* FIXME - it is not clear which targets need this next test
and which do not. It is known that it is needed for the
VxWorks and EPOC-PE targets, but it is also known that it
- was supressed for other ARM targets. This ought to be
+ was suppressed for other ARM targets. This ought to be
sorted out one day. */
#ifdef ARM_COFF_BUGFIX
/* We must not ignore the symbol value. If the symbol is
stub generation to the final linker pass. If we fail to
verify that the name is defined, we'll try to build stubs
for an undefined name... */
- if (! info->relocateable
+ if (! info->relocatable
&& ( h->root.type == bfd_link_hash_defined
|| h->root.type == bfd_link_hash_defweak))
{
if (h_sec->owner != NULL
&& INTERWORK_SET (h_sec->owner)
&& ! INTERWORK_FLAG (h_sec->owner))
- {
- _bfd_error_handler
- /* xgettext:c-format */
- (_("%s(%s): warning: interworking not enabled."),
- bfd_archive_filename (h_sec->owner), name);
- _bfd_error_handler
- /* xgettext:c-format */
- (_(" first occurrence: %s: arm call to thumb"),
- bfd_archive_filename (input_bfd));
- }
+ _bfd_error_handler
+ /* xgettext:c-format */
+ (_("%B(%s): warning: interworking not enabled.\n"
+ " first occurrence: %B: arm call to thumb"),
+ h_sec->owner, input_bfd, name);
--my_offset;
myh->root.u.def.value = my_offset;
&& INTERWORK_SET (h_sec->owner)
&& ! INTERWORK_FLAG (h_sec->owner)
&& ! globals->support_old_code)
- {
- _bfd_error_handler
- /* xgettext:c-format */
- (_("%s(%s): warning: interworking not enabled."),
- bfd_archive_filename (h_sec->owner), name);
- _bfd_error_handler
- /* xgettext:c-format */
- (_(" first occurrence: %s: thumb call to arm"),
- bfd_archive_filename (input_bfd));
- _bfd_error_handler
- (_(" consider relinking with --support-old-code enabled"));
- }
+ _bfd_error_handler
+ /* xgettext:c-format */
+ (_("%B(%s): warning: interworking not enabled.\n"
+ " first occurrence: %B: thumb call to arm\n"
+ " consider relinking with --support-old-code enabled"),
+ h_sec->owner, input_bfd, name);
-- my_offset;
myh->root.u.def.value = my_offset;
+ sec->output_offset);
}
- else if (! info->relocateable)
+ else if (! info->relocatable)
{
if (! ((*info->callbacks->undefined_symbol)
(info, h->root.root.string, input_bfd, input_section,
rstat = bfd_reloc_ok;
#ifndef ARM_WINCE
/* Only perform this fix during the final link, not a relocatable link. nickc@cygnus.com */
- else if (! info->relocateable
+ else if (! info->relocatable
&& howto->type == ARM_THUMB23)
{
/* This is pretty much a copy of what the default
bfd_vma address = rel->r_vaddr - input_section->vma;
- if (address > input_section->_raw_size)
+ if (address > high_address)
rstat = bfd_reloc_outofrange;
else
{
#endif
else
#endif /* THUMBEXTENSION */
- rstat = _bfd_final_link_relocate (howto, input_bfd, input_section,
- contents,
- rel->r_vaddr - input_section->vma,
- val, addend);
+ if (info->relocatable && ! howto->partial_inplace)
+ rstat = bfd_reloc_ok;
+ else
+ rstat = _bfd_final_link_relocate (howto, input_bfd, input_section,
+ contents,
+ rel->r_vaddr - input_section->vma,
+ val, addend);
#if 1 /* THUMBEXTENSION */
/* FIXME:
Is this the best way to fix up thumb addresses? krk@cygnus.com
Probably not, but it works, and if it works it don't need fixing! nickc@cygnus.com */
/* Only perform this fix during the final link, not a relocatable link. nickc@cygnus.com */
- if (! info->relocateable
+ if (! info->relocatable
&& (rel->r_type == ARM_32 || rel->r_type == ARM_RVA32))
{
/* Determine if we need to set the bottom bit of a relocated address
break;
case bfd_reloc_outofrange:
(*_bfd_error_handler)
- (_("%s: bad reloc address 0x%lx in section `%s'"),
- bfd_archive_filename (input_bfd),
- (unsigned long) rel->r_vaddr,
- bfd_get_section_name (input_bfd, input_section));
+ (_("%B: bad reloc address 0x%lx in section `%A'"),
+ input_bfd, input_section, (unsigned long) rel->r_vaddr);
return FALSE;
case bfd_reloc_overflow:
{
if (symndx == -1)
name = "*ABS*";
else if (h != NULL)
- name = h->root.root.string;
+ name = NULL;
else
{
name = _bfd_coff_internal_syment_name (input_bfd, sym, buf);
}
if (! ((*info->callbacks->reloc_overflow)
- (info, name, howto->name, (bfd_vma) 0, input_bfd,
- input_section, rel->r_vaddr - input_section->vma)))
+ (info, (h ? &h->root : NULL), name, howto->name,
+ (bfd_vma) 0, input_bfd, input_section,
+ rel->r_vaddr - input_section->vma)))
return FALSE;
}
}
memset (foo, test_char, (size_t) globals->arm_glue_size);
#endif
- s->_raw_size = s->_cooked_size = globals->arm_glue_size;
+ s->size = globals->arm_glue_size;
s->contents = foo;
}
memset (foo, test_char, (size_t) globals->thumb_glue_size);
#endif
- s->_raw_size = s->_cooked_size = globals->thumb_glue_size;
+ s->size = globals->thumb_glue_size;
s->contents = foo;
}
/* If we are only performing a partial link do not bother
getting a bfd to hold the glue. */
- if (info->relocateable)
+ if (info->relocatable)
return TRUE;
globals = coff_arm_hash_table (info);
/* If we are only performing a partial link do not bother
to construct any glue. */
- if (info->relocateable)
+ if (info->relocatable)
return TRUE;
/* Here we have a bfd that is to be included on the link. We have a hook
/* If the index is outside of the range of our table, something has gone wrong. */
if (symndx >= obj_conv_table_size (abfd))
{
- _bfd_error_handler (_("%s: illegal symbol index in reloc: %d"),
- bfd_archive_filename (abfd), symndx);
+ _bfd_error_handler (_("%B: illegal symbol index in reloc: %d"),
+ abfd, symndx);
continue;
}
#define coff_bfd_copy_private_bfd_data coff_arm_copy_private_bfd_data
#define coff_bfd_link_hash_table_create coff_arm_link_hash_table_create
-/* When doing a relocateable link, we want to convert ARM26 relocs
- into ARM26D relocs. */
+/* When doing a relocatable link, we want to convert ARM_26 relocs
+ into ARM_26D relocs. */
static bfd_boolean
coff_arm_adjust_symndx (obfd, info, ibfd, sec, irel, adjustedp)
struct internal_reloc *irel;
bfd_boolean *adjustedp;
{
- if (irel->r_type == 3)
+ if (irel->r_type == ARM_26)
{
struct coff_link_hash_entry *h;
&& (h->root.type == bfd_link_hash_defined
|| h->root.type == bfd_link_hash_defweak)
&& h->root.u.def.section->output_section == sec->output_section)
- irel->r_type = 7;
+ irel->r_type = ARM_26D;
}
*adjustedp = FALSE;
return TRUE;
/* Called when merging the private data areas of two BFDs.
This is important as it allows us to detect if we are
attempting to merge binaries compiled for different ARM
- targets, eg different CPUs or differents APCS's. */
+ targets, eg different CPUs or different APCS's. */
static bfd_boolean
coff_arm_merge_private_bfd_data (ibfd, obfd)
if (ibfd == obfd)
return TRUE;
- if (bfd_get_mach (obfd) && bfd_get_mach (obfd) != bfd_get_mach (ibfd))
- {
- /* For now, allow an output file type of 'xscale' if the
- input file type is 'iWMMXt'. This means that we will
- not have to build an entire iWMMXt enabled set of libraries
- just to test a iWMMXt enabled binary. Change the output
- type to iWMMXt though. Similarly allow 'xscale' binaries
- to be linked into a 'iWMMXt' output binary. */
- if ( bfd_get_mach (obfd) == bfd_mach_arm_XScale
- && bfd_get_mach (ibfd) == bfd_mach_arm_iWMMXt)
- bfd_set_arch_mach (obfd, bfd_get_arch (obfd), bfd_mach_arm_iWMMXt);
- else if ( bfd_get_mach (ibfd) != bfd_mach_arm_XScale
- || bfd_get_mach (obfd) != bfd_mach_arm_iWMMXt)
- {
- bfd_set_error (bfd_error_wrong_format);
- return FALSE;
- }
- }
-
/* If the two formats are different we cannot merge anything.
This is not an error, since it is permissable to change the
input and output formats. */
|| obfd->xvec->flavour != bfd_target_coff_flavour)
return TRUE;
- /* Verify that the APCS is the same for the two BFDs */
+ /* Determine what should happen if the input ARM architecture
+ does not match the output ARM architecture. */
+ if (! bfd_arm_merge_machines (ibfd, obfd))
+ return FALSE;
+
+ /* Verify that the APCS is the same for the two BFDs. */
if (APCS_SET (ibfd))
{
if (APCS_SET (obfd))
{
_bfd_error_handler
/* xgettext: c-format */
- (_("ERROR: %s is compiled for APCS-%d, whereas %s is compiled for APCS-%d"),
- bfd_archive_filename (ibfd), APCS_26_FLAG (ibfd) ? 26 : 32,
- bfd_get_filename (obfd), APCS_26_FLAG (obfd) ? 26 : 32
+ (_("ERROR: %B is compiled for APCS-%d, whereas %B is compiled for APCS-%d"),
+ ibfd, obfd,
+ APCS_26_FLAG (ibfd) ? 26 : 32,
+ APCS_26_FLAG (obfd) ? 26 : 32
);
bfd_set_error (bfd_error_wrong_format);
if (APCS_FLOAT_FLAG (ibfd))
/* xgettext: c-format */
- msg = _("ERROR: %s passes floats in float registers, whereas %s passes them in integer registers");
+ msg = _("ERROR: %B passes floats in float registers, whereas %B passes them in integer registers");
else
/* xgettext: c-format */
- msg = _("ERROR: %s passes floats in integer registers, whereas %s passes them in float registers");
+ msg = _("ERROR: %B passes floats in integer registers, whereas %B passes them in float registers");
- _bfd_error_handler (msg, bfd_archive_filename (ibfd),
- bfd_get_filename (obfd));
+ _bfd_error_handler (msg, ibfd, obfd);
bfd_set_error (bfd_error_wrong_format);
return FALSE;
if (PIC_FLAG (ibfd))
/* xgettext: c-format */
- msg = _("ERROR: %s is compiled as position independent code, whereas target %s is absolute position");
+ msg = _("ERROR: %B is compiled as position independent code, whereas target %B is absolute position");
else
/* xgettext: c-format */
- msg = _("ERROR: %s is compiled as absolute position code, whereas target %s is position independent");
- _bfd_error_handler (msg, bfd_archive_filename (ibfd),
- bfd_get_filename (obfd));
+ msg = _("ERROR: %B is compiled as absolute position code, whereas target %B is position independent");
+ _bfd_error_handler (msg, ibfd, obfd);
bfd_set_error (bfd_error_wrong_format);
return FALSE;
if (INTERWORK_FLAG (ibfd))
/* xgettext: c-format */
- msg = _("Warning: %s supports interworking, whereas %s does not");
+ msg = _("Warning: %B supports interworking, whereas %B does not");
else
/* xgettext: c-format */
- msg = _("Warning: %s does not support interworking, whereas %s does");
+ msg = _("Warning: %B does not support interworking, whereas %B does");
- _bfd_error_handler (msg, bfd_archive_filename (ibfd),
- bfd_get_filename (obfd));
+ _bfd_error_handler (msg, ibfd, obfd);
}
}
else
if (APCS_SET (abfd))
{
- /* xgettext: APCS is ARM Prodecure Call Standard, it should not be translated. */
+ /* xgettext: APCS is ARM Procedure Call Standard, it should not be translated. */
fprintf (file, " [APCS-%d]", APCS_26_FLAG (abfd) ? 26 : 32);
if (APCS_FLOAT_FLAG (abfd))
{
if (flag)
/* xgettext: c-format */
- _bfd_error_handler (_("Warning: Not setting interworking flag of %s since it has already been specified as non-interworking"),
- bfd_archive_filename (abfd));
+ _bfd_error_handler (_("Warning: Not setting interworking flag of %B since it has already been specified as non-interworking"),
+ abfd);
else
/* xgettext: c-format */
- _bfd_error_handler (_("Warning: Clearing the interworking flag of %s due to outside request"),
- bfd_archive_filename (abfd));
+ _bfd_error_handler (_("Warning: Clearing the interworking flag of %B due to outside request"),
+ abfd);
flag = 0;
}
{
/* xgettext:c-format */
_bfd_error_handler (("\
-Warning: Clearing the interworking flag of %s because non-interworking code in %s has been linked with it"),
- bfd_get_filename (dest),
- bfd_archive_filename (src));
+Warning: Clearing the interworking flag of %B because non-interworking code in %B has been linked with it"),
+ dest, src);
}
SET_INTERWORK_FLAG (dest, 0);
globals->bfd_of_glue_owner->output_has_begun = TRUE;
}
- {
- asection * arm_arch_section;
-
- /* Look for a .note section. If one is present check
- the machine number encoded in it, and set it to the current
- machine number if it is different. This allows XScale and
- iWMMXt binaries to be merged and the resulting output to be set
- to iWMMXt, even if the first input file had an XScale .note. */
-
- arm_arch_section = bfd_get_section_by_name (abfd, ".note");
-
- if (arm_arch_section != NULL)
- {
- char buffer [4];
-
- if (bfd_get_section_contents (abfd, arm_arch_section, buffer,
- (file_ptr) 0, sizeof buffer))
- {
- unsigned long arm_mach;
-
- /* We have to extract the value this way to allow for a
- host whose endian-ness is different from the target. */
- arm_mach = bfd_get_32 (abfd, buffer);
-
- if (arm_mach != bfd_get_mach (abfd))
- {
- bfd_put_32 (abfd, bfd_get_mach (abfd), buffer);
-
- if (! bfd_set_section_contents (abfd, arm_arch_section, buffer,
- (file_ptr) 0, sizeof buffer))
- (*_bfd_error_handler)
- (_("warning: unable to update contents of .note section in %s"),
- bfd_get_filename (abfd));
- }
- }
- }
- }
-
- return TRUE;
+ return bfd_arm_update_notes (abfd, ARM_NOTE_SECTION);
}
#include "coffcode.h"
#ifndef EXTRA_S_FLAGS
#ifdef COFF_WITH_PE
-#define EXTRA_S_FLAGS (SEC_LINK_ONCE | SEC_LINK_DUPLICATES)
+#define EXTRA_S_FLAGS (SEC_CODE | SEC_LINK_ONCE | SEC_LINK_DUPLICATES)
#else
-#define EXTRA_S_FLAGS 0
+#define EXTRA_S_FLAGS SEC_CODE
#endif
#endif
extern const bfd_target TARGET_BIG_SYM ;
/* Target vectors. */
-CREATE_LITTLE_COFF_TARGET_VEC (TARGET_LITTLE_SYM, TARGET_LITTLE_NAME, D_PAGED, EXTRA_S_FLAGS, TARGET_UNDERSCORE, & TARGET_BIG_SYM)
-CREATE_BIG_COFF_TARGET_VEC (TARGET_BIG_SYM, TARGET_BIG_NAME, D_PAGED, EXTRA_S_FLAGS, TARGET_UNDERSCORE, & TARGET_LITTLE_SYM)
+CREATE_LITTLE_COFF_TARGET_VEC (TARGET_LITTLE_SYM, TARGET_LITTLE_NAME, D_PAGED, EXTRA_S_FLAGS, TARGET_UNDERSCORE, & TARGET_BIG_SYM, COFF_SWAP_TABLE)
+CREATE_BIG_COFF_TARGET_VEC (TARGET_BIG_SYM, TARGET_BIG_NAME, D_PAGED, EXTRA_S_FLAGS, TARGET_UNDERSCORE, & TARGET_LITTLE_SYM, COFF_SWAP_TABLE)