GNU ld的--undefined选项是做什么用的?

5

有人能解释一下GNU ld选项--undefined的作用吗?

我正在开发一个LiteOS项目。该应用程序链接了许多-u选项,例如-utask_shellcmd

GNU链接器手册中关于--undefined=symbol的说明如下:

强制将符号作为未定义符号输入到输出文件中。这样做可能会触发从标准库中链接其他模块。

因此,该符号将被包含在输出文件中作为未定义符号。如果该符号已经在其中一个链接的obj文件中定义,会怎么样?如果它真的是未定义的,则链接其他模块将会在什么时候发生,以及如何发生?


编译器会查看您的翻译单元并创建一个已编译的目标文件。该文件的一部分是外部符号表,其中包含目标文件引用但不属于该对象的外部符号。这些是未定义的符号。 - jxh
1
在正常的托管环境中,main() 函数被调用的方式是因为启动代码 (crt0.o 或类似文件) 调用了该函数 —— 但没有定义它,因此链接器会在您的目标文件中寻找定义。--undefined=symbol 选项告诉链接器应在扫描的目标文件和库中查找 symbol。我还没有检查过它在链接器命令行上的位置是否重要。如果符号已经被定义,那么它就不重要(也不会再次链接)。如果在链接结束时仍未定义,则链接可能会失败。 - Jonathan Leffler
1个回答

10

-u选项仅与归档(.a)库有关(也可能与--as-needed一起使用的.so库)。

与链接命令行中出现的单个目标文件(.o)按照它们出现的顺序全部链接不同,归档库中的目标文件仅在它们出现在链接命令行顺序的某一点满足一个或多个未定义符号引用时才链接。一旦从归档中提取了一个.o文件进行链接,递归地重复这个过程,因此如果它引入了更多未定义符号引用,则会从同一(或稍后)归档中提取其他目标文件来满足这些符号引用。

使用-u允许你将特定符号(及其间接依赖的所属目标文件)引入链接中。当然,你也可以直接在命令行中放置所有.o文件,而不使用任何归档库,但是通过使用库,你可以在获取所需的文件的同时,避免链接未使用的目标文件(这在大部分代码根据构建时间可配置设置在其他文件中而可能未被使用时尤其有用!)。


基本上,它可能会导致未使用的符号链接到生成的二进制文件中。对吗?那么为什么需要这样做呢? - minghua
1
@minghua:实际上,对于普通托管应用程序,以main(通过crt1.o)为根的未定义符号依赖关系树就足以获取所需的所有内容。但是对于像内核这样的独立项目,您可能需要定义自己的根。另外,无论哪种方式——但这在裸机/内核编程中更常见,在其中可以对链接器进行假设的情况下,不属于主符号依赖关系树的对象文件可能会通过链接器脚本插入到表中的特殊部分来发挥作用等最终生成的结果。 - R.. GitHub STOP HELPING ICE
2
其中一个特殊情况是可移植的,即静态对象的构造函数(在C++中或通过GNU C属性使函数成为在启动时运行的“ctor”)。拉入一个否则未使用的目标文件可能会通过导致该文件中的静态构造函数被链接和在启动时运行而改变程序行为。 - R.. GitHub STOP HELPING ICE

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接