This is the mail archive of the
binutils@sourceware.cygnus.com
mailing list for the binutils project.
Re: A weak symbol patch
- To: hjl@varesearch.com
- Subject: Re: A weak symbol patch
- From: Ian Lance Taylor <ian@zembu.com>
- Date: 7 Jul 1999 14:19:19 -0400
- CC: binutils@sourceware.cygnus.com, geoffk@ozemail.com.au
- References: <19990706203412.DAA553FC1@varesearch.com>
Date: Tue, 6 Jul 1999 13:34:12 -0700 (PDT)
From: hjl@varesearch.com (H.J. Lu)
I believe there is a linker bug regarding the weak symbol handling. I
have sent 2 testcases for the bug. Here is a patch. Could you please
take a look?
I am about to check in the appended patch, which is based on yours. I
think this will fix your test case.
Ian
Index: elflink.h
===================================================================
RCS file: /cvs/binutils/binutils/bfd/elflink.h,v
retrieving revision 1.9
diff -u -r1.9 elflink.h
--- elflink.h 1999/07/01 23:20:07 1.9
+++ elflink.h 1999/07/07 18:18:39
@@ -492,14 +492,19 @@
represent variables; this can cause confusion in principle, but
any such confusion would seem to indicate an erroneous program or
shared library. We also permit a common symbol in a regular
- object to override a weak symbol in a shared object. */
+ object to override a weak symbol in a shared object.
+ We prefer a non-weak definition in a shared library to a weak
+ definition in the executable. */
+
if (newdyn
&& newdef
&& (olddef
|| (h->root.type == bfd_link_hash_common
&& (bind == STB_WEAK
- || ELF_ST_TYPE (sym->st_info) == STT_FUNC))))
+ || ELF_ST_TYPE (sym->st_info) == STT_FUNC)))
+ && (h->root.type != bfd_link_hash_defweak
+ || bind == STB_WEAK))
{
*override = true;
newdef = false;
@@ -543,7 +548,10 @@
As above, we again permit a common symbol in a regular object to
override a definition in a shared object if the shared object
- symbol is a function or is weak. */
+ symbol is a function or is weak.
+
+ As above, we permit a non-weak definition in a shared object to
+ override a weak definition in a regular object. */
if (! newdyn
&& (newdef
@@ -552,7 +560,9 @@
|| h->type == STT_FUNC)))
&& olddyn
&& olddef
- && (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_DYNAMIC) != 0)
+ && (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_DYNAMIC) != 0
+ && (bind != STB_WEAK
+ || h->root.type == bfd_link_hash_defweak))
{
/* Change the hash table entry to undefined, and let
_bfd_generic_link_add_one_symbol do the right thing with the
@@ -626,6 +636,31 @@
h->verinfo.vertree = NULL;
}
+ /* Handle the special case of a weak definition in a regular object
+ followed by a non-weak definition in a shared object. In this
+ case, we prefer the definition in the shared object. To make
+ this work we have to frob the flags. */
+ if (olddef
+ && ! olddyn
+ && h->root.type == bfd_link_hash_defweak
+ && newdef
+ && newdyn
+ && bind != STB_WEAK)
+ h->elf_link_hash_flags &= ~ ELF_LINK_HASH_DEF_REGULAR;
+
+ /* Handle the special case of a non-weak definition in a shared
+ object followed by a weak definition in a regular object. In
+ this case we prefer to definition in the shared object. To make
+ this work we have to tell the caller to not treat the new symbol
+ as a definition. */
+ if (olddef
+ && olddyn
+ && h->root.type != bfd_link_hash_defweak
+ && newdef
+ && ! newdyn
+ && bind == STB_WEAK)
+ *override = true;
+
return true;
}