LD_PRELOAD使用gcc或g ++编译.so

时间:2016-06-17 07:19:07

标签: sockets gcc ld-preload

我有一个套接字API的包装器,我使用LD_PRELOAD在我的应用程序之前预加载。但是,当我使用g ++编译我的.so包装器库时,它不起作用,即替代了套接字实现的glibc版本。

这是我编译包装器.so库(其中之一)的方法:

gcc -Wall -fPIC -shared socket_hooks.c -o socket_hooks.so
or
g++ -Wall -fPIC -shared socket_hooks.c -o socket_hooks.so

这是我编译和运行我的udp客户端的方法:

g++ -Wall udp_client.cpp  -o udp_client
LD_PRELOAD=./socket_hooks.so ./udp_client

现在当我启用debug(export LD_DEBUG = all)并使用 gcc (工作版)编译的例子运行.so时,我看到:

 17278: symbol=socket;  lookup in file=./udp_client [0]
 17278: symbol=socket;  lookup in file=./socket_hooks.so [0]
 17278: binding file ./udp_client [0] to ./socket_hooks.so [0]: normal symbol `socket' [GLIBC_2.2.5]

当我使用 g ++ 编译.so时,我看到以下内容:

 17285: symbol=socket;  lookup in file=./udp_client [0]
 17285: symbol=socket;  lookup in file=./socket_hooks.so [0]
 17285: symbol=socket;  lookup in file=/lib/x86_64-linux-gnu/libc.so.6 [0]
 17285: binding file ./udp_client [0] to /lib/x86_64-linux-gnu/libc.so.6 [0]: normal symbol `socket' [GLIBC_2.2.5]

在这两种情况下" socket"找到符号,但在后一种情况下,它没有被拾取,而是使用了libc。

你能解释一下这里发生了什么吗?

1 个答案:

答案 0 :(得分:1)

使用C ++编译器编译模块时,您的符号会被修改以支持函数重载,例如socket可能会转换为_Z10socketiii。这就是为什么运行时加载程序找不到它 - 它正在寻找socket,而不是_Z10socketiii

为了禁用名称修改,您必须使用extern "C"使用C链接声明函数,可能与__cplusplus宏一起使用,以便与C编译器保持兼容:

#ifdef __cplusplus
extern "C" {
#endif

int socket(int domain, int type, int protocol);

#ifdef __cplusplus
}
#endif

或者,按每个符号设置链接:

#ifdef __cplusplus
#define DONT_MANGLE_ME extern "C"
#else
#define DONT_MANGLE_ME
#endif

DONT_MANGLE_ME int socket(int domain, int type, int protocol);