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

Ama*_*nda 7 linux debian glibc fedora c++11

我相信其他Fedora 28用户会知道,操作系统的glibc最近更新为glibc 2.27.在许多其他事情中,2.27增加了logf()和powf()的新实现.这导致我的应用程序无法在具有旧glibc(例如Debian)的发行版上运行.在Debian上调用应用程序时,会产生以下错误:

  • ...找不到libm.so.6版本GLIBC-2.27(./app_name要求)

我使用以下过程跟踪符号到logf和powf:

objdump -T ./app_name | grep GLIBC_2.27
Run Code Online (Sandbox Code Playgroud)

其中给出了以下输出:

0000000000000000      DF *UND*  0000000000000000  GLIBC_2.27  powf
0000000000000000      DF *UND*  0000000000000000  GLIBC_2.27  logf
Run Code Online (Sandbox Code Playgroud)

然后...

objdump -T /lib/libm.so.6 | grep -w logf
objdump -T /lib/libm.so.6 | grep -w powf
Run Code Online (Sandbox Code Playgroud)

其中给出了以下输出:

000397a0 g    DF .text  00000135  GLIBC_2.27  logf
00010430 g    DF .text  0000009e (GLIBC_2.0)  logf
Run Code Online (Sandbox Code Playgroud)

和...

000397a0 g    DF .text  00000135  GLIBC_2.27  powf
00010430 g    DF .text  0000009e (GLIBC_2.0)  powf
Run Code Online (Sandbox Code Playgroud)

因此,有了powf()和logf()也在GLIBC-2.0中实现的信息,我将以下内容添加到我的项目中(在main()之上)并重新编译.

__asm__(".symver logf,logf@GLIBC_2.0");
__asm__(".symver powf,powf@GLIBC_2.0"); 
Run Code Online (Sandbox Code Playgroud)

不幸的是,我的项目仍在使用GLIBC-2.27的powf和logf.实际上,我为Debian分发二进制文件非常重要,如果可以避免,我宁愿不必编译该分发版.

从历史上看,我已成功将此过程用于libc.so.6中的符号,但不是libm.so.6.我应该为libm.so.6做些不同的事吗?

显然,我在这里遗漏了一些东西,所以我将不胜感激任何提供的帮助.

非常感谢

阿曼达

Jon*_*ely 6

我认为问题是你曾经objdump找到32位libm的符号版本,我假设你实际上正在构建一个64位应用程序.在Fedora 28容器中,如果我查看64位库,那么我会看到这些版本:

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
Run Code Online (Sandbox Code Playgroud)

这符合预期:

#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);
}
Run Code Online (Sandbox Code Playgroud)

它使用64位库中的版本:

$ 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
Run Code Online (Sandbox Code Playgroud)

所以我认为问题是你试图链接到那些不在64位库中的符号(因为glibc在版本2.2.5之前没有这些符号的64位版本,所以它们不会与GLIBC_2.0版本一起存在).

要使其适用于32位或64位,您可以:

#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);
}
Run Code Online (Sandbox Code Playgroud)

这使用了正确的版本:

$ 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
Run Code Online (Sandbox Code Playgroud)