有没有办法"静态地"将共享的.so(或.o)库插入到可执行文件中?

Mar*_*tin 14 c c++ gcc shared-libraries

首先,请考虑以下情况.

以下是一个程序:

// test.cpp
extern "C" void printf(const char*, ...);

int main() {
        printf("Hello");
}
Run Code Online (Sandbox Code Playgroud)

下面是一个图书馆:

// ext.cpp (the external library)
#include <iostream>

extern "C" void printf(const char* p, ...);

void printf(const char* p, ...) {
        std::cout << p << " World!\n";
}
Run Code Online (Sandbox Code Playgroud)

现在我可以用两种不同的方式编译上面的程序和库.

第一种方法是在不链接外部库的情况下编译程序:

$ g++ test.cpp -o test
$ ldd test
        linux-gate.so.1 =>  (0xb76e8000)
        libc.so.6 => /lib/i386-linux-gnu/libc.so.6 (0xb7518000)
        /lib/ld-linux.so.2 (0xb76e9000)
Run Code Online (Sandbox Code Playgroud)

如果我运行上面的程序,它将打印:

$ ./test 
Hello
Run Code Online (Sandbox Code Playgroud)

第二种方法是使用指向外部库的链接编译程序:

$ g++ -shared -fPIC ext.cpp -o libext.so
$ g++ test.cpp -L./ -lext  -o test
$ export LD_LIBRARY_PATH=./
$ ldd test
        linux-gate.so.1 =>  (0xb773e000)
        libext.so => ./libext.so (0xb7738000)
        libc.so.6 => /lib/i386-linux-gnu/libc.so.6 (0xb756b000)
        libstdc++.so.6 => /usr/lib/i386-linux-gnu/libstdc++.so.6 (0xb7481000)
        /lib/ld-linux.so.2 (0xb773f000)
        libm.so.6 => /lib/i386-linux-gnu/libm.so.6 (0xb743e000)
        libgcc_s.so.1 => /lib/i386-linux-gnu/libgcc_s.so.1 (0xb7421000)
$ ./test
Hello World!
Run Code Online (Sandbox Code Playgroud)

正如您所看到的,在第一种情况下程序使用printffrom libc.so,而在第二种情况下它使用printffrom libext.so.

我的问题是:从第一种情况下获得的可执行文件和libext的目标代码(作为.so或.o),是否有可能像第二种情况一样获得可执行文件?换句话说,是否有可能将链接替换为后者中定义的所有符号libc.so的链接libext.so

**注意通过LD_PRELOAD的插入不是我想要的.我想获得一个与我需要的库直接相关的exectuable.我再次强调,我只能访问第一个二进制文件和外部对象,我想"静态地"插入**

Max*_*kin 8

有可能的.了解共享库插入:

编译使用动态库的程序时,二进制文件中包含未定义符号列表,以及程序链接的库列表.符号和库之间没有对应关系; 这两个列表只是告诉加载器要加载哪些库以及需要解析哪些符号.在运行时,使用提供它的第一个库来解析每个符号.这意味着如果我们可以在其他库之前获取包含我们的包装器函数的库,程序中的未定义符号将被解析为包装器而不是实际函数.