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
Avoid Daemon Running in Dedicated CPU Cores
Using Winscp to Grab a File Through a Tunnel
Difference Between $() and () in Bash
How to Get The Output of at Command in Current or Another Terminal Window
How to Distinguish Between Different Operating System Distros in Node.Js
How to 'Chmod -R +W' with Ant, Files and Folders
Linux: How to Check The Largest Contiguous Address Range Available to a Process
How Event Packet Header Is Getiing in Hci_Send_Req API Implementation
Starting Multiple Firefox Profiles with Batch File in Linux
Building Robert Nelson's Linux Kernel into Yocto(Daisy) for Beaglebone Black
Error: You Must Install at Least One Postgresql-Client-<Version> Package
Environment Variables in Symbolic Links
Find Syslog Max Message Length