Index: binutils/bfd/elf32-ppc.c |
diff --git a/binutils/bfd/elf32-ppc.c b/binutils/bfd/elf32-ppc.c |
index 95058a233dbbc6acc7891b982c25810985eaf3b2..fc4347e444de3df72429372113a28168b8657e9f 100644 |
--- a/binutils/bfd/elf32-ppc.c |
+++ b/binutils/bfd/elf32-ppc.c |
@@ -1,6 +1,6 @@ |
/* PowerPC-specific support for 32-bit ELF |
Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, |
- 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation, Inc. |
+ 2004, 2005, 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc. |
Written by Ian Lance Taylor, Cygnus Support. |
This file is part of BFD, the Binary File Descriptor library. |
@@ -3323,6 +3323,8 @@ update_plt_info (bfd *abfd, struct plt_entry **plist, |
{ |
struct plt_entry *ent; |
+ if (addend < 32768) |
+ sec = NULL; |
for (ent = *plist; ent != NULL; ent = ent->next) |
if (ent->sec == sec && ent->addend == addend) |
break; |
@@ -3508,8 +3510,7 @@ ppc_elf_check_relocs (bfd *abfd, |
if (info->shared) |
addend = rel->r_addend; |
} |
- if (!update_plt_info (abfd, ifunc, |
- addend < 32768 ? NULL : got2, addend)) |
+ if (!update_plt_info (abfd, ifunc, got2, addend)) |
return FALSE; |
} |
} |
@@ -3748,8 +3749,7 @@ ppc_elf_check_relocs (bfd *abfd, |
addend = rel->r_addend; |
} |
h->needs_plt = 1; |
- if (!update_plt_info (abfd, &h->plt.plist, |
- addend < 32768 ? NULL : got2, addend)) |
+ if (!update_plt_info (abfd, &h->plt.plist, got2, addend)) |
return FALSE; |
} |
break; |
@@ -3780,10 +3780,9 @@ ppc_elf_check_relocs (bfd *abfd, |
case R_PPC_EMB_MRKREF: |
case R_PPC_NONE: |
case R_PPC_max: |
- case R_PPC_RELAX32: |
- case R_PPC_RELAX32PC: |
- case R_PPC_RELAX32_PLT: |
- case R_PPC_RELAX32PC_PLT: |
+ case R_PPC_RELAX: |
+ case R_PPC_RELAX_PLT: |
+ case R_PPC_RELAX_PLTREL24: |
break; |
/* These should only appear in dynamic objects. */ |
@@ -3961,7 +3960,7 @@ ppc_elf_check_relocs (bfd *abfd, |
|| !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, |
@@ -3986,7 +3985,7 @@ ppc_elf_check_relocs (bfd *abfd, |
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 |
{ |
@@ -4007,17 +4006,17 @@ ppc_elf_check_relocs (bfd *abfd, |
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; |
@@ -4486,7 +4485,7 @@ ppc_elf_gc_sweep_hook (bfd *abfd, |
struct plt_entry *ent; |
ent = find_plt_ent (&h->plt.plist, NULL, 0); |
- if (ent->plt.refcount > 0) |
+ if (ent != NULL && ent->plt.refcount > 0) |
ent->plt.refcount -= 1; |
} |
} |
@@ -4534,7 +4533,7 @@ ppc_elf_gc_sweep_hook (bfd *abfd, |
if (r_type == R_PPC_PLTREL24 && info->shared) |
addend = rel->r_addend; |
ent = find_plt_ent (&h->plt.plist, got2, addend); |
- if (ent->plt.refcount > 0) |
+ if (ent != NULL && ent->plt.refcount > 0) |
ent->plt.refcount -= 1; |
} |
break; |
@@ -4582,9 +4581,10 @@ ppc_elf_tls_setup (bfd *obfd, |
&& tga->root.type == bfd_link_hash_undefweak))) |
{ |
struct plt_entry *ent; |
- ent = find_plt_ent (&tga->plt.plist, NULL, 0); |
- if (ent != NULL |
- && ent->plt.refcount > 0) |
+ for (ent = tga->plt.plist; ent != NULL; ent = ent->next) |
+ if (ent->plt.refcount > 0) |
+ break; |
+ if (ent != NULL) |
{ |
tga->root.type = bfd_link_hash_indirect; |
tga->root.u.i.link = &opt->root; |
@@ -4669,6 +4669,7 @@ ppc_elf_tls_optimize (bfd *obfd ATTRIBUTE_UNUSED, |
{ |
Elf_Internal_Sym *locsyms = NULL; |
Elf_Internal_Shdr *symtab_hdr = &elf_symtab_hdr (ibfd); |
+ asection *got2 = bfd_get_section_by_name (ibfd, ".got2"); |
for (sec = ibfd->sections; sec != NULL; sec = sec->next) |
if (sec->has_tls_reloc && !bfd_is_abs_section (sec->output_section)) |
@@ -4762,6 +4763,13 @@ ppc_elf_tls_optimize (bfd *obfd ATTRIBUTE_UNUSED, |
else |
continue; |
+ case R_PPC_TLSGD: |
+ case R_PPC_TLSLD: |
+ expecting_tls_get_addr = 2; |
+ tls_set = 0; |
+ tls_clear = 0; |
+ break; |
+ |
default: |
continue; |
} |
@@ -4769,7 +4777,8 @@ ppc_elf_tls_optimize (bfd *obfd ATTRIBUTE_UNUSED, |
if (pass == 0) |
{ |
if (!expecting_tls_get_addr |
- || !sec->has_tls_get_addr_call) |
+ || (expecting_tls_get_addr == 1 |
+ && !sec->has_tls_get_addr_call)) |
continue; |
if (rel + 1 < relend |
@@ -4785,6 +4794,23 @@ ppc_elf_tls_optimize (bfd *obfd ATTRIBUTE_UNUSED, |
break; |
} |
+ if (expecting_tls_get_addr) |
+ { |
+ struct plt_entry *ent; |
+ bfd_vma addend = 0; |
+ |
+ if (info->shared |
+ && ELF32_R_TYPE (rel[1].r_info) == R_PPC_PLTREL24) |
+ addend = rel[1].r_addend; |
+ ent = find_plt_ent (&htab->tls_get_addr->plt.plist, |
+ got2, addend); |
+ if (ent != NULL && ent->plt.refcount > 0) |
+ ent->plt.refcount -= 1; |
+ |
+ if (expecting_tls_get_addr == 2) |
+ continue; |
+ } |
+ |
if (h != NULL) |
{ |
tls_mask = &ppc_elf_hash_entry (h)->tls_mask; |
@@ -4829,16 +4855,6 @@ ppc_elf_tls_optimize (bfd *obfd ATTRIBUTE_UNUSED, |
*got_count -= 1; |
} |
- if (expecting_tls_get_addr) |
- { |
- struct plt_entry *ent; |
- |
- ent = find_plt_ent (&htab->tls_get_addr->plt.plist, |
- NULL, 0); |
- if (ent != NULL && ent->plt.refcount > 0) |
- ent->plt.refcount -= 1; |
- } |
- |
*tls_mask |= tls_set; |
*tls_mask &= ~tls_clear; |
} |
@@ -5619,6 +5635,7 @@ ppc_elf_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED, |
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) |
{ |
@@ -5662,7 +5679,7 @@ ppc_elf_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED, |
for (ent = *local_plt; ent != NULL; ent = ent->next) |
if (ent->plt.refcount > 0) |
{ |
- asection *s = htab->iplt; |
+ s = htab->iplt; |
if (!doneone) |
{ |
@@ -6018,7 +6035,7 @@ ppc_elf_relax_section (bfd *abfd, |
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; |
@@ -6202,7 +6219,6 @@ ppc_elf_relax_section (bfd *abfd, |
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 |
@@ -6239,28 +6255,28 @@ ppc_elf_relax_section (bfd *abfd, |
{ |
size = 4 * ARRAY_SIZE (shared_stub_entry); |
insn_offset = 12; |
- stub_rtype = R_PPC_RELAX32PC; |
} |
else |
{ |
size = 4 * ARRAY_SIZE (stub_entry); |
insn_offset = 0; |
- stub_rtype = R_PPC_RELAX32; |
} |
- |
- if (R_PPC_RELAX32_PLT - R_PPC_RELAX32 |
- != R_PPC_RELAX32PC_PLT - R_PPC_RELAX32PC) |
- abort (); |
+ stub_rtype = R_PPC_RELAX; |
if (tsec == htab->plt |
|| tsec == htab->glink) |
- stub_rtype += R_PPC_RELAX32_PLT - R_PPC_RELAX32; |
+ { |
+ stub_rtype = R_PPC_RELAX_PLT; |
+ if (r_type == R_PPC_PLTREL24) |
+ stub_rtype = R_PPC_RELAX_PLTREL24; |
+ } |
/* Hijack the old relocation. Since we need two |
relocations for this use a "composite" reloc. */ |
irel->r_info = ELF32_R_INFO (ELF32_R_SYM (irel->r_info), |
stub_rtype); |
irel->r_offset = trampoff + insn_offset; |
- if (r_type == R_PPC_PLTREL24) |
+ if (r_type == R_PPC_PLTREL24 |
+ && stub_rtype != R_PPC_RELAX_PLTREL24) |
irel->r_addend = 0; |
/* Record the fixup so we don't do it again this section. */ |
@@ -6430,7 +6446,7 @@ ppc_elf_relax_section (bfd *abfd, |
{ |
/* Convert the internal relax relocs to external form. */ |
for (irel = internal_relocs; irel < irelend; irel++) |
- if (ELF32_R_TYPE (irel->r_info) == R_PPC_RELAX32) |
+ if (ELF32_R_TYPE (irel->r_info) == R_PPC_RELAX) |
{ |
unsigned long r_symndx = ELF32_R_SYM (irel->r_info); |
@@ -6613,6 +6629,91 @@ is_static_defined (struct elf_link_hash_entry *h) |
&& 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; |
+} |
+ |
+/* If INSN is an opcode that may be used with an @tprel operand, return |
+ the transformed insn for an undefined weak symbol, ie. with the |
+ thread pointer REG operand removed. Otherwise return 0. */ |
+ |
+unsigned int |
+_bfd_elf_ppc_at_tprel_transform (unsigned int insn, unsigned int reg) |
+{ |
+ if ((insn & (0x1f << 16)) == reg << 16 |
+ && ((insn & (0x3f << 26)) == 14u << 26 /* addi */ |
+ || (insn & (0x3f << 26)) == 15u << 26 /* addis */ |
+ || (insn & (0x3f << 26)) == 32u << 26 /* lwz */ |
+ || (insn & (0x3f << 26)) == 34u << 26 /* lbz */ |
+ || (insn & (0x3f << 26)) == 36u << 26 /* stw */ |
+ || (insn & (0x3f << 26)) == 38u << 26 /* stb */ |
+ || (insn & (0x3f << 26)) == 40u << 26 /* lhz */ |
+ || (insn & (0x3f << 26)) == 42u << 26 /* lha */ |
+ || (insn & (0x3f << 26)) == 44u << 26 /* sth */ |
+ || (insn & (0x3f << 26)) == 46u << 26 /* lmw */ |
+ || (insn & (0x3f << 26)) == 47u << 26 /* stmw */ |
+ || (insn & (0x3f << 26)) == 48u << 26 /* lfs */ |
+ || (insn & (0x3f << 26)) == 50u << 26 /* lfd */ |
+ || (insn & (0x3f << 26)) == 52u << 26 /* stfs */ |
+ || (insn & (0x3f << 26)) == 54u << 26 /* stfd */ |
+ || ((insn & (0x3f << 26)) == 58u << 26 /* lwa,ld,lmd */ |
+ && (insn & 3) != 1) |
+ || ((insn & (0x3f << 26)) == 62u << 26 /* std, stmd */ |
+ && ((insn & 3) == 0 || (insn & 3) == 3)))) |
+ { |
+ insn &= ~(0x1f << 16); |
+ } |
+ else if ((insn & (0x1f << 21)) == reg << 21 |
+ && ((insn & (0x3e << 26)) == 24u << 26 /* ori, oris */ |
+ || (insn & (0x3e << 26)) == 26u << 26 /* xori,xoris */ |
+ || (insn & (0x3e << 26)) == 28u << 26 /* andi,andis */)) |
+ { |
+ insn &= ~(0x1f << 21); |
+ insn |= (insn & (0x1f << 16)) << 5; |
+ if ((insn & (0x3e << 26)) == 26 << 26 /* xori,xoris */) |
+ insn -= 2 >> 26; /* convert to ori,oris */ |
+ } |
+ else |
+ insn = 0; |
+ return insn; |
+} |
+ |
/* The RELOCATE_SECTION function is called by the ELF backend linker |
to handle the relocations for a section. |
@@ -6658,7 +6759,6 @@ ppc_elf_relocate_section (bfd *output_bfd, |
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; |
@@ -6702,7 +6802,7 @@ ppc_elf_relocate_section (bfd *output_bfd, |
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; |
@@ -6800,6 +6900,7 @@ ppc_elf_relocate_section (bfd *output_bfd, |
&& (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 */ |
@@ -6813,37 +6914,12 @@ ppc_elf_relocate_section (bfd *output_bfd, |
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); |
@@ -6914,9 +6990,7 @@ ppc_elf_relocate_section (bfd *output_bfd, |
insn1 |= 32 << 26; /* lwz */ |
if (offset != (bfd_vma) -1) |
{ |
- rel[1].r_info |
- = ELF32_R_INFO (ELF32_R_SYM (rel[1].r_info), |
- R_PPC_NONE); |
+ rel[1].r_info = ELF32_R_INFO (STN_UNDEF, R_PPC_NONE); |
insn2 = 0x7c631214; /* add 3,3,2 */ |
bfd_put_32 (output_bfd, insn2, contents + offset); |
} |
@@ -6990,8 +7064,7 @@ ppc_elf_relocate_section (bfd *output_bfd, |
bfd_put_32 (output_bfd, insn2, contents + offset); |
/* Zap the reloc on the _tls_get_addr call too. */ |
BFD_ASSERT (offset == rel[1].r_offset); |
- rel[1].r_info = ELF32_R_INFO (ELF32_R_SYM (rel[1].r_info), |
- R_PPC_NONE); |
+ rel[1].r_info = ELF32_R_INFO (STN_UNDEF, R_PPC_NONE); |
} |
break; |
@@ -7020,8 +7093,7 @@ ppc_elf_relocate_section (bfd *output_bfd, |
contents + rel->r_offset - d_offset); |
/* Zap the reloc on the _tls_get_addr call too. */ |
BFD_ASSERT (rel->r_offset - d_offset == rel[1].r_offset); |
- rel[1].r_info = ELF32_R_INFO (ELF32_R_SYM (rel[1].r_info), |
- R_PPC_NONE); |
+ rel[1].r_info = ELF32_R_INFO (STN_UNDEF, R_PPC_NONE); |
rel--; |
continue; |
} |
@@ -7044,20 +7116,24 @@ ppc_elf_relocate_section (bfd *output_bfd, |
/* 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; |
@@ -7288,6 +7364,7 @@ ppc_elf_relocate_section (bfd *output_bfd, |
|| 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 |
@@ -7439,6 +7516,21 @@ ppc_elf_relocate_section (bfd *output_bfd, |
case R_PPC_TPREL16_LO: |
case R_PPC_TPREL16_HI: |
case R_PPC_TPREL16_HA: |
+ if (h != NULL |
+ && h->root.type == bfd_link_hash_undefweak |
+ && h->dynindx == -1) |
+ { |
+ /* Make this relocation against an undefined weak symbol |
+ resolve to zero. This is really just a tweak, since |
+ code using weak externs ought to check that they are |
+ defined before using them. */ |
+ bfd_byte *p = contents + rel->r_offset - d_offset; |
+ unsigned int insn = bfd_get_32 (output_bfd, p); |
+ insn = _bfd_elf_ppc_at_tprel_transform (insn, 2); |
+ if (insn != 0) |
+ bfd_put_32 (output_bfd, insn, p); |
+ break; |
+ } |
addend -= htab->elf.tls_sec->vma + TP_OFFSET; |
/* The TPREL16 relocs shouldn't really be used in shared |
libs as they will result in DT_TEXTREL being set, but |
@@ -7519,7 +7611,7 @@ ppc_elf_relocate_section (bfd *output_bfd, |
&& !h->def_regular)) |
{ |
int skip; |
- |
+ bfd_byte * loc; |
#ifdef DEBUG |
fprintf (stderr, "ppc_elf_relocate_section needs to " |
"create relocation for %s\n", |
@@ -7653,12 +7745,20 @@ ppc_elf_relocate_section (bfd *output_bfd, |
} |
break; |
- case R_PPC_RELAX32PC_PLT: |
- case R_PPC_RELAX32_PLT: |
+ case R_PPC_RELAX_PLT: |
+ case R_PPC_RELAX_PLTREL24: |
if (h != NULL) |
{ |
- struct plt_entry *ent = find_plt_ent (&h->plt.plist, got2, |
- info->shared ? addend : 0); |
+ struct plt_entry *ent; |
+ bfd_vma got2_addend = 0; |
+ |
+ if (r_type == R_PPC_RELAX_PLTREL24) |
+ { |
+ if (info->shared) |
+ got2_addend = addend; |
+ addend = 0; |
+ } |
+ ent = find_plt_ent (&h->plt.plist, got2, got2_addend); |
if (htab->plt_type == PLT_NEW) |
relocation = (htab->glink->output_section->vma |
+ htab->glink->output_offset |
@@ -7668,18 +7768,14 @@ ppc_elf_relocate_section (bfd *output_bfd, |
+ htab->plt->output_offset |
+ ent->plt.offset); |
} |
- if (r_type == R_PPC_RELAX32_PLT) |
- goto relax32; |
/* Fall thru */ |
- case R_PPC_RELAX32PC: |
- relocation -= (input_section->output_section->vma |
- + input_section->output_offset |
- + rel->r_offset - 4); |
- /* Fall thru */ |
+ case R_PPC_RELAX: |
+ if (info->shared) |
+ relocation -= (input_section->output_section->vma |
+ + input_section->output_offset |
+ + rel->r_offset - 4); |
- case R_PPC_RELAX32: |
- relax32: |
{ |
unsigned long t0; |
unsigned long t1; |
@@ -7909,7 +8005,9 @@ ppc_elf_relocate_section (bfd *output_bfd, |
} |
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); |