diff options
author | David S. Miller <davem@redhat.com> | 2010-02-11 19:57:40 +0000 |
---|---|---|
committer | David S. Miller <davem@redhat.com> | 2010-02-11 19:57:40 +0000 |
commit | 00c5099111744132fa72c773faf4df4a6dad1fb9 (patch) | |
tree | bfb6f183da74d795cce5f259eb00d559e40ea3fa /bfd/elfxx-sparc.c | |
parent | 6fa78d941bfeeaabea9a746a6588831b63daf0ec (diff) | |
download | gdb-00c5099111744132fa72c773faf4df4a6dad1fb9.zip gdb-00c5099111744132fa72c773faf4df4a6dad1fb9.tar.gz gdb-00c5099111744132fa72c773faf4df4a6dad1fb9.tar.bz2 |
bfd/
* elfxx-sparc.c (_bfd_sparc_elf_check_relocs): For R_SPARC_GOTDATA_OP_HIX22
and R_SPARC_GOTDATA_OP_LOX10, only bump the GOT refcount for global
symbols.
(_bfd_sparc_elf_gc_sweep_hook): Likewise only decrement the GOT count for
these relocs on global symbols.
(gdopoff): New.
(_bfd_sparc_elf_relocate_section): Perform GOTDATA optimizations on
local symbol references which are not STT_GNU_IFUNC. Handle
relocation of them like R_SPARC_HIX22 and R_SPARC_LOX10 respectively,
and deal with negative vs. non-negative values properly.
ld/testsuite
* ld-sparc/gotop32.s: Add local symbol case.
* ld-sparc/gotop64.s: Likewise.
* ld-sparc/gotop32.rd: Adjust expected results.
* ld-sparc/gotop32.td: Likewise.
* ld-sparc/gotop64.dd: Likewise.
* ld-sparc/gotop64.rd: Likewise.
* ld-sparc/gotop64.td: Likewise.
Diffstat (limited to 'bfd/elfxx-sparc.c')
-rw-r--r-- | bfd/elfxx-sparc.c | 111 |
1 files changed, 85 insertions, 26 deletions
diff --git a/bfd/elfxx-sparc.c b/bfd/elfxx-sparc.c index bc36920..1947d1a 100644 --- a/bfd/elfxx-sparc.c +++ b/bfd/elfxx-sparc.c @@ -1345,8 +1345,6 @@ _bfd_sparc_elf_check_relocs (bfd *abfd, struct bfd_link_info *info, case R_SPARC_GOT10: case R_SPARC_GOT13: case R_SPARC_GOT22: - case R_SPARC_GOTDATA_HIX22: - case R_SPARC_GOTDATA_LOX10: case R_SPARC_GOTDATA_OP_HIX22: case R_SPARC_GOTDATA_OP_LOX10: tls_type = GOT_NORMAL; @@ -1386,7 +1384,16 @@ _bfd_sparc_elf_check_relocs (bfd *abfd, struct bfd_link_info *info, _bfd_sparc_elf_local_got_tls_type (abfd) = (char *) (local_got_refcounts + symtab_hdr->sh_info); } - local_got_refcounts[r_symndx] += 1; + switch (r_type) + { + case R_SPARC_GOTDATA_OP_HIX22: + case R_SPARC_GOTDATA_OP_LOX10: + break; + + default: + local_got_refcounts[r_symndx] += 1; + break; + } old_tls_type = _bfd_sparc_elf_local_got_tls_type (abfd) [r_symndx]; } @@ -1766,8 +1773,17 @@ _bfd_sparc_elf_gc_sweep_hook (bfd *abfd, struct bfd_link_info *info, } else { - if (local_got_refcounts[r_symndx] > 0) - local_got_refcounts[r_symndx]--; + switch (r_type) + { + case R_SPARC_GOTDATA_OP_HIX22: + case R_SPARC_GOTDATA_OP_LOX10: + break; + + default: + if (local_got_refcounts[r_symndx] > 0) + local_got_refcounts[r_symndx]--; + break; + } } break; @@ -2672,6 +2688,21 @@ tpoff (struct bfd_link_info *info, bfd_vma address) return address - htab->tls_size - htab->tls_sec->vma; } +/* Return the relocation value for a %gdop relocation. */ + +static bfd_vma +gdopoff (struct bfd_link_info *info, bfd_vma address) +{ + struct elf_link_hash_table *htab = elf_hash_table (info); + bfd_vma got_base; + + got_base = (htab->hgot->root.u.def.value + + htab->hgot->root.u.def.section->output_offset + + htab->hgot->root.u.def.section->output_section->vma); + + return address - got_base; +} + /* Relocate a SPARC ELF section. */ bfd_boolean @@ -2821,10 +2852,17 @@ _bfd_sparc_elf_relocate_section (bfd *output_bfd, switch (r_type) { - case R_SPARC_GOTDATA_HIX22: - case R_SPARC_GOTDATA_LOX10: + case R_SPARC_GOTDATA_OP: + continue; + case R_SPARC_GOTDATA_OP_HIX22: case R_SPARC_GOTDATA_OP_LOX10: + r_type = (r_type == R_SPARC_GOTDATA_OP_HIX22 + ? R_SPARC_GOT22 + : R_SPARC_GOT10); + howto = _bfd_sparc_elf_howto_table + r_type; + /* Fall through. */ + case R_SPARC_GOT10: case R_SPARC_GOT13: case R_SPARC_GOT22: @@ -2911,19 +2949,37 @@ _bfd_sparc_elf_relocate_section (bfd *output_bfd, switch (r_type) { - case R_SPARC_GOTDATA_HIX22: - case R_SPARC_GOTDATA_LOX10: case R_SPARC_GOTDATA_OP_HIX22: case R_SPARC_GOTDATA_OP_LOX10: - /* We don't support these code transformation optimizations - yet, so just leave the sequence alone and treat as - GOT22/GOT10. */ - if (r_type == R_SPARC_GOTDATA_HIX22 - || r_type == R_SPARC_GOTDATA_OP_HIX22) - r_type = R_SPARC_GOT22; + if (SYMBOL_REFERENCES_LOCAL (info, h)) + r_type = (r_type == R_SPARC_GOTDATA_OP_HIX22 + ? R_SPARC_GOTDATA_HIX22 + : R_SPARC_GOTDATA_LOX10); else - r_type = R_SPARC_GOT10; - /* Fall through. */ + r_type = (r_type == R_SPARC_GOTDATA_OP_HIX22 + ? R_SPARC_GOT22 + : R_SPARC_GOT10); + howto = _bfd_sparc_elf_howto_table + r_type; + break; + + case R_SPARC_GOTDATA_OP: + if (SYMBOL_REFERENCES_LOCAL (info, h)) + { + bfd_vma insn = bfd_get_32 (input_bfd, contents + rel->r_offset); + + /* {ld,ldx} [%rs1 + %rs2], %rd --> add %rs1, %rs2, %rd */ + relocation = 0x80000000 | (insn & 0x3e07c01f); + bfd_put_32 (output_bfd, relocation, contents + rel->r_offset); + } + continue; + } + + switch (r_type) + { + case R_SPARC_GOTDATA_HIX22: + case R_SPARC_GOTDATA_LOX10: + relocation = gdopoff (info, relocation); + break; case R_SPARC_GOT10: case R_SPARC_GOT13: @@ -3576,11 +3632,6 @@ _bfd_sparc_elf_relocate_section (bfd *output_bfd, } continue; - case R_SPARC_GOTDATA_OP: - /* We don't support gotdata code transformation optimizations - yet, so simply leave the sequence as-is. */ - continue; - case R_SPARC_TLS_IE_LD: case R_SPARC_TLS_IE_LDX: if (! info->shared && (h == NULL || h->dynindx == -1)) @@ -3704,12 +3755,15 @@ _bfd_sparc_elf_relocate_section (bfd *output_bfd, r = bfd_reloc_ok; } - else if (r_type == R_SPARC_HIX22) + else if (r_type == R_SPARC_HIX22 + || r_type == R_SPARC_GOTDATA_HIX22) { bfd_vma x; relocation += rel->r_addend; - relocation = relocation ^ MINUS_ONE; + if (r_type == R_SPARC_HIX22 + || (bfd_signed_vma) relocation < 0) + relocation = relocation ^ MINUS_ONE; x = bfd_get_32 (input_bfd, contents + rel->r_offset); x = (x & ~(bfd_vma) 0x3fffff) | ((relocation >> 10) & 0x3fffff); @@ -3720,12 +3774,17 @@ _bfd_sparc_elf_relocate_section (bfd *output_bfd, bfd_arch_bits_per_address (input_bfd), relocation); } - else if (r_type == R_SPARC_LOX10) + else if (r_type == R_SPARC_LOX10 + || r_type == R_SPARC_GOTDATA_LOX10) { bfd_vma x; relocation += rel->r_addend; - relocation = (relocation & 0x3ff) | 0x1c00; + if (r_type == R_SPARC_LOX10 + || (bfd_signed_vma) relocation < 0) + relocation = (relocation & 0x3ff) | 0x1c00; + else + relocation = (relocation & 0x3ff); x = bfd_get_32 (input_bfd, contents + rel->r_offset); x = (x & ~(bfd_vma) 0x1fff) | relocation; |