This is the mail archive of the
binutils@sourceware.org
mailing list for the binutils project.
Blackfin patch: Clean up bfin_relocate_section
- From: Bernd Schmidt <bernds_cb1 at t-online dot de>
- To: binutils at sources dot redhat dot com
- Cc: Jie Zhang <jzhang918 at gmail dot com>
- Date: Mon, 24 Oct 2005 14:39:56 +0200
- Subject: Blackfin patch: Clean up bfin_relocate_section
This patch cleans up bfin_relocate_section - the BFD documentation
suggests that it shouldn't be calling the howto's special_function, and
cleaning that up solved some problems I was having with some upcoming
assembler modifications.
I'm working on this port at Analog Devices together with Jie Zhang. Can
I add myself to the MAINTAINERS file? In the meantime, could someone
approve the patch please?
Bernd
* 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 ----