Mac OS X 上的弱符号链接
目前,我在使用 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 <弱链接符号的strong>属性((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
即使使用选项-undefinedynamic_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
nm - “a.out”的 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)
Currently I encountered a weak link issue on Mac OS X 10.6.7 with Xcode 4.0.2.
$ gcc --version
i686-apple-darwin10-gcc-4.2.1 (GCC) 4.2.1 (Apple Inc. build 5666) (dot 3)
As the developer document said, we can use gcc attribute((weak_import)) for weak link symbol. However, the following sample code always throw compile error.
As the following:
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");
}
The error message is the following:
$ 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
Even if use option -undefined dynamic_lookup
, it still throws error at runtime:
$ 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
The nm -m
message of "a.out" is the following:
$ nm -m a.out | grep Hello
(undefined) external _SayHello (dynamically looked up)
Which was expected as the following:
(undefined) weak external _SayHello (dynamically looked up)
However, when I compile on Ubuntu with gcc (Ubuntu/Linaro 4.4.4-14ubuntu5) 4.4.5, it works as expected:
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!
The symbol of SayHello in binary is:
$ nm a.out | grep Hello
w SayHello
"w" The symbol is a weak symbol that has not been specifically tagged as a weak object symbol.
And I test the old xcode 3.2, it works as expected.
Could anyone help me on this? Was it a bug of ld?
And I found more interested things. When I create a dummy lib to export the SayHello symbol in dynamic lib, it works as expected.
dummy.c:
int SayHello() {
return;
}
$ gcc -dynamiclib -o libdummy.dylib dummy.c
$ gcc weak.c libdummy.dylib
$ ./a.out
SayHello is present!
If the "libdummy.dylib" does not exist:
$ rm libdummy.dylib
$ ./a.out
SayHello is not present!
Works as expected! Weak symbol now in nm message, as expected:
$ nm -m a.out | grep Hello
(undefined) weak external _SayHello (from libdummy)
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
今天在 GCC 12 和 Clang 14 上,如果没有
-undefineddynamic_lookup
选项,这仍然会出错:但它可以在选项集下正常工作:
C0deH4cker 调用了这个 评论中的链接。它详细介绍了该问题,包括一些解决方法。
This still errors today on GCC 12 and Clang 14 without the
-undefined dynamic_lookup
option:But it works correctly with the option set:
C0deH4cker called out this link in comments. It walks through the problem in detail including some workarounds.