Как динамически вставлять функции C из Python в Linux (без LD_PRELOAD)?

Как мне во время выполнения (без LD_PRELOAD) перехватить/перехватить функцию C, например fopen() в Linux, а-ля Detours для Windows? Я хотел бы сделать это из Python (следовательно, я предполагаю, что программа уже запускает виртуальную машину CPython), а также перенаправить на код Python. Я в порядке, просто подключая функции общей библиотеки. Я также хотел бы сделать это, не меняя способ запуска программы.

Одна из идей состоит в том, чтобы развернуть мой собственный инструмент на основе ptrace() или переписать код, найденный с помощью dlsym() или в PLT, и ориентироваться на функции, вызываемые C, сгенерированные ctypes, но я решил сначала спросить здесь. Спасибо.


person Yang    schedule 03.02.2011    source источник
comment
Как бы вы сделали это с LD_PRELOAD?   -  person Matt Joiner    schedule 04.02.2011
comment
Вам нужно будет написать собственный модуль, чтобы выполнить низкоуровневую работу за вас. Даже если вам удастся получить доступ и изменить PLT из Python (что, вероятно, возможно), вам понадобится код для запуска виртуальной машины Python.   -  person Glenn Maynard    schedule 04.02.2011
comment
@Matt Joiner: Судя по тому, как вы задаете свой вопрос, я так понимаю, вам не нравится то, что я сказал, и в этом случае было бы продуктивно / конструктивно, если бы вы могли быть более конкретными. Но в случае, если вы действительно просто спрашивали, вот как вы выполняете интерпозицию нединамически: stackoverflow.com/questions/426230/what-is-the-ld-preload-trick (и, да, я применял это много раз раньше)   -  person Yang    schedule 04.02.2011
comment
@Glenn Maynard: Извините, если мой вопрос не ясен - я упомянул, что хотел бы сделать это из Python, поэтому предполагается, что виртуальная машина уже запущена. Но в любом случае я подправил вопрос, чтобы прояснить это. Манипулирование PLT из Python — это именно то, к чему я стремился с помощью своего соломенного человека.   -  person Yang    schedule 04.02.2011
comment
Речь идет не о создании экземпляра виртуальной машины, а о вызове ее; вы не можете указать PLT на функцию Python, в конце концов, вам нужно указать его на собственный код, который вызывает среду выполнения Python и запускает нужную функцию.   -  person Glenn Maynard    schedule 04.02.2011
comment
@Yang: Я искренне заинтересован. Я знаком с методом LD_PRELOAD и не понимаю, как это возможно с использованием Python. Если у вас есть ссылки на этот эффект, мне очень интересно.   -  person Matt Joiner    schedule 04.02.2011
comment
@Matt Joiner: Ах, ладно. Я также не имел в виду, что перешел на Python до использования LD_PRELOAD. Вы бы сделали это с кодом C, который вызывает нужный вам Python. Еще одна причина, по которой LD_PRELOAD не подходит.   -  person Yang    schedule 09.02.2011
comment
@Glenn Maynard: ctypes позволяет создавать указатели вызываемых функций C из вызываемых функций Python, поэтому я надеюсь, что смогу вызвать такую ​​функцию из PLT.   -  person Yang    schedule 09.02.2011
comment
Ян, ты когда-нибудь находил решение этой проблемы? Можно ли было изменить PLT?   -  person Matt Joiner    schedule 17.01.2012
comment
@MattJoiner К сожалению, я еще не нашел решения (хотя я все еще верю, что это возможно!)   -  person Yang    schedule 17.01.2012
comment
Может быть, вы могли бы написать модуль ядра, чтобы поймать fopen? Просто мозговой штурм.   -  person gogators    schedule 23.01.2012
comment
Я бы предположил, что, если об изменении среды выполнения не может быть и речи, загрузка произвольных модулей ядра, вероятно, невозможна.   -  person richo    schedule 23.01.2012
comment
fopen не является функцией ядра   -  person Matt Joiner    schedule 23.01.2012


Ответы (2)


Вы найдете способ сделать это у одного из разработчиков ltrace. См. эту публикацию, содержащую полный патч в чтобы поймать динамически загружаемую библиотеку. Чтобы вызвать его из python, вам, вероятно, потребуется создать модуль C.

person Coren    schedule 24.01.2012

google-perftools имеет собственную реализацию Detour в src/windows. /preamble_patcher* . На данный момент это только для Windows, но я не вижу причин, по которым он не будет работать на любой машине x86, за исключением того факта, что он использует функции win32 для поиска адресов символов.

Быстрое сканирование кода, и я вижу, что используются эти функции win32, все из которых имеют версии для Linux:

  • GetModuleHandle/GetProcAddress : получить адрес функции. dlsym может это сделать.
  • VirtualProtect : разрешить модификацию сборки. защита.
  • GetCurrentProcess: получить пид
  • FlushInstructionCache (судя по комментариям, не работает)

Это не кажется слишком сложным, чтобы скомпилировать и связать это с python, но я бы отправил сообщение разработчикам perftools и посмотрел, что они думают.

person aaron    schedule 12.02.2011
comment
Хотите объяснить, какая сборка модифицирована? - person Matt Joiner; 12.02.2011
comment
Пожалуйста, дайте ссылку на указанный исходный файл. - person Matt Joiner; 24.01.2012
comment
code.google.com/codesearch#BGeH2W13jNw/trunk/src/windows/, вызовы функций win32 оставляют несколько инструкций в начале каждого вызова функции, которые можно превратить в переход к любой функции, которую вы хотеть. - person aaron; 02.02.2012