* elf32-bfin.c (bfin_howto_table): Set src_mask to 0 for all relocs. (bfin_imm16_reloc): Always add in the addend. Don't fetch existing contents from section. (bfin_relocate_section): Rework so as to not call special_functions. Handle the relocation stack here. Treat pcrel24 relocs specially. Index: elf32-bfin.c =================================================================== RCS file: /cvs/src/src/bfd/elf32-bfin.c,v retrieving revision 1.1 diff -c -p -r1.1 elf32-bfin.c *** elf32-bfin.c 30 Sep 2005 15:36:41 -0000 1.1 --- elf32-bfin.c 24 Oct 2005 12:37:42 -0000 *************** bfin_imm16_reloc (bfd *abfd, *** 433,443 **** if (!relocatable || !strcmp (symbol->name, symbol->section->name)) relocation += output_base + symbol->section->output_offset; ! if (symbol->flags & BSF_SECTION_SYM) ! { ! /* Add in supplied addend. */ ! relocation += reloc_entry->addend; ! } } else { --- 433,440 ---- if (!relocatable || !strcmp (symbol->name, symbol->section->name)) relocation += output_base + symbol->section->output_offset; ! /* Add in supplied addend. */ ! relocation += reloc_entry->addend; } else { *************** bfin_imm16_reloc (bfd *abfd, *** 470,476 **** /* Here the variable relocation holds the final address of the symbol we are relocating against, plus any addend. */ - x = bfd_get_16 (abfd, (bfd_byte *) data + reloc_addr); relocation >>= (bfd_vma) howto->rightshift; x = relocation; bfd_put_16 (abfd, x, (unsigned char *) data + reloc_addr); --- 467,472 ---- *************** static reloc_howto_type bfin_howto_table *** 759,765 **** bfin_bfd_reloc, /* special_function. */ "R_pcrel5m2", /* name. */ FALSE, /* partial_inplace. */ ! 0x0000000F, /* src_mask. */ 0x0000000F, /* dst_mask. */ FALSE), /* pcrel_offset. */ --- 755,761 ---- bfin_bfd_reloc, /* special_function. */ "R_pcrel5m2", /* name. */ FALSE, /* partial_inplace. */ ! 0, /* src_mask. */ 0x0000000F, /* dst_mask. */ FALSE), /* pcrel_offset. */ *************** static reloc_howto_type bfin_howto_table *** 787,793 **** bfin_bfd_reloc, /* special_function. */ "R_pcrel10", /* name. */ FALSE, /* partial_inplace. */ ! 0x000003FF, /* src_mask. */ 0x000003FF, /* dst_mask. */ TRUE), /* pcrel_offset. */ --- 783,789 ---- bfin_bfd_reloc, /* special_function. */ "R_pcrel10", /* name. */ FALSE, /* partial_inplace. */ ! 0, /* src_mask. */ 0x000003FF, /* dst_mask. */ TRUE), /* pcrel_offset. */ *************** static reloc_howto_type bfin_howto_table *** 805,811 **** bfin_bfd_reloc, /* special_function. */ "R_pcrel12_jump", /* name. */ FALSE, /* partial_inplace. */ ! 0x0FFF, /* src_mask. */ 0x0FFF, /* dst_mask. */ TRUE), /* pcrel_offset. */ --- 801,807 ---- bfin_bfd_reloc, /* special_function. */ "R_pcrel12_jump", /* name. */ FALSE, /* partial_inplace. */ ! 0, /* src_mask. */ 0x0FFF, /* dst_mask. */ TRUE), /* pcrel_offset. */ *************** static reloc_howto_type bfin_howto_table *** 819,825 **** bfin_imm16_reloc, /* special_function. */ "R_rimm16", /* name. */ FALSE, /* partial_inplace. */ ! 0x0000FFFF, /* src_mask. */ 0x0000FFFF, /* dst_mask. */ TRUE), /* pcrel_offset. */ --- 815,821 ---- bfin_imm16_reloc, /* special_function. */ "R_rimm16", /* name. */ FALSE, /* partial_inplace. */ ! 0, /* src_mask. */ 0x0000FFFF, /* dst_mask. */ TRUE), /* pcrel_offset. */ *************** static reloc_howto_type bfin_howto_table *** 833,839 **** bfin_imm16_reloc, /* special_function. */ "R_luimm16", /* name. */ FALSE, /* partial_inplace. */ ! 0x0000FFFF, /* src_mask. */ 0x0000FFFF, /* dst_mask. */ TRUE), /* pcrel_offset. */ --- 829,835 ---- bfin_imm16_reloc, /* special_function. */ "R_luimm16", /* name. */ FALSE, /* partial_inplace. */ ! 0, /* src_mask. */ 0x0000FFFF, /* dst_mask. */ TRUE), /* pcrel_offset. */ *************** static reloc_howto_type bfin_howto_table *** 847,853 **** bfin_imm16_reloc, /* special_function. */ "R_huimm16", /* name. */ FALSE, /* partial_inplace. */ ! 0x0000FFFF, /* src_mask. */ 0x0000FFFF, /* dst_mask. */ TRUE), /* pcrel_offset. */ --- 843,849 ---- bfin_imm16_reloc, /* special_function. */ "R_huimm16", /* name. */ FALSE, /* partial_inplace. */ ! 0, /* src_mask. */ 0x0000FFFF, /* dst_mask. */ TRUE), /* pcrel_offset. */ *************** static reloc_howto_type bfin_howto_table *** 861,867 **** bfin_bfd_reloc, /* special_function. */ "R_pcrel12_jump_s", /* name. */ FALSE, /* partial_inplace. */ ! 0x00000FFF, /* src_mask. */ 0x00000FFF, /* dst_mask. */ TRUE), /* pcrel_offset. */ --- 857,863 ---- bfin_bfd_reloc, /* special_function. */ "R_pcrel12_jump_s", /* name. */ FALSE, /* partial_inplace. */ ! 0, /* src_mask. */ 0x00000FFF, /* dst_mask. */ TRUE), /* pcrel_offset. */ *************** static reloc_howto_type bfin_howto_table *** 875,881 **** bfin_pcrel24_reloc, /* special_function. */ "R_pcrel24_jump_x", /* name. */ FALSE, /* partial_inplace. */ ! 0x00FFFFFF, /* src_mask. */ 0x00FFFFFF, /* dst_mask. */ TRUE), /* pcrel_offset. */ --- 871,877 ---- bfin_pcrel24_reloc, /* special_function. */ "R_pcrel24_jump_x", /* name. */ FALSE, /* partial_inplace. */ ! 0, /* src_mask. */ 0x00FFFFFF, /* dst_mask. */ TRUE), /* pcrel_offset. */ *************** static reloc_howto_type bfin_howto_table *** 889,895 **** bfin_pcrel24_reloc, /* special_function. */ "R_pcrel24", /* name. */ FALSE, /* partial_inplace. */ ! 0x00FFFFFF, /* src_mask. */ 0x00FFFFFF, /* dst_mask. */ TRUE), /* pcrel_offset. */ --- 885,891 ---- bfin_pcrel24_reloc, /* special_function. */ "R_pcrel24", /* name. */ FALSE, /* partial_inplace. */ ! 0, /* src_mask. */ 0x00FFFFFF, /* dst_mask. */ TRUE), /* pcrel_offset. */ *************** static reloc_howto_type bfin_howto_table *** 931,937 **** bfin_pcrel24_reloc, /* special_function. */ "R_pcrel24_jump_l", /* name. */ FALSE, /* partial_inplace. */ ! 0x00FFFFFF, /* src_mask. */ 0x00FFFFFF, /* dst_mask. */ TRUE), /* pcrel_offset. */ --- 927,933 ---- bfin_pcrel24_reloc, /* special_function. */ "R_pcrel24_jump_l", /* name. */ FALSE, /* partial_inplace. */ ! 0, /* src_mask. */ 0x00FFFFFF, /* dst_mask. */ TRUE), /* pcrel_offset. */ *************** static reloc_howto_type bfin_howto_table *** 945,951 **** bfin_pcrel24_reloc, /* special_function. */ "R_pcrel24_call_x", /* name. */ FALSE, /* partial_inplace. */ ! 0x00FFFFFF, /* src_mask. */ 0x00FFFFFF, /* dst_mask. */ TRUE), /* pcrel_offset. */ --- 941,947 ---- bfin_pcrel24_reloc, /* special_function. */ "R_pcrel24_call_x", /* name. */ FALSE, /* partial_inplace. */ ! 0, /* src_mask. */ 0x00FFFFFF, /* dst_mask. */ TRUE), /* pcrel_offset. */ *************** static reloc_howto_type bfin_howto_table *** 973,979 **** bfin_bfd_reloc, /* special_function. */ "R_byte_data", /* name. */ FALSE, /* partial_inplace. */ ! 0xFF, /* src_mask. */ 0xFF, /* dst_mask. */ TRUE), /* pcrel_offset. */ --- 969,975 ---- bfin_bfd_reloc, /* special_function. */ "R_byte_data", /* name. */ FALSE, /* partial_inplace. */ ! 0, /* src_mask. */ 0xFF, /* dst_mask. */ TRUE), /* pcrel_offset. */ *************** static reloc_howto_type bfin_howto_table *** 987,993 **** bfin_bfd_reloc, /* special_function. */ "R_byte2_data", /* name. */ FALSE, /* partial_inplace. */ ! 0xFFFF, /* src_mask. */ 0xFFFF, /* dst_mask. */ TRUE), /* pcrel_offset. */ --- 983,989 ---- bfin_bfd_reloc, /* special_function. */ "R_byte2_data", /* name. */ FALSE, /* partial_inplace. */ ! 0, /* src_mask. */ 0xFFFF, /* dst_mask. */ TRUE), /* pcrel_offset. */ *************** static reloc_howto_type bfin_howto_table *** 1001,1007 **** bfin_byte4_reloc, /* special_function. */ "R_byte4_data", /* name. */ FALSE, /* partial_inplace. */ ! 0xFFFFFFFF, /* src_mask. */ 0xFFFFFFFF, /* dst_mask. */ TRUE), /* pcrel_offset. */ --- 997,1003 ---- bfin_byte4_reloc, /* special_function. */ "R_byte4_data", /* name. */ FALSE, /* partial_inplace. */ ! 0, /* src_mask. */ 0xFFFFFFFF, /* dst_mask. */ TRUE), /* pcrel_offset. */ *************** static reloc_howto_type bfin_howto_table *** 1015,1021 **** bfin_bfd_reloc, /* special_function. */ "R_pcrel11", /* name. */ FALSE, /* partial_inplace. */ ! 0x000003FF, /* src_mask. */ 0x000003FF, /* dst_mask. */ FALSE), /* pcrel_offset. */ }; --- 1011,1017 ---- bfin_bfd_reloc, /* special_function. */ "R_pcrel11", /* name. */ FALSE, /* partial_inplace. */ ! 0, /* src_mask. */ 0x000003FF, /* dst_mask. */ FALSE), /* pcrel_offset. */ }; *************** elf32_bfin_reloc_type_class (const Elf_I *** 1660,1665 **** --- 1656,1662 ---- return reloc_class_normal; } } + static bfd_boolean bfin_relocate_section (bfd * output_bfd, struct bfd_link_info *info, *************** bfin_relocate_section (bfd * output_bfd, *** 1678,1684 **** asection *sreloc; Elf_Internal_Rela *rel; Elf_Internal_Rela *relend; - char *error_msg = NULL; int i = 0; if (info->relocatable) --- 1675,1680 ---- *************** bfin_relocate_section (bfd * output_bfd, *** 1705,1710 **** --- 1701,1707 ---- bfd_vma relocation = 0; bfd_boolean unresolved_reloc; bfd_reloc_status_type r; + bfd_vma address; r_type = ELF32_R_TYPE (rel->r_info); if (r_type < 0 || r_type >= 243) *************** bfin_relocate_section (bfd * output_bfd, *** 1735,1744 **** sym = local_syms + r_symndx; sec = local_sections[r_symndx]; relocation = _bfd_elf_rela_local_sym (output_bfd, sym, &sec, rel); - /* Call to bfd_elf_rela_local_sym would have CHANGED the sec - as well as updated relocation. The value returned is - w.r.t the original section. */ - sec = local_sections[r_symndx]; } else { --- 1732,1737 ---- *************** bfin_relocate_section (bfd * output_bfd, *** 1762,1767 **** --- 1755,1799 ---- } } + address = rel->r_offset; + /* First, get stack relocs out of the way. */ + switch (r_type) + { + case R_push: + reloc_stack_push (relocation + rel->r_addend); + r = bfd_reloc_ok; + goto done_reloc; + case R_const: + reloc_stack_push (rel->r_addend); + r = bfd_reloc_ok; + goto done_reloc; + case R_add: + case R_sub: + case R_mult: + case R_div: + case R_mod: + case R_lshift: + case R_rshift: + case R_neg: + case R_and: + case R_or: + case R_xor: + case R_land: + case R_lor: + case R_comp: + case R_page: + case R_hwpage: + reloc_stack_operate (r_type); + r = bfd_reloc_ok; + goto done_reloc; + + default: + if (!is_reloc_stack_empty()) + relocation = reloc_stack_pop (); + break; + } + + /* Then, process normally. */ switch (r_type) { case R_BFIN_GNU_VTINHERIT: *************** bfin_relocate_section (bfd * output_bfd, *** 1773,1779 **** in the global offset table. */ if (h != NULL && strcmp (h->root.root.string, "_GLOBAL_OFFSET_TABLE_") == 0) ! break; /* Fall through. */ /* Relocation is the offset of the entry for this symbol in the global offset table. */ --- 1805,1811 ---- in the global offset table. */ if (h != NULL && strcmp (h->root.root.string, "_GLOBAL_OFFSET_TABLE_") == 0) ! goto do_default; /* Fall through. */ /* Relocation is the offset of the entry for this symbol in the global offset table. */ *************** bfin_relocate_section (bfd * output_bfd, *** 1793,1805 **** off = h->got.offset; BFD_ASSERT (off != (bfd_vma) - 1); - dyn = elf_hash_table (info)->dynamic_sections_created; if (!WILL_CALL_FINISH_DYNAMIC_SYMBOL (dyn, info->shared, h) || (info->shared && (info->symbolic || h->dynindx == -1 ! || h->forced_local) && h->def_regular)) { /* This is actually a static link, or it is a -Bsymbolic link and the symbol is defined --- 1825,1838 ---- off = h->got.offset; BFD_ASSERT (off != (bfd_vma) - 1); dyn = elf_hash_table (info)->dynamic_sections_created; + if (!WILL_CALL_FINISH_DYNAMIC_SYMBOL (dyn, info->shared, h) || (info->shared && (info->symbolic || h->dynindx == -1 ! || h->forced_local) ! && h->def_regular)) { /* This is actually a static link, or it is a -Bsymbolic link and the symbol is defined *************** bfin_relocate_section (bfd * output_bfd, *** 1827,1836 **** } else { ! BFD_ASSERT (local_got_offsets != NULL ! && local_got_offsets[r_symndx] != (bfd_vma) - 1); ! off = local_got_offsets[r_symndx]; /* The offset must always be a multiple of 4. We use the least significant bit to record whether we have --- 1860,1868 ---- } else { ! BFD_ASSERT (local_got_offsets != NULL); off = local_got_offsets[r_symndx]; + BFD_ASSERT (off != (bfd_vma) - 1); /* The offset must always be a multiple of 4. We use the least significant bit to record whether we have *************** bfin_relocate_section (bfd * output_bfd, *** 1839,1845 **** off &= ~1; else { - bfd_put_32 (output_bfd, relocation, sgot->contents + off); if (info->shared) --- 1871,1876 ---- *************** bfin_relocate_section (bfd * output_bfd, *** 1871,1941 **** /* bfin : preg = [preg + 17bitdiv4offset] relocation is div by 4. */ relocation /= 4; } break; default: ! if (howto->special_function) ! { ! bfd_reloc_status_type cont; ! arelent reloc_ent; ! asymbol symbol; ! asymbol *symbol1; ! symbol.flags = 0; ! symbol.section = bfd_und_section_ptr; ! symbol.value = 0; - if (h != NULL) - { - if (unresolved_reloc) - { - break; - } - if (h->root.type != bfd_link_hash_undefweak - && h->root.type != bfd_link_hash_undefined) - { - symbol.the_bfd = input_bfd; - symbol.section = h->root.u.def.section; - symbol.name = h->root.root.string; - symbol.value = h->root.u.def.value; - } - if (h->root.type == bfd_link_hash_defweak - || h->root.type == bfd_link_hash_undefweak) - { - symbol.name = h->root.root.string; - symbol.flags |= BSF_WEAK; - } - } - else - { - symbol = *sec->symbol; - } - reloc_ent.address = rel->r_offset; - reloc_ent.howto = howto; - reloc_ent.addend = rel->r_addend; - symbol1 = &symbol; - reloc_ent.sym_ptr_ptr = &symbol1; - - cont = - howto->special_function (input_bfd, &reloc_ent, &symbol, - contents, input_section, - info-> - relocatable ? output_bfd : NULL, - &error_msg); - if (cont == bfd_reloc_ok) - { - continue; - } - } - else - { - fprintf (stderr, "%s no special func r_type is %d\n", - input_bfd->filename, r_type); - bfd_set_error (bfd_error_bad_value); - return FALSE; - } break; } /* Dynamic relocs are not propagated for SEC_DEBUGGING sections because such sections are not SEC_ALLOC and thus ld.so will not process them. */ --- 1902,1953 ---- /* bfin : preg = [preg + 17bitdiv4offset] relocation is div by 4. */ relocation /= 4; } + goto do_default; + + case R_pcrel24: + case R_pcrel24_jump_l: + { + bfd_vma x; + + relocation += rel->r_addend; + + /* Perform usual pc-relative correction. */ + relocation -= input_section->output_section->vma + input_section->output_offset; + relocation -= address; + + /* We are getting reloc_entry->address 2 byte off from + the start of instruction. Assuming absolute postion + of the reloc data. But, following code had been written assuming + reloc address is starting at begining of instruction. + To compensate that I have increased the value of + relocation by 1 (effectively 2) and used the addr -2 instead of addr. */ + + relocation += 2; + address -= 2; + + relocation >>= 1; + + x = bfd_get_16 (input_bfd, contents + address); + x = (x & 0xff00) | ((relocation >> 16) & 0xff); + bfd_put_16 (input_bfd, x, contents + address); + + x = bfd_get_16 (input_bfd, contents + address + 2); + x = relocation & 0xFFFF; + bfd_put_16 (input_bfd, x, contents + address + 2); + r = bfd_reloc_ok; + } break; default: ! do_default: ! r = _bfd_final_link_relocate (howto, input_bfd, input_section, ! contents, address, ! relocation, rel->r_addend); break; } + done_reloc: /* Dynamic relocs are not propagated for SEC_DEBUGGING sections because such sections are not SEC_ALLOC and thus ld.so will not process them. */ *************** bfin_relocate_section (bfd * output_bfd, *** 1949,1958 **** return FALSE; } - r = _bfd_final_link_relocate (howto, input_bfd, input_section, - contents, rel->r_offset, - relocation, rel->r_addend); - if (r != bfd_reloc_ok) { const char *name; --- 1961,1966 ----