我在Ubuntu 16.04(适用于 Linux 的 Windows 子系统)上出现以下错误
/lib/x86_64-linux-gnu/libc.so.6: version 'GLIBC_2.25' not found
Run Code Online (Sandbox Code Playgroud)
我已经试过了:
apt-get update
apt-get install libc6
Run Code Online (Sandbox Code Playgroud)
看来,系统有最新的 libc6,因为它输出
libc6 is already the newest version (2.23-0ubuntu10)
Run Code Online (Sandbox Code Playgroud)
但是我想运行的程序失败了。
我如何解决它?
0xC*_*22L 13
现在这个答案可能会有点晚了,但让我尝试向您提供一些有关您在这里遇到的问题的技术背景以及解决它的可能方法。
首先,所评论的是真实的。glibc 是 C 运行时,是 Ubuntu 系统的核心。然而,其他发行版选择其他运行时,程序也可以选择静态链接更自由许可的运行时(例如 musl-libc)。但后一种方法也有其局限性。
根据经验,您可以运行在您的系统上构建的软件。对于某些 BSD 或 Gentoo Linux 等系统来说,这完全没问题,但对于 Debian 和 Ubuntu 等预打包发行版来说,这开始成为一个问题。
您的内核提供了许多系统调用。其中的某个子集是标准化的,有些是特定于您的系统的,即本例中的 GNU/Linux。
大多数系统调用(例如“打开文件”)在 C 运行时中有直接的对应项,但 C 运行时通常会在顶部提供其他内容(例如动态链接的设施...)。
glibc 是一个所谓的共享对象。其他系统称其为动态库或动态链接库。尽管实现和功能不同,但目标基本相同。
术语“共享对象”是指对象代码(“库函数”)在系统中的进程之间共享。
另一个优点是,仅需要更新这个库,而不需要更新与特定版本的库静态链接的每个应用程序。
专有软件(即不是FLOSS 的软件)存在许可问题,因为 glibc 许可证给不愿意披露其专有源代码的人带来了某些“问题”。现在这显然不是您的代码的问题,因为您可以继续构建您自己的.
您遇到的错误:
/lib/x86_64-linux-gnu/libc.so.6: version 'GLIBC_2.25' not found
Run Code Online (Sandbox Code Playgroud)
我经常与那些抱怨 Windows 上的“DLL 地狱”的人开玩笑。Linux 也并没有更好,传统的链接器几乎无法控制链接的符号。
好吧,让我们动手吧。确保您已经binutils安装了 ( apt install binutils),并且我假设您已经安装了标准 Bash shell 并且可以在 中找到它/bin/bash。
我们将从以下调用开始(代替readelf,objdump也可以,但它有自己的命令行参数):
readelf --dyn-syms /bin/bash|grep -P '\WUND\W'
Run Code Online (Sandbox Code Playgroud)
它的作用是列出 Bash 二进制文件中的所有动态符号,然后将输出限制为那些未定义的项目 ( UND)。这将为我们提供 Bash 使用 glibc 的函数列表。GLIBC_2.2.5我们可以通过附加删除所有引用该版本的条目来进一步完善这一点grep -v 'GLIBC_2\.2\.5':
$ readelf --dyn-syms /bin/bash|grep -P '\WUND\W'|grep -v 'GLIBC_2\.2\.5'
0: 0000000000000000 0 NOTYPE LOCAL DEFAULT UND
2: 0000000000000000 0 FUNC GLOBAL DEFAULT UND __ctype_toupper_loc@GLIBC_2.3 (3)
3: 0000000000000000 0 FUNC GLOBAL DEFAULT UND tgetflag@NCURSES_TINFO_5.0.19991023 (4)
6: 0000000000000000 0 FUNC GLOBAL DEFAULT UND __snprintf_chk@GLIBC_2.3.4 (5)
14: 0000000000000000 0 FUNC GLOBAL DEFAULT UND __vfprintf_chk@GLIBC_2.3.4 (5)
20: 0000000000000000 0 NOTYPE WEAK DEFAULT UND _ITM_deregisterTMCloneTab
22: 0000000000000000 0 FUNC GLOBAL DEFAULT UND tgetent@NCURSES_TINFO_5.0.19991023 (4)
25: 0000000000000000 0 FUNC GLOBAL DEFAULT UND tputs@NCURSES_TINFO_5.0.19991023 (4)
37: 0000000000000000 0 FUNC GLOBAL DEFAULT UND faccessat@GLIBC_2.4 (6)
50: 0000000000000000 0 FUNC GLOBAL DEFAULT UND tgoto@NCURSES_TINFO_5.0.19991023 (4)
60: 0000000000000000 0 FUNC GLOBAL DEFAULT UND eaccess@GLIBC_2.4 (6)
63: 0000000000000000 0 FUNC GLOBAL DEFAULT UND __stack_chk_fail@GLIBC_2.4 (6)
72: 0000000000000000 0 FUNC GLOBAL DEFAULT UND __fdelt_chk@GLIBC_2.15 (7)
80: 0000000000000000 0 FUNC GLOBAL DEFAULT UND tgetnum@NCURSES_TINFO_5.0.19991023 (4)
98: 0000000000000000 0 FUNC GLOBAL DEFAULT UND tgetstr@NCURSES_TINFO_5.0.19991023 (4)
101: 0000000000000000 0 FUNC GLOBAL DEFAULT UND __asprintf_chk@GLIBC_2.8 (8)
104: 0000000000000000 0 FUNC GLOBAL DEFAULT UND __memmove_chk@GLIBC_2.3.4 (5)
106: 0000000000000000 0 FUNC GLOBAL DEFAULT UND __memcpy_chk@GLIBC_2.3.4 (5)
108: 0000000000000000 0 NOTYPE WEAK DEFAULT UND __gmon_start__
114: 0000000000000000 0 FUNC GLOBAL DEFAULT UND memcpy@GLIBC_2.14 (9)
138: 0000000000000000 0 FUNC GLOBAL DEFAULT UND regexec@GLIBC_2.3.4 (5)
145: 0000000000000000 0 FUNC GLOBAL DEFAULT UND __vsnprintf_chk@GLIBC_2.3.4 (5)
147: 0000000000000000 0 FUNC GLOBAL DEFAULT UND __strncpy_chk@GLIBC_2.3.4 (5)
153: 0000000000000000 0 FUNC GLOBAL DEFAULT UND __strcpy_chk@GLIBC_2.3.4 (5)
157: 0000000000000000 0 FUNC GLOBAL DEFAULT UND __printf_chk@GLIBC_2.3.4 (5)
160: 0000000000000000 0 FUNC GLOBAL DEFAULT UND __longjmp_chk@GLIBC_2.11 (11)
195: 0000000000000000 0 FUNC GLOBAL DEFAULT UND __fprintf_chk@GLIBC_2.3.4 (5)
198: 0000000000000000 0 NOTYPE WEAK DEFAULT UND _ITM_registerTMCloneTable
215: 0000000000000000 0 FUNC GLOBAL DEFAULT UND __ctype_tolower_loc@GLIBC_2.3 (3)
216: 0000000000000000 0 FUNC GLOBAL DEFAULT UND __ctype_b_loc@GLIBC_2.3 (3)
219: 0000000000000000 0 FUNC GLOBAL DEFAULT UND __sprintf_chk@GLIBC_2.3.4 (5)
Run Code Online (Sandbox Code Playgroud)
2.2.5 版本是第一个支持 x86-64 作为架构的版本,这就是我们对它不感兴趣的原因。第一个可用版本永远不会造成问题。
但是,如果您希望在“仅”有 glibc 2.14 的系统上使用此 Bash 二进制文件,它将无法工作,因为__fdelt_chk@GLIBC_2.15至少需要 2.15 版本。
插曲:符号版本控制
@GLIBC_2.3.4符号名称上的 (etc.) 后缀描述版本范围(另请参阅此处)。这使得 ELF 共享对象能够支持符号的多个版本。例如,函数foo()在库的 1.0 版本中可能采用 2 个参数,但在 2.x 版本范围中采用 3 个参数。动态链接到这些符号的软件包含符号版本这一事实意味着它将始终链接到函数的适当版本。然而,缺点就是你所遇到的。如果使用的符号之一需要比您系统上可用的库版本更新的库版本,则在具有较新 glibc(或实际上也使用符号版本控制的任何其他库)的系统上链接的软件将无法在您(较旧的)系统上运行。
“克服”这个问题的经典方法始终是建立在一个足够老的系统上,就库版本而言提供足够低的共同点。这甚至允许您在某种程度上运行在一个发行版上构建的二进制文件,以便在一系列其他发行版上运行。缺点是这意味着旧的编译器、旧的工具链、旧的库(因为库不仅仅是 C 运行时)。
存在某些替代方案(见下文),但它们都要求您准确分析您想要什么。例如,静态链接到 musl-libc - 具有更自由的许可条款 - 如果您的程序提供插件接口并与插件交换缓冲区,则该链接将不起作用...在这种情况下,动态链接到相同的 C 运行时非常重要。此外,由于
sbrk.
LD_LIBRARY_PATH其设置为指向更新的glibc。memcpyglibc 2.14 的新功能是 a GNU_IFUNC,这意味着一旦在运行时,将选择最有效的版本(例如针对特定处理器模型进行优化!)。这与简单地提供对函数(要重新定位)的直接引用的经典方法相反。这样做的主要结论是,在这种特殊情况下,您不能只修改符号名称,因为这种形式的“延迟加载”机制的 ABI 与所述符号的旧版本的 ABI 不同。
如果您确实对链接器的内部工作原理感兴趣,您可以阅读一本有关该主题的书或参考 Ian Lance Taylor 的优秀文章系列,您可以在此处找到其中的概述。
| 归档时间: |
|
| 查看次数: |
20767 次 |
| 最近记录: |