[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Bug#966173: libc6: __atan2_finite reference in dlopened module no longer found in executable linked to libm



Package: libc6
Version: 2.31-1
Severity: normal

I've encountered an odd bug in openarena (#966150) which I'm concerned
might be a glibc regression affecting other packages.

Some background: openarena is a game running on the ioquake3 engine
(main executable: /usr/lib/ioquake3/ioquake3). During startup, the engine
dlopens some modules, which implement the actual openarena game and UI.
One of those modules is uix86_64.so.

uix86_64.so uses mathematical functions from libm, but is not itself
linked to libm. At runtime (at least on older systems) it works as
intended, because the ioquake3 executable *is* linked to libm. I'm aware
that this is not the most robust setup, and uix86_64.so would ideally be
linked with -lm to make it self-contained; but it's documented as being
expected to work, and has always worked in the past:

    Symbol references in the shared object are resolved using (in order):
    symbols in the link map of objects loaded for the main program and its
    dependencies; [... and some more places ...]
    — dlopen(3)

The bug (#966150) is that a version of uix86_64.so compiled with a slightly
older (2020-02-18) toolchain fails to load on an up-to-date sid system, with:

    undefined symbol: __atan2_finite

If I recompile openarena in a sid chroot, *with no source code changes*
(in particular uix86_64.so is still not linked to -lm!), then it starts
to work again. The recompiled uix86_64.so has an undefined reference
to atan2, but no reference to __atan2_finite any more.

I'm going to address this in bullseye by making openarena more robust
(explicitly linking to -lm). After I've done that, the updated version of
openarena will not be suitable as a reproducer for this bug report, but
the buster version of openarena will still be suitable.

If you believe this is not a significant regression in glibc and should
only be fixed by changes in openarena, I have no problem with doing that
and just closing this bug report. However, I wanted to raise this in
case it affects other previously-built binaries.

This can be reproduced somewhat conveniently as follows:

* Have a buster virtual machine
* Install openarena and enough of a desktop to get a terminal in an X11
  environment
* Run openarena
    * It succeeds
    * To exit quickly: Shift+Escape, type "/quit", Enter
* Add a bullseye apt source and "apt update", but do not upgrade everything
* Upgrade libc6 from 2.28-10 to 2.31-1, while upgrading as few other
  packages as possible
    * I used aptitude, which made me also upgrade gcc-9 and related
      packages, removing gcc-8
* Run openarena
    * It fails as described in #966150
* Downgrade libc6 and closely-related packages from 2.31-1 to 2.28-10
    * In my case this meant downgrading libc-dev-bin, libc6-dev, libc6
      and libc-bin, and removing libcrypt-dev and libcrypt1
* Run openarena
    * It succeeds again, confirming that this was a glibc behaviour change

I've been trying to put together a standalone reproducer that only uses
libdl and libm, but so far I have not been successful.

I believe this is related to a change in the representation of
the __atan2_finite symbol, which is used (at least by versions of
openarena compiled against older glibc) because openarena is compiled
with -ffast-math. In 2.28-10, that symbol was not hidden:

$ objdump -Tx /lib/x86_64-linux-gnu/libm.so.6
...
0000000000028280 g   iD  .text  0000000000000046  GLIBC_2.15  __atan2_finite

In 2.31-1, it is hidden, and there is no non-hidden definition (default
symbol-version):

$ objdump -Tx /lib/x86_64-linux-gnu/libm.so.6
...
000000000002a1e0 g   iD  .text  0000000000000049 (GLIBC_2.15) __atan2_finite

Because uix86_64.so is not directly linked to -lm, it has an undefined
reference to __atan2_finite with no particular version:

$ objdump -Tx /usr/lib/openarena/baseoa/pak6-patch088/uix86_64.so
...
0000000000000000      D  *UND*  0000000000000000              __atan2_finite

As far as I can work out, this unversioned undefined reference can be
satisfied by __atan2_finite@@GLIBC_2.15 in the global namespace from
the old libm, but not by the hidden version __atan2_finite@GLIBC_2.15
in the new libm.

Thanks,
    smcv


Reply to: