binutils-2.20: add patch for ld segfault on powerpc
authorJeremy Lainé <jeremy.laine@bolloretelecom.eu>
Mon, 28 Dec 2009 21:09:58 +0000 (22:09 +0100)
committerJeremy Lainé <jeremy.laine@bolloretelecom.eu>
Mon, 28 Dec 2009 21:09:58 +0000 (22:09 +0100)
recipes/binutils/binutils-2.20/binutils-powerpc-pr11088.patch [new file with mode: 0644]
recipes/binutils/binutils_2.20.bb

diff --git a/recipes/binutils/binutils-2.20/binutils-powerpc-pr11088.patch b/recipes/binutils/binutils-2.20/binutils-powerpc-pr11088.patch
new file mode 100644 (file)
index 0000000..d5be176
--- /dev/null
@@ -0,0 +1,275 @@
+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;
index 5398688..6961377 100644 (file)
@@ -2,7 +2,7 @@ require binutils.inc
 LICENSE = "GPLv3"
 
 INC_PR = "r1"
-PR = "${INC_PR}.2"
+PR = "${INC_PR}.3"
 
 SRC_URI = "\
      ${GNU_MIRROR}/binutils/binutils-${PV}.tar.bz2 \
@@ -17,4 +17,7 @@ SRC_URI = "\
      "
 
 # powerpc patches
-SRC_URI += "file://binutils-2.16.1-e300c2c3.patch;patch=1"
+SRC_URI += "\
+     file://binutils-2.16.1-e300c2c3.patch;patch=1 \
+     file://binutils-powerpc-pr11088.patch;patch=1 \
+     "