From mboxrd@z Thu Jan 1 00:00:00 1970 From: Ian Lance Taylor To: hjl@varesearch.com Cc: binutils@sourceware.cygnus.com, geoffk@ozemail.com.au Subject: Re: A weak symbol patch Date: Wed, 07 Jul 1999 11:20:00 -0000 Message-id: <19990707181919.2961.qmail@daffy.airs.com> References: <19990706203412.DAA553FC1@varesearch.com> X-SW-Source: 1999-q3/msg00062.html 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; }