|
|
|
@ -17,12 +17,9 @@ 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. */ |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* XXX FIXME: This code is littered with 32bit int, 16bit short, 8bit char
|
|
|
|
dependencies. As is the gas & simulator code or the v850. */ |
|
|
|
|
|
|
|
|
|
|
|
#include "bfd.h" |
|
|
|
#include "sysdep.h" |
|
|
|
#include "bfdlink.h" |
|
|
|
@ -32,7 +29,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ |
|
|
|
|
|
|
|
/* sign-extend a 24-bit number */ |
|
|
|
#define SEXT24(x) ((((x) & 0xffffff) ^ (~ 0x7fffff)) + 0x800000) |
|
|
|
|
|
|
|
|
|
|
|
static reloc_howto_type *v850_elf_reloc_type_lookup |
|
|
|
PARAMS ((bfd *abfd, bfd_reloc_code_real_type code)); |
|
|
|
static void v850_elf_info_to_howto_rel |
|
|
|
@ -103,7 +100,7 @@ static reloc_howto_type v850_elf_howto_table[] = |
|
|
|
0, /* dst_mask */ |
|
|
|
false), /* pcrel_offset */ |
|
|
|
|
|
|
|
/* A PC relative 9 bit branch. */ |
|
|
|
/* A PC relative 9 bit branch. */ |
|
|
|
HOWTO (R_V850_9_PCREL, /* type */ |
|
|
|
2, /* rightshift */ |
|
|
|
2, /* size (0 = byte, 1 = short, 2 = long) */ |
|
|
|
@ -118,7 +115,7 @@ static reloc_howto_type v850_elf_howto_table[] = |
|
|
|
0x00ffffff, /* dst_mask */ |
|
|
|
true), /* pcrel_offset */ |
|
|
|
|
|
|
|
/* A PC relative 22 bit branch. */ |
|
|
|
/* A PC relative 22 bit branch. */ |
|
|
|
HOWTO (R_V850_22_PCREL, /* type */ |
|
|
|
2, /* rightshift */ |
|
|
|
2, /* size (0 = byte, 1 = short, 2 = long) */ |
|
|
|
@ -312,7 +309,7 @@ static reloc_howto_type v850_elf_howto_table[] = |
|
|
|
0x7f, /* src_mask */ |
|
|
|
0x7f, /* dst_mask */ |
|
|
|
false), /* pcrel_offset */ |
|
|
|
|
|
|
|
|
|
|
|
/* 7 bit offset from the tiny data area pointer. */ |
|
|
|
HOWTO (R_V850_TDA_7_7_OFFSET, /* type */ |
|
|
|
0, /* rightshift */ |
|
|
|
@ -462,7 +459,7 @@ static reloc_howto_type v850_elf_howto_table[] = |
|
|
|
0, /* src_mask */ |
|
|
|
0, /* dst_mask */ |
|
|
|
false), /* pcrel_offset */ |
|
|
|
|
|
|
|
|
|
|
|
}; |
|
|
|
|
|
|
|
/* Map BFD reloc types to V850 ELF reloc types. */ |
|
|
|
@ -521,7 +518,7 @@ v850_elf_reloc_type_lookup (abfd, code) |
|
|
|
if (v850_elf_reloc_map[i].bfd_reloc_val == code) |
|
|
|
{ |
|
|
|
BFD_ASSERT (v850_elf_howto_table[v850_elf_reloc_map[i].elf_reloc_val].type == v850_elf_reloc_map[i].elf_reloc_val); |
|
|
|
|
|
|
|
|
|
|
|
return & v850_elf_howto_table[v850_elf_reloc_map[i].elf_reloc_val]; |
|
|
|
} |
|
|
|
} |
|
|
|
@ -544,7 +541,7 @@ v850_elf_info_to_howto_rel (abfd, cache_ptr, dst) |
|
|
|
cache_ptr->howto = &v850_elf_howto_table[r_type]; |
|
|
|
} |
|
|
|
|
|
|
|
/* Set the howto pointer for a V850 ELF reloc (type RELA). */ |
|
|
|
/* Set the howto pointer for a V850 ELF reloc (type RELA). */ |
|
|
|
static void |
|
|
|
v850_elf_info_to_howto_rela (abfd, cache_ptr, dst) |
|
|
|
bfd * abfd ATTRIBUTE_UNUSED; |
|
|
|
@ -644,14 +641,14 @@ v850_elf_check_relocs (abfd, info, sec, relocs) |
|
|
|
other = V850_OTHER_SDA; |
|
|
|
common = ".scommon"; |
|
|
|
goto small_data_common; |
|
|
|
|
|
|
|
|
|
|
|
case R_V850_ZDA_16_16_SPLIT_OFFSET: |
|
|
|
case R_V850_ZDA_16_16_OFFSET: |
|
|
|
case R_V850_ZDA_15_16_OFFSET: |
|
|
|
other = V850_OTHER_ZDA; |
|
|
|
common = ".zcommon"; |
|
|
|
goto small_data_common; |
|
|
|
|
|
|
|
|
|
|
|
case R_V850_TDA_4_5_OFFSET: |
|
|
|
case R_V850_TDA_4_4_OFFSET: |
|
|
|
case R_V850_TDA_6_8_OFFSET: |
|
|
|
@ -760,21 +757,21 @@ remember_hi16s_reloc (abfd, addend, address) |
|
|
|
bfd_byte * address; |
|
|
|
{ |
|
|
|
hi16s_location * entry = NULL; |
|
|
|
|
|
|
|
|
|
|
|
/* Find a free structure. */ |
|
|
|
if (free_hi16s == NULL) |
|
|
|
free_hi16s = (hi16s_location *) bfd_zalloc (abfd, sizeof (* free_hi16s)); |
|
|
|
|
|
|
|
entry = free_hi16s; |
|
|
|
free_hi16s = free_hi16s->next; |
|
|
|
|
|
|
|
|
|
|
|
entry->addend = addend; |
|
|
|
entry->address = address; |
|
|
|
entry->counter = hi16s_counter ++; |
|
|
|
entry->found = false; |
|
|
|
entry->next = previous_hi16s; |
|
|
|
previous_hi16s = entry; |
|
|
|
|
|
|
|
|
|
|
|
/* Cope with wrap around of our counter. */ |
|
|
|
if (hi16s_counter == 0) |
|
|
|
{ |
|
|
|
@ -784,7 +781,7 @@ remember_hi16s_reloc (abfd, addend, address) |
|
|
|
|
|
|
|
hi16s_counter = 0x10000; |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
return; |
|
|
|
} |
|
|
|
|
|
|
|
@ -798,7 +795,7 @@ find_remembered_hi16s_reloc (addend, already_found) |
|
|
|
hi16s_location * previous = NULL; |
|
|
|
hi16s_location * prev; |
|
|
|
bfd_byte * addr; |
|
|
|
|
|
|
|
|
|
|
|
/* Search the table. Record the most recent entry that matches. */ |
|
|
|
for (entry = previous_hi16s; entry; entry = entry->next) |
|
|
|
{ |
|
|
|
@ -808,7 +805,7 @@ find_remembered_hi16s_reloc (addend, already_found) |
|
|
|
previous = prev; |
|
|
|
match = entry; |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
prev = entry; |
|
|
|
} |
|
|
|
|
|
|
|
@ -824,9 +821,9 @@ find_remembered_hi16s_reloc (addend, already_found) |
|
|
|
|
|
|
|
/* Note that this entry has now been used. */ |
|
|
|
match->found = true; |
|
|
|
|
|
|
|
|
|
|
|
return addr; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
/* FIXME: The code here probably ought to be removed and the code in reloc.c
|
|
|
|
allowed to do its stuff instead. At least for most of the relocs, anwyay. */ |
|
|
|
@ -839,62 +836,62 @@ v850_elf_perform_relocation (abfd, r_type, addend, address) |
|
|
|
{ |
|
|
|
unsigned long insn; |
|
|
|
bfd_signed_vma saddend = (bfd_signed_vma) addend; |
|
|
|
|
|
|
|
|
|
|
|
switch (r_type) |
|
|
|
{ |
|
|
|
default: |
|
|
|
/* fprintf (stderr, "reloc type %d not SUPPORTED\n", r_type ); */ |
|
|
|
return bfd_reloc_notsupported; |
|
|
|
|
|
|
|
|
|
|
|
case R_V850_32: |
|
|
|
bfd_put_32 (abfd, addend, address); |
|
|
|
return bfd_reloc_ok; |
|
|
|
|
|
|
|
|
|
|
|
case R_V850_22_PCREL: |
|
|
|
if (saddend > 0x1fffff || saddend < -0x200000) |
|
|
|
return bfd_reloc_overflow; |
|
|
|
|
|
|
|
|
|
|
|
if ((addend % 2) != 0) |
|
|
|
return bfd_reloc_dangerous; |
|
|
|
|
|
|
|
|
|
|
|
insn = bfd_get_32 (abfd, address); |
|
|
|
insn &= ~0xfffe003f; |
|
|
|
insn |= (((addend & 0xfffe) << 16) | ((addend & 0x3f0000) >> 16)); |
|
|
|
bfd_put_32 (abfd, insn, address); |
|
|
|
return bfd_reloc_ok; |
|
|
|
|
|
|
|
|
|
|
|
case R_V850_9_PCREL: |
|
|
|
if (saddend > 0xff || saddend < -0x100) |
|
|
|
return bfd_reloc_overflow; |
|
|
|
|
|
|
|
|
|
|
|
if ((addend % 2) != 0) |
|
|
|
return bfd_reloc_dangerous; |
|
|
|
|
|
|
|
|
|
|
|
insn = bfd_get_16 (abfd, address); |
|
|
|
insn &= ~ 0xf870; |
|
|
|
insn |= ((addend & 0x1f0) << 7) | ((addend & 0x0e) << 3); |
|
|
|
break; |
|
|
|
|
|
|
|
|
|
|
|
case R_V850_HI16: |
|
|
|
addend += (bfd_get_16 (abfd, address) << 16); |
|
|
|
addend = (addend >> 16); |
|
|
|
insn = addend; |
|
|
|
break; |
|
|
|
|
|
|
|
|
|
|
|
case R_V850_HI16_S: |
|
|
|
/* Remember where this relocation took place. */ |
|
|
|
remember_hi16s_reloc (abfd, addend, address); |
|
|
|
|
|
|
|
addend += (bfd_get_16 (abfd, address) << 16); |
|
|
|
addend = (addend >> 16) + ((addend & 0x8000) != 0); |
|
|
|
|
|
|
|
/* This relocation cannot overflow. */ |
|
|
|
|
|
|
|
/* This relocation cannot overflow. */ |
|
|
|
if (addend > 0x7fff) |
|
|
|
addend = 0; |
|
|
|
|
|
|
|
|
|
|
|
insn = addend; |
|
|
|
break; |
|
|
|
|
|
|
|
|
|
|
|
case R_V850_LO16: |
|
|
|
/* Calculate the sum of the value stored in the instruction and the
|
|
|
|
addend and check for overflow from the low 16 bits into the high |
|
|
|
@ -972,7 +969,6 @@ v850_elf_perform_relocation (abfd, r_type, addend, address) |
|
|
|
------------ |
|
|
|
0x00116fff = fred + 0x10ffff = 0x7000 + 0x10ffff |
|
|
|
|
|
|
|
|
|
|
|
Overflow can also occur if the computation carries into the 16th bit |
|
|
|
and it also results in the 15th bit having the same value as the 15th |
|
|
|
bit of the original value. What happens is that the HI16S reloc |
|
|
|
@ -1007,7 +1003,7 @@ v850_elf_perform_relocation (abfd, r_type, addend, address) |
|
|
|
+ 0x00006fff |
|
|
|
------------ |
|
|
|
0x00006fff but 'fred + 0x7000' = 0x00016fff |
|
|
|
|
|
|
|
|
|
|
|
Note - there is no need to change anything if a carry occurs, and the |
|
|
|
15th bit changes its value from being set to being clear, as the HI16S |
|
|
|
reloc will have already added in 1 to the high part for us: |
|
|
|
@ -1046,7 +1042,7 @@ v850_elf_perform_relocation (abfd, r_type, addend, address) |
|
|
|
|
|
|
|
#define BIT15_SET(x) ((x) & 0x8000) |
|
|
|
#define OVERFLOWS(a,i) ((((a) & 0xffff) + (i)) > 0xffff) |
|
|
|
|
|
|
|
|
|
|
|
if ((BIT15_SET (result) && ! BIT15_SET (addend)) |
|
|
|
|| (OVERFLOWS (addend, insn) |
|
|
|
&& ((! BIT15_SET (insn)) || (BIT15_SET (addend))))) |
|
|
|
@ -1054,7 +1050,7 @@ v850_elf_perform_relocation (abfd, r_type, addend, address) |
|
|
|
boolean already_updated; |
|
|
|
bfd_byte * hi16s_address = find_remembered_hi16s_reloc |
|
|
|
(addend, & already_updated); |
|
|
|
|
|
|
|
|
|
|
|
/* Amend the matching HI16_S relocation. */ |
|
|
|
if (hi16s_address != NULL) |
|
|
|
{ |
|
|
|
@ -1071,7 +1067,7 @@ v850_elf_perform_relocation (abfd, r_type, addend, address) |
|
|
|
return bfd_reloc_overflow; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/* Do not complain if value has top bit set, as this has been anticipated. */ |
|
|
|
insn = result & 0xffff; |
|
|
|
break; |
|
|
|
@ -1081,7 +1077,7 @@ v850_elf_perform_relocation (abfd, r_type, addend, address) |
|
|
|
addend += (char) bfd_get_8 (abfd, address); |
|
|
|
|
|
|
|
saddend = (bfd_signed_vma) addend; |
|
|
|
|
|
|
|
|
|
|
|
if (saddend > 0x7f || saddend < -0x80) |
|
|
|
return bfd_reloc_overflow; |
|
|
|
|
|
|
|
@ -1090,150 +1086,150 @@ v850_elf_perform_relocation (abfd, r_type, addend, address) |
|
|
|
|
|
|
|
case R_V850_CALLT_16_16_OFFSET: |
|
|
|
addend += bfd_get_16 (abfd, address); |
|
|
|
|
|
|
|
|
|
|
|
saddend = (bfd_signed_vma) addend; |
|
|
|
|
|
|
|
|
|
|
|
if (saddend > 0xffff || saddend < 0) |
|
|
|
return bfd_reloc_overflow; |
|
|
|
|
|
|
|
insn = addend; |
|
|
|
break; |
|
|
|
|
|
|
|
|
|
|
|
case R_V850_16: |
|
|
|
|
|
|
|
/* drop through */ |
|
|
|
/* drop through */ |
|
|
|
case R_V850_SDA_16_16_OFFSET: |
|
|
|
case R_V850_ZDA_16_16_OFFSET: |
|
|
|
case R_V850_TDA_16_16_OFFSET: |
|
|
|
addend += bfd_get_16 (abfd, address); |
|
|
|
|
|
|
|
|
|
|
|
saddend = (bfd_signed_vma) addend; |
|
|
|
|
|
|
|
|
|
|
|
if (saddend > 0x7fff || saddend < -0x8000) |
|
|
|
return bfd_reloc_overflow; |
|
|
|
|
|
|
|
insn = addend; |
|
|
|
break; |
|
|
|
|
|
|
|
|
|
|
|
case R_V850_SDA_15_16_OFFSET: |
|
|
|
case R_V850_ZDA_15_16_OFFSET: |
|
|
|
insn = bfd_get_16 (abfd, address); |
|
|
|
addend += (insn & 0xfffe); |
|
|
|
|
|
|
|
|
|
|
|
saddend = (bfd_signed_vma) addend; |
|
|
|
|
|
|
|
|
|
|
|
if (saddend > 0x7ffe || saddend < -0x8000) |
|
|
|
return bfd_reloc_overflow; |
|
|
|
|
|
|
|
|
|
|
|
if (addend & 1) |
|
|
|
return bfd_reloc_dangerous; |
|
|
|
|
|
|
|
|
|
|
|
insn = (addend & ~1) | (insn & 1); |
|
|
|
break; |
|
|
|
|
|
|
|
|
|
|
|
case R_V850_TDA_6_8_OFFSET: |
|
|
|
insn = bfd_get_16 (abfd, address); |
|
|
|
addend += ((insn & 0x7e) << 1); |
|
|
|
|
|
|
|
|
|
|
|
saddend = (bfd_signed_vma) addend; |
|
|
|
|
|
|
|
|
|
|
|
if (saddend > 0xfc || saddend < 0) |
|
|
|
return bfd_reloc_overflow; |
|
|
|
|
|
|
|
|
|
|
|
if (addend & 3) |
|
|
|
return bfd_reloc_dangerous; |
|
|
|
|
|
|
|
|
|
|
|
insn &= 0xff81; |
|
|
|
insn |= (addend >> 1); |
|
|
|
break; |
|
|
|
|
|
|
|
|
|
|
|
case R_V850_TDA_7_8_OFFSET: |
|
|
|
insn = bfd_get_16 (abfd, address); |
|
|
|
addend += ((insn & 0x7f) << 1); |
|
|
|
|
|
|
|
|
|
|
|
saddend = (bfd_signed_vma) addend; |
|
|
|
|
|
|
|
|
|
|
|
if (saddend > 0xfe || saddend < 0) |
|
|
|
return bfd_reloc_overflow; |
|
|
|
|
|
|
|
|
|
|
|
if (addend & 1) |
|
|
|
return bfd_reloc_dangerous; |
|
|
|
|
|
|
|
|
|
|
|
insn &= 0xff80; |
|
|
|
insn |= (addend >> 1); |
|
|
|
break; |
|
|
|
|
|
|
|
|
|
|
|
case R_V850_TDA_7_7_OFFSET: |
|
|
|
insn = bfd_get_16 (abfd, address); |
|
|
|
addend += insn & 0x7f; |
|
|
|
|
|
|
|
|
|
|
|
saddend = (bfd_signed_vma) addend; |
|
|
|
|
|
|
|
|
|
|
|
if (saddend > 0x7f || saddend < 0) |
|
|
|
return bfd_reloc_overflow; |
|
|
|
|
|
|
|
|
|
|
|
insn &= 0xff80; |
|
|
|
insn |= addend; |
|
|
|
break; |
|
|
|
|
|
|
|
|
|
|
|
case R_V850_TDA_4_5_OFFSET: |
|
|
|
insn = bfd_get_16 (abfd, address); |
|
|
|
addend += ((insn & 0xf) << 1); |
|
|
|
|
|
|
|
|
|
|
|
saddend = (bfd_signed_vma) addend; |
|
|
|
|
|
|
|
|
|
|
|
if (saddend > 0x1e || saddend < 0) |
|
|
|
return bfd_reloc_overflow; |
|
|
|
|
|
|
|
|
|
|
|
if (addend & 1) |
|
|
|
return bfd_reloc_dangerous; |
|
|
|
|
|
|
|
|
|
|
|
insn &= 0xfff0; |
|
|
|
insn |= (addend >> 1); |
|
|
|
break; |
|
|
|
|
|
|
|
|
|
|
|
case R_V850_TDA_4_4_OFFSET: |
|
|
|
insn = bfd_get_16 (abfd, address); |
|
|
|
addend += insn & 0xf; |
|
|
|
|
|
|
|
|
|
|
|
saddend = (bfd_signed_vma) addend; |
|
|
|
|
|
|
|
|
|
|
|
if (saddend > 0xf || saddend < 0) |
|
|
|
return bfd_reloc_overflow; |
|
|
|
|
|
|
|
|
|
|
|
insn &= 0xfff0; |
|
|
|
insn |= addend; |
|
|
|
break; |
|
|
|
|
|
|
|
|
|
|
|
case R_V850_ZDA_16_16_SPLIT_OFFSET: |
|
|
|
case R_V850_SDA_16_16_SPLIT_OFFSET: |
|
|
|
insn = bfd_get_32 (abfd, address); |
|
|
|
addend += ((insn & 0xfffe0000) >> 16) + ((insn & 0x20) >> 5); |
|
|
|
|
|
|
|
|
|
|
|
saddend = (bfd_signed_vma) addend; |
|
|
|
|
|
|
|
|
|
|
|
if (saddend > 0x7fff || saddend < -0x8000) |
|
|
|
return bfd_reloc_overflow; |
|
|
|
|
|
|
|
|
|
|
|
insn &= 0x0001ffdf; |
|
|
|
insn |= (addend & 1) << 5; |
|
|
|
insn |= (addend & ~1) << 16; |
|
|
|
|
|
|
|
|
|
|
|
bfd_put_32 (abfd, insn, address); |
|
|
|
return bfd_reloc_ok; |
|
|
|
|
|
|
|
|
|
|
|
case R_V850_CALLT_6_7_OFFSET: |
|
|
|
insn = bfd_get_16 (abfd, address); |
|
|
|
addend += ((insn & 0x3f) << 1); |
|
|
|
|
|
|
|
|
|
|
|
saddend = (bfd_signed_vma) addend; |
|
|
|
|
|
|
|
|
|
|
|
if (saddend > 0x7e || saddend < 0) |
|
|
|
return bfd_reloc_overflow; |
|
|
|
|
|
|
|
|
|
|
|
if (addend & 1) |
|
|
|
return bfd_reloc_dangerous; |
|
|
|
|
|
|
|
|
|
|
|
insn &= 0xff80; |
|
|
|
insn |= (addend >> 1); |
|
|
|
break; |
|
|
|
@ -1261,7 +1257,7 @@ v850_elf_reloc (abfd, reloc, symbol, data, isection, obfd, err) |
|
|
|
char ** err ATTRIBUTE_UNUSED; |
|
|
|
{ |
|
|
|
long relocation; |
|
|
|
|
|
|
|
|
|
|
|
/* If there is an output BFD,
|
|
|
|
and the symbol is not a section name (which is only defined at final link time), |
|
|
|
and either we are not putting the addend into the instruction |
|
|
|
@ -1275,13 +1271,13 @@ v850_elf_reloc (abfd, reloc, symbol, data, isection, obfd, err) |
|
|
|
reloc->address += isection->output_offset; |
|
|
|
return bfd_reloc_ok; |
|
|
|
} |
|
|
|
#if 0
|
|
|
|
#if 0 |
|
|
|
else if (obfd != NULL) |
|
|
|
{ |
|
|
|
return bfd_reloc_continue; |
|
|
|
} |
|
|
|
#endif |
|
|
|
|
|
|
|
|
|
|
|
/* Catch relocs involving undefined symbols. */ |
|
|
|
if (bfd_is_und_section (symbol->section) |
|
|
|
&& (symbol->flags & BSF_WEAK) == 0 |
|
|
|
@ -1293,37 +1289,36 @@ v850_elf_reloc (abfd, reloc, symbol, data, isection, obfd, err) |
|
|
|
/* 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; |
|
|
|
} |
|
|
|
|
|
|
|
reloc->addend = relocation; |
|
|
|
reloc->addend = relocation; |
|
|
|
return bfd_reloc_ok; |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/*ARGSUSED*/ |
|
|
|
static boolean |
|
|
|
v850_elf_is_local_label_name (abfd, name) |
|
|
|
bfd * abfd ATTRIBUTE_UNUSED; |
|
|
|
@ -1362,7 +1357,7 @@ v850_elf_final_link_relocate (howto, input_bfd, output_bfd, |
|
|
|
+ input_section->output_offset); |
|
|
|
value -= offset; |
|
|
|
break; |
|
|
|
|
|
|
|
|
|
|
|
case R_V850_22_PCREL: |
|
|
|
value -= (input_section->output_section->vma |
|
|
|
+ input_section->output_offset |
|
|
|
@ -1371,10 +1366,10 @@ v850_elf_final_link_relocate (howto, input_bfd, output_bfd, |
|
|
|
/* If the sign extension will corrupt the value then we have overflowed. */ |
|
|
|
if (((value & 0xff000000) != 0x0) && ((value & 0xff000000) != 0xff000000)) |
|
|
|
return bfd_reloc_overflow; |
|
|
|
|
|
|
|
|
|
|
|
value = SEXT24 (value); /* Only the bottom 24 bits of the PC are valid */ |
|
|
|
break; |
|
|
|
|
|
|
|
|
|
|
|
case R_V850_HI16_S: |
|
|
|
case R_V850_HI16: |
|
|
|
case R_V850_LO16: |
|
|
|
@ -1383,12 +1378,12 @@ v850_elf_final_link_relocate (howto, input_bfd, output_bfd, |
|
|
|
case R_V850_8: |
|
|
|
break; |
|
|
|
|
|
|
|
case R_V850_ZDA_15_16_OFFSET: |
|
|
|
case R_V850_ZDA_15_16_OFFSET: |
|
|
|
case R_V850_ZDA_16_16_OFFSET: |
|
|
|
case R_V850_ZDA_16_16_SPLIT_OFFSET: |
|
|
|
if (sym_sec == NULL) |
|
|
|
return bfd_reloc_undefined; |
|
|
|
|
|
|
|
|
|
|
|
value -= sym_sec->output_section->vma; |
|
|
|
break; |
|
|
|
|
|
|
|
@ -1401,7 +1396,7 @@ v850_elf_final_link_relocate (howto, input_bfd, output_bfd, |
|
|
|
|
|
|
|
if (sym_sec == NULL) |
|
|
|
return bfd_reloc_undefined; |
|
|
|
|
|
|
|
|
|
|
|
/* Get the value of __gp. */ |
|
|
|
h = bfd_link_hash_lookup (info->hash, "__gp", false, false, true); |
|
|
|
if (h == (struct bfd_link_hash_entry *) NULL |
|
|
|
@ -1426,12 +1421,12 @@ v850_elf_final_link_relocate (howto, input_bfd, output_bfd, |
|
|
|
{ |
|
|
|
unsigned long ep; |
|
|
|
struct bfd_link_hash_entry * h; |
|
|
|
|
|
|
|
|
|
|
|
/* Get the value of __ep. */ |
|
|
|
h = bfd_link_hash_lookup (info->hash, "__ep", false, false, true); |
|
|
|
if (h == (struct bfd_link_hash_entry *) NULL |
|
|
|
|| h->type != bfd_link_hash_defined) |
|
|
|
return bfd_reloc_continue; /* Actually this indicates that __ep could not be found. */ |
|
|
|
return bfd_reloc_continue; /* Actually this indicates that __ep could not be found. */ |
|
|
|
|
|
|
|
ep = (h->u.def.value |
|
|
|
+ h->u.def.section->output_section->vma |
|
|
|
@ -1440,17 +1435,17 @@ v850_elf_final_link_relocate (howto, input_bfd, output_bfd, |
|
|
|
value -= ep; |
|
|
|
} |
|
|
|
break; |
|
|
|
|
|
|
|
|
|
|
|
case R_V850_CALLT_6_7_OFFSET: |
|
|
|
{ |
|
|
|
unsigned long ctbp; |
|
|
|
struct bfd_link_hash_entry * h; |
|
|
|
|
|
|
|
|
|
|
|
/* Get the value of __ctbp. */ |
|
|
|
h = bfd_link_hash_lookup (info->hash, "__ctbp", false, false, true); |
|
|
|
if (h == (struct bfd_link_hash_entry *) NULL |
|
|
|
|| h->type != bfd_link_hash_defined) |
|
|
|
return (bfd_reloc_dangerous + 1); /* Actually this indicates that __ctbp could not be found. */ |
|
|
|
return (bfd_reloc_dangerous + 1); /* Actually this indicates that __ctbp could not be found. */ |
|
|
|
|
|
|
|
ctbp = (h->u.def.value |
|
|
|
+ h->u.def.section->output_section->vma |
|
|
|
@ -1458,7 +1453,7 @@ v850_elf_final_link_relocate (howto, input_bfd, output_bfd, |
|
|
|
value -= ctbp; |
|
|
|
} |
|
|
|
break; |
|
|
|
|
|
|
|
|
|
|
|
case R_V850_CALLT_16_16_OFFSET: |
|
|
|
{ |
|
|
|
unsigned long ctbp; |
|
|
|
@ -1466,7 +1461,7 @@ v850_elf_final_link_relocate (howto, input_bfd, output_bfd, |
|
|
|
|
|
|
|
if (sym_sec == NULL) |
|
|
|
return bfd_reloc_undefined; |
|
|
|
|
|
|
|
|
|
|
|
/* Get the value of __ctbp. */ |
|
|
|
h = bfd_link_hash_lookup (info->hash, "__ctbp", false, false, true); |
|
|
|
if (h == (struct bfd_link_hash_entry *) NULL |
|
|
|
@ -1481,7 +1476,7 @@ v850_elf_final_link_relocate (howto, input_bfd, output_bfd, |
|
|
|
value -= (ctbp - sym_sec->output_section->vma); |
|
|
|
} |
|
|
|
break; |
|
|
|
|
|
|
|
|
|
|
|
case R_V850_NONE: |
|
|
|
case R_V850_GNU_VTINHERIT: |
|
|
|
case R_V850_GNU_VTENTRY: |
|
|
|
@ -1492,7 +1487,7 @@ v850_elf_final_link_relocate (howto, input_bfd, output_bfd, |
|
|
|
} |
|
|
|
|
|
|
|
/* Perform the relocation. */ |
|
|
|
return v850_elf_perform_relocation (input_bfd, r_type, value + addend, hit_data); |
|
|
|
return v850_elf_perform_relocation (input_bfd, r_type, value + addend, hit_data); |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
@ -1524,12 +1519,12 @@ v850_elf_relocate_section (output_bfd, info, input_bfd, input_section, |
|
|
|
|
|
|
|
return false; |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/* Reset the list of remembered HI16S relocs to empty. */ |
|
|
|
free_hi16s = previous_hi16s; |
|
|
|
previous_hi16s = NULL; |
|
|
|
hi16s_counter = 0; |
|
|
|
|
|
|
|
|
|
|
|
rel = relocs; |
|
|
|
relend = relocs + input_section->reloc_count; |
|
|
|
for (; rel < relend; rel++) |
|
|
|
@ -1596,11 +1591,11 @@ fprintf (stderr, "local: sec: %s, sym: %s (%d), value: %x + %x + %x addend %x\n" |
|
|
|
else |
|
|
|
{ |
|
|
|
h = sym_hashes[r_symndx - symtab_hdr->sh_info]; |
|
|
|
|
|
|
|
|
|
|
|
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; |
|
|
|
|
|
|
|
|
|
|
|
if (h->root.type == bfd_link_hash_defined |
|
|
|
|| h->root.type == bfd_link_hash_defweak) |
|
|
|
{ |
|
|
|
@ -1696,7 +1691,7 @@ fprintf (stderr, "unknown: name: %s\n", h->root.root.string); |
|
|
|
case (bfd_reloc_dangerous + 1): |
|
|
|
msg = _("could not locate special linker symbol __ctbp"); |
|
|
|
goto common_error; |
|
|
|
|
|
|
|
|
|
|
|
default: |
|
|
|
msg = _("internal error: unknown error"); |
|
|
|
/* fall through */ |
|
|
|
@ -1803,7 +1798,7 @@ v850_elf_final_write_processing (abfd, linker) |
|
|
|
elf_elfheader (abfd)->e_flags |= val; |
|
|
|
} |
|
|
|
|
|
|
|
/* Function to keep V850 specific file flags. */ |
|
|
|
/* Function to keep V850 specific file flags. */ |
|
|
|
static boolean |
|
|
|
v850_elf_set_private_flags (abfd, flags) |
|
|
|
bfd * abfd; |
|
|
|
@ -1864,7 +1859,7 @@ v850_elf_merge_private_bfd_data (ibfd, obfd) |
|
|
|
to the default values. */ |
|
|
|
if (bfd_get_arch_info (ibfd)->the_default) |
|
|
|
return true; |
|
|
|
|
|
|
|
|
|
|
|
elf_flags_init (obfd) = true; |
|
|
|
elf_elfheader (obfd)->e_flags = in_flags; |
|
|
|
|
|
|
|
@ -1896,14 +1891,14 @@ v850_elf_print_private_bfd_data (abfd, ptr) |
|
|
|
PTR ptr; |
|
|
|
{ |
|
|
|
FILE * file = (FILE *) ptr; |
|
|
|
|
|
|
|
|
|
|
|
BFD_ASSERT (abfd != NULL && ptr != NULL); |
|
|
|
|
|
|
|
|
|
|
|
_bfd_elf_print_private_bfd_data (abfd, ptr); |
|
|
|
|
|
|
|
|
|
|
|
/* xgettext:c-format */ |
|
|
|
fprintf (file, _("private flags = %lx: "), elf_elfheader (abfd)->e_flags); |
|
|
|
|
|
|
|
|
|
|
|
switch (elf_elfheader (abfd)->e_flags & EF_V850_ARCH) |
|
|
|
{ |
|
|
|
default: |
|
|
|
@ -1911,9 +1906,9 @@ v850_elf_print_private_bfd_data (abfd, ptr) |
|
|
|
case E_V850E_ARCH: fprintf (file, _("v850e architecture")); break; |
|
|
|
case E_V850EA_ARCH: fprintf (file, _("v850ea architecture")); break; |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
fputc ('\n', file); |
|
|
|
|
|
|
|
|
|
|
|
return true; |
|
|
|
} |
|
|
|
|
|
|
|
@ -1934,7 +1929,6 @@ static asection v850_elf_zcom_section; |
|
|
|
static asymbol v850_elf_zcom_symbol; |
|
|
|
static asymbol * v850_elf_zcom_symbol_ptr; |
|
|
|
|
|
|
|
|
|
|
|
/* Given a BFD section, try to locate the corresponding ELF section
|
|
|
|
index. */ |
|
|
|
|
|
|
|
@ -1953,7 +1947,7 @@ v850_elf_section_from_bfd_section (abfd, hdr, sec, retval) |
|
|
|
*retval = SHN_V850_ZCOMMON; |
|
|
|
else |
|
|
|
return false; |
|
|
|
|
|
|
|
|
|
|
|
return true; |
|
|
|
} |
|
|
|
|
|
|
|
@ -1966,34 +1960,34 @@ v850_elf_symbol_processing (abfd, asym) |
|
|
|
{ |
|
|
|
elf_symbol_type * elfsym = (elf_symbol_type *) asym; |
|
|
|
unsigned short index; |
|
|
|
|
|
|
|
|
|
|
|
index = elfsym->internal_elf_sym.st_shndx; |
|
|
|
|
|
|
|
/* If the section index is an "ordinary" index, then it may
|
|
|
|
refer to a v850 specific section created by the assembler. |
|
|
|
Check the section's type and change the index it matches. |
|
|
|
|
|
|
|
|
|
|
|
FIXME: Should we alter the st_shndx field as well ? */ |
|
|
|
|
|
|
|
|
|
|
|
if (index < elf_elfheader(abfd)[0].e_shnum) |
|
|
|
switch (elf_elfsections(abfd)[index]->sh_type) |
|
|
|
{ |
|
|
|
case SHT_V850_SCOMMON: |
|
|
|
index = SHN_V850_SCOMMON; |
|
|
|
break; |
|
|
|
|
|
|
|
|
|
|
|
case SHT_V850_TCOMMON: |
|
|
|
index = SHN_V850_TCOMMON; |
|
|
|
break; |
|
|
|
|
|
|
|
|
|
|
|
case SHT_V850_ZCOMMON: |
|
|
|
index = SHN_V850_ZCOMMON; |
|
|
|
break; |
|
|
|
|
|
|
|
|
|
|
|
default: |
|
|
|
break; |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
switch (index) |
|
|
|
{ |
|
|
|
case SHN_V850_SCOMMON: |
|
|
|
@ -2013,7 +2007,7 @@ v850_elf_symbol_processing (abfd, asym) |
|
|
|
asym->section = & v850_elf_scom_section; |
|
|
|
asym->value = elfsym->internal_elf_sym.st_size; |
|
|
|
break; |
|
|
|
|
|
|
|
|
|
|
|
case SHN_V850_TCOMMON: |
|
|
|
if (v850_elf_tcom_section.name == NULL) |
|
|
|
{ |
|
|
|
@ -2055,7 +2049,6 @@ v850_elf_symbol_processing (abfd, asym) |
|
|
|
/* Hook called by the linker routine which adds symbols from an object
|
|
|
|
file. We must handle the special v850 section numbers here. */ |
|
|
|
|
|
|
|
/*ARGSUSED*/ |
|
|
|
static boolean |
|
|
|
v850_elf_add_symbol_hook (abfd, info, sym, namep, flagsp, secp, valp) |
|
|
|
bfd * abfd; |
|
|
|
@ -2067,32 +2060,32 @@ v850_elf_add_symbol_hook (abfd, info, sym, namep, flagsp, secp, valp) |
|
|
|
bfd_vma * valp; |
|
|
|
{ |
|
|
|
int index = sym->st_shndx; |
|
|
|
|
|
|
|
|
|
|
|
/* If the section index is an "ordinary" index, then it may
|
|
|
|
refer to a v850 specific section created by the assembler. |
|
|
|
Check the section's type and change the index it matches. |
|
|
|
|
|
|
|
|
|
|
|
FIXME: Should we alter the st_shndx field as well ? */ |
|
|
|
|
|
|
|
|
|
|
|
if (index < elf_elfheader(abfd)[0].e_shnum) |
|
|
|
switch (elf_elfsections(abfd)[index]->sh_type) |
|
|
|
{ |
|
|
|
case SHT_V850_SCOMMON: |
|
|
|
index = SHN_V850_SCOMMON; |
|
|
|
break; |
|
|
|
|
|
|
|
|
|
|
|
case SHT_V850_TCOMMON: |
|
|
|
index = SHN_V850_TCOMMON; |
|
|
|
break; |
|
|
|
|
|
|
|
|
|
|
|
case SHT_V850_ZCOMMON: |
|
|
|
index = SHN_V850_ZCOMMON; |
|
|
|
break; |
|
|
|
|
|
|
|
|
|
|
|
default: |
|
|
|
break; |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
switch (index) |
|
|
|
{ |
|
|
|
case SHN_V850_SCOMMON: |
|
|
|
@ -2100,13 +2093,13 @@ v850_elf_add_symbol_hook (abfd, info, sym, namep, flagsp, secp, valp) |
|
|
|
(*secp)->flags |= SEC_IS_COMMON; |
|
|
|
*valp = sym->st_size; |
|
|
|
break; |
|
|
|
|
|
|
|
|
|
|
|
case SHN_V850_TCOMMON: |
|
|
|
*secp = bfd_make_section_old_way (abfd, ".tcommon"); |
|
|
|
(*secp)->flags |= SEC_IS_COMMON; |
|
|
|
*valp = sym->st_size; |
|
|
|
break; |
|
|
|
|
|
|
|
|
|
|
|
case SHN_V850_ZCOMMON: |
|
|
|
*secp = bfd_make_section_old_way (abfd, ".zcommon"); |
|
|
|
(*secp)->flags |= SEC_IS_COMMON; |
|
|
|
@ -2129,7 +2122,7 @@ v850_elf_link_output_symbol_hook (abfd, info, name, sym, input_sec) |
|
|
|
/* If we see a common symbol, which implies a relocatable link, then
|
|
|
|
if a symbol was in a special common section in an input file, mark |
|
|
|
it as a special common in the output file. */ |
|
|
|
|
|
|
|
|
|
|
|
if (sym->st_shndx == SHN_COMMON) |
|
|
|
{ |
|
|
|
if (strcmp (input_sec->name, ".scommon") == 0) |
|
|
|
@ -2193,18 +2186,17 @@ v850_elf_fake_sections (abfd, hdr, sec) |
|
|
|
} |
|
|
|
else if (strcmp (name, ".zcommon") == 0) |
|
|
|
hdr->sh_type = SHT_V850_ZCOMMON; |
|
|
|
|
|
|
|
|
|
|
|
return true; |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#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 |
|
|
|
|
|
|
|
|
|
|
|
#define elf_info_to_howto v850_elf_info_to_howto_rela |
|
|
|
#define elf_info_to_howto_rel v850_elf_info_to_howto_rel |
|
|
|
|
|
|
|
@ -2223,7 +2215,6 @@ v850_elf_fake_sections (abfd, hdr, sec) |
|
|
|
|
|
|
|
#define elf_backend_can_gc_sections 1 |
|
|
|
|
|
|
|
|
|
|
|
#define bfd_elf32_bfd_is_local_label_name v850_elf_is_local_label_name |
|
|
|
#define bfd_elf32_bfd_reloc_type_lookup v850_elf_reloc_type_lookup |
|
|
|
#define bfd_elf32_bfd_copy_private_bfd_data v850_elf_copy_private_bfd_data |
|
|
|
|