не может перехватить PyDict_New с LD_PRELOAD

1

Я пытаюсь использовать LD_PRELOAD для перехвата функции PyDict_New. Я проверил, что этот рецепт работал с getpid в интерпретаторе python, и я адаптировал его для использования PyDict_New вместо этого, но он просто не работает, как я ожидаю. Хотя я четко выделяю словари, и эта функция должна использоваться, мое переопределение не вызывается.

Что я делаю не так?


Предпосылки: Я пытаюсь отладить проблему в очень большой системе. Я обнаружил, что есть указатель с плохим подсчетом ссылок. Я знаю, где именно выделяется dict, и где проблема проявляется, но я вполне уверен, что счет идет плохо в какое-то промежуточное время, а простая трассировка кода не будет выполняться, так как dict кэшируется и повторно используется (через PyDict_New) системой gc.

Теги:
ld-preload
dlsym

2 ответа

3
Лучший ответ

LD_PRELOAD может перегружать только те функции, которые сами загружаются динамически. Если вы используете двоичный код python, PyDict_New не динамически загружается, и поэтому нет возможности для динамического загрузчика перехватить разрешение этого символа. Если вы вместо этого создадите свой собственный "python", скомпилировав свой собственный двоичный файл и связавшись с libpython.so, он должен работать. Вот что вам нужно будет добавить в вашу программу (/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

После этого LD_PRELOAD на. /foo должен работать.

  • 0
    Что вы подразумеваете под "сами загружаются динамически". Разве LD_PRELOAD не будет работать для переопределения глобальных функций в общей библиотеке, не скомпилированной с -Bsymbolic?
  • 1
    Я имел в виду тот факт, что символы в исполняемом файле не загружаются динамически ld.so. Поскольку они не загружаются ld.so, LD_PRELOAD просто не используется. В этом случае функция, которую ОП хотел переопределить, была скомпилирована в исполняемый файл python и не загружалась ld.so из какой-либо общей библиотеки. В представленном решении весь python динамически загружается из libpython2.7.so, поэтому LD_PRELOAD будет работать. Что касается -Bsymbolic, я понимаю, что единственный эффект, который будет иметь - это иметь библиотеку, предпочитающую сначала свои собственные символы вместо того, чтобы смотреть сначала на исполняемый файл.
Показать ещё 1 комментарий
1

Я думаю, было бы намного проще в вашем случае просто загрузить исходный дистрибутив Python (для соответствующей вам версии), построить его в режиме отладки и запустить приложение с ним.

Этот метод обеспечит вам большую гибкость при отладке проблемы. Например, вы можете установить условные точки останова в PyDict_New или просто заменить его своей собственной версией.

  • 0
    Хотя это не решает вопрос, я буду голосовать. Я не думал об этом. Я думаю, я просто не привык работать на таком низком уровне.
  • 0
    @bukzor: ваш вопрос на самом деле не дает достаточно подробностей для прямого обращения (покажите ваш код, ваши пути компиляции / компоновки / выполнения, ожидаемый вывод, вывод, который вы видите, и т. д., в настоящее время он слишком абстрактен ). Несмотря на это, предлагаемый мною подход должен помочь вам быстрее отладить проблему, ИМХО
Показать ещё 1 комментарий

Ещё вопросы

Сообщество Overcoder
Наверх
Меню