首先,考虑以下情况。
下面是一个程序:
// test.cpp
extern "C" void printf(const char*, ...);
int main() {
printf("Hello");
}
下面是一个库:
// ext.cpp (the external library)
#include <iostream>
extern "C" void printf(const char* p, ...);
void printf(const char* p, ...) {
std::cout << p << " World!\n";
}
现在我可以用两种不同的方式编译上面的程序和库。
第一种方法是编译程序而不链接外部库:
$ 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)
如果我运行上面的程序,它将打印:
$ ./test
Hello
第二种方法是编译带有外部库链接的程序:
$ 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!
如您所见,在第一种情况下,程序使用printf
from libc.so
,而在第二种情况下,它使用printf
from libext.so
。
我的问题是:从第一种情况下获得的可执行文件和libext的目标代码(.so或.o),是否有可能获得第二种情况下的可执行文件?换句话说,是否可以将链接替换为链接到后者中定义的所有符号libc.so
的链接?libext.so
**请注意,通过 LD_PRELOAD 插入不是我想要的。我想获得一个直接链接到我需要的库的可执行文件。我再次强调这一事实,我只能访问第一个二进制文件和我想“静态”插入的外部对象**