2011-12-18 69 views
1

我试图用LD_PRELOAD拦截PyDict_New函数。我已经验证了this recipe在python解释器中使用了getpid,而我已经使用adapted it to use PyDict_New,但它并不像我期望的那样工作。虽然我明确分配字典,并且必须使用此函数,但我的覆盖不会被调用。不能拦截PyDict_New与LD_PRELOAD

我在做什么错?


背景:我试图在一个非常大的系统中调试问题。我发现有一个引用计数不好的字典。我知道字典首先分配的位置,以及问题出现的位置,但我很确定在某个中间时间计数会变差,并且一个简单的代码跟踪不会执行,因为该字典被缓存并重新使用(通过PyDict_New)由gc系统。

回答

3

LD_PRELOAD只能重载本身自动加载的函数。如果您使用python二进制文件,PyDict_New不会动态加载,因此动态加载程序无法拦截该符号的分辨率。如果您通过编译自己的二进制文件并使用libpython.so进行链接来创建自己的“python”,它应该可以工作。下面是你需要把你的程序(/tmp/foo.c)什么:

#include "Python.h" 

int 
main(int argc, char **argv) 
{ 
    return Py_Main(argc, argv); 
} 

而且你可以简单地构建它: 的gcc -o富-I/usr/include目录/ python2.7 foo.c -lpython2.7

执行此操作后,./foo上的LD_PRELOAD应起作用。

+0

你是什么意思“自己动态加载”。 LD_PRELOAD不会在不使用-Bsymbolic编译的共享库中重写全局函数吗? – 2011-12-26 06:23:03

+1

我指的是可执行文件中的符号不​​是由ld.so动态加载的。由于它们没有被ld.so加载,LD_PRELOAD根本就没有被使用。在这种情况下,OP想要覆盖的函数被编译到python可执行文件中,而不是由ld.so从任何共享库加载。在提供的解决方案中,所有的python都是从libpython2.7.so动态加载的,所以LD_PRELOAD可以工作。至于-Bsymbolic,我的理解是唯一的影响是让一个库首先选择自己的符号,而不是首先查看可执行文件。 – 2011-12-28 15:58:29

+0

我需要尝试一下。 – bukzor 2011-12-29 20:14:11

1

我认为只要下载Python的源代码分发版(对于与您相关的版本),在调试模式下构建它并使用它运行应用程序会容易得多。

这种方法将为您提供更多的调试问题的灵活性。例如,您可以在PyDict_New中设置条件断点,或者将其替换为您自己的版本。

+0

虽然这不能解决问题,但我会将它投票。我没有想到这一点。我想我只是不习惯在这么低的水平上工作。 – bukzor 2011-12-18 04:56:40

+0

@bukzor:你的问题实际上并没有提供足够的细节来直接解决(显示你的代码,你的编译/链接/执行路径,你期望的输出,你看到的输出等等。*否则它现在太抽象了* )。尽管如此,我提议的方法应该让你更快地调试你的问题,恕我直言 – 2011-12-18 05:53:17

+0

如果你点击我的文章中的链接,你会发现所有的信息。也许我应该让他们更加突出/明确。明天会做。 – bukzor 2011-12-18 07:37:09