3

我有一个问题,几周以来我都无法解决。我确信有一个解决方案,也许这里有一个想法。

有一个名为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 

但在这里我的希望是:

由于我在之前 dlopen'd libaudio.so的同一进程下运行,我也可以调用 dlopen("libaudio.so") 并且将获得与之前的进程相同的对该库的引用。

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

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

这意味着:该进程在他的实例后面仍然具有原始的write函数,并且只有我的实例会调用MY_WRITE_FUNCTION

我知道没有办法强制进程重新加载HAL_MODULE_INFO_SYM并调用HAL_MODULE_INFO_SYM->methods->open(device) - 因此更改此符号不起作用。

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

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

4

1 回答 1

1

我认为可以做到,但前提是您在流程调用之前libaudio.so进行干预。

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

如果你没有及时做,这个过程已经有了它的dev指针,我看你没有办法改变它。

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

于 2013-06-11T10:39:15.377 回答