【问题标题】:gcc: link-time substitutiongcc:链接时替换
【发布时间】:2018-06-15 07:35:53
【问题描述】:

我目前正在尝试了解 gcc 编译器和链接器是如何工作的。我遇到了一种叫做“链接时间替换”的技术,我觉得这很有趣。目标是在多个文件中对一个函数进行多个定义,并决定哪些定义在链接时进入最终的可执行文件。

一个简单的例子:

main.c:

#include "header.h"

int main(void)
{
    hello("everyone");
    return 0;
}

header.h:

#ifndef _HEADER_H
#define _HEADER_H

void hello(const char * name);

#endif

file1.c:

#include "header.h"
#include <stdio.h>

void hello(const char * name)
{
    printf("File1: Hello, %s!\n", name);
}

file2.c:

#include "header.h"
#include <stdio.h>

void hello(const char * name)
{
    printf("File2: Hello, %s!\n", name);
}

现在我有两个问题:

  • 是否可以通过使用适当的链接顺序来选择函数(如果所有三个文件都出现在链接器的参数列表中)?
  • 假设 file2.c 实现了 main.c 所需的许多功能。是否可以使用链接器通过 file1.c 中的不同实现(具有相同名称)替换单个函数或某些函数?链接器应首先使用 file1.c 中的函数定义,然后将 file2.c 用于剩余的未解析函数。

我希望我的问题是可以理解的;)

谢谢!

【问题讨论】:

  • 你能编辑file2吗?在这种情况下,我会选择以更明确的方式使用的功能。例如。借助预处理器开关封装在条件部分中。
  • 与您的问题和疑问无关,但以下划线开头并后跟大写字母的符号(例如_HEADER_H)在所有范围内保留 “实现”(编译器和标准库)。
  • 是的,我可以编辑file2。预处理器开关当然是解决这个问题的方法,但我想知道是否有更优雅的方法,也许是通过巧妙地使用链接器(我特别尝试了解参数的顺序在链接过程中如何发挥作用)。
  • @Some程序员老兄:感谢您的澄清,不知道这一点! ;)
  • 您可以将一个函数标记为weak symbol

标签: c gcc linker


【解决方案1】:

是否可以通过使用适当的链接顺序来选择一个函数(如果所有三个文件都出现在链接器的参数列表中)?

如果“所有三个文件”是指目标文件(并假设没有弱符号),则否:所有 3 个文件都将被链接,您将收到重复符号定义错误。

但是如果你把file1.o放到lib1.a,把file2.o放到lib2.a,那么是的:

gcc main.c -l1 -l2  # uses file1.o:hello
gcc main.c -l2 -l1  # uses file2.o:hello

更多详情herehere

假设file2.c 实现了main.c 需要的许多功能。是否可以使用链接器替换file1.c中不同实现(同名)的单个函数或部分函数?

可以,但仅限于支持弱符号的平台(例如 ELF 平台,请参阅__attribute__((weak))here)。

如果 file2.o 中的所有符号都是弱定义的,而 file1.o 中的所有符号都不是,那么链接 file1.o 和 file2.o 将达到预期的结果:强符号获胜。

我相信(但尚未测试)如果 file1.o 和 file2.o 都弱定义了相同的符号,那么顺序很重要:

gcc main.c file1.o file2.o  # file1.o definitions override file2.o
gcc main.c file2.o file1.o  # file2.o definitions override file1.o

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2010-12-28
    • 2012-06-20
    • 2012-06-27
    • 2013-07-12
    • 2014-09-20
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多