我正在尝试在我的最终g ++链接命令中使用-Wl
,-wrap=sendto
-Wl
,-wrap
,sendto
来链接我的应用以替换标准 sendto
与我自己的功能。
我用以下代码编译以下源代码:
gcc -c -o wrap.o wrap.c
并在最终g ++命令中包含wrap.o,该命令链接应用程序(应用程序的其余部分是C ++,因此使用g ++):
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
ssize_t __real_sendto(int, const void *, size_t, int, const struct sockaddr *, socklen_t);
ssize_t __wrap_sendto
(
int sockfd,
const void *buf,
size_t len,
int flags,
const struct sockaddr *dest_addr,
socklen_t addrlen
)
{
printf("my wrap sendto ...\n");
return __real_sendto(sockfd, buf, len, flags, dest_addr, addrlen);
}
当我在自己的源代码中使用sendto
时,包装器实际上已经使用了,但我在最终的g ++命令中使用sendto链接的所有第三方共享对象仍然使用系统sendto,即不是我的包装器。如何获得我在整个过程中使用的sendto包装器?
我还尝试了LD_PRELOAD
方法,其中包含sendto和dlsym(RTLD_NEXT)
,但这也没有用。
如何确定第三方库为何继续直接使用libc sendto?
当我使用ldd找到我编译的应用程序的所有共享对象依赖项,然后objdump -T
在每一个上面greto for sendto时,我得到所有第三方共享对象的UND(未定义)。但是,定义它的共享对象是:
/lib64/libpthread.so.0
000000000000ed80 w DF .text 0000000000000064 GLIBC_2.2.5 sendto
/lib64/libc.so.6
00000000000e98d0 w DF .text 0000000000000064 GLIBC_2.2.5 sendto
我在sendto.c
上的glibc git
中看到以下内容:
weak_alias (__libc_sendto, sendto)
weak_alias (__libc_sendto, __sendto)
答案 0 :(得分:0)
--wrap sendto
选项未在二进制文件中定义sendto
符号。相反,它会使用__wrap_sendto
替换对此符号的引用,并将sendto
保留为未定义。
换句话说,您的可执行文件不提供sendto
,因此运行时符号解析从glibc中选择一个。
要解决此问题,您需要在可执行文件中定义sendto
。再次尝试dlsym
,但这次没有LD_PRELOAD
/ shim库:
ssize_t sendto
(
int sockfd,
const void *buf,
size_t len,
int flags,
const struct sockaddr *dest_addr,
socklen_t addrlen
)
{
ssize_t (*libc_sendto)(int, const void *, size_t, int, const struct sockaddr *, socklen_t)
= dlsym(RTLD_NEXT, "sendto");
printf("my wrap sendto ...\n");
return libc_sendto(sockfd, buf, len, flags, dest_addr, addrlen);
}
如果第三方图书馆在此之后发现错误的sendto
,那么我只会看到一种(不太可能)的可能性。共享库与-Bsymbolic
/ -Bsymbolic-functions
相关联,并提供自己的sendto
。
此外,由于您已将此问题标记为g++
,因此请确保您的符号名称不会受到损害 - 请使用extern "C"
。
答案 1 :(得分:0)
我最终设法弄清楚这里发生了什么。即使正在调用strace状态sendto:
Comparator
事实上发生的是发送(...)被调用(可能因为0,null,0最后三个参数)。我为发送(...)制作拦截器的那一刻起作用了。