你能在 ld 脚本中添加两个 SECTION 部分吗

Can you add two SECTION sections to ld script

我有一个通过链接几个 .o 文件制作的可执行文件,使用了一些复杂的链接描述文件。如果设置了特定的环境标志,我希望涉及另一个部分。所以,像这样:

/* withfoo.ld */
SECTIONS {
 .foo 0x80000000 : {
    _start_foo = .;
    . += 0xfff;
    _end_foo = .;
 }
}

然后编译:

if [ $FOO_DEFINED ]; then
    gcc -Wl,-T normal.ld $(OBJS) foo.o foo.ld
else
    gcc -Wl,-T normal.ld $(OBJS)
fi

我希望不必修改的地方 normal.ldnormal.ld 中有一个 SECTIONS 定义。所以这给了我两个部分...我收到警告:

/usr/bin/ld: warning: foo.ld contains output sections; did you forget -T?

是否存在实际问题或者这只是一个警告?还有我不知道的正确方法吗?

GNU 链接描述文件和 LD 不支持条件编译。您不能同时使用两个链接描述文件并使其按预期工作。您必须使用其他类型的宏语言(例如 m4 或什至只使用 GNU C 预处理器 cpp 来预处理链接描述文件。


不确定这是否是您正在寻找的一种解决方案。 C 预处理器 cpp 可以处理任何类型的文件(甚至是非 C 文件)的文本,并且会像 [=] 一样盲目解析预处理器指令和宏50=]C 文件。您还可以通过 cpp 命令行传递 C 样式定义,就像使用 GCC 一样。您使用所有 C 预处理器指令创建一个链接器脚本,并基于它生成特定的链接器脚本。例如创建一个特殊的链接描述文件,如下所示:

linker.ld.pp :

SECTIONS {
#ifdef FOO
 .foo 0x80000000 : {
    _start_foo = .;
    . += 0xfff;
    _end_foo = .;
 }
#endif
}

这使用典型的 C 风格 #if/#ifdef/#endif 进行条件编译。如果你 运行 它通过 C 预处理器使用如下命令:

cpp -P -DFOO linker.ld.pp

你会得到这样的输出:

SECTIONS {
 .foo 0x80000000 : {
    _start_foo = .;
    . += 0xfff;
    _end_foo = .;
 }
}

不定义 FOO 会这样:

cpp -P linker.ld.pp

输出将是:

SECTIONS {
}

要重定向预处理器,您可以使用以下命令输出到链接描述文件:

cpp -P -DFOO linker.ld.pp >withfoo.ld
cpp -P linker.ld.pp >withoutfoo.ld

如果愿意,您可以在 CPP 命令行上指定多个 -D 指令来定义多个预处理器符号。这种方法的想法是,您只有一个链接描述文件,但您创建了一个 shell 脚本来生成所需的必要专用脚本。


其他观察结果

通常您在 GCC 命令行上使用 -T 选项指定链接描述文件:

gcc -T withfoo.ld $(OBJS) foo.o