Перенаправление функций Linux - PullRequest
2 голосов
/ 04 июня 2011

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

У меня есть две функции с одинаковой подписью:

void someFunc () {
    puts ("someFunc");
}

void someFunc_wrapper () {
    puts ("someFunc_wrapper");
}

И я хочу перенаправить любой вызов функции в someFunc с помощью вызова функции-оболочки. Конечно, я мог бы сделать это с помощью определения макросов или поместить функцию-обертку в общую библиотеку, а затем вызвать программу следующим образом:

LD_PRELOAD=./mylib.so my_program

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

Любая помощь будет оценена :)

Ответы [ 2 ]

2 голосов
/ 05 июня 2011

ld имеет опцию --wrap=symbol, которая должна делать то, что вы хотите.На странице руководства есть пример того, как это работает.

0 голосов
/ 04 июня 2011

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

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

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

#include <stdio.h>

void foo(void) {
    printf("Hello from foo\n");
}

void bar(void) {
    printf("Hello from bar\n");
}

#ifdef INTERCEPT

typedef void(*myfunptr)(void);

myfunptr thingy = foo;

void turnonbar(void)
{
    thingy = bar;
}

#else
#define turnonbar()
#define thingy foo
#endif

int main(void) {
    thingy();
    turnonbar();
    thingy();
    return 0;
}
...