* elf32-score.c (score_elf_got_lo16_reloc): Change some variables type from
unsigned to signed. (score_elf_final_link_relocate): Fix bugs of handling relocation type R_SCORE_GOT15, R_SCORE_GOT_LO16, and R_SCORE_REL32. (_bfd_score_elf_relocate_section): Handle R_SCORE_GOT_LO16 specially.
This commit is contained in:
parent
53881e24b5
commit
0150d082be
2 changed files with 58 additions and 18 deletions
|
@ -1,3 +1,11 @@
|
||||||
|
2006-12-25 Mei Ligang <ligang@sunnorth.com.cn>
|
||||||
|
|
||||||
|
* elf32-score.c (score_elf_got_lo16_reloc): Change some variables type from
|
||||||
|
unsigned to signed.
|
||||||
|
(score_elf_final_link_relocate): Fix bugs of handling relocation type R_SCORE_GOT15,
|
||||||
|
R_SCORE_GOT_LO16, and R_SCORE_REL32.
|
||||||
|
(_bfd_score_elf_relocate_section): Handle R_SCORE_GOT_LO16 specially.
|
||||||
|
|
||||||
2006-12-23 Jakub Jelinek <jakub@redhat.com>
|
2006-12-23 Jakub Jelinek <jakub@redhat.com>
|
||||||
|
|
||||||
* elf-bfd.h (struct elf_backend_data): Add as_needed_cleanup hook.
|
* elf-bfd.h (struct elf_backend_data): Add as_needed_cleanup hook.
|
||||||
|
|
|
@ -532,8 +532,8 @@ score_elf_got_lo16_reloc (bfd *abfd,
|
||||||
char **error_message ATTRIBUTE_UNUSED)
|
char **error_message ATTRIBUTE_UNUSED)
|
||||||
{
|
{
|
||||||
bfd_vma addend = 0, offset = 0;
|
bfd_vma addend = 0, offset = 0;
|
||||||
unsigned long val;
|
signed long val;
|
||||||
unsigned long hi16_offset, hi16_value, uvalue;
|
signed long hi16_offset, hi16_value, uvalue;
|
||||||
|
|
||||||
hi16_value = bfd_get_32 (abfd, hi16_rel_addr);
|
hi16_value = bfd_get_32 (abfd, hi16_rel_addr);
|
||||||
hi16_offset = ((((hi16_value >> 16) & 0x3) << 15) | (hi16_value & 0x7fff)) >> 1;
|
hi16_offset = ((((hi16_value >> 16) & 0x3) << 15) | (hi16_value & 0x7fff)) >> 1;
|
||||||
|
@ -543,7 +543,10 @@ score_elf_got_lo16_reloc (bfd *abfd,
|
||||||
if (reloc_entry->address > input_section->size)
|
if (reloc_entry->address > input_section->size)
|
||||||
return bfd_reloc_outofrange;
|
return bfd_reloc_outofrange;
|
||||||
uvalue = ((hi16_offset << 16) | (offset & 0xffff)) + val;
|
uvalue = ((hi16_offset << 16) | (offset & 0xffff)) + val;
|
||||||
hi16_offset = (uvalue >> 16) & 0x7fff;
|
if ((uvalue > -0x8000) && (uvalue < 0x7fff))
|
||||||
|
hi16_offset = 0;
|
||||||
|
else
|
||||||
|
hi16_offset = (uvalue >> 16) & 0x7fff;
|
||||||
hi16_value = (hi16_value & ~0x37fff) | (hi16_offset & 0x7fff) | ((hi16_offset << 1) & 0x30000);
|
hi16_value = (hi16_value & ~0x37fff) | (hi16_offset & 0x7fff) | ((hi16_offset << 1) & 0x30000);
|
||||||
bfd_put_32 (abfd, hi16_value, hi16_rel_addr);
|
bfd_put_32 (abfd, hi16_value, hi16_rel_addr);
|
||||||
offset = (uvalue & 0xffff) << 1;
|
offset = (uvalue & 0xffff) << 1;
|
||||||
|
@ -1897,6 +1900,7 @@ score_elf_final_link_relocate (reloc_howto_type *howto,
|
||||||
r_symndx = ELF32_R_SYM (rel->r_info);
|
r_symndx = ELF32_R_SYM (rel->r_info);
|
||||||
r_type = ELF32_R_TYPE (rel->r_info);
|
r_type = ELF32_R_TYPE (rel->r_info);
|
||||||
rel_addr = (input_section->output_section->vma + input_section->output_offset + rel->r_offset);
|
rel_addr = (input_section->output_section->vma + input_section->output_offset + rel->r_offset);
|
||||||
|
local_p = score_elf_local_relocation_p (input_bfd, rel, local_sections, TRUE);
|
||||||
|
|
||||||
if (r_type == R_SCORE_GOT15)
|
if (r_type == R_SCORE_GOT15)
|
||||||
{
|
{
|
||||||
|
@ -1905,25 +1909,22 @@ score_elf_final_link_relocate (reloc_howto_type *howto,
|
||||||
const struct elf_backend_data *bed;
|
const struct elf_backend_data *bed;
|
||||||
bfd_vma lo_value = 0;
|
bfd_vma lo_value = 0;
|
||||||
|
|
||||||
addend = (bfd_get_32 (input_bfd, hit_data) >> howto->bitpos) & howto->src_mask;
|
|
||||||
|
|
||||||
bed = get_elf_backend_data (output_bfd);
|
bed = get_elf_backend_data (output_bfd);
|
||||||
relend = relocs + input_section->reloc_count * bed->s->int_rels_per_ext_rel;
|
relend = relocs + input_section->reloc_count * bed->s->int_rels_per_ext_rel;
|
||||||
lo16_rel = score_elf_next_relocation (input_bfd, R_SCORE_GOT_LO16, rel, relend);
|
lo16_rel = score_elf_next_relocation (input_bfd, R_SCORE_GOT_LO16, rel, relend);
|
||||||
if (lo16_rel != NULL)
|
if ((local_p) && (lo16_rel != NULL))
|
||||||
{
|
{
|
||||||
lo_value = (bfd_get_32 (input_bfd, contents + lo16_rel->r_offset) >> howto->bitpos)
|
bfd_vma tmp = 0;
|
||||||
& howto->src_mask;
|
tmp = bfd_get_32 (input_bfd, contents + lo16_rel->r_offset);
|
||||||
|
lo_value = (((tmp >> 16) & 0x3) << 14) | ((tmp & 0x7fff) >> 1);
|
||||||
}
|
}
|
||||||
addend = (addend << 16) + lo_value;
|
addend = lo_value;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
addend = (bfd_get_32 (input_bfd, hit_data) >> howto->bitpos) & howto->src_mask;
|
addend = (bfd_get_32 (input_bfd, hit_data) >> howto->bitpos) & howto->src_mask;
|
||||||
}
|
}
|
||||||
|
|
||||||
local_p = score_elf_local_relocation_p (input_bfd, rel, local_sections, TRUE);
|
|
||||||
|
|
||||||
/* If we haven't already determined the GOT offset, or the GP value,
|
/* If we haven't already determined the GOT offset, or the GP value,
|
||||||
and we're going to need it, get it now. */
|
and we're going to need it, get it now. */
|
||||||
switch (r_type)
|
switch (r_type)
|
||||||
|
@ -1932,9 +1933,21 @@ score_elf_final_link_relocate (reloc_howto_type *howto,
|
||||||
case R_SCORE_GOT15:
|
case R_SCORE_GOT15:
|
||||||
if (!local_p)
|
if (!local_p)
|
||||||
{
|
{
|
||||||
g = score_elf_global_got_index (elf_hash_table (info)->dynobj,
|
g = score_elf_global_got_index (elf_hash_table (info)->dynobj,
|
||||||
(struct elf_link_hash_entry *) h);
|
(struct elf_link_hash_entry *) h);
|
||||||
}
|
if ((! elf_hash_table(info)->dynamic_sections_created
|
||||||
|
|| (info->shared
|
||||||
|
&& (info->symbolic || h->root.dynindx == -1)
|
||||||
|
&& h->root.def_regular)))
|
||||||
|
{
|
||||||
|
/* This is a static link or a -Bsymbolic link. The
|
||||||
|
symbol is defined locally, or was forced to be local.
|
||||||
|
We must initialize this entry in the GOT. */
|
||||||
|
bfd *tmpbfd = elf_hash_table (info)->dynobj;
|
||||||
|
asection *sgot = score_elf_got_section (tmpbfd, FALSE);
|
||||||
|
bfd_put_32 (tmpbfd, value, sgot->contents + g);
|
||||||
|
}
|
||||||
|
}
|
||||||
else if (r_type == R_SCORE_GOT15 || r_type == R_SCORE_CALL15)
|
else if (r_type == R_SCORE_GOT15 || r_type == R_SCORE_CALL15)
|
||||||
{
|
{
|
||||||
/* There's no need to create a local GOT entry here; the
|
/* There's no need to create a local GOT entry here; the
|
||||||
|
@ -1993,6 +2006,11 @@ score_elf_final_link_relocate (reloc_howto_type *howto,
|
||||||
input_section))
|
input_section))
|
||||||
return bfd_reloc_undefined;
|
return bfd_reloc_undefined;
|
||||||
}
|
}
|
||||||
|
else if (r_symndx == 0)
|
||||||
|
/* r_symndx will be zero only for relocs against symbols
|
||||||
|
from removed linkonce sections, or sections discarded by
|
||||||
|
a linker script. */
|
||||||
|
value = 0;
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (r_type != R_SCORE_REL32)
|
if (r_type != R_SCORE_REL32)
|
||||||
|
@ -2122,7 +2140,10 @@ score_elf_final_link_relocate (reloc_howto_type *howto,
|
||||||
|
|
||||||
if ((long) value > 0x3fff || (long) value < -0x4000)
|
if ((long) value > 0x3fff || (long) value < -0x4000)
|
||||||
return bfd_reloc_overflow;
|
return bfd_reloc_overflow;
|
||||||
bfd_put_16 (input_bfd, value, hit_data + 2);
|
|
||||||
|
addend = bfd_get_32 (input_bfd, hit_data);
|
||||||
|
value = (addend & ~howto->dst_mask) | (value & howto->dst_mask);
|
||||||
|
bfd_put_32 (input_bfd, value, hit_data);
|
||||||
return bfd_reloc_ok;
|
return bfd_reloc_ok;
|
||||||
|
|
||||||
case R_SCORE_GPREL32:
|
case R_SCORE_GPREL32:
|
||||||
|
@ -2133,10 +2154,10 @@ score_elf_final_link_relocate (reloc_howto_type *howto,
|
||||||
|
|
||||||
case R_SCORE_GOT_LO16:
|
case R_SCORE_GOT_LO16:
|
||||||
addend = bfd_get_32 (input_bfd, hit_data);
|
addend = bfd_get_32 (input_bfd, hit_data);
|
||||||
value = ((((addend >> 16) & 0x3) << 15) | (addend & 0x7fff)) >> 1;
|
value = (((addend >> 16) & 0x3) << 14) | ((addend & 0x7fff) >> 1);
|
||||||
value += symbol;
|
value += symbol;
|
||||||
offset = (value & 0xffff) << 1;
|
value = (addend & (~(howto->dst_mask))) | ((value & 0x3fff) << 1)
|
||||||
value = (addend & (~(howto->dst_mask))) | (offset & 0x7fff) | ((offset << 1) & 0x30000);
|
| (((value >> 14) & 0x3) << 16);
|
||||||
|
|
||||||
bfd_put_32 (input_bfd, value, hit_data);
|
bfd_put_32 (input_bfd, value, hit_data);
|
||||||
return bfd_reloc_ok;
|
return bfd_reloc_ok;
|
||||||
|
@ -2303,6 +2324,17 @@ _bfd_score_elf_relocate_section (bfd *output_bfd,
|
||||||
| (offset & 0x7fff) | ((offset << 1) & 0x30000);
|
| (offset & 0x7fff) | ((offset << 1) & 0x30000);
|
||||||
bfd_put_32 (input_bfd, value, contents + rel->r_offset);
|
bfd_put_32 (input_bfd, value, contents + rel->r_offset);
|
||||||
break;
|
break;
|
||||||
|
case R_SCORE_GOT_LO16:
|
||||||
|
value = bfd_get_32 (input_bfd, contents + rel->r_offset);
|
||||||
|
addend = (((value >> 16) & 0x3) << 14) | ((value & 0x7fff) >> 1);
|
||||||
|
msec = sec;
|
||||||
|
addend = _bfd_elf_rel_local_sym (output_bfd, sym, &msec, addend) - relocation;
|
||||||
|
addend += msec->output_section->vma + msec->output_offset;
|
||||||
|
value = (value & (~(howto->dst_mask))) | ((addend & 0x3fff) << 1)
|
||||||
|
| (((addend >> 14) & 0x3) << 16);
|
||||||
|
|
||||||
|
bfd_put_32 (input_bfd, value, contents + rel->r_offset);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
value = bfd_get_32 (input_bfd, contents + rel->r_offset);
|
value = bfd_get_32 (input_bfd, contents + rel->r_offset);
|
||||||
/* Get the (signed) value from the instruction. */
|
/* Get the (signed) value from the instruction. */
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue