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;
_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];
}
}
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;
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
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:
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:
}
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))
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);
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;
+1010: 7f ff ff fc call 1000 <_.*>
+1014: ae 05 e0 d0 add %l7, 0xd0, %l7 ! 1010d0 <.*>
+1018: 01 00 00 00 nop *
- +101c: 23 00 00 08 sethi %hi\(0x2000\), %l1
+ +101c: 23 00 00 00 sethi %hi\(0\), %l1
+1020: 01 00 00 00 nop *
+1024: a2 1c 60 08 xor %l1, 8, %l1
+1028: 01 00 00 00 nop *
+102c: f0 5d c0 11 ldx \[ %l7 \+ %l1 \], %i0
+1030: 01 00 00 00 nop *
- +1034: 81 c7 e0 08 ret
- +1038: 81 e8 00 00 restore
+ +1034: 23 00 00 03 sethi %hi\(0xc00\), %l1
+ +1038: 01 00 00 00 nop *
+ +103c: a2 1c 63 24 xor %l1, 0x324, %l1
+ +1040: 01 00 00 00 nop *
+ +1044: b0 05 c0 11 add %l7, %l1, %i0
+ +1048: 01 00 00 00 nop *
+ +104c: 81 c7 e0 08 ret
+ +1050: 81 e8 00 00 restore
#pass