system()函数未从LD_PRELOAD'ed库中调用。

8 浏览
0 Comments

system()函数未从LD_PRELOAD'ed库中调用。

我正在尝试在Linux上使用LD_PRELOAD来包装对system函数的调用,以便对参数进行一些预处理。这是我的system.cpp代码:

#define _GNU_SOURCE
#include 
#include 
#include 
typedef int (*orig_system_type)(const char *command);
int system(const char *command)
{
    std::string new_cmd = std::string("set -f;") + command;
    // 下一行仅用于调试
    std::cout << new_cmd << std::endl;
    orig_system_type orig_system;
    orig_system = (orig_system_type)dlsym(RTLD_NEXT,"system");
    return orig_system(new_cmd.c_str());
}

我使用以下命令编译它:

g++ -shared -fPIC -ldl -o libsystem.so system.cpp

这将生成.so对象。然后,我使用以下命令运行程序:

$ LD_PRELOAD=/path/to/libsystem.so ./myprogram

我没有收到任何错误消息,但似乎我的system函数没有被调用。通过运行LD_DEBUG=libs,我可以看到我的.so被加载了,但是我的system函数没有被调用,而是调用了标准库中的函数。

我需要在代码或编译中做出哪些更改才能使它工作?

0
0 Comments

问题的出现原因是因为system()函数是被一个C函数调用的,而C++版本的system()函数会进行名称修饰,导致无法被识别。解决方法是在函数声明中添加extern "C"关键字,以解决名称修饰的问题。

0
0 Comments

问题的出现原因是system()函数没有从LD_PRELOAD的库中调用。解决方法有两种:

方法一:在构造函数/初始化函数中保存“orig_system”指针,这样可以避免每次调用dlsym。代码如下:

extern "C" {
typedef int (*orig_system_type)(const char *command);
static orig_system_type orig_system;
static void myInit() __attribute__((constructor));
void myInit()
{
    orig_system = (orig_system_type)dlsym(RTLD_NEXT,"system");
}
int system(const char *command)
{
    std::string new_cmd = std::string("set -f;") + command;
    // next line is for debuggin only
    std::cout << new_cmd << std::endl;
    return orig_system(new_cmd.c_str());
}
}

方法二:使用GNU ld的--wrap选项。首先在编译共享库时使用-Wl,--wrap system选项。然后在代码中编写如下内容:

extern "C" {
void* __real_system(const char* command);
void* __wrap_system(const char* command)
{
    std::string new_cmd = std::string("set -f;") + command;
    // next line is for debuggin only
    std::cout << new_cmd << std::endl;
    return __real_system(new_cmd.c_str());
}
}

以上是解决问题的两种方法。

0
0 Comments

问题出现的原因是驱动程序是用C++编写的,而不是C,因此名称修饰(name mangling)导致系统无法正确调用system函数。解决方法是在驱动程序中使用extern "C"来指定system函数以C语言方式进行链接,以避免名称修饰问题。

修改后的驱动程序代码如下:

#include <cstdlib>
extern "C" {
    int system(const char* command);
}
int main() {
    system("find -name *.cpp");
}

然后使用env LD_PRELOAD=$PWD/libsystem.so ./a.out运行程序,即可正常输出结果:

set -f;find -name *.cpp
./system.cpp
./test.cpp

0