无法使用 LD_PRELOAD 拦截 PyDict_New

发布于 2024-12-21 15:52:56 字数 456 浏览 0 评论 0原文

我正在尝试使用 LD_PRELOAD 来拦截 PyDict_New 函数。我已经验证这个食谱可以在Python解释器中与getpid一起使用,并且我已经对其进行了调整以使用 PyDict_New 来代替,但它根本无法按我的预期工作。尽管我明确分配了字典,并且必须使用此函数,但我的重写并未被调用。

我做错了什么?


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

I'm trying to use LD_PRELOAD to intercept the PyDict_New function. I've verified that this recipe workd with getpid in the python interpreter, and I've adapted it to use PyDict_New instead, but it simply doesn't work as I expect. Although I'm clearly allocating dictionaries, and this function must be used, my override isn't being called.

What am I doing wrong?


Background: I'm trying to debug a problem in a very large system. I've found that there is a dict with a bad reference count. I know where the dict is first allocated, and where the problem manifests, but I'm pretty certain that the count goes bad at some intermediate time, and a simple code trace won't do, as the dict is cached and re-used (via PyDict_New) by the gc system.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

就是爱搞怪 2024-12-28 15:52:56

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 应该可以工作。

LD_PRELOAD can only overload functions that are themselves loaded dynamically. If you're using the python binary, PyDict_New is not dynamically loaded and therefore there's no way for the dynamic loader to intercept the resolution of that symbol. If you instead create your own "python" by compiling your own binary and linking with libpython.so, it should work. Here's what you'd need to put in your program (/tmp/foo.c):

#include "Python.h"

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

And you can simply build it with:
gcc -o foo -I/usr/include/python2.7 foo.c -lpython2.7

After you do this, LD_PRELOAD on ./foo should work.

糖果控 2024-12-28 15:52:56

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

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

I think it would be much easier in your case to just download the source distribution of Python (for the version relevant to you), build it in debug mode and run your application with it.

This method will provide you with much more flexibility in debugging the problem. For example, you can set conditional breakpoints in PyDict_New or just replace it with your own version.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文