aboutsummaryrefslogtreecommitdiff
path: root/bfd/coff-arm.c
diff options
context:
space:
mode:
authorNick Clifton <nickc@redhat.com>1997-05-14 17:00:43 +0000
committerNick Clifton <nickc@redhat.com>1997-05-14 17:00:43 +0000
commit46686c7839c7872d851d9a43df81953dbfc25dc0 (patch)
treed427926af7ced3e7d027b1ffe36d252f760cb59e /bfd/coff-arm.c
parentc23cc10a8fc7518f564bb69bdb7726b17982ae3b (diff)
downloadgdb-46686c7839c7872d851d9a43df81953dbfc25dc0.zip
gdb-46686c7839c7872d851d9a43df81953dbfc25dc0.tar.gz
gdb-46686c7839c7872d851d9a43df81953dbfc25dc0.tar.bz2
Added support for storing ARM Procedure Calling Standard variant, and ARM
architecture variant in the BFD and COFF structures. This goes towards fixing PRs 11709 and 11326 and will integrate with future updates to LD and GCC.
Diffstat (limited to 'bfd/coff-arm.c')
-rw-r--r--bfd/coff-arm.c224
1 files changed, 216 insertions, 8 deletions
diff --git a/bfd/coff-arm.c b/bfd/coff-arm.c
index a33bbb2..1f0e348 100644
--- a/bfd/coff-arm.c
+++ b/bfd/coff-arm.c
@@ -1,5 +1,5 @@
/* BFD back-end for ARM 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/arm.h"
@@ -44,7 +43,9 @@ aoutarm_fix_pcrel_26 PARAMS ((bfd *, arelent *, asymbol *, PTR,
static bfd_reloc_status_type coff_arm_reloc
PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **));
-
+static boolean coff_arm_adjust_symndx
+ PARAMS ((bfd *, struct bfd_link_info *, bfd *, asection *,
+ struct internal_reloc *, boolean *));
/* Used by the assembler. */
static bfd_reloc_status_type
@@ -216,7 +217,7 @@ static reloc_howto_type aoutarm_std_reloc_howto[] =
"ARM26D",
true,
0x00ffffff,
- 0x00ffffff,
+ 0x0,
false),
{-1},
HOWTO( 9,
@@ -294,6 +295,37 @@ coff_arm_rtype_to_howto (abfd, sec, rel, h, sym, addendp)
{
*addendp -= pe_data(sec->output_section->owner)->pe_opthdr.ImageBase;
}
+
+ /* 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
+ this case without pcrel_offset set, and adjust the addend to
+ compensate. */
+ if (rel->r_type == 3
+ && h != NULL
+ && (h->root.type == bfd_link_hash_defined
+ || h->root.type == bfd_link_hash_defweak)
+ && h->root.u.def.section->output_section == sec->output_section)
+ {
+ static reloc_howto_type fake_arm26_reloc =
+ HOWTO (3,
+ 2,
+ 2,
+ 26,
+ true,
+ 0,
+ complain_overflow_signed,
+ aoutarm_fix_pcrel_26 ,
+ "ARM26",
+ false,
+ 0x00ffffff,
+ 0x00ffffff,
+ false);
+
+ *addendp -= rel->r_vaddr - sec->vma;
+ return &fake_arm26_reloc;
+ }
+
return howto;
}
@@ -419,6 +451,170 @@ arm_reloc_type_lookup(abfd,code)
/* We use the special COFF backend linker. */
#define coff_relocate_section _bfd_coff_generic_relocate_section
+/* When doing a relocateable link, we want to convert ARM26 relocs
+ into ARM26D relocs. */
+
+static boolean
+coff_arm_adjust_symndx (obfd, info, ibfd, sec, irel, adjustedp)
+ bfd *obfd;
+ struct bfd_link_info *info;
+ bfd *ibfd;
+ asection *sec;
+ struct internal_reloc *irel;
+ boolean *adjustedp;
+{
+ if (irel->r_type == 3)
+ {
+ struct coff_link_hash_entry *h;
+
+ h = obj_coff_sym_hashes (ibfd)[irel->r_symndx];
+ if (h != NULL
+ && (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;
+ }
+ *adjustedp = false;
+ return true;
+}
+
+
+#define APCS_FLAG( abfd ) (coff_data (abfd)->flags & F_APCS_26)
+#define APCS_SET( abfd ) (coff_data (abfd)->flags & F_APCS_SET)
+#define SET_APCS_FLAG( abfd, flg ) (coff_data (abfd)->flags = (coff_data (abfd)->flags & ~ F_APCS_26) | (flg | F_APCS_SET))
+
+/* 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. */
+
+boolean
+coff_arm_bfd_merge_private_bfd_data (ibfd, obfd)
+ bfd * ibfd;
+ bfd * obfd;
+{
+ BFD_ASSERT (ibfd != NULL && obfd != NULL)
+
+ if (ibfd == obfd)
+ return true;
+
+ /* If the two formats are different we cannot check anything */
+ if (ibfd->xvec != obfd->xvec)
+ return true;
+
+ /* Verify that the APCS is the same for the two BFDs */
+ if (APCS_SET (ibfd))
+ {
+ if (APCS_SET (obfd))
+ {
+ /* If the src and dest have different APCS flag bits set, fail */
+ if (APCS_FLAG (obfd) != APCS_FLAG (ibfd))
+ {
+ _bfd_error_handler
+ ("%s: ERROR: compiled for APCS-%d whereas target %s uses APCS-%d",
+ bfd_get_filename (ibfd), APCS_FLAG (ibfd) ? 26 : 32,
+ bfd_get_filename (obfd), APCS_FLAG (obfd) ? 26 : 32
+ );
+
+ bfd_set_error (bfd_error_wrong_format);
+ return false;
+ }
+ }
+ else
+ SET_APCS_FLAG (obfd, APCS_FLAG (ibfd));
+ }
+
+ return true;
+}
+
+
+/* Display the flags field */
+
+boolean
+coff_arm_bfd_print_private_bfd_data (abfd, ptr)
+ bfd * abfd;
+ PTR ptr;
+{
+ FILE * file = (FILE *) ptr;
+
+ BFD_ASSERT (abfd != NULL && ptr != NULL)
+
+ fprintf (file, "private flags = %x", coff_data( abfd )->flags);
+
+ if (APCS_SET (abfd))
+ fprintf (file, ": [APCS-%d]", APCS_FLAG( abfd ) ? 26 : 32);
+
+ fputc ('\n', file);
+
+ return true;
+}
+
+
+/* Copies the given flags into the coff_tdata.flags field.
+ Typically these flags come from the f_flags[] field of
+ the COFF filehdr structure, which contains important,
+ target specific information. */
+
+boolean
+coff_arm_bfd_set_private_flags (abfd, flags)
+ bfd * abfd;
+ flagword flags;
+{
+ int flag;
+
+ BFD_ASSERT (abfd != NULL);
+
+ flag = (flags & F_APCS26) ? F_APCS_26 : 0;
+
+ /* Make sure that the APCS field has not been initialised to the opposite value */
+ if (APCS_SET (abfd) && (APCS_FLAG (abfd) != flag))
+ return false;
+
+ SET_APCS_FLAG (abfd, flag);
+
+ return true;
+}
+
+
+/* Copy the important parts of the target specific data
+ from one instance of a BFD to another. */
+
+boolean
+coff_arm_bfd_copy_private_bfd_data (src, dest)
+ bfd * src;
+ bfd * dest;
+{
+ BFD_ASSERT (src != NULL && dest != NULL)
+
+ if (src == dest)
+ return true;
+
+ /* If the destination is not in the same format as the source, do not do the copy */
+ if (src->xvec != dest->xvec)
+ return true;
+
+ /* copy the flags field */
+ if (APCS_SET (src))
+ {
+ if (APCS_SET (dest))
+ {
+ /* If the src and dest have different APCS flag bits set, fail */
+ if (APCS_FLAG (dest) != APCS_FLAG (src))
+ return false;
+ }
+ else
+ SET_APCS_FLAG (dest, APCS_FLAG (src));
+ }
+
+ return true;
+}
+
+
+#define coff_adjust_symndx coff_arm_adjust_symndx
+#define coff_bfd_merge_private_bfd_data coff_arm_bfd_merge_private_bfd_data
+#define coff_bfd_print_private_bfd_data coff_arm_bfd_print_private_bfd_data
+#define coff_bfd_set_private_flags coff_arm_bfd_set_private_flags
+#define coff_bfd_copy_private_bfd_data coff_arm_bfd_copy_private_bfd_data
#include "coffcode.h"
@@ -435,14 +631,20 @@ armcoff_little_vec =
"coff-arm-little",
#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
@@ -492,14 +694,20 @@ armcoff_big_vec =
"coff-arm-big",
#endif
bfd_target_coff_flavour,
- true, /* data byte order is big */
- true, /* header byte order is big */
+ BFD_ENDIAN_BIG, /* data byte order is big */
+ BFD_ENDIAN_BIG, /* header byte order is big */
(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