Я хочу заменить вызовы функции 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 ****** ..."
Самый обычный случай плохой связи с 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));
}