【问题标题】:Making a function that defaults to aliasing an externally defined symbol in gcc/ld在 gcc/ld 中创建一个默认为外部定义符号别名的函数
【发布时间】:2020-09-24 23:09:23
【问题描述】:

我有一个只有标头的库,目前正在调用 malloc 和 free

这个头文件包含在许多不同的静态库中,用于构建不同配置的程序。

我希望能够在链接时将这些调用替换为对另一个分配器的调用——基于该分配器库是否包含在链接步骤中,而不影响对malloc 和free 的其他调用。

我的想法是让库调用 customizable_malloc 和 customizable_free 并让这些符号“默认”解析为 malloc 和 free - 然后分配器库可以为 customizable_malloc 和customizable_free

但是,我搞砸了 weak/alias/weakref 属性,我似乎无法让任何工作。有没有办法做到这一点?

注意:我知道我可以创建一个额外的间接层:customizable_malloc 可能是调用 malloc 的函数的弱别名。但这增加了一个似乎不必要的间接级别。

理想情况下,这是我希望链接器在遇到可定制的_malloc 调用时采取的步骤:

  1. 检查 Customized_malloc 的定义是否存在
  2. 如果有,请调用它
  3. 如果不是,则将调用视为对常规 malloc 的调用。

澄清说明:在单一目标场景中,这可以通过#define 完成。该库可以创建默认为malloc 和free 的宏customizable_malloc 和customizable_free。但是,这在这种情况下不起作用,因为在不知道是否存在覆盖的情况下将内容构建到静态库中。

【问题讨论】:

  • in the link step 只需与您自己的malloc 实现链接即可。但还有更多,请阅读overwriting malloc from glibc。
  • @KamilCuk 问题是我不想全局覆盖 malloc 和 free - 我想专门改变这个库的行为。 (其中的原因真的不值得探讨)。
  • 然后你必须重命名它们,例如customizable_*。那么奇怪的是你不能让它与弱符号一起工作(很可能你遇到了在解析弱符号时静态库的顺序很重要的情况,对-Wl,--whole-archive感兴趣)。然后请提供minimal reproducible example。一个真正简单的方法是使用静态函数指针。

标签: c gcc ld elf


【解决方案1】:

额外的间接级别是唯一的方法。 ELF(和其他现实世界的二进制格式)符号定义语法(包括弱符号)不提供任何方式来提供从其他地方引用外部定义的定义。

只需执行您正在考虑的包装方法即可。它简单、干净,并且相对于malloc/free 的成本而言,它不会对性能产生任何重大影响。

【讨论】:

    【解决方案2】:

    您可以使用 GNU-ld --defsym 选项实现预期的结果。

    例子:

    #include <malloc.h>
    #include <stdio.h>
    
    void *custom_malloc(size_t sz);
    
    int main()
    {
      void *p = custom_malloc(1);
      void *q = malloc(42);  // important: malloc needs to be referenced somewhere
      printf("p = %p, q = %p\n", p, q);
      return 0;
    }
    

    使用gcc -c t.c 编译它(自然)将无法链接到未解析的custom_malloc 引用(如果未使用提供custom_malloc 的库):

    $ gcc t.o 
    /usr/bin/ld: t.o: in function `main':
    t.c:(.text+0xe): undefined reference to `custom_malloc'
    collect2: error: ld returned 1 exit status
    

    添加--defsym=custom_malloc=malloc 解决了这个问题:

    $ gcc t.o -Wl,--defsym=custom_malloc=malloc && ./a.out
    p = 0x558ca4dc22a0, q = 0x558ca4dc22c0
    

    附:如果malloc 没有链接到程序中(即如果我注释掉// important 行),那么--defsym 会失败:

    $ gcc t.c -Wl,--defsym=custom_malloc=malloc && ./a.ou
    /usr/bin/ld:--defsym:1: unresolvable symbol `malloc' referenced in expression
    ...
    

    但这(我相信)与您的场景不太相关。

    P.P.S.正如 R 正确指出的那样,“额外的间接级别”可能是单个无条件的 JMP malloc 指令,并且这种间接的开销不太可能是可测量的。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-04-09
      • 1970-01-01
      • 2021-10-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多