【问题标题】:Manually specify remapping of specific linking symbols手动指定特定链接符号的重新映射
【发布时间】:2017-04-25 15:29:38
【问题描述】:

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

ma​​in_v1.c

void foo(void);

int main(void)
{
    foo();
}

bar.c

#include <stdio.h>

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

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


通过坚持对 main_v1.c 进行适度的更改,并链接到一个额外的“映射”对象文件,这是一种仅使用标准 C 即可获得所需结果的方法。

ma​​in_v2.c

extern void (*const foo)(void);

int main(void)
{
    foo();
}

bar.c 没有改变。

ma​​p.c

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

如果目标文件是用 lto 编译的,函数指针取消引用甚至会被忽略(使用最近的 gcc)。这是一个相当不错的结果,但如果将main() 修改为直接调用bar(),那么bar() 本身在链接后内联,因此还有改进的余地。

【问题讨论】:

    标签: c linux linker ld symbols


    【解决方案1】:

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

    我们假设您已经编译了一个 main_v1.o,并且可能无法从您的 main_v1.c 和同样的 bar.o 编译自您的 bar.c

    现在写另一个源文件:

    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()!
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-06-29
      • 1970-01-01
      • 2012-12-24
      • 2015-05-27
      • 2023-03-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多