不能用LD_PRELOAD拦截PyDict_New

时间:2011-12-18 03:45:57

标签: python c dlsym ld-preload

我正在尝试使用LD_PRELOAD拦截PyDict_New函数。我已经验证this recipe在python解释器中使用了getpid,而我adapted it to use PyDict_New代替了它,但它根本无法正常工作。虽然我清楚地分配字典,但必须使用此函数,但我的覆盖不会被调用。

我做错了什么?


背景:我正在尝试在一个非常大的系统中调试问题。我发现有一个带有错误引用计数的字典。我知道dict首先被分配到哪里,问题出现在哪里,但我很确定计数在某个中间时间变坏了,并且一个简单的代码跟踪不会,因为dict被缓存并重新使用(通过PyDict_New)由gc系统。

2 个答案:

答案 0 :(得分: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 foo -I / usr / include / python2.7 foo.c -lpython2.7

执行此操作后,。/ foo上的LD_PRELOAD应该可以正常工作。

答案 1 :(得分:1)

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

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