Index: bfd/elf32-v850.c |
diff --git a/bfd/elf32-v850.c b/bfd/elf32-v850.c |
index 11fbbb4cbc302d2e83a4a839401a1277f518d2ed..6528dc18670f512856d36b3fe35e6a7e65af4f18 100644 |
--- a/bfd/elf32-v850.c |
+++ b/bfd/elf32-v850.c |
@@ -1,7 +1,5 @@ |
/* V850-specific support for 32-bit ELF |
- Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, |
- 2006, 2007, 2008, 2009, 2010, 2011, 2012 |
- Free Software Foundation, Inc. |
+ Copyright 1996-2013 Free Software Foundation, Inc. |
This file is part of BFD, the Binary File Descriptor library. |
@@ -55,7 +53,7 @@ v850_elf_check_relocs (bfd *abfd, |
struct elf_link_hash_entry **sym_hashes; |
const Elf_Internal_Rela *rel; |
const Elf_Internal_Rela *rel_end; |
- enum v850_reloc_type r_type; |
+ unsigned int r_type; |
int other = 0; |
const char *common = NULL; |
@@ -85,34 +83,16 @@ v850_elf_check_relocs (bfd *abfd, |
while (h->root.type == bfd_link_hash_indirect |
|| h->root.type == bfd_link_hash_warning) |
h = (struct elf_link_hash_entry *) h->root.u.i.link; |
+ |
+ /* PR15323, ref flags aren't set for references in the same |
+ object. */ |
+ h->root.non_ir_ref = 1; |
} |
- r_type = (enum v850_reloc_type) ELF32_R_TYPE (rel->r_info); |
+ r_type = ELF32_R_TYPE (rel->r_info); |
switch (r_type) |
{ |
default: |
- case R_V850_NONE: |
- case R_V850_9_PCREL: |
- case R_V850_16_PCREL: |
- case R_V850_17_PCREL: |
- case R_V850_22_PCREL: |
- case R_V850_32_PCREL: |
- case R_V850_32_ABS: |
- case R_V850_HI16: |
- case R_V850_HI16_S: |
- case R_V850_LO16: |
- case R_V850_LO16_S1: |
- case R_V850_LO16_SPLIT_OFFSET: |
- case R_V850_23: |
- case R_V850_ABS32: |
- case R_V850_REL32: |
- case R_V850_16: |
- case R_V850_16_S1: |
- case R_V850_16_SPLIT_OFFSET: |
- case R_V850_8: |
- case R_V850_CALLT_6_7_OFFSET: |
- case R_V850_CALLT_15_16_OFFSET: |
- case R_V850_CALLT_16_16_OFFSET: |
break; |
/* This relocation describes the C++ object vtable hierarchy. |
@@ -134,6 +114,9 @@ v850_elf_check_relocs (bfd *abfd, |
case R_V850_SDA_16_16_SPLIT_OFFSET: |
case R_V850_SDA_16_16_OFFSET: |
case R_V850_SDA_15_16_OFFSET: |
+ case R_V810_GPWLO_1: |
+ case R_V850_HWLO: |
+ case R_V850_HWLO_1: |
other = V850_OTHER_SDA; |
common = ".scommon"; |
goto small_data_common; |
@@ -510,13 +493,19 @@ v850_elf_perform_relocation (bfd *abfd, |
switch (r_type) |
{ |
default: |
+#ifdef DEBUG |
+ fprintf (stderr, "reloc number %d not recognised\n", r_type); |
+#endif |
return bfd_reloc_notsupported; |
case R_V850_REL32: |
case R_V850_ABS32: |
+ case R_V810_WORD: |
+ case R_V850_PC32: |
bfd_put_32 (abfd, addend, address); |
return bfd_reloc_ok; |
+ case R_V850_WLO23: |
case R_V850_23: |
insn = bfd_get_32 (abfd, address); |
insn &= ~((0x7f << 4) | (0x7fff80 << (16-7))); |
@@ -524,6 +513,7 @@ v850_elf_perform_relocation (bfd *abfd, |
bfd_put_32 (abfd, (bfd_vma) insn, address); |
return bfd_reloc_ok; |
+ case R_V850_PCR22: |
case R_V850_22_PCREL: |
if (saddend > 0x1fffff || saddend < -0x200000) |
return bfd_reloc_overflow; |
@@ -537,6 +527,7 @@ v850_elf_perform_relocation (bfd *abfd, |
bfd_put_32 (abfd, (bfd_vma) insn, address); |
return bfd_reloc_ok; |
+ case R_V850_PC17: |
case R_V850_17_PCREL: |
if (saddend > 0xffff || saddend < -0x10000) |
return bfd_reloc_overflow; |
@@ -549,6 +540,7 @@ v850_elf_perform_relocation (bfd *abfd, |
insn |= ((addend & 0xfffe) << 16) | ((addend & 0x10000) >> (16-4)); |
break; |
+ case R_V850_PC16U: |
case R_V850_16_PCREL: |
if ((saddend < -0xffff) || (saddend > 0)) |
return bfd_reloc_overflow; |
@@ -561,6 +553,7 @@ v850_elf_perform_relocation (bfd *abfd, |
insn |= (-addend & 0xfffe); |
break; |
+ case R_V850_PC9: |
case R_V850_9_PCREL: |
if (saddend > 0xff || saddend < -0x100) |
return bfd_reloc_overflow; |
@@ -573,12 +566,14 @@ v850_elf_perform_relocation (bfd *abfd, |
insn |= ((addend & 0x1f0) << 7) | ((addend & 0x0e) << 3); |
break; |
+ case R_V810_WHI: |
case R_V850_HI16: |
addend += (bfd_get_16 (abfd, address) << 16); |
addend = (addend >> 16); |
insn = addend; |
break; |
+ case R_V810_WHI1: |
case R_V850_HI16_S: |
/* Remember where this relocation took place. */ |
remember_hi16s_reloc (abfd, addend, address); |
@@ -593,12 +588,14 @@ v850_elf_perform_relocation (bfd *abfd, |
insn = addend; |
break; |
+ case R_V810_WLO: |
case R_V850_LO16: |
insn = bfd_get_16 (abfd, address); |
if (! v850_elf_perform_lo16_relocation (abfd, &insn, addend)) |
return bfd_reloc_overflow; |
break; |
+ case R_V810_BYTE: |
case R_V850_8: |
addend += (char) bfd_get_8 (abfd, address); |
@@ -624,7 +621,7 @@ v850_elf_perform_relocation (bfd *abfd, |
case R_V850_CALLT_15_16_OFFSET: |
insn = bfd_get_16 (abfd, address); |
- addend += insn & 0xfffe;; |
+ addend += insn & 0xfffe; |
saddend = (bfd_signed_vma) addend; |
@@ -652,6 +649,7 @@ v850_elf_perform_relocation (bfd *abfd, |
break; |
case R_V850_16: |
+ case R_V810_HWORD: |
case R_V850_SDA_16_16_OFFSET: |
case R_V850_ZDA_16_16_OFFSET: |
case R_V850_TDA_16_16_OFFSET: |
@@ -668,6 +666,7 @@ v850_elf_perform_relocation (bfd *abfd, |
case R_V850_16_S1: |
case R_V850_SDA_15_16_OFFSET: |
case R_V850_ZDA_15_16_OFFSET: |
+ case R_V810_GPWLO_1: |
insn = bfd_get_16 (abfd, address); |
addend += (insn & 0xfffe); |
@@ -756,6 +755,9 @@ v850_elf_perform_relocation (bfd *abfd, |
insn |= addend; |
break; |
+ case R_V810_WLO_1: |
+ case R_V850_HWLO: |
+ case R_V850_HWLO_1: |
case R_V850_LO16_S1: |
insn = bfd_get_16 (abfd, address); |
result = insn & 0xfffe; |
@@ -768,6 +770,7 @@ v850_elf_perform_relocation (bfd *abfd, |
bfd_put_16 (abfd, insn, address); |
return bfd_reloc_ok; |
+ case R_V850_BLO: |
case R_V850_LO16_SPLIT_OFFSET: |
insn = bfd_get_32 (abfd, address); |
result = ((insn & 0xfffe0000) >> 16) | ((insn & 0x20) >> 5); |
@@ -886,7 +889,7 @@ v850_elf_ignore_reloc (bfd *abfd ATTRIBUTE_UNUSED, |
} |
/* Note: It is REQUIRED that the 'type' value of each entry |
in this array match the index of the entry in the array. |
- SeeAlso: RELOC_NUBMER in include/elf/v850.h */ |
+ SeeAlso: RELOC_NUBMER in include/elf/v850.h. */ |
static reloc_howto_type v850_elf_howto_table[] = |
{ |
/* This reloc does nothing. */ |
@@ -1742,6 +1745,109 @@ static const struct v850_elf_reloc_map v850_elf_reloc_map[] = |
{ BFD_RELOC_V850_CODE, R_V850_CODE }, |
{ BFD_RELOC_V850_DATA, R_V850_DATA }, |
}; |
+ |
+#define V800_RELOC(name,sz,bit,shift,complain,pcrel,resolver) \ |
+ HOWTO (name, shift, sz, bit, pcrel, 0, complain_overflow_ ## complain, \ |
+ bfd_elf_ ## resolver ## _reloc, #name, FALSE, 0, ~0, FALSE) |
+ |
+#define V800_EMPTY(name) EMPTY_HOWTO (name - R_V810_NONE) |
+ |
+#define bfd_elf_v850_reloc v850_elf_reloc |
+ |
+/* Note: It is REQUIRED that the 'type' value (R_V810_...) of each entry |
+ in this array match the index of the entry in the array minus 0x30. |
+ See: bfd_elf_v850_relocate_section(), v800_elf_reloc_type_lookup() |
+ and v800_elf_info_to_howto(). */ |
+ |
+static reloc_howto_type v800_elf_howto_table[] = |
+{ |
+ V800_RELOC (R_V810_NONE, 0, 0, 0, dont, FALSE, generic), /* Type = 0x30 */ |
+ V800_RELOC (R_V810_BYTE, 0, 8, 0, dont, FALSE, generic), |
+ V800_RELOC (R_V810_HWORD, 1, 16, 0, dont, FALSE, generic), |
+ V800_RELOC (R_V810_WORD, 2, 32, 0, dont, FALSE, generic), |
+ V800_RELOC (R_V810_WLO, 1, 16, 0, dont, FALSE, generic), |
+ V800_RELOC (R_V810_WHI, 1, 16, 0, dont, FALSE, generic), |
+ V800_RELOC (R_V810_WHI1, 1, 16, 0, dont, FALSE, generic), |
+ V800_RELOC (R_V810_GPBYTE, 0, 8, 0, dont, FALSE, v850), |
+ V800_RELOC (R_V810_GPHWORD, 1, 16, 0, dont, FALSE, v850), |
+ V800_RELOC (R_V810_GPWORD, 2, 32, 0, dont, FALSE, v850), |
+ V800_RELOC (R_V810_GPWLO, 1, 16, 0, dont, FALSE, v850), |
+ V800_RELOC (R_V810_GPWHI, 1, 16, 0, dont, FALSE, v850), |
+ V800_RELOC (R_V810_GPWHI1, 1, 16, 0, dont, FALSE, v850), |
+ V800_RELOC (R_V850_HWLO, 1, 16, 0, dont, FALSE, generic), |
+ V800_EMPTY (R_V810_reserved1), |
+ V800_RELOC (R_V850_EP7BIT, 0, 7, 0, unsigned, FALSE, v850), |
+ V800_RELOC (R_V850_EPHBYTE, 0, 8, 1, unsigned, FALSE, v850), |
+ V800_RELOC (R_V850_EPWBYTE, 0, 8, 2, unsigned, FALSE, v850), |
+ V800_RELOC (R_V850_REGHWLO, 1, 16, 0, dont, FALSE, v850), |
+ V800_EMPTY (R_V810_reserved2), |
+ V800_RELOC (R_V850_GPHWLO, 1, 16, 0, dont, FALSE, v850), |
+ V800_EMPTY (R_V810_reserved3), |
+ V800_RELOC (R_V850_PCR22, 2, 22, 0, signed, TRUE, generic), |
+ V800_RELOC (R_V850_BLO, 2, 24, 0, dont, FALSE, v850), |
+ V800_RELOC (R_V850_EP4BIT, 0, 4, 0, unsigned, FALSE, v850), |
+ V800_RELOC (R_V850_EP5BIT, 0, 5, 0, unsigned, FALSE, v850), |
+ V800_RELOC (R_V850_REGBLO, 2, 24, 0, dont, FALSE, v850), |
+ V800_RELOC (R_V850_GPBLO, 2, 24, 0, dont, FALSE, v850), |
+ V800_RELOC (R_V810_WLO_1, 1, 16, 0, dont, FALSE, v850), |
+ V800_RELOC (R_V810_GPWLO_1, 1, 16, 0, signed, FALSE, v850), |
+ V800_RELOC (R_V850_BLO_1, 2, 16, 0, signed, FALSE, v850), |
+ V800_RELOC (R_V850_HWLO_1, 1, 16, 0, signed, FALSE, v850), |
+ V800_EMPTY (R_V810_reserved4), |
+ V800_RELOC (R_V850_GPBLO_1, 2, 16, 1, signed, FALSE, v850), |
+ V800_RELOC (R_V850_GPHWLO_1, 1, 16, 1, signed, FALSE, v850), |
+ V800_EMPTY (R_V810_reserved5), |
+ V800_RELOC (R_V850_EPBLO, 2, 16, 1, signed, FALSE, v850), |
+ V800_RELOC (R_V850_EPHWLO, 1, 16, 1, signed, FALSE, v850), |
+ V800_EMPTY (R_V810_reserved6), |
+ V800_RELOC (R_V850_EPWLO_N, 1, 16, 1, signed, FALSE, v850), |
+ V800_RELOC (R_V850_PC32, 2, 32, 1, signed, TRUE, v850), |
+ V800_RELOC (R_V850_W23BIT, 2, 23, 1, signed, FALSE, v850), |
+ V800_RELOC (R_V850_GPW23BIT, 2, 23, 1, signed, FALSE, v850), |
+ V800_RELOC (R_V850_EPW23BIT, 2, 23, 1, signed, FALSE, v850), |
+ V800_RELOC (R_V850_B23BIT, 2, 23, 1, signed, FALSE, v850), |
+ V800_RELOC (R_V850_GPB23BIT, 2, 23, 1, signed, FALSE, v850), |
+ V800_RELOC (R_V850_EPB23BIT, 2, 23, 1, signed, FALSE, v850), |
+ V800_RELOC (R_V850_PC16U, 1, 16, 1, unsigned, TRUE, generic), |
+ V800_RELOC (R_V850_PC17, 2, 17, 1, signed, TRUE, generic), |
+ V800_RELOC (R_V850_DW8, 2, 8, 2, signed, FALSE, v850), |
+ V800_RELOC (R_V850_GPDW8, 2, 8, 2, signed, FALSE, v850), |
+ V800_RELOC (R_V850_EPDW8, 2, 8, 2, signed, FALSE, v850), |
+ V800_RELOC (R_V850_PC9, 1, 9, 3, signed, TRUE, v850), |
+ V800_RELOC (R_V810_REGBYTE, 0, 8, 0, dont, FALSE, v850), |
+ V800_RELOC (R_V810_REGHWORD, 1, 16, 0, dont, FALSE, v850), |
+ V800_RELOC (R_V810_REGWORD, 2, 32, 0, dont, FALSE, v850), |
+ V800_RELOC (R_V810_REGWLO, 1, 16, 0, dont, FALSE, v850), |
+ V800_RELOC (R_V810_REGWHI, 1, 16, 0, dont, FALSE, v850), |
+ V800_RELOC (R_V810_REGWHI1, 1, 16, 0, dont, FALSE, v850), |
+ V800_RELOC (R_V850_REGW23BIT, 2, 23, 1, signed, FALSE, v850), |
+ V800_RELOC (R_V850_REGB23BIT, 2, 23, 1, signed, FALSE, v850), |
+ V800_RELOC (R_V850_REGDW8, 2, 8, 2, signed, FALSE, v850), |
+ V800_RELOC (R_V810_EPBYTE, 0, 8, 0, dont, FALSE, v850), |
+ V800_RELOC (R_V810_EPHWORD, 1, 16, 0, dont, FALSE, v850), |
+ V800_RELOC (R_V810_EPWORD, 2, 32, 0, dont, FALSE, v850), |
+ V800_RELOC (R_V850_WLO23, 2, 32, 1, dont, FALSE, v850), |
+ V800_RELOC (R_V850_WORD_E, 2, 32, 1, dont, FALSE, v850), |
+ V800_RELOC (R_V850_REGWORD_E, 2, 32, 1, dont, FALSE, v850), |
+ V800_RELOC (R_V850_WORD, 2, 32, 0, dont, FALSE, v850), |
+ V800_RELOC (R_V850_GPWORD, 2, 32, 0, dont, FALSE, v850), |
+ V800_RELOC (R_V850_REGWORD, 2, 32, 0, dont, FALSE, v850), |
+ V800_RELOC (R_V850_EPWORD, 2, 32, 0, dont, FALSE, v850), |
+ V800_RELOC (R_V810_TPBYTE, 0, 8, 0, dont, FALSE, v850), |
+ V800_RELOC (R_V810_TPHWORD, 1, 16, 0, dont, FALSE, v850), |
+ V800_RELOC (R_V810_TPWORD, 2, 32, 0, dont, FALSE, v850), |
+ V800_RELOC (R_V810_TPWLO, 1, 16, 0, dont, FALSE, v850), |
+ V800_RELOC (R_V810_TPWHI, 1, 16, 0, dont, FALSE, v850), |
+ V800_RELOC (R_V810_TPWHI1, 1, 16, 0, dont, FALSE, v850), |
+ V800_RELOC (R_V850_TPHWLO, 1, 16, 1, dont, FALSE, v850), |
+ V800_RELOC (R_V850_TPBLO, 2, 24, 0, dont, FALSE, v850), |
+ V800_RELOC (R_V810_TPWLO_1, 1, 16, 0, signed, FALSE, v850), |
+ V800_RELOC (R_V850_TPBLO_1, 2, 16, 0, signed, FALSE, v850), |
+ V800_RELOC (R_V850_TPHWLO_1, 1, 16, 0, signed, FALSE, v850), |
+ V800_RELOC (R_V850_TP23BIT, 2, 23, 0, signed, FALSE, v850), |
+ V800_RELOC (R_V850_TPW23BIT, 2, 23, 0, signed, FALSE, v850), |
+ V800_RELOC (R_V850_TPDW8, 2, 8, 0, signed, FALSE, v850) |
+}; |
/* Map a bfd relocation into the appropriate howto structure. */ |
@@ -1814,6 +1920,12 @@ v850_elf_is_local_label_name (bfd *abfd ATTRIBUTE_UNUSED, const char *name) |
return ( (name[0] == '.' && (name[1] == 'L' || name[1] == '.')) |
|| (name[0] == '_' && name[1] == '.' && name[2] == 'L' && name[3] == '_')); |
} |
+ |
+static bfd_boolean |
+v850_elf_is_target_special_symbol (bfd *abfd, asymbol *sym) |
+{ |
+ return v850_elf_is_local_label_name (abfd, sym->name); |
+} |
/* We overload some of the bfd_reloc error codes for own purposes. */ |
#define bfd_reloc_gp_not_found bfd_reloc_other |
@@ -1841,12 +1953,14 @@ v850_elf_final_link_relocate (reloc_howto_type *howto, |
/* Adjust the value according to the relocation. */ |
switch (r_type) |
{ |
+ case R_V850_PC9: |
case R_V850_9_PCREL: |
value -= (input_section->output_section->vma |
+ input_section->output_offset); |
value -= offset; |
break; |
+ case R_V850_PC16U: |
case R_V850_16_PCREL: |
value -= (input_section->output_section->vma |
+ input_section->output_offset |
@@ -1858,6 +1972,7 @@ v850_elf_final_link_relocate (reloc_howto_type *howto, |
break; |
+ case R_V850_PC17: |
case R_V850_17_PCREL: |
value -= (input_section->output_section->vma |
+ input_section->output_offset |
@@ -1870,6 +1985,7 @@ v850_elf_final_link_relocate (reloc_howto_type *howto, |
value = SEXT17 (value); |
break; |
+ case R_V850_PCR22: |
case R_V850_22_PCREL: |
value -= (input_section->output_section->vma |
+ input_section->output_offset |
@@ -1883,6 +1999,7 @@ v850_elf_final_link_relocate (reloc_howto_type *howto, |
value = SEXT22 (value); |
break; |
+ case R_V850_PC32: |
case R_V850_32_PCREL: |
value -= (input_section->output_section->vma |
+ input_section->output_offset |
@@ -1899,6 +2016,15 @@ v850_elf_final_link_relocate (reloc_howto_type *howto, |
case R_V850_16: |
case R_V850_ABS32: |
case R_V850_8: |
+ case R_V810_BYTE: |
+ case R_V810_HWORD: |
+ case R_V810_WORD: |
+ case R_V810_WLO: |
+ case R_V810_WHI: |
+ case R_V810_WHI1: |
+ case R_V810_WLO_1: |
+ case R_V850_WLO23: |
+ case R_V850_BLO: |
break; |
case R_V850_ZDA_15_16_OFFSET: |
@@ -1913,6 +2039,7 @@ v850_elf_final_link_relocate (reloc_howto_type *howto, |
case R_V850_SDA_15_16_OFFSET: |
case R_V850_SDA_16_16_OFFSET: |
case R_V850_SDA_16_16_SPLIT_OFFSET: |
+ case R_V810_GPWLO_1: |
{ |
unsigned long gp; |
struct bfd_link_hash_entry * h; |
@@ -2002,6 +2129,7 @@ v850_elf_final_link_relocate (reloc_howto_type *howto, |
break; |
case R_V850_NONE: |
+ case R_V810_NONE: |
case R_V850_GNU_VTINHERIT: |
case R_V850_GNU_VTENTRY: |
case R_V850_LONGCALL: |
@@ -2010,6 +2138,9 @@ v850_elf_final_link_relocate (reloc_howto_type *howto, |
return bfd_reloc_ok; |
default: |
+#ifdef DEBUG |
+ fprintf (stderr, "reloc number %d not recognised\n", r_type); |
+#endif |
return bfd_reloc_notsupported; |
} |
@@ -2046,7 +2177,7 @@ v850_elf_relocate_section (bfd *output_bfd, |
relend = relocs + input_section->reloc_count; |
for (; rel < relend; rel++) |
{ |
- int r_type; |
+ unsigned int r_type; |
reloc_howto_type *howto; |
unsigned long r_symndx; |
Elf_Internal_Sym *sym; |
@@ -2062,7 +2193,13 @@ v850_elf_relocate_section (bfd *output_bfd, |
|| r_type == R_V850_GNU_VTINHERIT) |
continue; |
- howto = v850_elf_howto_table + r_type; |
+ if (bfd_get_arch (input_bfd) == bfd_arch_v850_rh850) |
+ howto = v800_elf_howto_table + (r_type - R_V810_NONE); |
+ else |
+ howto = v850_elf_howto_table + r_type; |
+ |
+ BFD_ASSERT (r_type == howto->type); |
+ |
h = NULL; |
sym = NULL; |
sec = NULL; |
@@ -2074,7 +2211,7 @@ v850_elf_relocate_section (bfd *output_bfd, |
} |
else |
{ |
- bfd_boolean unresolved_reloc, warned; |
+ bfd_boolean unresolved_reloc, warned, ignored; |
/* Note - this check is delayed until now as it is possible and |
valid to have a file without any symbols but with relocs that |
@@ -2091,7 +2228,7 @@ v850_elf_relocate_section (bfd *output_bfd, |
RELOC_FOR_GLOBAL_SYMBOL (info, input_bfd, input_section, rel, |
r_symndx, symtab_hdr, sym_hashes, |
h, sec, relocation, |
- unresolved_reloc, warned); |
+ unresolved_reloc, warned, ignored); |
} |
if (sec != NULL && discarded_section (sec)) |
@@ -2199,31 +2336,42 @@ v850_elf_gc_mark_hook (asection *sec, |
return _bfd_elf_gc_mark_hook (sec, info, rel, h, sym); |
} |
-/* Set the right machine number. */ |
+/* Set the right machine number and architecture. */ |
static bfd_boolean |
v850_elf_object_p (bfd *abfd) |
{ |
- switch (elf_elfheader (abfd)->e_flags & EF_V850_ARCH) |
+ enum bfd_architecture arch; |
+ unsigned long mach; |
+ |
+ switch (elf_elfheader (abfd)->e_machine) |
{ |
- default: |
- case E_V850_ARCH: |
- bfd_default_set_arch_mach (abfd, bfd_arch_v850, bfd_mach_v850); |
+ case EM_V800: |
+ arch = bfd_arch_v850_rh850; |
+ mach = (elf_elfheader (abfd)->e_flags & EF_V800_850E3) |
+ ? bfd_mach_v850e3v5 : bfd_mach_v850e2v3; |
break; |
- case E_V850E_ARCH: |
- bfd_default_set_arch_mach (abfd, bfd_arch_v850, bfd_mach_v850e); |
- break; |
- case E_V850E1_ARCH: |
- bfd_default_set_arch_mach (abfd, bfd_arch_v850, bfd_mach_v850e1); |
- break; |
- case E_V850E2_ARCH: |
- bfd_default_set_arch_mach (abfd, bfd_arch_v850, bfd_mach_v850e2); |
- break; |
- case E_V850E2V3_ARCH: |
- bfd_default_set_arch_mach (abfd, bfd_arch_v850, bfd_mach_v850e2v3); |
+ |
+ case EM_CYGNUS_V850: |
+ case EM_V850: |
+ arch = bfd_arch_v850; |
+ switch (elf_elfheader (abfd)->e_flags & EF_V850_ARCH) |
+ { |
+ default: |
+ case E_V850_ARCH: mach = bfd_mach_v850; break; |
+ case E_V850E_ARCH: mach = bfd_mach_v850e; break; |
+ case E_V850E1_ARCH: mach = bfd_mach_v850e1; break; |
+ case E_V850E2_ARCH: mach = bfd_mach_v850e2; break; |
+ case E_V850E2V3_ARCH: mach = bfd_mach_v850e2v3; break; |
+ case E_V850E3V5_ARCH: mach = bfd_mach_v850e3v5; break; |
+ } |
break; |
+ |
+ default: |
+ return FALSE; |
} |
- return TRUE; |
+ |
+ return bfd_default_set_arch_mach (abfd, arch, mach); |
} |
/* Store the machine number in the flags field. */ |
@@ -2234,18 +2382,32 @@ v850_elf_final_write_processing (bfd *abfd, |
{ |
unsigned long val; |
- switch (bfd_get_mach (abfd)) |
+ switch (bfd_get_arch (abfd)) |
{ |
+ case bfd_arch_v850_rh850: |
+ val = EF_RH850_ABI; |
+ if (bfd_get_mach (abfd) == bfd_mach_v850e3v5) |
+ val |= EF_V800_850E3; |
+ elf_elfheader (abfd)->e_flags |= val; |
+ break; |
+ |
+ case bfd_arch_v850: |
+ switch (bfd_get_mach (abfd)) |
+ { |
+ default: |
+ case bfd_mach_v850: val = E_V850_ARCH; break; |
+ case bfd_mach_v850e: val = E_V850E_ARCH; break; |
+ case bfd_mach_v850e1: val = E_V850E1_ARCH; break; |
+ case bfd_mach_v850e2: val = E_V850E2_ARCH; break; |
+ case bfd_mach_v850e2v3: val = E_V850E2V3_ARCH; break; |
+ case bfd_mach_v850e3v5: val = E_V850E3V5_ARCH; break; |
+ } |
+ elf_elfheader (abfd)->e_flags &=~ EF_V850_ARCH; |
+ elf_elfheader (abfd)->e_flags |= val; |
+ break; |
default: |
- case bfd_mach_v850: val = E_V850_ARCH; break; |
- case bfd_mach_v850e: val = E_V850E_ARCH; break; |
- case bfd_mach_v850e1: val = E_V850E1_ARCH; break; |
- case bfd_mach_v850e2: val = E_V850E2_ARCH; break; |
- case bfd_mach_v850e2v3: val = E_V850E2V3_ARCH; break; |
+ break; |
} |
- |
- elf_elfheader (abfd)->e_flags &=~ EF_V850_ARCH; |
- elf_elfheader (abfd)->e_flags |= val; |
} |
/* Function to keep V850 specific file flags. */ |
@@ -2302,17 +2464,36 @@ v850_elf_merge_private_bfd_data (bfd *ibfd, bfd *obfd) |
if (in_flags == out_flags) |
return TRUE; |
+ if (bfd_get_arch (obfd) == bfd_arch_v850_rh850) |
+ { |
+ if ((in_flags & EF_V800_850E3) != (out_flags & EF_V800_850E3)) |
+ { |
+ _bfd_error_handler (_("%B: Architecture mismatch with previous modules"), |
+ ibfd); |
+ elf_elfheader (obfd)->e_flags |= EF_V800_850E3; |
+ } |
+ |
+ if ((in_flags & EF_RH850_DATA_ALIGN8) != (out_flags & EF_RH850_DATA_ALIGN8)) |
+ { |
+ _bfd_error_handler (_("%B: Alignment mismatch with previous modules"), |
+ ibfd); |
+ elf_elfheader (obfd)->e_flags |= EF_RH850_DATA_ALIGN8; |
+ } |
+ |
+ return TRUE; |
+ } |
+ |
if ((in_flags & EF_V850_ARCH) != (out_flags & EF_V850_ARCH) |
&& (in_flags & EF_V850_ARCH) != E_V850_ARCH) |
{ |
- |
- /* Allow v850e1 binaries to be linked with v850e binaries. |
- Set the output binary to v850e. */ |
- if ((in_flags & EF_V850_ARCH) == E_V850E1_ARCH |
+ /* Allow earlier architecture binaries to be linked with later binaries. |
+ Set the output binary to the later architecture, except for v850e1, |
+ which we set to v850e. */ |
+ if ( (in_flags & EF_V850_ARCH) == E_V850E1_ARCH |
&& (out_flags & EF_V850_ARCH) == E_V850E_ARCH) |
return TRUE; |
- if ((in_flags & EF_V850_ARCH) == E_V850_ARCH |
+ if ( (in_flags & EF_V850_ARCH) == E_V850_ARCH |
&& (out_flags & EF_V850_ARCH) == E_V850E_ARCH) |
{ |
elf_elfheader (obfd)->e_flags = |
@@ -2320,7 +2501,7 @@ v850_elf_merge_private_bfd_data (bfd *ibfd, bfd *obfd) |
return TRUE; |
} |
- if (((in_flags & EF_V850_ARCH) == E_V850_ARCH |
+ if (( (in_flags & EF_V850_ARCH) == E_V850_ARCH |
|| (in_flags & EF_V850_ARCH) == E_V850E_ARCH) |
&& (out_flags & EF_V850_ARCH) == E_V850E2_ARCH) |
{ |
@@ -2329,7 +2510,7 @@ v850_elf_merge_private_bfd_data (bfd *ibfd, bfd *obfd) |
return TRUE; |
} |
- if (((in_flags & EF_V850_ARCH) == E_V850_ARCH |
+ if (( (in_flags & EF_V850_ARCH) == E_V850_ARCH |
|| (in_flags & EF_V850_ARCH) == E_V850E_ARCH |
|| (in_flags & EF_V850_ARCH) == E_V850E2_ARCH) |
&& (out_flags & EF_V850_ARCH) == E_V850E2V3_ARCH) |
@@ -2339,6 +2520,17 @@ v850_elf_merge_private_bfd_data (bfd *ibfd, bfd *obfd) |
return TRUE; |
} |
+ if (( (in_flags & EF_V850_ARCH) == E_V850_ARCH |
+ || (in_flags & EF_V850_ARCH) == E_V850E_ARCH |
+ || (in_flags & EF_V850_ARCH) == E_V850E2_ARCH |
+ || (in_flags & EF_V850_ARCH) == E_V850E2V3_ARCH) |
+ && (out_flags & EF_V850_ARCH) == E_V850E3V5_ARCH) |
+ { |
+ elf_elfheader (obfd)->e_flags = |
+ ((out_flags & ~ EF_V850_ARCH) | E_V850E3V5_ARCH); |
+ return TRUE; |
+ } |
+ |
_bfd_error_handler (_("%B: Architecture mismatch with previous modules"), |
ibfd); |
} |
@@ -2360,14 +2552,30 @@ v850_elf_print_private_bfd_data (bfd *abfd, void * ptr) |
/* xgettext:c-format. */ |
fprintf (file, _("private flags = %lx: "), elf_elfheader (abfd)->e_flags); |
- switch (elf_elfheader (abfd)->e_flags & EF_V850_ARCH) |
+ if (bfd_get_arch (abfd) == bfd_arch_v850_rh850) |
{ |
- default: |
- case E_V850_ARCH: fprintf (file, _("v850 architecture")); break; |
- case E_V850E_ARCH: fprintf (file, _("v850e architecture")); break; |
- case E_V850E1_ARCH: fprintf (file, _("v850e1 architecture")); break; |
- case E_V850E2_ARCH: fprintf (file, _("v850e2 architecture")); break; |
- case E_V850E2V3_ARCH: fprintf (file, _("v850e2v3 architecture")); break; |
+ if ((elf_elfheader (abfd)->e_flags & EF_RH850_ABI) != EF_RH850_ABI) |
+ fprintf (file, _("unknown v850 architecture")); |
+ else if (elf_elfheader (abfd)->e_flags & EF_V800_850E3) |
+ fprintf (file, _("v850 E3 architecture")); |
+ else |
+ fprintf (file, _("v850 architecture")); |
+ |
+ if (elf_elfheader (abfd)->e_flags & EF_RH850_DATA_ALIGN8) |
+ fprintf (file, _(", 8-byte data alignment")); |
+ } |
+ else |
+ { |
+ switch (elf_elfheader (abfd)->e_flags & EF_V850_ARCH) |
+ { |
+ default: |
+ case E_V850_ARCH: fprintf (file, _("v850 architecture")); break; |
+ case E_V850E_ARCH: fprintf (file, _("v850e architecture")); break; |
+ case E_V850E1_ARCH: fprintf (file, _("v850e1 architecture")); break; |
+ case E_V850E2_ARCH: fprintf (file, _("v850e2 architecture")); break; |
+ case E_V850E2V3_ARCH: fprintf (file, _("v850e2v3 architecture")); break; |
+ case E_V850E3V5_ARCH: fprintf (file, _("v850e3v5 architecture")); break; |
+ } |
} |
fputc ('\n', file); |
@@ -2933,7 +3141,7 @@ v850_elf_relax_section (bfd *abfd, |
if (alignmoveto < alignto) |
{ |
- unsigned int i; |
+ bfd_vma i; |
align_pad_size = alignto - alignmoveto; |
#ifdef DEBUG_RELAX |
@@ -2965,6 +3173,7 @@ v850_elf_relax_section (bfd *abfd, |
Elf_Internal_Rela *lo_irelfn; |
Elf_Internal_Rela *irelcall; |
bfd_signed_vma foff; |
+ unsigned int r_type; |
if (! (irel->r_offset >= addr && irel->r_offset < toaddr |
&& (ELF32_R_TYPE (irel->r_info) == (int) R_V850_LONGCALL |
@@ -3060,23 +3269,33 @@ v850_elf_relax_section (bfd *abfd, |
/* Get the reloc for the address from which the register is |
being loaded. This reloc will tell us which function is |
actually being called. */ |
+ |
for (hi_irelfn = internal_relocs; hi_irelfn < irelend; hi_irelfn ++) |
- if (hi_irelfn->r_offset == laddr + 2 |
- && ELF32_R_TYPE (hi_irelfn->r_info) |
- == (int) R_V850_HI16_S) |
- break; |
+ { |
+ r_type = ELF32_R_TYPE (hi_irelfn->r_info); |
+ |
+ if (hi_irelfn->r_offset == laddr + 2 |
+ && (r_type == (int) R_V850_HI16_S || r_type == (int) R_V810_WHI1)) |
+ break; |
+ } |
for (lo_irelfn = internal_relocs; lo_irelfn < irelend; lo_irelfn ++) |
- if (lo_irelfn->r_offset == laddr + 6 |
- && ELF32_R_TYPE (lo_irelfn->r_info) |
- == (int) R_V850_LO16) |
- break; |
+ { |
+ r_type = ELF32_R_TYPE (lo_irelfn->r_info); |
+ |
+ if (lo_irelfn->r_offset == laddr + 6 |
+ && (r_type == (int) R_V850_LO16 || r_type == (int) R_V810_WLO)) |
+ break; |
+ } |
for (irelcall = internal_relocs; irelcall < irelend; irelcall ++) |
- if (irelcall->r_offset == laddr + 8 |
- && ELF32_R_TYPE (irelcall->r_info) |
- == (int) R_V850_22_PCREL) |
- break; |
+ { |
+ r_type = ELF32_R_TYPE (irelcall->r_info); |
+ |
+ if (irelcall->r_offset == laddr + 8 |
+ && (r_type == (int) R_V850_22_PCREL || r_type == (int) R_V850_PCR22)) |
+ break; |
+ } |
if ( hi_irelfn == irelend |
|| lo_irelfn == irelend |
@@ -3202,7 +3421,10 @@ v850_elf_relax_section (bfd *abfd, |
symtab_hdr->contents = (bfd_byte *) isymbuf; |
/* Replace the long call with a jarl. */ |
- irel->r_info = ELF32_R_INFO (ELF32_R_SYM (hi_irelfn->r_info), R_V850_22_PCREL); |
+ if (bfd_get_arch (abfd) == bfd_arch_v850_rh850) |
+ irel->r_info = ELF32_R_INFO (ELF32_R_SYM (hi_irelfn->r_info), R_V850_PCR22); |
+ else |
+ irel->r_info = ELF32_R_INFO (ELF32_R_SYM (hi_irelfn->r_info), R_V850_22_PCREL); |
addend = 0; |
@@ -3278,14 +3500,22 @@ v850_elf_relax_section (bfd *abfd, |
being loaded. This reloc will tell us which function is |
actually being called. */ |
for (hi_irelfn = internal_relocs; hi_irelfn < irelend; hi_irelfn ++) |
- if (hi_irelfn->r_offset == laddr + 2 |
- && ELF32_R_TYPE (hi_irelfn->r_info) == (int) R_V850_HI16_S) |
- break; |
+ { |
+ r_type = ELF32_R_TYPE (hi_irelfn->r_info); |
+ |
+ if (hi_irelfn->r_offset == laddr + 2 |
+ && ((r_type == (int) R_V850_HI16_S) || r_type == (int) R_V810_WHI1)) |
+ break; |
+ } |
for (lo_irelfn = internal_relocs; lo_irelfn < irelend; lo_irelfn ++) |
- if (lo_irelfn->r_offset == laddr + 6 |
- && ELF32_R_TYPE (lo_irelfn->r_info) == (int) R_V850_LO16) |
- break; |
+ { |
+ r_type = ELF32_R_TYPE (lo_irelfn->r_info); |
+ |
+ if (lo_irelfn->r_offset == laddr + 6 |
+ && (r_type == (int) R_V850_LO16 || r_type == (int) R_V810_WLO)) |
+ break; |
+ } |
if ( hi_irelfn == irelend |
|| lo_irelfn == irelend) |
@@ -3392,8 +3622,11 @@ v850_elf_relax_section (bfd *abfd, |
{ |
/* Replace the long jump with a jr. */ |
- irel->r_info = |
- ELF32_R_INFO (ELF32_R_SYM (irel->r_info), R_V850_22_PCREL); |
+ if (bfd_get_arch (abfd) == bfd_arch_v850_rh850) |
+ irel->r_info = ELF32_R_INFO (ELF32_R_SYM (irel->r_info), R_V850_PCR22); |
+ else |
+ irel->r_info = |
+ ELF32_R_INFO (ELF32_R_SYM (irel->r_info), R_V850_22_PCREL); |
irel->r_addend = addend; |
addend = 0; |
@@ -3425,8 +3658,11 @@ v850_elf_relax_section (bfd *abfd, |
{ |
/* Replace the long jump with a br. */ |
- irel->r_info = |
- ELF32_R_INFO (ELF32_R_SYM (irel->r_info), R_V850_9_PCREL); |
+ if (bfd_get_arch (abfd) == bfd_arch_v850_rh850) |
+ irel->r_info = ELF32_R_INFO (ELF32_R_SYM (irel->r_info), R_V850_PC9); |
+ else |
+ irel->r_info = |
+ ELF32_R_INFO (ELF32_R_SYM (irel->r_info), R_V850_9_PCREL); |
irel->r_addend = addend; |
addend = 0; |
@@ -3539,7 +3775,6 @@ static const struct bfd_elf_special_section v850_elf_special_sections[] = |
#define ELF_ARCH bfd_arch_v850 |
#define ELF_MACHINE_CODE EM_V850 |
#define ELF_MACHINE_ALT1 EM_CYGNUS_V850 |
-#define ELF_MACHINE_ALT2 EM_V800 /* This is the value used by the GreenHills toolchain. */ |
#define ELF_MAXPAGESIZE 0x1000 |
#define elf_info_to_howto v850_elf_info_to_howto_rela |
@@ -3562,8 +3797,10 @@ static const struct bfd_elf_special_section v850_elf_special_sections[] = |
#define elf_backend_rela_normal 1 |
#define bfd_elf32_bfd_is_local_label_name v850_elf_is_local_label_name |
+#define bfd_elf32_bfd_is_target_special_symbol v850_elf_is_target_special_symbol |
+ |
#define bfd_elf32_bfd_reloc_type_lookup v850_elf_reloc_type_lookup |
-#define bfd_elf32_bfd_reloc_name_lookup v850_elf_reloc_name_lookup |
+#define bfd_elf32_bfd_reloc_name_lookup v850_elf_reloc_name_lookup |
#define bfd_elf32_bfd_merge_private_bfd_data v850_elf_merge_private_bfd_data |
#define bfd_elf32_bfd_set_private_flags v850_elf_set_private_flags |
#define bfd_elf32_bfd_print_private_bfd_data v850_elf_print_private_bfd_data |
@@ -3571,4 +3808,122 @@ static const struct bfd_elf_special_section v850_elf_special_sections[] = |
#define elf_symbol_leading_char '_' |
+#undef elf32_bed |
+#define elf32_bed elf32_v850_bed |
+ |
+#include "elf32-target.h" |
+ |
+/* Map BFD reloc types to V800 ELF reloc types. */ |
+ |
+static const struct v850_elf_reloc_map v800_elf_reloc_map[] = |
+{ |
+ { BFD_RELOC_NONE, R_V810_NONE }, |
+ { BFD_RELOC_8, R_V810_BYTE }, |
+ { BFD_RELOC_16, R_V810_HWORD }, |
+ { BFD_RELOC_32, R_V810_WORD }, |
+ { BFD_RELOC_LO16, R_V810_WLO }, |
+ { BFD_RELOC_HI16, R_V810_WHI }, |
+ { BFD_RELOC_HI16_S, R_V810_WHI1 }, |
+ { BFD_RELOC_V850_32_PCREL, R_V850_PC32 }, |
+ { BFD_RELOC_V850_22_PCREL, R_V850_PCR22 }, |
+ { BFD_RELOC_V850_17_PCREL, R_V850_PC17 }, |
+ { BFD_RELOC_V850_16_PCREL, R_V850_PC16U }, |
+ { BFD_RELOC_V850_9_PCREL, R_V850_PC9 }, |
+ { BFD_RELOC_V850_LO16_S1, R_V810_WLO_1 }, /* Or R_V850_HWLO or R_V850_HWLO_1. */ |
+ { BFD_RELOC_V850_23, R_V850_WLO23 }, |
+ { BFD_RELOC_V850_LO16_SPLIT_OFFSET, R_V850_BLO }, |
+ { BFD_RELOC_V850_ZDA_16_16_OFFSET, R_V810_HWORD }, |
+ { BFD_RELOC_V850_TDA_16_16_OFFSET, R_V810_HWORD }, |
+ { BFD_RELOC_V850_SDA_16_16_OFFSET, R_V810_HWORD }, |
+ { BFD_RELOC_V850_SDA_15_16_OFFSET, R_V810_GPWLO_1 } |
+}; |
+ |
+/* Map a bfd relocation into the appropriate howto structure. */ |
+ |
+static reloc_howto_type * |
+v800_elf_reloc_type_lookup (bfd * abfd, bfd_reloc_code_real_type code) |
+{ |
+ unsigned int i; |
+ |
+ BFD_ASSERT (bfd_get_arch (abfd) == bfd_arch_v850_rh850); |
+ |
+ for (i = ARRAY_SIZE (v800_elf_reloc_map); i --;) |
+ if (v800_elf_reloc_map[i].bfd_reloc_val == code) |
+ { |
+ unsigned int elf_reloc_val = v800_elf_reloc_map[i].elf_reloc_val; |
+ unsigned int idx = elf_reloc_val - R_V810_NONE; |
+ |
+ BFD_ASSERT (v800_elf_howto_table[idx].type == elf_reloc_val); |
+ |
+ return v800_elf_howto_table + idx; |
+ } |
+ |
+#ifdef DEBUG |
+ fprintf (stderr, "failed to find v800 equiv of bfd reloc code %d\n", code); |
+#endif |
+ return NULL; |
+} |
+ |
+static reloc_howto_type * |
+v800_elf_reloc_name_lookup (bfd * abfd, const char * r_name) |
+{ |
+ unsigned int i; |
+ |
+ BFD_ASSERT (bfd_get_arch (abfd) == bfd_arch_v850_rh850); |
+ |
+ for (i = ARRAY_SIZE (v800_elf_howto_table); i--;) |
+ if (v800_elf_howto_table[i].name != NULL |
+ && strcasecmp (v800_elf_howto_table[i].name, r_name) == 0) |
+ return v800_elf_howto_table + i; |
+ |
+ return NULL; |
+} |
+ |
+ |
+/* Set the howto pointer in CACHE_PTR for a V800 ELF reloc. */ |
+ |
+static void |
+v800_elf_info_to_howto (bfd * abfd, |
+ arelent * cache_ptr, |
+ Elf_Internal_Rela * dst) |
+{ |
+ unsigned int r_type = ELF32_R_TYPE (dst->r_info); |
+ |
+ BFD_ASSERT (bfd_get_arch (abfd) == bfd_arch_v850_rh850); |
+ |
+ BFD_ASSERT (r_type < (unsigned int) R_V800_max); |
+ |
+ if (r_type == R_V800_NONE) |
+ r_type = R_V810_NONE; |
+ |
+ BFD_ASSERT (r_type >= (unsigned int) R_V810_NONE); |
+ r_type -= R_V810_NONE; |
+ BFD_ASSERT (r_type < ARRAY_SIZE (v800_elf_howto_table)); |
+ |
+ cache_ptr->howto = v800_elf_howto_table + r_type; |
+} |
+ |
+ |
+#undef TARGET_LITTLE_SYM |
+#define TARGET_LITTLE_SYM bfd_elf32_v850_rh850_vec |
+#undef TARGET_LITTLE_NAME |
+#define TARGET_LITTLE_NAME "elf32-v850-rh850" |
+#undef ELF_ARCH |
+#define ELF_ARCH bfd_arch_v850_rh850 |
+#undef ELF_MACHINE_CODE |
+#define ELF_MACHINE_CODE EM_V800 |
+#undef ELF_MACHINE_ALT1 |
+ |
+#undef elf32_bed |
+#define elf32_bed elf32_v850_rh850_bed |
+ |
+#undef elf_info_to_howto |
+#define elf_info_to_howto v800_elf_info_to_howto |
+#undef elf_info_to_howto_rel |
+#define elf_info_to_howto_rel NULL |
+#undef bfd_elf32_bfd_reloc_type_lookup |
+#define bfd_elf32_bfd_reloc_type_lookup v800_elf_reloc_type_lookup |
+#undef bfd_elf32_bfd_reloc_name_lookup |
+#define bfd_elf32_bfd_reloc_name_lookup v800_elf_reloc_name_lookup |
+ |
#include "elf32-target.h" |