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

在不修改这两个源文件的情况下,是否有办法获取通过编译它们而生成的目标文件,并说服链接程序将main_v1.c中的foo链接到bar.c中的bar?

main_v1.c

void foo(void);

int main(void)
{
    foo();
}

bar.c

#include <stdio.h>

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

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

通过坚持对main_v1.c进行适度的更改,并链接一个附加的“映射”目标文件,这是一种仅使用标准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()本身,因此仍有改进的空间.

解决方法:

这将是GNU ld
--wrap option
的工作

我们假设您已经编译了main_v1.o,并且可能与您的
main_v1.c,同样是从bar.c编译的bar.o.

现在编写另一个源文件:

wrap.c

extern void bar(void);

void __wrap_foo(void)
{
    bar();
}

编译为wrap.o并将其与先前的目标文件链接,如下所示:

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

然后:

$./prog
bar()!
上一篇:javascript-“代理”将“ this [toString]”与“ this [Symbol.toStringTag]”混淆


下一篇:mysql – 在列名称之前登录SQL语句