ld wrap和LD_PRELOAD都无法拦截系统调用

问题描述 投票:0回答:2

我试图在我的最终g ++链接命令中使用-Wl-wrap=sendto -Wl-wrapsendto链接我的应用程序以用我自己的替换标准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在每一个grepping 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)
gcc g++ ld sendto
2个回答
0
投票

--wrap sendto选项未在二进制文件中定义sendto符号。相反,它用__wrap_sendto替换对这个符号的引用,并留下sendto undefined。

换句话说,您的可执行文件不提供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"


0
投票

我最终设法弄清楚这里发生了什么。即使正在调用strace状态sendto:

[pid 17956] sendto(4, "abc"..., 2052, 0, NULL, 0) = 2052  

事实上发生了什么是发送(...)被调用(可能因为0,null,0最后三个参数)。我为发送(...)制作拦截器的那一刻起作用了。

© www.soinside.com 2019 - 2024. All rights reserved.