* 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.
This commit is contained in:
Jie Zhang 2005-10-24 14:25:13 +00:00
parent f02571c5d9
commit f470759536
2 changed files with 111 additions and 95 deletions

View File

@ -1,3 +1,11 @@
2005-10-24 Bernd Schmidt <bernd.schmidt@analog.com>
* 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.
2005-10-24 Alan Modra <amodra@bigpond.net.au>
* elflink.c (elf_link_input_bfd): Don't use linker_mark and

View File

@ -433,11 +433,8 @@ bfin_imm16_reloc (bfd *abfd,
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;
}
/* Add in supplied addend. */
relocation += reloc_entry->addend;
}
else
{
@ -470,7 +467,6 @@ bfin_imm16_reloc (bfd *abfd,
/* 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);
@ -759,7 +755,7 @@ static reloc_howto_type bfin_howto_table [] =
bfin_bfd_reloc, /* special_function. */
"R_pcrel5m2", /* name. */
FALSE, /* partial_inplace. */
0x0000000F, /* src_mask. */
0, /* src_mask. */
0x0000000F, /* dst_mask. */
FALSE), /* pcrel_offset. */
@ -787,7 +783,7 @@ static reloc_howto_type bfin_howto_table [] =
bfin_bfd_reloc, /* special_function. */
"R_pcrel10", /* name. */
FALSE, /* partial_inplace. */
0x000003FF, /* src_mask. */
0, /* src_mask. */
0x000003FF, /* dst_mask. */
TRUE), /* pcrel_offset. */
@ -805,7 +801,7 @@ static reloc_howto_type bfin_howto_table [] =
bfin_bfd_reloc, /* special_function. */
"R_pcrel12_jump", /* name. */
FALSE, /* partial_inplace. */
0x0FFF, /* src_mask. */
0, /* src_mask. */
0x0FFF, /* dst_mask. */
TRUE), /* pcrel_offset. */
@ -819,7 +815,7 @@ static reloc_howto_type bfin_howto_table [] =
bfin_imm16_reloc, /* special_function. */
"R_rimm16", /* name. */
FALSE, /* partial_inplace. */
0x0000FFFF, /* src_mask. */
0, /* src_mask. */
0x0000FFFF, /* dst_mask. */
TRUE), /* pcrel_offset. */
@ -833,7 +829,7 @@ static reloc_howto_type bfin_howto_table [] =
bfin_imm16_reloc, /* special_function. */
"R_luimm16", /* name. */
FALSE, /* partial_inplace. */
0x0000FFFF, /* src_mask. */
0, /* src_mask. */
0x0000FFFF, /* dst_mask. */
TRUE), /* pcrel_offset. */
@ -847,7 +843,7 @@ static reloc_howto_type bfin_howto_table [] =
bfin_imm16_reloc, /* special_function. */
"R_huimm16", /* name. */
FALSE, /* partial_inplace. */
0x0000FFFF, /* src_mask. */
0, /* src_mask. */
0x0000FFFF, /* dst_mask. */
TRUE), /* pcrel_offset. */
@ -861,7 +857,7 @@ static reloc_howto_type bfin_howto_table [] =
bfin_bfd_reloc, /* special_function. */
"R_pcrel12_jump_s", /* name. */
FALSE, /* partial_inplace. */
0x00000FFF, /* src_mask. */
0, /* src_mask. */
0x00000FFF, /* dst_mask. */
TRUE), /* pcrel_offset. */
@ -875,7 +871,7 @@ static reloc_howto_type bfin_howto_table [] =
bfin_pcrel24_reloc, /* special_function. */
"R_pcrel24_jump_x", /* name. */
FALSE, /* partial_inplace. */
0x00FFFFFF, /* src_mask. */
0, /* src_mask. */
0x00FFFFFF, /* dst_mask. */
TRUE), /* pcrel_offset. */
@ -889,7 +885,7 @@ static reloc_howto_type bfin_howto_table [] =
bfin_pcrel24_reloc, /* special_function. */
"R_pcrel24", /* name. */
FALSE, /* partial_inplace. */
0x00FFFFFF, /* src_mask. */
0, /* src_mask. */
0x00FFFFFF, /* dst_mask. */
TRUE), /* pcrel_offset. */
@ -931,7 +927,7 @@ static reloc_howto_type bfin_howto_table [] =
bfin_pcrel24_reloc, /* special_function. */
"R_pcrel24_jump_l", /* name. */
FALSE, /* partial_inplace. */
0x00FFFFFF, /* src_mask. */
0, /* src_mask. */
0x00FFFFFF, /* dst_mask. */
TRUE), /* pcrel_offset. */
@ -945,7 +941,7 @@ static reloc_howto_type bfin_howto_table [] =
bfin_pcrel24_reloc, /* special_function. */
"R_pcrel24_call_x", /* name. */
FALSE, /* partial_inplace. */
0x00FFFFFF, /* src_mask. */
0, /* src_mask. */
0x00FFFFFF, /* dst_mask. */
TRUE), /* pcrel_offset. */
@ -973,7 +969,7 @@ static reloc_howto_type bfin_howto_table [] =
bfin_bfd_reloc, /* special_function. */
"R_byte_data", /* name. */
FALSE, /* partial_inplace. */
0xFF, /* src_mask. */
0, /* src_mask. */
0xFF, /* dst_mask. */
TRUE), /* pcrel_offset. */
@ -987,7 +983,7 @@ static reloc_howto_type bfin_howto_table [] =
bfin_bfd_reloc, /* special_function. */
"R_byte2_data", /* name. */
FALSE, /* partial_inplace. */
0xFFFF, /* src_mask. */
0, /* src_mask. */
0xFFFF, /* dst_mask. */
TRUE), /* pcrel_offset. */
@ -1001,7 +997,7 @@ static reloc_howto_type bfin_howto_table [] =
bfin_byte4_reloc, /* special_function. */
"R_byte4_data", /* name. */
FALSE, /* partial_inplace. */
0xFFFFFFFF, /* src_mask. */
0, /* src_mask. */
0xFFFFFFFF, /* dst_mask. */
TRUE), /* pcrel_offset. */
@ -1015,7 +1011,7 @@ static reloc_howto_type bfin_howto_table [] =
bfin_bfd_reloc, /* special_function. */
"R_pcrel11", /* name. */
FALSE, /* partial_inplace. */
0x000003FF, /* src_mask. */
0, /* src_mask. */
0x000003FF, /* dst_mask. */
FALSE), /* pcrel_offset. */
};
@ -1660,6 +1656,7 @@ elf32_bfin_reloc_type_class (const Elf_Internal_Rela * rela)
return reloc_class_normal;
}
}
static bfd_boolean
bfin_relocate_section (bfd * output_bfd,
struct bfd_link_info *info,
@ -1678,7 +1675,6 @@ bfin_relocate_section (bfd * output_bfd,
asection *sreloc;
Elf_Internal_Rela *rel;
Elf_Internal_Rela *relend;
char *error_msg = NULL;
int i = 0;
if (info->relocatable)
@ -1705,6 +1701,7 @@ bfin_relocate_section (bfd * output_bfd,
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)
@ -1735,10 +1732,6 @@ bfin_relocate_section (bfd * output_bfd,
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
{
@ -1762,6 +1755,45 @@ bfin_relocate_section (bfd * output_bfd,
}
}
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:
@ -1773,7 +1805,7 @@ bfin_relocate_section (bfd * output_bfd,
in the global offset table. */
if (h != NULL
&& strcmp (h->root.root.string, "_GLOBAL_OFFSET_TABLE_") == 0)
break;
goto do_default;
/* Fall through. */
/* Relocation is the offset of the entry for this symbol in
the global offset table. */
@ -1793,13 +1825,14 @@ bfin_relocate_section (bfd * output_bfd,
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))
|| h->forced_local)
&& h->def_regular))
{
/* This is actually a static link, or it is a
-Bsymbolic link and the symbol is defined
@ -1827,10 +1860,9 @@ bfin_relocate_section (bfd * output_bfd,
}
else
{
BFD_ASSERT (local_got_offsets != NULL
&& local_got_offsets[r_symndx] != (bfd_vma) - 1);
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
@ -1839,7 +1871,6 @@ bfin_relocate_section (bfd * output_bfd,
off &= ~1;
else
{
bfd_put_32 (output_bfd, relocation, sgot->contents + off);
if (info->shared)
@ -1871,71 +1902,52 @@ bfin_relocate_section (bfd * output_bfd,
/* 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:
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;
do_default:
r = _bfd_final_link_relocate (howto, input_bfd, input_section,
contents, address,
relocation, rel->r_addend);
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;
}
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. */
@ -1949,10 +1961,6 @@ bfin_relocate_section (bfd * output_bfd,
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;