This is the mail archive of the binutils@sources.redhat.com mailing list for the binutils project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

GOT refcounting broke non-refcount targets


... in particular, I've seen this problem with ARM and SH.  The problem is
that _bfd_elf_link_hash_copy_indirect checks the refcount like so:

  /* Copy over the global and procedure linkage table refcount entries.
     These may have been already set up by a check_relocs routine.  */
  tmp = dir->got.refcount;
  if (tmp <= 0)
    {
      dir->got.refcount = ind->got.refcount;
      ind->got.refcount = tmp;
    }
  else
    BFD_ASSERT (ind->got.refcount <= 0);

But if got.offset is being used instead of got.refcount, then 0 is a valid
offset.  In fact, it's the first GOT entry.  This produces an assertion
failure in sh_elf_relocate_sections, and a corrupt libc.so.6.  At a guess
this can happen on sh64, sparc, and MIPS also; I tested MIPS but did not see
the problem there, because it doesn't use got.offset as an offset (and
explicitly avoids zeros, for the same reason).

Sparc has the same problem and even worse: the only use of got.refcount in
elf32-sparc.c is:
            if (h->got.refcount > 0)
              h->got.refcount--;
Since the refcount is never set, and the offset is set, this will corrupt
things.  This overloading of fields to save memory seems terribly unwise...

I didn't fix Sparc32 completely, because I wasn't quite sure what to do with
the above chunk, but I did fix the refcounting problem on
ARM/SH/SH64/SPARC32/SPARC64.  I'm not in love with the patch though.  Any
comments?

-- 
Daniel Jacobowitz
MontaVista Software                         Debian GNU/Linux Developer

2002-08-21  Daniel Jacobowitz  <drow@mvista.com>

	* elf-bfd.h (_bfd_elf_norefcount_copy_indirect): Add prototype.
	* elf.c (_bfd_elf_norefcount_copy_indirect): New function, cloned
	from _bfd_elf_link_hash_copy_indirect.
	* elf32-arm.h (elf_backend_copy_indirect_symbol): Define.
	* elf32-sh.h (elf_backend_copy_indirect_symbol): Define.
	* elf32-sparc.h (elf_backend_copy_indirect_symbol): Define.
	* elf64-sh64.h (elf_backend_copy_indirect_symbol): Define.
	* elf64-sparc.h (elf_backend_copy_indirect_symbol): Define.

Index: elf-bfd.h
===================================================================
RCS file: /cvs/src/src/bfd/elf-bfd.h,v
retrieving revision 1.85
diff -u -p -r1.85 elf-bfd.h
--- elf-bfd.h	25 Jul 2002 06:54:51 -0000	1.85
+++ elf-bfd.h	21 Aug 2002 22:07:39 -0000
@@ -1272,6 +1272,8 @@ extern struct bfd_link_hash_table *_bfd_
   PARAMS ((bfd *));
 extern void _bfd_elf_link_hash_copy_indirect
   PARAMS ((struct elf_link_hash_entry *, struct elf_link_hash_entry *));
+extern void _bfd_elf_norefcount_copy_indirect
+  PARAMS ((struct elf_link_hash_entry *, struct elf_link_hash_entry *));
 extern void _bfd_elf_link_hash_hide_symbol
   PARAMS ((struct bfd_link_info *, struct elf_link_hash_entry *, boolean));
 extern boolean _bfd_elf_link_hash_table_init
Index: elf.c
===================================================================
RCS file: /cvs/src/src/bfd/elf.c,v
retrieving revision 1.159
diff -u -p -r1.159 elf.c
--- elf.c	17 Aug 2002 16:09:02 -0000	1.159
+++ elf.c	21 Aug 2002 22:07:40 -0000
@@ -1467,6 +1467,59 @@ _bfd_elf_link_hash_copy_indirect (dir, i
     BFD_ASSERT (ind->dynindx == -1);
 }
 
+/* As above, for targets which use got->offset and plt->offset
+   for actual offsets.  */
+
+void
+_bfd_elf_norefcount_copy_indirect (dir, ind)
+     struct elf_link_hash_entry *dir, *ind;
+{
+  bfd_signed_vma tmp;
+
+  /* Copy down any references that we may have already seen to the
+     symbol which just became indirect.  */
+
+  dir->elf_link_hash_flags |=
+    (ind->elf_link_hash_flags
+     & (ELF_LINK_HASH_REF_DYNAMIC
+	| ELF_LINK_HASH_REF_REGULAR
+	| ELF_LINK_HASH_REF_REGULAR_NONWEAK
+	| ELF_LINK_NON_GOT_REF));
+
+  if (ind->root.type != bfd_link_hash_indirect)
+    return;
+
+  /* Copy over the global and procedure linkage table offset entries.
+     These may have been already set up by a check_relocs routine.  */
+  tmp = dir->got.offset;
+  if (tmp < 0)
+    {
+      dir->got.offset = ind->got.offset;
+      ind->got.offset = tmp;
+    }
+  else
+    BFD_ASSERT (ind->got.refcount <= 0);
+
+  tmp = dir->plt.offset;
+  if (tmp < 0)
+    {
+      dir->plt.offset = ind->plt.offset;
+      ind->plt.offset = tmp;
+    }
+  else
+    BFD_ASSERT (ind->plt.refcount <= 0);
+
+  if (dir->dynindx == -1)
+    {
+      dir->dynindx = ind->dynindx;
+      dir->dynstr_index = ind->dynstr_index;
+      ind->dynindx = -1;
+      ind->dynstr_index = 0;
+    }
+  else
+    BFD_ASSERT (ind->dynindx == -1);
+}
+
 void
 _bfd_elf_link_hash_hide_symbol (info, h, force_local)
      struct bfd_link_info *info;
Index: elf32-arm.h
===================================================================
RCS file: /cvs/src/src/bfd/elf32-arm.h,v
retrieving revision 1.90
diff -u -p -r1.90 elf32-arm.h
--- elf32-arm.h	1 Aug 2002 14:03:01 -0000	1.90
+++ elf32-arm.h	21 Aug 2002 22:07:41 -0000
@@ -3638,6 +3638,8 @@ elf32_arm_reloc_type_class (rela)
 #define elf_backend_size_dynamic_sections	elf32_arm_size_dynamic_sections
 #define elf_backend_post_process_headers	elf32_arm_post_process_headers
 #define elf_backend_reloc_type_class		elf32_arm_reloc_type_class
+#define elf_backend_copy_indirect_symbol \
+						_bfd_elf_norefcount_copy_indirect
 
 #define elf_backend_can_gc_sections 1
 #define elf_backend_plt_readonly    1
Index: elf32-sh.c
===================================================================
RCS file: /cvs/src/src/bfd/elf32-sh.c,v
retrieving revision 1.53
diff -u -p -r1.53 elf32-sh.c
--- elf32-sh.c	16 Aug 2002 18:40:54 -0000	1.53
+++ elf32-sh.c	21 Aug 2002 22:07:42 -0000
@@ -5876,6 +5876,8 @@ sh_elf_reloc_type_class (rela)
 #define elf_backend_finish_dynamic_sections \
 					sh_elf_finish_dynamic_sections
 #define elf_backend_reloc_type_class	sh_elf_reloc_type_class
+#define elf_backend_copy_indirect_symbol \
+					_bfd_elf_norefcount_copy_indirect
 
 #define elf_backend_want_got_plt	1
 #define elf_backend_plt_readonly	1
Index: elf32-sparc.c
===================================================================
RCS file: /cvs/src/src/bfd/elf32-sparc.c,v
retrieving revision 1.41
diff -u -p -r1.41 elf32-sparc.c
--- elf32-sparc.c	23 Jul 2002 12:29:32 -0000	1.41
+++ elf32-sparc.c	21 Aug 2002 22:07:42 -0000
@@ -2123,6 +2123,8 @@ elf32_sparc_reloc_type_class (rela)
 #define elf_backend_gc_mark_hook        elf32_sparc_gc_mark_hook
 #define elf_backend_gc_sweep_hook       elf32_sparc_gc_sweep_hook
 #define elf_backend_reloc_type_class	elf32_sparc_reloc_type_class
+#define elf_backend_copy_indirect_symbol \
+					_bfd_elf_norefcount_copy_indirect
 
 #define elf_backend_can_gc_sections 1
 #define elf_backend_want_got_plt 0
Index: elf64-sh64.c
===================================================================
RCS file: /cvs/src/src/bfd/elf64-sh64.c,v
retrieving revision 1.16
diff -u -p -r1.16 elf64-sh64.c
--- elf64-sh64.c	16 Aug 2002 18:40:54 -0000	1.16
+++ elf64-sh64.c	21 Aug 2002 22:07:43 -0000
@@ -4157,6 +4157,8 @@ sh64_elf64_finish_dynamic_sections (outp
 					sh64_elf64_finish_dynamic_symbol
 #define elf_backend_finish_dynamic_sections \
 					sh64_elf64_finish_dynamic_sections
+#define elf_backend_copy_indirect_symbol \
+					_bfd_elf_norefcount_copy_indirect
 
 #define elf_backend_want_got_plt	1
 #define elf_backend_plt_readonly	1
Index: elf64-sparc.c
===================================================================
RCS file: /cvs/src/src/bfd/elf64-sparc.c,v
retrieving revision 1.59
diff -u -p -r1.59 elf64-sparc.c
--- elf64-sparc.c	23 Jul 2002 12:29:33 -0000	1.59
+++ elf64-sparc.c	21 Aug 2002 22:07:43 -0000
@@ -3150,6 +3150,8 @@ const struct elf_size_info sparc64_elf_s
   sparc64_elf_object_p
 #define elf_backend_reloc_type_class \
   sparc64_elf_reloc_type_class
+#define elf_backend_copy_indirect_symbol \
+  _bfd_elf_norefcount_copy_indirect
 
 #define elf_backend_want_got_plt 0
 #define elf_backend_plt_readonly 0


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]