276 lines
7.5 KiB
Diff
276 lines
7.5 KiB
Diff
Fix ld segfault when compiling Qt 4.6.0 on powerpc. See:
|
|
|
|
http://sourceware.org/bugzilla/show_bug.cgi?id=11088
|
|
|
|
===================================================================
|
|
RCS file: /cvs/src/src/include/elf/ppc.h,v
|
|
retrieving revision 1.26
|
|
retrieving revision 1.27
|
|
diff -u -r1.26 -r1.27
|
|
--- src/include/elf/ppc.h 2009/09/21 11:51:01 1.26
|
|
+++ src/include/elf/ppc.h 2009/12/17 05:45:25 1.27
|
|
@@ -73,10 +73,9 @@
|
|
|
|
#ifndef RELOC_MACROS_GEN_FUNC
|
|
/* Fake relocations for branch stubs, only used internally by ld. */
|
|
- RELOC_NUMBER (R_PPC_RELAX32, 48)
|
|
- RELOC_NUMBER (R_PPC_RELAX32PC, 49)
|
|
- RELOC_NUMBER (R_PPC_RELAX32_PLT, 50)
|
|
- RELOC_NUMBER (R_PPC_RELAX32PC_PLT, 51)
|
|
+ RELOC_NUMBER (R_PPC_RELAX, 48)
|
|
+ RELOC_NUMBER (R_PPC_RELAX_PLT, 49)
|
|
+ RELOC_NUMBER (R_PPC_RELAX_PLTREL24, 50)
|
|
#endif
|
|
|
|
/* Relocs added to support TLS. */
|
|
===================================================================
|
|
RCS file: /cvs/src/src/bfd/elf32-ppc.c,v
|
|
retrieving revision 1.272
|
|
retrieving revision 1.273
|
|
diff -u -r1.272 -r1.273
|
|
--- src/bfd/elf32-ppc.c 2009/12/11 13:42:02 1.272
|
|
+++ src/bfd/elf32-ppc.c 2009/12/17 05:45:25 1.273
|
|
@@ -3323,6 +3323,8 @@
|
|
{
|
|
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 @@
|
|
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 @@
|
|
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 @@
|
|
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. */
|
|
@@ -4486,7 +4485,7 @@
|
|
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 @@
|
|
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 @@
|
|
&& 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 @@
|
|
{
|
|
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 @@
|
|
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 @@
|
|
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 @@
|
|
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 @@
|
|
*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;
|
|
}
|
|
@@ -6239,28 +6255,28 @@
|
|
{
|
|
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 @@
|
|
{
|
|
/* 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);
|
|
|
|
@@ -7669,12 +7685,20 @@
|
|
}
|
|
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
|
|
@@ -7684,18 +7708,14 @@
|
|
+ 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;
|