Fedora 28/Glibc 2.27 Libm.So.6 Logf() and Powf() C++

Fedora 28 / GLIBC 2.27 libm.so.6 logf() and powf() c++

I think the problem is that you used objdump to find the symbol versions of the 32-bit libm, and I assume you're actually building a 64-bit application. In a Fedora 28 container if I look at the 64-bit library then I see these versions instead:

objdump -T /lib64/libm.so.6 | egrep -w 'logf|powf'
0000000000011ea0 g DF .text 0000000000000138 (GLIBC_2.2.5) powf
000000000004cad0 g iD .text 000000000000002a GLIBC_2.27 powf
000000000004c610 g iD .text 000000000000002a GLIBC_2.27 logf
0000000000011e40 g DF .text 0000000000000051 (GLIBC_2.2.5) logf

And this works as expected:

#include <math.h>

__asm__(".symver logf,logf@GLIBC_2.2.5");
__asm__(".symver powf,powf@GLIBC_2.2.5");

int main(int argc, char**)
{
return powf(argc, 2.0f) * logf(argc);
}

It uses the versions from the 64-bit library:

$ g++ m.cc 
$ nm --undefined-only a.out
w __gmon_start__
U __libc_start_main@@GLIBC_2.2.5
U logf@GLIBC_2.2.5
U powf@GLIBC_2.2.5

So I think the problem was that you were trying to link to symbols that simply aren't in the 64-bit library (because glibc didn't have 64-bit versions of those symbols until version 2.2.5, so they don't exist with the GLIBC_2.0 version).

To make it work for 32-bit or 64-bit you could do:

#include <math.h>

#if __LP64__
# define SYMVER "GLIBC_2.2.5"
#else
# define SYMVER "GLIBC_2.0"
#endif
#define USE_OLD_SYM(F,V) __asm__(".symver " #F "," #F "@" V)
USE_OLD_SYM(logf,SYMVER);
USE_OLD_SYM(powf,SYMVER);

int main(int argc, char**)
{
return powf(argc, 2.0f) * logf(argc);
}

That uses the right version for the wordsize:

$ g++ m.cc  
$ nm --undefined-only a.out
w __gmon_start__
U __libc_start_main@@GLIBC_2.2.5
U logf@GLIBC_2.2.5
U powf@GLIBC_2.2.5
$ g++ m.cc -m32
$ nm --undefined-only a.out
w __gmon_start__
U __libc_start_main@@GLIBC_2.0
U logf@GLIBC_2.0
U powf@GLIBC_2.0

how do I remove `GLIBC_2.27' requirement at compile time?

I faced the same problem.

/lib/i386-linux-gnu/libm.so.6: version `GLIBC_2.27' not found (required by your_lib.so) 

After searching over the internet, I found some links that could be useful.

Static link:
Link with -static. See How can I link to a specific glibc version?

Using docker: See Can docker solve a problem of mismatched C shared libraries?

Proprietary solution: See https://github.com/wheybags/glibc_version_header

I have decided to follow the first one. So I created a static library for your_lib.so and linked it statically with my binary.

How can I link to a specific glibc version?

You are correct in that glibc uses symbol versioning. If you are curious, the symbol versioning implementation introduced in glibc 2.1 is described here and is an extension of Sun's symbol versioning scheme described here.

One option is to statically link your binary. This is probably the easiest option.

You could also build your binary in a chroot build environment, or using a glibc-new => glibc-old cross-compiler.

According to the http://www.trevorpounds.com blog post Linking to Older Versioned Symbols (glibc), it is possible to to force any symbol to be linked against an older one so long as it is valid by using the same .symver pseudo-op that is used for defining versioned symbols in the first place. The following example is excerpted from the blog post.

The following example makes use of glibc’s realpath, but makes sure it is linked against an older 2.2.5 version.

#include <limits.h>
#include <stdlib.h>
#include <stdio.h>

__asm__(".symver realpath,realpath@GLIBC_2.2.5");
int main()
{
const char* unresolved = "/lib64";
char resolved[PATH_MAX+1];

if(!realpath(unresolved, resolved))
{ return 1; }

printf("%s\n", resolved);

return 0;
}

Make compiling nfsshell claims rpc/rpc.h doesn't exist

Glibc's RPC support was deprecated some years ago but could still be built up to version 2.31, if an appropriate configure option was provided. Debian apparently did this, unlike some other distributions (such as RedHat). In version 2.32 of GNU libc, the legacy support was removed. Here's an extract from the 2.32 announcement:

Deprecated and removed features, and other changes affecting compatibility:

  • Remove configure option --enable-obsolete-rpc. Sun RPC is removed
    from glibc. This includes the rpcgen program, librpcsvc, and the Sun
    RPC header files. Backward compatibility for old programs is kept
    only for architectures and ABIs that have been added in or before
    glibc 2.31. New programs need to use TI-RPC
    http://git.linux-nfs.org/?p=steved/libtirpc.git;a=summary and
    rpcsvc-proto https://github.com/thkukuk/rpcsvc-proto.

  • Remove configure option --enable-obsolete-nsl. libnsl is only built
    as shared library for backward compatibility and the NSS modules "nis"
    and "nisplus" are not built at all and libnsl's headers aren't
    installed. This compatibility is kept only for architectures and ABIs
    that have been added in or before version 2.28. Replacement
    implementations based on TI-RPC, which additionally support IPv6, are
    available from https://github.com/thkukuk/. This change does not
    affect the "compat" NSS module, which does not depended on libnsl
    since 2.27 and thus can be used without NIS.

And here's a Debian package search for tirpc: https://packages.debian.org/search?keywords=tirpc



Related Topics



Leave a reply



Submit