Linux二进制文件通常动态链接到核心系统库(libc).这使得二进制文件的内存占用空间非常小,但依赖于最新库的二进制文件将无法在较旧的系统上运行.相反,链接到旧库的二进制文件将在最新系统上运行愉快.
因此,为了确保我们的应用程序在分发期间具有良好的覆盖率,我们需要找出我们可以支持的最旧的libc并将我们的二进制文件链接起来.
我们应该如何确定我们可以链接到的最旧版本的libc?
我们有一个第三方库,编写时没有考虑多线程或异常处理.我们的主要可执行文件是多线程的并使用异常.
第三方库用于exit()中止程序以解决严重问题(例如"未初始化驱动程序"或"未找到文件").exit()不允许调用多线程应用程序,因为它不能正确关闭线程.另外,我真的不想退出主应用程序,因为它是一个服务器应用程序,并且在许多情况下,主程序可以采取主动的事情来从错误中恢复.
我想基本上exit(int status)用我自己的函数替换系统提供的函数,即
class exit_exception : public runtime_error
{
public: exit_exception(int status)
: runtime_error("exit called with status " + to_string(status)) {}
};
extern "C" void exit(int status) {
throw exit_exception(status);
}
Run Code Online (Sandbox Code Playgroud)
并在我的代码中捕获异常.它似乎有效,但这显然是一种黑客行为,而不是大自然打算exit()使用的方式.不知道我做错了什么?
许多人建议我把它放在一个单独的过程中,但这会打败很多东西.第三方库执行非常高速的数据传输,需要在主应用程序进程中,因为它位于相同的虚拟内存空间中,不用于malloc从作为控制器的FPGA协处理器分配内存.这段代码接近"铁",并且正在挤压内存和PCIe总线的每一点带宽.
我的程序仍可以返回状态代码与返回值的OS int main(),这并没有最终调用exit().否则我会遇到麻烦.
似乎GLIBC 2.28(于2018年8月发布)对fcntl进行了相当激进的更改。定义已更改<fcntl.h>为不再是外部函数,而是#define更改为fcntl64。
其结果是,如果你的系统上使用此glibc的编译代码-如果它使用的fcntl()在所有从2018年八月前--the生成的二进制文件将不能在系统上执行这会影响到相当多的各种应用.. .fcntl()的手册页显示,这是一小部分子功能的入口:
https://linux.die.net/man/2/fcntl
如果您可以告诉链接器所需的GLIBC函数的特定版本,那就太好了。但是我发现最接近的是在另一篇文章的答案中描述的这个技巧:
这有点复杂。 fcntl是不vffcntl带va_list的可变参数。在这种情况下,您无法转发可变参数函数的调用。:-(
当一个程序具有稳定的代码且具有较低的依赖关系时,就很难在当前的Ubuntu上构建它了……然后让可执行文件拒绝在仅一年前(近日)发布的另一个Ubuntu上运行。一个人有什么追索权?
我正在尝试在Linux上构建满足以下条件的可执行文件:
我当前的开发环境是CentOS 7上的gcc4.8.5,glibc 2.17.由于对memcpy的依赖,构建的二进制文件在glibc <2.14的系统上不起作用.
objdump -T main | fgrep GLIBC_2.14
0000000000000000 DF *UND* 0000000000000000 GLIBC_2.14 memcpy
Run Code Online (Sandbox Code Playgroud)
在glibc 2.14中引入了memcpy的重大变化,所以我想强制使用旧版本.我在.so文件中遇到了这个stackoverflow post 与旧版符号版本的链接,但是由于与libstdc ++相关的链接器问题,它对我不起作用.这是我尝试下面的解决方案.
main.cpp中
#include <iostream>
#include <string.h>
int main(int argc, char** argv)
{
char source[] = "once upon a midnight dreary...", dest[4];
memcpy(dest, source, sizeof dest);
std::cout << dest << std::endl;
}
Run Code Online (Sandbox Code Playgroud)
wrap_memcpy.cpp
#include <string.h>
__asm__(".symver memcpy, memcpy@GLIBC_2.2.5");
void *__wrap_memcpy(void *dest, const void *src, size_t n)
{
return memcpy(dest, src, …Run Code Online (Sandbox Code Playgroud) 我正在构建一些需要作为共享对象(.so)的代码.
我的构建机器上的libc可能比已发布的机器更新的问题,所以我想静态地链接它以避免兼容性问题.(我的程序使用memcpy,当它可以低到2.5时显然是GLIBC_2.14的东西).
使用-shared和-static进行编译不起作用,因为crtbeginT.o未使用-fPIC编译.
编辑:可能不是动态链接libc静态和其他库的GCC重复,重新访问?因为这个问题谈论静态链接libc的主要精灵,这是关于静态链接libc的共享对象.
我希望实现如下所示:
我有一个库的多个版本.我使用dlopen()动态加载最新版本的库.然后我想看看该版本中是否存在特定函数(以及类似的返回类型和参数列表).如果它然后打开它,否则回退到以前的版本检查相同.
我在"版本脚本"上看过一些帖子,但我无法使用它.此外,我认为搜索符号表将不是一个解决方案,因为它只检查那里的函数名称.