[英]Redirecting system() function call using LD_PRELOAD
我想使用LD_PRELOAD替换程序对system()函数的调用。
因此,我在共享库中创建了以下包装器函数以进行测试。
// 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;
}
并使用gcc编译并链接到共享库libsyshook.so。
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
当我连接调试器时,可以看到该system()调用在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
函数相同。
在此示例中,如果您在加载了LD_PRELOAD的库中创建了自己的printf
或strlen
函数,则编译后将不会调用该函数,因为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));
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.