Вставка функции в Linux без dlsym - PullRequest
8 голосов
/ 16 июня 2009

В настоящее время я работаю над проектом, в котором мне нужно отслеживать использование нескольких системных вызовов и низкоуровневых функций, таких как mmap, brk, sbrk. До сих пор я делал это с помощью вставки функции: я пишу функцию-оболочку с тем же именем, что и функция, которую я заменяю (например, mmap), и загружаю ее в программу, устанавливая LD_PRELOAD переменная окружения. Я вызываю реальную функцию через указатель, который загружаю с помощью dlsym.

К сожалению, одна из функций, которую я хочу обернуть, sbrk, используется внутри dlsym, поэтому программа вылетает, когда я пытаюсь загрузить символ. sbrk не является системным вызовом в Linux, поэтому я не могу просто использовать syscall для его косвенного вызова.

Итак, мой вопрос: как я могу вызвать библиотечную функцию из одноименной функции-оболочки без использования dlsym? Есть ли какой-нибудь трюк с компилятором (использующий gcc), который позволяет мне ссылаться на оригинальную функцию?

Ответы [ 4 ]

14 голосов
/ 16 июня 2009

см. Параметр ld --wrap symbol. Со страницы руководства:

- символ обтекания Используйте функцию обертки для символа. Любой неопределенный ссылка на символ будет разрешена до "__wrap_symbol". Любой неопределенный ссылка на "__real_symbol" будет быть преобразован в символ.

Это может быть использовано для обеспечения Обертка для системной функции. должна быть вызвана функция-обертка "__wrap_symbol". Если он хочет позвонить системная функция, она должна вызывать "__real_symbol".

Вот тривиальный пример:

void *
__wrap_malloc (size_t c)
{
    printf ("malloc called with %zu\n", c);
    return __real_malloc (c);
}

Если вы связываете другой код с этим файл с помощью --wrap malloc, затем все звонки на "malloc" вызовут вместо этого используйте функцию "__wrap_malloc". вызов "__real_malloc" в
«__wrap_malloc» назовем реальным Функция "malloc".

Вы можете предоставить «__real_malloc», так что что ссылки без опции --wrap преуспеет. Если вы сделаете это, вы не следует ставить определение "__real_malloc" в том же файле, что и "__wrap_malloc"; если вы делаете, то ассемблер может разрешить вызов раньше у компоновщика есть шанс обернуть его "ТаНос".

Другой вариант, возможно, посмотреть на источник для ltrace, он более или менее делает то же самое: -P.

Вот идея, хотя. Вы можете сделать так, чтобы ваша LD_PRELOAD 'ed библиотека изменила записи PLT, чтобы они указывали на ваш код. Это, технически, функция sbrk() по-прежнему может вызываться из вашего кода.

2 голосов
/ 16 июня 2009

Вы можете ненавязчиво изучить вызов функции, используя такие инструменты, как:

  • GDB
  • ltrace
  • Systemtap

Эти инструменты позволяют программе монитора сообщать вам, когда вызывается функция, и позволяют запрашивать аргументы.

Основные отличия:

  • GDB является интерактивным, но мощным
  • ltrace прост в использовании, но вы можете напечатать только имя функции
  • systemtap не интерактивен, но он может быть очень быстрым и мощным.
0 голосов
/ 21 июня 2011

Не работает ли truss в вашей системе? Это отлично работает для такого рода вещей здесь, на Solaris.

0 голосов
/ 14 августа 2009

Если вы используете хост-систему с glibc, у libc есть некоторый внутренний бэкэнд динамического компоновщика времени выполнения, который я использовал некоторое время назад. Если я правильно помню, я думаю, что это называется __libc_dlsym. (Чтобы проверить, «$ readelf -s /usr/lib/libc.a | grep dlsym» должен помочь.) Объявите ее как внешне связанную функцию с теми же аргументами и возвращаемым значением, что и у dlsym, и используйте ее для переноса самого dlsym.

...