覆盖函数指针后面的c静态函数

时间:2013-06-11 08:47:42

标签: c static shared-libraries function-overriding

我有一个问题,几个星期后我无法解决。 我确信有一个解决方案,也许这里有一个想法。

有一个名为 libaudio.so 的共享库,如下所示:

static ssize_t out_write(..)
{
    // /!\ I need to overwrite/extend this function
    return 0;
}

static int adev_open_output_stream(struct audio_stream_out **stream_out)
{
    struct stream_out *out;
    out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
    if (!out)
            return -ENOMEM;

    out->stream.write = out_write;  // pointer to static function above

    *stream_out = &out->stream;
    return 0;
}

static int adev_open(hw_device_t** device)
{
    struct audio_device *adev;
    adev = calloc(1, sizeof(struct audio_device));
    if (!adev)
            return -ENOMEM;

    adev->hw_device.open_output_stream = adev_open_output_stream; // pointer to static function above

    *device = &adev->hw_device.common;    
    return 0;
}

static struct hw_module_methods_t hal_module_methods = {
    .open = adev_open, // this function can be called after obtained via dlsym() below
};

struct audio_module HAL_MODULE_INFO_SYM = {
        .methods = &hal_module_methods, // this field is public available and can be called via dlsym()
};

下面的代码(也是名为 libplugin.so 的共享库)在进程下运行作为插件

此过程先前打开了 libaudio.so (上图),获得了* HAL_MODULE_INFO_SYM *并调用了

HAL_MODULE_INFO_SYM->methods->open(device)

我无法访问设备 - 该过程的实例,所以我不能只用

覆盖写入功能
struct audio_stream_out **stream_out
device->open_output_stream(stream_out)
stream_out.write = MY_WRITE_FUNCTION 

但是我希望:

由于我在以前执行过相同的过程中运行 libaudio.so ,我也可以调用dlopen(“libaudio.so”)并获得与此库相同的引用作为之前的过程。

我也可以调用dlsym(HAL_MODULE_INFO_SYM),然后获得相同的公共结构。 然后我可以调用 open 和* open_output_stream *然后理论上将指针更改为 write -function。

但是,用我开始的C知识,这不会影响流程的实例,只会影响我自己的实例。

这意味着:该过程仍然在其实例后面有原始的写入功能,只有我的实例会调用 MY_WRITE_FUNCTION

我知道无法强制流程重新加载 HAL_MODULE_INFO_SYM 并调用 HAL_MODULE_INFO_SYM-> methods-> open(设备) - 所以更改此符号会不会不行。

我无法更改外部代码,也无法更改libaudio.so。我只能访问自己的小libplugin.so。

如果有人可以帮助我,我会非常感激。

1 个答案:

答案 0 :(得分:1)

我认为可以这样做,但只有在之前干预过程才会调用libaudio.so

那时,您可以在HAL_MODULE_INFO_SYM中获取libaudio.so的地址(使用dlopen,如您所建议的那样),将methods指针复制到某处并替换为指向您自己的方法结构的指针。该结构中的方法只是从保存的指针调用原始方法 就其本身而言,这没有任何效果,但是在调用真实open之后,您的open方法可以查看返回的dev并对其进行操作。

如果你没有及时完成,那么该进程已经有dev指针,我认为你无法改变它。

但我想警告你,这一切似乎都很脆弱,并且取决于libaudio.so实施的细节。它很容易导致麻烦,特别是如果将来更改库。