From e73b6ae6344c58f5a10ecbf1e0f3ffe8005424b8 Mon Sep 17 00:00:00 2001 From: Jeff Law Date: Wed, 4 Sep 1996 03:03:53 +0000 Subject: * elf32-v850.c (bfd_elf32_v850_reloc): Fix handling of low order sign bit propogationfor R_V850_HI16_S. Fixes c-torture execute/950221-1.c, maybe others. --- bfd/ChangeLog | 6 ++- bfd/elf32-v850.c | 135 ++++++++++++++++++++++++++++++++++++++++++++++++------- 2 files changed, 124 insertions(+), 17 deletions(-) diff --git a/bfd/ChangeLog b/bfd/ChangeLog index 8c1b154..5cde6a5 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -5,7 +5,6 @@ Tue Sep 3 12:16:20 1996 Doug Evans * config.bfd (sparclet-*-aout*): Add case. * configure.in (sparcle_aout_vec): Add case. * configure: Regenerated. - * libaout.h (machine_type): Add M_SPARCLET_LE. * targets.c (sparcle_aout_vec): Declare. (bfd_target_vector): Add sparcle_aout_vec. * aout-sparcle.c: New file. @@ -13,7 +12,10 @@ Tue Sep 3 12:16:20 1996 Doug Evans start-sanitize-v850 Tue Sep 3 00:57:02 1996 Jeffrey A Law (law@cygnus.com) - * elf32-v850.c (bfd_elf3_v850_reloc): New function for + * elf32-v850.c (bfd_elf32_v850_reloc): Fix handling of + low order sign bit propogation for R_V850_HI16_S. + + * elf32-v850.c (bfd_elf32_v850_reloc): New function for handling V850 specific relocs. (elf_v850_howto_table): Use the new function for some relocations. Twiddle masks & shifts for some relocs. 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 -- cgit v1.1