Re: --gc-sections leads to relocation truncated to fit: R_PPC64_REL24 against .opd +$bignum

classic Classic list List threaded Threaded
2 messages Options
Reply | Threaded
Open this post in threaded view
|

Re: --gc-sections leads to relocation truncated to fit: R_PPC64_REL24 against .opd +$bignum

Alan Modra
On Sun, Jun 05, 2005 at 10:15:19PM +0200, Olaf Hering wrote:
> Is --gc-sections supposed to work correctly?

Sigh.  Yes, it is supposed to..  Non-dotsym compilers exposed a bug in
gc_mark_hook, and broke --no-opd-optimize too.  It's a wonder Jakub
hadn't complained to me about this one.

bfd/
        * elf64-pcc.c (ppc64_elf_gc_mark_hook): For the local sym in .opd
        case, include addend when indexing .opd section map.
        (ppc64_elf_edit_opd): Add no_opd_opt param.  Do nothing besides
        clear opd_adjust array if no_opd_opt set.  Tidy code.
        * elf64-ppc.h (ppc64_elf_edit_opd): Update prototype.
ld/
        * emultempl/ppc64elf.em (ppc_before_allocation): Always run
        ppc64_elf_edit_opd.

Index: bfd/elf64-ppc.c
===================================================================
RCS file: /cvs/src/src/bfd/elf64-ppc.c,v
retrieving revision 1.208
diff -u -p -r1.208 elf64-ppc.c
--- bfd/elf64-ppc.c 2 Jun 2005 13:13:54 -0000 1.208
+++ bfd/elf64-ppc.c 6 Jun 2005 12:31:56 -0000
@@ -5064,7 +5064,7 @@ ppc64_elf_gc_mark_hook (asection *sec,
   if (!rsec->gc_mark)
     _bfd_elf_gc_mark (info, rsec, ppc64_elf_gc_mark_hook);
 
-  rsec = opd_sym_section[sym->st_value / 8];
+  rsec = opd_sym_section[(sym->st_value + rel->r_addend) / 8];
  }
     }
 
@@ -6155,6 +6155,7 @@ dec_dynrel_count (bfd_vma r_info,
 
 bfd_boolean
 ppc64_elf_edit_opd (bfd *obfd, struct bfd_link_info *info,
+    bfd_boolean no_opd_opt,
     bfd_boolean non_overlapping)
 {
   bfd *ibfd;
@@ -6184,11 +6185,14 @@ ppc64_elf_edit_opd (bfd *obfd, struct bf
  {
   /* check_relocs hasn't been called.  Must be a ld -r link
      or --just-symbols object.   */
-  opd_adjust = bfd_zalloc (obfd, amt);
+  opd_adjust = bfd_alloc (obfd, amt);
   ppc64_elf_section_data (sec)->opd.adjust = opd_adjust;
  }
       memset (opd_adjust, 0, amt);
 
+      if (no_opd_opt)
+ continue;
+
       if (sec->sec_info_type == ELF_INFO_TYPE_JUST_SYMS)
  continue;
 
@@ -6358,18 +6362,16 @@ ppc64_elf_edit_opd (bfd *obfd, struct bf
 
   elf_section_data (sec)->relocs = relstart;
 
-  wptr = sec->contents;
-  rptr = sec->contents;
   new_contents = sec->contents;
-
   if (add_aux_fields)
     {
       new_contents = bfd_malloc (sec->size + cnt_16b * 8);
       if (new_contents == NULL)
  return FALSE;
       need_pad = FALSE;
-      wptr = new_contents;
     }
+  wptr = new_contents;
+  rptr = sec->contents;
 
   write_rel = relstart;
   skip = FALSE;
Index: bfd/elf64-ppc.h
===================================================================
RCS file: /cvs/src/src/bfd/elf64-ppc.h,v
retrieving revision 1.22
diff -u -p -r1.22 elf64-ppc.h
--- bfd/elf64-ppc.h 4 May 2005 15:53:26 -0000 1.22
+++ bfd/elf64-ppc.h 6 Jun 2005 12:42:58 -0000
@@ -20,7 +20,7 @@ Foundation, Inc., 51 Franklin Street - F
 void ppc64_elf_init_stub_bfd
   (bfd *, struct bfd_link_info *);
 bfd_boolean ppc64_elf_edit_opd
-  (bfd *, struct bfd_link_info *, bfd_boolean);
+  (bfd *, struct bfd_link_info *, bfd_boolean, bfd_boolean);
 asection *ppc64_elf_tls_setup
   (bfd *, struct bfd_link_info *);
 bfd_boolean ppc64_elf_tls_optimize
Index: ld/emultempl/ppc64elf.em
===================================================================
RCS file: /cvs/src/src/ld/emultempl/ppc64elf.em,v
retrieving revision 1.43
diff -u -p -r1.43 ppc64elf.em
--- ld/emultempl/ppc64elf.em 12 May 2005 07:32:04 -0000 1.43
+++ ld/emultempl/ppc64elf.em 6 Jun 2005 12:44:32 -0000
@@ -102,8 +102,8 @@ ppc_before_allocation (void)
 {
   if (stub_file != NULL)
     {
-      if (!no_opd_opt
-  && !ppc64_elf_edit_opd (output_bfd, &link_info, non_overlapping_opd))
+      if (!ppc64_elf_edit_opd (output_bfd, &link_info, no_opd_opt,
+       non_overlapping_opd))
  einfo ("%X%P: can not edit %s %E\n", "opd");
 
       if (ppc64_elf_tls_setup (output_bfd, &link_info) && !no_tls_opt)

--
Alan Modra
IBM OzLabs - Linux Technology Centre
Reply | Threaded
Open this post in threaded view
|

Re: --gc-sections leads to relocation truncated to fit: R_PPC64_REL24 against .opd +$bignum

Alan Modra
Olaf pointed out that the bfd_alloc can fail.  A scan over elf64-ppc.c
reveal another place that needs fixing too.

        * elf64-ppc.c (ppc_stub_name): Return immediately on bfd_malloc fail.
        (ppc64_elf_edit_opd): Ignore zero size .opd.  Check bfd_alloc
        return value.

Index: bfd/elf64-ppc.c
===================================================================
RCS file: /cvs/src/src/bfd/elf64-ppc.c,v
retrieving revision 1.209
diff -u -p -r1.209 elf64-ppc.c
--- bfd/elf64-ppc.c 6 Jun 2005 12:59:54 -0000 1.209
+++ bfd/elf64-ppc.c 6 Jun 2005 13:11:09 -0000
@@ -3581,26 +3581,26 @@ ppc_stub_name (const asection *input_sec
     {
       len = 8 + 1 + strlen (h->elf.root.root.string) + 1 + 8 + 1;
       stub_name = bfd_malloc (len);
-      if (stub_name != NULL)
- {
-  sprintf (stub_name, "%08x.%s+%x",
-   input_section->id & 0xffffffff,
-   h->elf.root.root.string,
-   (int) rel->r_addend & 0xffffffff);
- }
+      if (stub_name == NULL)
+ return stub_name;
+
+      sprintf (stub_name, "%08x.%s+%x",
+       input_section->id & 0xffffffff,
+       h->elf.root.root.string,
+       (int) rel->r_addend & 0xffffffff);
     }
   else
     {
       len = 8 + 1 + 8 + 1 + 8 + 1 + 8 + 1;
       stub_name = bfd_malloc (len);
-      if (stub_name != NULL)
- {
-  sprintf (stub_name, "%08x.%x:%x+%x",
-   input_section->id & 0xffffffff,
-   sym_sec->id & 0xffffffff,
-   (int) ELF64_R_SYM (rel->r_info) & 0xffffffff,
-   (int) rel->r_addend & 0xffffffff);
- }
+      if (stub_name == NULL)
+ return stub_name;
+
+      sprintf (stub_name, "%08x.%x:%x+%x",
+       input_section->id & 0xffffffff,
+       sym_sec->id & 0xffffffff,
+       (int) ELF64_R_SYM (rel->r_info) & 0xffffffff,
+       (int) rel->r_addend & 0xffffffff);
     }
   if (stub_name[len - 2] == '+' && stub_name[len - 1] == '0')
     stub_name[len - 2] = 0;
@@ -6176,7 +6176,7 @@ ppc64_elf_edit_opd (bfd *obfd, struct bf
       bfd_size_type cnt_16b = 0;
 
       sec = bfd_get_section_by_name (ibfd, ".opd");
-      if (sec == NULL)
+      if (sec == NULL || sec->size == 0)
  continue;
 
       amt = sec->size * sizeof (long) / 8;
@@ -6186,6 +6186,8 @@ ppc64_elf_edit_opd (bfd *obfd, struct bf
   /* check_relocs hasn't been called.  Must be a ld -r link
      or --just-symbols object.   */
   opd_adjust = bfd_alloc (obfd, amt);
+  if (opd_adjust == NULL)
+    return FALSE;
   ppc64_elf_section_data (sec)->opd.adjust = opd_adjust;
  }
       memset (opd_adjust, 0, amt);

--
Alan Modra
IBM OzLabs - Linux Technology Centre