在不更改调用站点的情况下包装函数?

问题描述 投票:0回答:1

假设函数

int foo(int x)
在库
libfoo
中可用,但我无法控制。我确实控制了一个在许多文件中多次调用
foo()
的代码库。

现在,我想在实际调用

foo()
之前插入一些逻辑。假设它的“如果条件成立则调用 foo,否则执行其他操作”(不要介意细节)。到目前为止 - 不是问题。我写了一个
int foo_wrapper(int x)
将我的逻辑放在那里,并称之为一个。

现在是最困难的部分:我不想更改调用站点的代码。也就是说,我仍然希望有

foo()
电话。所以:

  • 没有
    foo_
    几乎同名的函数
  • 没有宏欺骗来替代调用
  • 无预编译源代码生成

本质上我希望我的大多数编译单元“不看”libfoo,但在某些翻译单元中我提供了一个包装器

int foo()
;并让该翻译单元中的实现实际调用 libfoo 的
foo()
函数。这有多容易实现(不用太用力地把自己扭成一个结)?

有关

libfoo
的其他信息:

  • 它是一个静态库;对于动态库,可以使用库搜索路径并找到包装器而不是原始库;然后包装器可能能够动态定位
    libfoo
    本身,加载它,并在必要时使用原始
    foo
    符号。
  • 我正在Linux上工作,跨平台不是必需的;当然,保持这一点总是好的。

注意:最好使用也适用于 C 代码的解决方案,但不是必需的。

c++ linker overriding hook pointer-aliasing
1个回答
0
投票

这有多容易实现(不用太用力地把自己扭成一个结)?

考虑到仅限 Linux 的限制,这是可以轻松实现的。

如果

libfoo
是一个共享库,那么这正是库插入器使用 LD_PRELOAD
 和类似技巧所做的事情。

但是由于

libfoo

 是一个存档库,因此您所需要做的就是将所有 
unresolved 引用从 foo
 重命名为 
foo_wrapper
。您可以通过运行 
objcopy --redefine-sym foo=foo_wrapper caller.o new_coller.o
 来做到这一点,其中 
caller.o
 是最初调用 
foo
 的目标文件。

您必须对代码库中的每个对象重复此操作。

附注使用宏来实现完全相同的结果

可能要简单得多——您所要做的就是在命令行上使用-Dfoo=foo_wrapper

© www.soinside.com 2019 - 2024. All rights reserved.