aboutsummaryrefslogtreecommitdiff
path: root/bfd/elf32-v850.c
diff options
context:
space:
mode:
Diffstat (limited to 'bfd/elf32-v850.c')
-rw-r--r--bfd/elf32-v850.c135
1 files changed, 120 insertions, 15 deletions
diff --git a/bfd/elf32-v850.c b/bfd/elf32-v850.c
index 22921b7..4c42d6d 100644
--- a/bfd/elf32-v850.c
+++ b/bfd/elf32-v850.c
@@ -26,6 +26,9 @@ static reloc_howto_type *bfd_elf32_bfd_reloc_type_lookup
PARAMS ((bfd *abfd, bfd_reloc_code_real_type code));
static void v850_info_to_howto_rel
PARAMS ((bfd *, arelent *, Elf32_Internal_Rel *));
+static bfd_reloc_status_type bfd_elf32_v850_reloc
+ PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **));
+
/* Try to minimize the amount of space occupied by relocation tables
@@ -71,7 +74,7 @@ static reloc_howto_type elf_v850_howto_table[] =
true, /* pc_relative */
0, /* bitpos */
complain_overflow_bitfield, /* complain_on_overflow */
- bfd_elf_generic_reloc, /* special_function */
+ bfd_elf32_v850_reloc, /* special_function */
"R_V850_9_PCREL", /* name */
false, /* partial_inplace */
0x00ffffff, /* src_mask */
@@ -86,7 +89,7 @@ static reloc_howto_type elf_v850_howto_table[] =
true, /* pc_relative */
7, /* bitpos */
complain_overflow_signed, /* complain_on_overflow */
- bfd_elf_generic_reloc, /* special_function */
+ bfd_elf32_v850_reloc, /* special_function */
"R_V850_22_PCREL", /* name */
false, /* partial_inplace */
0x07ffff80, /* src_mask */
@@ -99,9 +102,9 @@ static reloc_howto_type elf_v850_howto_table[] =
1, /* size (0 = byte, 1 = short, 2 = long) */
16, /* bitsize */
false, /* pc_relative */
- 16, /* bitpos */
+ 0, /* bitpos */
complain_overflow_dont,/* complain_on_overflow */
- bfd_elf_generic_reloc, /* special_function */
+ bfd_elf32_v850_reloc, /* special_function */
"R_V850_HI16_S", /* name */
true, /* partial_inplace */
0xffff, /* src_mask */
@@ -114,9 +117,9 @@ static reloc_howto_type elf_v850_howto_table[] =
1, /* size (0 = byte, 1 = short, 2 = long) */
16, /* bitsize */
false, /* pc_relative */
- 16, /* bitpos */
+ 0, /* bitpos */
complain_overflow_dont,/* complain_on_overflow */
- bfd_elf_generic_reloc, /* special_function */
+ bfd_elf32_v850_reloc, /* special_function */
"R_V850_HI16", /* name */
true, /* partial_inplace */
0xffff, /* src_mask */
@@ -129,7 +132,7 @@ static reloc_howto_type elf_v850_howto_table[] =
1, /* size (0 = byte, 1 = short, 2 = long) */
16, /* bitsize */
false, /* pc_relative */
- 16, /* bitpos */
+ 0, /* bitpos */
complain_overflow_dont,/* complain_on_overflow */
bfd_elf_generic_reloc, /* special_function */
"R_V850_LO16", /* name */
@@ -148,8 +151,8 @@ static reloc_howto_type elf_v850_howto_table[] =
complain_overflow_dont,/* complain_on_overflow */
bfd_elf_generic_reloc, /* special_function */
"R_V850_32", /* name */
- false, /* partial_inplace */
- 0, /* src_mask */
+ true, /* partial_inplace */
+ 0xffffffff, /* src_mask */
0xffffffff, /* dst_mask */
false), /* pcrel_offset */
@@ -163,8 +166,8 @@ static reloc_howto_type elf_v850_howto_table[] =
complain_overflow_dont,/* complain_on_overflow */
bfd_elf_generic_reloc, /* special_function */
"R_V850_16", /* name */
- false, /* partial_inplace */
- 0, /* src_mask */
+ true, /* partial_inplace */
+ 0xffff, /* src_mask */
0xffff, /* dst_mask */
false), /* pcrel_offset */
@@ -178,8 +181,8 @@ static reloc_howto_type elf_v850_howto_table[] =
complain_overflow_dont,/* complain_on_overflow */
bfd_elf_generic_reloc, /* special_function */
"R_V850_8", /* name */
- false, /* partial_inplace */
- 0, /* src_mask */
+ true, /* partial_inplace */
+ 0xff, /* src_mask */
0xff, /* dst_mask */
false), /* pcrel_offset */
};
@@ -238,8 +241,110 @@ v850_info_to_howto_rel (abfd, cache_ptr, dst)
cache_ptr->howto = &elf_v850_howto_table[r_type];
}
-#define TARGET_BIG_SYM bfd_elf32_v850_vec
-#define TARGET_BIG_NAME "elf32-v850"
+static bfd_reloc_status_type
+bfd_elf32_v850_reloc (abfd, reloc, symbol, data, isection, obfd, err)
+ bfd *abfd;
+ arelent *reloc;
+ asymbol *symbol;
+ PTR data;
+ asection *isection;
+ bfd *obfd;
+ char **err;
+{
+ if (obfd != (bfd *) NULL
+ && (symbol->flags & BSF_SECTION_SYM) == 0
+ && (! reloc->howto->partial_inplace
+ || reloc->addend == 0))
+ {
+ reloc->address += isection->output_offset;
+ return bfd_reloc_ok;
+ }
+ else if (obfd != NULL)
+ {
+ return bfd_reloc_continue;
+ }
+
+ /* We handle final linking of some relocs ourselves. */
+ {
+ long relocation, insn;
+
+ /* Is the address of the relocation really within the section? */
+ if (reloc->address > isection->_cooked_size)
+ return bfd_reloc_outofrange;
+
+ /* Work out which section the relocation is targetted at and the
+ initial relocation command value. */
+
+ /* Get symbol value. (Common symbols are special.) */
+ if (bfd_is_com_section (symbol->section))
+ relocation = 0;
+ else
+ relocation = symbol->value;
+
+ /* Convert input-section-relative symbol value to absolute + addend. */
+ relocation += symbol->section->output_section->vma;
+ relocation += symbol->section->output_offset;
+ relocation += reloc->addend;
+
+ if (reloc->howto->pc_relative == true)
+ {
+ /* Here the variable relocation holds the final address of the
+ symbol we are relocating against, plus any addend. */
+ relocation -= isection->output_section->vma + isection->output_offset;
+
+ /* Deal with pcrel_offset */
+ relocation -= reloc->address;
+ }
+
+ /* I've got no clue... */
+ reloc->addend = 0;
+
+ if (reloc->howto->type == R_V850_22_PCREL)
+ {
+ if (relocation > 0x1ffff || relocation < -0x200000)
+ return bfd_reloc_overflow;
+
+ if ((relocation % 2) != 0)
+ return bfd_reloc_dangerous;
+
+ insn = bfd_get_32 (abfd, (bfd_byte *) data + reloc->address);
+ insn |= (((relocation & 0xfffe) << 16)
+ | ((relocation & 0x3f0000) >> 16));
+ bfd_put_32 (abfd, insn, (bfd_byte *)data + reloc->address);
+ return bfd_reloc_ok;
+ }
+ else if (reloc->howto->type == R_V850_9_PCREL)
+ {
+ if (relocation > 0xff || relocation < -0x100)
+ return bfd_reloc_overflow;
+
+ if ((relocation % 2) != 0)
+ return bfd_reloc_dangerous;
+
+ insn = bfd_get_16 (abfd, (bfd_byte *) data + reloc->address);
+ insn |= ((relocation & 0x1f0) << 7) | ((relocation & 0x0e) << 3);
+ bfd_put_16 (abfd, insn, (bfd_byte *)data + reloc->address);
+ return bfd_reloc_ok;
+ }
+ else if (reloc->howto->type == R_V850_HI16_S)
+ {
+ relocation = (relocation >> 16) + ((relocation & 0x8000) != 0);
+ bfd_put_16 (abfd, relocation, (bfd_byte *)data + reloc->address);
+ return bfd_reloc_ok;
+ }
+ else if (reloc->howto->type == R_V850_HI16)
+ {
+ relocation = (relocation >> 16);
+ bfd_put_16 (abfd, relocation, (bfd_byte *)data + reloc->address);
+ return bfd_reloc_ok;
+ }
+ }
+
+ return bfd_reloc_continue;
+}
+
+#define TARGET_LITTLE_SYM bfd_elf32_v850_vec
+#define TARGET_LITTLE_NAME "elf32-v850"
#define ELF_ARCH bfd_arch_v850
#define ELF_MACHINE_CODE EM_CYGNUS_V850
#define ELF_MAXPAGESIZE 0x1000