Build “;版本'GLIBC_2.16';未找到”;将生成环境升级到Ubuntu 14.4后出现目标主机错误

Build “;版本'GLIBC_2.16';未找到”;将生成环境升级到Ubuntu 14.4后出现目标主机错误,build,glibc,Build,Glibc,将构建环境升级到Ubuntu 14.4后,主可执行文件拒绝在具有较旧Linux版本的主机上启动,并显示以下消息: /lib/i386 linux gnu/libc.so.6:找不到版本'GLIBC_2.16' (由/可执行文件名称要求) 为了将我的包安全地分发给具有较旧的Glibc的主机,我是否应该尝试: 静态链接到libc 在生成计算机上降级libc 安装旧的glibc和一个Ubuntu分发版goes? 用什么 注: -我不需要使用任何来自旧版本Ubuntu的二进制文件 -我不需要在较旧的

将构建环境升级到Ubuntu 14.4后,主可执行文件拒绝在具有较旧Linux版本的主机上启动,并显示以下消息:

/lib/i386 linux gnu/libc.so.6:找不到版本'GLIBC_2.16' (由/可执行文件名称要求)

为了将我的包安全地分发给具有较旧的Glibc的主机,我是否应该尝试:

  • 静态链接到libc
  • 在生成计算机上降级libc
  • 安装旧的glibc和一个Ubuntu分发版goes? 用什么
注: -我不需要使用任何来自旧版本Ubuntu的二进制文件
-我不需要在较旧的Ubuntu版本上构建,经过长时间的调查,我终于找到了解决问题的方法

首先,我查看了可执行文件的依赖关系:

ldd -v <executable_name>
Version information:
products/<executable>:
    ld-linux.so.2 (GLIBC_2.3) => /lib/ld-linux.so.2
    librt.so.1 (GLIBC_2.2) => /lib/i386-linux-gnu/librt.so.1
    libdl.so.2 (GLIBC_2.0) => /lib/i386-linux-gnu/libdl.so.2
    libdl.so.2 (GLIBC_2.1) => /lib/i386-linux-gnu/libdl.so.2
    libpthread.so.0 (GLIBC_2.2) => /lib/i386-linux-gnu/libpthread.so.0
    libpthread.so.0 (GLIBC_2.3.2) => /lib/i386-linux-gnu/libpthread.so.0
    libpthread.so.0 (GLIBC_2.1) => /lib/i386-linux-gnu/libpthread.so.0
    libpthread.so.0 (GLIBC_2.0) => /lib/i386-linux-gnu/libpthread.so.0
    libpulse.so.0 (PULSE_0) => /usr/lib/i386-linux-gnu/libpulse.so.0
    libsndfile.so.1 (libsndfile.so.1.0) => /usr/lib/i386-linux-gnu/libsndfile.so.1
    libc.so.6 (GLIBC_2.15) => /lib/i386-linux-gnu/libc.so.6
    libc.so.6 (GLIBC_2.11) => /lib/i386-linux-gnu/libc.so.6
    libc.so.6 (GLIBC_2.1.3) => /lib/i386-linux-gnu/libc.so.6
    libc.so.6 (GLIBC_2.2.4) => /lib/i386-linux-gnu/libc.so.6
    libc.so.6 (GLIBC_2.4) => /lib/i386-linux-gnu/libc.so.6
    libc.so.6 (GLIBC_2.1) => /lib/i386-linux-gnu/libc.so.6
    libc.so.6 (GLIBC_2.3) => /lib/i386-linux-gnu/libc.so.6
    libc.so.6 (GLIBC_2.2) => /lib/i386-linux-gnu/libc.so.6
    libc.so.6 (GLIBC_2.7) => /lib/i386-linux-gnu/libc.so.6
    libc.so.6 (GLIBC_2.0) => /lib/i386-linux-gnu/libc.so.6
    libc.so.6 (GLIBC_2.3.4) => /lib/i386-linux-gnu/libc.so.6
尽管Glibc使用所谓的_符号版本控制u,但此特定函数仅在中添加

因此,我尝试调查是什么导致了调试版本和发布版本之间的差异

设置时,Cmake定义确定编译器标志的内部变量。对于GCC 4.8.4,它们是:

  • 调试:-g
  • 发布:-NDEBUG-O3
Glibc poll.h包括poll2.h,它包含棘手的poll,但在Glibc 2.16中不可用。这包括在_使用_加强_级别定义下

根据发布版本中的Linux手册页(见下面的引文),由于-O3级别,我的-D_FORTIFY_SOURCE=2

注意:在Ubuntu 8.10及更高版本中,-D_FORTIFY_SOURCE=2由 默认值,并在-O设置为2或更高时激活。这 为多个libc启用额外的编译时和运行时检查 功能。要禁用,请指定-U\U加强\U源或 -D_加固_源=0

_FORTIFY_SOURCE(自glibc 2.3.4起)定义此宏会导致执行一些轻量级检查以检测某些缓冲区溢出 使用各种字符串和内存操作时出错 功能。并不是所有的缓冲区溢出都被检测到,只是一些溢出 常见案例。在当前实现中,将添加检查 对于对memcpy(3)、mempcpy(3)、memmove(3)、memset(3)、stpcpy(3)的调用, strcpy(3)、strncpy(3)、strcat(3)、strnccat(3)、sprintf(3)、snprintf(3), vsprintf(3)、vsnprintf(3)和get(3)。如果_FORTIFY_SOURCE设置为 1,使用编译器优化级别1(gcc-O1)及以上,检查 不应改变执行符合性程序的行为。 将_FORTIFY_SOURCE设置为2时,会添加一些检查,但有些 一致性程序可能会失败。可以执行一些检查 在编译时,并导致编译器警告;其他支票需要 在运行时放置,如果检查失败,将导致运行时错误。 使用此宏需要编译器支持,可从gcc(1)获得 从4.0版开始

或者只是使用

man -K _FORTIFY_SOURCE
我检查了可执行文件包含的每个静态库,它们的代码使用poll函数,最终找到了它:

objdump -t  lib.a | grep poll
00000000         *UND*  00000000 Curl_poll
00000000 l    d  .text.Curl_poll    00000000 .text.Curl_poll
00000000         *UND*  00000000 poll
00000000         *UND*  00000000 __poll_chk
00000000 g     F .text.Curl_poll    0000025c Curl_poll
通过将-U_FORTIFY_SOURCE添加到目标CmakeLists.txt中的编译器标志,可以禁用此优化。这消除了最近检测到的任何GLIBC2.16依赖项:

ldd -v <executable_name>
Version information:
products/<executable>:
    ld-linux.so.2 (GLIBC_2.3) => /lib/ld-linux.so.2
    librt.so.1 (GLIBC_2.2) => /lib/i386-linux-gnu/librt.so.1
    libdl.so.2 (GLIBC_2.0) => /lib/i386-linux-gnu/libdl.so.2
    libdl.so.2 (GLIBC_2.1) => /lib/i386-linux-gnu/libdl.so.2
    libpthread.so.0 (GLIBC_2.2) => /lib/i386-linux-gnu/libpthread.so.0
    libpthread.so.0 (GLIBC_2.3.2) => /lib/i386-linux-gnu/libpthread.so.0
    libpthread.so.0 (GLIBC_2.1) => /lib/i386-linux-gnu/libpthread.so.0
    libpthread.so.0 (GLIBC_2.0) => /lib/i386-linux-gnu/libpthread.so.0
    libpulse.so.0 (PULSE_0) => /usr/lib/i386-linux-gnu/libpulse.so.0
    libsndfile.so.1 (libsndfile.so.1.0) => /usr/lib/i386-linux-gnu/libsndfile.so.1
    libc.so.6 (GLIBC_2.15) => /lib/i386-linux-gnu/libc.so.6
    libc.so.6 (GLIBC_2.11) => /lib/i386-linux-gnu/libc.so.6
    libc.so.6 (GLIBC_2.1.3) => /lib/i386-linux-gnu/libc.so.6
    libc.so.6 (GLIBC_2.2.4) => /lib/i386-linux-gnu/libc.so.6
    libc.so.6 (GLIBC_2.4) => /lib/i386-linux-gnu/libc.so.6
    libc.so.6 (GLIBC_2.1) => /lib/i386-linux-gnu/libc.so.6
    libc.so.6 (GLIBC_2.3) => /lib/i386-linux-gnu/libc.so.6
    libc.so.6 (GLIBC_2.2) => /lib/i386-linux-gnu/libc.so.6
    libc.so.6 (GLIBC_2.7) => /lib/i386-linux-gnu/libc.so.6
    libc.so.6 (GLIBC_2.0) => /lib/i386-linux-gnu/libc.so.6
    libc.so.6 (GLIBC_2.3.4) => /lib/i386-linux-gnu/libc.so.6
.c.o包括poll.h和poll2.h,其内容如下:

# 1 "/usr/include/i386-linux-gnu/bits/poll2.h" 1 3 4 
# 24 "/usr/include/i386-linux-gnu/bits/poll2.h" 3 4 


extern int __poll_alias (struct pollfd *__fds, nfds_t __nfds, int __timeout) __asm__ ("" "poll") 
                               ; 
extern int __poll_chk (struct pollfd *__fds, nfds_t __nfds, int __timeout, 
         unsigned int __fdslen); 
extern int __poll_chk_warn (struct pollfd *__fds, nfds_t __nfds, int __timeout, unsigned int __fdslen) __asm__ ("" "__poll_chk") 


  __attribute__((__warning__ ("poll called with fds buffer too small file nfds entries"))); 

extern __inline __attribute__ ((__always_inline__)) __attribute__ ((__gnu_inline__)) __attribute__ ((__artificial__)) int 
poll (struct pollfd *__fds, nfds_t __nfds, int __timeout) 
{ 
  if (__builtin_object_size (__fds, 2 > 1) != (unsigned int) -1) 
    { 
      if (! __builtin_constant_p (__nfds)) 
 return __poll_chk (__fds, __nfds, __timeout, __builtin_object_size (__fds, 2 > 1)); 
      else if (__builtin_object_size (__fds, 2 > 1) / sizeof (*__fds) < __nfds) 
 return __poll_chk_warn (__fds, __nfds, __timeout, __builtin_object_size (__fds, 2 > 1)); 
    } 

  return __poll_alias (__fds, __nfds, __timeout); 
}
到目前为止,我无法解释为什么其他库中没有添加刁钻的uuu poll_chk符号。但现在,我的二进制文件在任何目标Linux主机上运行。

可能重复
Version information:
products/<executable>:
    ld-linux.so.2 (GLIBC_2.3) => /lib/ld-linux.so.2
    librt.so.1 (GLIBC_2.2) => /lib/i386-linux-gnu/librt.so.1
    libdl.so.2 (GLIBC_2.0) => /lib/i386-linux-gnu/libdl.so.2
    libdl.so.2 (GLIBC_2.1) => /lib/i386-linux-gnu/libdl.so.2
    libpthread.so.0 (GLIBC_2.2) => /lib/i386-linux-gnu/libpthread.so.0
    libpthread.so.0 (GLIBC_2.3.2) => /lib/i386-linux-gnu/libpthread.so.0
    libpthread.so.0 (GLIBC_2.1) => /lib/i386-linux-gnu/libpthread.so.0
    libpthread.so.0 (GLIBC_2.0) => /lib/i386-linux-gnu/libpthread.so.0
    libpulse.so.0 (PULSE_0) => /usr/lib/i386-linux-gnu/libpulse.so.0
    libsndfile.so.1 (libsndfile.so.1.0) => /usr/lib/i386-linux-gnu/libsndfile.so.1
    libc.so.6 (GLIBC_2.15) => /lib/i386-linux-gnu/libc.so.6
    libc.so.6 (GLIBC_2.11) => /lib/i386-linux-gnu/libc.so.6
    libc.so.6 (GLIBC_2.1.3) => /lib/i386-linux-gnu/libc.so.6
    libc.so.6 (GLIBC_2.2.4) => /lib/i386-linux-gnu/libc.so.6
    libc.so.6 (GLIBC_2.4) => /lib/i386-linux-gnu/libc.so.6
    libc.so.6 (GLIBC_2.1) => /lib/i386-linux-gnu/libc.so.6
    libc.so.6 (GLIBC_2.3) => /lib/i386-linux-gnu/libc.so.6
    libc.so.6 (GLIBC_2.2) => /lib/i386-linux-gnu/libc.so.6
    libc.so.6 (GLIBC_2.7) => /lib/i386-linux-gnu/libc.so.6
    libc.so.6 (GLIBC_2.0) => /lib/i386-linux-gnu/libc.so.6
    libc.so.6 (GLIBC_2.3.4) => /lib/i386-linux-gnu/libc.so.6
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -E")
# 1 "/usr/include/i386-linux-gnu/bits/poll2.h" 1 3 4 
# 24 "/usr/include/i386-linux-gnu/bits/poll2.h" 3 4 


extern int __poll_alias (struct pollfd *__fds, nfds_t __nfds, int __timeout) __asm__ ("" "poll") 
                               ; 
extern int __poll_chk (struct pollfd *__fds, nfds_t __nfds, int __timeout, 
         unsigned int __fdslen); 
extern int __poll_chk_warn (struct pollfd *__fds, nfds_t __nfds, int __timeout, unsigned int __fdslen) __asm__ ("" "__poll_chk") 


  __attribute__((__warning__ ("poll called with fds buffer too small file nfds entries"))); 

extern __inline __attribute__ ((__always_inline__)) __attribute__ ((__gnu_inline__)) __attribute__ ((__artificial__)) int 
poll (struct pollfd *__fds, nfds_t __nfds, int __timeout) 
{ 
  if (__builtin_object_size (__fds, 2 > 1) != (unsigned int) -1) 
    { 
      if (! __builtin_constant_p (__nfds)) 
 return __poll_chk (__fds, __nfds, __timeout, __builtin_object_size (__fds, 2 > 1)); 
      else if (__builtin_object_size (__fds, 2 > 1) / sizeof (*__fds) < __nfds) 
 return __poll_chk_warn (__fds, __nfds, __timeout, __builtin_object_size (__fds, 2 > 1)); 
    } 

  return __poll_alias (__fds, __nfds, __timeout); 
}
objdump -t  lib.a | grep poll 
00000000 UND    00000000 poll