Are the pthread "compatibility" copies of symbols in libc still necessary?

Florian Weimer fweimer@redhat.com
Fri Mar 16 15:42:00 GMT 2018


On 03/16/2018 04:35 PM, Carlos O'Donell wrote:
> On 03/16/2018 08:41 AM, Florian Weimer wrote:
>> On 03/16/2018 03:30 PM, Zack Weinberg wrote:
>>> A number of source files that properly belong to libc.so are also
>>> compiled as part of libpthread, with a note that this is for
>>> "compatibility for old binaries".  The exact set varies based on
>>> architecture, but includes basic things like read, write, and fork - I
>>> _think_ there was a difference in semantics in the distant past,
>>> having something to do with thread cancellation.
>>
>> They are still needed because versioned symbols also embed a DSO name, and the dynamic linker checks that if it has not been interposed.
>>
>> I think it's this code in elf/dl-lookup.c:
>>
>>        if (__glibc_unlikely (res < 0) && skip_map == NULL)
>>      {
>>        /* Oh, oh.  The file named in the relocation entry does not
>>           contain the needed symbol.  This code is never reached
>>           for unversioned lookups.  */
>>        assert (version != NULL);
>>        const char *reference_name = undef_map ? undef_map->l_name : "";
>>        struct dl_exception exception;
>>        /* XXX We cannot translate the message.  */
>>        _dl_exception_create_format
>>          (&exception, DSO_FILENAME (reference_name),
>>           "symbol %s version %s not defined in file %s"
>>           " with link time reference%s",
>>           undef_name, version->name, version->filename,
>>           res == -2 ? " (no version symbols)" : "");
>>        _dl_signal_cexception (0, &exception, N_("relocation error"));
>>        _dl_exception_free (&exception);
>>        *ref = NULL;
>>        return 0;
>>      }
>>
>> This is required by the GNU symbol versioning spec, but I don't know why.
> 
> The specification says the data must be recorded, but it doesn't say what you
> have to *do* with the data?

It does:

“
A fatal error shall be triggered when no matching definition can be 
found in the object whose name is the one referenced by the vn_name 
element in the Elfxx_Verneed entry.
”

>> Even new binaries use these symbols:
>>
>> $ LD_DEBUG=bindings systemctl |& grep binding.*system.*libpthread.*[^_]fork
>>       11905:    binding file /usr/lib/systemd/libsystemd-shared-234.so [0] to /lib64/libpthread.so.0 [0]: normal symbol `fork' [GLIBC_2.2.5]
>>       11905:    binding file systemctl [0] to /lib64/libpthread.so.0 [0]: normal symbol `fork' [GLIBC_2.2.5]
>>
>> This may be a linker bug because at least fork is a compat symbol.

> Is it a dynamic loader bug that the compat symbol was selected?

No, I don't think the dynamic linker has to make this distinction, at 
least not if the soname matches the one in the version.

> My conclusion is this:
> 
> * We can remove fork@GLIBC_2.2.5 from libpthread.so, the shared object doesn't
>    encode it as being needed and won't cause a failure per the rules that
>    require the referenced shared object to have the versioned symbol that was
>    bound at static link time.

I already tried a while bug and failed because the system does not boot 
anymore after that, due to the check mentioned above.  I don't think the 
code has changed since then.

Thanks,
Florian



More information about the Libc-alpha mailing list