skip to Main Content

I have an executable compiled on a latest operating system. The executable is just a few lines of math code.

Problem is, it’s crashing when it’s running on a different system.

ImportError: /lib64/libm.so.6: version `GLIBC_2.29' not found (required by /path/to/mylib.cpython-36m-x86_64-linux-gnu.so)

I understand the error. The program was compiled on glibc 2.29 or newer and it cannot load on the other computer where the glibc version differs.

In theory you’re supposed to build on the same system that you will distribute the software to. In practice you’re not going to setup build servers and distribute different executables for each versions of ubuntu and debian OS. All I want is to ship a handful of math functions, there’s no reason this can’t work on two computers.

I was able to find which symbols are used and causing troubles with nm /path/to/file.so or objdump -T /path/to/file.so

$ nm --dynamic mylib.cpython-38m-x86_64-linux-gnu.so  | grep GLIBC
                 U pow@GLIBC_2.29
                 U sqrt@GLIBC_2.2.5

The issue is due to pow(), the power function from the standard math library, was broken in version 2.29 of the GLIBC.

The broader question is, how to determine which functions were changed in which versions of the glibc? is there a wiki page or changelog somewhere?

then how to link or relink to a specific function/symbol to maximize compatibility?

P.S. Obviously from the filename I am using cython to compiled C functions alongside python code. Cython is compiling with gcc and can be given compiler and linker flags.

2

Answers


  1. Chosen as BEST ANSWER

    You can refer to the glibc source code to find which symbols are available.

    This pow() function is from the math module. The source code with the version mapping is visible here https://github.com/bminor/glibc/blob/release/2.29/master/math/Versions

    Looking for pow; the function was altered in versions 2.0 and 2.29

      ...
      }
      GLIBC_2.29 {
        # No SVID compatible error handling.
        exp; exp2; log; log2; pow;
      }
      ...
    

    Finding some changelog here https://lwn.net/Articles/778286/ and here https://www.linaro.org/blog/glibc-improvements-and-what-to-expect-in-future-linux-distributions/

    "The glibc 2.29 replaced its generic exp, exp2, exp10f, log, log2, pow, sinf, cosf, sincosf and tanf with an optimized version originally from Arm Optimized Routines. These new routines also follow the new C standard regarding error handling, which results in less overhead. The performance improvements range from two to three times on both latency and throughput."

    It's a fantastic improvement!

    Unfortunately the way the way the glib (does not) handles compatibility, it's equivalent to removing the function. Software compiled earlier is forever stuck on the older function @2.0.0 and will never get the improvement. Software compiled later can only use the newest function and will explode on systems that don't have it. Sad.

    You could instruct the linker to use the function in version 2.0.0 to ensure maximum compatibility, however you probably want to use the newer faster function. It's not clear to me how to do that.

    __asm__(".symver pow,pow@GLIBC_2.0.0");
    

  2. In theory you’re supposed to build on the same system that you will distribute the software to.

    That is incorrect: you don’t need to build on every version (that would be a nightmare).

    What you are supposed to do is build on the lowest version of the system that you intend to support.

    For example, if you build your math program (assuming it doesn’t need graphics dependencies) on a RedHat 7.21 system (in a VM — I don’t advocate actually running such an oldie), it will run on every Linux system that is not older than 20 years.

    The broader question is, how to determine which functions were changed in which versions of the glibc?

    That is the wrong question to ask, but user5994461 has provided a good answer for it.


    1 Here I really mean RedHat-7.2 (which was the base for RHEL-2.1), and not RHEL-7.2 that was released in 2015.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search