Можно ли обернуть вызовы в статически связанную стороннюю библиотеку? - PullRequest
1 голос
/ 16 июня 2010

Я хотел бы отследить вызовы какой-либо сторонней библиотеки, сделанные из другой сторонней библиотеки.

Пример: я хочу отследить вызовы к библиотеке A. Мое приложение статически связывает библиотеку B, которая, в свою очередь, статически связана с библиотекой A. Поэтому в основном у меня есть libAB.a

В случае динамического связывания я мог бы написать библиотеку A2 с обертками для функций, которые я хочу отследить из библиотеки A, и использовать LD_PRELOAD = A2.so. Тогда вместо этого будут вызываться мои обертки, и я увижу след. В моем случае я не могу использовать динамическое связывание.

Можно ли добиться того же, используя статическое связывание?

В идеальном случае я хотел бы связать свое приложение с libAB.a и библиотекой трассировки libA2.a и получить трассировку.

Спасибо
Робуста

Ответы [ 3 ]

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

Хорошо, я нашел это:)

man ld

       --wrap symbol
       Use a wrapper function for symbol.  Any undefined reference to symbol will be resolved to "__wrap_symbol".  Any undefined ref‐
       erence to "__real_symbol" will be resolved to symbol.

       This  can  be  used to provide a wrapper for a system function.  The wrapper function should be called "__wrap_symbol".  If it
       wishes to call the system function, it should call "__real_symbol".

       Here is a trivial example:

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

       If you link other code with this file using --wrap malloc, then all calls to "malloc" will call the  function  "__wrap_malloc"
       instead.  The call to "__real_malloc" in "__wrap_malloc" will call the real "malloc" function.
0 голосов
/ 16 июня 2010

Ну, это похоже на мертвый замок:)

Но я думаю, что вы можете решить это с помощью макросов. Хотя это решение может быть не совсем чистым и работать не во всех ситуациях.

Вы можете попробовать это:

void functionFromLibA();
#define functionFromLibA() trace(); functionFromLibA()
int main()
{
    functionFromLibA();
}

Это будет расширено до:

void myfunc();
int main()
{
trace(); functionFromLibA();
}

РЕДАКТИРОВАТЬ: Но обратите внимание, что для этого решения все объявления прототипов функций должны быть сделаны до определения макросов. В противном случае вы будете расширять прототипы при предварительной обработке.

0 голосов
/ 16 июня 2010

В зависимости от того, насколько важна производительность, вы можете сделать это с помощью GDB ... (Установите точку останова для всех функций, которые вас интересуют, и регистрируйте трассировки стека ... но это включает в себя обучение написанию сценариев GDB)

Есть также такие вещи, как Oprofile http://oprofile.sourceforge.net/, LTTng http://lttng.org/, и perf (поставляется с последними ядрами в исходном коде ядра, он находится в каталоге tools / perf / вам нужно его скомпилировать, в Ubuntu я думаю, что он находится в пакет linux-tools)

Я не могу рассказать вам, как добиться того, чего вы хотите, с помощью любого из этих инструментов, но oprofile и LTTng имеют много документации и активное сообщество пользователей.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...