summaryrefslogtreecommitdiff
path: root/bfd/coff-sh.c
diff options
context:
space:
mode:
authorNick Clifton <nickc@redhat.com>2000-02-28 18:56:11 +0000
committerNick Clifton <nickc@redhat.com>2000-02-28 18:56:11 +0000
commit20278ee49a2fd6caf92b879545837982f5524a10 (patch)
treee2cdab5954a605d99aba69c226ae310a6636d268 /bfd/coff-sh.c
parent270472e2b0804783c1993fa834b3f1d09bf5d664 (diff)
downloadbinutils-redhat-20278ee49a2fd6caf92b879545837982f5524a10.tar.gz
Add WinCE support.
Diffstat (limited to 'bfd/coff-sh.c')
-rw-r--r--bfd/coff-sh.c209
1 files changed, 206 insertions, 3 deletions
diff --git a/bfd/coff-sh.c b/bfd/coff-sh.c
index e505a1af9e..2fdde67301 100644
--- a/bfd/coff-sh.c
+++ b/bfd/coff-sh.c
@@ -26,6 +26,11 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
#include "bfdlink.h"
#include "coff/sh.h"
#include "coff/internal.h"
+
+#ifdef COFF_WITH_PE
+#include "coff/pe.h"
+#endif
+
#include "libcoff.h"
/* Internal functions. */
@@ -48,19 +53,57 @@ static bfd_byte *sh_coff_get_relocated_section_contents
PARAMS ((bfd *, struct bfd_link_info *, struct bfd_link_order *,
bfd_byte *, boolean, asymbol **));
+#ifdef COFF_WITH_PE
+/* Can't build import tables with 2**4 alignment. */
+#define COFF_DEFAULT_SECTION_ALIGNMENT_POWER 2
+#else
/* Default section alignment to 2**4. */
-#define COFF_DEFAULT_SECTION_ALIGNMENT_POWER (4)
+#define COFF_DEFAULT_SECTION_ALIGNMENT_POWER 4
+#endif
+
+#ifdef COFF_IMAGE_WITH_PE
+/* Align PE executables. */
+#define COFF_PAGE_SIZE 0x1000
+#endif
/* Generate long file names. */
#define COFF_LONG_FILENAMES
+#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 ATTRIBUTE_UNUSED;
+ reloc_howto_type * howto;
+{
+ return ! howto->pc_relative && howto->type != R_SH_IMAGEBASE;
+}
+#endif
+
/* The supported relocations. There are a lot of relocations defined
in coff/internal.h which we do not expect to ever see. */
static reloc_howto_type sh_coff_howtos[] =
{
EMPTY_HOWTO (0),
EMPTY_HOWTO (1),
+#ifdef COFF_WITH_PE
+ /* Windows CE */
+ HOWTO (R_SH_IMM32CE, /* type */
+ 0, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 32, /* bitsize */
+ false, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_bitfield, /* complain_on_overflow */
+ sh_reloc, /* special_function */
+ "r_imm32ce", /* name */
+ true, /* partial_inplace */
+ 0xffffffff, /* src_mask */
+ 0xffffffff, /* dst_mask */
+ false), /* pcrel_offset */
+#else
EMPTY_HOWTO (2),
+#endif
EMPTY_HOWTO (3), /* R_SH_PCREL8 */
EMPTY_HOWTO (4), /* R_SH_PCREL16 */
EMPTY_HOWTO (5), /* R_SH_HIGH8 */
@@ -116,7 +159,23 @@ static reloc_howto_type sh_coff_howtos[] =
false), /* pcrel_offset */
EMPTY_HOWTO (15),
+#ifdef COFF_WITH_PE
+ HOWTO (R_SH_IMAGEBASE, /* type */
+ 0, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 32, /* bitsize */
+ false, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_bitfield, /* complain_on_overflow */
+ sh_reloc, /* special_function */
+ "rva32", /* name */
+ true, /* partial_inplace */
+ 0xffffffff, /* src_mask */
+ 0xffffffff, /* dst_mask */
+ false), /* pcrel_offset */
+#else
EMPTY_HOWTO (16), /* R_SH_IMM8 */
+#endif
EMPTY_HOWTO (17), /* R_SH_IMM8BY2 */
EMPTY_HOWTO (18), /* R_SH_IMM8BY4 */
EMPTY_HOWTO (19), /* R_SH_IMM4 */
@@ -303,6 +362,7 @@ static reloc_howto_type sh_coff_howtos[] =
/* FIXME: This should not be set here. */
#define __A_MAGIC_SET__
+#ifndef COFF_WITH_PE
/* Swap the r_offset field in and out. */
#define SWAP_IN_RELOC_OFFSET bfd_h_get_32
#define SWAP_OUT_RELOC_OFFSET bfd_h_put_32
@@ -315,6 +375,7 @@ static reloc_howto_type sh_coff_howtos[] =
dst->r_stuff[1] = 'C'; \
} \
while (0)
+#endif
/* Get the value of a symbol, when performing a relocation. */
@@ -334,6 +395,96 @@ get_symbol_value (symbol)
return relocation;
}
+#ifdef COFF_WITH_PE
+/* Convert an rtype to howto for the COFF backend linker.
+ Copied from coff-i386. */
+#define coff_rtype_to_howto coff_sh_rtype_to_howto
+
+static reloc_howto_type *
+coff_sh_rtype_to_howto (abfd, sec, rel, h, sym, addendp)
+ bfd * abfd;
+ asection * sec;
+ struct internal_reloc * rel;
+ struct coff_link_hash_entry * h;
+ struct internal_syment * sym;
+ bfd_vma * addendp;
+{
+ reloc_howto_type * howto;
+
+ howto = sh_coff_howtos + rel->r_type;
+
+ *addendp = 0;
+
+ if (howto->pc_relative)
+ *addendp += sec->vma;
+
+ if (sym != NULL && sym->n_scnum == 0 && sym->n_value != 0)
+ {
+ /* This is a common symbol. The section contents include the
+ size (sym->n_value) as an addend. The relocate_section
+ function will be adding in the final value of the symbol. We
+ need to subtract out the current size in order to get the
+ correct result. */
+ BFD_ASSERT (h != NULL);
+ }
+
+ if (howto->pc_relative)
+ {
+ *addendp -= 4;
+
+ /* If the symbol is defined, then the generic code is going to
+ add back the symbol value in order to cancel out an
+ adjustment it made to the addend. However, we set the addend
+ to 0 at the start of this function. We need to adjust here,
+ to avoid the adjustment the generic code will make. FIXME:
+ This is getting a bit hackish. */
+ if (sym != NULL && sym->n_scnum != 0)
+ *addendp -= sym->n_value;
+ }
+
+ if (rel->r_type == R_SH_IMAGEBASE)
+ *addendp -= pe_data (sec->output_section->owner)->pe_opthdr.ImageBase;
+
+ return howto;
+}
+
+/* This structure is used to map BFD reloc codes to SH PE relocs. */
+struct shcoff_reloc_map
+{
+ unsigned char bfd_reloc_val;
+ unsigned char shcoff_reloc_val;
+};
+
+/* An array mapping BFD reloc codes to SH PE relocs. */
+static const struct shcoff_reloc_map sh_reloc_map[] =
+{
+ { BFD_RELOC_32, R_SH_IMM32CE },
+ { BFD_RELOC_RVA, R_SH_IMAGEBASE },
+ { BFD_RELOC_CTOR, R_SH_IMM32CE },
+};
+
+/* Given a BFD reloc code, return the howto structure for the
+ corresponding SH PE reloc. */
+#define coff_bfd_reloc_type_lookup sh_coff_reloc_type_lookup
+
+static reloc_howto_type *
+sh_coff_reloc_type_lookup (abfd, code)
+ bfd * abfd ATTRIBUTE_UNUSED;
+ bfd_reloc_code_real_type code;
+{
+ unsigned int i;
+
+ for (i = 0; i < sizeof (sh_reloc_map) / sizeof (struct shcoff_reloc_map); i++)
+ {
+ if (sh_reloc_map[i].bfd_reloc_val == code)
+ return &sh_coff_howtos[(int) sh_reloc_map[i].shcoff_reloc_val];
+ }
+
+ fprintf (stderr, "SH Error: unknown reloc type %d\n", code);
+ return NULL;
+}
+#endif /* COFF_WITH_PE */
+
/* This macro is used in coffcode.h to get the howto corresponding to
an internal reloc. */
@@ -401,6 +552,10 @@ sh_reloc (abfd, reloc_entry, symbol_in, data, input_section, output_bfd,
/* Almost all relocs have to do with relaxing. If any work must be
done for them, it has been done in sh_relax_section. */
if (r_type != R_SH_IMM32
+#ifdef COFF_WITH_PE
+ && r_type != R_SH_IMM32CE
+ && r_type != R_SH_IMAGEBASE
+#endif
&& (r_type != R_SH_PCDISP
|| (symbol_in->flags & BSF_LOCAL) != 0))
return bfd_reloc_ok;
@@ -414,10 +569,21 @@ sh_reloc (abfd, reloc_entry, symbol_in, data, input_section, output_bfd,
switch (r_type)
{
case R_SH_IMM32:
+#ifdef COFF_WITH_PE
+ case R_SH_IMM32CE:
+#endif
insn = bfd_get_32 (abfd, hit_data);
insn += sym_value + reloc_entry->addend;
bfd_put_32 (abfd, insn, hit_data);
break;
+#ifdef COFF_WITH_PE
+ case R_SH_IMAGEBASE:
+ insn = bfd_get_32 (abfd, hit_data);
+ insn += (sym_value + reloc_entry->addend
+ - pe_data (input_section->output_section->owner)->pe_opthdr.ImageBase);
+ bfd_put_32 (abfd, insn, hit_data);
+ break;
+#endif
case R_SH_PCDISP:
insn = bfd_get_16 (abfd, hit_data);
sym_value += reloc_entry->addend;
@@ -618,7 +784,14 @@ sh_relax_section (abfd, sec, link_info, again)
paddr += sec->vma;
for (irelfn = internal_relocs; irelfn < irelend; irelfn++)
if (irelfn->r_vaddr == paddr
+#ifdef COFF_WITH_PE
+ && (irelfn->r_type == R_SH_IMM32
+ || irelfn->r_type == R_SH_IMM32CE
+ || irelfn->r_type == R_SH_IMAGEBASE))
+
+#else
&& irelfn->r_type == R_SH_IMM32)
+#endif
break;
if (irelfn >= irelend)
{
@@ -996,6 +1169,10 @@ sh_relax_delete_bytes (abfd, sec, addr, count)
break;
case R_SH_IMM32:
+#ifdef COFF_WITH_PE
+ case R_SH_IMM32CE:
+ case R_SH_IMAGEBASE:
+#endif
/* If this reloc is against a symbol defined in this
section, and the symbol will not be adjusted below, we
must check the addend to see it will put the value in
@@ -1212,7 +1389,13 @@ sh_relax_delete_bytes (abfd, sec, addr, count)
{
struct internal_syment sym;
+#ifdef COFF_WITH_PE
+ if (irelscan->r_type != R_SH_IMM32
+ && irelscan->r_type != R_SH_IMAGEBASE
+ && irelscan->r_type != R_SH_IMM32CE)
+#else
if (irelscan->r_type != R_SH_IMM32)
+#endif
continue;
bfd_coff_swap_sym_in (abfd,
@@ -1364,7 +1547,7 @@ struct sh_opcode
mask value in the sh_major_opcode structure. */
unsigned short opcode;
/* Flags for this instruction. */
- unsigned flags;
+ unsigned short flags;
};
/* Flag which appear in the sh_opcode structure. */
@@ -1993,6 +2176,7 @@ sh_insn_uses_reg (insn, op, reg)
return false;
}
+
/* See whether an instruction sets a general purpose register. */
static boolean
@@ -2200,6 +2384,7 @@ sh_load_use (i1, op1, i2, op2)
return false;
}
+#ifndef COFF_IMAGE_WITH_PE
/* Try to align loads and stores within a span of memory. This is
called by both the ELF and the COFF sh targets. ABFD and SEC are
the BFD and section we are examining. CONTENTS is the contents of
@@ -2419,6 +2604,7 @@ _bfd_sh_align_load_span (abfd, sec, contents, swap, relocs,
return true;
}
+#endif
/* Look for loads and stores which we can align to four byte
boundaries. See the longer comment above sh_relax_section for why
@@ -2659,6 +2845,10 @@ sh_relocate_section (output_bfd, info, input_bfd, input_section, contents,
/* Almost all relocs have to do with relaxing. If any work must
be done for them, it has been done in sh_relax_section. */
if (rel->r_type != R_SH_IMM32
+#ifdef COFF_WITH_PE
+ && rel->r_type != R_SH_IMM32CE
+ && rel->r_type != R_SH_IMAGEBASE
+#endif
&& rel->r_type != R_SH_PCDISP)
continue;
@@ -2703,6 +2893,11 @@ sh_relocate_section (output_bfd, info, input_bfd, input_section, contents,
return false;
}
+#ifdef COFF_WITH_PE
+ if (rel->r_type == R_SH_IMAGEBASE)
+ addend -= pe_data (input_section->output_section->owner)->pe_opthdr.ImageBase;
+#endif
+
val = 0;
if (h == NULL)
@@ -2899,7 +3094,9 @@ sh_coff_get_relocated_section_contents (output_bfd, link_info, link_order,
/* The target vectors. */
+#ifndef TARGET_SHL_SYM
CREATE_BIG_COFF_TARGET_VEC (shcoff_vec, "coff-sh", BFD_IS_RELAXABLE, 0, '_', NULL)
+#endif
#ifdef TARGET_SHL_SYM
#define TARGET_SYM TARGET_SHL_SYM
@@ -2911,9 +3108,14 @@ CREATE_BIG_COFF_TARGET_VEC (shcoff_vec, "coff-sh", BFD_IS_RELAXABLE, 0, '_', NUL
#define TARGET_SHL_NAME "coff-shl"
#endif
+#ifdef COFF_WITH_PE
+CREATE_LITTLE_COFF_TARGET_VEC (TARGET_SYM, TARGET_SHL_NAME, BFD_IS_RELAXABLE,
+ SEC_CODE | SEC_DATA, '_', NULL);
+#else
CREATE_LITTLE_COFF_TARGET_VEC (TARGET_SYM, TARGET_SHL_NAME, BFD_IS_RELAXABLE, 0, '_', NULL)
+#endif
-
+#ifndef TARGET_SHL_SYM
/* Some people want versions of the SH COFF target which do not align
to 16 byte boundaries. We implement that by adding a couple of new
target vectors. These are just like the ones above, but they
@@ -3089,3 +3291,4 @@ const bfd_target shlcoff_small_vec =
(PTR) &bfd_coff_small_swap_table
};
+#endif