Перенаправление вызова функции system () с использованием LD_PRELOAD

Я хочу заменить вызовы функции system (), сделанные моей программой с использованием LD_PRELOAD.

Поэтому я создал следующие функции-оболочки в общей библиотеке для тестирования.

// syshook.c

int system(const char * command)
{
printf("system() called for %s ************************************\n", command);
return 55;
}

char * getenv (const char* name)
{
printf("my getenv() *********************");
return 0;
}

И скомпилирован и связан с общим объектом libsyshook.so с помощью gcc.

gcc -Wall -fPIC -c *.c
gcc -shared -Wl,-soname,libsyshook.so -o libsyshook.so.1.0
ln -s libsyshook.so libsyshook.so.1.0

Однако, когда я запускаю программу с LD_PRELOAD, как показано ниже, моя функция-обертка для system () не вызывается, а вызывается обертка для getenv ().

LD_PRELOAD="libsyshook.so" myprog

Когда я присоединяю отладчик, я вижу, что системный вызов () вызывает реализацию в libpthread.so. Так почему же перенаправление system () не работает? Я не думаю, что есть какие-либо ограничения на это?

Редактировать:
Моя тестовая программа, скомпилированная для myprog выше, выглядит следующим образом. Комментарии указывают на мои наблюдения.

void TestClass::testMethod()
{
string cmdLine = "date";
if (!mainWin) cmdLine = "time";

int retFromSys = system(cmdLine.c_str());   // goes into libpthread when stepped in.
cout << "return from system " << retFromSys << endl; // prints 0, not 55
getenv("DEBUG_SYS");  // Wrapper function called for this. Prints "my getenv ****** ..."

0

Решение

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

Например, если GCC прочитал эту строку в вашем коде:

printf("%d", strlen("toto"));

Он заменит эту строку перед компиляцией:

puts("4");

Потому что это знает printf а также strlen функции, и думаю, что результат будет одинаковым с puts функция.

В этом примере, если вы сделали свой собственный printf или же strlen Функция в библиотеке, загруженной с LD_PRELOAD, ваша функция не будет вызываться после компиляции, потому что GCC заменил бы вызовы функций.

Я думаю, что ваша проблема по той же причине. system это очень тяжелая функция, и GCC может заменить ваш вызов функции другим. Например, если вы пытались:

system("ls");

GCC может заменить вашу линию:

execlp("ls", "ls");

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

В качестве решения, я предлагаю вам попробовать позвонить system с более «случайным» параметром, чтобы заставить GCC думать, что он не должен пытаться заменить его. Может быть что-то вроде:

int main(int argc, char** argv)
{
char* line = NULL;

// Useless condition to make GCC think the parameter is variable
if (argc == 1)
line = "ls";

return (system(line));
}
0

Другие решения


По вопросам рекламы [email protected]