|| !h->def_regular)))
{
struct ppc_elf_dyn_relocs *p;
- struct ppc_elf_dyn_relocs **head;
+ struct ppc_elf_dyn_relocs **rel_head;
#ifdef DEBUG
fprintf (stderr,
relocations we need for this symbol. */
if (h != NULL)
{
- head = &ppc_elf_hash_entry (h)->dyn_relocs;
+ rel_head = &ppc_elf_hash_entry (h)->dyn_relocs;
}
else
{
s = sec;
vpp = &elf_section_data (s)->local_dynrel;
- head = (struct ppc_elf_dyn_relocs **) vpp;
+ rel_head = (struct ppc_elf_dyn_relocs **) vpp;
}
- p = *head;
+ p = *rel_head;
if (p == NULL || p->sec != sec)
{
p = bfd_alloc (htab->elf.dynobj, sizeof *p);
if (p == NULL)
return FALSE;
- p->next = *head;
- *head = p;
+ p->next = *rel_head;
+ *rel_head = p;
p->sec = sec;
p->count = 0;
p->pc_count = 0;
local_plt = (struct plt_entry **) end_local_got;
end_local_plt = local_plt + locsymcount;
lgot_masks = (char *) end_local_plt;
+
for (; local_got < end_local_got; ++local_got, ++lgot_masks)
if (*local_got > 0)
{
for (ent = *local_plt; ent != NULL; ent = ent->next)
if (ent->plt.refcount > 0)
{
- asection *s = htab->iplt;
+ s = htab->iplt;
if (!doneone)
{
for (irel = internal_relocs; irel < irelend; irel++)
{
unsigned long r_type = ELF32_R_TYPE (irel->r_info);
- bfd_vma reladdr, toff, roff;
+ bfd_vma toff, roff;
asection *tsec;
struct one_fixup *f;
size_t insn_offset = 0;
continue;
roff = irel->r_offset;
- reladdr = isec->output_section->vma + isec->output_offset + roff;
/* If the branch is in range, no need to do anything. */
if (tsec != bfd_und_section_ptr
&& h->root.u.def.section->output_section != NULL);
}
+/* If INSN is an opcode that may be used with an @tls operand, return
+ the transformed insn for TLS optimisation, otherwise return 0. If
+ REG is non-zero only match an insn with RB or RA equal to REG. */
+
+unsigned int
+_bfd_elf_ppc_at_tls_transform (unsigned int insn, unsigned int reg)
+{
+ unsigned int rtra;
+
+ if ((insn & (0x3f << 26)) != 31 << 26)
+ return 0;
+
+ if (reg == 0 || ((insn >> 11) & 0x1f) == reg)
+ rtra = insn & ((1 << 26) - (1 << 16));
+ else if (((insn >> 16) & 0x1f) == reg)
+ rtra = (insn & (0x1f << 21)) | ((insn & (0x1f << 11)) << 5);
+ else
+ return 0;
+
+ if ((insn & (0x3ff << 1)) == 266 << 1)
+ /* add -> addi. */
+ insn = 14 << 26;
+ else if ((insn & (0x1f << 1)) == 23 << 1
+ && ((insn & (0x1f << 6)) < 14 << 6
+ || ((insn & (0x1f << 6)) >= 16 << 6
+ && (insn & (0x1f << 6)) < 24 << 6)))
+ /* load and store indexed -> dform. */
+ insn = (32 | ((insn >> 6) & 0x1f)) << 26;
+ else if ((insn & (((0x1a << 5) | 0x1f) << 1)) == 21 << 1)
+ /* ldx, ldux, stdx, stdux -> ld, ldu, std, stdu. */
+ insn = ((58 | ((insn >> 6) & 4)) << 26) | ((insn >> 6) & 1);
+ else if ((insn & (((0x1f << 5) | 0x1f) << 1)) == 341 << 1)
+ /* lwax -> lwa. */
+ insn = (58 << 26) | 2;
+ else
+ return 0;
+ insn |= rtra;
+ return insn;
+}
+
/* The RELOCATE_SECTION function is called by the ELF backend linker
to handle the relocations for a section.
Elf_Internal_Rela *rel;
Elf_Internal_Rela *relend;
Elf_Internal_Rela outrel;
- bfd_byte *loc;
asection *got2, *sreloc = NULL;
bfd_vma *local_got_offsets;
bfd_boolean ret = TRUE;
reloc_howto_type *howto;
unsigned long r_symndx;
bfd_vma relocation;
- bfd_vma branch_bit, insn, from;
+ bfd_vma branch_bit, from;
bfd_boolean unresolved_reloc;
bfd_boolean warned;
unsigned int tls_type, tls_mask, tls_gd;
&& (tls_mask & TLS_TPREL) == 0)
{
bfd_vma insn;
+
insn = bfd_get_32 (output_bfd, contents + rel->r_offset - d_offset);
insn &= 31 << 21;
insn |= 0x3c020000; /* addis 0,2,0 */
if ((tls_mask & TLS_TLS) != 0
&& (tls_mask & TLS_TPREL) == 0)
{
- bfd_vma insn, rtra;
+ bfd_vma insn;
+
insn = bfd_get_32 (output_bfd, contents + rel->r_offset);
- if ((insn & ((31 << 26) | (31 << 11)))
- == ((31 << 26) | (2 << 11)))
- rtra = insn & ((1 << 26) - (1 << 16));
- else if ((insn & ((31 << 26) | (31 << 16)))
- == ((31 << 26) | (2 << 16)))
- rtra = (insn & (31 << 21)) | ((insn & (31 << 11)) << 5);
- else
+ insn = _bfd_elf_ppc_at_tls_transform (insn, 2);
+ if (insn == 0)
abort ();
- if ((insn & ((1 << 11) - (1 << 1))) == 266 << 1)
- /* add -> addi. */
- insn = 14 << 26;
- else if ((insn & (31 << 1)) == 23 << 1
- && ((insn & (31 << 6)) < 14 << 6
- || ((insn & (31 << 6)) >= 16 << 6
- && (insn & (31 << 6)) < 24 << 6)))
- /* load and store indexed -> dform. */
- insn = (32 | ((insn >> 6) & 31)) << 26;
- else if ((insn & (31 << 1)) == 21 << 1
- && (insn & (0x1a << 6)) == 0)
- /* ldx, ldux, stdx, stdux -> ld, ldu, std, stdu. */
- insn = (((58 | ((insn >> 6) & 4)) << 26)
- | ((insn >> 6) & 1));
- else if ((insn & (31 << 1)) == 21 << 1
- && (insn & ((1 << 11) - (1 << 1))) == 341 << 1)
- /* lwax -> lwa. */
- insn = (58 << 26) | 2;
- else
- abort ();
- insn |= rtra;
bfd_put_32 (output_bfd, insn, contents + rel->r_offset);
r_type = R_PPC_TPREL16_LO;
rel->r_info = ELF32_R_INFO (r_symndx, r_type);
/* Branch not taken prediction relocations. */
case R_PPC_ADDR14_BRNTAKEN:
case R_PPC_REL14_BRNTAKEN:
- insn = bfd_get_32 (output_bfd, contents + rel->r_offset);
- insn &= ~BRANCH_PREDICT_BIT;
- insn |= branch_bit;
+ {
+ bfd_vma insn;
- from = (rel->r_offset
- + input_section->output_offset
- + input_section->output_section->vma);
+ insn = bfd_get_32 (output_bfd, contents + rel->r_offset);
+ insn &= ~BRANCH_PREDICT_BIT;
+ insn |= branch_bit;
- /* Invert 'y' bit if not the default. */
- if ((bfd_signed_vma) (relocation + rel->r_addend - from) < 0)
- insn ^= BRANCH_PREDICT_BIT;
+ from = (rel->r_offset
+ + input_section->output_offset
+ + input_section->output_section->vma);
- bfd_put_32 (output_bfd, insn, contents + rel->r_offset);
- break;
+ /* Invert 'y' bit if not the default. */
+ if ((bfd_signed_vma) (relocation + rel->r_addend - from) < 0)
+ insn ^= BRANCH_PREDICT_BIT;
+
+ bfd_put_32 (output_bfd, insn, contents + rel->r_offset);
+ break;
+ }
}
ifunc = NULL;
|| h->root.type != bfd_link_hash_undefweak))
{
asection *rsec = htab->relgot;
+ bfd_byte * loc;
outrel.r_offset = (htab->got->output_section->vma
+ htab->got->output_offset
&& !h->def_regular))
{
int skip;
-
+ bfd_byte * loc;
#ifdef DEBUG
fprintf (stderr, "ppc_elf_relocate_section needs to "
"create relocation for %s\n",
}
if (r_type == R_PPC_EMB_SDA21)
- { /* fill in register field */
+ {
+ bfd_vma insn; /* Fill in register field. */
+
insn = bfd_get_32 (output_bfd, contents + rel->r_offset);
insn = (insn & ~RA_REGISTER_MASK) | (reg << RA_REGISTER_SHIFT);
bfd_put_32 (output_bfd, insn, contents + rel->r_offset);
/* PowerPC64-specific support for 64-bit ELF.
Copyright 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008,
- 2009 Free Software Foundation, Inc.
+ 2009, 2010 Free Software Foundation, Inc.
Written by Linus Nordberg, Swox AB <info@swox.com>,
based on elf32-ppc.c by Ian Lance Taylor.
Largely rewritten by Alan Modra.
/* No relocs implies we are linking a --just-symbols object. */
if (opd_sec->reloc_count == 0)
{
- bfd_vma val;
-
if (!bfd_get_section_contents (opd_bfd, opd_sec, &val, offset, 8))
return (bfd_vma) -1;
for (ent = *local_plt; ent != NULL; ent = ent->next)
if (ent->plt.refcount > 0)
{
- asection *s = htab->iplt;
-
+ s = htab->iplt;
ent->plt.offset = s->size;
s->size += PLT_ENTRY_SIZE;
if (tls_mask != 0
&& (tls_mask & TLS_TPREL) == 0)
{
- bfd_vma rtra;
insn = bfd_get_32 (output_bfd, contents + rel->r_offset);
- if ((insn & ((0x3f << 26) | (31 << 11)))
- == ((31 << 26) | (13 << 11)))
- rtra = insn & ((1 << 26) - (1 << 16));
- else if ((insn & ((0x3f << 26) | (31 << 16)))
- == ((31 << 26) | (13 << 16)))
- rtra = (insn & (31 << 21)) | ((insn & (31 << 11)) << 5);
- else
+ insn = _bfd_elf_ppc_at_tls_transform (insn, 13);
+ if (insn == 0)
abort ();
- if ((insn & ((1 << 11) - (1 << 1))) == 266 << 1)
- /* add -> addi. */
- insn = 14 << 26;
- else if ((insn & (31 << 1)) == 23 << 1
- && ((insn & (31 << 6)) < 14 << 6
- || ((insn & (31 << 6)) >= 16 << 6
- && (insn & (31 << 6)) < 24 << 6)))
- /* load and store indexed -> dform. */
- insn = (32 | ((insn >> 6) & 31)) << 26;
- else if ((insn & (31 << 1)) == 21 << 1
- && (insn & (0x1a << 6)) == 0)
- /* ldx, ldux, stdx, stdux -> ld, ldu, std, stdu. */
- insn = (((58 | ((insn >> 6) & 4)) << 26)
- | ((insn >> 6) & 1));
- else if ((insn & (31 << 1)) == 21 << 1
- && (insn & ((1 << 11) - (1 << 1))) == 341 << 1)
- /* lwax -> lwa. */
- insn = (58 << 26) | 2;
- else
- abort ();
- insn |= rtra;
bfd_put_32 (output_bfd, insn, contents + rel->r_offset);
/* Was PPC64_TLS which sits on insn boundary, now
PPC64_TPREL16_LO which is at low-order half-word. */
? h->elf.type == STT_GNU_IFUNC
: ELF_ST_TYPE (sym->st_info) == STT_GNU_IFUNC)))
{
- Elf_Internal_Rela outrel;
bfd_boolean skip, relocate;
asection *sreloc;
- bfd_byte *loc;
bfd_vma out_off;
/* When generating a dynamic object, these relocations
if (h->needs_copy)
{
- Elf_Internal_Rela rela;
- bfd_byte *loc;
-
/* This symbol needs a copy reloc. Set it up. */
if (h->dynindx == -1