如何与GCC进行弱连接工作?

23 c linker gcc weak

似乎有3种方法告诉GCC弱连接符号:

  • __attribute__((weak_import))
  • __attribute__((weak))
  • #pragma weak symbol_name

这些都不适合我:

#pragma weak asdf
extern void asdf(void) __attribute__((weak_import, weak));
...
{
    if(asdf != NULL) asdf();
}
Run Code Online (Sandbox Code Playgroud)

我总是得到这样的链接错误:

Undefined symbols:
  "_asdf", referenced from:
      _asdf$non_lazy_ptr in ccFA05kN.o
ld: symbol(s) not found
collect2: ld returned 1 exit status

我在OS X 10.5.5上使用GCC 4.0.1.我究竟做错了什么?

Jef*_*eld 29

我只是调查了一下,并认为其他人可能会对我的发现感兴趣.

与weak_import的弱连接实际上只适用于动态库.你可以得到它(通过指定-undefined dynamic_lookup如上建议)与静态链接工作,但这不是这么热的想法.这意味着在运行时之前不会检测到任何未定义的符号.这是我个人在生产代码中要避免的.

这是一个Mac OS X终端会话,展示了如何使其工作:

这是fc

int f(int n)
{
    return n * 7;
}
Run Code Online (Sandbox Code Playgroud)

这是whatnof.c

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

extern int f (int) __attribute__((weak_import));

int main() {
    if(f == NULL)
        printf("what, no f?\n");
    else
        printf("f(8) is %d\n", f(8));
    exit(0);
}
Run Code Online (Sandbox Code Playgroud)

从fc创建一个动态库:

$ cc -dynamiclib -o f.dylib f.c
Run Code Online (Sandbox Code Playgroud)

编译并链接动态库,列出动态库.

$ cc -o whatnof whatnof.c f.dylib
$ otool -L whatnof
whatnof:
       f.dylib (compatibility version 0.0.0, current version 0.0.0)
       /usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 125.2.0)
Run Code Online (Sandbox Code Playgroud)

运行whatnof看看会发生什么:

$ whatnof
f(8) is 56
Run Code Online (Sandbox Code Playgroud)

现在将f.dylib替换为空库(无符号):

$ mv f.dylib f.dylib.real
$ touch null.c
$ cc -dynamiclib -o f.dylib null.c
Run Code Online (Sandbox Code Playgroud)

运行相同的whatnof看看会发生什么:

$ whatnof
what, no f?
Run Code Online (Sandbox Code Playgroud)

weak_import的基本思想(或"用例")是它允许您链接一组动态(共享)库,但是对相同库的早期版本运行相同的代码.您可以检查函数是否为NULL,以查看它们是否在代码当前运行的特定动态库中受支持.这似乎是Xcode支持的基本开发模型的一部分.我希望这个例子很有用; 它帮助我放松了对Xcode设计的这一部分.


小智 6

添加-Wl,-flat_namespace,-undefined,dynamic_lookup到用于执行最终链接的gcc编译器行.

  • 当我使用gcc / MinGW时,它显示`cc1.exe:错误:无法识别的命令行选项“ -flat_namespace,-undefined,dynamic_lookup”。 (2认同)

Cir*_*四事件 6

最小可运行 Linux 示例

主程序

#include <stdio.h>

int my_weak_var __attribute__((weak)) = 1;

int main(void) {
    printf("%d\n", my_weak_var);
}
Run Code Online (Sandbox Code Playgroud)

notmain.c

int my_weak_var = 2;
Run Code Online (Sandbox Code Playgroud)

使用两个对象编译并运行:

gcc -c -std=c99 -Wall -Wextra -pedantic -o main.o main.c
gcc -c -std=c99 -Wall -Wextra -pedantic -o notmain.o notmain.c
gcc -std=c99 -Wall -Wextra -pedantic -o main.out main.o notmain.o
./main.out
Run Code Online (Sandbox Code Playgroud)

输出:

2
Run Code Online (Sandbox Code Playgroud)

编译并运行,无需notmain.o

gcc -std=c99 -Wall -Wextra -pedantic -o main.out main.o
./main.out
Run Code Online (Sandbox Code Playgroud)

输出:

1
Run Code Online (Sandbox Code Playgroud)

GitHub 上游.

因此我们看到,如果在 上给出notmain.o,那么非弱符号将按预期优先。

我们可以通过以下方式分析ELF 目标文件符号:

nm main.o notmain.o
Run Code Online (Sandbox Code Playgroud)

这使:

main.o:
                 U _GLOBAL_OFFSET_TABLE_
0000000000000000 T main
0000000000000000 V my_weak_var
                 U printf

notmain.o:
0000000000000000 D my_weak_var
Run Code Online (Sandbox Code Playgroud)

进而:

man nm
Run Code Online (Sandbox Code Playgroud)

包含:

符号类型。至少使用以下类型;其他也取决于目标文件格式。如果是小写,则该符号通常是本地的;如果大写,则该符号是全局的(外部)。然而,有一些小写符号显示为特殊的全局符号(“u”、“v”和“w”)。

“D”
“d” 该符号位于初始化数据部分。

“V”
“v”符号是弱对象。当弱定义符号与普通定义符号链接时,使用普通定义符号不会出现错误。当链接未定义的弱符号且该符号未定义时,弱符号的值将变为零且不会出现错误。在某些系统上,大写字母表示已指定默认值。

但是,如果处理静态库,您可能必须按照以下说明.a使用: How to make gcc link Strong Symbol in static Library to Overwrite Weak Symbol?-Wl,--whole-archive

弱符号也可以保持未定义,这在 Binutils 中会导致“平台特定行为”,请参阅:未解决的弱函数的 GCC 行为

在 Ubuntu 18.10、GCC 8.2.0 上测试。


Nic*_*lli 1

来自 gcc 文档手册:

虚弱的

弱属性导致声明作为弱符号而不是全局符号发出。这主要用于定义可以在用户代码中覆盖的库函数,尽管它也可以与非函数声明一起使用。ELF 目标支持弱符号,使用 GNU 汇编器和链接器时 a.out 目标也支持弱符号。

这意味着一个对象可以合法地覆盖弱符号(在另一个对象/库中定义),而不会在链接时出现错误。不清楚的是您是否将库与符号链接。看来您还没有定义符号并且库没有正确链接。

  • 该引用不适用于此处:“Mac OS X 弱链接设计 [来自经典的 Mac OS 代码片段管理器]。如果您熟悉 [ELF],您可能会习惯术语 *weak 符号的不同含义* 或 *弱链接*,其中弱符号可能会被非弱符号覆盖。等效的 Mac OS X 功能是*弱定义* — 请参阅[“符号定义的范围和处理”](http://developer. apple.com/library/mac/#documentation/DeveloperTools/Conceptual/MachOTpics/1-Articles/executing_files.html#//apple_ref/doc/uid/TP40001829-98432-TPXREF120)了解更多信息。” (2认同)