【问题标题】:How to redirect a function call to a user-defined one of the same name?如何将函数调用重定向到用户定义的同名函数调用?
【发布时间】:2021-07-06 09:41:42
【问题描述】:

环境:

  • 操作系统:Ubuntu 16.04
  • 编译器:GCC 5.4.0

我有两个依赖库(静态或共享,不确定这是否会影响)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,但很少甚至无法访问这些库。那么是否有可能实现这样的想法以及如何实现?

更新

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

【问题讨论】:

  • 只需在app.c中定义一个名为foo的函数即可。
  • @n.1.8e9-where's-my-sharem。我其实知道这个方法。但是我必须使用宏指令进行条件编译。重定向不是永久性的,我希望这可以通过条件变量进行配置,例如testrun = true / false
  • 如果您需要选择在运行时调用哪一个,例如一个命令行参数,那么这是相当复杂的。您应该在问题中提到这一点。
  • 您的描述不清楚,但您似乎在描述插入或类似的东西。搜索“interposition”、“interpose”或“interposing”以获取信息。

标签: c linker


【解决方案1】:

希望能更清楚地说明问题: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. 如下链接您的应用程序:
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() 之间切换的机制。

附:有关链接器 --wrap 标志的文档,请参阅 man ld

Example 使用 --wrap 进行模拟。

使用共享库时,这种方法将不起作用。但是可以通过函数插入获得不同的等效 approach

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-12-31
    • 2023-03-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多