This is the mail archive of the
binutils@sources.redhat.com
mailing list for the binutils project.
mips4/32-el BFD breakage
- From: Pjotr Kourzanov <peter dot kourzanov at xs4all dot nl>
- To: binutils at sources dot redhat dot com, drow at mvista dot com
- Date: Mon, 07 Mar 2005 17:22:23 +0100
- Subject: mips4/32-el BFD breakage
Dear binutils developers,
Having dug into a particularly nasty problem of crashing applications
that use huge shared libraries (>40000 symbols) under a MIPS4,
little-endian target (I think the problem is MIPS generic, so it affects
MIPS3 as well) with Linux 2.4 kernel and GLIBC 2.3.2, I came up with the
attached two patches (one for 2.15, another one for the CVS MAIN).
It seems that a change to BFD broke GLIBC's dynamic loader, which
just gets a SIGSEGV whenever an application tries to link to huge shared
libraries in _dl_map_object_deps.
I have traced the problem to this change:
2003-11-17 Daniel Jacobowitz <drow@mvista.com>
* elf.c (_bfd_elf_link_hash_copy_indirect): Copy
ELF_LINK_HASH_NEEDS_PLT.
It apparently introduces ELF_LINK_HASH_NEEDS_PLT handling in
_bfd_elf_link_hash_copy_indirect which is bogus on (at least) my MIPS
with huge shared objects.
As a workaround, I've reverted this particular change by copying the
_bfd_elf_link_hash_copy_indirect implementation from elf.c to
elfxx-mips.c (suffixing it with "_mips") and disabling copying of the
ELF_LINK_HASH_NEEDS_PLT flag.
As I am not a MIPS binutils expert, could one of you shed light on why
this change was required?
Thanks in advance,
Pjotr Kourzanov
--- ../../Binutils/binutils-2.15.cvs/bfd/elfxx-mips.c 2005-01-28 17:01:27.000000000 +0100
+++ bfd/elfxx-mips.c 2005-03-07 11:42:36.000000000 +0100
@@ -7595,6 +7594,62 @@
return TRUE;
}
+/* Copy data from an indirect symbol to its direct symbol, hiding the
+ old indirect symbol. Also used for copying flags to a weakdef. */
+
+void
+_bfd_elf_link_hash_copy_indirect_mips (const struct elf_backend_data *bed,
+ struct elf_link_hash_entry *dir,
+ struct elf_link_hash_entry *ind)
+{
+ bfd_signed_vma tmp;
+ bfd_signed_vma lowest_valid = bed->can_refcount;
+
+ /* 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
+ | 0/*ELF_LINK_HASH_NEEDS_PLT*/
+ | ELF_LINK_POINTER_EQUALITY_NEEDED);
+
+ if (ind->root.type != bfd_link_hash_indirect)
+ return;
+
+ /* 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 < lowest_valid)
+ {
+ dir->got.refcount = ind->got.refcount;
+ ind->got.refcount = tmp;
+ }
+ else
+ BFD_ASSERT (ind->got.refcount < lowest_valid);
+
+ tmp = dir->plt.refcount;
+ if (tmp < lowest_valid)
+ {
+ dir->plt.refcount = ind->plt.refcount;
+ ind->plt.refcount = tmp;
+ }
+ else
+ BFD_ASSERT (ind->plt.refcount < lowest_valid);
+
+ 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);
+}
+
/* Copy data from a MIPS ELF indirect symbol to its direct symbol,
hiding the old indirect symbol. Process additional relocation
information. Also called for weakdefs, in which case we just let
@@ -7607,7 +7662,7 @@
{
struct mips_elf_link_hash_entry *dirmips, *indmips;
- _bfd_elf_link_hash_copy_indirect (bed, dir, ind);
+ _bfd_elf_link_hash_copy_indirect_mips (bed, dir, ind);
if (ind->root.type != bfd_link_hash_indirect)
return;
--- bfd/elfxx-mips.c.old 2005-03-07 11:48:21.000000000 +0100
+++ bfd/elfxx-mips.c 2005-03-06 17:26:40.000000000 +0100
@@ -8307,6 +7563,60 @@
return TRUE;
}
+/* Copy data from an indirect symbol to its direct symbol, hiding the
+ old indirect symbol. Also used for copying flags to a weakdef. */
+
+void
+_bfd_elf_link_hash_copy_indirect_mips (const struct elf_backend_data *bed,
+ struct elf_link_hash_entry *dir,
+ struct elf_link_hash_entry *ind)
+{
+ bfd_signed_vma tmp;
+ bfd_signed_vma lowest_valid = bed->can_refcount;
+
+ /* Copy down any references that we may have already seen to the
+ symbol which just became indirect. */
+
+ dir->ref_dynamic |= ind->ref_dynamic;
+ dir->ref_regular |= ind->ref_regular;
+ dir->ref_regular_nonweak |= ind->ref_regular_nonweak;
+ dir->non_got_ref |= ind->non_got_ref;
+/* dir->needs_plt |= ind->needs_plt; */
+ dir->pointer_equality_needed |= ind->pointer_equality_needed;
+
+ if (ind->root.type != bfd_link_hash_indirect)
+ return;
+
+ /* 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 < lowest_valid)
+ {
+ dir->got.refcount = ind->got.refcount;
+ ind->got.refcount = tmp;
+ }
+ else
+ BFD_ASSERT (ind->got.refcount < lowest_valid);
+
+ tmp = dir->plt.refcount;
+ if (tmp < lowest_valid)
+ {
+ dir->plt.refcount = ind->plt.refcount;
+ ind->plt.refcount = tmp;
+ }
+ else
+ BFD_ASSERT (ind->plt.refcount < lowest_valid);
+
+ 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);
+}
/* Copy data from a MIPS ELF indirect symbol to its direct symbol,
hiding the old indirect symbol. Process additional relocation
information. Also called for weakdefs, in which case we just let
@@ -8319,7 +7629,7 @@
{
struct mips_elf_link_hash_entry *dirmips, *indmips;
- _bfd_elf_link_hash_copy_indirect (bed, dir, ind);
+ _bfd_elf_link_hash_copy_indirect_mips (bed, dir, ind);
if (ind->root.type != bfd_link_hash_indirect)
return;