我希望代码能够使用某个自编写的库来运行应用程序,而则不需要。所以我使用__attribute__ ((weak))
并在需要时预加载库。我需要能够在不重新编译的情况下做到这一点。如果我静态链接库,一切正常。
此外,库是用C ++编写的,而使用它的应用程序可以是C ++或C.
我归结为:
库标题test_lib.h
:
#ifdef __cplusplus
extern "C"
#endif
void test_func() __attribute__ ((weak));
库实现test_lib.cpp
:
#include "test_lib.h"
#include <iostream>
extern "C"
void test_func()
{
std::cout << "in test_func\n";
}
C测试test_main.c
:
#include <stdio.h>
#include "test_lib.h"
int main(void)
{
if (test_func){ printf("+\n"); }
else{ printf("-\n"); }
return 0;
}
C ++测试test_main_cpp.cpp
:
#include <iostream>
#include "test_lib.h"
int main(void)
{
if (test_func){ std::cout << "+\n"; }
else{ std::cout << "-\n"; }
return 0;
}
为方便起见,编译和运行脚本:
#!/bin/bash
g++ -shared -fPIC test_lib.cpp -o libtest.so
gcc test_main.c -o test_c
g++ test_main_cpp.cpp -o test_cpp
# output should be "-"
./test_c
./test_cpp
# output should be "+"
LD_PRELOAD=libtest.so ./test_c
LD_PRELOAD=libtest.so ./test_cpp
预期输出为:
-
-
+
+
我得到的是:
-
-
-
-
最后还有一些额外的信息:
$ uname -a
Linux bermuda-iii 3.8.6-1-ARCH #1 SMP PREEMPT Sat Apr 6 07:27:01 CEST 2013 x86_64 GNU/Linux
$ gcc --version
gcc (GCC) 4.8.0
$ nm libtest.so | grep -i func
0000000000000858 W test_func
$ nm test_c | grep -i func
w test_func
$ nm test_cpp | grep -i func
w test_func
所以:(de)mangling似乎工作正常,符号test_func
对于可执行文件是已知的。但是`LD_PRELOAD'似乎不起作用。
我错过了什么?
答案 0 :(得分:1)
诀窍是确保应用程序也被编译为与位置无关的代码,否则在运行时无法替换该符号:
在链接可执行文件的位置,您需要执行以下操作:
gcc -fPIC test_main.c -o test_c
或
g++ test_main_cpp.cpp -o test_cpp
e.g。
$ gcc test_main.c -o test_c -fPIC
$ ./test_c
-
$ LD_PRELOAD=`pwd`/libtest_lib.so ./test_c
+
通过将主可执行文件编译为位置无关代码,它允许在运行时由覆盖库替换弱符号。