Прежде всего рассмотрим следующий случай.
Ниже приведена программа:
// 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
из libc.so
, а во втором случае она использует printf
из libext.so
.
Мой вопрос: из исполняемого, полученного как в первом случае, и объектного кода libext (либо как .so, либо .o), можно ли получить исполняемый файл, как во втором дело? Другими словами, можно ли заменить ссылку на libc.so
ссылкой на libext.so
для всех символов, определенных в последнем?
** Обратите внимание, что interposition через LD_PRELOAD не то, что я хочу. Я хочу получить exectuable, который напрямую связан с библиотеками, в которых я нуждаюсь. Я снова подчеркиваю тот факт, что у меня есть только доступ к первому двоичному файлу и к внешнему объекту, который я хочу "статически" вставить **