我有一个问题,几个星期以来我都无法解决。 我确信有一个解决方案,也许这里有人有想法。
有一个名为 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/