如何将函数调用重定向到用户定义的同名函数调用?

How to redirect a function call to a user-defined one of the same name?

环境:

我有两个依赖库(静态的或共享的,不确定是否影响),libAlibB。函数 foo()libA 中定义,并在 libB 中调用。现在我的应用程序代码 app.c 直接从 libB 调用函数,最终会调用 foo()。一个简单的工作流程是 app.c -> libB.a -> libA.a -> foo().

但是,我想更改 foo() 的实现方式以用于某些特定目的。我希望 app.c 可以有一个神奇的功能,如果被调用,将对 foo() 的调用重定向到 app.c 提供的那个。所以工作流程,如果可以实现的话,应该是

app.c -> libB.a -(other than foo())-> libA.a
 |      /
 |  (to call foo())
 v   /
foo()

尴尬的是,我可以完全控制 app.c 但很少甚至无法访问这些库。那么有没有可能实现这样的想法,如何实现呢?

更新

正如评论中所提到的,错过这一点可能会导致完全不同的解决方案,重定向可更好地配置并在运行时发生。这是为了测试目的,因此通常工作流应该是它的样子,而只有在执行测试时才会改变自己。

希望更清楚地说明问题:app.c 调用 bar(),它在 libB.a 中定义。 bar() 调用 foo(),它在 libA.a.

中定义

期望的结果:在运行时可选将对foo()的调用重定向到备用实现foo_other()取决于命令行参数或环境变量。


解决方案(假设foo的签名是int foo(void)):

  1. 将此代码添加到 app.c:
int foo_other()
{
  printf("%s in %s:%d\n", __func__, __FILE__, __LINE__);
  return 42;
}

int __real_foo();
int __wrap_foo()
{
  printf("%s in %s:%d\n", __func__, __FILE__, __LINE__);
  if (getenv("TTT") != NULL) return foo_other();
  return __real_foo();
}
  1. Link您的申请如下:
gcc app.c  libB.a libA.a -Wl,--wrap,foo

结果:

$ ./a.out
bar in bar.c:6
__wrap_foo in main.c:19
foo in foo.c:4

$ TTT=1 ./a.out
bar in bar.c:6
__wrap_foo in main.c:19
foo_other in main.c:13

显然,您可以删除调试 printf 调用,并根据需要更改用于在真实 foo()foo_other() 之间切换的机制。

P.S。有关链接器 --wrap 标志的文档,请参阅 man ld.

Example 使用 --wrap 进行模拟。

使用共享库时,此方法将不起作用。但是通过函数插入可以得到一个不同的等价物 approach