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

标签 c static shared-libraries 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 

但我的希望是:

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

我也可以调用 dlsym(HAL_MODULE_INFO_SYM) 然后获得相同的公共(public)结构。 然后我可以调用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。

如果有人能帮助我,我将不胜感激。

最佳答案

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

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

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

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

关于c - 覆盖函数指针后面的c静态函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17039933/

相关文章:

java - 同步发生了一些奇怪的事情(Test2.class)

static - NUXTJS 静态托管路径

c - 将汇编程序反编译为c

c - 反转 '\0' 终止的 C 字符串?

C++静态变量

c - 共享库中的静态变量

angular - 为 Angular/ react 组件创建组件库的技巧

c - 链接共享库时的问题

c - Ansi C,多线程矩阵乘法

c - 返回 C 中正因子计数的方法