[PATCH] [ELF] LLD does not create a record in the .dynsym if a strong symbol defined in the executable file replaces a weak symbol from a shared library.

Simon Atanasyan simon at atanasyan.com
Thu Aug 14 06:18:48 PDT 2014


On Thu, Aug 14, 2014 at 4:51 AM, kledzik at apple.com <kledzik at apple.com> wrote:
> From the description of the problem, I thought that libfoo would have a weak definition of "flag" and main had a strong definition of "flag" and the problem was that the binaries were not set up properly so that ld.so would pick main's flag to override libfoo's flag.
>
> But looking at the example code,  "flag" is extern.  So this seems like the other meaning of weak - that the symbol can be missing at runtime.  But the use of "flag" in foo() is not checking if its address is NULL before accessing. But in this case it should not be NULL because ld.so should find it in main.
>
> Which case is this?

The original problem is related to the _IO_stdin_used symbol. It is
defined as a weak symbol in the libc.so and as a strong symbol in the
crt1.o. The code in libc checks its address and if the address is not
null uses an appropriate variant of IO routines.

Everything works correctly if the program linked by GNU linker. This
linker understand that a weak symbol from a shared library is
coalesced away by a strong symbol defined in an object file and put a
corresponding record in a dynamic symbol table. If you use LLD it does
not put such symbol in the dynamic symbol table so at runtime from the
shared library point of view this symbol remains weak.

> What info is missing after resolve() is done?

When resolve() is done we have a "defined" (strong) symbol and forget
that a weak symbol from a shared library was coalesced away. We
consider the strong symbols as a common "defined" symbol which does
not require any records in the dynamic symbol table.

-- 
Simon Atanasyan




More information about the llvm-commits mailing list