手动指定特定链接符号的重新映射

Manually specify remapping of specific linking symbols

有没有办法在不修改这两个源文件的情况下获取编译它们产生的目标文件,并说服linker link foo in [=49] =] 到 bar 在 bar.c?

main_v1.c

void foo(void);

int main(void)
{
    foo();
}

bar.c

#include <stdio.h>

void bar(void)
{
    puts("bar()!");
}

修改目标文件本身是公平的游戏,但假设我们甚至可能没有可用的源代码。平台是Linux.


坚持对 main_v1.c 进行适度的更改,并 link 添加一个额外的 "mapping" 目标文件,这是一种仅使用标准 C 就几乎可以得到所需结果的方法。

main_v2.c

extern void (*const foo)(void);

int main(void)
{
    foo();
}

bar.c不变

map.c

void bar(void);
void (*const foo)(void) = bar;

如果目标文件是用 lto 编译的,甚至可以省略函数指针解引用(使用最近的 gcc)。这是一个很好的结果,但是如果 main() 被修改为直接调用 bar(),那么 bar() 本身在 linking 之后内联,因此还有改进的余地。

这将是 GNU ld 的工作 --wrap选项

我们假设您有一个 main_v1.o 已编译并且可能无法更改 main_v1.c 以及从您的 bar.c.

编译而来的 bar.o

现在写另一个源文件:

wrap.c

extern void bar(void);

void __wrap_foo(void)
{
    bar();
}

将其编译为 wrap.o 并使用先前的目标文件将其编译为 link,如下所示:

$ gcc -c wrap.c
$ gcc -o prog -Wl,--wrap=foo main_v1.o bar.o wrap.o

然后:

$ ./prog
bar()!