Mac OS X 上的弱符号链接

Weak symbol link on Mac OS X

提问人:Robin 提问时间:5/15/2011 最后编辑:James RisnerRobin 更新时间:9/28/2022 访问量:5727

问:

目前,我在带有 Xcode 4.0.2 的 Mac OS X 10.6.7 上遇到了弱链接问题。

$ gcc --version
i686-apple-darwin10-gcc-4.2.1 (GCC) 4.2.1 (Apple Inc. build 5666) (dot 3)

正如开发者文档所说,我们可以使用 gcc attribute((weak_import)) 作为弱链接符号。但是,以下示例代码始终抛出编译错误。
如下:

weak.c

#include <stdlib.h>
#include <stdio.h>

extern int SayHello() __attribute__((weak));

int main()
{
    int result;

    if (SayHello!=NULL)
    {
        printf("SayHello is present!\n");
        result=SayHello();
    }
    else
        printf("SayHello is not present!\n");
}

错误消息如下:

$ gcc weak.c 
Undefined symbols for architecture x86_64:
  "_f", referenced from:
      _main in cceOf2wN.o
     (maybe you meant: __dyld_func_lookup)
ld: symbol(s) not found for architecture x86_64
collect2: ld returned 1 exit status

即使使用选项,它仍然会在运行时抛出错误:-undefined dynamic_lookup

$ gcc -undefined dynamic_lookup weak.c 
$ ./a.out 
dyld: Symbol not found: _SayHello
  Referenced from: /private/tmp/o/./a.out
  Expected in: dynamic lookup

Trace/BPT trap

“a.out”的消息如下:nm -m

$ nm -m a.out  | grep Hello

(undefined) external _SayHello (dynamically looked up)

预计如下:

(undefined) weak external _SayHello (dynamically looked up)

但是,当我使用 gcc (Ubuntu/Linaro 4.4.4-14ubuntu5) 4.4.5 在 Ubuntu 上编译时,它按预期工作:

weak.c

#include <stdlib.h>
#include <stdio.h>

extern int SayHello() __attribute__((weak));

int main()
{
    int result;

    if (SayHello!=NULL)
    {
        printf("SayHello is present!\n");
        result=SayHello();
    }
    else
        printf("SayHello is not present!\n");
}

 

$ gcc weak.c 
$ ./a.out 
SayHello is not present!

二进制中 SayHello 的符号是:

$ nm a.out | grep Hello
w SayHello

“w” 该符号是一个弱符号,尚未被专门标记为弱对象符号。

我测试了旧的 xcode 3.2,它按预期工作。

谁能帮我解决这个问题?是ld的bug吗?

我发现了更多有趣的东西。当我创建一个虚拟库以在动态库中导出 SayHello 符号时,它按预期工作。

dummy.c

int SayHello() {
    return;
}

 

$ gcc -dynamiclib -o libdummy.dylib dummy.c 
$ gcc weak.c libdummy.dylib 
$ ./a.out 
SayHello is present!

如果“libdummy.dylib”不存在:

$ rm libdummy.dylib 
$ ./a.out 
SayHello is not present!

按预期工作!正如预期的那样,nm 消息中的弱符号现在:

$ nm -m a.out | grep Hello

                 (undefined) weak external _SayHello (from libdummy)
macOS 链接器 链接器错误 较弱

评论

0赞 Chris Frederick 5/15/2011
您碰巧知道使用的是哪个版本的 gcc XCode 吗?你的答案可能就在那里......
1赞 Robin 5/16/2011
嗨,克里斯托弗,gcc 的版本是 i686-apple-darwin10-gcc-4.2.1 (GCC) 4.2.1 (Apple Inc. build 5666) (dot 3)。我认为这可能是 gcc 4.2.1(build 5666)(dot 3)中 ld 的错误。
0赞 Tobias 6/11/2011
我遇到了重复的符号(typeid(T)),其中T包含在几个编译单元中。仅在 gcc 4.2.1 (build 5666) (dot 3) (XCode 4) 中发生,而不在 gcc 4.2.1 (build 5664) (XCode 3) 中发生。我猜它可能是在星期一建造的......
0赞 C0deH4cker 9/12/2013
也许是因为你用了而不是?我正在寻找类似问题的修复方法。__attribute__((weak))__attribute__((weak_import))
1赞 C0deH4cker 9/12/2013
实际上,刚刚发现了似乎是问题所在。“Xcode < 4.5 中的链接器忘记在DYLD_INFO数据中将弱导入标记为弱导入。”glandium.org/blog/?p=2764

答:

0赞 James Risner 9/28/2022 #1

今天在 GCC 12 和 Clang 14 上仍然错误,没有选项:-undefined dynamic_lookup

Undefined symbols for architecture arm64:
  "_SayHello", referenced from:
      _main in weak-518bb6.o
ld: symbol(s) not found for architecture arm64

但它在选项集上正常工作:

% gcc-12 -undefined dynamic_lookup  -o weak weak.c && ./weak
ld: warning: -undefined dynamic_lookup may not work with chained fixups
SayHello is not present!
% cc -undefined dynamic_lookup  -o weak weak.c && ./weak
ld: warning: -undefined dynamic_lookup may not work with chained fixups
SayHello is not present!

gcc-12 (Homebrew GCC 12.2.0) 12.2.0
Apple clang version 14.0.0 (clang-1400.0.29.102)

C0deH4cker 在评论中指出了这个链接。它详细介绍了该问题,包括一些解决方法。